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:
mcmartin
2003-01-03 12:14:19 +00:00
parent af999b15ea
commit 578cf23ba3
12 changed files with 149 additions and 19 deletions
+1
View File
@@ -1,4 +1,5 @@
Changes towards version 0.2:
- FlushGraphics now waits and notifies on a per-thread level
- No longer using SHGetFolderPath on Windows - SvdB
- Key repeat is now enabled when typing text, from slayne
- Capital letter bug in new input code fixed, from slayne
-4
View File
@@ -78,10 +78,6 @@ Implementation bugs (low priority):
- 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
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
might be wrong etc.
- Condition variable DCQ patch should have fixed this. Confirm?
+4
View File
@@ -651,6 +651,10 @@ SOURCE=..\sc2code\libs\threads\thrcommon.c
SOURCE=..\sc2code\libs\threads\thrcommon.h
# End Source File
# Begin Source File
SOURCE=..\sc2code\libs\threads\condbank.c
# End Source File
# End Group
# Begin Group "time"
@@ -109,6 +109,7 @@ typedef struct tfb_drawcommand
BOOLEAN UsePalette;
int BlendNumerator;
int BlendDenominator;
DWORD thread;
} TFB_DrawCommand;
// Queue Stuff
@@ -54,12 +54,10 @@ UninitGraphics () // Also probably empty
}
// Batch/UnbatchGraphics: These routines appear to be used to ensure
// that the screen doesn't update with a half-drawn region. This can
// be implemented in all sorts of ways - I've chosen to fold it into
// our DrawCommandQueue, for the most part. These just forward to
// the TFB_ versions in dcqueue.c. They may also make continuity_break
// redundant, but I haven't tested that yet. --Michael
/* Batching and Unbatching functions. A "Batch" is a collection of
DrawCommands that will never be flipped to the screen half-rendered.
BatchGraphics and UnbatchGraphics function vaguely like a non-blocking
recursive lock to do this respect. */
void
BatchGraphics (void)
{
@@ -72,6 +70,9 @@ UnbatchGraphics (void)
TFB_UnbatchGraphics ();
}
/* Sleeps this thread until all Draw Commands queued by that thread have
been processed. */
void
FlushGraphics (void)
{
@@ -80,7 +81,7 @@ FlushGraphics (void)
DrawCommand.Type = TFB_DRAWCOMMANDTYPE_FLUSHGRAPHICS;
DrawCommand.image = 0;
TFB_EnqueueDrawCommand(&DrawCommand);
WaitCondVar (RenderingCond);
WaitForSignal ();
}
void
+2 -1
View File
@@ -223,7 +223,8 @@ TFB_EnqueueDrawCommand (TFB_DrawCommand* DrawCommand)
{
return;
}
DrawCommand->thread = CurrentThreadID ();
if (DrawCommand->Type <= TFB_DRAWCOMMANDTYPE_COPYFROMOTHERBUFFER
&& TYPE_GET (_CurFramePtr->TypeIndexAndFlags) == SCREEN_DRAWABLE)
{
@@ -737,7 +737,8 @@ TFB_FlushGraphics () // Only call from main thread!!
break;
case TFB_DRAWCOMMANDTYPE_FLUSHGRAPHICS:
// done = TRUE;
TFB_SwapBuffers ();
// TFB_SwapBuffers ();
SignalThread (DC.thread);
break;
case TFB_DRAWCOMMANDTYPE_SKIPGRAPHICS:
TFB_DrawCommandQueue_Clear ();
+7 -1
View File
@@ -65,7 +65,8 @@
extern void InitThreadSystem (void);
extern void UnInitThreadSystem (void);
extern void init_cond_bank (void);
extern void uninit_cond_bank (void);
typedef int (*ThreadFunction) (void *);
@@ -130,5 +131,10 @@ extern void WaitCondVar (CondVar);
extern void SignalCondVar (CondVar);
extern void BroadcastCondVar (CondVar);
extern DWORD CurrentThreadID (void);
extern void WaitForSignal (void);
extern void SignalThread (DWORD);
#endif /* _THREADLIB_H */
+1 -1
View File
@@ -1,2 +1,2 @@
uqm_SUBDIRS="sdl"
uqm_CFILES="thrcommon.c"
uqm_CFILES="condbank.c thrcommon.c"
+110
View File
@@ -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);
}
@@ -86,14 +86,16 @@ typedef SDL_cond *NativeCondVar;
#define NativeCreateCondVar() \
SDL_CreateCond ()
#define NativeDestroyCondVar(condvar) \
SDL_DestroyCond((condvar))
SDL_DestroyCond ((condvar))
#define NativeWaitCondVar(condvar) \
SDLWrapper_WaitCondVar((condvar))
SDLWrapper_WaitCondVar ((condvar))
#define NativeSignalCondVar(condvar) \
SDL_CondSignal((condvar))
SDL_CondSignal ((condvar))
#define NativeBroadcastCondVar(condvar) \
SDL_CondBroadcast((condvar))
SDL_CondBroadcast ((condvar))
#define NativeCurrentThreadID() \
SDL_ThreadID ()
#endif /* _SDLTHREAD_H */
+7
View File
@@ -89,11 +89,13 @@ InitThreadSystem (void)
signal(SIGUSR1, SigUSR1Handler);
#endif
NativeInitThreadSystem ();
init_cond_bank ();
}
void
UnInitThreadSystem (void)
{
uninit_cond_bank ();
NativeUnInitThreadSystem ();
#ifdef PROFILE_THREADS
signal(SIGUSR1, SIG_DFL);
@@ -602,3 +604,8 @@ void BroadcastCondVar (CondVar cv)
{
NativeBroadcastCondVar (cv);
}
DWORD CurrentThreadID ()
{
return (DWORD)NativeThreadID ();
}