sdl12-compat: Hook into glBindFramebuffer and enable OpenGL scaling by default.

From dbb8868e716ada768d6475c52cb986e42128ac6b Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Tue, 27 Apr 2021 15:37:01 -0400
Subject: [PATCH] Hook into glBindFramebuffer and enable OpenGL scaling by
 default.

This makes GL scaling work with UT2004 and other things that use OpenGL
framebuffer objects. We make sure when they want to render to the window
framebuffer, they render to our FBO instead, so we can still scale the
final output at the end of the frame.
---
 src/SDL12_compat.c | 35 +++++++++++++++++++++++++++++++----
 src/SDL20_syms.h   |  2 +-
 2 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/src/SDL12_compat.c b/src/SDL12_compat.c
index d5f055b..3201069 100644
--- a/src/SDL12_compat.c
+++ b/src/SDL12_compat.c
@@ -3181,11 +3181,23 @@ LoadOpenGLFunctions(void)
     #include "SDL20_syms.h"
 }
 
+/* if the app binds its own framebuffer objects, it'll try to bind the window framebuffer
+   (always zero) to draw to the screen, but if we're using a framebuffer object to handle
+   scaling, we need to catch those binds and make sure rendering intended for the window
+   framebuffer is redirected to our scaling FBO, so we have SDL_GL_GetProcAddress() hand out
+   a shim for glBindFramebuffer to catch this. */
+static void GLAPIENTRY
+glBindFramebuffer_shim_for_scaling(GLenum target, GLuint name)
+{
+    /* OpenGLLogicalScalingFBO will be zero if we aren't scaling, making this use the default. */
+    /*if ((name == 0) && (OpenGLLogicalScalingFBO != 0)) { SDL20_Log("OVERRIDE WINDOW FRAMEBUFFER FOR SCALING!"); }*/
+    OpenGLFuncs.glBindFramebuffer(target, (name == 0) ? OpenGLLogicalScalingFBO : name);
+}
+
+
 static SDL_bool
 InitializeOpenGLScaling(const int w, const int h)
 {
-    LoadOpenGLFunctions();
-
     if (!OpenGLFuncs.SUPPORTS_GL_ARB_framebuffer_object) {
         return SDL_FALSE;  /* no FBOs, no scaling. */
     }
@@ -3239,9 +3251,12 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags12)
            work with these apps, too. That's easy from SDL_GL_GetProcAddress, but we
            maybe need to export the symbol from here too, for those that link against
            OpenGL directly. UT2004 is known to use FBOs with SDL 1.2, and I assume
-           idTech 4 games (Doom 3, Quake 4, Prey) do as well.*/
+           idTech 4 games (Doom 3, Quake 4, Prey) do as well. */
         const char *env = SDL20_getenv("SDL12COMPAT_OPENGL_SCALING");
-        use_gl_scaling = (env && SDL20_atoi(env)) ? SDL_TRUE : SDL_FALSE;
+
+        /* for now we default GL scaling to ENABLED. If an app breaks or is linked directly
+           to glBindFramebuffer, they'll need to turn it off with this environment variable */
+        use_gl_scaling = (!env || SDL20_atoi(env)) ? SDL_TRUE : SDL_FALSE;
     }
 
     FIXME("currently ignores SDL_WINDOWID, which we could use with SDL_CreateWindowFrom ...?");
@@ -3391,6 +3406,8 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags12)
 
         VideoSurface12->flags |= SDL12_OPENGL;
 
+        LoadOpenGLFunctions();
+
         /* Try to set up a logical scaling */
         if (use_gl_scaling) {
             if (!InitializeOpenGLScaling(width, height)) {
@@ -4193,6 +4210,16 @@ SDL_FreeYUVOverlay(SDL12_Overlay * overlay)
     FIXME("write me");
 }
 
+DECLSPEC void * SDLCALL
+SDL_GL_GetProcAddress(const char *sym)
+{
+    /* see comments on glBindFramebuffer_shim_for_scaling for explanation */
+    if ((SDL_strcmp(sym, "glBindFramebuffer") == 0) || (SDL_strcmp(sym, "glBindFramebufferEXT") == 0)) {
+        return (void *) glBindFramebuffer_shim_for_scaling;
+    }
+    return SDL20_GL_GetProcAddress(sym);
+}
+
 DECLSPEC int SDLCALL
 SDL_GL_LoadLibrary(const char *libname)
 {
diff --git a/src/SDL20_syms.h b/src/SDL20_syms.h
index 85cb2c9..8663122 100644
--- a/src/SDL20_syms.h
+++ b/src/SDL20_syms.h
@@ -118,7 +118,7 @@ SDL20_SYM(int,SaveBMP_RW,(SDL_Surface *a, SDL_RWops *b, int c),(a,b,c),return)
 SDL20_SYM(int,SetPaletteColors,(SDL_Palette *a, const SDL_Color *b, int c, int d),(a,b,c,d),return)
 SDL20_SYM(SDL_bool,GL_ExtensionSupported,(const char *a),(a),return)
 SDL20_SYM(int,GL_LoadLibrary,(const char *a),(a),return)
-SDL20_SYM_PASSTHROUGH(void *,GL_GetProcAddress,(const char *a),(a),return)
+SDL20_SYM(void *,GL_GetProcAddress,(const char *a),(a),return)
 SDL20_SYM(int,GL_SetAttribute,(SDL_GLattr a, int b),(a,b),return)
 SDL20_SYM(int,GL_GetAttribute,(SDL_GLattr a, int *b),(a,b),return)
 SDL20_SYM(int,GL_SetSwapInterval,(int a),(a),return)