Moved DCQ rendering code out of SDL domain along with a few other functions; screen transitions timing fix
git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3465 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -20,6 +20,9 @@
|
||||
#include "libs/graphics/drawable.h"
|
||||
#include "libs/graphics/context.h"
|
||||
#include "libs/graphics/dcqueue.h"
|
||||
#include "libs/graphics/gfx_common.h"
|
||||
#include "libs/graphics/bbox.h"
|
||||
#include "libs/timelib.h"
|
||||
#include "libs/log.h"
|
||||
#include "libs/misc.h"
|
||||
// for TFB_DEBUG_HALT
|
||||
@@ -33,6 +36,10 @@ TFB_DrawCommand DCQ[DCQ_MAX];
|
||||
|
||||
TFB_DrawCommandQueue DrawCommandQueue;
|
||||
|
||||
#define FPS_PERIOD (ONE_SECOND / 100)
|
||||
int RenderedFrames = 0;
|
||||
|
||||
|
||||
// Wait for the queue to be emptied.
|
||||
static void
|
||||
TFB_WaitForSpace (int requested_slots)
|
||||
@@ -137,12 +144,19 @@ Init_DrawCommandQueue (void)
|
||||
DrawCommandQueue.FullSize = 0;
|
||||
DrawCommandQueue.Size = 0;
|
||||
|
||||
DCQ_Mutex = CreateRecursiveMutex ("DCQ", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
|
||||
TFB_BBox_Init (ScreenWidth, ScreenHeight);
|
||||
|
||||
DCQ_Mutex = CreateRecursiveMutex ("DCQ",
|
||||
SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
|
||||
|
||||
RenderingCond = CreateCondVar ("DCQ empty",
|
||||
SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
|
||||
}
|
||||
|
||||
void
|
||||
Uninit_DrawCommandQueue (void)
|
||||
{
|
||||
DestroyCondVar (RenderingCond);
|
||||
DestroyRecursiveMutex (DCQ_Mutex);
|
||||
}
|
||||
|
||||
@@ -245,3 +259,328 @@ TFB_EnqueueDrawCommand (TFB_DrawCommand* DrawCommand)
|
||||
TFB_DrawCommandQueue_Push (DrawCommand);
|
||||
}
|
||||
|
||||
static void
|
||||
computeFPS (void)
|
||||
{
|
||||
static TimeCount last_time;
|
||||
static TimePeriod fps_counter;
|
||||
TimeCount current_time;
|
||||
TimePeriod delta_time;
|
||||
|
||||
current_time = GetTimeCounter ();
|
||||
delta_time = current_time - last_time;
|
||||
last_time = current_time;
|
||||
|
||||
fps_counter += delta_time;
|
||||
if (fps_counter > FPS_PERIOD)
|
||||
{
|
||||
log_add (log_User, "fps %.2f, effective %.2f",
|
||||
(float)ONE_SECOND / delta_time,
|
||||
(float)ONE_SECOND * RenderedFrames / fps_counter);
|
||||
|
||||
fps_counter = 0;
|
||||
RenderedFrames = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Only call from main() thread!!
|
||||
void
|
||||
TFB_FlushGraphics (void)
|
||||
{
|
||||
int commands_handled;
|
||||
BOOLEAN livelock_deterrence;
|
||||
|
||||
// This is technically a locking violation on DrawCommandQueue.Size,
|
||||
// but it is likely to not be very destructive.
|
||||
if (DrawCommandQueue.Size == 0)
|
||||
{
|
||||
static int last_fade = 255;
|
||||
static int last_transition = 255;
|
||||
int current_fade = GetFadeAmount ();
|
||||
int current_transition = TransitionAmount;
|
||||
|
||||
if ((current_fade != 255 && current_fade != last_fade) ||
|
||||
(current_transition != 255 &&
|
||||
current_transition != last_transition) ||
|
||||
(current_fade == 255 && last_fade != 255) ||
|
||||
(current_transition == 255 && last_transition != 255))
|
||||
{
|
||||
TFB_SwapBuffers (TFB_REDRAW_FADING);
|
||||
// if fading, redraw every frame
|
||||
}
|
||||
else
|
||||
{
|
||||
TaskSwitch ();
|
||||
}
|
||||
|
||||
last_fade = current_fade;
|
||||
last_transition = current_transition;
|
||||
BroadcastCondVar (RenderingCond);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GfxFlags & TFB_GFXFLAGS_SHOWFPS)
|
||||
computeFPS ();
|
||||
|
||||
commands_handled = 0;
|
||||
livelock_deterrence = FALSE;
|
||||
|
||||
if (DrawCommandQueue.FullSize > DCQ_FORCE_BREAK_SIZE)
|
||||
{
|
||||
TFB_BatchReset ();
|
||||
}
|
||||
|
||||
if (DrawCommandQueue.Size > DCQ_FORCE_SLOWDOWN_SIZE)
|
||||
{
|
||||
Lock_DCQ (-1);
|
||||
livelock_deterrence = TRUE;
|
||||
}
|
||||
|
||||
TFB_BBox_Reset ();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
TFB_DrawCommand DC;
|
||||
|
||||
if (!TFB_DrawCommandQueue_Pop (&DC))
|
||||
{
|
||||
// the Queue is now empty.
|
||||
break;
|
||||
}
|
||||
|
||||
++commands_handled;
|
||||
if (!livelock_deterrence && commands_handled + DrawCommandQueue.Size
|
||||
> DCQ_LIVELOCK_MAX)
|
||||
{
|
||||
// log_add (log_Debug, "Initiating livelock deterrence!");
|
||||
livelock_deterrence = TRUE;
|
||||
|
||||
Lock_DCQ (-1);
|
||||
}
|
||||
|
||||
switch (DC.Type)
|
||||
{
|
||||
case TFB_DRAWCOMMANDTYPE_SETMIPMAP:
|
||||
{
|
||||
TFB_DrawCommand_SetMipmap *cmd = &DC.data.setmipmap;
|
||||
TFB_DrawImage_SetMipmap (cmd->image, cmd->mipmap,
|
||||
cmd->hotx, cmd->hoty);
|
||||
break;
|
||||
}
|
||||
|
||||
case TFB_DRAWCOMMANDTYPE_IMAGE:
|
||||
{
|
||||
TFB_DrawCommand_Image *cmd = &DC.data.image;
|
||||
TFB_Image *DC_image = cmd->image;
|
||||
const int x = cmd->x;
|
||||
const int y = cmd->y;
|
||||
|
||||
TFB_DrawCanvas_Image (DC_image, x, y,
|
||||
cmd->scale, cmd->scaleMode, cmd->colormap,
|
||||
TFB_GetScreenCanvas (cmd->destBuffer));
|
||||
|
||||
if (cmd->destBuffer == TFB_SCREEN_MAIN)
|
||||
{
|
||||
LockMutex (DC_image->mutex);
|
||||
if (cmd->scale)
|
||||
TFB_BBox_RegisterCanvas (DC_image->ScaledImg,
|
||||
x - DC_image->last_scale_hs.x,
|
||||
y - DC_image->last_scale_hs.y);
|
||||
else
|
||||
TFB_BBox_RegisterCanvas (DC_image->NormalImg,
|
||||
x - DC_image->NormalHs.x,
|
||||
y - DC_image->NormalHs.y);
|
||||
UnlockMutex (DC_image->mutex);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TFB_DRAWCOMMANDTYPE_FILLEDIMAGE:
|
||||
{
|
||||
TFB_DrawCommand_FilledImage *cmd = &DC.data.filledimage;
|
||||
TFB_Image *DC_image = cmd->image;
|
||||
const int x = cmd->x;
|
||||
const int y = cmd->y;
|
||||
|
||||
TFB_DrawCanvas_FilledImage (DC_image, x, y,
|
||||
cmd->scale, cmd->scaleMode, cmd->color,
|
||||
TFB_GetScreenCanvas (cmd->destBuffer));
|
||||
|
||||
if (cmd->destBuffer == TFB_SCREEN_MAIN)
|
||||
{
|
||||
LockMutex (DC_image->mutex);
|
||||
if (cmd->scale)
|
||||
TFB_BBox_RegisterCanvas (DC_image->ScaledImg,
|
||||
x - DC_image->last_scale_hs.x,
|
||||
y - DC_image->last_scale_hs.y);
|
||||
else
|
||||
TFB_BBox_RegisterCanvas (DC_image->NormalImg,
|
||||
x - DC_image->NormalHs.x,
|
||||
y - DC_image->NormalHs.y);
|
||||
UnlockMutex (DC_image->mutex);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TFB_DRAWCOMMANDTYPE_FONTCHAR:
|
||||
{
|
||||
TFB_DrawCommand_FontChar *cmd = &DC.data.fontchar;
|
||||
TFB_Char *DC_char = cmd->fontchar;
|
||||
const int x = cmd->x;
|
||||
const int y = cmd->y;
|
||||
|
||||
TFB_DrawCanvas_FontChar (DC_char, cmd->backing, x, y,
|
||||
TFB_GetScreenCanvas (cmd->destBuffer));
|
||||
|
||||
if (cmd->destBuffer == TFB_SCREEN_MAIN)
|
||||
{
|
||||
RECT r;
|
||||
|
||||
r.corner.x = x - DC_char->HotSpot.x;
|
||||
r.corner.y = y - DC_char->HotSpot.y;
|
||||
r.extent.width = DC_char->extent.width;
|
||||
r.extent.height = DC_char->extent.height;
|
||||
|
||||
TFB_BBox_RegisterRect (&r);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TFB_DRAWCOMMANDTYPE_LINE:
|
||||
{
|
||||
TFB_DrawCommand_Line *cmd = &DC.data.line;
|
||||
|
||||
if (cmd->destBuffer == TFB_SCREEN_MAIN)
|
||||
{
|
||||
TFB_BBox_RegisterPoint (cmd->x1, cmd->y1);
|
||||
TFB_BBox_RegisterPoint (cmd->x2, cmd->y2);
|
||||
}
|
||||
TFB_DrawCanvas_Line (cmd->x1, cmd->y1, cmd->x2, cmd->y2,
|
||||
cmd->color, TFB_GetScreenCanvas (cmd->destBuffer));
|
||||
break;
|
||||
}
|
||||
|
||||
case TFB_DRAWCOMMANDTYPE_RECTANGLE:
|
||||
{
|
||||
TFB_DrawCommand_Rect *cmd = &DC.data.rect;
|
||||
|
||||
if (cmd->destBuffer == TFB_SCREEN_MAIN)
|
||||
TFB_BBox_RegisterRect (&cmd->rect);
|
||||
TFB_DrawCanvas_Rect (&cmd->rect, cmd->color,
|
||||
TFB_GetScreenCanvas (cmd->destBuffer));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TFB_DRAWCOMMANDTYPE_SCISSORENABLE:
|
||||
{
|
||||
TFB_DrawCommand_Scissor *cmd = &DC.data.scissor;
|
||||
|
||||
TFB_DrawCanvas_SetClipRect (
|
||||
TFB_GetScreenCanvas (TFB_SCREEN_MAIN), &cmd->rect);
|
||||
TFB_BBox_SetClipRect (&DC.data.scissor.rect);
|
||||
break;
|
||||
}
|
||||
|
||||
case TFB_DRAWCOMMANDTYPE_SCISSORDISABLE:
|
||||
TFB_DrawCanvas_SetClipRect (
|
||||
TFB_GetScreenCanvas (TFB_SCREEN_MAIN), NULL);
|
||||
TFB_BBox_SetClipRect (NULL);
|
||||
break;
|
||||
|
||||
case TFB_DRAWCOMMANDTYPE_COPYTOIMAGE:
|
||||
{
|
||||
TFB_DrawCommand_CopyToImage *cmd = &DC.data.copytoimage;
|
||||
TFB_Image *DC_image = cmd->image;
|
||||
const POINT dstPt = {0, 0};
|
||||
|
||||
if (DC_image == 0)
|
||||
{
|
||||
log_add (log_Debug, "DCQ ERROR: COPYTOIMAGE passed null "
|
||||
"image ptr");
|
||||
break;
|
||||
}
|
||||
LockMutex (DC_image->mutex);
|
||||
TFB_DrawCanvas_CopyRect (
|
||||
TFB_GetScreenCanvas (cmd->srcBuffer), &cmd->rect,
|
||||
DC_image->NormalImg, dstPt);
|
||||
UnlockMutex (DC_image->mutex);
|
||||
break;
|
||||
}
|
||||
|
||||
case TFB_DRAWCOMMANDTYPE_COPY:
|
||||
{
|
||||
TFB_DrawCommand_Copy *cmd = &DC.data.copy;
|
||||
const RECT r = cmd->rect;
|
||||
|
||||
if (cmd->destBuffer == TFB_SCREEN_MAIN)
|
||||
TFB_BBox_RegisterRect (&cmd->rect);
|
||||
|
||||
TFB_DrawCanvas_CopyRect (
|
||||
TFB_GetScreenCanvas (cmd->srcBuffer), &r,
|
||||
TFB_GetScreenCanvas (cmd->destBuffer), r.corner);
|
||||
break;
|
||||
}
|
||||
|
||||
case TFB_DRAWCOMMANDTYPE_DELETEIMAGE:
|
||||
{
|
||||
TFB_Image *DC_image = DC.data.deleteimage.image;
|
||||
TFB_DrawImage_Delete (DC_image);
|
||||
break;
|
||||
}
|
||||
|
||||
case TFB_DRAWCOMMANDTYPE_DELETEDATA:
|
||||
{
|
||||
void *data = DC.data.deletedata.data;
|
||||
HFree (data);
|
||||
break;
|
||||
}
|
||||
|
||||
case TFB_DRAWCOMMANDTYPE_SENDSIGNAL:
|
||||
ClearSemaphore (DC.data.sendsignal.sem);
|
||||
break;
|
||||
|
||||
case TFB_DRAWCOMMANDTYPE_REINITVIDEO:
|
||||
{
|
||||
TFB_DrawCommand_ReinitVideo *cmd = &DC.data.reinitvideo;
|
||||
int oldDriver = GraphicsDriver;
|
||||
int oldFlags = GfxFlags;
|
||||
int oldWidth = ScreenWidthActual;
|
||||
int oldHeight = ScreenHeightActual;
|
||||
if (TFB_ReInitGraphics (cmd->driver, cmd->flags,
|
||||
cmd->width, cmd->height))
|
||||
{
|
||||
log_add (log_Error, "Could not provide requested mode: "
|
||||
"reverting to last known driver.");
|
||||
// We don't know what exactly failed, so roll it all back
|
||||
if (TFB_ReInitGraphics (oldDriver, oldFlags,
|
||||
oldWidth, oldHeight))
|
||||
{
|
||||
log_add (log_Fatal,
|
||||
"Couldn't reinit at that point either. "
|
||||
"Your video has been somehow tied in knots.");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
TFB_SwapBuffers (TFB_REDRAW_YES);
|
||||
break;
|
||||
}
|
||||
|
||||
case TFB_DRAWCOMMANDTYPE_CALLBACK:
|
||||
{
|
||||
DC.data.callback.callback (DC.data.callback.arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (livelock_deterrence)
|
||||
Unlock_DCQ ();
|
||||
|
||||
TFB_SwapBuffers (TFB_REDRAW_NO);
|
||||
RenderedFrames++;
|
||||
BroadcastCondVar (RenderingCond);
|
||||
}
|
||||
|
||||
@@ -87,14 +87,14 @@ typedef struct tfb_dc_fontchar
|
||||
|
||||
typedef struct tfb_dc_copy
|
||||
{
|
||||
int x, y, w, h;
|
||||
RECT rect;
|
||||
SCREEN srcBuffer, destBuffer;
|
||||
} TFB_DrawCommand_Copy;
|
||||
|
||||
typedef struct tfb_dc_copyimg
|
||||
{
|
||||
TFB_Image *image;
|
||||
int x, y, w, h;
|
||||
RECT rect;
|
||||
SCREEN srcBuffer;
|
||||
} TFB_DrawCommand_CopyToImage;
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "gfxintrn.h"
|
||||
#include "libs/graphics/gfx_common.h"
|
||||
#include "libs/graphics/drawcmd.h"
|
||||
#include "libs/timelib.h"
|
||||
#include "libs/misc.h"
|
||||
// for TFB_DEBUG_HALT
|
||||
|
||||
@@ -35,6 +36,9 @@ int ScreenColorDepth;
|
||||
int GraphicsDriver;
|
||||
int TFB_DEBUG_HALT = 0;
|
||||
|
||||
volatile int TransitionAmount = 255;
|
||||
RECT TransitionClipRect;
|
||||
|
||||
static int gscale = GSCALE_IDENTITY;
|
||||
static int gscale_mode = TFB_SCALE_NEAREST;
|
||||
|
||||
@@ -78,3 +82,119 @@ GetGraphicScaleMode (void)
|
||||
{
|
||||
return gscale_mode;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
TFB_BatchGraphics ();
|
||||
}
|
||||
|
||||
void
|
||||
UnbatchGraphics (void)
|
||||
{
|
||||
TFB_UnbatchGraphics ();
|
||||
}
|
||||
|
||||
/* Sleeps this thread until all Draw Commands queued by that thread have
|
||||
been processed. */
|
||||
|
||||
void
|
||||
FlushGraphics ()
|
||||
{
|
||||
TFB_DrawScreen_WaitForSignal ();
|
||||
}
|
||||
|
||||
static void
|
||||
ExpandRect (RECT *rect, int expansion)
|
||||
{
|
||||
if (rect->corner.x - expansion >= 0)
|
||||
{
|
||||
rect->extent.width += expansion;
|
||||
rect->corner.x -= expansion;
|
||||
}
|
||||
else
|
||||
{
|
||||
rect->extent.width += rect->corner.x;
|
||||
rect->corner.x = 0;
|
||||
}
|
||||
|
||||
if (rect->corner.y - expansion >= 0)
|
||||
{
|
||||
rect->extent.height += expansion;
|
||||
rect->corner.y -= expansion;
|
||||
}
|
||||
else
|
||||
{
|
||||
rect->extent.height += rect->corner.y;
|
||||
rect->corner.y = 0;
|
||||
}
|
||||
|
||||
if (rect->corner.x + rect->extent.width + expansion <= ScreenWidth)
|
||||
rect->extent.width += expansion;
|
||||
else
|
||||
rect->extent.width = ScreenWidth - rect->corner.x;
|
||||
|
||||
if (rect->corner.y + rect->extent.height + expansion <= ScreenHeight)
|
||||
rect->extent.height += expansion;
|
||||
else
|
||||
rect->extent.height = ScreenHeight - rect->corner.y;
|
||||
}
|
||||
|
||||
void
|
||||
SetTransitionSource (const RECT *pRect)
|
||||
{
|
||||
RECT ActualRect;
|
||||
|
||||
if (pRect)
|
||||
{ /* expand the rect to accomodate scalers in OpenGL mode */
|
||||
ActualRect = *pRect;
|
||||
pRect = &ActualRect;
|
||||
ExpandRect (&ActualRect, 2);
|
||||
}
|
||||
TFB_DrawScreen_Copy (pRect, TFB_SCREEN_MAIN, TFB_SCREEN_TRANSITION);
|
||||
}
|
||||
|
||||
// ScreenTransition() is synchronous (does not return until transition done)
|
||||
void
|
||||
ScreenTransition (int TransType, const RECT *pRect)
|
||||
{
|
||||
const TimePeriod DURATION = ONE_SECOND * 31 / 60;
|
||||
TimeCount startTime;
|
||||
(void) TransType; /* dodge compiler warning */
|
||||
|
||||
if (pRect)
|
||||
{
|
||||
TransitionClipRect = *pRect;
|
||||
}
|
||||
else
|
||||
{
|
||||
TransitionClipRect.corner.x = 0;
|
||||
TransitionClipRect.corner.y = 0;
|
||||
TransitionClipRect.extent.width = ScreenWidth;
|
||||
TransitionClipRect.extent.height = ScreenHeight;
|
||||
}
|
||||
|
||||
TFB_UploadTransitionScreen ();
|
||||
|
||||
TransitionAmount = 0;
|
||||
FlushGraphics ();
|
||||
startTime = GetTimeCounter ();
|
||||
while (TransitionAmount < 255)
|
||||
{
|
||||
TimePeriod deltaT;
|
||||
int newAmount;
|
||||
|
||||
SleepThread (ONE_SECOND / 100);
|
||||
|
||||
deltaT = GetTimeCounter () - startTime;
|
||||
newAmount = deltaT * 255 / DURATION;
|
||||
if (newAmount > 255)
|
||||
newAmount = 255;
|
||||
|
||||
TransitionAmount = newAmount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,10 +61,16 @@ enum
|
||||
// The flag variable itself
|
||||
extern int GfxFlags;
|
||||
|
||||
// The following functions are driver-defined
|
||||
void TFB_PreInit (void);
|
||||
int TFB_InitGraphics (int driver, int flags, int width, int height);
|
||||
int TFB_ReInitGraphics (int driver, int flags, int width, int height);
|
||||
void TFB_UninitGraphics (void);
|
||||
void TFB_ProcessEvents (void);
|
||||
void TFB_SetGamma (float gamma);
|
||||
void TFB_UploadTransitionScreen (void);
|
||||
// This function should not be called directly
|
||||
void TFB_SwapBuffers (int force_full_redraw);
|
||||
|
||||
#define GSCALE_IDENTITY 256
|
||||
|
||||
@@ -81,17 +87,18 @@ int SetGraphicScale (int scale);
|
||||
int GetGraphicScale (void);
|
||||
int SetGraphicScaleMode (int mode /* enum SCALE */);
|
||||
int GetGraphicScaleMode (void);
|
||||
void SetTransitionSource (RECT *pRect);
|
||||
void ScreenTransition (int transition, RECT *pRect);
|
||||
void SetTransitionSource (const RECT *pRect);
|
||||
void ScreenTransition (int transition, const RECT *pRect);
|
||||
|
||||
// TODO: there should be accessor functions for these
|
||||
extern volatile int TransitionAmount;
|
||||
extern RECT TransitionClipRect;
|
||||
|
||||
extern float FrameRate;
|
||||
extern int FrameRateTickBase;
|
||||
|
||||
void TFB_FlushGraphics (void); // Only call from main thread!!
|
||||
|
||||
void TFB_SetGamma (float gamma);
|
||||
// Unknown Stuff
|
||||
|
||||
extern int ScreenWidth;
|
||||
extern int ScreenHeight;
|
||||
extern int ScreenWidthActual;
|
||||
|
||||
@@ -26,9 +26,6 @@
|
||||
#include "libs/graphics/tfb_draw.h"
|
||||
|
||||
|
||||
int batch_depth = 0;
|
||||
|
||||
|
||||
//Status: Not entirely unimplemented!
|
||||
BOOLEAN
|
||||
InitGraphics (int argc, char* argv[], COUNT KbytesRequired)
|
||||
@@ -57,130 +54,6 @@ UninitGraphics () // Also probably empty
|
||||
//mem_uninit ();
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
TFB_BatchGraphics ();
|
||||
}
|
||||
|
||||
void
|
||||
UnbatchGraphics (void)
|
||||
{
|
||||
TFB_UnbatchGraphics ();
|
||||
}
|
||||
|
||||
/* Sleeps this thread until all Draw Commands queued by that thread have
|
||||
been processed. */
|
||||
|
||||
void
|
||||
FlushGraphics ()
|
||||
{
|
||||
TFB_DrawScreen_WaitForSignal ();
|
||||
}
|
||||
|
||||
static void
|
||||
ExpandRect (RECT *rect, int expansion)
|
||||
{
|
||||
if (rect->corner.x - expansion >= 0)
|
||||
{
|
||||
rect->extent.width += expansion;
|
||||
rect->corner.x -= expansion;
|
||||
}
|
||||
else
|
||||
{
|
||||
rect->extent.width += rect->corner.x;
|
||||
rect->corner.x = 0;
|
||||
}
|
||||
|
||||
if (rect->corner.y - expansion >= 0)
|
||||
{
|
||||
rect->extent.height += expansion;
|
||||
rect->corner.y -= expansion;
|
||||
}
|
||||
else
|
||||
{
|
||||
rect->extent.height += rect->corner.y;
|
||||
rect->corner.y = 0;
|
||||
}
|
||||
|
||||
if (rect->corner.x + rect->extent.width + expansion <= ScreenWidth)
|
||||
rect->extent.width += expansion;
|
||||
else
|
||||
rect->extent.width = ScreenWidth - rect->corner.x;
|
||||
|
||||
if (rect->corner.y + rect->extent.height + expansion <= ScreenHeight)
|
||||
rect->extent.height += expansion;
|
||||
else
|
||||
rect->extent.height = ScreenHeight - rect->corner.y;
|
||||
}
|
||||
|
||||
void
|
||||
SetTransitionSource (RECT *pRect)
|
||||
{
|
||||
RECT ActualRect;
|
||||
|
||||
if (pRect)
|
||||
{ /* expand the rect to accomodate scalers in OpenGL mode */
|
||||
ActualRect = *pRect;
|
||||
pRect = &ActualRect;
|
||||
ExpandRect (&ActualRect, 2);
|
||||
}
|
||||
TFB_DrawScreen_Copy(pRect, TFB_SCREEN_MAIN, TFB_SCREEN_TRANSITION);
|
||||
}
|
||||
|
||||
// Status: Implemented
|
||||
void
|
||||
ScreenTransition (int TransType, RECT *pRect)
|
||||
{
|
||||
const float DURATION = (31.0f / 60.0f); // in seconds
|
||||
Uint32 last_time = 0, current_time, delta_time, add_amount;
|
||||
(void) TransType; /* dodge compiler warning */
|
||||
|
||||
if (pRect)
|
||||
{
|
||||
TransitionClipRect.x = pRect->corner.x;
|
||||
TransitionClipRect.y = pRect->corner.y;
|
||||
TransitionClipRect.w = pRect->extent.width;
|
||||
TransitionClipRect.h = pRect->extent.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
TransitionClipRect.x = TransitionClipRect.y = 0;
|
||||
TransitionClipRect.w = ScreenWidth;
|
||||
TransitionClipRect.h = ScreenHeight;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENGL
|
||||
if (GraphicsDriver == TFB_GFXDRIVER_SDL_OPENGL)
|
||||
{
|
||||
TFB_GL_UploadTransitionScreen ();
|
||||
}
|
||||
#endif
|
||||
|
||||
TransitionAmount = 0;
|
||||
FlushGraphics ();
|
||||
last_time = SDL_GetTicks ();
|
||||
for (;;)
|
||||
{
|
||||
SDL_Delay (10);
|
||||
|
||||
current_time = SDL_GetTicks ();
|
||||
delta_time = current_time - last_time;
|
||||
last_time = current_time;
|
||||
|
||||
add_amount = (Uint32) ((delta_time / 1000.0f / DURATION) * 255);
|
||||
if (TransitionAmount + add_amount >= 255)
|
||||
break;
|
||||
|
||||
TransitionAmount += add_amount;
|
||||
}
|
||||
TransitionAmount = 255;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
_image_intersect (IMAGE_BOX *box1, IMAGE_BOX *box2, RECT *rect)
|
||||
{
|
||||
|
||||
@@ -1669,3 +1669,55 @@ TFB_DrawCanvas_GetRotatedExtent (TFB_Canvas src_canvas, int angle, EXTENT *size)
|
||||
size->width = dstw;
|
||||
}
|
||||
|
||||
void
|
||||
TFB_DrawCanvas_CopyRect (TFB_Canvas source, const RECT *srcRect,
|
||||
TFB_Canvas target, POINT dstPt)
|
||||
{
|
||||
SDL_Rect sourceRect, targetRect;
|
||||
|
||||
if (source == 0 || target == 0)
|
||||
{
|
||||
log_add (log_Warning,
|
||||
"ERROR: TFB_DrawCanvas_CopyRect passed null canvas ptr");
|
||||
return;
|
||||
}
|
||||
|
||||
sourceRect.x = srcRect->corner.x;
|
||||
sourceRect.y = srcRect->corner.y;
|
||||
sourceRect.w = srcRect->extent.width;
|
||||
sourceRect.h = srcRect->extent.height;
|
||||
|
||||
targetRect.x = dstPt.x;
|
||||
targetRect.y = dstPt.y;
|
||||
// According to SDL docs, width and height are ignored, but
|
||||
// we'll set them anyway, just in case.
|
||||
targetRect.w = srcRect->extent.width;
|
||||
targetRect.h = srcRect->extent.height;
|
||||
|
||||
SDL_BlitSurface (source, &sourceRect, target, &targetRect);
|
||||
}
|
||||
|
||||
void
|
||||
TFB_DrawCanvas_SetClipRect (TFB_Canvas canvas, const RECT *clipRect)
|
||||
{
|
||||
if (canvas == 0)
|
||||
{
|
||||
log_add (log_Warning,
|
||||
"ERROR: TFB_DrawCanvas_SetClipRect passed null canvas ptr");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!clipRect)
|
||||
{ // clipping disabled
|
||||
SDL_SetClipRect (canvas, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_Rect r;
|
||||
r.x = clipRect->corner.x;
|
||||
r.y = clipRect->corner.y;
|
||||
r.w = clipRect->extent.width;
|
||||
r.h = clipRect->extent.height;
|
||||
SDL_SetClipRect (canvas, &r);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,17 +45,12 @@ SDL_Surface *SDL_Screens[TFB_GFX_NUMSCREENS];
|
||||
|
||||
SDL_Surface *format_conv_surf = NULL;
|
||||
|
||||
volatile int TransitionAmount = 255;
|
||||
SDL_Rect TransitionClipRect;
|
||||
static volatile BOOLEAN abortFlag = FALSE;
|
||||
|
||||
int GfxFlags = 0;
|
||||
|
||||
TFB_GRAPHICS_BACKEND *graphics_backend = NULL;
|
||||
|
||||
#define FPS_PERIOD 100
|
||||
int RenderedFrames = 0;
|
||||
|
||||
volatile int QuitPosted = 0;
|
||||
volatile int GameActive = 1; // Track the SDL_ACTIVEEVENT state SDL_APPACTIVE
|
||||
|
||||
@@ -174,10 +169,6 @@ TFB_InitGraphics (int driver, int flags, int width, int height)
|
||||
Init_DrawCommandQueue ();
|
||||
|
||||
TFB_DrawCanvas_Initialize ();
|
||||
TFB_BBox_Init (ScreenWidth, ScreenHeight);
|
||||
|
||||
RenderingCond = CreateCondVar ("DCQ empty",
|
||||
SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
|
||||
|
||||
atexit (TFB_UninitGraphics);
|
||||
|
||||
@@ -277,8 +268,13 @@ TFB_SwapBuffers (int force_full_redraw)
|
||||
|
||||
if (transition_amount != 255)
|
||||
{
|
||||
SDL_Rect r;
|
||||
r.x = TransitionClipRect.corner.x;
|
||||
r.y = TransitionClipRect.corner.y;
|
||||
r.w = TransitionClipRect.extent.width;
|
||||
r.h = TransitionClipRect.extent.height;
|
||||
graphics_backend->screen (TFB_SCREEN_TRANSITION,
|
||||
255 - transition_amount, &TransitionClipRect);
|
||||
255 - transition_amount, &r);
|
||||
}
|
||||
|
||||
if (fade_amount != 255)
|
||||
@@ -339,7 +335,7 @@ TFB_DisplayFormatAlpha (SDL_Surface *surface)
|
||||
TFB_Canvas
|
||||
TFB_GetScreenCanvas (SCREEN screen)
|
||||
{
|
||||
return (TFB_Canvas) SDL_Screens[screen];
|
||||
return SDL_Screens[screen];
|
||||
}
|
||||
|
||||
void TFB_BlitSurface (SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst,
|
||||
@@ -586,323 +582,14 @@ void TFB_BlitSurface (SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst,
|
||||
}
|
||||
|
||||
void
|
||||
TFB_ComputeFPS (void)
|
||||
TFB_UploadTransitionScreen (void)
|
||||
{
|
||||
static Uint32 last_time = 0, fps_counter = 0;
|
||||
Uint32 current_time, delta_time;
|
||||
|
||||
current_time = SDL_GetTicks ();
|
||||
delta_time = current_time - last_time;
|
||||
last_time = current_time;
|
||||
|
||||
fps_counter += delta_time;
|
||||
if (fps_counter > FPS_PERIOD)
|
||||
#ifdef HAVE_OPENGL
|
||||
if (GraphicsDriver == TFB_GFXDRIVER_SDL_OPENGL)
|
||||
{
|
||||
log_add (log_User, "fps %.2f, effective %.2f",
|
||||
1000.0 / delta_time,
|
||||
1000.0 * RenderedFrames / fps_counter);
|
||||
|
||||
fps_counter = 0;
|
||||
RenderedFrames = 0;
|
||||
TFB_GL_UploadTransitionScreen ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TFB_FlushGraphics (void) // Only call from main thread!!
|
||||
{
|
||||
int commands_handled;
|
||||
BOOLEAN livelock_deterrence;
|
||||
BOOLEAN done;
|
||||
|
||||
// This is technically a locking violation on DrawCommandQueue.Size,
|
||||
// but it is likely to not be very destructive.
|
||||
if (DrawCommandQueue.Size == 0)
|
||||
{
|
||||
static int last_fade = 255;
|
||||
static int last_transition = 255;
|
||||
int current_fade = GetFadeAmount ();
|
||||
int current_transition = TransitionAmount;
|
||||
|
||||
if ((current_fade != 255 && current_fade != last_fade) ||
|
||||
(current_transition != 255 &&
|
||||
current_transition != last_transition) ||
|
||||
(current_fade == 255 && last_fade != 255) ||
|
||||
(current_transition == 255 && last_transition != 255))
|
||||
{
|
||||
TFB_SwapBuffers (TFB_REDRAW_FADING);
|
||||
// if fading, redraw every frame
|
||||
}
|
||||
else
|
||||
{
|
||||
TaskSwitch ();
|
||||
}
|
||||
|
||||
last_fade = current_fade;
|
||||
last_transition = current_transition;
|
||||
BroadcastCondVar (RenderingCond);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GfxFlags & TFB_GFXFLAGS_SHOWFPS)
|
||||
TFB_ComputeFPS ();
|
||||
|
||||
commands_handled = 0;
|
||||
livelock_deterrence = FALSE;
|
||||
|
||||
if (DrawCommandQueue.FullSize > DCQ_FORCE_BREAK_SIZE)
|
||||
{
|
||||
TFB_BatchReset ();
|
||||
}
|
||||
|
||||
if (DrawCommandQueue.Size > DCQ_FORCE_SLOWDOWN_SIZE)
|
||||
{
|
||||
Lock_DCQ (-1);
|
||||
livelock_deterrence = TRUE;
|
||||
}
|
||||
|
||||
TFB_BBox_Reset ();
|
||||
|
||||
done = FALSE;
|
||||
while (!done)
|
||||
{
|
||||
TFB_DrawCommand DC;
|
||||
|
||||
if (!TFB_DrawCommandQueue_Pop (&DC))
|
||||
{
|
||||
// the Queue is now empty.
|
||||
break;
|
||||
}
|
||||
|
||||
++commands_handled;
|
||||
if (!livelock_deterrence && commands_handled + DrawCommandQueue.Size
|
||||
> DCQ_LIVELOCK_MAX)
|
||||
{
|
||||
// log_add (log_Debug, "Initiating livelock deterrence!");
|
||||
livelock_deterrence = TRUE;
|
||||
|
||||
Lock_DCQ (-1);
|
||||
}
|
||||
|
||||
switch (DC.Type)
|
||||
{
|
||||
case TFB_DRAWCOMMANDTYPE_SETMIPMAP:
|
||||
TFB_DrawImage_SetMipmap (DC.data.setmipmap.image,
|
||||
DC.data.setmipmap.mipmap,
|
||||
DC.data.setmipmap.hotx, DC.data.setmipmap.hoty);
|
||||
break;
|
||||
case TFB_DRAWCOMMANDTYPE_IMAGE:
|
||||
{
|
||||
TFB_DrawCommand_Image *cmd = &DC.data.image;
|
||||
TFB_Image *DC_image = cmd->image;
|
||||
int x = cmd->x;
|
||||
int y = cmd->y;
|
||||
|
||||
TFB_DrawCanvas_Image (DC_image, x, y,
|
||||
cmd->scale, cmd->scaleMode, cmd->colormap,
|
||||
SDL_Screens[cmd->destBuffer]);
|
||||
|
||||
if (cmd->destBuffer == 0)
|
||||
{
|
||||
LockMutex (DC_image->mutex);
|
||||
if (DC.data.image.scale)
|
||||
TFB_BBox_RegisterCanvas (DC_image->ScaledImg,
|
||||
x - DC_image->last_scale_hs.x,
|
||||
y - DC_image->last_scale_hs.y);
|
||||
else
|
||||
TFB_BBox_RegisterCanvas (DC_image->NormalImg,
|
||||
x - DC_image->NormalHs.x,
|
||||
y - DC_image->NormalHs.y);
|
||||
UnlockMutex (DC_image->mutex);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case TFB_DRAWCOMMANDTYPE_FILLEDIMAGE:
|
||||
{
|
||||
TFB_DrawCommand_FilledImage *cmd = &DC.data.filledimage;
|
||||
TFB_Image *DC_image = cmd->image;
|
||||
int x = cmd->x;
|
||||
int y = cmd->y;
|
||||
|
||||
TFB_DrawCanvas_FilledImage (DC_image, x, y,
|
||||
cmd->scale, cmd->scaleMode, cmd->color,
|
||||
SDL_Screens[cmd->destBuffer]);
|
||||
|
||||
if (cmd->destBuffer == 0)
|
||||
{
|
||||
LockMutex (DC_image->mutex);
|
||||
if (DC.data.filledimage.scale)
|
||||
TFB_BBox_RegisterCanvas (DC_image->ScaledImg,
|
||||
x - DC_image->last_scale_hs.x,
|
||||
y - DC_image->last_scale_hs.y);
|
||||
else
|
||||
TFB_BBox_RegisterCanvas (DC_image->NormalImg,
|
||||
x - DC_image->NormalHs.x,
|
||||
y - DC_image->NormalHs.y);
|
||||
UnlockMutex (DC_image->mutex);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case TFB_DRAWCOMMANDTYPE_FONTCHAR:
|
||||
{
|
||||
TFB_Char *DC_char = DC.data.fontchar.fontchar;
|
||||
int x = DC.data.fontchar.x;
|
||||
int y = DC.data.fontchar.y;
|
||||
|
||||
TFB_DrawCanvas_FontChar (DC.data.fontchar.fontchar,
|
||||
DC.data.fontchar.backing,
|
||||
DC.data.fontchar.x, DC.data.fontchar.y,
|
||||
SDL_Screens[DC.data.fontchar.destBuffer]);
|
||||
|
||||
if (DC.data.fontchar.destBuffer == 0)
|
||||
{
|
||||
RECT r;
|
||||
|
||||
r.corner.x = x - DC_char->HotSpot.x;
|
||||
r.corner.y = y - DC_char->HotSpot.y;
|
||||
r.extent.width = DC_char->extent.width;
|
||||
r.extent.height = DC_char->extent.height;
|
||||
|
||||
TFB_BBox_RegisterRect (&r);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case TFB_DRAWCOMMANDTYPE_LINE:
|
||||
{
|
||||
if (DC.data.line.destBuffer == 0)
|
||||
{
|
||||
TFB_BBox_RegisterPoint (DC.data.line.x1, DC.data.line.y1);
|
||||
TFB_BBox_RegisterPoint (DC.data.line.x2, DC.data.line.y2);
|
||||
}
|
||||
TFB_DrawCanvas_Line (DC.data.line.x1, DC.data.line.y1,
|
||||
DC.data.line.x2, DC.data.line.y2,
|
||||
DC.data.line.color,
|
||||
SDL_Screens[DC.data.line.destBuffer]);
|
||||
break;
|
||||
}
|
||||
case TFB_DRAWCOMMANDTYPE_RECTANGLE:
|
||||
{
|
||||
if (DC.data.rect.destBuffer == 0)
|
||||
TFB_BBox_RegisterRect (&DC.data.rect.rect);
|
||||
TFB_DrawCanvas_Rect (&DC.data.rect.rect, DC.data.rect.color,
|
||||
SDL_Screens[DC.data.rect.destBuffer]);
|
||||
|
||||
break;
|
||||
}
|
||||
case TFB_DRAWCOMMANDTYPE_SCISSORENABLE:
|
||||
{
|
||||
SDL_Rect r;
|
||||
r.x = DC.data.scissor.rect.corner.x;
|
||||
r.y = DC.data.scissor.rect.corner.y;
|
||||
r.w = DC.data.scissor.rect.extent.width;
|
||||
r.h = DC.data.scissor.rect.extent.height;
|
||||
SDL_SetClipRect (SDL_Screens[0], &r);
|
||||
TFB_BBox_SetClipRect (&DC.data.scissor.rect);
|
||||
break;
|
||||
}
|
||||
case TFB_DRAWCOMMANDTYPE_SCISSORDISABLE:
|
||||
SDL_SetClipRect (SDL_Screens[0], NULL);
|
||||
TFB_BBox_SetClipRect (NULL);
|
||||
break;
|
||||
case TFB_DRAWCOMMANDTYPE_COPYTOIMAGE:
|
||||
{
|
||||
SDL_Rect src, dest;
|
||||
TFB_Image *DC_image = DC.data.copytoimage.image;
|
||||
|
||||
if (DC_image == 0)
|
||||
{
|
||||
log_add (log_Debug, "DCQ ERROR: COPYTOIMAGE passed null "
|
||||
"image ptr");
|
||||
break;
|
||||
}
|
||||
LockMutex (DC_image->mutex);
|
||||
|
||||
src.x = dest.x = DC.data.copytoimage.x;
|
||||
src.y = dest.y = DC.data.copytoimage.y;
|
||||
src.w = DC.data.copytoimage.w;
|
||||
src.h = DC.data.copytoimage.h;
|
||||
|
||||
dest.x = 0;
|
||||
dest.y = 0;
|
||||
SDL_BlitSurface (SDL_Screens[DC.data.copytoimage.srcBuffer],
|
||||
&src, DC_image->NormalImg, &dest);
|
||||
UnlockMutex (DC_image->mutex);
|
||||
break;
|
||||
}
|
||||
case TFB_DRAWCOMMANDTYPE_COPY:
|
||||
{
|
||||
SDL_Rect src, dest;
|
||||
src.x = dest.x = DC.data.copy.x;
|
||||
src.y = dest.y = DC.data.copy.y;
|
||||
src.w = DC.data.copy.w;
|
||||
src.h = DC.data.copy.h;
|
||||
|
||||
if (DC.data.copy.destBuffer == 0)
|
||||
{
|
||||
TFB_BBox_RegisterPoint (src.x, src.y);
|
||||
TFB_BBox_RegisterPoint (src.x + src.w, src.y + src.h);
|
||||
}
|
||||
|
||||
SDL_BlitSurface (SDL_Screens[DC.data.copy.srcBuffer], &src,
|
||||
SDL_Screens[DC.data.copy.destBuffer], &dest);
|
||||
break;
|
||||
}
|
||||
case TFB_DRAWCOMMANDTYPE_DELETEIMAGE:
|
||||
{
|
||||
TFB_Image *DC_image = (TFB_Image *)DC.data.deleteimage.image;
|
||||
TFB_DrawImage_Delete (DC_image);
|
||||
break;
|
||||
}
|
||||
case TFB_DRAWCOMMANDTYPE_DELETEDATA:
|
||||
{
|
||||
void *data = DC.data.deletedata.data;
|
||||
HFree (data);
|
||||
break;
|
||||
}
|
||||
case TFB_DRAWCOMMANDTYPE_SENDSIGNAL:
|
||||
ClearSemaphore (DC.data.sendsignal.sem);
|
||||
break;
|
||||
case TFB_DRAWCOMMANDTYPE_REINITVIDEO:
|
||||
{
|
||||
int oldDriver = GraphicsDriver;
|
||||
int oldFlags = GfxFlags;
|
||||
int oldWidth = ScreenWidthActual;
|
||||
int oldHeight = ScreenHeightActual;
|
||||
if (TFB_ReInitGraphics (DC.data.reinitvideo.driver,
|
||||
DC.data.reinitvideo.flags,
|
||||
DC.data.reinitvideo.width, DC.data.reinitvideo.height))
|
||||
{
|
||||
log_add (log_Error, "Could not provide requested mode: "
|
||||
"reverting to last known driver.");
|
||||
// We don't know what exactly failed, so roll it all back
|
||||
if (TFB_ReInitGraphics (oldDriver, oldFlags,
|
||||
oldWidth, oldHeight))
|
||||
{
|
||||
log_add (log_Fatal,
|
||||
"Couldn't reinit at that point either. "
|
||||
"Your video has been somehow tied in knots.");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
TFB_SwapBuffers (TFB_REDRAW_YES);
|
||||
break;
|
||||
}
|
||||
case TFB_DRAWCOMMANDTYPE_CALLBACK:
|
||||
{
|
||||
DC.data.callback.callback (DC.data.callback.arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (livelock_deterrence)
|
||||
Unlock_DCQ ();
|
||||
|
||||
TFB_SwapBuffers (TFB_REDRAW_NO);
|
||||
RenderedFrames++;
|
||||
BroadcastCondVar (RenderingCond);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -46,13 +46,9 @@ extern SDL_Surface *SDL_Screens[TFB_GFX_NUMSCREENS];
|
||||
|
||||
extern SDL_Surface *format_conv_surf;
|
||||
|
||||
extern volatile int TransitionAmount;
|
||||
extern SDL_Rect TransitionClipRect;
|
||||
|
||||
void ScreenOrigin (FRAME Display, COORD sx, COORD sy);
|
||||
void LoadDisplay (DISPLAY_INTERFACE **pDisplay);
|
||||
|
||||
void TFB_SwapBuffers (int force_full_redraw);
|
||||
SDL_Surface* TFB_DisplayFormatAlpha (SDL_Surface *surface);
|
||||
void TFB_BlitSurface (SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst,
|
||||
SDL_Rect *dstrect, int blend_numer, int blend_denom);
|
||||
|
||||
@@ -114,15 +114,12 @@ TFB_DrawScreen_FontChar (TFB_Char *fontChar, TFB_Image *backing,
|
||||
}
|
||||
|
||||
void
|
||||
TFB_DrawScreen_CopyToImage (TFB_Image *img, RECT *lpRect, SCREEN src)
|
||||
TFB_DrawScreen_CopyToImage (TFB_Image *img, const RECT *r, SCREEN src)
|
||||
{
|
||||
TFB_DrawCommand DC;
|
||||
|
||||
DC.Type = TFB_DRAWCOMMANDTYPE_COPYTOIMAGE;
|
||||
DC.data.copytoimage.x = lpRect->corner.x;
|
||||
DC.data.copytoimage.y = lpRect->corner.y;
|
||||
DC.data.copytoimage.w = lpRect->extent.width;
|
||||
DC.data.copytoimage.h = lpRect->extent.height;
|
||||
DC.data.copytoimage.rect = *r;
|
||||
DC.data.copytoimage.image = img;
|
||||
DC.data.copytoimage.srcBuffer = src;
|
||||
|
||||
@@ -130,7 +127,7 @@ TFB_DrawScreen_CopyToImage (TFB_Image *img, RECT *lpRect, SCREEN src)
|
||||
}
|
||||
|
||||
void
|
||||
TFB_DrawScreen_Copy (RECT *r, SCREEN src, SCREEN dest)
|
||||
TFB_DrawScreen_Copy (const RECT *r, SCREEN src, SCREEN dest)
|
||||
{
|
||||
RECT locRect;
|
||||
TFB_DrawCommand DC;
|
||||
@@ -144,10 +141,7 @@ TFB_DrawScreen_Copy (RECT *r, SCREEN src, SCREEN dest)
|
||||
}
|
||||
|
||||
DC.Type = TFB_DRAWCOMMANDTYPE_COPY;
|
||||
DC.data.copy.x = r->corner.x;
|
||||
DC.data.copy.y = r->corner.y;
|
||||
DC.data.copy.w = r->extent.width;
|
||||
DC.data.copy.h = r->extent.height;
|
||||
DC.data.copy.rect = *r;
|
||||
DC.data.copy.srcBuffer = src;
|
||||
DC.data.copy.destBuffer = dest;
|
||||
|
||||
|
||||
@@ -83,13 +83,13 @@ void TFB_DrawScreen_Line (int x1, int y1, int x2, int y2, Color color,
|
||||
void TFB_DrawScreen_Rect (RECT *rect, Color color, SCREEN dest);
|
||||
void TFB_DrawScreen_Image (TFB_Image *img, int x, int y, int scale,
|
||||
int scaleMode, TFB_ColorMap *cmap, SCREEN dest);
|
||||
void TFB_DrawScreen_Copy (RECT *r, SCREEN src, SCREEN dest);
|
||||
void TFB_DrawScreen_Copy (const RECT *r, SCREEN src, SCREEN dest);
|
||||
void TFB_DrawScreen_FilledImage (TFB_Image *img, int x, int y, int scale,
|
||||
int scaleMode, Color color, SCREEN dest);
|
||||
void TFB_DrawScreen_FontChar (TFB_Char *, TFB_Image *backing, int x, int y,
|
||||
SCREEN dest);
|
||||
|
||||
void TFB_DrawScreen_CopyToImage (TFB_Image *img, RECT *lpRect, SCREEN src);
|
||||
void TFB_DrawScreen_CopyToImage (TFB_Image *img, const RECT *r, SCREEN src);
|
||||
void TFB_DrawScreen_SetMipmap (TFB_Image *img, TFB_Image *mmimg, int hotx,
|
||||
int hoty);
|
||||
void TFB_DrawScreen_DeleteImage (TFB_Image *img);
|
||||
@@ -139,6 +139,7 @@ void TFB_DrawCanvas_Rotate (TFB_Canvas src, TFB_Canvas dst, int angle,
|
||||
EXTENT size);
|
||||
void TFB_DrawCanvas_GetRotatedExtent (TFB_Canvas src, int angle, EXTENT *size);
|
||||
void TFB_DrawCanvas_GetExtent (TFB_Canvas canvas, EXTENT *size);
|
||||
void TFB_DrawCanvas_SetClipRect (TFB_Canvas canvas, const RECT *clipRect);
|
||||
|
||||
void TFB_DrawCanvas_Delete (TFB_Canvas canvas);
|
||||
|
||||
@@ -151,6 +152,8 @@ void TFB_DrawCanvas_FilledImage (TFB_Image *img, int x, int y, int scale,
|
||||
int scaleMode, Color color, TFB_Canvas target);
|
||||
void TFB_DrawCanvas_FontChar (TFB_Char *, TFB_Image *backing, int x, int y,
|
||||
TFB_Canvas target);
|
||||
void TFB_DrawCanvas_CopyRect (TFB_Canvas source, const RECT *srcRect,
|
||||
TFB_Canvas target, POINT dstPt);
|
||||
|
||||
Color *TFB_DrawCanvas_ExtractPalette (TFB_Canvas canvas);
|
||||
void TFB_DrawCanvas_SetPalette (TFB_Canvas target, Color palette[256]);
|
||||
|
||||
Reference in New Issue
Block a user