mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-03-03 20:40:35 +00:00
* Adjustment: Initial work on moving x86Unix platform code into a more common POSIX platform.
This commit is contained in:
parent
e9414a1660
commit
6583134ef2
34 changed files with 33 additions and 5216 deletions
51
Engine/source/platformPOSIX/POSIXCPUInfo.cpp
Normal file
51
Engine/source/platformPOSIX/POSIXCPUInfo.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __APPLE__
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "platformX86UNIX/platformX86UNIX.h"
|
||||
#include "console/console.h"
|
||||
#include "core/stringTable.h"
|
||||
#include "core/strings/stringFunctions.h"
|
||||
#include <math.h>
|
||||
|
||||
#include "platform/platformCPUCount.h"
|
||||
#include <unistd.h>
|
||||
|
||||
Platform::SystemInfo_struct Platform::SystemInfo;
|
||||
|
||||
void Processor::init() {}
|
||||
|
||||
// TODO LINUX CPUInfo::CPUCount better support
|
||||
namespace CPUInfo
|
||||
{
|
||||
EConfig CPUCount(U32& TotAvailLogical, U32& TotAvailCore, U32& PhysicalNum)
|
||||
{
|
||||
PhysicalNum = TotAvailCore = 0;
|
||||
TotAvailLogical = (int)sysconf(_SC_NPROCESSORS_ONLN);
|
||||
|
||||
return CONFIG_SingleCoreHTDisabled;
|
||||
}
|
||||
}; // namespace CPUInfo
|
||||
|
||||
#endif
|
||||
426
Engine/source/platformPOSIX/POSIXConsole.cpp
Normal file
426
Engine/source/platformPOSIX/POSIXConsole.cpp
Normal file
|
|
@ -0,0 +1,426 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platformX86UNIX/platformX86UNIX.h"
|
||||
#include "platformPOSIX/POSIXStdConsole.h"
|
||||
#include "platformPOSIX/POSIXUtils.h"
|
||||
#include "platform/input/event.h"
|
||||
#include "platform/platform.h"
|
||||
#include "core/util/rawData.h"
|
||||
#include "core/strings/stringFunctions.h"
|
||||
#include "core/util/journal/process.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
StdConsole *stdConsole = NULL;
|
||||
|
||||
DefineEngineFunction(enableWinConsole, void, (bool _enable),, "enableWinConsole(bool);")
|
||||
{
|
||||
if (stdConsole)
|
||||
{
|
||||
stdConsole->enable(_enable);
|
||||
stdConsole->enableInput(_enable);
|
||||
}
|
||||
}
|
||||
|
||||
void StdConsole::create()
|
||||
{
|
||||
if (stdConsole == NULL)
|
||||
stdConsole = new StdConsole();
|
||||
}
|
||||
|
||||
void StdConsole::destroy()
|
||||
{
|
||||
if (stdConsole && stdConsole->isEnabled())
|
||||
stdConsole->enable(false);
|
||||
|
||||
delete stdConsole;
|
||||
stdConsole = NULL;
|
||||
}
|
||||
|
||||
static void signalHandler(int sigtype)
|
||||
{
|
||||
if (sigtype == SIGCONT && stdConsole != NULL)
|
||||
stdConsole->resetTerminal();
|
||||
}
|
||||
|
||||
void StdConsole::resetTerminal()
|
||||
{
|
||||
if (stdConsoleEnabled)
|
||||
{
|
||||
/* setup the proper terminal modes */
|
||||
struct termios termModes;
|
||||
tcgetattr(stdIn, &termModes);
|
||||
termModes.c_lflag &= ~ICANON; // enable non-canonical mode
|
||||
termModes.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHOKE);
|
||||
termModes.c_cc[VMIN] = 0;
|
||||
termModes.c_cc[VTIME] = 5;
|
||||
tcsetattr(stdIn, TCSAFLUSH, &termModes);
|
||||
}
|
||||
}
|
||||
|
||||
void StdConsole::enable(bool enabled)
|
||||
{
|
||||
if (enabled && !stdConsoleEnabled)
|
||||
{
|
||||
stdConsoleEnabled = true;
|
||||
|
||||
// install signal handler for sigcont
|
||||
signal(SIGCONT, &signalHandler);
|
||||
|
||||
// save the terminal state
|
||||
if (originalTermState == NULL)
|
||||
originalTermState = new termios;
|
||||
|
||||
tcgetattr(stdIn, originalTermState);
|
||||
|
||||
// put the terminal into our preferred mode
|
||||
resetTerminal();
|
||||
|
||||
printf("%s", Con::getVariable("Con::Prompt"));
|
||||
|
||||
}
|
||||
else if (!enabled && stdConsoleEnabled)
|
||||
{
|
||||
stdConsoleEnabled = false;
|
||||
|
||||
// uninstall signal handler
|
||||
signal(SIGCONT, SIG_DFL);
|
||||
|
||||
// reset the original terminal state
|
||||
if (originalTermState != NULL)
|
||||
tcsetattr(stdIn, TCSANOW, originalTermState);
|
||||
}
|
||||
}
|
||||
|
||||
void StdConsole::enableInput( bool enabled )
|
||||
{
|
||||
stdConsoleInputEnabled = enabled;
|
||||
}
|
||||
|
||||
bool StdConsole::isEnabled()
|
||||
{
|
||||
if ( stdConsole )
|
||||
return stdConsole->stdConsoleEnabled;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void stdConsoleConsumer(/*ConsoleLogEntry::Level*/ U32, const char *line)
|
||||
{
|
||||
stdConsole->processConsoleLine(line);
|
||||
}
|
||||
|
||||
StdConsole::StdConsole()
|
||||
{
|
||||
for (S32 iIndex = 0; iIndex < MAX_CMDS; iIndex ++)
|
||||
rgCmds[iIndex][0] = '\0';
|
||||
|
||||
stdOut = dup(1);
|
||||
stdIn = dup(0);
|
||||
stdErr = dup(2);
|
||||
|
||||
// Ensure in buffer is null terminated after allocation
|
||||
inbuf[0] = 0x00;
|
||||
|
||||
iCmdIndex = 0;
|
||||
stdConsoleEnabled = false;
|
||||
stdConsoleInputEnabled = false;
|
||||
Con::addConsumer(stdConsoleConsumer);
|
||||
inpos = 0;
|
||||
lineOutput = false;
|
||||
inBackground = false;
|
||||
originalTermState = NULL;
|
||||
|
||||
Process::notify(this, &StdConsole::process, PROCESS_LAST_ORDER);
|
||||
}
|
||||
|
||||
StdConsole::~StdConsole()
|
||||
{
|
||||
Con::removeConsumer(stdConsoleConsumer);
|
||||
|
||||
if (stdConsoleEnabled)
|
||||
enable(false);
|
||||
|
||||
if (originalTermState != NULL)
|
||||
{
|
||||
delete originalTermState;
|
||||
originalTermState = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void StdConsole::printf(const char *s, ...)
|
||||
{
|
||||
// Get the line into a buffer.
|
||||
static const int BufSize = 4096;
|
||||
static char buffer[BufSize];
|
||||
va_list args;
|
||||
va_start(args, s);
|
||||
vsnprintf(buffer, BufSize, s, args);
|
||||
va_end(args);
|
||||
// Replace tabs with carats, like the "real" console does.
|
||||
char *pos = buffer;
|
||||
while (*pos) {
|
||||
if (*pos == '\t') {
|
||||
*pos = '^';
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
// Axe the color characters.
|
||||
Con::stripColorChars(buffer);
|
||||
// Print it.
|
||||
write(stdOut, buffer, strlen(buffer));
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void StdConsole::processConsoleLine(const char *consoleLine)
|
||||
{
|
||||
if(stdConsoleEnabled)
|
||||
{
|
||||
if(lineOutput)
|
||||
printf("%s\n", consoleLine);
|
||||
else
|
||||
{
|
||||
// Clear current line before outputting the console line. This prevents prompt text from overflowing onto normal output.
|
||||
printf("%c[2K", 27);
|
||||
printf("%c%s\n%s%s", '\r', consoleLine, Con::getVariable("Con::Prompt"), inbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StdConsole::process()
|
||||
{
|
||||
if(stdConsoleEnabled)
|
||||
{
|
||||
//U16 key;
|
||||
char typedData[64]; // damn, if you can type this fast... :-D
|
||||
|
||||
if (UUtils->inBackground())
|
||||
// we don't have the terminal
|
||||
inBackground = true;
|
||||
else
|
||||
{
|
||||
// if we were in the background, reset the terminal
|
||||
if (inBackground)
|
||||
resetTerminal();
|
||||
inBackground = false;
|
||||
}
|
||||
|
||||
// see if stdIn has any input waiting
|
||||
// mojo for select call
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(stdIn, &rfds);
|
||||
// don't wait at all in select
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
int numEvents = select(stdIn+1, &rfds, NULL, NULL, &tv);
|
||||
if (numEvents <= 0)
|
||||
// no data available
|
||||
return;
|
||||
|
||||
numEvents = read(stdIn, typedData, 64);
|
||||
if (numEvents == -1)
|
||||
return;
|
||||
|
||||
// TODO LINUX, when debug in qtCreator some times we get false console inputs.
|
||||
if( !stdConsoleInputEnabled )
|
||||
return;
|
||||
|
||||
typedData[numEvents] = '\0';
|
||||
if (numEvents > 0)
|
||||
{
|
||||
char outbuf[512];
|
||||
S32 outpos = 0;
|
||||
|
||||
for (int i = 0; i < numEvents; i++)
|
||||
{
|
||||
switch(typedData[i])
|
||||
{
|
||||
case 8:
|
||||
case 127:
|
||||
/* backspace */
|
||||
if (inpos > 0)
|
||||
{
|
||||
outbuf[outpos++] = '\b';
|
||||
outbuf[outpos++] = ' ';
|
||||
outbuf[outpos++] = '\b';
|
||||
inpos--;
|
||||
}
|
||||
break;
|
||||
|
||||
// XXX Don't know if we can detect shift-TAB. So, only handling
|
||||
// TAB for now.
|
||||
|
||||
case '\t':
|
||||
// In the output buffer, we're going to have to erase the current line (in case
|
||||
// we're cycling through various completions) and write out the whole input
|
||||
// buffer, so (inpos * 3) + complen <= 512. Should be OK. The input buffer is
|
||||
// also 512 chars long so that constraint will also be fine for the input buffer.
|
||||
{
|
||||
// Erase the current line.
|
||||
U32 i;
|
||||
for (i = 0; i < inpos; i++) {
|
||||
outbuf[outpos++] = '\b';
|
||||
outbuf[outpos++] = ' ';
|
||||
outbuf[outpos++] = '\b';
|
||||
}
|
||||
// Modify the input buffer with the completion.
|
||||
U32 maxlen = 512 - (inpos * 3);
|
||||
inpos = Con::tabComplete(inbuf, inpos, maxlen, true);
|
||||
// Copy the input buffer to the output.
|
||||
for (i = 0; i < inpos; i++) {
|
||||
outbuf[outpos++] = inbuf[i];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
case '\r':
|
||||
/* new line */
|
||||
outbuf[outpos++] = '\n';
|
||||
|
||||
inbuf[inpos] = 0;
|
||||
outbuf[outpos] = 0;
|
||||
printf("%s", outbuf);
|
||||
|
||||
S32 eventSize;
|
||||
eventSize = 1;
|
||||
|
||||
{
|
||||
RawData rd;
|
||||
rd.size = inpos + 1;
|
||||
rd.data = (S8*) inbuf;
|
||||
|
||||
Con::smConsoleInput.trigger(rd);
|
||||
}
|
||||
|
||||
// If we've gone off the end of our array, wrap
|
||||
// back to the beginning
|
||||
if (iCmdIndex >= MAX_CMDS)
|
||||
iCmdIndex %= MAX_CMDS;
|
||||
|
||||
// Put the new command into the array
|
||||
strcpy(rgCmds[iCmdIndex ++], inbuf);
|
||||
|
||||
printf("%s", Con::getVariable("Con::Prompt"));
|
||||
inpos = outpos = 0;
|
||||
inbuf[0] = 0x00; // Ensure inbuf is NULL terminated after sending out command
|
||||
break;
|
||||
case 27:
|
||||
// JMQTODO: are these magic numbers keyboard map specific?
|
||||
if (typedData[i+1] == 91 || typedData[i+1] == 79)
|
||||
{
|
||||
i += 2;
|
||||
// an arrow key was pressed.
|
||||
switch(typedData[i])
|
||||
{
|
||||
case 'A':
|
||||
/* up arrow */
|
||||
// Go to the previous command in the cyclic array
|
||||
if ((-- iCmdIndex) < 0)
|
||||
iCmdIndex = MAX_CMDS - 1;
|
||||
|
||||
// If this command isn't empty ...
|
||||
if (rgCmds[iCmdIndex][0] != '\0')
|
||||
{
|
||||
// Obliterate current displayed text
|
||||
for (S32 i = outpos = 0; i < inpos; i ++)
|
||||
{
|
||||
outbuf[outpos++] = '\b';
|
||||
outbuf[outpos++] = ' ';
|
||||
outbuf[outpos++] = '\b';
|
||||
}
|
||||
|
||||
// Copy command into command and display buffers
|
||||
for (inpos = 0; inpos < (S32)strlen(rgCmds[iCmdIndex]); inpos++, outpos++)
|
||||
{
|
||||
outbuf[outpos] = rgCmds[iCmdIndex][inpos];
|
||||
inbuf [inpos ] = rgCmds[iCmdIndex][inpos];
|
||||
}
|
||||
}
|
||||
// If previous is empty, stay on current command
|
||||
else if ((++ iCmdIndex) >= MAX_CMDS)
|
||||
{
|
||||
iCmdIndex = 0;
|
||||
}
|
||||
break;
|
||||
case 'B':
|
||||
/* down arrow */
|
||||
// Go to the next command in the command array, if
|
||||
// it isn't empty
|
||||
if (rgCmds[iCmdIndex][0] != '\0' && (++ iCmdIndex) >= MAX_CMDS)
|
||||
iCmdIndex = 0;
|
||||
|
||||
// Obliterate current displayed text
|
||||
for (S32 i = outpos = 0; i < inpos; i ++)
|
||||
{
|
||||
outbuf[outpos++] = '\b';
|
||||
outbuf[outpos++] = ' ';
|
||||
outbuf[outpos++] = '\b';
|
||||
}
|
||||
|
||||
// Copy command into command and display buffers
|
||||
for (inpos = 0; inpos < (S32)strlen(rgCmds[iCmdIndex]); inpos++, outpos++)
|
||||
{
|
||||
outbuf[outpos] = rgCmds[iCmdIndex][inpos];
|
||||
inbuf [inpos ] = rgCmds[iCmdIndex][inpos];
|
||||
}
|
||||
break;
|
||||
case 'C':
|
||||
/* right arrow */
|
||||
break;
|
||||
case 'D':
|
||||
/* left arrow */
|
||||
break;
|
||||
}
|
||||
// read again to get rid of a bad char.
|
||||
//read(stdIn, &key, sizeof(char));
|
||||
break;
|
||||
} else {
|
||||
inbuf[inpos++] = typedData[i];
|
||||
outbuf[outpos++] = typedData[i];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
inbuf[inpos++] = typedData[i];
|
||||
outbuf[outpos++] = typedData[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (outpos)
|
||||
{
|
||||
outbuf[outpos] = 0;
|
||||
printf("%s", outbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
392
Engine/source/platformPOSIX/POSIXGL.client.cpp
Normal file
392
Engine/source/platformPOSIX/POSIXGL.client.cpp
Normal file
|
|
@ -0,0 +1,392 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#if 0
|
||||
#include "platformX86UNIX/platformGL.h"
|
||||
#include "platformX86UNIX/platformX86UNIX.h"
|
||||
#include "console/console.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
// declare stub functions
|
||||
#define GL_FUNCTION(fn_return, fn_name, fn_args, fn_value) fn_return stub_##fn_name fn_args{ fn_value }
|
||||
#include "platform/GLCoreFunc.h"
|
||||
#include "platform/GLExtFunc.h"
|
||||
#undef GL_FUNCTION
|
||||
|
||||
// point gl function pointers at stub functions
|
||||
#define GL_FUNCTION(fn_return,fn_name,fn_args, fn_value) fn_return (*fn_name)fn_args = stub_##fn_name;
|
||||
#include "platform/GLCoreFunc.h"
|
||||
#include "platform/GLExtFunc.h"
|
||||
#undef GL_FUNCTION
|
||||
|
||||
static void* dlHandle = NULL;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
//bind functions for each function prototype
|
||||
//------------------------------------------------------------------
|
||||
|
||||
//GL_EXT/ARB
|
||||
enum {
|
||||
ARB_multitexture = BIT(0),
|
||||
ARB_texture_compression = BIT(1),
|
||||
EXT_compiled_vertex_array = BIT(2),
|
||||
EXT_fog_coord = BIT(3),
|
||||
EXT_paletted_texture = BIT(4),
|
||||
NV_vertex_array_range = BIT(5),
|
||||
EXT_blend_color = BIT(6),
|
||||
EXT_blend_minmax = BIT(7)
|
||||
};
|
||||
|
||||
//WGL_ARB
|
||||
enum {
|
||||
WGL_ARB_extensions_string = BIT(0),
|
||||
WGL_EXT_swap_control = BIT(1),
|
||||
WGL_3DFX_gamma_control = BIT(2)
|
||||
};
|
||||
|
||||
|
||||
static bool isFnOk( const char *name)
|
||||
{
|
||||
bool ok = false;
|
||||
|
||||
// JMQ: these are specific to torque's d3d->gl wrapper. They are not used under linux.
|
||||
if (dStrcmp(name, "glAvailableVertexBufferEXT")==0)
|
||||
ok = true;
|
||||
else if (dStrcmp(name, "glAllocateVertexBufferEXT")==0)
|
||||
ok = true;
|
||||
else if (dStrcmp(name, "glLockVertexBufferEXT")==0)
|
||||
ok = true;
|
||||
else if (dStrcmp(name, "glUnlockVertexBufferEXT")==0)
|
||||
ok = true;
|
||||
else if (dStrcmp(name, "glSetVertexBufferEXT")==0)
|
||||
ok = true;
|
||||
else if (dStrcmp(name, "glOffsetVertexBufferEXT")==0)
|
||||
ok = true;
|
||||
else if (dStrcmp(name, "glFillVertexBufferEXT")==0)
|
||||
ok = true;
|
||||
else if (dStrcmp(name, "glFreeVertexBufferEXT")==0)
|
||||
ok = true;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
//bind functions for each function prototype
|
||||
//------------------------------------------------------------------
|
||||
static bool bindGLFunction( void *&fnAddress, const char *name )
|
||||
{
|
||||
void* addr = (void*)SDL_GL_GetProcAddress(name);
|
||||
bool ok = (bool)addr;
|
||||
if( !ok )
|
||||
{
|
||||
if (!isFnOk(name))
|
||||
Con::errorf(ConsoleLogEntry::General, " Missing OpenGL function '%s'", name);
|
||||
else
|
||||
ok = true;
|
||||
}
|
||||
else
|
||||
fnAddress = addr;
|
||||
return ok;
|
||||
}
|
||||
|
||||
static bool bindEXTFunction( void *&fnAddress, const char *name )
|
||||
{
|
||||
void* addr = (void*)SDL_GL_GetProcAddress(name);
|
||||
if( !addr )
|
||||
Con::errorf(ConsoleLogEntry::General, " Missing OpenGL extension '%s'", name);
|
||||
else
|
||||
fnAddress = addr;
|
||||
return (addr != NULL);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
//binds for each function group
|
||||
//------------------------------------------------------------------
|
||||
static bool bindGLFunctions()
|
||||
{
|
||||
bool result = true;
|
||||
#define GL_FUNCTION(fn_return, fn_name, fn_args, fn_value) \
|
||||
result &= bindGLFunction( *(void**)&fn_name, #fn_name);
|
||||
#include "platform/GLCoreFunc.h"
|
||||
#undef GL_FUNCTION
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool bindEXTFunctions(U32 extMask)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
#define GL_GROUP_BEGIN( flag ) \
|
||||
if( extMask & flag ) {
|
||||
#define GL_GROUP_END() }
|
||||
|
||||
#define GL_FUNCTION(fn_return, fn_name, fn_args, fn_value) \
|
||||
result &= bindEXTFunction( *(void**)&fn_name, #fn_name);
|
||||
#include "platform/GLExtFunc.h"
|
||||
#undef GL_FUNCTION
|
||||
|
||||
#undef GL_GROUP_BEGIN
|
||||
#undef GL_GROUP_END
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void unbindGLFunctions()
|
||||
{
|
||||
// point gl function pointers at stub functions
|
||||
#define GL_FUNCTION(fn_return, fn_name, fn_args, fn_value) fn_name = stub_##fn_name;
|
||||
#include "platform/GLCoreFunc.h"
|
||||
#include "platform/GLExtFunc.h"
|
||||
#undef GL_FUNCTION
|
||||
}
|
||||
|
||||
namespace GLLoader
|
||||
{
|
||||
|
||||
bool OpenGLInit()
|
||||
{
|
||||
return OpenGLDLLInit();
|
||||
}
|
||||
|
||||
void OpenGLShutdown()
|
||||
{
|
||||
OpenGLDLLShutdown();
|
||||
}
|
||||
|
||||
bool OpenGLDLLInit()
|
||||
{
|
||||
OpenGLDLLShutdown();
|
||||
|
||||
// load libGL.so
|
||||
if (SDL_GL_LoadLibrary("libGL.so") == -1 &&
|
||||
SDL_GL_LoadLibrary("libGL.so.1") == -1)
|
||||
{
|
||||
Con::errorf("Error loading GL library: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
// bind functions
|
||||
if (!bindGLFunctions())
|
||||
{
|
||||
Con::errorf("Error binding GL functions");
|
||||
OpenGLDLLShutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenGLDLLShutdown()
|
||||
{
|
||||
// there is no way to tell SDL to unload the library
|
||||
if (dlHandle != NULL)
|
||||
{
|
||||
dlclose(dlHandle);
|
||||
dlHandle = NULL;
|
||||
}
|
||||
|
||||
unbindGLFunctions();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GLState gGLState;
|
||||
|
||||
bool gOpenGLDisablePT = false;
|
||||
bool gOpenGLDisableCVA = false;
|
||||
bool gOpenGLDisableTEC = false;
|
||||
bool gOpenGLDisableARBMT = false;
|
||||
bool gOpenGLDisableFC = false;
|
||||
bool gOpenGLDisableTCompress = false;
|
||||
bool gOpenGLNoEnvColor = false;
|
||||
float gOpenGLGammaCorrection = 0.5;
|
||||
bool gOpenGLNoDrawArraysAlpha = false;
|
||||
|
||||
// JMQTODO: really need a platform-shared version of this nastiness
|
||||
bool GL_EXT_Init( )
|
||||
{
|
||||
// Load extensions...
|
||||
//
|
||||
const char* pExtString = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
|
||||
gGLState.primMode = 0;
|
||||
U32 extBitMask = 0;
|
||||
|
||||
// GL_EXT_paletted_texture
|
||||
if (pExtString && dStrstr(pExtString, (const char*)"GL_EXT_paletted_texture") != NULL)
|
||||
{
|
||||
extBitMask |= EXT_paletted_texture;
|
||||
gGLState.suppPalettedTexture = true;
|
||||
}
|
||||
else
|
||||
gGLState.suppPalettedTexture = false;
|
||||
|
||||
// EXT_compiled_vertex_array
|
||||
if (pExtString && dStrstr(pExtString, (const char*)"GL_EXT_compiled_vertex_array") != NULL)
|
||||
{
|
||||
extBitMask |= EXT_compiled_vertex_array;
|
||||
gGLState.suppLockedArrays = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
gGLState.suppLockedArrays = false;
|
||||
}
|
||||
|
||||
// ARB_multitexture
|
||||
if (pExtString && dStrstr(pExtString, (const char*)"GL_ARB_multitexture") != NULL)
|
||||
{
|
||||
extBitMask |= ARB_multitexture;
|
||||
gGLState.suppARBMultitexture = true;
|
||||
} else {
|
||||
gGLState.suppARBMultitexture = false;
|
||||
}
|
||||
|
||||
// EXT_blend_color
|
||||
if(pExtString && dStrstr(pExtString, (const char*)"GL_EXT_blend_color") != NULL)
|
||||
{
|
||||
extBitMask |= EXT_blend_color;
|
||||
gGLState.suppEXTblendcolor = true;
|
||||
} else {
|
||||
gGLState.suppEXTblendcolor = false;
|
||||
}
|
||||
|
||||
// EXT_blend_minmax
|
||||
if(pExtString && dStrstr(pExtString, (const char*)"GL_EXT_blend_minmax") != NULL)
|
||||
{
|
||||
extBitMask |= EXT_blend_color;
|
||||
gGLState.suppEXTblendminmax = true;
|
||||
} else {
|
||||
gGLState.suppEXTblendminmax = false;
|
||||
}
|
||||
|
||||
// EXT_fog_coord
|
||||
if (pExtString && dStrstr(pExtString, (const char*)"GL_EXT_fog_coord") != NULL)
|
||||
{
|
||||
extBitMask |= EXT_fog_coord;
|
||||
gGLState.suppFogCoord = true;
|
||||
} else {
|
||||
gGLState.suppFogCoord = false;
|
||||
}
|
||||
|
||||
// EXT_texture_compression_s3tc
|
||||
if (pExtString && dStrstr(pExtString, (const char*)"GL_EXT_texture_compression_s3tc") != NULL)
|
||||
gGLState.suppS3TC = true;
|
||||
else
|
||||
gGLState.suppS3TC = false;
|
||||
|
||||
// ARB_texture_compression
|
||||
if (pExtString && dStrstr(pExtString, (const char*)"GL_ARB_texture_compression") != NULL)
|
||||
{
|
||||
extBitMask |= ARB_texture_compression;
|
||||
gGLState.suppTextureCompression = true;
|
||||
} else {
|
||||
gGLState.suppTextureCompression = false;
|
||||
}
|
||||
|
||||
// NV_vertex_array_range (not on *nix)
|
||||
gGLState.suppVertexArrayRange = false;
|
||||
|
||||
// 3DFX_texture_compression_FXT1
|
||||
if (pExtString && dStrstr(pExtString, (const char*)"3DFX_texture_compression_FXT1") != NULL)
|
||||
gGLState.suppFXT1 = true;
|
||||
else
|
||||
gGLState.suppFXT1 = false;
|
||||
|
||||
if (!bindEXTFunctions(extBitMask))
|
||||
Con::warnf("You are missing some OpenGL Extensions. You may experience rendering problems.");
|
||||
|
||||
// Binary states, i.e., no supporting functions
|
||||
// EXT_packed_pixels
|
||||
// EXT_texture_env_combine
|
||||
//
|
||||
// dhc note: a number of these can have multiple matching 'versions', private, ext, and arb.
|
||||
gGLState.suppPackedPixels = pExtString? (dStrstr(pExtString, (const char*)"GL_EXT_packed_pixels") != NULL) : false;
|
||||
gGLState.suppTextureEnvCombine = pExtString? (dStrstr(pExtString, (const char*)"GL_EXT_texture_env_combine") != NULL) : false;
|
||||
gGLState.suppEdgeClamp = pExtString? (dStrstr(pExtString, (const char*)"GL_EXT_texture_edge_clamp") != NULL) : false;
|
||||
gGLState.suppEdgeClamp |= pExtString? (dStrstr(pExtString, (const char*)"GL_SGIS_texture_edge_clamp") != NULL) : false;
|
||||
gGLState.suppTexEnvAdd = pExtString? (dStrstr(pExtString, (const char*)"GL_ARB_texture_env_add") != NULL) : false;
|
||||
gGLState.suppTexEnvAdd |= pExtString? (dStrstr(pExtString, (const char*)"GL_EXT_texture_env_add") != NULL) : false;
|
||||
|
||||
// Anisotropic filtering
|
||||
gGLState.suppTexAnisotropic = pExtString? (dStrstr(pExtString, (const char*)"GL_EXT_texture_filter_anisotropic") != NULL) : false;
|
||||
if (gGLState.suppTexAnisotropic)
|
||||
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gGLState.maxAnisotropy);
|
||||
if (gGLState.suppARBMultitexture)
|
||||
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gGLState.maxTextureUnits);
|
||||
else
|
||||
gGLState.maxTextureUnits = 1;
|
||||
|
||||
// JMQ: vsync/swap interval skipped
|
||||
gGLState.suppSwapInterval = false;
|
||||
|
||||
Con::printf("OpenGL Init: Enabled Extensions");
|
||||
if (gGLState.suppARBMultitexture) Con::printf(" ARB_multitexture (Max Texture Units: %d)", gGLState.maxTextureUnits);
|
||||
if (gGLState.suppEXTblendcolor) Con::printf(" EXT_blend_color");
|
||||
if (gGLState.suppEXTblendminmax) Con::printf(" EXT_blend_minmax");
|
||||
if (gGLState.suppPalettedTexture) Con::printf(" EXT_paletted_texture");
|
||||
if (gGLState.suppLockedArrays) Con::printf(" EXT_compiled_vertex_array");
|
||||
if (gGLState.suppVertexArrayRange) Con::printf(" NV_vertex_array_range");
|
||||
if (gGLState.suppTextureEnvCombine) Con::printf(" EXT_texture_env_combine");
|
||||
if (gGLState.suppPackedPixels) Con::printf(" EXT_packed_pixels");
|
||||
if (gGLState.suppFogCoord) Con::printf(" EXT_fog_coord");
|
||||
if (gGLState.suppTextureCompression) Con::printf(" ARB_texture_compression");
|
||||
if (gGLState.suppS3TC) Con::printf(" EXT_texture_compression_s3tc");
|
||||
if (gGLState.suppFXT1) Con::printf(" 3DFX_texture_compression_FXT1");
|
||||
if (gGLState.suppTexEnvAdd) Con::printf(" (ARB|EXT)_texture_env_add");
|
||||
if (gGLState.suppTexAnisotropic) Con::printf(" EXT_texture_filter_anisotropic (Max anisotropy: %f)", gGLState.maxAnisotropy);
|
||||
if (gGLState.suppSwapInterval) Con::printf(" WGL_EXT_swap_control");
|
||||
|
||||
Con::warnf("OpenGL Init: Disabled Extensions");
|
||||
if (!gGLState.suppARBMultitexture) Con::warnf(" ARB_multitexture");
|
||||
if (!gGLState.suppEXTblendcolor) Con::warnf(" EXT_blend_color");
|
||||
if (!gGLState.suppEXTblendminmax) Con::warnf(" EXT_blend_minmax");
|
||||
if (!gGLState.suppPalettedTexture) Con::warnf(" EXT_paletted_texture");
|
||||
if (!gGLState.suppLockedArrays) Con::warnf(" EXT_compiled_vertex_array");
|
||||
if (!gGLState.suppVertexArrayRange) Con::warnf(" NV_vertex_array_range");
|
||||
if (!gGLState.suppTextureEnvCombine) Con::warnf(" EXT_texture_env_combine");
|
||||
if (!gGLState.suppPackedPixels) Con::warnf(" EXT_packed_pixels");
|
||||
if (!gGLState.suppFogCoord) Con::warnf(" EXT_fog_coord");
|
||||
if (!gGLState.suppTextureCompression) Con::warnf(" ARB_texture_compression");
|
||||
if (!gGLState.suppS3TC) Con::warnf(" EXT_texture_compression_s3tc");
|
||||
if (!gGLState.suppFXT1) Con::warnf(" 3DFX_texture_compression_FXT1");
|
||||
if (!gGLState.suppTexEnvAdd) Con::warnf(" (ARB|EXT)_texture_env_add");
|
||||
if (!gGLState.suppTexAnisotropic) Con::warnf(" EXT_texture_filter_anisotropic");
|
||||
if (!gGLState.suppSwapInterval) Con::warnf(" WGL_EXT_swap_control");
|
||||
Con::printf(" ");
|
||||
|
||||
// Set some console variables:
|
||||
Con::setBoolVariable( "$FogCoordSupported", gGLState.suppFogCoord );
|
||||
Con::setBoolVariable( "$TextureCompressionSupported", gGLState.suppTextureCompression );
|
||||
Con::setBoolVariable( "$AnisotropySupported", gGLState.suppTexAnisotropic );
|
||||
Con::setBoolVariable( "$PalettedTextureSupported", gGLState.suppPalettedTexture );
|
||||
Con::setBoolVariable( "$SwapIntervalSupported", gGLState.suppSwapInterval );
|
||||
|
||||
if (!gGLState.suppPalettedTexture && Con::getBoolVariable("$pref::OpenGL::forcePalettedTexture",false))
|
||||
{
|
||||
Con::setBoolVariable("$pref::OpenGL::forcePalettedTexture", false);
|
||||
Con::setBoolVariable("$pref::OpenGL::force16BitTexture", true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // 0
|
||||
107
Engine/source/platformPOSIX/POSIXMain.cpp
Normal file
107
Engine/source/platformPOSIX/POSIXMain.cpp
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __APPLE__
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "platform/platformInput.h"
|
||||
#include "console/console.h"
|
||||
|
||||
#include "platformX86UNIX/platformX86UNIX.h"
|
||||
#include "platformPOSIX/POSIXStdConsole.h"
|
||||
#include "platformPOSIX/POSIXState.h"
|
||||
|
||||
extern void InitWindowingSystem();
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Platform::init()
|
||||
{
|
||||
StdConsole::create();
|
||||
stdConsole->enable(true);
|
||||
|
||||
// init process control stuff
|
||||
ProcessControlInit();
|
||||
|
||||
Con::printf("Initializing platform...");
|
||||
|
||||
// Set the platform variable for the scripts
|
||||
Con::setVariable( "$platform", "x86UNIX" );
|
||||
#if defined(__linux__)
|
||||
Con::setVariable( "$platformUnixType", "Linux" );
|
||||
#elif defined(__OpenBSD__)
|
||||
Con::setVariable( "$platformUnixType", "OpenBSD" );
|
||||
#else
|
||||
Con::setVariable( "$platformUnixType", "Unknown" );
|
||||
#endif
|
||||
|
||||
Input::init();
|
||||
|
||||
//installRedBookDevices();
|
||||
|
||||
#ifndef TORQUE_DEDICATED
|
||||
// if we're not dedicated do more initialization
|
||||
InitWindowingSystem();
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Platform::shutdown()
|
||||
{
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
bool torque_engineinit(int argc, const char **argv);
|
||||
int torque_enginetick();
|
||||
S32 torque_getreturnstatus();
|
||||
bool torque_engineshutdown();
|
||||
|
||||
int torque_unixmain(int argc, const char **argv)
|
||||
{
|
||||
if (!torque_engineinit(argc, argv))
|
||||
return 1;
|
||||
|
||||
while(torque_enginetick())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
torque_engineshutdown();
|
||||
|
||||
return torque_getreturnstatus();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
extern S32 TorqueMain(S32 argc, const char **argv);
|
||||
|
||||
#if !defined(TORQUE_SHARED)
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
return TorqueMain(argc, argv);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
182
Engine/source/platformPOSIX/POSIXMath.cpp
Normal file
182
Engine/source/platformPOSIX/POSIXMath.cpp
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __APPLE__
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "console/console.h"
|
||||
#include "math/mMath.h"
|
||||
#include "core/strings/stringFunctions.h"
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
extern void mInstallLibrary_C();
|
||||
extern void mInstallLibrary_ASM();
|
||||
|
||||
|
||||
extern void mInstall_AMD_Math();
|
||||
extern void mInstall_Library_SSE();
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
DefineEngineStringlyVariadicFunction( mathInit, void, 1, 10, "( ... )"
|
||||
"@brief Install the math library with specified extensions.\n\n"
|
||||
"Possible parameters are:\n\n"
|
||||
" - 'DETECT' Autodetect math lib settings.\n\n"
|
||||
" - 'C' Enable the C math routines. C routines are always enabled.\n\n"
|
||||
" - 'SSE' Enable SSE math routines.\n\n"
|
||||
"@ingroup Math")
|
||||
{
|
||||
U32 properties = CPU_PROP_C; // C entensions are always used
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
Math::init(0);
|
||||
return;
|
||||
}
|
||||
for (argc--, argv++; argc; argc--, argv++)
|
||||
{
|
||||
if (dStricmp(*argv, "DETECT") == 0) {
|
||||
Math::init(0);
|
||||
return;
|
||||
}
|
||||
if (dStricmp(*argv, "C") == 0) {
|
||||
properties |= CPU_PROP_C;
|
||||
continue;
|
||||
}
|
||||
if (dStricmp(*argv, "FPU") == 0) {
|
||||
properties |= CPU_PROP_FPU;
|
||||
continue;
|
||||
}
|
||||
if (dStricmp(*argv, "MMX") == 0) {
|
||||
properties |= CPU_PROP_MMX;
|
||||
continue;
|
||||
}
|
||||
if (dStricmp(*argv, "3DNOW") == 0) {
|
||||
properties |= CPU_PROP_3DNOW;
|
||||
continue;
|
||||
}
|
||||
if (dStricmp(*argv, "SSE") == 0) {
|
||||
properties |= CPU_PROP_SSE;
|
||||
continue;
|
||||
}
|
||||
Con::printf("Error: MathInit(): ignoring unknown math extension '%s'", (const char*)argv[0]);
|
||||
}
|
||||
Math::init(properties);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Math::init(U32 properties)
|
||||
{
|
||||
if (!properties)
|
||||
// detect what's available
|
||||
properties = Platform::SystemInfo.processor.properties;
|
||||
else
|
||||
// Make sure we're not asking for anything that's not supported
|
||||
properties &= Platform::SystemInfo.processor.properties;
|
||||
|
||||
Con::printf("Math Init:");
|
||||
Con::printf(" Installing Standard C extensions");
|
||||
mInstallLibrary_C();
|
||||
|
||||
#if defined(TORQUE_CPU_X32) || defined(TORQUE_CPU_X64)
|
||||
Con::printf(" Installing Assembly extensions");
|
||||
mInstallLibrary_ASM();
|
||||
#endif
|
||||
|
||||
if (properties & CPU_PROP_FPU)
|
||||
{
|
||||
Con::printf(" Installing FPU extensions");
|
||||
}
|
||||
|
||||
if (properties & CPU_PROP_MMX)
|
||||
{
|
||||
Con::printf(" Installing MMX extensions");
|
||||
if (properties & CPU_PROP_3DNOW)
|
||||
{
|
||||
Con::printf(" Installing 3DNow extensions");
|
||||
mInstall_AMD_Math();
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(__MWERKS__) || (__MWERKS__ >= 0x2400)
|
||||
if (properties & CPU_PROP_SSE)
|
||||
{
|
||||
Con::printf(" Installing SSE extensions");
|
||||
mInstall_Library_SSE();
|
||||
}
|
||||
#endif //mwerks>2.4
|
||||
|
||||
Con::printf(" ");
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static MRandomLCG sgPlatRandom;
|
||||
|
||||
F32 Platform::getRandom()
|
||||
{
|
||||
return sgPlatRandom.randF();
|
||||
}
|
||||
|
||||
|
||||
#if defined(TORQUE_CPU_X86) || defined(__x86_64__)
|
||||
|
||||
U32 Platform::getMathControlState()
|
||||
{
|
||||
U16 cw;
|
||||
asm("fstcw %0" : "=m" (cw) :);
|
||||
return cw;
|
||||
}
|
||||
|
||||
void Platform::setMathControlState(U32 state)
|
||||
{
|
||||
U16 cw = state;
|
||||
asm("fldcw %0" : : "m" (cw));
|
||||
}
|
||||
|
||||
void Platform::setMathControlStateKnown()
|
||||
{
|
||||
U16 cw = 0x27F;
|
||||
asm("fldcw %0" : : "m" (cw));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
U32 Platform::getMathControlState()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Platform::setMathControlState(U32 state)
|
||||
{
|
||||
}
|
||||
|
||||
void Platform::setMathControlStateKnown()
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
68
Engine/source/platformPOSIX/POSIXMemory.cpp
Normal file
68
Engine/source/platformPOSIX/POSIXMemory.cpp
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platformX86UNIX/platformX86UNIX.h"
|
||||
#include <stdlib.h>
|
||||
#include <mm_malloc.h>
|
||||
|
||||
void* dMemcpy(void *dst, const void *src, dsize_t size)
|
||||
{
|
||||
return memcpy(dst,src,size);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
void* dMemmove(void *dst, const void *src, dsize_t size)
|
||||
{
|
||||
return memmove(dst,src,size);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
void* dMemset(void *dst, S32 c, dsize_t size)
|
||||
{
|
||||
return memset(dst,c,size);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
S32 dMemcmp(const void *ptr1, const void *ptr2, dsize_t len)
|
||||
{
|
||||
return memcmp(ptr1, ptr2, len);
|
||||
}
|
||||
|
||||
void* dRealMalloc(dsize_t s)
|
||||
{
|
||||
return malloc(s);
|
||||
}
|
||||
|
||||
void dRealFree(void* p)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
void *dMalloc_aligned(dsize_t in_size, int alignment)
|
||||
{
|
||||
return _mm_malloc(in_size, alignment);
|
||||
}
|
||||
|
||||
void dFree_aligned(void* p)
|
||||
{
|
||||
return _mm_free(p);
|
||||
}
|
||||
237
Engine/source/platformPOSIX/POSIXProcessControl.cpp
Normal file
237
Engine/source/platformPOSIX/POSIXProcessControl.cpp
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __APPLE__
|
||||
|
||||
#include "platformX86UNIX/platformX86UNIX.h"
|
||||
#include "platformPOSIX/POSIXState.h"
|
||||
#include "platformPOSIX/POSIXStdConsole.h"
|
||||
#include "platform/platformInput.h"
|
||||
#include "windowManager/platformWindow.h"
|
||||
#include "windowManager/platformWindowMgr.h"
|
||||
#include "console/console.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include "console/engineAPI.h"
|
||||
#ifndef TORQUE_DEDICATED
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This is a mainly a debugging function for intercepting a nonzero exit code
|
||||
// and generating a core dump for a stack trace.
|
||||
// Need an S64 here because postQuitMessage uses a U32, and
|
||||
// forceshutdown uses an S32. So S64 is needed to
|
||||
// accomodate them both
|
||||
static void CheckExitCode(S64 exitCode)
|
||||
{
|
||||
if (exitCode != 0)
|
||||
{
|
||||
Con::errorf(ConsoleLogEntry::General,
|
||||
"Nonzero exit code: %d, triggering SIGSEGV for core dump",
|
||||
exitCode);
|
||||
kill(getpid(), SIGSEGV);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void SignalHandler(int sigtype)
|
||||
{
|
||||
if (sigtype == SIGSEGV || sigtype == SIGTRAP)
|
||||
{
|
||||
signal(SIGSEGV, SIG_DFL);
|
||||
signal(SIGTRAP, SIG_DFL);
|
||||
// restore the signal handling to default so that we don't get into
|
||||
// a crash loop with ImmediateShutdown
|
||||
ImmediateShutdown(-sigtype, sigtype);
|
||||
}
|
||||
else
|
||||
{
|
||||
signal(sigtype, SIG_DFL);
|
||||
dPrintf("Unknown signal caught by SignalHandler: %d\n", sigtype);
|
||||
// exit to be safe
|
||||
ImmediateShutdown(1);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void Cleanup(bool minimal)
|
||||
{
|
||||
if (!minimal)
|
||||
{
|
||||
Input::destroy();
|
||||
}
|
||||
|
||||
StdConsole::destroy();
|
||||
|
||||
#ifndef TORQUE_DEDICATED
|
||||
SDL_Quit();
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ImmediateShutdown(S32 exitCode, S32 signalNum)
|
||||
{
|
||||
bool segfault = signalNum > 0;
|
||||
|
||||
Cleanup(segfault);
|
||||
|
||||
if (!segfault)
|
||||
{
|
||||
dPrintf("Exiting\n");
|
||||
// exit (doesn't call destructors)
|
||||
_exit(exitCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
// there is a problem in kernel 2.4.17 which causes a hang when a segfault
|
||||
// occurs. also subsequent runs of "ps" will hang and the machine has to be
|
||||
// hard reset to clear up the problem
|
||||
// JMQ: this bug appears to be fixed in 2.4.18
|
||||
//#define KERNEL_2_4_WORKAROUND
|
||||
#ifdef KERNEL_2_4_WORKAROUND
|
||||
dPrintf("Segmentation Fault (Exiting without core dump due to #define KERNEL_2_4_WORKAROUND)\n");
|
||||
dFflushStdout();
|
||||
_exit(exitCode);
|
||||
#else
|
||||
// kill with signal
|
||||
kill(getpid(), signalNum);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void ProcessControlInit()
|
||||
{
|
||||
// JMQ: ignore IO signals background read/write terminal (so that we don't
|
||||
// get suspended in daemon mode)
|
||||
signal(SIGTTIN, SIG_IGN);
|
||||
signal(SIGTTOU, SIG_IGN);
|
||||
|
||||
// we're not interested in the exit status of child processes, so this
|
||||
// prevents zombies from accumulating.
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||
signal(SIGCHLD, SIG_IGN);
|
||||
#else
|
||||
signal(SIGCLD, SIG_IGN);
|
||||
#endif
|
||||
|
||||
// install signal handler for SIGSEGV, so that we can attempt
|
||||
// clean shutdown
|
||||
signal(SIGSEGV, &SignalHandler);
|
||||
signal(SIGTRAP, &SignalHandler);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void Platform::postQuitMessage(const S32 in_quitVal)
|
||||
{
|
||||
// if we have a window send a quit event, otherwise just force shutdown
|
||||
#if 0
|
||||
if (x86UNIXState->windowCreated())
|
||||
{
|
||||
CheckExitCode(in_quitVal);
|
||||
SendQuitEvent();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
forceShutdown(in_quitVal);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void Platform::debugBreak()
|
||||
{
|
||||
// in windows, "Calling DebugBreak causes the program to display
|
||||
// a dialog box as if it had crashed." So we segfault.
|
||||
Con::errorf(ConsoleLogEntry::General,
|
||||
"Platform::debugBreak: triggering SIGSEGV for core dump");
|
||||
//kill(getpid(), SIGSEGV);
|
||||
|
||||
// On Linux, the mouse cursor will remain trapped when the SIGTRAP below triggers so we ensure the mouse
|
||||
// locked state is disabled prior to dropping to debug
|
||||
PlatformWindow* firstWindow = WindowManager->getFirstWindow();
|
||||
if (firstWindow)
|
||||
{
|
||||
firstWindow->setMouseLocked(false);
|
||||
}
|
||||
|
||||
kill(getpid(), SIGTRAP);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void Platform::forceShutdown(S32 returnValue)
|
||||
{
|
||||
#if 0
|
||||
// if a dedicated server is running, turn it off
|
||||
if (x86UNIXState->isDedicated() && Game->isRunning())
|
||||
Game->setRunning(false);
|
||||
else
|
||||
#endif
|
||||
ImmediateShutdown(returnValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void Platform::outputDebugString(const char *string, ...)
|
||||
{
|
||||
char buffer[2048];
|
||||
|
||||
va_list args;
|
||||
va_start( args, string );
|
||||
|
||||
dVsprintf( buffer, sizeof(buffer), string, args );
|
||||
va_end( args );
|
||||
|
||||
U32 length = dStrlen(buffer);
|
||||
if( length == (sizeof(buffer) - 1 ) )
|
||||
length--;
|
||||
|
||||
buffer[length++] = '\n';
|
||||
buffer[length] = '\0';
|
||||
|
||||
fwrite(buffer, sizeof(char), length, stderr);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// testing function
|
||||
//DefineEngineFunction(debug_debugbreak, void, () , , "debug_debugbreak();");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void Platform::restartInstance()
|
||||
{
|
||||
/*
|
||||
if (Game->isRunning() )
|
||||
{
|
||||
//Con::errorf( "Error restarting Instance. Game is Still running!");
|
||||
return;
|
||||
}
|
||||
|
||||
char cmd[2048];
|
||||
sprintf(cmd, "%s &", x86UNIXState->getExePathName());
|
||||
system(cmd);
|
||||
*/
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
261
Engine/source/platformPOSIX/POSIXState.h
Normal file
261
Engine/source/platformPOSIX/POSIXState.h
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "math/mPoint2.h"
|
||||
#include "platformX86UNIX/platformX86UNIX.h"
|
||||
//#include "platformX86UNIX/platformGL.h"
|
||||
#include "core/strings/stringFunctions.h"
|
||||
|
||||
#define Display int
|
||||
#define Window int
|
||||
#define Screen int
|
||||
|
||||
#include <libgen.h> // for basename
|
||||
|
||||
typedef void (*LockFunc_t)(void);
|
||||
|
||||
class DisplayPtrManager;
|
||||
|
||||
class x86UNIXPlatformState
|
||||
{
|
||||
friend class DisplayPtrManager;
|
||||
|
||||
private:
|
||||
Point2I mDesktopSize;
|
||||
Point2I mWindowSize;
|
||||
S32 mDesktopBpp;
|
||||
Display *mDisplay;
|
||||
Window mCurrentWindow;
|
||||
Screen *mScreenPointer;
|
||||
int mScreenNumber;
|
||||
char mWindowName[40];
|
||||
char mExePathName[4096];
|
||||
char mExeName[40];
|
||||
bool mWindowCreated;
|
||||
bool mWindowActive;
|
||||
bool mWindowLocked;
|
||||
bool mXWindowsRunning;
|
||||
bool mDedicated;
|
||||
bool mCDAudioEnabled;
|
||||
bool mDSleep;
|
||||
bool mUseRedirect;
|
||||
|
||||
// Access to the display* needs to be controlled because the SDL event
|
||||
// loop runs in a separate thread. If you need the display pointer,
|
||||
// use the DisplayPtrManager class. See the clipboard functions in
|
||||
// x86unixinput.cc for an example.
|
||||
//Display *getDisplayPointer() { return mDisplay; }
|
||||
|
||||
public:
|
||||
U32 currentTime;
|
||||
|
||||
void setDisplayPointer( Display *displayPointer ) { mDisplay = displayPointer; }
|
||||
Display* getDisplayPointer() { return mDisplay; }
|
||||
|
||||
void setScreenNumber( int newNumber ) { mScreenNumber = newNumber; }
|
||||
int getScreenNumber() { return mScreenNumber; }
|
||||
|
||||
void setScreenPointer( Screen *newScreenPointer )
|
||||
{ mScreenPointer = newScreenPointer; }
|
||||
Screen * getScreenPointer() { return mScreenPointer; }
|
||||
|
||||
// for compatibility, convert 24 bpp to 32
|
||||
void setDesktopBpp( S32 bpp )
|
||||
{
|
||||
if (bpp == 24)
|
||||
mDesktopBpp = 32;
|
||||
else
|
||||
mDesktopBpp = bpp;
|
||||
}
|
||||
S32 getDesktopBpp() { return mDesktopBpp; }
|
||||
|
||||
void setDesktopSize( S32 horizontal, S32 vertical )
|
||||
{ mDesktopSize.set( horizontal, vertical ); }
|
||||
Point2I getDesktopSize() { return mDesktopSize; }
|
||||
|
||||
void setWindow( Window newWindow ) { mCurrentWindow = newWindow; }
|
||||
Window getWindow() { return mCurrentWindow; }
|
||||
|
||||
void setWindowSize (S32 horizontal, S32 vertical )
|
||||
{ mWindowSize.set ( horizontal, vertical ); }
|
||||
void setWindowSize( Point2I size ) { mWindowSize = size; }
|
||||
Point2I& getWindowSize() { return ( mWindowSize ); }
|
||||
|
||||
void setWindowName (const char * windowName)
|
||||
{
|
||||
if (windowName == NULL)
|
||||
dStrncpy( mWindowName, "", sizeof( mWindowName ));
|
||||
else
|
||||
dStrncpy( mWindowName, windowName, sizeof( mWindowName ) );
|
||||
}
|
||||
const char * getWindowName() { return mWindowName; }
|
||||
|
||||
void setExePathName(const char* exePathName)
|
||||
{
|
||||
if (exePathName == NULL)
|
||||
dStrncpy(mExePathName, "", sizeof(mExePathName));
|
||||
else
|
||||
dStrncpy(mExePathName, exePathName, sizeof(mExePathName));
|
||||
|
||||
// set the base exe name field
|
||||
char tempBuf[2048];
|
||||
dStrncpy(tempBuf, mExePathName, 2048);
|
||||
dStrncpy(mExeName, basename(tempBuf), sizeof(mExeName));
|
||||
}
|
||||
const char * getExePathName() { return mExePathName; }
|
||||
const char * getExeName() { return mExeName; }
|
||||
|
||||
bool windowCreated() { return mWindowCreated; }
|
||||
bool windowActive() { return mWindowActive; }
|
||||
bool windowLocked() { return mWindowLocked; }
|
||||
void setWindowCreated(bool windowCreated)
|
||||
{ mWindowCreated = windowCreated; }
|
||||
void setWindowActive(bool windowActive)
|
||||
{ mWindowActive = windowActive; }
|
||||
void setWindowLocked(bool windowLocked)
|
||||
{ mWindowLocked = windowLocked; }
|
||||
|
||||
bool isXWindowsRunning() { return mXWindowsRunning; }
|
||||
void setXWindowsRunning(bool running) { mXWindowsRunning = running; }
|
||||
|
||||
bool isDedicated() { return mDedicated; }
|
||||
void setDedicated(bool dedicated) { mDedicated = dedicated; }
|
||||
|
||||
bool getCDAudioEnabled() { return mCDAudioEnabled; }
|
||||
void setCDAudioEnabled(bool enabled) { mCDAudioEnabled = enabled; }
|
||||
|
||||
bool getDSleep() { return mDSleep; }
|
||||
void setDSleep(bool enabled) { mDSleep = enabled; }
|
||||
|
||||
bool getUseRedirect() { return mUseRedirect; }
|
||||
void setUseRedirect(bool enabled) { mUseRedirect = enabled; }
|
||||
|
||||
x86UNIXPlatformState()
|
||||
{
|
||||
currentTime = 0;
|
||||
mDesktopBpp = 16;
|
||||
mDesktopSize.set( 0, 0 );
|
||||
mWindowSize.set( 800, 600 );
|
||||
setWindowName("Torque");
|
||||
setExePathName(NULL);
|
||||
mWindowCreated = mWindowActive = mWindowLocked = false;
|
||||
mXWindowsRunning = false;
|
||||
mDedicated = false;
|
||||
mCDAudioEnabled = false;
|
||||
mDSleep = false;
|
||||
#ifdef USE_FILE_REDIRECT
|
||||
mUseRedirect = true;
|
||||
#else
|
||||
mUseRedirect = false;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
extern x86UNIXPlatformState * x86UNIXState;
|
||||
|
||||
class DisplayPtrManager
|
||||
{
|
||||
// static interface
|
||||
private:
|
||||
static bool sgDisplayLocked;
|
||||
static LockFunc_t sgLockFunc;
|
||||
static LockFunc_t sgUnlockFunc;
|
||||
|
||||
static bool lockDisplay()
|
||||
{
|
||||
if (!sgDisplayLocked && sgLockFunc)
|
||||
{
|
||||
sgLockFunc();
|
||||
sgDisplayLocked = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
static void unlockDisplay()
|
||||
{
|
||||
if (sgDisplayLocked && sgUnlockFunc)
|
||||
{
|
||||
sgUnlockFunc();
|
||||
sgDisplayLocked = false;
|
||||
}
|
||||
}
|
||||
|
||||
//friend Display* x86UNIXPlatformState::getDisplayPointer();
|
||||
|
||||
public:
|
||||
static void setDisplayLockFunction(LockFunc_t lockFunc)
|
||||
{ sgLockFunc = lockFunc; }
|
||||
static void setDisplayUnlockFunction(LockFunc_t unlockFunc)
|
||||
{ sgUnlockFunc = unlockFunc; }
|
||||
|
||||
// nonstatic interface
|
||||
private:
|
||||
bool mAcquiredLock; // true if this instance acquired the display lock
|
||||
// (multiple instances of DisplayPtrManager can coexist, but only
|
||||
// the first to access the display pointer will be responsible for
|
||||
// acquiring and releasing the lock)
|
||||
bool mOpenedDisplay; // true if this instance created a display pointer
|
||||
// because the one in platform state was null.
|
||||
Display* mDisplay;
|
||||
|
||||
private:
|
||||
Display* openDisplay()
|
||||
{
|
||||
return mDisplay;
|
||||
}
|
||||
|
||||
void closeDisplay()
|
||||
{
|
||||
if (mOpenedDisplay)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
public:
|
||||
DisplayPtrManager()
|
||||
{
|
||||
mAcquiredLock = false;
|
||||
mOpenedDisplay = false;
|
||||
mDisplay = NULL;
|
||||
}
|
||||
|
||||
~DisplayPtrManager()
|
||||
{
|
||||
if (mAcquiredLock)
|
||||
{
|
||||
DisplayPtrManager::unlockDisplay();
|
||||
mAcquiredLock = false;
|
||||
}
|
||||
closeDisplay();
|
||||
}
|
||||
|
||||
Display* getDisplayPointer()
|
||||
{
|
||||
Display* display = x86UNIXState->getDisplayPointer();
|
||||
if (display == NULL)
|
||||
return openDisplay();
|
||||
|
||||
mAcquiredLock = DisplayPtrManager::lockDisplay();
|
||||
return display;
|
||||
}
|
||||
};
|
||||
75
Engine/source/platformPOSIX/POSIXStdConsole.h
Normal file
75
Engine/source/platformPOSIX/POSIXStdConsole.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _X86UNIXSTDCONSOLE_H_
|
||||
#define _X86UNIXSTDCONSOLE_H_
|
||||
|
||||
#define MAX_CMDS 10
|
||||
#ifndef _CONSOLE_H_
|
||||
#include "console/console.h"
|
||||
#endif
|
||||
#ifndef _EVENT_H_
|
||||
#include "platform/event.h"
|
||||
#endif
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
class StdConsole
|
||||
{
|
||||
bool stdConsoleEnabled;
|
||||
bool stdConsoleInputEnabled;
|
||||
// true if we're running in the background
|
||||
bool inBackground;
|
||||
|
||||
int stdOut;
|
||||
int stdIn;
|
||||
int stdErr;
|
||||
char inbuf[512];
|
||||
S32 inpos;
|
||||
bool lineOutput;
|
||||
char curTabComplete[512];
|
||||
S32 tabCompleteStart;
|
||||
char rgCmds[MAX_CMDS][512];
|
||||
S32 iCmdIndex;
|
||||
|
||||
// this holds the original terminal state
|
||||
// before we messed with it
|
||||
struct termios *originalTermState;
|
||||
|
||||
void printf(const char *s, ...);
|
||||
|
||||
public:
|
||||
StdConsole();
|
||||
virtual ~StdConsole();
|
||||
void process();
|
||||
void enable(bool);
|
||||
void enableInput(bool enabled);
|
||||
void processConsoleLine(const char *consoleLine);
|
||||
static void create();
|
||||
static void destroy();
|
||||
static bool isEnabled();
|
||||
void resetTerminal();
|
||||
};
|
||||
|
||||
extern StdConsole *stdConsole;
|
||||
|
||||
#endif
|
||||
70
Engine/source/platformPOSIX/POSIXStrings.cpp
Normal file
70
Engine/source/platformPOSIX/POSIXStrings.cpp
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platformX86UNIX/platformX86UNIX.h"
|
||||
#include "core/strings/stringFunctions.h"
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
const char *stristr(const char *szStringToBeSearched, const char *szSubstringToSearchFor)
|
||||
{
|
||||
const char *pPos = NULL;
|
||||
char *szCopy1 = NULL;
|
||||
char *szCopy2 = NULL;
|
||||
|
||||
// verify parameters
|
||||
if ( szStringToBeSearched == NULL ||
|
||||
szSubstringToSearchFor == NULL )
|
||||
{
|
||||
return szStringToBeSearched;
|
||||
}
|
||||
|
||||
// empty substring - return input (consistent with strstr)
|
||||
if (strlen(szSubstringToSearchFor) == 0 ) {
|
||||
return szStringToBeSearched;
|
||||
}
|
||||
|
||||
szCopy1 = dStrlwr(strdup(szStringToBeSearched));
|
||||
szCopy2 = dStrlwr(strdup(szSubstringToSearchFor));
|
||||
|
||||
if ( szCopy1 == NULL || szCopy2 == NULL ) {
|
||||
// another option is to raise an exception here
|
||||
free((void*)szCopy1);
|
||||
free((void*)szCopy2);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pPos = strstr((const char*)szCopy1, (const char*)szCopy2);
|
||||
|
||||
if ( pPos != NULL ) {
|
||||
// map to the original string
|
||||
pPos = szStringToBeSearched + (pPos - szCopy1);
|
||||
}
|
||||
|
||||
free((void*)szCopy1);
|
||||
free((void*)szCopy2);
|
||||
|
||||
return pPos;
|
||||
} // stristr(...)
|
||||
|
||||
163
Engine/source/platformPOSIX/POSIXTime.cpp
Normal file
163
Engine/source/platformPOSIX/POSIXTime.cpp
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __APPLE__
|
||||
|
||||
#include "platformX86UNIX/platformX86UNIX.h"
|
||||
#include "platform/platformTimer.h"
|
||||
#include "time.h"
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static U32 sgCurrentTime = 0;
|
||||
|
||||
U32 x86UNIXGetTickCount();
|
||||
|
||||
//--------------------------------------
|
||||
void Platform::getLocalTime(LocalTime <)
|
||||
{
|
||||
struct tm *systime;
|
||||
time_t long_time;
|
||||
|
||||
time( &long_time ); // Get time as long integer.
|
||||
systime = localtime( &long_time ); // Convert to local time.
|
||||
|
||||
lt.sec = systime->tm_sec;
|
||||
lt.min = systime->tm_min;
|
||||
lt.hour = systime->tm_hour;
|
||||
lt.month = systime->tm_mon;
|
||||
lt.monthday = systime->tm_mday;
|
||||
lt.weekday = systime->tm_wday;
|
||||
lt.year = systime->tm_year;
|
||||
lt.yearday = systime->tm_yday;
|
||||
lt.isdst = systime->tm_isdst;
|
||||
}
|
||||
|
||||
String Platform::localTimeToString( const LocalTime < )
|
||||
{
|
||||
tm systime;
|
||||
|
||||
systime.tm_sec = lt.sec;
|
||||
systime.tm_min = lt.min;
|
||||
systime.tm_hour = lt.hour;
|
||||
systime.tm_mon = lt.month;
|
||||
systime.tm_mday = lt.monthday;
|
||||
systime.tm_wday = lt.weekday;
|
||||
systime.tm_year = lt.year;
|
||||
systime.tm_yday = lt.yearday;
|
||||
systime.tm_isdst = lt.isdst;
|
||||
|
||||
return asctime( &systime );
|
||||
}
|
||||
|
||||
U32 Platform::getTime()
|
||||
{
|
||||
time_t long_time;
|
||||
time( &long_time );
|
||||
return long_time;
|
||||
}
|
||||
|
||||
U32 Platform::getRealMilliseconds()
|
||||
{
|
||||
// struct rusage usageStats;
|
||||
// getrusage(RUSAGE_SELF, &usageStats);
|
||||
// return usageStats.ru_utime.tv_usec;
|
||||
return x86UNIXGetTickCount();
|
||||
}
|
||||
|
||||
U32 Platform::getVirtualMilliseconds()
|
||||
{
|
||||
return sgCurrentTime;
|
||||
}
|
||||
|
||||
void Platform::advanceTime(U32 delta)
|
||||
{
|
||||
sgCurrentTime += delta;
|
||||
}
|
||||
|
||||
void Platform::fileToLocalTime(const FileTime & ft, LocalTime * lt)
|
||||
{
|
||||
if(!lt)
|
||||
return;
|
||||
|
||||
time_t long_time = ft;
|
||||
|
||||
struct tm systime;
|
||||
|
||||
/// Convert to local time, thread safe.
|
||||
localtime_r( &long_time, &systime );
|
||||
|
||||
/// Fill the return struct
|
||||
lt->sec = systime.tm_sec;
|
||||
lt->min = systime.tm_min;
|
||||
lt->hour = systime.tm_hour;
|
||||
lt->month = systime.tm_mon;
|
||||
lt->monthday = systime.tm_mday;
|
||||
lt->weekday = systime.tm_wday;
|
||||
lt->year = systime.tm_year;
|
||||
lt->yearday = systime.tm_yday;
|
||||
lt->isdst = systime.tm_isdst;
|
||||
}
|
||||
|
||||
PlatformTimer *PlatformTimer::create()
|
||||
{
|
||||
return new DefaultPlatformTimer();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
//-------------------------------------- x86UNIX Implementation
|
||||
//
|
||||
//
|
||||
static bool sg_initialized = false;
|
||||
static U32 sg_secsOffset = 0;
|
||||
//--------------------------------------
|
||||
U32 x86UNIXGetTickCount()
|
||||
{
|
||||
// TODO: What happens when crossing a day boundary?
|
||||
//
|
||||
timeval t;
|
||||
|
||||
if (sg_initialized == false) {
|
||||
sg_initialized = true;
|
||||
|
||||
gettimeofday(&t, NULL);
|
||||
sg_secsOffset = t.tv_sec;
|
||||
}
|
||||
|
||||
gettimeofday(&t, NULL);
|
||||
|
||||
U32 secs = t.tv_sec - sg_secsOffset;
|
||||
U32 uSecs = t.tv_usec;
|
||||
|
||||
// Make granularity 1 ms
|
||||
return (secs * 1000) + (uSecs / 1000);
|
||||
}
|
||||
|
||||
|
||||
void Platform::sleep(U32 ms)
|
||||
{
|
||||
// note: this will overflow if you want to sleep for more than 49 days. just so ye know.
|
||||
usleep( ms * 1000 );
|
||||
}
|
||||
#endif
|
||||
284
Engine/source/platformPOSIX/POSIXUtils.cpp
Normal file
284
Engine/source/platformPOSIX/POSIXUtils.cpp
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
// for UnixCommandExecutor
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "platformX86UNIX/platformX86UNIX.h"
|
||||
#include "platformPOSIX/POSIXUtils.h"
|
||||
|
||||
UnixUtils *UUtils = NULL;
|
||||
UnixUtils utils;
|
||||
|
||||
UnixUtils::UnixUtils()
|
||||
{
|
||||
UUtils = this;
|
||||
|
||||
mUnameInfo = (struct utsname*)dRealMalloc(sizeof(struct utsname));;
|
||||
if (uname(mUnameInfo) == -1)
|
||||
{
|
||||
// oh well
|
||||
dRealFree(mUnameInfo);
|
||||
mUnameInfo = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
UnixUtils::~UnixUtils()
|
||||
{
|
||||
if (mUnameInfo != NULL)
|
||||
{
|
||||
dRealFree(mUnameInfo);
|
||||
mUnameInfo = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const char* UnixUtils::getOSName()
|
||||
{
|
||||
if (mUnameInfo == NULL)
|
||||
return "";
|
||||
|
||||
return mUnameInfo->sysname;
|
||||
}
|
||||
|
||||
bool UnixUtils::inBackground()
|
||||
{
|
||||
int terminalGroupId = tcgetpgrp(fileno(stdin));
|
||||
int myPid = getpid();
|
||||
if (terminalGroupId != myPid)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// UnixCommandExecutor
|
||||
void UnixCommandExecutor::clearFields()
|
||||
{
|
||||
mRet = -1;
|
||||
mStdoutSave = -1;
|
||||
mStderrSave = -1;
|
||||
mPipeFiledes[0] = -1;
|
||||
mPipeFiledes[1] = -1;
|
||||
mChildPID = -1;
|
||||
mBytesRead = 0;
|
||||
mStdoutClosed = false;
|
||||
mStderrClosed = false;
|
||||
mChildExited = false;
|
||||
}
|
||||
|
||||
UnixCommandExecutor::UnixCommandExecutor()
|
||||
{
|
||||
clearFields();
|
||||
}
|
||||
|
||||
UnixCommandExecutor::~UnixCommandExecutor()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
int UnixCommandExecutor::exec(char* args[],
|
||||
char* stdoutCapture, int stdoutCaptureSize)
|
||||
{
|
||||
// check for shitty parameters
|
||||
if (args == NULL || stdoutCapture == NULL ||
|
||||
stdoutCaptureSize <= 0)
|
||||
return -666;
|
||||
|
||||
// we're going to be redirecting stdout, so save it so that we can
|
||||
// restore it
|
||||
mRet = dup(1);
|
||||
if (mRet == -1)
|
||||
{
|
||||
cleanup();
|
||||
return mRet;
|
||||
}
|
||||
mStdoutSave = mRet;
|
||||
|
||||
// save stderr
|
||||
mRet = dup(2);
|
||||
if (mRet == -1)
|
||||
{
|
||||
cleanup();
|
||||
return mRet;
|
||||
}
|
||||
mStderrSave = mRet;
|
||||
|
||||
// we'll need some pipe action for communicating with subprocess
|
||||
mRet = pipe(mPipeFiledes);
|
||||
if (mRet == -1)
|
||||
{
|
||||
cleanup();
|
||||
return mRet;
|
||||
}
|
||||
|
||||
// close stdout
|
||||
mRet = close(1);
|
||||
if (mRet == -1)
|
||||
{
|
||||
cleanup();
|
||||
return mRet;
|
||||
}
|
||||
mStdoutClosed = true;
|
||||
|
||||
// stderr just gets closed and the output discarded
|
||||
mRet = close(2);
|
||||
if (mRet == -1)
|
||||
{
|
||||
cleanup();
|
||||
return mRet;
|
||||
}
|
||||
mStderrClosed = true;
|
||||
|
||||
// dup the pipe output into stdout
|
||||
mRet = dup2(mPipeFiledes[1], 1);
|
||||
if (mRet == -1)
|
||||
{
|
||||
cleanup();
|
||||
return mRet;
|
||||
}
|
||||
|
||||
// fork
|
||||
mRet = fork();
|
||||
if (mRet == -1)
|
||||
{
|
||||
cleanup();
|
||||
return mRet;
|
||||
}
|
||||
|
||||
if (mRet == 0)
|
||||
{
|
||||
// child process
|
||||
|
||||
//close(mPipeFiledes[0]);
|
||||
mRet = execvp(args[0], args);
|
||||
// if exec returns, some bad shit went down, so just
|
||||
// get outta here
|
||||
exit(mRet);
|
||||
}
|
||||
|
||||
// parent process
|
||||
mChildPID = mRet;
|
||||
|
||||
// need to suck in data from pipe while child is running,
|
||||
// otherwise child will eventually block on write and we'll
|
||||
// wait forever
|
||||
memset(stdoutCapture, 0, stdoutCaptureSize);
|
||||
|
||||
// set input to be non blocking so that we don't block on read
|
||||
mRet = fcntl(mPipeFiledes[0], F_SETFL, O_NONBLOCK);
|
||||
if (mRet == -1)
|
||||
{
|
||||
cleanup();
|
||||
return mRet;
|
||||
}
|
||||
|
||||
// check to see if child has exited
|
||||
mRet = waitpid(mChildPID, NULL, WNOHANG);
|
||||
while (mRet == 0)
|
||||
{
|
||||
// not exited, read some data
|
||||
mRet = read(mPipeFiledes[0], stdoutCapture + mBytesRead,
|
||||
stdoutCaptureSize - mBytesRead);
|
||||
// any error that isn't EAGAIN means we should exit
|
||||
if (mRet == -1 && errno != EAGAIN)
|
||||
{
|
||||
cleanup();
|
||||
return mRet;
|
||||
}
|
||||
|
||||
// if the read was ok, increment bytes read
|
||||
if (mRet != -1)
|
||||
mBytesRead += mRet;
|
||||
|
||||
// check again for child exit
|
||||
mRet = waitpid(mChildPID, NULL, WNOHANG);
|
||||
}
|
||||
|
||||
// check for error from waitpid
|
||||
if (mRet == -1 && errno != ECHILD)
|
||||
{
|
||||
cleanup();
|
||||
return mRet;
|
||||
}
|
||||
|
||||
// if we get here, the child exited
|
||||
mChildExited = true;
|
||||
|
||||
// read final bit of data
|
||||
mRet = read(mPipeFiledes[0], stdoutCapture + mBytesRead,
|
||||
stdoutCaptureSize - mBytesRead);
|
||||
if (mRet == -1 && errno != EAGAIN)
|
||||
{
|
||||
cleanup();
|
||||
return mRet;
|
||||
}
|
||||
|
||||
if (mRet != -1)
|
||||
mBytesRead += mRet;
|
||||
|
||||
// done...cleanup
|
||||
cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UnixCommandExecutor::cleanup()
|
||||
{
|
||||
// if child spawned and not exited, wait
|
||||
if (mChildPID > 0 && !mChildExited)
|
||||
waitpid(mChildPID, NULL, 0);
|
||||
// close pipe descriptors
|
||||
if (mPipeFiledes[0] != -1)
|
||||
close(mPipeFiledes[0]);
|
||||
if (mPipeFiledes[1] != -1)
|
||||
close(mPipeFiledes[1]);
|
||||
// if stdout is redirected, restore it
|
||||
if (mStdoutClosed && mStdoutSave != -1)
|
||||
dup2(mStdoutSave, 1);
|
||||
// close stdout save descriptor
|
||||
if (mStdoutSave != -1)
|
||||
close(mStdoutSave);
|
||||
// if stderr is redirected, restore it
|
||||
if (mStderrClosed && mStderrSave != -1)
|
||||
dup2(mStderrSave, 2);
|
||||
// close stderr save descriptor
|
||||
if (mStderrSave != -1)
|
||||
close(mStderrSave);
|
||||
|
||||
clearFields();
|
||||
}
|
||||
|
||||
/* Usage:
|
||||
UnixCommandExecutor exec;
|
||||
char* args[] = { "ps", "-aux", NULL };
|
||||
char data[20000];
|
||||
int ret = exec.exec(args, data, sizeof(data));
|
||||
printf("%s", data);
|
||||
*/
|
||||
90
Engine/source/platformPOSIX/POSIXUtils.h
Normal file
90
Engine/source/platformPOSIX/POSIXUtils.h
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _X86UNIXUTILS_H_
|
||||
#define _X86UNIXUTILS_H_
|
||||
|
||||
struct utsname;
|
||||
|
||||
class UnixUtils
|
||||
{
|
||||
public:
|
||||
UnixUtils();
|
||||
virtual ~UnixUtils();
|
||||
|
||||
/**
|
||||
Returns true if we're running in the background, false otherwise.
|
||||
There's no "standard" way to determine this in unix, but
|
||||
modern job control unices should support the method described
|
||||
here:
|
||||
|
||||
http://www.faqs.org/faqs/unix-faq/faq/part3/
|
||||
|
||||
(question 3.7)
|
||||
*/
|
||||
bool inBackground();
|
||||
|
||||
/**
|
||||
Returns the name of the OS, as reported by uname.
|
||||
*/
|
||||
const char* getOSName();
|
||||
|
||||
private:
|
||||
struct utsname* mUnameInfo;
|
||||
};
|
||||
|
||||
extern UnixUtils *UUtils;
|
||||
|
||||
// utility class for running a unix command and capturing its output
|
||||
class UnixCommandExecutor
|
||||
{
|
||||
private:
|
||||
int mRet;
|
||||
int mStdoutSave;
|
||||
int mStderrSave;
|
||||
int mPipeFiledes[2];
|
||||
int mChildPID;
|
||||
int mBytesRead;
|
||||
bool mStdoutClosed;
|
||||
bool mStderrClosed;
|
||||
bool mChildExited;
|
||||
|
||||
void clearFields();
|
||||
void cleanup();
|
||||
|
||||
public:
|
||||
UnixCommandExecutor();
|
||||
~UnixCommandExecutor();
|
||||
|
||||
// Runs the specified command.
|
||||
// - args is a null terminated list of the command and its arguments,
|
||||
// e.g: "ps", "-aux", NULL
|
||||
// - stdoutCapture is the buffer where stdout data will be stored
|
||||
// - stdoutCaptureSize is the size of the buffer
|
||||
// None of these parameters may be null. stdoutCaptureSize must be > 0
|
||||
//
|
||||
// returns -2 if the parameters are bad. returns -1 if some other
|
||||
// error occurs, check errno for the exact error.
|
||||
int exec(char* args[], char* stdoutCapture, int stdoutCaptureSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue