First shot at SMP renderer with sdl_glimp. Does not work yet!

This commit is contained in:
Ryan C. Gordon 2005-11-28 10:56:27 +00:00
parent 4517e7a34b
commit 6c0079508c
2 changed files with 116 additions and 47 deletions

View file

@ -326,8 +326,8 @@ ifeq ($(PLATFORM),darwin)
$(B)/baseq3/vm/ui.qvm \ $(B)/baseq3/vm/ui.qvm \
$(B)/missionpack/vm/qagame.qvm \ $(B)/missionpack/vm/qagame.qvm \
$(B)/missionpack/vm/cgame.qvm \ $(B)/missionpack/vm/cgame.qvm \
$(B)/missionpack/vm/ui.qvm $(B)/missionpack/vm/ui.qvm \
# $(B)/$(PLATFORM)quake3-smp \ $(B)/$(PLATFORM)quake3-smp \
else # ifeq darwin else # ifeq darwin
@ -997,6 +997,18 @@ ifeq ($(PLATFORM),darwin)
$(B)/client/linux_snd.o \ $(B)/client/linux_snd.o \
$(B)/client/sdl_snd.o \ $(B)/client/sdl_snd.o \
Q3POBJ_SMP=\
$(B)/client/unix_main.o \
$(B)/client/unix_net.o \
$(B)/client/unix_shared.o \
$(B)/client/linux_signals.o \
$(B)/client/linux_common.o \
$(B)/client/linux_qgl.o \
$(B)/client/sdl_glimp_smp.o \
$(B)/client/linux_joystick.o \
$(B)/client/linux_snd.o \
$(B)/client/sdl_snd.o \
ifeq ($(ARCH),i386) ifeq ($(ARCH),i386)
I386OBJS := \ I386OBJS := \
$(B)/client/ftola.o \ $(B)/client/ftola.o \
@ -1212,6 +1224,7 @@ $(B)/client/linux_common.o : $(UDIR)/linux_common.c; $(DO_CC)
$(B)/client/linux_glimp.o : $(UDIR)/linux_glimp.c; $(DO_CC) $(GL_CFLAGS) $(B)/client/linux_glimp.o : $(UDIR)/linux_glimp.c; $(DO_CC) $(GL_CFLAGS)
$(B)/client/sdl_glimp.o : $(UDIR)/sdl_glimp.c; $(DO_CC) $(GL_CFLAGS) $(B)/client/sdl_glimp.o : $(UDIR)/sdl_glimp.c; $(DO_CC) $(GL_CFLAGS)
$(B)/client/linux_glimp_smp.o : $(UDIR)/linux_glimp.c; $(DO_SMP_CC) $(GL_CFLAGS) $(B)/client/linux_glimp_smp.o : $(UDIR)/linux_glimp.c; $(DO_SMP_CC) $(GL_CFLAGS)
$(B)/client/sdl_glimp_smp.o : $(UDIR)/sdl_glimp.c; $(DO_SMP_CC) $(GL_CFLAGS)
$(B)/client/linux_joystick.o : $(UDIR)/linux_joystick.c; $(DO_CC) $(B)/client/linux_joystick.o : $(UDIR)/linux_joystick.c; $(DO_CC)
$(B)/client/linux_qgl.o : $(UDIR)/linux_qgl.c; $(DO_CC) $(GL_CFLAGS) $(B)/client/linux_qgl.o : $(UDIR)/linux_qgl.c; $(DO_CC) $(GL_CFLAGS)
$(B)/client/linux_input.o : $(UDIR)/linux_input.c; $(DO_CC) $(B)/client/linux_input.o : $(UDIR)/linux_input.c; $(DO_CC)

View file

