Merge remote-tracking branch 'RBDOOM-3-BFG/master'

This commit is contained in:
Robert Beckebans 2013-05-24 19:00:00 +02:00
commit 3fd3a6b284
14 changed files with 332 additions and 265 deletions

View file

@ -411,7 +411,10 @@ bool idFile_SaveGamePipelined::OpenForWriting( const char* const filename, bool
{
compressThread = new( TAG_IDFILE ) idSGFcompressThread();
compressThread->sgf = this;
compressThread->StartWorkerThread( "SGF_CompressThread", CORE_2B, THREAD_NORMAL );
// DG: change threadname from "SGF_CompressThread" to "SGF_Compress", because Linux
// has a 15 (+ \0) char limit for threadnames. also, "thread" in a threadname is redundant
compressThread->StartWorkerThread( "SGF_Compress", CORE_2B, THREAD_NORMAL );
// DG end
}
if( nativeFile != NULL && sgf_threads.GetInteger() >= 2 )
{
@ -468,7 +471,10 @@ bool idFile_SaveGamePipelined::OpenForWriting( idFile* file )
{
compressThread = new( TAG_IDFILE ) idSGFcompressThread();
compressThread->sgf = this;
compressThread->StartWorkerThread( "SGF_CompressThread", CORE_2B, THREAD_NORMAL );
// DG: change threadname from "SGF_CompressThread" to "SGF_Compress", because Linux
// has a 15 (+ \0) char limit for threadnames. also, "thread" in a threadname is redundant
compressThread->StartWorkerThread( "SGF_Compress", CORE_2B, THREAD_NORMAL );
// DG end
}
if( nativeFile != NULL && sgf_threads.GetInteger() >= 2 )
{
@ -810,7 +816,10 @@ bool idFile_SaveGamePipelined::OpenForReading( const char* const filename, bool
{
decompressThread = new( TAG_IDFILE ) idSGFdecompressThread();
decompressThread->sgf = this;
decompressThread->StartWorkerThread( "SGF_DecompressThread", CORE_2B, THREAD_NORMAL );
// DG: change threadname from "SGF_DecompressThread" to "SGF_Decompress", because Linux
// has a 15 (+ \0) char limit for threadnames. also, "thread" in a threadname is redundant
decompressThread->StartWorkerThread( "SGF_Decompress", CORE_2B, THREAD_NORMAL );
// DG end
}
if( nativeFile != NULL && sgf_threads.GetInteger() >= 2 )
{
@ -857,7 +866,10 @@ bool idFile_SaveGamePipelined::OpenForReading( idFile* file )
{
decompressThread = new( TAG_IDFILE ) idSGFdecompressThread();
decompressThread->sgf = this;
decompressThread->StartWorkerThread( "SGF_DecompressThread", CORE_1B, THREAD_NORMAL );
// DG: change threadname from "SGF_DecompressThread" to "SGF_Decompress", because Linux
// has a 15 (+ \0) char limit for threadnames. also, "thread" in a threadname is redundant
decompressThread->StartWorkerThread( "SGF_Decompress", CORE_1B, THREAD_NORMAL );
// DG end
}
if( nativeFile != NULL && sgf_threads.GetInteger() >= 2 )
{

View file

@ -1107,7 +1107,13 @@ idJobThread::Start
void idJobThread::Start( core_t core, unsigned int threadNum )
{
this->threadNum = threadNum;
StartWorkerThread( va( "JobListProcessor_%d", threadNum ), core, THREAD_NORMAL, JOB_THREAD_STACK_SIZE );
// DG: change threadname from "JobListProcessor_%d" to "JLProc_%d", because Linux
// has a 15 (+ \0) char limit for threadnames.
// furthermore: va is not thread safe, use snPrintf instead
char name[16];
idStr::snPrintf( name, 16, "JLProc_%d", threadNum );
StartWorkerThread( name, core, THREAD_NORMAL, JOB_THREAD_STACK_SIZE );
// DG end
}
/*
@ -1493,4 +1499,4 @@ void idParallelJobManagerLocal::Submit( idParallelJobList_Threads* jobList, int
threads[i].AddJobList( jobList );
threads[i].SignalWork();
}
}
}

View file

@ -93,8 +93,6 @@ that a thread can wait on for it to be raised. It's used to indicate data is av
a thread has reached a specific point.
================================================
*/
// RB begin
#if defined(_WIN32)
class idSysSignal
{
public:
@ -132,36 +130,6 @@ private:
idSysSignal( const idSysSignal& s ) {}
void operator=( const idSysSignal& s ) {}
};
#else
class idSysSignal
{
public:
static const int WAIT_INFINITE = -1;
idSysSignal( bool manualReset = false );
~idSysSignal();
void Raise();
void Clear();
// Wait returns true if the object is in a signalled state and
// returns false if the wait timed out. Wait also clears the signalled
// state when the signalled state is reached within the time out period.
bool Wait( int timeout = WAIT_INFINITE );
private:
pthread_mutex_t mutex;
pthread_cond_t cond;
bool signaled;
int signalCounter;
bool waiting;
bool manualReset;
idSysSignal( const idSysSignal& s ) {}
void operator=( const idSysSignal& s ) {}
};
#endif
/*
================================================

View file

@ -3,7 +3,8 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2012 Robert Beckebans
Copyright (C) 2012-2013 Robert Beckebans
Copyright (C) 2013 Daniel Gibson
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -29,11 +30,63 @@ If you have questions concerning this license or the applicable additional terms
#pragma hdrstop
#include "../../precompiled.h"
#ifdef __FreeBSD__
#include <pthread_ng.h> // for pthread_set_name_np
#endif
// DG: Note: On Linux you need at least (e)glibc 2.12 to be able to set the threadname
//#define DEBUG_THREADS
typedef void* ( *pthread_function_t )( void* );
/*
========================
Sys_SetThreadName
caedes: This should be seen as a helper-function for Sys_CreateThread() only.
(re)setting the name of a running thread seems like a bad idea and
currently (fresh d3 bfg source) isn't done anyway.
Furthermore SDL doesn't support it
========================
*/
#ifdef DEBUG_THREADS
static int Sys_SetThreadName( pthread_t handle, const char* name )
{
int ret = 0;
#ifdef __linux__
// NOTE: linux only supports threadnames up to 16chars *including* terminating NULL
// http://man7.org/linux/man-pages/man3/pthread_setname_np.3.html
// on my machine a longer name (eg "JobListProcessor_0") caused an ENOENT error (instead of ERANGE)
assert( strlen( name ) < 16 );
ret = pthread_setname_np( handle, name );
if( ret != 0 )
idLib::common->Printf( "Setting threadname \"%s\" failed, reason: %s (%i)\n", name, strerror( errno ), errno );
// pthread_getname_np(pthread_t, char*, size_t)
#elif defined(__FreeBSD__)
// according to http://www.freebsd.org/cgi/man.cgi?query=pthread_set_name_np&sektion=3
// the interface is void pthread_set_name_np(pthread_t tid, const char *name);
pthread_set_name_np( handle, name ); // doesn't return anything
// seems like there is no get_name equivalent
#endif
/* TODO: OSX:
// according to http://stackoverflow.com/a/7989973
// this needs to be called in the thread to be named!
ret = pthread_setname_np(name);
// int pthread_getname_np(pthread_t, char*, size_t);
// so we'd have to wrap the xthread_t function in Sys_CreateThread and set the name in the wrapping function...
*/
return ret;
}
// TODO: Sys_GetThreadName() ?
#endif // DEBUG_THREADS
/*
========================
Sys_Createthread
@ -41,8 +94,6 @@ Sys_Createthread
*/
uintptr_t Sys_CreateThread( xthread_t function, void* parms, xthreadPriority priority, const char* name, core_t core, int stackSize, bool suspended )
{
//Sys_EnterCriticalSection();
pthread_attr_t attr;
pthread_attr_init( &attr );
@ -58,37 +109,85 @@ uintptr_t Sys_CreateThread( xthread_t function, void* parms, xthreadPriority pri
idLib::common->FatalError( "ERROR: pthread_create %s failed\n", name );
return ( uintptr_t )0;
}
pthread_attr_destroy( &attr );
// RB: TODO pthread_setname_np is different on Linux, MacOSX and other systems
#if defined(DEBUG_THREADS)
if( pthread_setname_np( handle, name ) != 0 )
if( Sys_SetThreadName( handle, name ) != 0 )
{
idLib::common->FatalError( "ERROR: pthread_setname_np %s failed\n", name );
idLib::common->Warning( "Warning: pthread_setname_np %s failed\n", name );
return ( uintptr_t )0;
}
#endif
/*
TODO RB: support thread priorities?
pthread_attr_destroy( &attr );
#if 0
// RB: realtime policies require root privileges
// all Linux threads have one of the following scheduling policies:
// SCHED_OTHER or SCHED_NORMAL: the default policy, priority: [-20..0..19], default 0
// SCHED_FIFO: first in/first out realtime policy
// SCHED_RR: round-robin realtime policy
// SCHED_BATCH: similar to SCHED_OTHER, but with a throughput orientation
// SCHED_IDLE: lower priority than SCHED_OTHER
int schedulePolicy = SCHED_OTHER;
struct sched_param scheduleParam;
int error = pthread_getschedparam( handle, &schedulePolicy, &scheduleParam );
if( error != 0 )
{
idLib::common->FatalError( "ERROR: pthread_getschedparam %s failed: %s\n", name, strerror( error ) );
return ( uintptr_t )0;
}
schedulePolicy = SCHED_FIFO;
int minPriority = sched_get_priority_min( schedulePolicy );
int maxPriority = sched_get_priority_max( schedulePolicy );
if( priority == THREAD_HIGHEST )
{
SetThreadPriority( ( HANDLE )handle, THREAD_PRIORITY_HIGHEST ); // we better sleep enough to do this
// we better sleep enough to do this
scheduleParam.__sched_priority = maxPriority;
}
else if( priority == THREAD_ABOVE_NORMAL )
{
SetThreadPriority( ( HANDLE )handle, THREAD_PRIORITY_ABOVE_NORMAL );
scheduleParam.__sched_priority = Lerp( minPriority, maxPriority, 0.75f );
}
else if( priority == THREAD_NORMAL )
{
scheduleParam.__sched_priority = Lerp( minPriority, maxPriority, 0.5f );
}
else if( priority == THREAD_BELOW_NORMAL )
{
SetThreadPriority( ( HANDLE )handle, THREAD_PRIORITY_BELOW_NORMAL );
scheduleParam.__sched_priority = Lerp( minPriority, maxPriority, 0.25f );
}
else if( priority == THREAD_LOWEST )
{
SetThreadPriority( ( HANDLE )handle, THREAD_PRIORITY_LOWEST );
scheduleParam.__sched_priority = minPriority;
}
*/
// set new priority
error = pthread_setschedparam( handle, schedulePolicy, &scheduleParam );
if( error != 0 )
{
idLib::common->FatalError( "ERROR: pthread_setschedparam( name = %s, policy = %i, priority = %i ) failed: %s\n", name, schedulePolicy, scheduleParam.__sched_priority, strerror( error ) );
return ( uintptr_t )0;
}
pthread_getschedparam( handle, &schedulePolicy, &scheduleParam );
if( error != 0 )
{
idLib::common->FatalError( "ERROR: pthread_getschedparam %s failed: %s\n", name, strerror( error ) );
return ( uintptr_t )0;
}
#endif
// Under Linux, we don't set the thread affinity and let the OS deal with scheduling
@ -104,7 +203,7 @@ Sys_GetCurrentThreadID
uintptr_t Sys_GetCurrentThreadID()
{
/*
* This cast is save because pthread_self()
* This cast is safe because pthread_self()
* returns a pointer and uintptr_t is
* designed to hold a pointer. The compiler
* is just too stupid to know. :)
@ -163,8 +262,23 @@ void Sys_Yield()
================================================================================================
*/
idSysSignal::idSysSignal( bool manualReset )
/*
========================
Sys_SignalCreate
========================
*/
void Sys_SignalCreate( signalHandle_t& handle, bool manualReset )
{
// handle = CreateEvent( NULL, manualReset, FALSE, NULL );
handle.manualReset = manualReset;
// if this is true, the signal is only set to nonsignaled when Clear() is called,
// else it's "auto-reset" and the state is set to !signaled after a single waiting
// thread has been released
// the inital state is always "not signaled"
handle.signaled = false;
handle.waiting = 0;
#if 0
pthread_mutexattr_t attr;
@ -174,121 +288,138 @@ idSysSignal::idSysSignal( bool manualReset )
pthread_mutex_init( &mutex, &attr );
pthread_mutexattr_destroy( &attr );
#else
pthread_mutex_init( &mutex, NULL );
pthread_mutex_init( &handle.mutex, NULL );
#endif
pthread_cond_init( &cond, NULL );
pthread_cond_init( &handle.cond, NULL );
signaled = false;
signalCounter = 0;
waiting = false;
this->manualReset = manualReset;
}
idSysSignal::~idSysSignal()
/*
========================
Sys_SignalDestroy
========================
*/
void Sys_SignalDestroy( signalHandle_t& handle )
{
pthread_cond_destroy( &cond );
pthread_mutex_destroy( &mutex );
// CloseHandle( handle );
handle.signaled = false;
handle.waiting = 0;
pthread_mutex_destroy( &handle.mutex );
pthread_cond_destroy( &handle.cond );
}
void idSysSignal::Raise()
/*
========================
Sys_SignalRaise
========================
*/
void Sys_SignalRaise( signalHandle_t& handle )
{
pthread_mutex_lock( &mutex );
// SetEvent( handle );
pthread_mutex_lock( &handle.mutex );
//if( waiting )
if( handle.manualReset )
{
//pthread_cond_signal( &cond );
//pthread_cond_broadcast( &cond );
}
//else
if( !signaled )
{
// emulate Windows behaviour: if no thread is waiting, leave the signal on so next wait keeps going
signaled = true;
signalCounter++;
pthread_cond_signal( &cond );
//pthread_cond_broadcast( &cond );
}
pthread_mutex_unlock( &mutex );
}
void idSysSignal::Clear()
{
pthread_mutex_lock( &mutex );
signaled = false;
pthread_mutex_unlock( &mutex );
}
// Wait returns true if the object is in a signalled state and
// returns false if the wait timed out. Wait also clears the signalled
// state when the signalled state is reached within the time out period.
bool idSysSignal::Wait( int timeout )
{
pthread_mutex_lock( &mutex );
int result = 0;
#if 1
assert( !waiting ); // WaitForEvent from multiple threads? that wouldn't be good
if( signaled )
{
if( !manualReset )
{
// emulate Windows behaviour: signal has been raised already. clear and keep going
signaled = false;
result = 0;
}
// signaled until reset
handle.signaled = true;
// wake *all* threads waiting on this cond
pthread_cond_broadcast( &handle.cond );
}
else
#endif
{
#if 0
int signalValue = signalCounter;
//while( !signaled && signalValue == signalCounter )
#endif
// automode: signaled until first thread is released
if( handle.waiting > 0 )
{
waiting = true;
if( timeout == WAIT_INFINITE )
{
result = pthread_cond_wait( &cond, &mutex );
assert( result == 0 );
}
else
{
timespec ts;
clock_gettime( CLOCK_REALTIME, &ts );
// DG: handle timeouts > 1s better
int64 t = timeout * 1000000;
ts.tv_nsec += t % 1000000000;
ts.tv_sec += t / 1000000000;
// DG end
result = pthread_cond_timedwait( &cond, &mutex, &ts );
assert( result == 0 || ( timeout != idSysSignal::WAIT_INFINITE && result == ETIMEDOUT ) );
}
waiting = false;
// there are waiting threads => release one
pthread_cond_signal( &handle.cond );
}
if( !manualReset )
else
{
signaled = false;
// no waiting threads, save signal
handle.signaled = true;
// while the MSDN documentation is a bit unspecific about what happens
// when SetEvent() is called n times without a wait inbetween
// (will only one wait be successful afterwards or n waits?)
// it seems like the signaled state is a flag, not a counter.
// http://stackoverflow.com/a/13703585 claims the same.
}
}
pthread_mutex_unlock( &mutex );
return ( result == 0 );
pthread_mutex_unlock( &handle.mutex );
}
/*
========================
Sys_SignalClear
========================
*/
void Sys_SignalClear( signalHandle_t& handle )
{
// ResetEvent( handle );
pthread_mutex_lock( &handle.mutex );
// TODO: probably signaled could be atomically changed?
handle.signaled = false;
pthread_mutex_unlock( &handle.mutex );
}
/*
========================
Sys_SignalWait
========================
*/
bool Sys_SignalWait( signalHandle_t& handle, int timeout )
{
//DWORD result = WaitForSingleObject( handle, timeout == idSysSignal::WAIT_INFINITE ? INFINITE : timeout );
//assert( result == WAIT_OBJECT_0 || ( timeout != idSysSignal::WAIT_INFINITE && result == WAIT_TIMEOUT ) );
//return ( result == WAIT_OBJECT_0 );
int status;
pthread_mutex_lock( &handle.mutex );
if( handle.signaled ) // there is a signal that hasn't been used yet
{
if( ! handle.manualReset ) // for auto-mode only one thread may be released - this one.
handle.signaled = false;
status = 0; // success!
}
else // we'll have to wait for a signal
{
++handle.waiting;
if( timeout == idSysSignal::WAIT_INFINITE )
{
status = pthread_cond_wait( &handle.cond, &handle.mutex );
}
else
{
timespec ts;
clock_gettime( CLOCK_REALTIME, &ts );
// DG: handle timeouts > 1s better
ts.tv_nsec += ( timeout % 1000 ) * 1000000; // millisec to nanosec
ts.tv_sec += timeout / 1000;
if( ts.tv_nsec >= 1000000000 ) // nanoseconds are more than one second
{
ts.tv_nsec -= 1000000000; // remove one second in nanoseconds
ts.tv_sec += 1; // add one second to seconds
}
// DG end
status = pthread_cond_timedwait( &handle.cond, &handle.mutex, &ts );
}
--handle.waiting;
}
pthread_mutex_unlock( &handle.mutex );
assert( status == 0 || ( timeout != idSysSignal::WAIT_INFINITE && status == ETIMEDOUT ) );
return ( status == 0 );
}
/*
================================================================================================

View file

@ -45,8 +45,19 @@ typedef CRITICAL_SECTION mutexHandle_t;
typedef HANDLE signalHandle_t;
typedef LONG interlockedInt_t;
#else
struct signalHandle_t
{
// DG: all this stuff is needed to emulate Window's Event API
// (CreateEvent(), SetEvent(), WaitForSingleObject(), ...)
pthread_cond_t cond;
pthread_mutex_t mutex;
int waiting; // number of threads waiting for a signal
bool manualReset;
bool signaled; // is it signaled right now?
};
typedef pthread_mutex_t mutexHandle_t;
typedef pthread_cond_t signalHandle_t;
typedef int interlockedInt_t;
#endif
// RB end
@ -195,15 +206,11 @@ uintptr_t Sys_CreateThread( xthread_t function, void* parms, xthreadPriority p
void Sys_DestroyThread( uintptr_t threadHandle );
void Sys_SetCurrentThreadName( const char* name );
// use alternative pthread implementation in idSysSignal
#if defined(_WIN32)
void Sys_SignalCreate( signalHandle_t& handle, bool manualReset );
void Sys_SignalDestroy( signalHandle_t& handle );
void Sys_SignalRaise( signalHandle_t& handle );
void Sys_SignalClear( signalHandle_t& handle );
bool Sys_SignalWait( signalHandle_t& handle, int timeout );
#endif
// RB end
void Sys_MutexCreate( mutexHandle_t& handle );
void Sys_MutexDestroy( mutexHandle_t& handle );

View file

@ -91,8 +91,9 @@ void idAutoRender::StartBackgroundAutoSwaps( autoRenderIconType_t iconType )
// it is getting purged before our our first frame has been rendered.
globalImages->UnbindAll();
StartThread( "BackgroundAutoSwaps", CORE_0B, THREAD_NORMAL, AUTO_RENDER_STACK_SIZE );
// DG: set name to "BGAutoSwaps" because Linux has a 16char (incl. \0) namelimit for threads
StartThread( "BGAutoSwaps", CORE_0B, THREAD_NORMAL, AUTO_RENDER_STACK_SIZE );
// DG end
}
/*
@ -300,4 +301,4 @@ void idAutoRender::RenderLoadingIcon( float fracX, float fracY, float size, floa
renderProgManager.BindShader_TextureVertexColor();
RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );
}
}

View file

@ -313,99 +313,6 @@ void idRenderProgManager::LoadFragmentShader( int index )
fragmentShaders[index].progId = ( GLuint ) LoadGLSLShader( GL_FRAGMENT_SHADER, fragmentShaders[index].name, fragmentShaders[index].uniforms );
}
/*
================================================================================================
idRenderProgManager::LoadShader
================================================================================================
*/
GLuint idRenderProgManager::LoadShader( GLenum target, const char* name, const char* startToken )
{
idStr fullPath = "renderprogs\\gl\\";
fullPath += name;
common->Printf( "%s", fullPath.c_str() );
char* fileBuffer = NULL;
fileSystem->ReadFile( fullPath.c_str(), ( void** )&fileBuffer, NULL );
if( fileBuffer == NULL )
{
common->Printf( ": File not found\n" );
return INVALID_PROGID;
}
if( !R_IsInitialized() )
{
common->Printf( ": Renderer not initialized\n" );
fileSystem->FreeFile( fileBuffer );
return INVALID_PROGID;
}
// vertex and fragment shaders are both be present in a single file, so
// scan for the proper header to be the start point, and stamp a 0 in after the end
char* start = strstr( ( char* )fileBuffer, startToken );
if( start == NULL )
{
common->Printf( ": %s not found\n", startToken );
fileSystem->FreeFile( fileBuffer );
return INVALID_PROGID;
}
char* end = strstr( start, "END" );
if( end == NULL )
{
common->Printf( ": END not found for %s\n", startToken );
fileSystem->FreeFile( fileBuffer );
return INVALID_PROGID;
}
end[3] = 0;
idStr program = start;
program.Replace( "vertex.normal", "vertex.attrib[11]" );
program.Replace( "vertex.texcoord[0]", "vertex.attrib[8]" );
program.Replace( "vertex.texcoord", "vertex.attrib[8]" );
GLuint progId;
qglGenProgramsARB( 1, &progId );
qglBindProgramARB( target, progId );
qglGetError();
qglProgramStringARB( target, GL_PROGRAM_FORMAT_ASCII_ARB, program.Length(), program.c_str() );
GLenum err = qglGetError();
GLint ofs = -1;
qglGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &ofs );
if( ( err == GL_INVALID_OPERATION ) || ( ofs != -1 ) )
{
if( err == GL_INVALID_OPERATION )
{
const GLubyte* str = qglGetString( GL_PROGRAM_ERROR_STRING_ARB );
common->Printf( "\nGL_PROGRAM_ERROR_STRING_ARB: %s\n", str );
}
else
{
common->Printf( "\nUNKNOWN ERROR\n" );
}
if( ofs < 0 )
{
common->Printf( "GL_PROGRAM_ERROR_POSITION_ARB < 0\n" );
}
else if( ofs >= program.Length() )
{
common->Printf( "error at end of shader\n" );
}
else
{
common->Printf( "error at %i:\n%s", ofs, program.c_str() + ofs );
}
qglDeleteProgramsARB( 1, &progId );
fileSystem->FreeFile( fileBuffer );
return INVALID_PROGID;
}
common->Printf( "\n" );
fileSystem->FreeFile( fileBuffer );
return progId;
}
/*
================================================================================================
idRenderProgManager::BindShader

View file

@ -409,7 +409,6 @@ protected:
BindShader( builtinShaders[i], builtinShaders[i] );
}
GLuint LoadShader( GLenum target, const char* name, const char* startToken );
bool CompileGLSL( GLenum target, const char* name );
GLuint LoadGLSLShader( GLenum target, const char* name, idList<int>& uniforms );
void LoadGLSLProgram( const int programIndex, const int vertexShaderIndex, const int fragmentShaderIndex );

View file

@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2013 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -181,9 +182,11 @@ void RB_DrawElementsWithCounters( const drawSurf_t* surf )
// DG: this happens all the time in the erebus1 map with blendlight.vfp,
// so don't call assert (through verify) here until it's fixed (if fixable)
// else the game crashes on linux when using debug builds
// FIXME: fix this properly if possible?
// RB: yes but it would require an additional blend light skinned shader
//if( !verify( renderProgManager.ShaderUsesJoints() ) )
if( ! renderProgManager.ShaderUsesJoints() )
if( !renderProgManager.ShaderUsesJoints() )
// DG end
{
return;
@ -2271,7 +2274,10 @@ static int RB_DrawShaderPasses( const drawSurf_t* const* const drawSurfs, const
GL_State( stageGLState );
renderProgManager.BindShader( newStage->glslProgram, newStage->glslProgram );
// RB: CRITICAL BUGFIX: changed newStage->glslProgram to vertexProgram and fragmentProgram
// otherwise it will result in an out of bounds crash in RB_DrawElementsWithCounters
renderProgManager.BindShader( newStage->vertexProgram, newStage->fragmentProgram );
// RB end
for( int j = 0; j < newStage->numVertexParms; j++ )
{

View file

@ -56,6 +56,13 @@ public:
alSourcef( openalSource, AL_GAIN, ( gain ) < ( 1.0f ) ? ( gain ) : ( 1.0f ) );
}
void SetPitch( float p )
{
idSoundVoice_Base::SetPitch( p );
alSourcef( openalSource, AL_PITCH, p );
}
void Create( const idSoundSample* leadinSample, const idSoundSample* loopingSample );
// Start playing at a particular point in the buffer. Does an Update() too

View file

@ -54,16 +54,18 @@ public:
{
gain = g;
}
virtual void SetPitch( float p )
{
pitch = p;
}
// RB end
void SetCenterChannel( float c )
{
centerChannel = c;
}
void SetPitch( float p )
{
pitch = p;
}
void SetInnerRadius( float r )
{
innerRadius = r;

View file

@ -26,12 +26,19 @@ If you have questions concerning this license or the applicable additional terms
===========================================================================
*/
#include <SDL_cpuinfo.h>
#pragma hdrstop
#include "../../idlib/precompiled.h"
//#include "win_local.h"
// DG: SDL_*.h somehow needs the following functions, so #undef those silly
// "don't use" #defines from Str.h
#undef strcasecmp
#undef strncmp
#undef vsnprintf
// DG end
#include <SDL_cpuinfo.h>
#pragma warning(disable:4740) // warning C4740: flow in or out of inline asm code suppresses global optimization
#pragma warning(disable:4731) // warning C4731: 'XXX' : frame pointer register 'ebx' modified by inline assembly code

View file

@ -31,6 +31,13 @@ If you have questions concerning this license or the applicable additional terms
#include "../../idlib/precompiled.h"
// DG: SDL.h somehow needs the following functions, so #undef those silly
// "don't use" #defines from Str.h
#undef strncmp
#undef strcasecmp
#undef vsnprintf
// DG end
#include <SDL.h>
#include "renderer/tr_local.h"
@ -72,7 +79,7 @@ const char* kbdNames[] =
"english", "french", "german", "italian", "spanish", "turkish", "norwegian", NULL
};
idCVar in_kbd( "in_kbd", "english", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT, "keyboard layout", kbdNames, idCmdSystem::ArgCompletion_String<kbdNames> );
idCVar in_keyboard( "in_keyboard", "english", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT, "keyboard layout", kbdNames, idCmdSystem::ArgCompletion_String<kbdNames> );
struct kbd_poll_t
{
@ -552,7 +559,7 @@ void Sys_InitInput()
SDL_EnableKeyRepeat( SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL );
#endif
in_kbd.SetModified();
in_keyboard.SetModified();
}
/*
@ -587,9 +594,9 @@ unsigned char Sys_GetConsoleKey( bool shifted )
{
static unsigned char keys[2] = { '`', '~' };
if( in_kbd.IsModified() )
if( in_keyboard.IsModified() )
{
idStr lang = in_kbd.GetString();
idStr lang = in_keyboard.GetString();
if( lang.Length() )
{
@ -625,7 +632,7 @@ unsigned char Sys_GetConsoleKey( bool shifted )
}
}
in_kbd.ClearModified();
in_keyboard.ClearModified();
}
return shifted ? keys[1] : keys[0];

View file

@ -29,11 +29,18 @@ If you have questions concerning this license or the applicable additional terms
===========================================================================
*/
#include "../../idlib/precompiled.h"
// DG: SDL.h somehow needs the following functions, so #undef those silly
// "don't use" #defines from Str.h
#undef strncmp
#undef strcasecmp
#undef vsnprintf
// DG end
#include <SDL.h>
#include <SDL_syswm.h>
#include "../../idlib/precompiled.h"
#include "renderer/tr_local.h"
#include "sdl_local.h"