From f37e4a94d3acaa5c1872386d5a682292d48faf93 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 26 Jan 2022 17:02:49 -0500 Subject: [PATCH] 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. --- src/video/SDL_sysvideo.h | 1 + src/video/SDL_video.c | 46 ++++++++++++++++++++++++++++++---------- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 3f401a5b2..470c14ba3 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 d3fe65502..b0a7058d7 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);