Added Uq-Ruan Masters game - it compiles but does not work (renders too slowly? Another problem?)
This commit is contained in:
589
project/jni/application/sc2/src/libs/graphics/dcqueue.c
Normal file
589
project/jni/application/sc2/src/libs/graphics/dcqueue.c
Normal file
@@ -0,0 +1,589 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "port.h"
|
||||
#include "libs/threadlib.h"
|
||||
#include "libs/graphics/drawcmd.h"
|
||||
#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
|
||||
|
||||
|
||||
static RecursiveMutex DCQ_Mutex;
|
||||
|
||||
CondVar RenderingCond;
|
||||
|
||||
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)
|
||||
{
|
||||
int old_depth, i;
|
||||
log_add (log_Debug, "DCQ overload (Size = %d, FullSize = %d, "
|
||||
"Requested = %d). Sleeping until renderer is done.",
|
||||
DrawCommandQueue.Size, DrawCommandQueue.FullSize,
|
||||
requested_slots);
|
||||
// Restore the DCQ locking level. I *think* this is
|
||||
// always 1, but...
|
||||
TFB_BatchReset ();
|
||||
old_depth = GetRecursiveMutexDepth (DCQ_Mutex);
|
||||
for (i = 0; i < old_depth; i++)
|
||||
UnlockRecursiveMutex (DCQ_Mutex);
|
||||
WaitCondVar (RenderingCond);
|
||||
for (i = 0; i < old_depth; i++)
|
||||
LockRecursiveMutex (DCQ_Mutex);
|
||||
log_add (log_Debug, "DCQ clear (Size = %d, FullSize = %d). Continuing.",
|
||||
DrawCommandQueue.Size, DrawCommandQueue.FullSize);
|
||||
}
|
||||
|
||||
void
|
||||
Lock_DCQ (int slots)
|
||||
{
|
||||
LockRecursiveMutex (DCQ_Mutex);
|
||||
while (DrawCommandQueue.FullSize >= DCQ_MAX - slots)
|
||||
{
|
||||
TFB_WaitForSpace (slots);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Unlock_DCQ (void)
|
||||
{
|
||||
UnlockRecursiveMutex (DCQ_Mutex);
|
||||
}
|
||||
|
||||
// Always have the DCQ locked when calling this.
|
||||
static void
|
||||
Synchronize_DCQ (void)
|
||||
{
|
||||
if (!DrawCommandQueue.Batching)
|
||||
{
|
||||
int front = DrawCommandQueue.Front;
|
||||
int back = DrawCommandQueue.InsertionPoint;
|
||||
DrawCommandQueue.Back = DrawCommandQueue.InsertionPoint;
|
||||
if (front <= back)
|
||||
{
|
||||
DrawCommandQueue.Size = (back - front);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawCommandQueue.Size = (back + DCQ_MAX - front);
|
||||
}
|
||||
DrawCommandQueue.FullSize = DrawCommandQueue.Size;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TFB_BatchGraphics (void)
|
||||
{
|
||||
LockRecursiveMutex (DCQ_Mutex);
|
||||
DrawCommandQueue.Batching++;
|
||||
UnlockRecursiveMutex (DCQ_Mutex);
|
||||
}
|
||||
|
||||
void
|
||||
TFB_UnbatchGraphics (void)
|
||||
{
|
||||
LockRecursiveMutex (DCQ_Mutex);
|
||||
if (DrawCommandQueue.Batching)
|
||||
{
|
||||
DrawCommandQueue.Batching--;
|
||||
}
|
||||
Synchronize_DCQ ();
|
||||
UnlockRecursiveMutex (DCQ_Mutex);
|
||||
}
|
||||
|
||||
// Cancel all pending batch operations, making them unbatched. This will
|
||||
// cause a small amount of flicker when invoked, but prevents
|
||||
// batching problems from freezing the game.
|
||||
void
|
||||
TFB_BatchReset (void)
|
||||
{
|
||||
LockRecursiveMutex (DCQ_Mutex);
|
||||
DrawCommandQueue.Batching = 0;
|
||||
Synchronize_DCQ ();
|
||||
UnlockRecursiveMutex (DCQ_Mutex);
|
||||
}
|
||||
|
||||
|
||||
// Draw Command Queue Stuff
|
||||
|
||||
void
|
||||
Init_DrawCommandQueue (void)
|
||||
{
|
||||
DrawCommandQueue.Back = 0;
|
||||
DrawCommandQueue.Front = 0;
|
||||
DrawCommandQueue.InsertionPoint = 0;
|
||||
DrawCommandQueue.Batching = 0;
|
||||
DrawCommandQueue.FullSize = 0;
|
||||
DrawCommandQueue.Size = 0;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
TFB_DrawCommandQueue_Push (TFB_DrawCommand* Command)
|
||||
{
|
||||
Lock_DCQ (1);
|
||||
DCQ[DrawCommandQueue.InsertionPoint] = *Command;
|
||||
DrawCommandQueue.InsertionPoint = (DrawCommandQueue.InsertionPoint + 1)
|
||||
% DCQ_MAX;
|
||||
DrawCommandQueue.FullSize++;
|
||||
Synchronize_DCQ ();
|
||||
Unlock_DCQ ();
|
||||
}
|
||||
|
||||
int
|
||||
TFB_DrawCommandQueue_Pop (TFB_DrawCommand *target)
|
||||
{
|
||||
LockRecursiveMutex (DCQ_Mutex);
|
||||
|
||||
if (DrawCommandQueue.Size == 0)
|
||||
{
|
||||
Unlock_DCQ ();
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (DrawCommandQueue.Front == DrawCommandQueue.Back &&
|
||||
DrawCommandQueue.Size != DCQ_MAX)
|
||||
{
|
||||
log_add (log_Debug, "Augh! Assertion failure in DCQ! "
|
||||
"Front == Back, Size != DCQ_MAX");
|
||||
DrawCommandQueue.Size = 0;
|
||||
Unlock_DCQ ();
|
||||
return (0);
|
||||
}
|
||||
|
||||
*target = DCQ[DrawCommandQueue.Front];
|
||||
DrawCommandQueue.Front = (DrawCommandQueue.Front + 1) % DCQ_MAX;
|
||||
|
||||
DrawCommandQueue.Size--;
|
||||
DrawCommandQueue.FullSize--;
|
||||
UnlockRecursiveMutex (DCQ_Mutex);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
TFB_DrawCommandQueue_Clear ()
|
||||
{
|
||||
LockRecursiveMutex (DCQ_Mutex);
|
||||
DrawCommandQueue.Size = 0;
|
||||
DrawCommandQueue.Front = 0;
|
||||
DrawCommandQueue.Back = 0;
|
||||
DrawCommandQueue.Batching = 0;
|
||||
DrawCommandQueue.FullSize = 0;
|
||||
DrawCommandQueue.InsertionPoint = 0;
|
||||
UnlockRecursiveMutex (DCQ_Mutex);
|
||||
}
|
||||
|
||||
void
|
||||
TFB_EnqueueDrawCommand (TFB_DrawCommand* DrawCommand)
|
||||
{
|
||||
if (TFB_DEBUG_HALT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (DrawCommand->Type <= TFB_DRAWCOMMANDTYPE_COPYTOIMAGE
|
||||
&& _CurFramePtr->Type == SCREEN_DRAWABLE)
|
||||
{
|
||||
static RECT scissor_rect;
|
||||
|
||||
// Set the clipping region.
|
||||
// We allow drawing with no current context set, so the whole screen
|
||||
if ((_pCurContext && !rectsEqual (scissor_rect, _pCurContext->ClipRect))
|
||||
|| (!_pCurContext && scissor_rect.extent.width != 0))
|
||||
{
|
||||
// Enqueue command to set the glScissor spec
|
||||
TFB_DrawCommand DC;
|
||||
|
||||
if (_pCurContext)
|
||||
scissor_rect = _pCurContext->ClipRect;
|
||||
else
|
||||
scissor_rect.extent.width = 0;
|
||||
|
||||
if (scissor_rect.extent.width)
|
||||
{
|
||||
DC.Type = TFB_DRAWCOMMANDTYPE_SCISSORENABLE;
|
||||
DC.data.scissor.rect = scissor_rect;
|
||||
}
|
||||
else
|
||||
{
|
||||
DC.Type = TFB_DRAWCOMMANDTYPE_SCISSORDISABLE;
|
||||
}
|
||||
|
||||
TFB_EnqueueDrawCommand(&DC);
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
cmd->drawMode,
|
||||
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,
|
||||
cmd->drawMode,
|
||||
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,
|
||||
cmd->drawMode, 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, cmd->drawMode,
|
||||
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, cmd->drawMode,
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user