gray: add the DGRAY_PUSH_ON/OFF and DGRAY_POP feature

DGRAY_PUSH_ON/OFF will push the current gray engine state to a stack
before transitioning to on/off mode. DGRAY_POP will later recover the
saved state and transition back to it.
This commit is contained in:
Lephe 2020-07-13 17:14:58 +02:00
parent 94fb300e72
commit 0eb58c39a3
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
2 changed files with 35 additions and 12 deletions

View file

@ -43,12 +43,11 @@ enum {
When functions that use the gray engine call functions that don't and vice-
versa, it can be tedious to know exacly when the gray engine should be
running. This function provides a stack of gray engine states to solve this
problem. When entering a function that uses/doesn't use the gray engine, you
can call dgray(DGRAY_PUSH_ON)/dgray(DGRAY_PUSH_OFF) to start/stop the
engine; then call dgray(DGRAY_POP) at the end of the function.
dgray(DGRAY_POP) will restore the state of the engine as it was before the
previous DGRAY_PUSH_*. This allows each function to set its own state
running. To solve this problem, this function provides DGRAY_PUSH_ON and
DGRAY_PUSH_OFF that save the current state of the engine before starting or
stopping it. DGRAY_POP can later be used to transition back to the saved
state. 32 states can be saved, meaning that up to 32 DGRAY_PUSH_* can be in
effect simultaneously. This allows each function to set its own state
without altering the state of their callers.
This function returns non-zero if the engine has failed to initialize at

View file

@ -148,25 +148,49 @@ static void gray_stop(void)
/* dgray(): Start or stop the gray engine at the next dupdate() */
int dgray(int mode)
{
/* Stack of states for the push modes */
static uint8_t states[32] = { 0 };
static uint8_t current = 0;
if(mode == DGRAY_ON)
{
if(!gray_isinit()) return 1;
/* Set the display module's alternate rendering mode to
override rendering functions to use their g*() variant */
dmode = &gray_mode;
return 0;
if(!dgray_enabled()) dmode = &gray_mode;
}
else if(mode == DGRAY_OFF)
{
/* Set the mode to a temporary one that only overrides
dupdate() so that we can stop the engine next frame */
if(dmode == &gray_mode) dmode = &gray_exit_mode;
return 0;
if(dgray_enabled()) dmode = &gray_exit_mode;
}
else if(mode == DGRAY_PUSH_ON)
{
if(current >= 32) return 1;
states[current++] = dgray_enabled() ? DGRAY_ON : DGRAY_OFF;
/* TODO: DGRAY_PUSH_* and DGRAY_POP */
return 2;
return dgray(DGRAY_ON);
}
else if(mode == DGRAY_PUSH_OFF)
{
if(current >= 32) return 1;
states[current++] = dgray_enabled() ? DGRAY_ON : DGRAY_OFF;
return dgray(DGRAY_OFF);
}
else if(mode == DGRAY_POP)
{
/* Stay at 0 if the user's push/pop logic is broken */
if(current > 0) current--;
/* Switch to previous state */
return dgray(states[current]);
}
else return 1;
return 0;
}
/* gray_int(): Interrupt handler */