testgles2: Add --threaded option to use a render thread per window
This is helpful for reproducing bugs like #6056main
parent
9670d2bb9e
commit
222f1a2693
137
test/testgles2.c
137
test/testgles2.c
|
@ -51,6 +51,13 @@ typedef struct shader_data
|
|||
GLuint color_buffer;
|
||||
} shader_data;
|
||||
|
||||
typedef struct thread_data
|
||||
{
|
||||
SDL_Thread *thread;
|
||||
int done;
|
||||
int index;
|
||||
} thread_data;
|
||||
|
||||
static SDLTest_CommonState *state;
|
||||
static SDL_GLContext *context = NULL;
|
||||
static int depth = 16;
|
||||
|
@ -434,6 +441,7 @@ Render(unsigned int width, unsigned int height, shader_data* data)
|
|||
if(data->angle_z >= 360) data->angle_z -= 360;
|
||||
if(data->angle_z < 0) data->angle_z += 360;
|
||||
|
||||
GL_CHECK(ctx.glViewport(0, 0, width, height));
|
||||
GL_CHECK(ctx.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
|
||||
GL_CHECK(ctx.glDrawArrays(GL_TRIANGLES, 0, 36));
|
||||
}
|
||||
|
@ -441,55 +449,83 @@ Render(unsigned int width, unsigned int height, shader_data* data)
|
|||
int done;
|
||||
Uint32 frames;
|
||||
shader_data *datas;
|
||||
thread_data *threads;
|
||||
|
||||
void loop()
|
||||
static void
|
||||
render_window(int index)
|
||||
{
|
||||
int w, h, status;
|
||||
|
||||
if (!state->windows[index]) {
|
||||
return;
|
||||
}
|
||||
|
||||
status = SDL_GL_MakeCurrent(state->windows[index], context[index]);
|
||||
if (status) {
|
||||
SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_GL_GetDrawableSize(state->windows[index], &w, &h);
|
||||
Render(w, h, &datas[index]);
|
||||
SDL_GL_SwapWindow(state->windows[index]);
|
||||
++frames;
|
||||
}
|
||||
|
||||
static int SDLCALL
|
||||
render_thread_fn(void* render_ctx)
|
||||
{
|
||||
thread_data *thread = render_ctx;
|
||||
|
||||
while (!done && !thread->done && state->windows[thread->index]) {
|
||||
render_window(thread->index);
|
||||
}
|
||||
|
||||
SDL_GL_MakeCurrent(state->windows[thread->index], NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
loop_threaded()
|
||||
{
|
||||
SDL_Event event;
|
||||
int i;
|
||||
int status;
|
||||
|
||||
/* Check for events */
|
||||
++frames;
|
||||
while (SDL_PollEvent(&event) && !done) {
|
||||
switch (event.type) {
|
||||
case SDL_WINDOWEVENT:
|
||||
switch (event.window.event) {
|
||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||
/* Wait for events */
|
||||
while (SDL_WaitEvent(&event) && !done) {
|
||||
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE) {
|
||||
SDL_Window *window = SDL_GetWindowFromID(event.window.windowID);
|
||||
if (window) {
|
||||
for (i = 0; i < state->num_windows; ++i) {
|
||||
if (event.window.windowID == SDL_GetWindowID(state->windows[i])) {
|
||||
int w, h;
|
||||
status = SDL_GL_MakeCurrent(state->windows[i], context[i]);
|
||||
if (status) {
|
||||
SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError());
|
||||
break;
|
||||
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;
|
||||
}
|
||||
/* Change view port to the new window dimensions */
|
||||
SDL_GL_GetDrawableSize(state->windows[i], &w, &h);
|
||||
ctx.glViewport(0, 0, w, h);
|
||||
state->window_w = event.window.data1;
|
||||
state->window_h = event.window.data2;
|
||||
/* Update window content */
|
||||
Render(event.window.data1, event.window.data2, &datas[i]);
|
||||
SDL_GL_SwapWindow(state->windows[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
SDLTest_CommonEvent(state, &event, &done);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
loop()
|
||||
{
|
||||
SDL_Event event;
|
||||
int i;
|
||||
|
||||
/* Check for events */
|
||||
while (SDL_PollEvent(&event) && !done) {
|
||||
SDLTest_CommonEvent(state, &event, &done);
|
||||
}
|
||||
if (!done) {
|
||||
for (i = 0; i < state->num_windows; ++i) {
|
||||
status = SDL_GL_MakeCurrent(state->windows[i], context[i]);
|
||||
if (status) {
|
||||
SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError());
|
||||
|
||||
/* Continue for next window */
|
||||
continue;
|
||||
}
|
||||
Render(state->window_w, state->window_h, &datas[i]);
|
||||
SDL_GL_SwapWindow(state->windows[i]);
|
||||
render_window(i);
|
||||
}
|
||||
}
|
||||
#ifdef __EMSCRIPTEN__
|
||||
|
@ -502,7 +538,7 @@ void loop()
|
|||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int fsaa, accel;
|
||||
int fsaa, accel, threaded;
|
||||
int value;
|
||||
int i;
|
||||
SDL_DisplayMode mode;
|
||||
|
@ -513,6 +549,7 @@ main(int argc, char *argv[])
|
|||
/* Initialize parameters */
|
||||
fsaa = 0;
|
||||
accel = 0;
|
||||
threaded = 0;
|
||||
|
||||
/* Initialize test framework */
|
||||
state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
|
||||
|
@ -530,6 +567,9 @@ main(int argc, char *argv[])
|
|||
} else if (SDL_strcasecmp(argv[i], "--accel") == 0) {
|
||||
++accel;
|
||||
consumed = 1;
|
||||
} else if (SDL_strcasecmp(argv[i], "--threaded") == 0) {
|
||||
++threaded;
|
||||
consumed = 1;
|
||||
} else if (SDL_strcasecmp(argv[i], "--zdepth") == 0) {
|
||||
i++;
|
||||
if (!argv[i]) {
|
||||
|
@ -543,7 +583,7 @@ main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
if (consumed < 0) {
|
||||
static const char *options[] = { "[--fsaa]", "[--accel]", "[--zdepth %d]", NULL };
|
||||
static const char *options[] = { "[--fsaa]", "[--accel]", "[--zdepth %d], [--threaded]", NULL };
|
||||
SDLTest_CommonLogUsage(state, argv[0], options);
|
||||
quit(1);
|
||||
}
|
||||
|
@ -551,7 +591,7 @@ main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
/* Set OpenGL parameters */
|
||||
state->window_flags |= SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_BORDERLESS;
|
||||
state->window_flags |= SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
|
||||
state->gl_red_size = 5;
|
||||
state->gl_green_size = 5;
|
||||
state->gl_blue_size = 5;
|
||||
|
@ -603,6 +643,7 @@ main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
SDL_GetCurrentDisplayMode(0, &mode);
|
||||
SDL_Log("Threaded : %s\n", threaded ? "yes" : "no");
|
||||
SDL_Log("Screen bpp: %d\n", SDL_BITSPERPIXEL(mode.format));
|
||||
SDL_Log("\n");
|
||||
SDL_Log("Vendor : %s\n", ctx.glGetString(GL_VENDOR));
|
||||
|
@ -724,6 +765,8 @@ main(int argc, char *argv[])
|
|||
|
||||
GL_CHECK(ctx.glEnable(GL_CULL_FACE));
|
||||
GL_CHECK(ctx.glEnable(GL_DEPTH_TEST));
|
||||
|
||||
SDL_GL_MakeCurrent(state->windows[i], NULL);
|
||||
}
|
||||
|
||||
/* Main render loop */
|
||||
|
@ -734,9 +777,31 @@ main(int argc, char *argv[])
|
|||
#ifdef __EMSCRIPTEN__
|
||||
emscripten_set_main_loop(loop, 0, 1);
|
||||
#else
|
||||
if (threaded) {
|
||||
threads = (thread_data*)SDL_calloc(state->num_windows, sizeof(thread_data));
|
||||
|
||||
/* Start a render thread for each window */
|
||||
for (i = 0; i < state->num_windows; ++i) {
|
||||
threads[i].index = i;
|
||||
threads[i].thread = SDL_CreateThread(render_thread_fn, "RenderThread", &threads[i]);
|
||||
}
|
||||
|
||||
while (!done) {
|
||||
loop_threaded();
|
||||
}
|
||||
|
||||
/* Join the remaining render threads (if any) */
|
||||
for (i = 0; i < state->num_windows; ++i) {
|
||||
threads[i].done = 1;
|
||||
if (threads[i].thread) {
|
||||
SDL_WaitThread(threads[i].thread, NULL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (!done) {
|
||||
loop();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Print out some timing information */
|
||||
|
|
Loading…
Reference in New Issue