Main and stream decored thread down-throttling, and game sleep when inactive (intended for portables and currently disabled in mainline); bug #1070; from Flandry

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3284 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
avolkov
2009-11-05 23:53:43 +00:00
parent a80d533fa7
commit ec9d3e4b72
9 changed files with 79 additions and 4 deletions
+2
View File
@@ -1,4 +1,6 @@
Changes towards version 0.7: Changes towards version 0.7:
- Thread down-throttling and game sleep when inactive (currently disabled),
(bug #1070), from Flandry
- Internal changes: GOOD_GUY/BAD_GUY ship flags retired - Alex - Internal changes: GOOD_GUY/BAD_GUY ship flags retired - Alex
- Fixed Melee menu timeout when both sides are Cyborgs (bug #1067) - Alex - Fixed Melee menu timeout when both sides are Cyborgs (bug #1067) - Alex
- Fixed AI ship not moving on warp in (bug #648) - Alex - Fixed AI ship not moving on warp in (bug #648) - Alex
+13 -3
View File
@@ -56,6 +56,7 @@ TFB_GRAPHICS_BACKEND *graphics_backend = NULL;
int RenderedFrames = 0; int RenderedFrames = 0;
volatile int QuitPosted = 0; volatile int QuitPosted = 0;
volatile int GameActive = 1; // Track the SDL_ACTIVEEVENT state SDL_APPACTIVE
void void
TFB_PreInit (void) TFB_PreInit (void)
@@ -198,10 +199,19 @@ TFB_ProcessEvents ()
{ {
/* Run through the InputEvent filter. */ /* Run through the InputEvent filter. */
ProcessInputEvent (&Event); ProcessInputEvent (&Event);
/* Handle Graphics events. */ /* Handle graphics and exposure events. */
switch (Event.type) { switch (Event.type) {
case SDL_ACTIVEEVENT: /* Lose/gain visibility */ case SDL_ACTIVEEVENT: /* Lose/gain visibility or focus */
// TODO /* Up to three different state changes can occur in one event. */
/* Here, disregard least significant change (mouse focus). */
#if 0 /* Currently disabled in mainline */
// This controls the automatic sleep/pause when minimized.
// On small displays (e.g. mobile devices), APPINPUTFOCUS would
// be an appropriate substitution for APPACTIVE:
// if (Event.active.state & SDL_APPINPUTFOCUS)
if (Event.active.state & SDL_APPACTIVE)
GameActive = Event.active.gain;
#endif
break; break;
case SDL_QUIT: case SDL_QUIT:
QuitPosted = 1; QuitPosted = 1;
+1
View File
@@ -37,6 +37,7 @@ extern BYTE LocateMouse (SWORD *px, SWORD *py);
extern volatile int MouseButtonDown; extern volatile int MouseButtonDown;
extern volatile int QuitPosted; extern volatile int QuitPosted;
extern volatile int GameActive;
/* Functions for dealing with Character Mode */ /* Functions for dealing with Character Mode */
+10 -1
View File
@@ -495,11 +495,12 @@ int
StreamDecoderTaskFunc (void *data) StreamDecoderTaskFunc (void *data)
{ {
Task task = (Task)data; Task task = (Task)data;
int active_streams;
int i; int i;
while (!Task_ReadState (task, TASK_EXIT)) while (!Task_ReadState (task, TASK_EXIT))
{ {
TaskSwitch (); active_streams = 0;
for (i = MUSIC_SOURCE; i < NUM_SOUNDSOURCES; ++i) for (i = MUSIC_SOURCE; i < NUM_SOUNDSOURCES; ++i)
{ {
@@ -517,9 +518,17 @@ StreamDecoderTaskFunc (void *data)
} }
process_stream (source); process_stream (source);
active_streams++;
UnlockMutex (source->stream_mutex); UnlockMutex (source->stream_mutex);
} }
if (active_streams == 0)
{ // Throttle down the thread when there are no active streams
SleepThread (ONE_SECOND / 10);
}
else
TaskSwitch ();
} }
FinishTask (task); FinishTask (task);
+4
View File
@@ -433,6 +433,10 @@ main (int argc, char *argv[])
SignalStopMainThread (); SignalStopMainThread ();
++i; ++i;
} }
else if (!GameActive)
{ // Throttle down the main loop when game is inactive
SleepThread (ONE_SECOND / 4);
}
TFB_ProcessEvents (); TFB_ProcessEvents ();
ProcessUtilityKeys (); ProcessUtilityKeys ();
+1
View File
@@ -100,6 +100,7 @@ void SetMenuRepeatDelay (DWORD min, DWORD max, DWORD step, BOOLEAN gestalt);
void SetDefaultMenuRepeatDelay (void); void SetDefaultMenuRepeatDelay (void);
void ResetKeyRepeat (void); void ResetKeyRepeat (void);
BOOLEAN PauseGame (void); BOOLEAN PauseGame (void);
void SleepGame (void);
BOOLEAN DoConfirmExit (void); BOOLEAN DoConfirmExit (void);
BOOLEAN WaitAnyButtonOrQuit (BOOLEAN CheckSpecial); BOOLEAN WaitAnyButtonOrQuit (BOOLEAN CheckSpecial);
void WaitForNoInput (SIZE Duration); void WaitForNoInput (SIZE Duration);
+5
View File
@@ -228,6 +228,11 @@ UpdateInputState (void)
* UpdateInputState routinely, so we handle pause and exit * UpdateInputState routinely, so we handle pause and exit
* state updates here. */ * state updates here. */
// Automatically pause and enter low-activity state while inactive,
// for example, window minimized.
if (!GameActive)
SleepGame ();
if (GamePaused) if (GamePaused)
PauseGame (); PauseGame ();
+1
View File
@@ -106,6 +106,7 @@ SignalStopMainThread (void)
{ {
GamePaused = FALSE; GamePaused = FALSE;
GLOBAL (CurrentActivity) |= CHECK_ABORT; GLOBAL (CurrentActivity) |= CHECK_ABORT;
TaskSwitch ();
} }
void void
+42
View File
@@ -20,9 +20,11 @@
#include "controls.h" #include "controls.h"
#include "util.h" #include "util.h"
#include "setup.h" #include "setup.h"
#include "settings.h"
#include "libs/inplib.h" #include "libs/inplib.h"
#include "libs/sound/trackplayer.h" #include "libs/sound/trackplayer.h"
#include "libs/mathlib.h" #include "libs/mathlib.h"
#include "libs/log.h"
void void
@@ -250,3 +252,43 @@ WaitAnyButtonOrQuit (BOOLEAN CheckSpecial)
return (GLOBAL (CurrentActivity) & CHECK_ABORT) != 0; return (GLOBAL (CurrentActivity) & CHECK_ABORT) != 0;
} }
// Stops game clock and music thread and minimizes interrupts/cycles
// based on value of global GameActive variable
// See similar sleep state for main thread in uqm.c:main()
void
SleepGame (void)
{
if (QuitPosted)
return; // Do not sleep the game when already asked to quit
log_add (log_Debug, "Game is going to sleep");
if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE &&
LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE)
SuspendGameClock ();
if (CommData.ConversationPhrases && PlayingTrack ())
PauseTrack ();
PauseMusic ();
LockMutex (GraphicsLock);
while (!GameActive && !QuitPosted)
SleepThread (ONE_SECOND / 2);
log_add (log_Debug, "Game is waking up");
WaitForNoInput (ONE_SECOND / 10);
FlushInput ();
ResumeMusic ();
if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE &&
LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE)
ResumeGameClock ();
if (CommData.ConversationPhrases && PlayingTrack ())
ResumeTrack ();
UnlockMutex (GraphicsLock);
TaskSwitch ();
}