testgles2: Add --threaded option to use a render thread per window
This is helpful for reproducing bugs like #6056main
parent
9670d2bb9e
commit
222f1a2693
151
test/testgles2.c
151
test/testgles2.c
|
@ -51,6 +51,13 @@ typedef struct shader_data
|
||||||
GLuint color_buffer;
|
GLuint color_buffer;
|
||||||
} shader_data;
|
} shader_data;
|
||||||
|
|
||||||
|
typedef struct thread_data
|
||||||
|
{
|
||||||
|
SDL_Thread *thread;
|
||||||
|
int done;
|
||||||
|
int index;
|
||||||
|
} 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;
|
||||||
|
@ -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 >= 360) data->angle_z -= 360;
|
||||||
if(data->angle_z < 0) 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.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
|
||||||
GL_CHECK(ctx.glDrawArrays(GL_TRIANGLES, 0, 36));
|
GL_CHECK(ctx.glDrawArrays(GL_TRIANGLES, 0, 36));
|
||||||
}
|
}
|
||||||
|
@ -441,56 +449,84 @@ Render(unsigned int width, unsigned int height, shader_data* data)
|
||||||
int done;
|
int done;
|
||||||
Uint32 frames;
|
Uint32 frames;
|
||||||
shader_data *datas;
|
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;
|
SDL_Event event;
|
||||||
int i;
|
int i;
|
||||||
int status;
|
|
||||||
|
|
||||||
/* Check for events */
|
/* Wait for events */
|
||||||
++frames;
|
while (SDL_WaitEvent(&event) && !done) {
|
||||||
while (SDL_PollEvent(&event) && !done) {
|
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE) {
|
||||||
switch (event.type) {
|
SDL_Window *window = SDL_GetWindowFromID(event.window.windowID);
|
||||||
case SDL_WINDOWEVENT:
|
if (window) {
|
||||||
switch (event.window.event) {
|
for (i = 0; i < state->num_windows; ++i) {
|
||||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
if (window == state->windows[i]) {
|
||||||
for (i = 0; i < state->num_windows; ++i) {
|
/* Stop the render thread when the window is closed */
|
||||||
if (event.window.windowID == SDL_GetWindowID(state->windows[i])) {
|
threads[i].done = 1;
|
||||||
int w, h;
|
if (threads[i].thread) {
|
||||||
status = SDL_GL_MakeCurrent(state->windows[i], context[i]);
|
SDL_WaitThread(threads[i].thread, NULL);
|
||||||
if (status) {
|
threads[i].thread = NULL;
|
||||||
SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* 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;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SDLTest_CommonEvent(state, &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 */
|
static void
|
||||||
continue;
|
loop()
|
||||||
}
|
{
|
||||||
Render(state->window_w, state->window_h, &datas[i]);
|
SDL_Event event;
|
||||||
SDL_GL_SwapWindow(state->windows[i]);
|
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) {
|
||||||
|
render_window(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
else {
|
else {
|
||||||
|
@ -502,7 +538,7 @@ void loop()
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int fsaa, accel;
|
int fsaa, accel, threaded;
|
||||||
int value;
|
int value;
|
||||||
int i;
|
int i;
|
||||||
SDL_DisplayMode mode;
|
SDL_DisplayMode mode;
|
||||||
|
@ -513,6 +549,7 @@ main(int argc, char *argv[])
|
||||||
/* Initialize parameters */
|
/* Initialize parameters */
|
||||||
fsaa = 0;
|
fsaa = 0;
|
||||||
accel = 0;
|
accel = 0;
|
||||||
|
threaded = 0;
|
||||||
|
|
||||||
/* Initialize test framework */
|
/* Initialize test framework */
|
||||||
state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
|
state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
|
||||||
|
@ -530,6 +567,9 @@ main(int argc, char *argv[])
|
||||||
} else if (SDL_strcasecmp(argv[i], "--accel") == 0) {
|
} else if (SDL_strcasecmp(argv[i], "--accel") == 0) {
|
||||||
++accel;
|
++accel;
|
||||||
consumed = 1;
|
consumed = 1;
|
||||||
|
} else if (SDL_strcasecmp(argv[i], "--threaded") == 0) {
|
||||||
|
++threaded;
|
||||||
|
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]) {
|
||||||
|
@ -543,7 +583,7 @@ main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (consumed < 0) {
|
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);
|
SDLTest_CommonLogUsage(state, argv[0], options);
|
||||||
quit(1);
|
quit(1);
|
||||||
}
|
}
|
||||||
|
@ -551,7 +591,7 @@ main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set OpenGL parameters */
|
/* 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_red_size = 5;
|
||||||
state->gl_green_size = 5;
|
state->gl_green_size = 5;
|
||||||
state->gl_blue_size = 5;
|
state->gl_blue_size = 5;
|
||||||
|
@ -603,6 +643,7 @@ main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_GetCurrentDisplayMode(0, &mode);
|
SDL_GetCurrentDisplayMode(0, &mode);
|
||||||
|
SDL_Log("Threaded : %s\n", threaded ? "yes" : "no");
|
||||||
SDL_Log("Screen bpp: %d\n", SDL_BITSPERPIXEL(mode.format));
|
SDL_Log("Screen bpp: %d\n", SDL_BITSPERPIXEL(mode.format));
|
||||||
SDL_Log("\n");
|
SDL_Log("\n");
|
||||||
SDL_Log("Vendor : %s\n", ctx.glGetString(GL_VENDOR));
|
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_CULL_FACE));
|
||||||
GL_CHECK(ctx.glEnable(GL_DEPTH_TEST));
|
GL_CHECK(ctx.glEnable(GL_DEPTH_TEST));
|
||||||
|
|
||||||
|
SDL_GL_MakeCurrent(state->windows[i], NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Main render loop */
|
/* Main render loop */
|
||||||
|
@ -734,8 +777,30 @@ main(int argc, char *argv[])
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
emscripten_set_main_loop(loop, 0, 1);
|
emscripten_set_main_loop(loop, 0, 1);
|
||||||
#else
|
#else
|
||||||
while (!done) {
|
if (threaded) {
|
||||||
loop();
|
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
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue