From e5aa5677a4722e2a26ca37c388189c9cc980ce56 Mon Sep 17 00:00:00 2001 From: mcmartin Date: Sat, 18 Jan 2003 03:17:06 +0000 Subject: [PATCH] DCQ optimization (Phase 2 of 3) This has dropped the .bss segment of the final binary by nearly 16MB. git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@562 8092fc87-c524-0410-9efc-e669fe64eaf9 --- sc2/src/sc2code/libs/graphics/drawcmd.h | 8 +- sc2/src/sc2code/libs/graphics/gfx_common.c | 73 ++++++++++++++++- sc2/src/sc2code/libs/graphics/gfx_common.h | 4 + sc2/src/sc2code/libs/graphics/sdl/3do_blt.c | 35 ++++---- sc2/src/sc2code/libs/graphics/sdl/dcqueue.c | 10 +-- sc2/src/sc2code/libs/graphics/sdl/dcqueue.h | 32 +++++++- .../sc2code/libs/graphics/sdl/sdl_common.c | 79 +++++++++++++------ 7 files changed, 187 insertions(+), 54 deletions(-) diff --git a/sc2/src/sc2code/libs/graphics/drawcmd.h b/sc2/src/sc2code/libs/graphics/drawcmd.h index a0973a338..b009852de 100644 --- a/sc2/src/sc2code/libs/graphics/drawcmd.h +++ b/sc2/src/sc2code/libs/graphics/drawcmd.h @@ -24,6 +24,7 @@ enum TFB_DRAWCOMMANDTYPE_LINE, TFB_DRAWCOMMANDTYPE_RECTANGLE, TFB_DRAWCOMMANDTYPE_IMAGE, + TFB_DRAWCOMMANDTYPE_FILLEDIMAGE, TFB_DRAWCOMMANDTYPE_COPY, TFB_DRAWCOMMANDTYPE_COPYTOIMAGE, @@ -31,6 +32,7 @@ enum TFB_DRAWCOMMANDTYPE_SCISSORENABLE, TFB_DRAWCOMMANDTYPE_SCISSORDISABLE, + TFB_DRAWCOMMANDTYPE_SETPALETTE, TFB_DRAWCOMMANDTYPE_DELETEIMAGE, TFB_DRAWCOMMANDTYPE_SENDSIGNAL, }; @@ -46,14 +48,14 @@ typedef struct tfb_drawcommand int r; int g; int b; - TFB_Palette Palette[256]; - BOOLEAN UsePalette; - BOOLEAN UseScaling; + int index; int BlendNumerator; int BlendDenominator; DWORD thread; SCREEN srcBuffer; SCREEN destBuffer; + BOOLEAN UsePalette; + BOOLEAN UseScaling; } TFB_DrawCommand; diff --git a/sc2/src/sc2code/libs/graphics/gfx_common.c b/sc2/src/sc2code/libs/graphics/gfx_common.c index c0935ef20..d81752f21 100644 --- a/sc2/src/sc2code/libs/graphics/gfx_common.c +++ b/sc2/src/sc2code/libs/graphics/gfx_common.c @@ -100,6 +100,40 @@ TFB_Draw_Rect (PRECT rect, int r, int g, int b, SCREEN dest) TFB_EnqueueDrawCommand (&DC); } +void +TFB_Draw_SetPalette (int index, int r, int g, int b) +{ + TFB_DrawCommand DC; + + DC.Type = TFB_DRAWCOMMANDTYPE_SETPALETTE; + DC.r = r; + DC.g = g; + DC.b = b; + DC.index = index; + DC.image = 0; + DC.BlendNumerator = BlendNumerator; + DC.BlendDenominator = BlendDenominator; + + TFB_EnqueueDrawCommand (&DC); +} + +/* This value is protected by the DCQ's lock. */ +static int _localpal[256][3]; + +void +TFB_FlushPaletteCache () +{ + int i; + Lock_DCQ (-1); + for (i = 0; i < 256; i++) + { + _localpal[i][0] = -1; + _localpal[i][1] = -1; + _localpal[i][2] = -1; + } + Unlock_DCQ (); +} + void TFB_Draw_Image (TFB_ImageStruct *img, int x, int y, BOOLEAN scaled, TFB_Palette *palette, SCREEN dest) { @@ -113,15 +147,29 @@ TFB_Draw_Image (TFB_ImageStruct *img, int x, int y, BOOLEAN scaled, TFB_Palette if (palette != NULL) { - int i; + int i, changed; + Lock_DCQ(257); + changed = 0; for (i = 0; i < 256; i++) { - DC.Palette[i] = palette[i]; + if ((_localpal[i][0] != palette[i].r) || + (_localpal[i][1] != palette[i].g) || + (_localpal[i][2] != palette[i].b)) + { + changed++; + _localpal[i][0] = palette[i].r; + _localpal[i][1] = palette[i].g; + _localpal[i][2] = palette[i].b; + TFB_Draw_SetPalette (i, palette[i].r, palette[i].g, + palette[i].b); + } } + // if (changed) { fprintf (stderr, "Actually changing palette! "); } DC.UsePalette = TRUE; } else { + Lock_DCQ (1); DC.UsePalette = FALSE; } @@ -129,6 +177,27 @@ TFB_Draw_Image (TFB_ImageStruct *img, int x, int y, BOOLEAN scaled, TFB_Palette DC.BlendNumerator = BlendNumerator; DC.BlendDenominator = BlendDenominator; + TFB_EnqueueDrawCommand (&DC); + Unlock_DCQ (); +} + +void +TFB_Draw_FilledImage (TFB_ImageStruct *img, int x, int y, BOOLEAN scaled, int r, int g, int b, SCREEN dest) +{ + TFB_DrawCommand DC; + + DC.Type = TFB_DRAWCOMMANDTYPE_FILLEDIMAGE; + DC.image = img; + DC.x = x; + DC.y = y; + DC.UseScaling = scaled; + DC.r = r; + DC.g = g; + DC.b = b; + DC.destBuffer = dest; + DC.BlendNumerator = BlendNumerator; + DC.BlendDenominator = BlendDenominator; + TFB_EnqueueDrawCommand (&DC); } diff --git a/sc2/src/sc2code/libs/graphics/gfx_common.h b/sc2/src/sc2code/libs/graphics/gfx_common.h index 2cf3dfb8b..cb0020270 100644 --- a/sc2/src/sc2code/libs/graphics/gfx_common.h +++ b/sc2/src/sc2code/libs/graphics/gfx_common.h @@ -93,9 +93,13 @@ void TFB_Draw_Line (int x1, int y1, int x2, int y2, int r, int g, int b, SCREEN void TFB_Draw_Rect (PRECT rect, int r, int g, int b, SCREEN dest); void TFB_Draw_Image (TFB_ImageStruct *img, int x, int y, BOOLEAN scaled, TFB_Palette *palette, SCREEN dest); void TFB_Draw_Copy (PRECT r, SCREEN src, SCREEN dest); +void TFB_Draw_FilledImage (TFB_ImageStruct *img, int x, int y, BOOLEAN scaled, int r, int g, int b, SCREEN dest); void TFB_Draw_CopyToImage (TFB_ImageStruct *img, PRECT lpRect, SCREEN src); void TFB_Draw_DeleteImage (TFB_ImageStruct *img); void TFB_Draw_WaitForSignal (void); +void TFB_Draw_SetPalette (int index, int r, int g, int b); +void TFB_FlushPaletteCache (void); + void TFB_FlushGraphics (void); // Only call from main thread!! diff --git a/sc2/src/sc2code/libs/graphics/sdl/3do_blt.c b/sc2/src/sc2code/libs/graphics/sdl/3do_blt.c index c27ba67cc..f4362ff52 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/3do_blt.c +++ b/sc2/src/sc2code/libs/graphics/sdl/3do_blt.c @@ -44,12 +44,12 @@ blt (PRECT pClipRect, PRIMITIVEPTR PrimPtr) if (TYPE_GET (_CurFramePtr->TypeIndexAndFlags) == SCREEN_DRAWABLE) { int x, y; - BOOLEAN scaled, paletted; + BOOLEAN scaled, paletted, filled; TFB_Palette palette[256]; x = pClipRect->corner.x - GetFrameHotX (_CurFramePtr); y = pClipRect->corner.y - GetFrameHotY (_CurFramePtr); - scaled = FALSE; + scaled = filled = FALSE; if (gscale != 0 && gscale != 256) { @@ -118,7 +118,7 @@ blt (PRECT pClipRect, PRIMITIVEPTR PrimPtr) if (GetPrimType (PrimPtr) == STAMPFILL_PRIM) { - int i, r, g, b; + int r, g, b; DWORD c32k; c32k = GetPrimColor (PrimPtr) >> 8; // shift out color index @@ -126,14 +126,11 @@ blt (PRECT pClipRect, PRIMITIVEPTR PrimPtr) g = (c32k >> (5 - (8 - 5))) & 0xF8; b = (c32k << (8 - 5)) & 0xF8; - for (i = 0; i < 256; ++i) - { - palette[i].r = r; - palette[i].g = g; - palette[i].b = b; - } - - paletted = TRUE; + palette[0].r = r; + palette[0].g = g; + palette[0].b = b; + + filled = TRUE; } else { @@ -145,9 +142,19 @@ blt (PRECT pClipRect, PRIMITIVEPTR PrimPtr) } UnlockMutex (img->mutex); - TFB_Draw_Image ((TFB_ImageStruct *)img, x, y, scaled, - (paletted ? palette : NULL), - TFB_SCREEN_MAIN); + if (filled) + { + TFB_Draw_FilledImage ((TFB_ImageStruct *)img, x, y, + scaled, palette[0].r, + palette[0].g, palette[0].b, + TFB_SCREEN_MAIN); + } + else + { + TFB_Draw_Image ((TFB_ImageStruct *)img, x, y, scaled, + (paletted ? palette : NULL), + TFB_SCREEN_MAIN); + } } else { diff --git a/sc2/src/sc2code/libs/graphics/sdl/dcqueue.c b/sc2/src/sc2code/libs/graphics/sdl/dcqueue.c index c1ecc94c4..dd7f979de 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/dcqueue.c +++ b/sc2/src/sc2code/libs/graphics/sdl/dcqueue.c @@ -22,6 +22,7 @@ #include "libs/threadlib.h" #include "SDL_thread.h" #include "libs/graphics/drawcmd.h" +#include "libs/graphics/sdl/dcqueue.h" Semaphore DCQ_sem; @@ -29,15 +30,6 @@ Semaphore DCQ_sem; static int DCQ_locking_depth = 0; static Uint32 DCQ_locking_thread = 0; -// Maximum size of the DCQ. The larger the DCQ, the larger frameskips -// become tolerable before initiating livelock deterrence and game -// slowdown. Other constants for controlling the frameskip/slowdown -// balance may be found in sdl_common.c near TFB_FlushGraphics. -#ifdef DCQ_OF_DOOM -#define DCQ_MAX 512 -#else -#define DCQ_MAX 16384 -#endif TFB_DrawCommand DCQ[DCQ_MAX]; TFB_DrawCommandQueue DrawCommandQueue; diff --git a/sc2/src/sc2code/libs/graphics/sdl/dcqueue.h b/sc2/src/sc2code/libs/graphics/sdl/dcqueue.h index 4db475497..fc7278e0e 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/dcqueue.h +++ b/sc2/src/sc2code/libs/graphics/sdl/dcqueue.h @@ -19,5 +19,35 @@ #ifndef DCQUEUE_H #define DCQUEUE_H -/* This is all in drawcmd.h now. */ +// Maximum size of the DCQ. The larger the DCQ, the larger frameskips +// become tolerable before initiating livelock deterrence and game +// slowdown. Other constants for controlling the frameskip/slowdown +// balance may be found in sdl_common.c near TFB_FlushGraphics. + +// Livelock deterrance constants. Because the entire screen is rarely +// refreshed, we may not drop draw commands on the floor with abandon. +// Furthermore, if the main program is queuing commands at a speed +// comparable to our processing of the commands, we never finish and +// the game freezes. Thus, if the queue starts out larger than +// DCQ_FORCE_SLOWDOWN_SIZE, or DCQ_LIVELOCK_MAX commands find +// themselves being processed in one go, livelock deterrence is +// enabled, and TFB_FlushGraphics locks the DCQ until it has processed +// all entries. If batched but pending commands exceed DCQ_FORCE_BREAK_SIZE, +// a continuity break is performed. This will effectively slow down the +// game logic, a fate we seek to avoid - however, it seems to be unavoidable +// on slower machines. Even there, it's seems nonexistent outside of +// communications screens. --Michael + +#ifdef DCQ_OF_DOOM +#define DCQ_MAX 512 +#define DCQ_FORCE_SLOWDOWN_SIZE 128 +#define DCQ_FORCE_BREAK_SIZE 512 +#define DCQ_LIVELOCK_MAX 256 +#else +#define DCQ_MAX 16384 +#define DCQ_FORCE_SLOWDOWN_SIZE 4096 +#define DCQ_FORCE_BREAK_SIZE 16384 +#define DCQ_LIVELOCK_MAX 4096 +#endif + #endif diff --git a/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c b/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c index c30566fba..0ed70b2bc 100644 --- a/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c +++ b/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c @@ -39,6 +39,8 @@ SDL_Rect TransitionClipRect; int GfxFlags = 0; +static TFB_Palette palette[256]; + int TFB_InitGraphics (int driver, int flags, int width, int height, int bpp) { @@ -76,6 +78,8 @@ TFB_InitGraphics (int driver, int flags, int width, int height, int bpp) //if (flags & TFB_GFXFLAGS_FULLSCREEN) // SDL_ShowCursor (SDL_DISABLE); + TFB_FlushPaletteCache (); + return 0; } @@ -467,30 +471,6 @@ TFB_ComputeFPS () } } -// Livelock deterrance constants. Because the entire screen is rarely -// refreshed, we may not drop draw commands on the floor with abandon. -// Furthermore, if the main program is queuing commands at a speed -// comparable to our processing of the commands, we never finish and -// the game freezes. Thus, if the queue starts out larger than -// DCQ_FORCE_SLOWDOWN_SIZE, or DCQ_LIVELOCK_MAX commands find -// themselves being processed in one go, livelock deterrence is -// enabled, and TFB_FlushGraphics locks the DCQ until it has processed -// all entries. If batched but pending commands exceed DCQ_FORCE_BREAK_SIZE, -// a continuity break is performed. This will effectively slow down the -// game logic, a fate we seek to avoid - however, it seems to be unavoidable -// on slower machines. Even there, it's seems nonexistent outside of -// communications screens. --Michael - -#ifdef DCQ_OF_DOOM -#define DCQ_FORCE_SLOWDOWN_SIZE 128 -#define DCQ_FORCE_BREAK_SIZE 512 -#define DCQ_LIVELOCK_MAX 256 -#else -#define DCQ_FORCE_SLOWDOWN_SIZE 1024 -#define DCQ_FORCE_BREAK_SIZE 4096 -#define DCQ_LIVELOCK_MAX 2048 -#endif - void TFB_FlushGraphics () // Only call from main thread!! { @@ -568,6 +548,21 @@ TFB_FlushGraphics () // Only call from main thread!! switch (DC.Type) { + case TFB_DRAWCOMMANDTYPE_SETPALETTE: + { + int index = DC.index; + if (index < 0 || index > 255) + { + fprintf(stderr, "DCQ panic: Tried to set palette #%i", index); + } + else + { + palette[index].r = DC.r & 0xFF; + palette[index].g = DC.g & 0xFF; + palette[index].b = DC.b & 0xFF; + } + break; + } case TFB_DRAWCOMMANDTYPE_IMAGE: { SDL_Rect targetRect; @@ -592,7 +587,7 @@ TFB_FlushGraphics () // Only call from main thread!! { if (DC.UsePalette) { - SDL_SetColors (surf, (SDL_Color*)DC.Palette, 0, 256); + SDL_SetColors (surf, (SDL_Color*)palette, 0, 256); } else { @@ -602,6 +597,40 @@ TFB_FlushGraphics () // Only call from main thread!! TFB_BlitSurface(surf, NULL, SDL_Screens[DC.destBuffer], &targetRect, DC.BlendNumerator, DC.BlendDenominator); + break; + } + case TFB_DRAWCOMMANDTYPE_FILLEDIMAGE: + { + SDL_Rect targetRect; + SDL_Surface *surf; + int i; + TFB_Palette pal[256]; + + + if (DC_image == 0) + { + fprintf (stderr, "TFB_FlushGraphics(): error, DC_image == 0\n"); + break; + } + + targetRect.x = DC.x; + targetRect.y = DC.y; + + if (DC.UseScaling) + surf = DC_image->ScaledImg; + else + surf = DC_image->NormalImg; + + for (i = 0; i < 256; i++) + { + pal[i].r = DC.r; + pal[i].g = DC.g; + pal[i].b = DC.b; + } + SDL_SetColors (surf, (SDL_Color*)pal, 0, 256); + + TFB_BlitSurface(surf, NULL, SDL_Screens[DC.destBuffer], &targetRect, DC.BlendNumerator, DC.BlendDenominator); + break; } case TFB_DRAWCOMMANDTYPE_LINE: