video: Don't check if we can use a "texture framebuffer" until needed. This prevents SDL from making an OpenGL context and maybe throwing it away immediately by default. It will now only do it when trying to request a window framebuffer directly, or creating an SDL_Renderer with the "software" backend, which makes that request itself. The way SDL decides if it should use a "texture framebuffer" needs dramatic updating, but this solves the immediate problem. Reference Issue #4624.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index 3f401a5..470c14b 100644
--- a/src/video/SDL_sysvideo.h
+++ b/src/video/SDL_sysvideo.h
@@ -330,6 +330,7 @@ struct SDL_VideoDevice
/* * * */
/* Data common to all drivers */
+ SDL_bool checked_texture_framebuffer;
SDL_bool is_dummy;
SDL_bool suspend_screensaver;
SDL_Window *wakeup_window;
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index d3fe655..b0a7058 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -414,6 +414,27 @@ SDL_DestroyWindowTexture(SDL_VideoDevice *unused, SDL_Window * window)
}
+/* This will switch the video backend from using a software surface to
+ using a GPU texture through the 2D render API, if we think this would
+ be more efficient. This only checks once, on demand. */
+static void
+PrepareWindowFramebuffer()
+{
+ /* Add the renderer framebuffer emulation if desired */
+ if (_this->checked_texture_framebuffer) {
+ return;
+ }
+
+ _this->checked_texture_framebuffer = SDL_TRUE;
+
+ if (ShouldUseTextureFramebuffer()) {
+ _this->CreateWindowFramebuffer = SDL_CreateWindowTexture;
+ _this->UpdateWindowFramebuffer = SDL_UpdateWindowTexture;
+ _this->DestroyWindowFramebuffer = SDL_DestroyWindowTexture;
+ }
+}
+
+
static int
cmpmodes(const void *A, const void *B)
{
@@ -564,13 +585,6 @@ SDL_VideoInit(const char *driver_name)
return SDL_SetError("The video driver did not add any displays");
}
- /* Add the renderer framebuffer emulation if desired */
- if (ShouldUseTextureFramebuffer()) {
- _this->CreateWindowFramebuffer = SDL_CreateWindowTexture;
- _this->UpdateWindowFramebuffer = SDL_UpdateWindowTexture;
- _this->DestroyWindowFramebuffer = SDL_DestroyWindowTexture;
- }
-
/* Disable the screen saver by default. This is a change from <= 2.0.1,
but most things using SDL are games or media players; you wouldn't
want a screensaver to trigger if you're playing exclusively with a
@@ -1827,9 +1841,13 @@ SDL_RecreateWindow(SDL_Window * window, Uint32 flags)
window->surface = NULL;
window->surface_valid = SDL_FALSE;
}
- if (_this->DestroyWindowFramebuffer) {
- _this->DestroyWindowFramebuffer(_this, window);
+
+ if (_this->checked_texture_framebuffer) { /* never checked? No framebuffer to destroy. Don't risk calling the wrong implementation. */
+ if (_this->DestroyWindowFramebuffer) {
+ _this->DestroyWindowFramebuffer(_this, window);
+ }
}
+
if (_this->DestroyWindow && !(flags & SDL_WINDOW_FOREIGN)) {
_this->DestroyWindow(_this, window);
}
@@ -2547,6 +2565,8 @@ SDL_CreateWindowFramebuffer(SDL_Window * window)
int bpp;
Uint32 Rmask, Gmask, Bmask, Amask;
+ PrepareWindowFramebuffer();
+
if (!_this->CreateWindowFramebuffer || !_this->UpdateWindowFramebuffer) {
return NULL;
}
@@ -2610,6 +2630,8 @@ SDL_UpdateWindowSurfaceRects(SDL_Window * window, const SDL_Rect * rects,
return SDL_SetError("Window surface is invalid, please call SDL_GetWindowSurface() to get a new surface");
}
+ SDL_assert(_this->checked_texture_framebuffer); /* we should have done this before we had a valid surface. */
+
return _this->UpdateWindowFramebuffer(_this, window, rects, numrects);
}
@@ -3138,8 +3160,10 @@ SDL_DestroyWindow(SDL_Window * window)
window->surface = NULL;
window->surface_valid = SDL_FALSE;
}
- if (_this->DestroyWindowFramebuffer) {
- _this->DestroyWindowFramebuffer(_this, window);
+ if (_this->checked_texture_framebuffer) { /* never checked? No framebuffer to destroy. Don't risk calling the wrong implementation. */
+ if (_this->DestroyWindowFramebuffer) {
+ _this->DestroyWindowFramebuffer(_this, window);
+ }
}
if (_this->DestroyWindow) {
_this->DestroyWindow(_this, window);