Migrate FlashContext to the new drawing modes; also remove FlashContext.parent; drawing to off-screen CONTEXTs is incomplete

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3486 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
avolkov
2009-12-28 17:26:54 +00:00
parent 218e623b39
commit 4b0f227bd0
4 changed files with 109 additions and 113 deletions
+90 -105
View File
@@ -19,10 +19,6 @@
// currently in use. // currently in use.
// TODO: // TODO:
// - Add Flash_setHighlight() to change the brightness as in
// Flash_createHighlight(), for an already created flash area.
// - Be able to set a minimum and maximum merge factor for overlay and
// transition areas, as the numer/denom with highlights.
// - During a few frames during the sequence, the frame to be displayed // - During a few frames during the sequence, the frame to be displayed
// is equal to a frame which was supplied as a parameter to the flash // is equal to a frame which was supplied as a parameter to the flash
// sequence (instead of generated during the sequence). It is not // sequence (instead of generated during the sequence). It is not
@@ -41,10 +37,7 @@
#include "libs/threadlib.h" #include "libs/threadlib.h"
extern void arith_frame_blit (FRAME srcFrame, const RECT *rsrc, static FlashContext *Flash_create (CONTEXT gfxContext);
FRAME dstFrame, const RECT *rdst, int num, int denom);
static FlashContext *Flash_create (CONTEXT gfxContext, FRAME parent);
static void Flash_fixState (FlashContext *context); static void Flash_fixState (FlashContext *context);
static void Flash_nextState (FlashContext *context); static void Flash_nextState (FlashContext *context);
static void Flash_clearCache (FlashContext *context); static void Flash_clearCache (FlashContext *context);
@@ -53,7 +46,7 @@ static void Flash_grabOriginal (FlashContext *context);
static void Flash_blendFraction (FlashContext *context, int numer, int denom, static void Flash_blendFraction (FlashContext *context, int numer, int denom,
int *resNumer, int *resDenom); int *resNumer, int *resDenom);
static void Flash_makeFrame (FlashContext *context, static void Flash_makeFrame (FlashContext *context,
FRAME dest, RECT *destRect, int numer, int denom); FRAME dest, int numer, int denom);
static inline void Flash_prepareCacheFrame (FlashContext *context, static inline void Flash_prepareCacheFrame (FlashContext *context,
COUNT index); COUNT index);
static void Flash_drawFrame (FlashContext *context, FRAME frame); static void Flash_drawFrame (FlashContext *context, FRAME frame);
@@ -64,13 +57,15 @@ static inline void Flash_drawCachedFrame (FlashContext *context,
int numer, int denom); int numer, int denom);
static void Flash_drawCurrentFrame (FlashContext *context); static void Flash_drawCurrentFrame (FlashContext *context);
static CONTEXT workGfxContext;
// Off-screen internal drawing context
static FlashContext * static FlashContext *
Flash_create (CONTEXT gfxContext, FRAME parent) Flash_create (CONTEXT gfxContext)
{ {
FlashContext *context = HMalloc (sizeof (FlashContext)); FlashContext *context = HMalloc (sizeof (FlashContext));
context->gfxContext = gfxContext; context->gfxContext = gfxContext;
context->parent = parent;
context->original = 0; context->original = 0;
@@ -96,7 +91,11 @@ Flash_create (CONTEXT gfxContext, FRAME parent)
context->cacheSize = Flash_DEFAULT_CACHE_SIZE; context->cacheSize = Flash_DEFAULT_CACHE_SIZE;
context->lastFrameIndex = (COUNT) -1; context->lastFrameIndex = (COUNT) -1;
// TODO: Delete the context somewhere
if (!workGfxContext)
workGfxContext = CreateContext ("Flash.workGfxContext");
return context; return context;
} }
@@ -104,9 +103,9 @@ Flash_create (CONTEXT gfxContext, FRAME parent)
// 'endNumer / denom' is the brightness in the end state of the sequence. // 'endNumer / denom' is the brightness in the end state of the sequence.
// These numbers are relative to the brighness of the original image. // These numbers are relative to the brighness of the original image.
FlashContext * FlashContext *
Flash_createHighlight (CONTEXT gfxContext, FRAME parent, const RECT *rect) Flash_createHighlight (CONTEXT gfxContext, const RECT *rect)
{ {
FlashContext *context = Flash_create (gfxContext, parent); FlashContext *context = Flash_create (gfxContext);
if (rect == NULL) if (rect == NULL)
{ {
@@ -125,10 +124,10 @@ Flash_createHighlight (CONTEXT gfxContext, FRAME parent, const RECT *rect)
} }
FlashContext * FlashContext *
Flash_createTransition (CONTEXT gfxContext, FRAME parent, Flash_createTransition (CONTEXT gfxContext, const POINT *origin,
const POINT *origin, FRAME first, FRAME final) FRAME first, FRAME final)
{ {
FlashContext *context = Flash_create (gfxContext, parent); FlashContext *context = Flash_create (gfxContext);
context->type = FlashType_transition; context->type = FlashType_transition;
@@ -141,10 +140,9 @@ Flash_createTransition (CONTEXT gfxContext, FRAME parent,
} }
FlashContext * FlashContext *
Flash_createOverlay (CONTEXT gfxContext, FRAME parent, Flash_createOverlay (CONTEXT gfxContext, const POINT *origin, FRAME overlay)
const POINT *origin, FRAME overlay)
{ {
FlashContext *context = Flash_create (gfxContext, parent); FlashContext *context = Flash_create (gfxContext);
context->type = FlashType_overlay; context->type = FlashType_overlay;
@@ -361,7 +359,8 @@ Flash_setMergeFactors(FlashContext *context, int startNumer, int endNumer,
// Set the time between updates of the flash area. // Set the time between updates of the flash area.
void void
Flash_setFrameTime (FlashContext *context, TimeCount frameTime) { Flash_setFrameTime (FlashContext *context, TimeCount frameTime)
{
context->frameTime = frameTime; context->frameTime = frameTime;
} }
@@ -451,8 +450,8 @@ Flash_getRect (FlashContext *context, RECT *rect)
} }
void void
Flash_setOverlay (FlashContext *context, const POINT *origin, Flash_setOverlay (FlashContext *context, const POINT *origin, FRAME overlay)
FRAME overlay) { {
assert(context->type == FlashType_overlay); assert(context->type == FlashType_overlay);
if (context->started) if (context->started)
@@ -533,32 +532,33 @@ Flash_getCacheSize (const FlashContext *context)
static void static void
Flash_grabOriginal (FlashContext *context) Flash_grabOriginal (FlashContext *context)
{ {
CONTEXT oldGfxContext;
RECT clipRect;
RECT grabRect;
if (context->original != (FRAME) 0) if (context->original != (FRAME) 0)
DestroyDrawable (ReleaseDrawable (context->original)); DestroyDrawable (ReleaseDrawable (context->original));
if (context->parent == 0) // XXX: This assumes that FlashContext.gfxContext is an on-screen CONTEXT
{ // (i.e. it's foreground frame is Screen). LoadDisplayPixmap() would
// Grab from the entire screen // not work with an off-screen context.
CONTEXT oldGfxContext; // TODO: Get rid of LoadDisplayPixmap(). It does not take CONTEXT
LockMutex (GraphicsLock); // clip-rect into account.
oldGfxContext = SetContext (context->gfxContext); LockMutex (GraphicsLock);
context->original = CaptureDrawable (LoadDisplayPixmap ( oldGfxContext = SetContext (context->gfxContext);
&context->rect, (FRAME) 0)); // FlashContext.rect is relative to the CONTEXT clip-rect
SetContext (oldGfxContext); grabRect = context->rect;
UnlockMutex (GraphicsLock); GetContextClipRect (&clipRect);
FlushGraphics (); grabRect.corner.x += clipRect.corner.x;
// LoadDisplayPixmap only queues the command to read grabRect.corner.y += clipRect.corner.y;
// a rectangle from the screen; a FlushGraphics() context->original = CaptureDrawable (LoadDisplayPixmap (
// is necessary to ensure that it can actually be used. &grabRect, (FRAME) 0));
} SetContext (oldGfxContext);
else UnlockMutex (GraphicsLock);
{ FlushGraphics ();
// Grab from a frame. // LoadDisplayPixmap only queues the command to read
context->original = CaptureDrawable (CreateDrawable (WANT_PIXMAP, // a rectangle from the screen; a FlushGraphics()
context->rect.extent.width, context->rect.extent.height, 1)); // is necessary to ensure that it can actually be used.
arith_frame_blit (context->parent, &context->rect,
context->original, NULL, 1, 1);
}
} }
static inline void static inline void
@@ -582,24 +582,33 @@ Flash_blendFraction (FlashContext *context, int numer, int denom,
} }
static void static void
Flash_makeFrame (FlashContext *context, FRAME dest, RECT *destRect, Flash_makeFrame (FlashContext *context, FRAME dest, int numer, int denom)
int numer, int denom)
{ {
RECT orgRect; CONTEXT oldGfxContext;
STAMP s;
int blendedNumer; int blendedNumer;
int blendedDenom; int blendedDenom;
orgRect.corner.x = 0; s.origin.x = 0;
orgRect.corner.y = 0; s.origin.y = 0;
orgRect.extent = context->rect.extent;
Flash_blendFraction (context, numer, denom, &blendedNumer, &blendedDenom); Flash_blendFraction (context, numer, denom, &blendedNumer, &blendedDenom);
LockMutex (GraphicsLock);
oldGfxContext = SetContext (workGfxContext);
SetContextFGFrame (dest);
switch (context->type) { switch (context->type) {
case FlashType_highlight: case FlashType_highlight:
{ {
arith_frame_blit (context->original, &orgRect, dest, destRect, // Clear the destination just in case
blendedNumer, blendedDenom); SetContextBackGroundColor (BUILD_COLOR_RGBA (0, 0, 0, 0));
ClearDrawable ();
// Draw the frame at modulated strength (0 < strength <= 128)
SetContextDrawMode (MAKE_DRAW_MODE (DRAW_ADDITIVE,
DRAW_FACTOR_1 * blendedNumer / blendedDenom));
s.frame = context->original;
DrawStamp (&s);
break; break;
} }
case FlashType_transition: case FlashType_transition:
@@ -614,42 +623,39 @@ Flash_makeFrame (FlashContext *context, FRAME dest, RECT *destRect,
if (final == (FRAME) 0) if (final == (FRAME) 0)
final = context->original; final = context->original;
arith_frame_blit (first, &orgRect, dest, destRect, // Draw the first frame at full strength
blendedDenom - blendedNumer, blendedDenom); SetContextDrawMode (DRAW_REPLACE_MODE);
arith_frame_blit (final, &orgRect, dest, destRect, s.frame = first;
blendedNumer, -blendedDenom); DrawStamp (&s);
// Merge in the final frame
SetContextDrawMode (MAKE_DRAW_MODE (DRAW_ALPHA,
DRAW_FACTOR_1 * blendedNumer / blendedDenom));
s.frame = final;
DrawStamp (&s);
break; break;
} }
case FlashType_overlay: case FlashType_overlay:
{ {
int addOrSubtractNumer; POINT oldOrigin;
int addOrSubtractDenom;
if (blendedNumer < 0)
{
// Subtractive blit.
blendedNumer = -blendedNumer;
addOrSubtractNumer = -1;
addOrSubtractDenom = 1;
}
else
{
// Additive blit.
addOrSubtractNumer = 1;
addOrSubtractDenom = -1;
}
// Draw the overlay at partial strength: // Draw the original at full strength
arith_frame_blit (context->u.overlay.frame, &orgRect, SetContextDrawMode (DRAW_REPLACE_MODE);
dest, destRect, blendedNumer, blendedDenom); s.frame = context->original;
DrawStamp (&s);
// Merge the original in at full strength: // Add or subtract the overlay at partial strength
// For additive blit: dest = context->original + dest SetContextDrawMode (MAKE_DRAW_MODE (DRAW_ADDITIVE,
// For subtractive blit blit: dest = context->original - dest DRAW_FACTOR_1 * blendedNumer / blendedDenom));
arith_frame_blit (context->original, &orgRect, dest, destRect, s.frame = context->u.overlay.frame;
addOrSubtractNumer, addOrSubtractDenom); // Offset the draw origin to hit the right area
oldOrigin = SetContextOrigin (GetFrameHot (s.frame));
DrawStamp (&s);
SetContextOrigin (oldOrigin);
break; break;
} }
} }
SetContext (oldGfxContext);
UnlockMutex (GraphicsLock);
} }
// Prepare an entry in the cache. // Prepare an entry in the cache.
@@ -674,7 +680,7 @@ Flash_prepareCacheFrame (FlashContext *context, COUNT index)
{ {
context->cache[index] = CaptureDrawable (CreateDrawable (WANT_PIXMAP, context->cache[index] = CaptureDrawable (CreateDrawable (WANT_PIXMAP,
context->rect.extent.width, context->rect.extent.height, 1)); context->rect.extent.width, context->rect.extent.height, 1));
Flash_makeFrame (context, context->cache[index], NULL, Flash_makeFrame (context, context->cache[index],
index, context->cacheSize - 1); index, context->cacheSize - 1);
} }
} }
@@ -683,20 +689,15 @@ static void
Flash_drawFrame (FlashContext *context, FRAME frame) Flash_drawFrame (FlashContext *context, FRAME frame)
{ {
CONTEXT oldGfxContext; CONTEXT oldGfxContext;
FRAME oldFGFrame = (FRAME) 0;
STAMP stamp; STAMP stamp;
LockMutex (GraphicsLock); LockMutex (GraphicsLock);
oldGfxContext = SetContext (context->gfxContext); oldGfxContext = SetContext (context->gfxContext);
if (context->parent != NULL)
oldFGFrame = SetContextFGFrame (context->parent);
stamp.origin = context->rect.corner; stamp.origin = context->rect.corner;
stamp.frame = frame; stamp.frame = frame;
DrawStamp(&stamp); DrawStamp(&stamp);
if (context->parent != NULL)
SetContextFGFrame (oldFGFrame);
SetContext (oldGfxContext); SetContext (oldGfxContext);
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
} }
@@ -752,33 +753,17 @@ Flash_drawUncachedFrame (FlashContext *context, int numer, int denom)
context->lastFrameIndex = 2; context->lastFrameIndex = 2;
#endif /* BEGIN_AND_END_FRMAE_EXCEPTIONS */ #endif /* BEGIN_AND_END_FRMAE_EXCEPTIONS */
if (context->parent == NULL)
{ {
// Painting to the screen; we need a temporary frame to draw to. // Painting to the screen; we need a temporary frame to draw to.
FRAME work; FRAME work;
work = CaptureDrawable (CreateDrawable (WANT_PIXMAP, work = CaptureDrawable (CreateDrawable (WANT_PIXMAP,
context->rect.extent.width, context->rect.extent.height, 1)); context->rect.extent.width, context->rect.extent.height, 1));
Flash_makeFrame (context, work, NULL, numer, denom); Flash_makeFrame (context, work, numer, denom);
Flash_drawFrame (context, work); Flash_drawFrame (context, work);
DestroyDrawable (ReleaseDrawable (work)); DestroyDrawable (ReleaseDrawable (work));
} }
else
{
// Painting to another frame; we can directly draw to it.
CONTEXT oldGfxContext;
FRAME oldFGFrame;
LockMutex (GraphicsLock);
oldGfxContext = SetContext (context->gfxContext);
oldFGFrame = SetContextFGFrame (context->parent);
Flash_makeFrame (context, context->parent, &context->rect,
numer, denom);
SetContextFGFrame (oldFGFrame);
SetContext (oldGfxContext);
UnlockMutex (GraphicsLock);
}
} }
static inline void static inline void
+17 -6
View File
@@ -76,6 +76,20 @@
* You can use Flash_nextTime() to determine when the next update is needed, * You can use Flash_nextTime() to determine when the next update is needed,
* or just call Flash_process() to try (it does no updates if not needed). * or just call Flash_process() to try (it does no updates if not needed).
* *
* Limitations:
*
* 1) Highlight and overlay flashing modes read the original gfxContext
* contents, but they do so with LoadDisplayPixmap(). This means that these
* modes can currently only be used with on-screen CONTEXTs (i.e. CONTEXTs
* that have Screen as foreground FRAME);
*
* 2) Functions that draw to the gfxContext or read the original gfxContext
* contents, which is most of them, must be called with gfxContext having
* the same clip-rect as it did when other drawing functions were called.
* Otherwise, original contents restoration may draw to the wrong area, or
* the wrong area may be read.
* There may be cases where one would *want* that to happen, and such
* cases are not covered by this limitation.
*/ */
#include "libs/gfxlib.h" #include "libs/gfxlib.h"
@@ -104,8 +118,6 @@ typedef enum {
struct FlashContext { struct FlashContext {
CONTEXT gfxContext; CONTEXT gfxContext;
// The graphics context used for drawing. // The graphics context used for drawing.
FRAME parent;
// The frame that contains the flash rectangle.
RECT rect; RECT rect;
// The rectangle to flash. // The rectangle to flash.
@@ -175,11 +187,10 @@ struct FlashContext {
#endif /* FLASH_INTERNAL */ #endif /* FLASH_INTERNAL */
FlashContext *Flash_createHighlight (CONTEXT gfxContext, FRAME parent, FlashContext *Flash_createHighlight (CONTEXT gfxContext, const RECT *rect);
const RECT *rect); FlashContext *Flash_createTransition (CONTEXT gfxContext,
FlashContext *Flash_createTransition (CONTEXT gfxContext, FRAME parent,
const POINT *origin, FRAME first, FRAME final); const POINT *origin, FRAME first, FRAME final);
FlashContext *Flash_createOverlay (CONTEXT gfxContext, FRAME parent, FlashContext *Flash_createOverlay (CONTEXT gfxContext,
const POINT *origin, FRAME overlay); const POINT *origin, FRAME overlay);
void Flash_setState (FlashContext *context, FlashState state, void Flash_setState (FlashContext *context, FlashState state,
+1 -1
View File
@@ -128,7 +128,7 @@ DoRestart (MENU_STATE *pMS)
pMS->hMusic = LoadMusic (MAINMENU_MUSIC); pMS->hMusic = LoadMusic (MAINMENU_MUSIC);
InactTimeOut = (pMS->hMusic ? 120 : 20) * ONE_SECOND; InactTimeOut = (pMS->hMusic ? 120 : 20) * ONE_SECOND;
pMS->flashContext = Flash_createOverlay (ScreenContext, pMS->flashContext = Flash_createOverlay (ScreenContext,
NULL, NULL, NULL); NULL, NULL);
Flash_setMergeFactors (pMS->flashContext, -3, 3, 16); Flash_setMergeFactors (pMS->flashContext, -3, 3, 16);
Flash_setSpeed (pMS->flashContext, (6 * ONE_SECOND) / 16, 0, Flash_setSpeed (pMS->flashContext, (6 * ONE_SECOND) / 16, 0,
(6 * ONE_SECOND) / 16, 0); (6 * ONE_SECOND) / 16, 0);
+1 -1
View File
@@ -580,7 +580,7 @@ GetMeleeStarShips (COUNT playerMask, HSTARSHIP *ships)
#endif #endif
gmstate.player[playerI].flashContext = gmstate.player[playerI].flashContext =
Flash_createHighlight (ScreenContext, (FRAME) 0, NULL); Flash_createHighlight (ScreenContext, NULL);
Flash_setMergeFactors (gmstate.player[playerI].flashContext, Flash_setMergeFactors (gmstate.player[playerI].flashContext,
2, 3, 2); 2, 3, 2);
Flash_setFrameTime (gmstate.player[playerI].flashContext, Flash_setFrameTime (gmstate.player[playerI].flashContext,