mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-10-21 17:21:44 +00:00
test: Add flag to suspend drawing when occluded
Add the flag "--suspend-when-occluded" to testgl, testgles2, and testsprite, which, when used, will suspend rendering and throttle the event loop when the occlusion flag is set on the window.
This commit is contained in:
@@ -31,6 +31,7 @@ typedef struct GL_Context
|
|||||||
static SDLTest_CommonState *state;
|
static SDLTest_CommonState *state;
|
||||||
static SDL_GLContext context;
|
static SDL_GLContext context;
|
||||||
static GL_Context ctx;
|
static GL_Context ctx;
|
||||||
|
static SDL_bool suspend_when_occluded;
|
||||||
|
|
||||||
static int LoadContext(GL_Context *data)
|
static int LoadContext(GL_Context *data)
|
||||||
{
|
{
|
||||||
@@ -237,12 +238,15 @@ int main(int argc, char *argv[])
|
|||||||
} else if (SDL_strcasecmp(argv[i], "--accel") == 0 && i + 1 < argc) {
|
} else if (SDL_strcasecmp(argv[i], "--accel") == 0 && i + 1 < argc) {
|
||||||
accel = SDL_atoi(argv[i + 1]);
|
accel = SDL_atoi(argv[i + 1]);
|
||||||
consumed = 2;
|
consumed = 2;
|
||||||
|
} else if(SDL_strcasecmp(argv[i], "--suspend-when-occluded") == 0) {
|
||||||
|
suspend_when_occluded = SDL_TRUE;
|
||||||
|
consumed = 1;
|
||||||
} else {
|
} else {
|
||||||
consumed = -1;
|
consumed = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (consumed < 0) {
|
if (consumed < 0) {
|
||||||
static const char *options[] = { "[--fsaa n]", "[--accel n]", NULL };
|
static const char *options[] = { "[--fsaa n]", "[--accel n]", "[--suspend-when-occluded]", NULL };
|
||||||
SDLTest_CommonLogUsage(state, argv[0], options);
|
SDLTest_CommonLogUsage(state, argv[0], options);
|
||||||
quit(1);
|
quit(1);
|
||||||
}
|
}
|
||||||
@@ -386,6 +390,7 @@ int main(int argc, char *argv[])
|
|||||||
done = 0;
|
done = 0;
|
||||||
while (!done) {
|
while (!done) {
|
||||||
SDL_bool update_swap_interval = SDL_FALSE;
|
SDL_bool update_swap_interval = SDL_FALSE;
|
||||||
|
int active_windows = 0;
|
||||||
|
|
||||||
/* Check for events */
|
/* Check for events */
|
||||||
++frames;
|
++frames;
|
||||||
@@ -408,9 +413,11 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
for (i = 0; i < state->num_windows; ++i) {
|
for (i = 0; i < state->num_windows; ++i) {
|
||||||
int w, h;
|
int w, h;
|
||||||
if (state->windows[i] == NULL) {
|
if (state->windows[i] == NULL ||
|
||||||
|
(suspend_when_occluded && (SDL_GetWindowFlags(state->windows[i]) & SDL_WINDOW_OCCLUDED))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
++active_windows;
|
||||||
SDL_GL_MakeCurrent(state->windows[i], context);
|
SDL_GL_MakeCurrent(state->windows[i], context);
|
||||||
if (update_swap_interval) {
|
if (update_swap_interval) {
|
||||||
SDL_GL_SetSwapInterval(swap_interval);
|
SDL_GL_SetSwapInterval(swap_interval);
|
||||||
@@ -420,6 +427,11 @@ int main(int argc, char *argv[])
|
|||||||
Render();
|
Render();
|
||||||
SDL_GL_SwapWindow(state->windows[i]);
|
SDL_GL_SwapWindow(state->windows[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If all windows are occluded, throttle event polling to 15hz. */
|
||||||
|
if (!active_windows) {
|
||||||
|
SDL_DelayNS(SDL_NS_PER_SECOND / 15);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print out some timing information */
|
/* Print out some timing information */
|
||||||
|
@@ -46,9 +46,18 @@ typedef struct shader_data
|
|||||||
GLuint color_buffer;
|
GLuint color_buffer;
|
||||||
} shader_data;
|
} shader_data;
|
||||||
|
|
||||||
|
typedef enum wait_state
|
||||||
|
{
|
||||||
|
WAIT_STATE_GO = 0,
|
||||||
|
WAIT_STATE_ENTER_SEM,
|
||||||
|
WAIT_STATE_WAITING_ON_SEM,
|
||||||
|
} wait_state;
|
||||||
|
|
||||||
typedef struct thread_data
|
typedef struct thread_data
|
||||||
{
|
{
|
||||||
SDL_Thread *thread;
|
SDL_Thread *thread;
|
||||||
|
SDL_Semaphore *suspend_sem;
|
||||||
|
SDL_AtomicInt suspended;
|
||||||
int done;
|
int done;
|
||||||
int index;
|
int index;
|
||||||
} thread_data;
|
} thread_data;
|
||||||
@@ -56,6 +65,7 @@ typedef struct thread_data
|
|||||||
static SDLTest_CommonState *state;
|
static SDLTest_CommonState *state;
|
||||||
static SDL_GLContext *context = NULL;
|
static SDL_GLContext *context = NULL;
|
||||||
static int depth = 16;
|
static int depth = 16;
|
||||||
|
static SDL_bool suspend_when_occluded;
|
||||||
static GLES2_Context ctx;
|
static GLES2_Context ctx;
|
||||||
|
|
||||||
static int LoadContext(GLES2_Context *data)
|
static int LoadContext(GLES2_Context *data)
|
||||||
@@ -557,6 +567,9 @@ render_thread_fn(void *render_ctx)
|
|||||||
thread_data *thread = render_ctx;
|
thread_data *thread = render_ctx;
|
||||||
|
|
||||||
while (!done && !thread->done && state->windows[thread->index]) {
|
while (!done && !thread->done && state->windows[thread->index]) {
|
||||||
|
if (SDL_AtomicCAS(&thread->suspended, WAIT_STATE_ENTER_SEM, WAIT_STATE_WAITING_ON_SEM)) {
|
||||||
|
SDL_WaitSemaphore(thread->suspend_sem);
|
||||||
|
}
|
||||||
render_window(thread->index);
|
render_window(thread->index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -564,29 +577,54 @@ render_thread_fn(void *render_ctx)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static thread_data *GetThreadDataForWindow(SDL_WindowID id)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
SDL_Window *window = SDL_GetWindowFromID(id);
|
||||||
|
if (window) {
|
||||||
|
for (i = 0; i < state->num_windows; ++i) {
|
||||||
|
if (window == state->windows[i]) {
|
||||||
|
return &threads[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
loop_threaded(void)
|
loop_threaded(void)
|
||||||
{
|
{
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
int i;
|
thread_data *tdata;
|
||||||
|
|
||||||
/* Wait for events */
|
/* Wait for events */
|
||||||
while (SDL_WaitEvent(&event) && !done) {
|
while (SDL_WaitEvent(&event) && !done) {
|
||||||
if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED) {
|
if (suspend_when_occluded && event.type == SDL_EVENT_WINDOW_OCCLUDED) {
|
||||||
SDL_Window *window = SDL_GetWindowFromID(event.window.windowID);
|
tdata = GetThreadDataForWindow(event.window.windowID);
|
||||||
if (window) {
|
if (tdata) {
|
||||||
for (i = 0; i < state->num_windows; ++i) {
|
SDL_AtomicCAS(&tdata->suspended, WAIT_STATE_GO, WAIT_STATE_ENTER_SEM);
|
||||||
if (window == state->windows[i]) {
|
}
|
||||||
/* Stop the render thread when the window is closed */
|
} else if (suspend_when_occluded && event.type == SDL_EVENT_WINDOW_EXPOSED) {
|
||||||
threads[i].done = 1;
|
tdata = GetThreadDataForWindow(event.window.windowID);
|
||||||
if (threads[i].thread) {
|
if (tdata) {
|
||||||
SDL_WaitThread(threads[i].thread, NULL);
|
if (SDL_AtomicSet(&tdata->suspended, WAIT_STATE_GO) == WAIT_STATE_WAITING_ON_SEM) {
|
||||||
threads[i].thread = NULL;
|
SDL_PostSemaphore(tdata->suspend_sem);
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED) {
|
||||||
|
tdata = GetThreadDataForWindow(event.window.windowID);
|
||||||
|
if (tdata) {
|
||||||
|
/* Stop the render thread when the window is closed */
|
||||||
|
tdata->done = 1;
|
||||||
|
if (tdata->thread) {
|
||||||
|
SDL_AtomicSet(&tdata->suspended, WAIT_STATE_GO);
|
||||||
|
SDL_PostSemaphore(tdata->suspend_sem);
|
||||||
|
SDL_WaitThread(tdata->thread, NULL);
|
||||||
|
tdata->thread = NULL;
|
||||||
|
SDL_DestroySemaphore(tdata->suspend_sem);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SDLTest_CommonEvent(state, &event, &done);
|
SDLTest_CommonEvent(state, &event, &done);
|
||||||
}
|
}
|
||||||
@@ -598,6 +636,7 @@ loop(void)
|
|||||||
{
|
{
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
int i;
|
int i;
|
||||||
|
int active_windows = 0;
|
||||||
|
|
||||||
/* Check for events */
|
/* Check for events */
|
||||||
while (SDL_PollEvent(&event) && !done) {
|
while (SDL_PollEvent(&event) && !done) {
|
||||||
@@ -605,6 +644,11 @@ loop(void)
|
|||||||
}
|
}
|
||||||
if (!done) {
|
if (!done) {
|
||||||
for (i = 0; i < state->num_windows; ++i) {
|
for (i = 0; i < state->num_windows; ++i) {
|
||||||
|
if (state->windows[i] == NULL ||
|
||||||
|
(suspend_when_occluded && (SDL_GetWindowFlags(state->windows[i]) & SDL_WINDOW_OCCLUDED))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++active_windows;
|
||||||
render_window(i);
|
render_window(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -613,6 +657,11 @@ loop(void)
|
|||||||
emscripten_cancel_main_loop();
|
emscripten_cancel_main_loop();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* If all windows are occluded, throttle event polling to 15hz. */
|
||||||
|
if (!done && !active_windows) {
|
||||||
|
SDL_DelayNS(SDL_NS_PER_SECOND / 15);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
@@ -649,6 +698,9 @@ int main(int argc, char *argv[])
|
|||||||
} else if (SDL_strcasecmp(argv[i], "--threaded") == 0) {
|
} else if (SDL_strcasecmp(argv[i], "--threaded") == 0) {
|
||||||
++threaded;
|
++threaded;
|
||||||
consumed = 1;
|
consumed = 1;
|
||||||
|
} else if(SDL_strcasecmp(argv[i], "--suspend-when-occluded") == 0) {
|
||||||
|
suspend_when_occluded = SDL_TRUE;
|
||||||
|
consumed = 1;
|
||||||
} else if (SDL_strcasecmp(argv[i], "--zdepth") == 0) {
|
} else if (SDL_strcasecmp(argv[i], "--zdepth") == 0) {
|
||||||
i++;
|
i++;
|
||||||
if (!argv[i]) {
|
if (!argv[i]) {
|
||||||
@@ -667,7 +719,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (consumed < 0) {
|
if (consumed < 0) {
|
||||||
static const char *options[] = { "[--fsaa]", "[--accel]", "[--zdepth %d]", "[--threaded]", NULL };
|
static const char *options[] = { "[--fsaa]", "[--accel]", "[--zdepth %d]", "[--threaded]", "[--suspend-when-occluded]",NULL };
|
||||||
SDLTest_CommonLogUsage(state, argv[0], options);
|
SDLTest_CommonLogUsage(state, argv[0], options);
|
||||||
quit(1);
|
quit(1);
|
||||||
}
|
}
|
||||||
@@ -869,6 +921,8 @@ int main(int argc, char *argv[])
|
|||||||
/* Start a render thread for each window */
|
/* Start a render thread for each window */
|
||||||
for (i = 0; i < state->num_windows; ++i) {
|
for (i = 0; i < state->num_windows; ++i) {
|
||||||
threads[i].index = i;
|
threads[i].index = i;
|
||||||
|
SDL_AtomicSet(&threads[i].suspended, 0);
|
||||||
|
threads[i].suspend_sem = SDL_CreateSemaphore(0);
|
||||||
threads[i].thread = SDL_CreateThread(render_thread_fn, "RenderThread", &threads[i]);
|
threads[i].thread = SDL_CreateThread(render_thread_fn, "RenderThread", &threads[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -42,6 +42,7 @@ static Uint64 next_fps_check;
|
|||||||
static Uint32 frames;
|
static Uint32 frames;
|
||||||
static const int fps_check_delay = 5000;
|
static const int fps_check_delay = 5000;
|
||||||
static int use_rendergeometry = 0;
|
static int use_rendergeometry = 0;
|
||||||
|
static SDL_bool suspend_when_occluded;
|
||||||
|
|
||||||
/* Number of iterations to move sprites - used for visual tests. */
|
/* Number of iterations to move sprites - used for visual tests. */
|
||||||
/* -1: infinite random moves (default); >=0: enables N deterministic moves */
|
/* -1: infinite random moves (default); >=0: enables N deterministic moves */
|
||||||
@@ -398,6 +399,7 @@ static void loop(void)
|
|||||||
{
|
{
|
||||||
Uint64 now;
|
Uint64 now;
|
||||||
int i;
|
int i;
|
||||||
|
int active_windows = 0;
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
|
|
||||||
/* Check for events */
|
/* Check for events */
|
||||||
@@ -405,9 +407,11 @@ static void loop(void)
|
|||||||
SDLTest_CommonEvent(state, &event, &done);
|
SDLTest_CommonEvent(state, &event, &done);
|
||||||
}
|
}
|
||||||
for (i = 0; i < state->num_windows; ++i) {
|
for (i = 0; i < state->num_windows; ++i) {
|
||||||
if (state->windows[i] == NULL) {
|
if (state->windows[i] == NULL ||
|
||||||
|
(suspend_when_occluded && (SDL_GetWindowFlags(state->windows[i]) & SDL_WINDOW_OCCLUDED))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
++active_windows;
|
||||||
MoveSprites(state->renderers[i], sprites[i]);
|
MoveSprites(state->renderers[i], sprites[i]);
|
||||||
}
|
}
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
@@ -416,6 +420,11 @@ static void loop(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* If all windows are occluded, throttle the event polling to 15hz. */
|
||||||
|
if (!done && !active_windows) {
|
||||||
|
SDL_DelayNS(SDL_NS_PER_SECOND / 15);
|
||||||
|
}
|
||||||
|
|
||||||
frames++;
|
frames++;
|
||||||
now = SDL_GetTicks();
|
now = SDL_GetTicks();
|
||||||
if (now >= next_fps_check) {
|
if (now >= next_fps_check) {
|
||||||
@@ -485,6 +494,9 @@ int main(int argc, char *argv[])
|
|||||||
} else if (SDL_strcasecmp(argv[i], "--cyclealpha") == 0) {
|
} else if (SDL_strcasecmp(argv[i], "--cyclealpha") == 0) {
|
||||||
cycle_alpha = SDL_TRUE;
|
cycle_alpha = SDL_TRUE;
|
||||||
consumed = 1;
|
consumed = 1;
|
||||||
|
} else if(SDL_strcasecmp(argv[i], "--suspend-when-occluded") == 0) {
|
||||||
|
suspend_when_occluded = SDL_TRUE;
|
||||||
|
consumed = 1;
|
||||||
} else if (SDL_strcasecmp(argv[i], "--use-rendergeometry") == 0) {
|
} else if (SDL_strcasecmp(argv[i], "--use-rendergeometry") == 0) {
|
||||||
if (argv[i + 1]) {
|
if (argv[i + 1]) {
|
||||||
if (SDL_strcasecmp(argv[i + 1], "mode1") == 0) {
|
if (SDL_strcasecmp(argv[i + 1], "mode1") == 0) {
|
||||||
@@ -512,6 +524,7 @@ int main(int argc, char *argv[])
|
|||||||
"[--blend none|blend|add|mod|mul|sub]",
|
"[--blend none|blend|add|mod|mul|sub]",
|
||||||
"[--cyclecolor]",
|
"[--cyclecolor]",
|
||||||
"[--cyclealpha]",
|
"[--cyclealpha]",
|
||||||
|
"[--suspend-when-occluded]",
|
||||||
"[--iterations N]",
|
"[--iterations N]",
|
||||||
"[--use-rendergeometry mode1|mode2]",
|
"[--use-rendergeometry mode1|mode2]",
|
||||||
"[num_sprites]",
|
"[num_sprites]",
|
||||||
|
Reference in New Issue
Block a user