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.
This commit is contained in:
Ryan C. Gordon 2022-01-26 17:02:49 -05:00
parent 71e06a536a
commit f37e4a94d3
No known key found for this signature in database
GPG Key ID: FA148B892AB48044
2 changed files with 36 additions and 11 deletions

View File

@ -330,6 +330,7 @@ struct SDL_VideoDevice
/* * * */ /* * * */
/* Data common to all drivers */ /* Data common to all drivers */
SDL_bool checked_texture_framebuffer;
SDL_bool is_dummy; SDL_bool is_dummy;
SDL_bool suspend_screensaver; SDL_bool suspend_screensaver;
SDL_Window *wakeup_window; SDL_Window *wakeup_window;

View File

@ -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 static int
cmpmodes(const void *A, const void *B) 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"); 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, /* 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 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 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 = NULL;
window->surface_valid = SDL_FALSE; 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)) { if (_this->DestroyWindow && !(flags & SDL_WINDOW_FOREIGN)) {
_this->DestroyWindow(_this, window); _this->DestroyWindow(_this, window);
} }
@ -2547,6 +2565,8 @@ SDL_CreateWindowFramebuffer(SDL_Window * window)
int bpp; int bpp;
Uint32 Rmask, Gmask, Bmask, Amask; Uint32 Rmask, Gmask, Bmask, Amask;
PrepareWindowFramebuffer();
if (!_this->CreateWindowFramebuffer || !_this->UpdateWindowFramebuffer) { if (!_this->CreateWindowFramebuffer || !_this->UpdateWindowFramebuffer) {
return NULL; 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"); 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); return _this->UpdateWindowFramebuffer(_this, window, rects, numrects);
} }
@ -3138,8 +3160,10 @@ SDL_DestroyWindow(SDL_Window * window)
window->surface = NULL; window->surface = NULL;
window->surface_valid = SDL_FALSE; window->surface_valid = SDL_FALSE;
} }
if (_this->DestroyWindowFramebuffer) { if (_this->checked_texture_framebuffer) { /* never checked? No framebuffer to destroy. Don't risk calling the wrong implementation. */
_this->DestroyWindowFramebuffer(_this, window); if (_this->DestroyWindowFramebuffer) {
_this->DestroyWindowFramebuffer(_this, window);
}
} }
if (_this->DestroyWindow) { if (_this->DestroyWindow) {
_this->DestroyWindow(_this, window); _this->DestroyWindow(_this, window);