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/drawable.h"
|
||||||
#include "libs/graphics/context.h"
|
#include "libs/graphics/context.h"
|
||||||
#include "libs/graphics/dcqueue.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/log.h"
|
||||||
#include "libs/misc.h"
|
#include "libs/misc.h"
|
||||||
// for TFB_DEBUG_HALT
|
// for TFB_DEBUG_HALT
|
||||||
@@ -33,6 +36,10 @@ TFB_DrawCommand DCQ[DCQ_MAX];
|
|||||||
|
|
||||||
TFB_DrawCommandQueue DrawCommandQueue;
|
TFB_DrawCommandQueue DrawCommandQueue;
|
||||||
|
|
||||||
|
#define FPS_PERIOD (ONE_SECOND / 100)
|
||||||
|
int RenderedFrames = 0;
|
||||||
|
|
||||||
|
|
||||||
// Wait for the queue to be emptied.
|
// Wait for the queue to be emptied.
|
||||||
static void
|
static void
|
||||||
TFB_WaitForSpace (int requested_slots)
|
TFB_WaitForSpace (int requested_slots)
|
||||||
@@ -137,12 +144,19 @@ Init_DrawCommandQueue (void)
|
|||||||
DrawCommandQueue.FullSize = 0;
|
DrawCommandQueue.FullSize = 0;
|
||||||
DrawCommandQueue.Size = 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
|
void
|
||||||
Uninit_DrawCommandQueue (void)
|
Uninit_DrawCommandQueue (void)
|
||||||
{
|
{
|
||||||
|
DestroyCondVar (RenderingCond);
|
||||||
DestroyRecursiveMutex (DCQ_Mutex);
|
DestroyRecursiveMutex (DCQ_Mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,3 +259,328 @@ TFB_EnqueueDrawCommand (TFB_DrawCommand* DrawCommand)
|
|||||||
TFB_DrawCommandQueue_Push (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
|
typedef struct tfb_dc_copy
|
||||||
{
|
{
|
||||||
int x, y, w, h;
|
RECT rect;
|
||||||
SCREEN srcBuffer, destBuffer;
|
SCREEN srcBuffer, destBuffer;
|
||||||
} TFB_DrawCommand_Copy;
|
} TFB_DrawCommand_Copy;
|
||||||
|
|
||||||
typedef struct tfb_dc_copyimg
|
typedef struct tfb_dc_copyimg
|
||||||
{
|
{
|
||||||
TFB_Image *image;
|
TFB_Image *image;
|
||||||
int x, y, w, h;
|
RECT rect;
|
||||||
SCREEN srcBuffer;
|
SCREEN srcBuffer;
|
||||||
} TFB_DrawCommand_CopyToImage;
|
} TFB_DrawCommand_CopyToImage;
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "gfxintrn.h"
|
#include "gfxintrn.h"
|
||||||
#include "libs/graphics/gfx_common.h"
|
#include "libs/graphics/gfx_common.h"
|
||||||
#include "libs/graphics/drawcmd.h"
|
#include "libs/graphics/drawcmd.h"
|
||||||
|
#include "libs/timelib.h"
|
||||||
#include "libs/misc.h"
|
#include "libs/misc.h"
|
||||||
// for TFB_DEBUG_HALT
|
// for TFB_DEBUG_HALT
|
||||||
|
|
||||||
@@ -35,6 +36,9 @@ int ScreenColorDepth;
|
|||||||
int GraphicsDriver;
|
int GraphicsDriver;
|
||||||
int TFB_DEBUG_HALT = 0;
|
int TFB_DEBUG_HALT = 0;
|
||||||
|
|
||||||
|
volatile int TransitionAmount = 255;
|
||||||
|
RECT TransitionClipRect;
|
||||||
|
|
||||||
static int gscale = GSCALE_IDENTITY;
|
static int gscale = GSCALE_IDENTITY;
|
||||||
static int gscale_mode = TFB_SCALE_NEAREST;
|
static int gscale_mode = TFB_SCALE_NEAREST;
|
||||||
|
|
||||||
@@ -78,3 +82,119 @@ GetGraphicScaleMode (void)
|
|||||||
{
|
{
|
||||||
return gscale_mode;
|
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
|
// The flag variable itself
|
||||||
extern int GfxFlags;
|
extern int GfxFlags;
|
||||||
|
|
||||||
|
// The following functions are driver-defined
|
||||||
void TFB_PreInit (void);
|
void TFB_PreInit (void);
|
||||||
int TFB_InitGraphics (int driver, int flags, int width, int height);
|
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_UninitGraphics (void);
|
||||||
void TFB_ProcessEvents (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
|
#define GSCALE_IDENTITY 256
|
||||||
|
|
||||||
@@ -81,17 +87,18 @@ int SetGraphicScale (int scale);
|
|||||||
int GetGraphicScale (void);
|
int GetGraphicScale (void);
|
||||||
int SetGraphicScaleMode (int mode /* enum SCALE */);
|
int SetGraphicScaleMode (int mode /* enum SCALE */);
|
||||||
int GetGraphicScaleMode (void);
|
int GetGraphicScaleMode (void);
|
||||||
void SetTransitionSource (RECT *pRect);
|
void SetTransitionSource (const RECT *pRect);
|
||||||
void ScreenTransition (int transition, 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 float FrameRate;
|
||||||
extern int FrameRateTickBase;
|
extern int FrameRateTickBase;
|
||||||
|
|
||||||
void TFB_FlushGraphics (void); // Only call from main thread!!
|
void TFB_FlushGraphics (void); // Only call from main thread!!
|
||||||
|
|
||||||
void TFB_SetGamma (float gamma);
|
|
||||||
// Unknown Stuff
|
|
||||||
|
|
||||||
extern int ScreenWidth;
|
extern int ScreenWidth;
|
||||||
extern int ScreenHeight;
|
extern int ScreenHeight;
|
||||||
extern int ScreenWidthActual;
|
extern int ScreenWidthActual;
|
||||||
|
|||||||
@@ -26,9 +26,6 @@
|
|||||||
#include "libs/graphics/tfb_draw.h"
|
#include "libs/graphics/tfb_draw.h"
|
||||||
|
|
||||||
|
|
||||||
int batch_depth = 0;
|
|
||||||
|
|
||||||
|
|
||||||
//Status: Not entirely unimplemented!
|
//Status: Not entirely unimplemented!
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
InitGraphics (int argc, char* argv[], COUNT KbytesRequired)
|
InitGraphics (int argc, char* argv[], COUNT KbytesRequired)
|
||||||
@@ -57,130 +54,6 @@ UninitGraphics () // Also probably empty
|
|||||||
//mem_uninit ();
|
//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
|
BOOLEAN
|
||||||
_image_intersect (IMAGE_BOX *box1, IMAGE_BOX *box2, RECT *rect)
|
_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;
|
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;
|
SDL_Surface *format_conv_surf = NULL;
|
||||||
|
|
||||||
volatile int TransitionAmount = 255;
|
|
||||||
SDL_Rect TransitionClipRect;
|
|
||||||
static volatile BOOLEAN abortFlag = FALSE;
|
static volatile BOOLEAN abortFlag = FALSE;
|
||||||
|
|
||||||
int GfxFlags = 0;
|
int GfxFlags = 0;
|
||||||
|
|
||||||
TFB_GRAPHICS_BACKEND *graphics_backend = NULL;
|
TFB_GRAPHICS_BACKEND *graphics_backend = NULL;
|
||||||
|
|
||||||
#define FPS_PERIOD 100
|
|
||||||
int RenderedFrames = 0;
|
|
||||||
|
|
||||||
volatile int QuitPosted = 0;
|
volatile int QuitPosted = 0;
|
||||||
volatile int GameActive = 1; // Track the SDL_ACTIVEEVENT state SDL_APPACTIVE
|
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 ();
|
Init_DrawCommandQueue ();
|
||||||
|
|
||||||
TFB_DrawCanvas_Initialize ();
|
TFB_DrawCanvas_Initialize ();
|
||||||
TFB_BBox_Init (ScreenWidth, ScreenHeight);
|
|
||||||
|
|
||||||
RenderingCond = CreateCondVar ("DCQ empty",
|
|
||||||
SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO);
|
|
||||||
|
|
||||||
atexit (TFB_UninitGraphics);
|
atexit (TFB_UninitGraphics);
|
||||||
|
|
||||||
@@ -277,8 +268,13 @@ TFB_SwapBuffers (int force_full_redraw)
|
|||||||
|
|
||||||
if (transition_amount != 255)
|
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,
|
graphics_backend->screen (TFB_SCREEN_TRANSITION,
|
||||||
255 - transition_amount, &TransitionClipRect);
|
255 - transition_amount, &r);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fade_amount != 255)
|
if (fade_amount != 255)
|
||||||
@@ -339,7 +335,7 @@ TFB_DisplayFormatAlpha (SDL_Surface *surface)
|
|||||||
TFB_Canvas
|
TFB_Canvas
|
||||||
TFB_GetScreenCanvas (SCREEN screen)
|
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,
|
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
|
void
|
||||||
TFB_ComputeFPS (void)
|
TFB_UploadTransitionScreen (void)
|
||||||
{
|
{
|
||||||
static Uint32 last_time = 0, fps_counter = 0;
|
#ifdef HAVE_OPENGL
|
||||||
Uint32 current_time, delta_time;
|
if (GraphicsDriver == TFB_GFXDRIVER_SDL_OPENGL)
|
||||||
|
|
||||||
current_time = SDL_GetTicks ();
|
|
||||||
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",
|
TFB_GL_UploadTransitionScreen ();
|
||||||
1000.0 / delta_time,
|
|
||||||
1000.0 * RenderedFrames / fps_counter);
|
|
||||||
|
|
||||||
fps_counter = 0;
|
|
||||||
RenderedFrames = 0;
|
|
||||||
}
|
}
|
||||||
}
|
#endif
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -46,13 +46,9 @@ extern SDL_Surface *SDL_Screens[TFB_GFX_NUMSCREENS];
|
|||||||
|
|
||||||
extern SDL_Surface *format_conv_surf;
|
extern SDL_Surface *format_conv_surf;
|
||||||
|
|
||||||
extern volatile int TransitionAmount;
|
|
||||||
extern SDL_Rect TransitionClipRect;
|
|
||||||
|
|
||||||
void ScreenOrigin (FRAME Display, COORD sx, COORD sy);
|
void ScreenOrigin (FRAME Display, COORD sx, COORD sy);
|
||||||
void LoadDisplay (DISPLAY_INTERFACE **pDisplay);
|
void LoadDisplay (DISPLAY_INTERFACE **pDisplay);
|
||||||
|
|
||||||
void TFB_SwapBuffers (int force_full_redraw);
|
|
||||||
SDL_Surface* TFB_DisplayFormatAlpha (SDL_Surface *surface);
|
SDL_Surface* TFB_DisplayFormatAlpha (SDL_Surface *surface);
|
||||||
void TFB_BlitSurface (SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst,
|
void TFB_BlitSurface (SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst,
|
||||||
SDL_Rect *dstrect, int blend_numer, int blend_denom);
|
SDL_Rect *dstrect, int blend_numer, int blend_denom);
|
||||||
|
|||||||
@@ -114,15 +114,12 @@ TFB_DrawScreen_FontChar (TFB_Char *fontChar, TFB_Image *backing,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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;
|
TFB_DrawCommand DC;
|
||||||
|
|
||||||
DC.Type = TFB_DRAWCOMMANDTYPE_COPYTOIMAGE;
|
DC.Type = TFB_DRAWCOMMANDTYPE_COPYTOIMAGE;
|
||||||
DC.data.copytoimage.x = lpRect->corner.x;
|
DC.data.copytoimage.rect = *r;
|
||||||
DC.data.copytoimage.y = lpRect->corner.y;
|
|
||||||
DC.data.copytoimage.w = lpRect->extent.width;
|
|
||||||
DC.data.copytoimage.h = lpRect->extent.height;
|
|
||||||
DC.data.copytoimage.image = img;
|
DC.data.copytoimage.image = img;
|
||||||
DC.data.copytoimage.srcBuffer = src;
|
DC.data.copytoimage.srcBuffer = src;
|
||||||
|
|
||||||
@@ -130,7 +127,7 @@ TFB_DrawScreen_CopyToImage (TFB_Image *img, RECT *lpRect, SCREEN src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TFB_DrawScreen_Copy (RECT *r, SCREEN src, SCREEN dest)
|
TFB_DrawScreen_Copy (const RECT *r, SCREEN src, SCREEN dest)
|
||||||
{
|
{
|
||||||
RECT locRect;
|
RECT locRect;
|
||||||
TFB_DrawCommand DC;
|
TFB_DrawCommand DC;
|
||||||
@@ -144,10 +141,7 @@ TFB_DrawScreen_Copy (RECT *r, SCREEN src, SCREEN dest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
DC.Type = TFB_DRAWCOMMANDTYPE_COPY;
|
DC.Type = TFB_DRAWCOMMANDTYPE_COPY;
|
||||||
DC.data.copy.x = r->corner.x;
|
DC.data.copy.rect = *r;
|
||||||
DC.data.copy.y = r->corner.y;
|
|
||||||
DC.data.copy.w = r->extent.width;
|
|
||||||
DC.data.copy.h = r->extent.height;
|
|
||||||
DC.data.copy.srcBuffer = src;
|
DC.data.copy.srcBuffer = src;
|
||||||
DC.data.copy.destBuffer = dest;
|
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_Rect (RECT *rect, Color color, SCREEN dest);
|
||||||
void TFB_DrawScreen_Image (TFB_Image *img, int x, int y, int scale,
|
void TFB_DrawScreen_Image (TFB_Image *img, int x, int y, int scale,
|
||||||
int scaleMode, TFB_ColorMap *cmap, SCREEN dest);
|
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,
|
void TFB_DrawScreen_FilledImage (TFB_Image *img, int x, int y, int scale,
|
||||||
int scaleMode, Color color, SCREEN dest);
|
int scaleMode, Color color, SCREEN dest);
|
||||||
void TFB_DrawScreen_FontChar (TFB_Char *, TFB_Image *backing, int x, int y,
|
void TFB_DrawScreen_FontChar (TFB_Char *, TFB_Image *backing, int x, int y,
|
||||||
SCREEN dest);
|
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,
|
void TFB_DrawScreen_SetMipmap (TFB_Image *img, TFB_Image *mmimg, int hotx,
|
||||||
int hoty);
|
int hoty);
|
||||||
void TFB_DrawScreen_DeleteImage (TFB_Image *img);
|
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);
|
EXTENT size);
|
||||||
void TFB_DrawCanvas_GetRotatedExtent (TFB_Canvas src, 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_GetExtent (TFB_Canvas canvas, EXTENT *size);
|
||||||
|
void TFB_DrawCanvas_SetClipRect (TFB_Canvas canvas, const RECT *clipRect);
|
||||||
|
|
||||||
void TFB_DrawCanvas_Delete (TFB_Canvas canvas);
|
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);
|
int scaleMode, Color color, TFB_Canvas target);
|
||||||
void TFB_DrawCanvas_FontChar (TFB_Char *, TFB_Image *backing, int x, int y,
|
void TFB_DrawCanvas_FontChar (TFB_Char *, TFB_Image *backing, int x, int y,
|
||||||
TFB_Canvas target);
|
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);
|
Color *TFB_DrawCanvas_ExtractPalette (TFB_Canvas canvas);
|
||||||
void TFB_DrawCanvas_SetPalette (TFB_Canvas target, Color palette[256]);
|
void TFB_DrawCanvas_SetPalette (TFB_Canvas target, Color palette[256]);
|
||||||
|
|||||||
Reference in New Issue
Block a user