FlushGraphics now tracks and wakes each thread individually, lessening
the stuttering when multiple threads are performing Flush operations. Also, a number of comments have been reworked for accuracy. git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@527 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
Changes towards version 0.2:
|
Changes towards version 0.2:
|
||||||
|
- FlushGraphics now waits and notifies on a per-thread level
|
||||||
- No longer using SHGetFolderPath on Windows - SvdB
|
- No longer using SHGetFolderPath on Windows - SvdB
|
||||||
- Key repeat is now enabled when typing text, from slayne
|
- Key repeat is now enabled when typing text, from slayne
|
||||||
- Capital letter bug in new input code fixed, from slayne
|
- Capital letter bug in new input code fixed, from slayne
|
||||||
|
|||||||
@@ -78,10 +78,6 @@ Implementation bugs (low priority):
|
|||||||
- 3D planet view when entering orbit is now done, but there's some things
|
- 3D planet view when entering orbit is now done, but there's some things
|
||||||
which could make it look nicer, like better slave shield and removing
|
which could make it look nicer, like better slave shield and removing
|
||||||
occasional pops/discontinuities
|
occasional pops/discontinuities
|
||||||
- Rotation and zooming isn't now as smooth as before after condition
|
|
||||||
variable DCQ patch
|
|
||||||
- This is because of the fact that all FlushGraphics routines wait on
|
|
||||||
one lone condition variable -- we need one per thread, effectively.
|
|
||||||
- Transitions (crossfades) aren't perhaps correctly done always, syncing
|
- Transitions (crossfades) aren't perhaps correctly done always, syncing
|
||||||
might be wrong etc.
|
might be wrong etc.
|
||||||
- Condition variable DCQ patch should have fixed this. Confirm?
|
- Condition variable DCQ patch should have fixed this. Confirm?
|
||||||
|
|||||||
@@ -651,6 +651,10 @@ SOURCE=..\sc2code\libs\threads\thrcommon.c
|
|||||||
|
|
||||||
SOURCE=..\sc2code\libs\threads\thrcommon.h
|
SOURCE=..\sc2code\libs\threads\thrcommon.h
|
||||||
# End Source File
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\sc2code\libs\threads\condbank.c
|
||||||
|
# End Source File
|
||||||
# End Group
|
# End Group
|
||||||
# Begin Group "time"
|
# Begin Group "time"
|
||||||
|
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ typedef struct tfb_drawcommand
|
|||||||
BOOLEAN UsePalette;
|
BOOLEAN UsePalette;
|
||||||
int BlendNumerator;
|
int BlendNumerator;
|
||||||
int BlendDenominator;
|
int BlendDenominator;
|
||||||
|
DWORD thread;
|
||||||
} TFB_DrawCommand;
|
} TFB_DrawCommand;
|
||||||
|
|
||||||
// Queue Stuff
|
// Queue Stuff
|
||||||
|
|||||||
@@ -54,12 +54,10 @@ UninitGraphics () // Also probably empty
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Batch/UnbatchGraphics: These routines appear to be used to ensure
|
/* Batching and Unbatching functions. A "Batch" is a collection of
|
||||||
// that the screen doesn't update with a half-drawn region. This can
|
DrawCommands that will never be flipped to the screen half-rendered.
|
||||||
// be implemented in all sorts of ways - I've chosen to fold it into
|
BatchGraphics and UnbatchGraphics function vaguely like a non-blocking
|
||||||
// our DrawCommandQueue, for the most part. These just forward to
|
recursive lock to do this respect. */
|
||||||
// the TFB_ versions in dcqueue.c. They may also make continuity_break
|
|
||||||
// redundant, but I haven't tested that yet. --Michael
|
|
||||||
void
|
void
|
||||||
BatchGraphics (void)
|
BatchGraphics (void)
|
||||||
{
|
{
|
||||||
@@ -72,6 +70,9 @@ UnbatchGraphics (void)
|
|||||||
TFB_UnbatchGraphics ();
|
TFB_UnbatchGraphics ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sleeps this thread until all Draw Commands queued by that thread have
|
||||||
|
been processed. */
|
||||||
|
|
||||||
void
|
void
|
||||||
FlushGraphics (void)
|
FlushGraphics (void)
|
||||||
{
|
{
|
||||||
@@ -80,7 +81,7 @@ FlushGraphics (void)
|
|||||||
DrawCommand.Type = TFB_DRAWCOMMANDTYPE_FLUSHGRAPHICS;
|
DrawCommand.Type = TFB_DRAWCOMMANDTYPE_FLUSHGRAPHICS;
|
||||||
DrawCommand.image = 0;
|
DrawCommand.image = 0;
|
||||||
TFB_EnqueueDrawCommand(&DrawCommand);
|
TFB_EnqueueDrawCommand(&DrawCommand);
|
||||||
WaitCondVar (RenderingCond);
|
WaitForSignal ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -224,6 +224,7 @@ TFB_EnqueueDrawCommand (TFB_DrawCommand* DrawCommand)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DrawCommand->thread = CurrentThreadID ();
|
||||||
if (DrawCommand->Type <= TFB_DRAWCOMMANDTYPE_COPYFROMOTHERBUFFER
|
if (DrawCommand->Type <= TFB_DRAWCOMMANDTYPE_COPYFROMOTHERBUFFER
|
||||||
&& TYPE_GET (_CurFramePtr->TypeIndexAndFlags) == SCREEN_DRAWABLE)
|
&& TYPE_GET (_CurFramePtr->TypeIndexAndFlags) == SCREEN_DRAWABLE)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -737,7 +737,8 @@ TFB_FlushGraphics () // Only call from main thread!!
|
|||||||
break;
|
break;
|
||||||
case TFB_DRAWCOMMANDTYPE_FLUSHGRAPHICS:
|
case TFB_DRAWCOMMANDTYPE_FLUSHGRAPHICS:
|
||||||
// done = TRUE;
|
// done = TRUE;
|
||||||
TFB_SwapBuffers ();
|
// TFB_SwapBuffers ();
|
||||||
|
SignalThread (DC.thread);
|
||||||
break;
|
break;
|
||||||
case TFB_DRAWCOMMANDTYPE_SKIPGRAPHICS:
|
case TFB_DRAWCOMMANDTYPE_SKIPGRAPHICS:
|
||||||
TFB_DrawCommandQueue_Clear ();
|
TFB_DrawCommandQueue_Clear ();
|
||||||
|
|||||||
@@ -65,7 +65,8 @@
|
|||||||
|
|
||||||
extern void InitThreadSystem (void);
|
extern void InitThreadSystem (void);
|
||||||
extern void UnInitThreadSystem (void);
|
extern void UnInitThreadSystem (void);
|
||||||
|
extern void init_cond_bank (void);
|
||||||
|
extern void uninit_cond_bank (void);
|
||||||
|
|
||||||
typedef int (*ThreadFunction) (void *);
|
typedef int (*ThreadFunction) (void *);
|
||||||
|
|
||||||
@@ -130,5 +131,10 @@ extern void WaitCondVar (CondVar);
|
|||||||
extern void SignalCondVar (CondVar);
|
extern void SignalCondVar (CondVar);
|
||||||
extern void BroadcastCondVar (CondVar);
|
extern void BroadcastCondVar (CondVar);
|
||||||
|
|
||||||
|
extern DWORD CurrentThreadID (void);
|
||||||
|
|
||||||
|
extern void WaitForSignal (void);
|
||||||
|
extern void SignalThread (DWORD);
|
||||||
|
|
||||||
#endif /* _THREADLIB_H */
|
#endif /* _THREADLIB_H */
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
uqm_SUBDIRS="sdl"
|
uqm_SUBDIRS="sdl"
|
||||||
uqm_CFILES="thrcommon.c"
|
uqm_CFILES="condbank.c thrcommon.c"
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
//Copyright Paul Reiche, Fred Ford. 1992-2002
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This defines the Condition Variable Bank. Individual threads may
|
||||||
|
sleep until they are signaled by their Thread ID. If the Condition
|
||||||
|
Variable Bank is exhausted (unlikely!) it will wait on the DCQ's
|
||||||
|
condition variable. This may produce stuttering. */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "starcon.h"
|
||||||
|
#include "libs/threadlib.h"
|
||||||
|
|
||||||
|
/* The Condition Variable Bank. */
|
||||||
|
|
||||||
|
#define CONDVAR_BANK_SIZE 10
|
||||||
|
|
||||||
|
static Semaphore bank_sem;
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
CondVar var;
|
||||||
|
DWORD id;
|
||||||
|
int used;
|
||||||
|
} bank[CONDVAR_BANK_SIZE];
|
||||||
|
|
||||||
|
void
|
||||||
|
init_cond_bank ()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
bank_sem = CreateSemaphore (1, "CondVar Bank Semaphore");
|
||||||
|
for (i = 0; i < CONDVAR_BANK_SIZE; i++)
|
||||||
|
{
|
||||||
|
bank[i].var = CreateCondVar ();
|
||||||
|
bank[i].id = bank[i].used = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
uninit_cond_bank ()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < CONDVAR_BANK_SIZE; i++)
|
||||||
|
{
|
||||||
|
DestroyCondVar (bank[i].var);
|
||||||
|
}
|
||||||
|
DestroySemaphore (bank_sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WaitForSignal ()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int index = -1;
|
||||||
|
DWORD me = CurrentThreadID ();
|
||||||
|
SetSemaphore (bank_sem);
|
||||||
|
for (i = 0; i < CONDVAR_BANK_SIZE; i++)
|
||||||
|
{
|
||||||
|
if (!bank[i].used)
|
||||||
|
{
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index == -1)
|
||||||
|
{
|
||||||
|
/* The bank is full! */
|
||||||
|
fprintf(stderr, "Condvar bank is full, %ul is waiting on DCQ.", me);
|
||||||
|
ClearSemaphore (bank_sem);
|
||||||
|
WaitCondVar (RenderingCond);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bank[i].used = 1;
|
||||||
|
bank[i].id = me;
|
||||||
|
ClearSemaphore (bank_sem);
|
||||||
|
WaitCondVar (bank[i].var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SignalThread (DWORD id)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
SetSemaphore (bank_sem);
|
||||||
|
for (i = 0; i < CONDVAR_BANK_SIZE; i++)
|
||||||
|
{
|
||||||
|
if (bank[i].used && bank[i].id == id)
|
||||||
|
{
|
||||||
|
bank[i].id = bank[i].used = 0;
|
||||||
|
SignalCondVar (bank[i].var);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ClearSemaphore (bank_sem);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -94,6 +94,8 @@ typedef SDL_cond *NativeCondVar;
|
|||||||
#define NativeBroadcastCondVar(condvar) \
|
#define NativeBroadcastCondVar(condvar) \
|
||||||
SDL_CondBroadcast ((condvar))
|
SDL_CondBroadcast ((condvar))
|
||||||
|
|
||||||
|
#define NativeCurrentThreadID() \
|
||||||
|
SDL_ThreadID ()
|
||||||
|
|
||||||
#endif /* _SDLTHREAD_H */
|
#endif /* _SDLTHREAD_H */
|
||||||
|
|
||||||
|
|||||||
@@ -89,11 +89,13 @@ InitThreadSystem (void)
|
|||||||
signal(SIGUSR1, SigUSR1Handler);
|
signal(SIGUSR1, SigUSR1Handler);
|
||||||
#endif
|
#endif
|
||||||
NativeInitThreadSystem ();
|
NativeInitThreadSystem ();
|
||||||
|
init_cond_bank ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
UnInitThreadSystem (void)
|
UnInitThreadSystem (void)
|
||||||
{
|
{
|
||||||
|
uninit_cond_bank ();
|
||||||
NativeUnInitThreadSystem ();
|
NativeUnInitThreadSystem ();
|
||||||
#ifdef PROFILE_THREADS
|
#ifdef PROFILE_THREADS
|
||||||
signal(SIGUSR1, SIG_DFL);
|
signal(SIGUSR1, SIG_DFL);
|
||||||
@@ -602,3 +604,8 @@ void BroadcastCondVar (CondVar cv)
|
|||||||
{
|
{
|
||||||
NativeBroadcastCondVar (cv);
|
NativeBroadcastCondVar (cv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DWORD CurrentThreadID ()
|
||||||
|
{
|
||||||
|
return (DWORD)NativeThreadID ();
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user