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:
Frank Praznik
2023-06-25 10:18:58 -04:00
parent 44536b7537
commit ef4ce8cec5
3 changed files with 97 additions and 18 deletions

View File

@@ -46,9 +46,18 @@ typedef struct shader_data
GLuint color_buffer;
} 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
{
SDL_Thread *thread;
SDL_Semaphore *suspend_sem;
SDL_AtomicInt suspended;
int done;
int index;
} thread_data;
@@ -56,6 +65,7 @@ typedef struct thread_data
static SDLTest_CommonState *state;
static SDL_GLContext *context = NULL;
static int depth = 16;
static SDL_bool suspend_when_occluded;
static GLES2_Context ctx;
static int LoadContext(GLES2_Context *data)
@@ -557,6 +567,9 @@ render_thread_fn(void *render_ctx)
thread_data *thread = render_ctx;
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);
}
@@ -564,29 +577,54 @@ render_thread_fn(void *render_ctx)
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
loop_threaded(void)
{
SDL_Event event;
int i;
thread_data *tdata;
/* Wait for events */
while (SDL_WaitEvent(&event) && !done) {
if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED) {
SDL_Window *window = SDL_GetWindowFromID(event.window.windowID);
if (window) {
for (i = 0; i < state->num_windows; ++i) {
if (window == state->windows[i]) {
/* Stop the render thread when the window is closed */
threads[i].done = 1;
if (threads[i].thread) {
SDL_WaitThread(threads[i].thread, NULL);
threads[i].thread = NULL;
}
break;
}
if (suspend_when_occluded && event.type == SDL_EVENT_WINDOW_OCCLUDED) {
tdata = GetThreadDataForWindow(event.window.windowID);
if (tdata) {
SDL_AtomicCAS(&tdata->suspended, WAIT_STATE_GO, WAIT_STATE_ENTER_SEM);
}
} else if (suspend_when_occluded && event.type == SDL_EVENT_WINDOW_EXPOSED) {
tdata = GetThreadDataForWindow(event.window.windowID);
if (tdata) {
if (SDL_AtomicSet(&tdata->suspended, WAIT_STATE_GO) == WAIT_STATE_WAITING_ON_SEM) {
SDL_PostSemaphore(tdata->suspend_sem);
}
}
} 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);
}
@@ -598,6 +636,7 @@ loop(void)
{
SDL_Event event;
int i;
int active_windows = 0;
/* Check for events */
while (SDL_PollEvent(&event) && !done) {
@@ -605,6 +644,11 @@ loop(void)
}
if (!done) {
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);
}
}
@@ -613,6 +657,11 @@ loop(void)
emscripten_cancel_main_loop();
}
#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[])
@@ -649,6 +698,9 @@ int main(int argc, char *argv[])
} else if (SDL_strcasecmp(argv[i], "--threaded") == 0) {
++threaded;
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) {
i++;
if (!argv[i]) {
@@ -667,7 +719,7 @@ int main(int argc, char *argv[])
}
}
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);
quit(1);
}
@@ -869,6 +921,8 @@ int main(int argc, char *argv[])
/* Start a render thread for each window */
for (i = 0; i < state->num_windows; ++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]);
}