From d65ac7785f50634686989f6147f2e111aa69162f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 22 Jun 2014 02:48:43 -0700 Subject: [PATCH] Restore window OpenGL state if creating an OpenGL renderer fails --- src/render/opengl/SDL_render_gl.c | 31 ++++++++++------- src/render/opengles/SDL_render_gles.c | 37 ++++++++++++--------- src/render/opengles2/SDL_render_gles2.c | 44 ++++++++++++++----------- src/video/SDL_video.c | 5 ++- 4 files changed, 70 insertions(+), 47 deletions(-) diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index f8fe0c4b5..a23d4f03b 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -390,6 +390,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags) GLint value; Uint32 window_flags; int profile_mask, major, minor; + SDL_bool changed_window = SDL_FALSE; SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask); SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major); @@ -398,32 +399,28 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags) window_flags = SDL_GetWindowFlags(window); if (!(window_flags & SDL_WINDOW_OPENGL) || profile_mask == SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) { - + + changed_window = SDL_TRUE; SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR); if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) { - /* Uh oh, better try to put it back... */ - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor); - SDL_RecreateWindow(window, window_flags); - return NULL; + goto error; } } renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); if (!renderer) { SDL_OutOfMemory(); - return NULL; + goto error; } data = (GL_RenderData *) SDL_calloc(1, sizeof(*data)); if (!data) { GL_DestroyRenderer(renderer); SDL_OutOfMemory(); - return NULL; + goto error; } renderer->WindowEvent = GL_WindowEvent; @@ -456,16 +453,16 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags) data->context = SDL_GL_CreateContext(window); if (!data->context) { GL_DestroyRenderer(renderer); - return NULL; + goto error; } if (SDL_GL_MakeCurrent(window, data->context) < 0) { GL_DestroyRenderer(renderer); - return NULL; + goto error; } if (GL_LoadFunctions(data) < 0) { GL_DestroyRenderer(renderer); - return NULL; + goto error; } #ifdef __MACOSX__ @@ -560,6 +557,16 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags) GL_ResetState(renderer); return renderer; + +error: + if (changed_window) { + /* Uh oh, better try to put it back... */ + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor); + SDL_RecreateWindow(window, window_flags); + } + return NULL; } static void diff --git a/src/render/opengles/SDL_render_gles.c b/src/render/opengles/SDL_render_gles.c index dcfd41b6e..90a485bb3 100644 --- a/src/render/opengles/SDL_render_gles.c +++ b/src/render/opengles/SDL_render_gles.c @@ -285,42 +285,39 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags) SDL_Renderer *renderer; GLES_RenderData *data; GLint value; - Uint32 windowFlags; + Uint32 window_flags; int profile_mask, major, minor; + SDL_bool changed_window = SDL_FALSE; SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask); SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major); SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor); - windowFlags = SDL_GetWindowFlags(window); - if (!(windowFlags & SDL_WINDOW_OPENGL) || + window_flags = SDL_GetWindowFlags(window); + if (!(window_flags & SDL_WINDOW_OPENGL) || profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) { + changed_window = SDL_TRUE; SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR); - if (SDL_RecreateWindow(window, windowFlags | SDL_WINDOW_OPENGL) < 0) { - /* Uh oh, better try to put it back... */ - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor); - SDL_RecreateWindow(window, windowFlags); - return NULL; + if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) { + goto error; } } renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); if (!renderer) { SDL_OutOfMemory(); - return NULL; + goto error; } data = (GLES_RenderData *) SDL_calloc(1, sizeof(*data)); if (!data) { GLES_DestroyRenderer(renderer); SDL_OutOfMemory(); - return NULL; + goto error; } renderer->WindowEvent = GLES_WindowEvent; @@ -351,16 +348,16 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags) data->context = SDL_GL_CreateContext(window); if (!data->context) { GLES_DestroyRenderer(renderer); - return NULL; + goto error; } if (SDL_GL_MakeCurrent(window, data->context) < 0) { GLES_DestroyRenderer(renderer); - return NULL; + goto error; } if (GLES_LoadFunctions(data) < 0) { GLES_DestroyRenderer(renderer); - return NULL; + goto error; } if (flags & SDL_RENDERER_PRESENTVSYNC) { @@ -411,6 +408,16 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags) GLES_ResetState(renderer); return renderer; + +error: + if (changed_window) { + /* Uh oh, better try to put it back... */ + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor); + SDL_RecreateWindow(window, window_flags); + } + return NULL; } static void diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 2d7c7baa1..d872b9954 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -1889,30 +1889,27 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) #ifndef ZUNE_HD GLboolean hasCompiler; #endif - Uint32 windowFlags; + Uint32 window_flags; GLint window_framebuffer; GLint value; int profile_mask, major, minor; + SDL_bool changed_window = SDL_FALSE; SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask); SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major); SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor); - windowFlags = SDL_GetWindowFlags(window); - if (!(windowFlags & SDL_WINDOW_OPENGL) || + window_flags = SDL_GetWindowFlags(window); + if (!(window_flags & SDL_WINDOW_OPENGL) || profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) { - + + changed_window = SDL_TRUE; SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR); - if (SDL_RecreateWindow(window, windowFlags | SDL_WINDOW_OPENGL) < 0) { - /* Uh oh, better try to put it back... */ - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor); - SDL_RecreateWindow(window, windowFlags); - return NULL; + if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) { + goto error; } } @@ -1920,14 +1917,14 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(SDL_Renderer)); if (!renderer) { SDL_OutOfMemory(); - return NULL; + goto error; } data = (GLES2_DriverContext *)SDL_calloc(1, sizeof(GLES2_DriverContext)); if (!data) { GLES2_DestroyRenderer(renderer); SDL_OutOfMemory(); - return NULL; + goto error; } renderer->info = GLES2_RenderDriver.info; renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); @@ -1936,19 +1933,18 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) /* Create an OpenGL ES 2.0 context */ data->context = SDL_GL_CreateContext(window); - if (!data->context) - { + if (!data->context) { GLES2_DestroyRenderer(renderer); - return NULL; + goto error; } if (SDL_GL_MakeCurrent(window, data->context) < 0) { GLES2_DestroyRenderer(renderer); - return NULL; + goto error; } if (GLES2_LoadFunctions(data) < 0) { GLES2_DestroyRenderer(renderer); - return NULL; + goto error; } #if __WINRT__ @@ -1996,7 +1992,7 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) { GLES2_DestroyRenderer(renderer); SDL_OutOfMemory(); - return NULL; + goto error; } data->shader_format_count = nFormats; #ifdef ZUNE_HD @@ -2040,6 +2036,16 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) GLES2_ResetState(renderer); return renderer; + +error: + if (changed_window) { + /* Uh oh, better try to put it back... */ + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor); + SDL_RecreateWindow(window, window_flags); + } + return NULL; } #endif /* SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED */ diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 2e097d059..dc6cf37b9 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -1357,6 +1357,7 @@ SDL_RecreateWindow(SDL_Window * window, Uint32 flags) { char *title = window->title; SDL_Surface *icon = window->icon; + SDL_bool loaded_opengl = SDL_FALSE; if ((flags & SDL_WINDOW_OPENGL) && !_this->GL_CreateContext) { return SDL_SetError("No OpenGL support in video driver"); @@ -1389,6 +1390,7 @@ SDL_RecreateWindow(SDL_Window * window, Uint32 flags) if (SDL_GL_LoadLibrary(NULL) < 0) { return -1; } + loaded_opengl = SDL_TRUE; } else { SDL_GL_UnloadLibrary(); } @@ -1402,8 +1404,9 @@ SDL_RecreateWindow(SDL_Window * window, Uint32 flags) if (_this->CreateWindow && !(flags & SDL_WINDOW_FOREIGN)) { if (_this->CreateWindow(_this, window) < 0) { - if ((flags & SDL_WINDOW_OPENGL) && !(window->flags & SDL_WINDOW_OPENGL)) { + if (loaded_opengl) { SDL_GL_UnloadLibrary(); + window->flags &= ~SDL_WINDOW_OPENGL; } return -1; }