From: <Mee...@us...> - 2012-01-23 20:14:52
|
Revision: 3749 http://sc2.svn.sourceforge.net/sc2/?rev=3749&view=rev Author: Meep-Eep Date: 2012-01-23 20:14:45 +0000 (Mon, 23 Jan 2012) Log Message: ----------- Switch SetFlashRect() to the new flash code, as the next step towards getting rid of threads. Also some small cleanups. Modified Paths: -------------- trunk/sc2/ChangeLog trunk/sc2/src/uqm/flash.c trunk/sc2/src/uqm/gameopt.c trunk/sc2/src/uqm/menu.c trunk/sc2/src/uqm/outfit.c trunk/sc2/src/uqm/planets/roster.c trunk/sc2/src/uqm/shipyard.c trunk/sc2/src/uqm/sis.c trunk/sc2/src/uqm/sis.h Modified: trunk/sc2/ChangeLog =================================================================== --- trunk/sc2/ChangeLog 2012-01-15 20:37:31 UTC (rev 3748) +++ trunk/sc2/ChangeLog 2012-01-23 20:14:45 UTC (rev 3749) @@ -1,4 +1,6 @@ Changes towards version 0.8: +- Switch SetFlashRect() to the new flash code -- SvdB +- Add C++ support to the build system, from Scott A. Colcord - Cleaning up DoModifyShips() - SvdB - Added Valgrind suppression file, from Louis Delacroix - Fix several memory leaks, from Loius Delacroix Modified: trunk/sc2/src/uqm/flash.c =================================================================== --- trunk/sc2/src/uqm/flash.c 2012-01-15 20:37:31 UTC (rev 3748) +++ trunk/sc2/src/uqm/flash.c 2012-01-23 20:14:45 UTC (rev 3749) @@ -18,6 +18,12 @@ // areas, drawing directly to the screen, using a cache, are // currently in use. +// NOTE: +// - If you change the properties of the original CONTEXT, specifically the +// dimensions and origin, you'll need to call Flash_preUpdate() before and +// Flash_postUpdate() after that change. Note that this may change which +// part of the screen is flashing. + // TODO: // - 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 @@ -472,7 +478,8 @@ } } -// Call before you update the graphics in the currently flashing area. +// Call before you update the graphics in the currently flashing area, +// or before you change the dimensions or origin of the graphics context. void Flash_preUpdate (FlashContext *context) { @@ -483,7 +490,8 @@ } } -// Call after you update the graphics in the currently flashing area. +// Call after you update the graphics in the currently flashing area, +// or after you change the dimensions or origin of the graphics context. void Flash_postUpdate (FlashContext *context) { @@ -803,5 +811,3 @@ Flash_drawCachedFrame (context, numer, denom); } - - Modified: trunk/sc2/src/uqm/gameopt.c =================================================================== --- trunk/sc2/src/uqm/gameopt.c 2012-01-15 20:37:31 UTC (rev 3748) +++ trunk/sc2/src/uqm/gameopt.c 2012-01-23 20:14:45 UTC (rev 3749) @@ -176,6 +176,26 @@ #define DDSHS_EDIT 1 #define DDSHS_BLOCKCUR 2 +static const RECT captainNameRect = { + /* .corner = */ { + /* .x = */ 3, + /* .y = */ 10 + }, /* .extent = */ { + /* .width = */ SHIP_NAME_WIDTH - 2, + /* .height = */ SHIP_NAME_HEIGHT + } +}; +static const RECT shipNameRect = { + /* .corner = */ { + /* .x = */ 2, + /* .y = */ 20 + }, /* .extent = */ { + /* .width = */ SHIP_NAME_WIDTH, + /* .height = */ SHIP_NAME_HEIGHT + } +}; + + static BOOLEAN DrawNameString (bool nameCaptain, UNICODE *Str, COUNT CursorPos, COUNT state) @@ -185,20 +205,11 @@ Color BackGround, ForeGround; FONT Font; - LockMutex (GraphicsLock); - { - r.corner.x = 2; - r.extent.width = SHIP_NAME_WIDTH; - r.extent.height = SHIP_NAME_HEIGHT; - - SetContext (StatusContext); if (nameCaptain) { // Naming the captain Font = TinyFont; - r.corner.y = 10; - ++r.corner.x; - r.extent.width -= 2; + r = captainNameRect; lf.baseline.x = r.corner.x + (r.extent.width >> 1) - 1; BackGround = BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09); @@ -207,7 +218,7 @@ else { // Naming the flagship Font = StarConFont; - r.corner.y = 20; + r = shipNameRect; lf.baseline.x = r.corner.x + (r.extent.width >> 1); BackGround = BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2D); @@ -218,6 +229,8 @@ lf.align = ALIGN_CENTER; } + LockMutex (GraphicsLock); + SetContext (StatusContext); SetContextFont (Font); lf.pStr = Str; lf.CharCount = (COUNT)~0; @@ -244,6 +257,10 @@ // disallow the change return (FALSE); } + + UnlockMutex (GraphicsLock); + PreUpdateFlashRect (); + LockMutex (GraphicsLock); SetContextForeGroundColor (BackGround); DrawFilledRectangle (&r); @@ -281,8 +298,8 @@ SetContextForeGroundColor (ForeGround); font_DrawText (&lf); - - SetFlashRect (&r); + + PostUpdateFlashRectLocked (); } UnlockMutex (GraphicsLock); @@ -309,7 +326,7 @@ UNICODE *Setting; LockMutex (GraphicsLock); - SetFlashRect (NULL); + SetFlashRect (nameCaptain ? &captainNameRect : &shipNameRect); UnlockMutex (GraphicsLock); DrawNameString (nameCaptain, buf, 0, DDSHS_EDIT); Modified: trunk/sc2/src/uqm/menu.c =================================================================== --- trunk/sc2/src/uqm/menu.c 2012-01-15 20:37:31 UTC (rev 3748) +++ trunk/sc2/src/uqm/menu.c 2012-01-23 20:14:45 UTC (rev 3749) @@ -28,9 +28,6 @@ #include "libs/tasklib.h" #include "libs/log.h" -extern Task flash_task; -extern RECT flash_rect; - static BYTE GetEndMenuState (BYTE BaseState); static BYTE GetBeginMenuState (BYTE BaseState); static BYTE FixMenuState (BYTE BadState); @@ -500,6 +497,7 @@ if (NewState <= end_index - beg_index) s.frame = SetAbsFrameIndex (PlayFrame, beg_index + NewState); + PreUpdateFlashRect (); LockMutex (GraphicsLock); OldContext = SetContext (StatusContext); GetContextClipRect (&r); @@ -600,13 +598,8 @@ } } UnbatchGraphics (); - if (flash_task - && flash_rect.corner.x == RADAR_X - && flash_rect.corner.y == RADAR_Y - && flash_rect.extent.width == RADAR_WIDTH - && flash_rect.extent.height == RADAR_HEIGHT) - SetFlashRect (SFR_MENU_3DO); SetContext (OldContext); UnlockMutex (GraphicsLock); + PostUpdateFlashRect (); } Modified: trunk/sc2/src/uqm/outfit.c =================================================================== --- trunk/sc2/src/uqm/outfit.c 2012-01-15 20:37:31 UTC (rev 3748) +++ trunk/sc2/src/uqm/outfit.c 2012-01-23 20:14:45 UTC (rev 3749) @@ -448,9 +448,9 @@ if (NewItem != pMS->CurState) { pMS->CurState = NewItem; + PreUpdateFlashRect (); DrawModuleStrings (pMS, NewItem); - // flash with PC menus too - SetFlashRect (SFR_MENU_ANY); + PostUpdateFlashRect (); } } else if (NewItem != pMS->delta_item || NewState != pMS->CurState) @@ -573,7 +573,9 @@ SetContextBackGroundColor (BLACK_COLOR)); DrawFilledRectangle (&r); } + PreUpdateFlashRect (); DeltaSISGauges (0, FUEL_TANK_SCALE, -GLOBAL (FuelCost)); + PostUpdateFlashRect (); SetContext (StatusContext); GetGaugeRect (&r, FALSE); SetFlashRect (&r); @@ -590,7 +592,9 @@ SetContext (SpaceContext); if (GLOBAL_SIS (FuelOnBoard)) { + PreUpdateFlashRect (); DeltaSISGauges (0, -FUEL_TANK_SCALE, GLOBAL (FuelCost)); + PostUpdateFlashRect (); if (GLOBAL_SIS (FuelOnBoard) % FUEL_VOLUME_PER_ROW == 0 && GLOBAL_SIS (FuelOnBoard) >= FUEL_RESERVE) { Modified: trunk/sc2/src/uqm/planets/roster.c =================================================================== --- trunk/sc2/src/uqm/planets/roster.c 2012-01-15 20:37:31 UTC (rev 3748) +++ trunk/sc2/src/uqm/planets/roster.c 2012-01-23 20:14:45 UTC (rev 3749) @@ -198,7 +198,9 @@ StarShipPtr->crew_level, TemplatePtr->crew_level); + PreUpdateFlashRect (); DrawStatusMessage (buf); + PostUpdateFlashRect (); DeltaSISGauges (-crew_delta, 0, 0); if (crew_delta) { Modified: trunk/sc2/src/uqm/shipyard.c =================================================================== --- trunk/sc2/src/uqm/shipyard.c 2012-01-15 20:37:31 UTC (rev 3748) +++ trunk/sc2/src/uqm/shipyard.c 2012-01-23 20:14:45 UTC (rev 3749) @@ -219,8 +219,7 @@ r.corner = s.origin; r.extent.width = RADAR_WIDTH; r.extent.height = RADAR_HEIGHT; - SetContextForeGroundColor ( - BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00)); + SetContextForeGroundColor (BLACK_COLOR); DrawFilledRectangle (&r); if (NewRaceItem != (BYTE)~0) { @@ -232,19 +231,22 @@ hStarShip = GetAvailableRaceFromIndex (NewRaceItem); NewRaceItem = GetIndexFromStarShip (&GLOBAL (avail_race_q), hStarShip); + + // Draw the ship name, above the ship image. s.frame = SetAbsFrameIndex (pMS->ModuleFrame, 3 + NewRaceItem); - // Ship name, above the ship image. DrawStamp (&s); + + // Draw the ship image. FleetPtr = LockFleetInfo (&GLOBAL (avail_race_q), hStarShip); s.frame = FleetPtr->melee_icon; - // Ship image. UnlockFleetInfo (&GLOBAL (avail_race_q), hStarShip); - t.baseline.x = s.origin.x + RADAR_WIDTH - 2; t.baseline.y = s.origin.y + RADAR_HEIGHT - 2; s.origin.x += (RADAR_WIDTH >> 1); s.origin.y += (RADAR_HEIGHT >> 1); DrawStamp (&s); + + // Print the ship cost. t.align = ALIGN_RIGHT; t.CharCount = (COUNT)~0; t.pStr = buf; @@ -257,8 +259,6 @@ UnbatchGraphics (); SetContext (OldContext); - // Flash the ship purchase menu even when optMenu == OPT_PC - SetFlashRect (SFR_MENU_ANY); UnlockMutex (GraphicsLock); } @@ -266,6 +266,10 @@ #define SHIP_WIN_HEIGHT (SHIP_WIN_WIDTH + 6) #define SHIP_WIN_FRAMES ((SHIP_WIN_WIDTH >> 1) + 1) +// Print the crew count of an escort ship on top of its (already drawn) +// image, either as '30' (full), '28/30' (partially full), or 'SCRAP' +// (empty). +// pRect is the rectangle of the ship image. static void ShowShipCrew (SHIP_FRAGMENT *StarShipPtr, const RECT *pRect) { @@ -274,20 +278,21 @@ UNICODE buf[80]; HFLEETINFO hTemplate; FLEET_INFO *TemplatePtr; + COUNT maxCrewLevel; hTemplate = GetStarShipFromIndex (&GLOBAL (avail_race_q), StarShipPtr->race_id); TemplatePtr = LockFleetInfo (&GLOBAL (avail_race_q), hTemplate); - if (StarShipPtr->crew_level >= TemplatePtr->crew_level) + maxCrewLevel = TemplatePtr->crew_level; + UnlockFleetInfo (&GLOBAL (avail_race_q), hTemplate); + + if (StarShipPtr->crew_level >= maxCrewLevel) sprintf (buf, "%u", StarShipPtr->crew_level); else if (StarShipPtr->crew_level == 0) // XXX: "SCRAP" needs to be moved to starcon.txt utf8StringCopy (buf, sizeof (buf), "SCRAP"); else - sprintf (buf, "%u/%u", - StarShipPtr->crew_level, - TemplatePtr->crew_level); - UnlockFleetInfo (&GLOBAL (avail_race_q), hTemplate); + sprintf (buf, "%u/%u", StarShipPtr->crew_level, maxCrewLevel); r = *pRect; t.baseline.x = r.corner.x + (r.extent.width >> 1); @@ -313,14 +318,17 @@ ShowCombatShip (MENU_STATE *pMS, COUNT which_window, SHIP_FRAGMENT *YankedStarShipPtr) { - COUNT i, num_ships; + COUNT i; + COUNT num_ships; HSHIPFRAG hStarShip, hNextShip; SHIP_FRAGMENT *StarShipPtr; struct { SHIP_FRAGMENT *StarShipPtr; POINT finished_s; - STAMP ship_s, lfdoor_s, rtdoor_s; + STAMP ship_s; + STAMP lfdoor_s; + STAMP rtdoor_s; } ship_win_info[MAX_BUILT_SHIPS], *pship_win_info; num_ships = 1; @@ -388,6 +396,10 @@ hNextShip = _GetSuccLink (StarShipPtr); pship_win_info->StarShipPtr = StarShipPtr; + // XXX BUG: this looks wrong according to the original + // semantics of LockShipFrag(): StarShipPtr is not valid + // anymore after UnlockShipFrag() is called, but it is + // used thereafter. pship_win_info->lfdoor_s.origin.x = -1; pship_win_info->rtdoor_s.origin.x = 1; @@ -496,6 +508,7 @@ } } +// Pre: GraphicsLock is unlocked. static void CrewTransaction (SIZE crew_delta) { @@ -519,10 +532,7 @@ && crew_bought - crew_delta < CREW_EXPENSE_THRESHOLD) { GLOBAL (CrewCost) += 2; - - UnlockMutex (GraphicsLock); DrawMenuStateStrings (PM_CREW, SHIPYARD_CREW); - LockMutex (GraphicsLock); } } else @@ -531,10 +541,7 @@ && crew_bought - crew_delta >= CREW_EXPENSE_THRESHOLD) { GLOBAL (CrewCost) -= 2; - - UnlockMutex (GraphicsLock); DrawMenuStateStrings (PM_CREW, SHIPYARD_CREW); - LockMutex (GraphicsLock); } } if (CheckAlliance (SHOFIXTI_SHIP) != GOOD_GUY) @@ -739,8 +746,14 @@ return 0; } + // Draw a crew member. DrawPoint (&r.corner); + + // Update the crew counter and RU. Note that the crew counter is + // flashing. + PreUpdateFlashRectLocked (); DeltaSISGauges (1, 0, -GLOBAL (CrewCost)); + PostUpdateFlashRectLocked (); return 1; } @@ -765,9 +778,14 @@ GET_GAME_STATE (CREW_PURCHASED0), GET_GAME_STATE (CREW_PURCHASED1)); + // Update the crew counter and RU. Note that the crew counter is + // flashing. + PreUpdateFlashRectLocked (); DeltaSISGauges (-1, 0, GLOBAL (CrewCost) - (crew_bought == CREW_EXPENSE_THRESHOLD ? 2 : 0)); + PostUpdateFlashRectLocked (); + // Remove the pixel representing the crew member. GetCPodCapacity (&r.corner); SetContextForeGroundColor (BLACK_COLOR); DrawPoint (&r.corner); @@ -824,8 +842,11 @@ } ++StarShipPtr->crew_level; + + PreUpdateFlashRectLocked (); DMS_GetEscortShipRect (&r, StarShipPtr->index); ShowShipCrew (StarShipPtr, &r); + PostUpdateFlashRectLocked (); return 1; } @@ -867,8 +888,10 @@ PlayMenuSound (MENU_SOUND_FAILURE); } + PreUpdateFlashRectLocked (); DMS_GetEscortShipRect (&r, StarShipPtr->index); ShowShipCrew (StarShipPtr, &r); + PostUpdateFlashRectLocked (); return crew_delta; } @@ -880,6 +903,7 @@ // selected. // 'dy' is -1 if the 'up' button was pressed, or '1' if the down button was // pressed. +// Pre: caller holds the GraphicsLock static void DMS_ModifyCrew (MENU_STATE *pMS, HSHIPFRAG hStarShip, SBYTE dy) { @@ -936,12 +960,15 @@ pMS->delta_item &= MODIFY_CREW_FLAG; } + UnlockMutex (GraphicsLock); CrewTransaction (crew_delta); + LockMutex (GraphicsLock); } // Helper function for DoModifyShips(), called when the player presses the // select button when the cursor is over an empty escort ship slot. // Try to add the currently selected ship as an escort ship. +// Pre: caller does not hold the GraphicsLock static void DMS_TryAddEscortShip (MENU_STATE *pMS) { @@ -1000,7 +1027,7 @@ // Cancel selecting an escort ship. pMS->delta_item &= ~MODIFY_CREW_FLAG; LockMutex (GraphicsLock); - SetFlashRect (SFR_MENU_3DO); + SetFlashRect (NULL); UnlockMutex (GraphicsLock); DrawMenuStateStrings (PM_CREW, SHIPYARD_CREW); LockMutex (GraphicsLock); @@ -1032,7 +1059,9 @@ if (currentShip != LOBYTE (pMS->delta_item)) { + PreUpdateFlashRect (); DrawRaceStrings (pMS, currentShip); + PostUpdateFlashRect (); pMS->delta_item = currentShip | MODIFY_CREW_FLAG; } } @@ -1041,6 +1070,7 @@ // Helper function for DoModifyShips(), called when the player presses // 'select' or 'cancel' after selling all the crew. +// Pre: caller holds the GraphicsLock static void DMS_ScrapEscortShip (MENU_STATE *pMS, HSHIPFRAG hStarShip) { @@ -1108,6 +1138,7 @@ // Helper function for DoModifyShips(), called every time DoModifyShip() is // called when we are in crew editing mode. +// Pre: Caller holds the GraphicsLock static void DMS_EditCrewMode (MENU_STATE *pMS, HSHIPFRAG hStarShip, BOOLEAN select, BOOLEAN cancel, SBYTE dy) @@ -1132,9 +1163,7 @@ } pMS->delta_item &= ~MODIFY_CREW_FLAG; - LockMutex (GraphicsLock); DMS_SetMode (pMS, DMS_Mode_navigate); - UnlockMutex (GraphicsLock); } else if (dy) { @@ -1146,7 +1175,7 @@ // Helper function for DoModifyShips(), called every time DoModifyShip() is // called when we are in the mode where you can select a ship or empty slot. -void +static void DMS_NavigateShipSlots (MENU_STATE *pMS, BOOLEAN special, BOOLEAN select, BOOLEAN cancel, SBYTE dx, SBYTE dy) { Modified: trunk/sc2/src/uqm/sis.c =================================================================== --- trunk/sc2/src/uqm/sis.c 2012-01-15 20:37:31 UTC (rev 3748) +++ trunk/sc2/src/uqm/sis.c 2012-01-23 20:14:45 UTC (rev 3749) @@ -31,6 +31,7 @@ #include "element.h" #include "setup.h" #include "state.h" +#include "flash.h" #include "libs/graphics/gfx_common.h" #include "libs/tasklib.h" #include "libs/log.h" @@ -1589,248 +1590,173 @@ } -Task flash_task = 0; -RECT flash_rect; -static FRAME flash_screen_frame = 0; - // The original contents of the flash rectangle. -static int flash_changed; -Mutex flash_mutex = 0; +static Task flash_task = 0; +static FlashContext *flashContext = NULL; +static RECT flash_rect; +static Mutex flash_mutex = 0; static int flash_rect_func (void *data) { -#define NORMAL_STRENGTH 4 -#define NORMAL_F_STRENGTH 0 -#define CACHE_SIZE 10 - DWORD TimeIn; - const DWORD WaitTime = ONE_SECOND / 16; - SIZE strength; - RECT cached_rect = {{0, 0}, {0, 0}}; - FRAME cached_screen_frame = 0; Task task = (Task)data; - bool cached[CACHE_SIZE]; - STAMP cached_stamp[CACHE_SIZE]; - int i; - // Init cache - for (i = 0; i < CACHE_SIZE; i++) - { - cached[i] = false; - cached_stamp[i].frame = 0; - } - - strength = NORMAL_STRENGTH; - TimeIn = GetTimeCounter (); while (!Task_ReadState(task, TASK_EXIT)) { - CONTEXT OldContext; - + TimeCount nextTime; LockMutex (flash_mutex); - if (flash_changed) - { - cached_rect = flash_rect; - if (cached_screen_frame) - DestroyDrawable (ReleaseDrawable (cached_screen_frame)); - flash_changed = 0; - // Wait for the flash_screen_frame to get initialized - FlushGraphics (); - cached_screen_frame = CaptureDrawable ( - CloneFrame (flash_screen_frame)); - UnlockMutex (flash_mutex); - - // Clear the cache. - for (i = 0; i < CACHE_SIZE; i++) - { - cached[i] = false; - if (cached_stamp[i].frame) - DestroyDrawable (ReleaseDrawable (cached_stamp[i].frame)); - cached_stamp[i].frame = 0; - } - } - else - UnlockMutex (flash_mutex); - - if (cached_rect.extent.width) - { - STAMP *pStamp; - -#define MIN_STRENGTH 4 -#define MAX_STRENGTH 6 - strength += 2; - if (strength > MAX_STRENGTH) - strength = MIN_STRENGTH; - if (cached[strength - MIN_STRENGTH]) - pStamp = &cached_stamp[strength - MIN_STRENGTH]; - else - { - pStamp = &cached_stamp[strength - MIN_STRENGTH]; - cached[strength - MIN_STRENGTH] = true; - pStamp->frame = CaptureDrawable ( - CloneFrame (cached_screen_frame)); - pStamp->origin.x = 0; - pStamp->origin.y = 0; - - if (strength != 4) - { // brighten the frame with an additive - DrawMode oldMode; - STAMP s; - int factor; - - s.origin.x = 0; - s.origin.y = 0; - s.frame = cached_screen_frame; - - factor = (strength - MIN_STRENGTH) * DRAW_FACTOR_1 / 4; - - LockMutex (GraphicsLock); - OldContext = SetContext (OffScreenContext); - SetContextFGFrame (pStamp->frame); - SetContextClipRect (NULL); - oldMode = SetContextDrawMode (MAKE_DRAW_MODE ( - DRAW_ADDITIVE, factor)); - DrawStamp (&s); - SetContextDrawMode (oldMode); - SetContext (OldContext); - UnlockMutex (GraphicsLock); - } - } - - LockMutex (GraphicsLock); - OldContext = SetContext (ScreenContext); - SetContextClipRect (&cached_rect); - // flash changed_can't be modified while GraphicSem is held - if (!flash_changed) - DrawStamp (pStamp); - // XXX: Shouldn't we save and restore the original cliprect? - SetContextClipRect (NULL); - SetContext (OldContext); - UnlockMutex (GraphicsLock); - } - FlushGraphics (); - SleepThreadUntil (TimeIn + WaitTime); - TimeIn = GetTimeCounter (); + Flash_process (flashContext); + nextTime = Flash_nextTime (flashContext); + UnlockMutex (flash_mutex); + SleepThreadUntil (nextTime); } - // Clear cache - { - if (cached_screen_frame) - DestroyDrawable (ReleaseDrawable (cached_screen_frame)); - - for (i = 0; i < CACHE_SIZE; i++) - { - if(cached_stamp[i].frame) - DestroyDrawable (ReleaseDrawable (cached_stamp[i].frame)); - } - } - LockMutex (flash_mutex); - flash_task = 0; - UnlockMutex (flash_mutex); - FinishTask (task); return 0; } +// Pre: the caller holds the GraphicsLock void -SetFlashRect (RECT *pRect) +SetFlashRect (const RECT *pRect) { RECT clip_r = {{0, 0}, {0, 0}}; - RECT temp_r, flash_rect1, old_r; - CONTEXT OldContext; - int create_flash = 0; - + RECT temp_r; + if (!flash_mutex) flash_mutex = CreateMutex ("FlashRect Lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO); - old_r = flash_rect; - flash_rect1 = flash_rect; - if (pRect != SFR_MENU_3DO && pRect != SFR_MENU_ANY) { + // The caller specified their own flash area, or NULL (stop flashing). GetContextClipRect (&clip_r); - OldContext = SetContext (ScreenContext); } else { - //Don't flash when using the PC menu if (optWhichMenu == OPT_PC && pRect != SFR_MENU_ANY) { - OldContext = SetContext (ScreenContext); + // The player wants PC menus and this flash is not used + // for a PC menu. + // Don't flash. pRect = 0; } else { - OldContext = SetContext (StatusContext); + // The player wants 3DO menus, or the flash is used in both + // 3DO and PC mode. + CONTEXT OldContext = SetContext (StatusContext); GetContextClipRect (&clip_r); pRect = &temp_r; temp_r.corner.x = RADAR_X - clip_r.corner.x; temp_r.corner.y = RADAR_Y - clip_r.corner.y; temp_r.extent.width = RADAR_WIDTH; temp_r.extent.height = RADAR_HEIGHT; - SetContext (ScreenContext); + SetContext (OldContext); } } - if (pRect == 0 || pRect->extent.width == 0) + // Conclude an old flash task. + if (flashContext != NULL) { - // End the flashing. - flash_rect1.extent.width = 0; - if (flash_task) - { - UnlockMutex (GraphicsLock); - ConcludeTask (flash_task); - LockMutex (GraphicsLock); - } + UnlockMutex (GraphicsLock); + ConcludeTask (flash_task); + LockMutex (GraphicsLock); + flash_task = 0; + + Flash_terminate (flashContext); + flashContext = 0; } - else + + // Start a new flash task. + if (pRect != 0 && pRect->extent.width != 0) { - flash_rect1 = *pRect; - flash_rect1.corner.x += clip_r.corner.x; - flash_rect1.corner.y += clip_r.corner.y; - create_flash = 1; + flash_rect = *pRect; + flash_rect.corner.x += clip_r.corner.x; + flash_rect.corner.y += clip_r.corner.y; + + flashContext = Flash_createHighlight (ScreenContext, &flash_rect); + Flash_setMergeFactors(flashContext, 3, 2, 2); + Flash_setSpeed (flashContext, 0, ONE_SECOND / 16, 0, ONE_SECOND / 16); + Flash_setFrameTime (flashContext, ONE_SECOND / 16); + Flash_start (flashContext); + + flash_task = AssignTask (flash_rect_func, 2048, "flash rectangle"); } - - LockMutex (flash_mutex); - flash_rect = flash_rect1; +} - if (old_r.extent.width && !rectsEqual (old_r, flash_rect)) +// Sleep while calling the flash rectangle update when necessary. +void +FlashRectSleepUntil (TimeCount wakeTime) +{ + while (GetTimeCounter() < wakeTime) { - // We had a flash rectangle, and now a different one is set. - if (flash_screen_frame) - { - // The screen contents may have changed; we grab a new copy. - STAMP old_s; - old_s.origin.x = old_r.corner.x; - old_s.origin.y = old_r.corner.y; - old_s.frame = flash_screen_frame; - DrawStamp (&old_s); - DestroyDrawable (ReleaseDrawable (flash_screen_frame)); - flash_screen_frame = 0; - } - else - log_add (log_Debug, "Couldn't locate flash_screen_rect"); + TimeCount flashNextTime = Flash_nextTime (flashContext); + TimeCount nextTime = (flashNextTime < wakeTime) ? + flashNextTime : wakeTime; + SleepThreadUntil (nextTime); + if (nextTime == flashNextTime) + Flash_process (flashContext); } - - if (flash_rect.extent.width) +} + +COUNT updateFlashRectRecursion = 0; +// XXX This is necessary at least because DMS_AddEscortShip() calls +// DrawRaceStrings() in an UpdateFlashRect block, which calls +// ClearSISRect(), which calls DrawMenuStateStrings(), which starts its own +// UpdateFlashRect block. This should probably be cleaned up. + +// GraphicsLock must be unlocked. +void +PreUpdateFlashRect (void) +{ + if (flash_task) { - // A new flash rectangle is set. - // Copy the original contents of the rectangle from the screen. - if (flash_screen_frame) - DestroyDrawable (ReleaseDrawable (flash_screen_frame)); - flash_screen_frame = - CaptureDrawable (LoadDisplayPixmap (&flash_rect, (FRAME)0)); + updateFlashRectRecursion++; + if (updateFlashRectRecursion > 1) + return; + + LockMutex (flash_mutex); + Flash_pause (flashContext); + // We need to actually pause, as the flash update function + // is called from another thread. + Flash_preUpdate (flashContext); + UnlockMutex (flash_mutex); } - flash_changed = 1; - UnlockMutex (flash_mutex); - // we create the thread after the LoadDisplayPixmap() - // so there is no race between the FlushGraphics in flash_task - // and the Enqueue in LoadDisplayPixmap() - if (create_flash && flash_task == 0) +} + +// GraphicsLock must be unlocked. +void +PostUpdateFlashRect (void) +{ + if (flash_task) { - flash_task = AssignTask (flash_rect_func, 2048, - "flash rectangle"); + updateFlashRectRecursion--; + if (updateFlashRectRecursion > 0) + return; + + LockMutex (flash_mutex); + Flash_postUpdate (flashContext); + Flash_continue (flashContext); + UnlockMutex (flash_mutex); } +} - SetContext (OldContext); +// Because the situation occurs a lot where the GraphicsLock is already +// locked, we add this function. +void +PreUpdateFlashRectLocked (void) +{ + UnlockMutex (GraphicsLock); + PreUpdateFlashRect (); + LockMutex (GraphicsLock); } +// Because the situation occurs a lot where the GraphicsLock is already +// locked, we add this function. +void +PostUpdateFlashRectLocked (void) +{ + UnlockMutex (GraphicsLock); + PostUpdateFlashRect (); + LockMutex (GraphicsLock); +} + Modified: trunk/sc2/src/uqm/sis.h =================================================================== --- trunk/sc2/src/uqm/sis.h 2012-01-15 20:37:31 UTC (rev 3748) +++ trunk/sc2/src/uqm/sis.h 2012-01-23 20:14:45 UTC (rev 3749) @@ -181,7 +181,11 @@ extern void InitSISContexts (void); extern void DrawSISFrame (void); extern void ClearSISRect (BYTE ClearFlags); -extern void SetFlashRect (RECT *pRect); +extern void SetFlashRect (const RECT *pRect); +extern void PreUpdateFlashRect (void); +extern void PostUpdateFlashRect (void); +extern void PreUpdateFlashRectLocked (void); +extern void PostUpdateFlashRectLocked (void); #define SFR_MENU_3DO ((RECT*)~0L) #define SFR_MENU_ANY ((RECT*)~1L) extern void DrawHyperCoords (POINT puniverse); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |