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
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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!!
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user