@ -60,6 +60,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "SDL.h" #include "SDL.h"
#ifdef SMP
#include "SDL_thread.h"
#endif
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -1024,8 +1028,9 @@ void GLimp_EndFrame (void)
QGL_EnableLogging( (qboolean)r_logFile->integer ); // bk001205 - was ->value QGL_EnableLogging( (qboolean)r_logFile->integer ); // bk001205 - was ->value
} }
// Figure out something to do with this...
#if 0 //def SMP
#ifdef SMP
/* /*
=========================================================== ===========================================================
@ -1034,50 +1039,101 @@ SMP acceleration
=========================================================== ===========================================================
*/ */
static pthread_mutex_t smpMutex = PTHREAD_MUTEX_INITIALIZER; /*
* I have no idea if this will even work...most platforms don't offer
* thread-safe OpenGL libraries, and it looks like the original Linux
* code counted on each thread claiming the GL context with glXMakeCurrent(),
* which you can't currently do in SDL. We'll just have to hope for the best.
*/
static pthread_cond_t renderCommandsEvent = PTHREAD_COND_INITIALIZER; static SDL_mutex *smpMutex = NULL;
static pthread_cond_t renderCompletedEvent = PTHREAD_COND_INITIALIZER; static SDL_cond *renderCommandsEvent = NULL;
static SDL_cond *renderCompletedEvent = NULL;
static void (*glimpRenderThread)( void ) = NULL;
static SDL_Thread *renderThread = NULL;
static void (*glimpRenderThread)( void ); static void GLimp_ShutdownRenderThread(void)
{
if (smpMutex != NULL)
{
SDL_DestroyMutex(smpMutex);
smpMutex = NULL;
}
static void *GLimp_RenderThreadWrapper( void *arg ) if (renderCommandsEvent != NULL)
{
SDL_DestroyCond(renderCommandsEvent);
renderCommandsEvent = NULL;
}
if (renderCompletedEvent != NULL)
{
SDL_DestroyCond(renderCompletedEvent);
renderCompletedEvent = NULL;
}
glimpRenderThread = NULL;
}
static int GLimp_RenderThreadWrapper( void *arg )
{ {
Com_Printf( "Render thread starting\n" ); Com_Printf( "Render thread starting\n" );
glimpRenderThread(); glimpRenderThread();
qglXMakeCurrent( dpy, None, NULL ); //qglXMakeCurrent( dpy, None, NULL );
Com_Printf( "Render thread terminating\n" ); Com_Printf( "Render thread terminating\n" );
return arg; return 0;
} }
qboolean GLimp_SpawnRenderThread( void (*function)( void ) ) qboolean GLimp_SpawnRenderThread( void (*function)( void ) )
{ {
pthread_t renderThread; if (renderThread != NULL) /* hopefully just a zombie at this point... */
int ret; {
Com_Printf("Already a render thread? Trying to clean it up...\n");
SDL_WaitThread(renderThread, NULL);
renderThread = NULL;
GLimp_ShutdownRenderThread();
}
pthread_mutex_init( &smpMutex, NULL ); smpMutex = SDL_CreateMutex();
if (smpMutex == NULL)
{
Com_Printf( "smpMutex creation failed: %s\n", SDL_GetError() );
GLimp_ShutdownRenderThread();
return qfalse;
}
pthread_cond_init( &renderCommandsEvent, NULL ); renderCommandsEvent = SDL_CreateCond();
pthread_cond_init( &renderCompletedEvent, NULL ); if (renderCommandsEvent == NULL)
{
Com_Printf( "renderCommandsEvent creation failed: %s\n", SDL_GetError() );
GLimp_ShutdownRenderThread();
return qfalse;
}
renderCompletedEvent = SDL_CreateCond();
if (renderCompletedEvent == NULL)
{
Com_Printf( "renderCompletedEvent creation failed: %s\n", SDL_GetError() );
GLimp_ShutdownRenderThread();
return qfalse;
}
glimpRenderThread = function; glimpRenderThread = function;
renderThread = SDL_CreateThread(GLimp_RenderThreadWrapper, NULL);
ret = pthread_create( &renderThread, if ( renderThread == NULL ) {
NULL, // attributes ri.Printf( PRINT_ALL, "SDL_CreateThread() returned %s", SDL_GetError() );
GLimp_RenderThreadWrapper, GLimp_ShutdownRenderThread();
NULL ); // argument
if ( ret ) {
ri.Printf( PRINT_ALL, "pthread_create returned %d: %s", ret, strerror( ret ) );
return qfalse; return qfalse;
} else { } else {
ret = pthread_detach( renderThread ); // !!! FIXME: No detach API available in SDL!
if ( ret ) { //ret = pthread_detach( renderThread );
ri.Printf( PRINT_ALL, "pthread_detach returned %d: %s", ret, strerror( ret ) ); //if ( ret ) {
} //ri.Printf( PRINT_ALL, "pthread_detach returned %d: %s", ret, strerror( ret ) );
//}
} }
return qtrue; return qtrue;
@ -1088,58 +1144,58 @@ static volatile qboolean smpDataReady;
void *GLimp_RendererSleep( void ) void *GLimp_RendererSleep( void )
{ {
void *data; void *data = NULL;
qglXMakeCurrent( dpy, None, NULL ); //qglXMakeCurrent( dpy, None, NULL );
pthread_mutex_lock( &smpMutex ); SDL_LockMutex(smpMutex);
{ {
smpData = NULL; smpData = NULL;
smpDataReady = qfalse; smpDataReady = qfalse;
// after this, the front end can exit GLimp_FrontEndSleep // after this, the front end can exit GLimp_FrontEndSleep
pthread_cond_signal( &renderCompletedEvent ); SDL_CondSignal(renderCompletedEvent);
while ( !smpDataReady ) { while ( !smpDataReady ) {
pthread_cond_wait( &renderCommandsEvent, &smpMutex ); SDL_CondWait(renderCommandsEvent, smpMutex);
} }
data = (void *)smpData; data = (void *)smpData;
} }
pthread_mutex_unlock( &smpMutex ); SDL_UnlockMutex(smpMutex);
qglXMakeCurrent( dpy, win, ctx ); //qglXMakeCurrent( dpy, win, ctx );
return data; return data;
} }
void GLimp_FrontEndSleep( void ) void GLimp_FrontEndSleep( void )
{ {
pthread_mutex_lock( &smpMutex ); SDL_LockMutex(smpMutex);
{ {
while ( smpData ) { while ( smpData ) {
pthread_cond_wait( &renderCompletedEvent, &smpMutex ); SDL_CondWait(renderCompletedEvent, smpMutex);
} }
} }
pthread_mutex_unlock( &smpMutex ); SDL_UnlockMutex(smpMutex);
qglXMakeCurrent( dpy, win, ctx ); //qglXMakeCurrent( dpy, win, ctx );
} }
void GLimp_WakeRenderer( void *data ) void GLimp_WakeRenderer( void *data )
{ {
qglXMakeCurrent( dpy, None, NULL ); //qglXMakeCurrent( dpy, None, NULL );
pthread_mutex_lock( &smpMutex ); SDL_LockMutex(smpMutex);
{ {
assert( smpData == NULL ); assert( smpData == NULL );
smpData = data; smpData = data;
smpDataReady = qtrue; smpDataReady = qtrue;
// after this, the renderer can continue through GLimp_RendererSleep // after this, the renderer can continue through GLimp_RendererSleep
pthread_cond_signal( &renderCommandsEvent ); SDL_CondSignal(renderCommandsEvent);
} }
pthread_mutex_unlock( &smpMutex ); SDL_UnlockMutex(smpMutex);
} }
#else #else