sdl2-compat: opengl: Implemented SDL_GL_BindTexture and SDL_GL_UnbindTexture.

From e37526c5fb3eb91d88e7d8e12a28409b9c593e3d Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Mon, 8 Jan 2024 14:10:14 -0500
Subject: [PATCH] opengl: Implemented SDL_GL_BindTexture and
 SDL_GL_UnbindTexture.

These were removed from SDL3, replaced with texture properties for DIY
purposes.
---
 src/sdl2_compat.c          | 204 +++++++++++++++++++++++++++++++++++++
 src/sdl3_include_wrapper.h |  15 +--
 src/sdl3_syms.h            |   4 +-
 3 files changed, 211 insertions(+), 12 deletions(-)

diff --git a/src/sdl2_compat.c b/src/sdl2_compat.c
index 91b6da0..eb2b944 100644
--- a/src/sdl2_compat.c
+++ b/src/sdl2_compat.c
@@ -176,6 +176,8 @@ do { \
     } \
 } while (SDL_NULL_WHILE_LOOP_CONDITION)
 
+#include <SDL3/SDL_opengl.h>
+#include <SDL3/SDL_opengl_glext.h>
 
 static SDL_bool WantDebugLogging = SDL_FALSE;
 static Uint32 LinkedSDL3VersionInt = 0;
@@ -6331,6 +6333,208 @@ SDL_GL_SwapWindow(SDL_Window *window)
     (void) SDL3_GL_SwapWindow(window);
 }
 
+typedef void (GLAPIENTRY *openglfn_glEnable_t)(GLenum what);
+typedef void (GLAPIENTRY *openglfn_glDisable_t)(GLenum what);
+typedef void (GLAPIENTRY *openglfn_glActiveTexture_t)(GLenum what);
+typedef void (GLAPIENTRY *openglfn_glBindTexture_t)(GLenum target, GLuint name);
+typedef openglfn_glActiveTexture_t openglfn_glActiveTextureARB_t;
+
+static void *getglfn(const char *fn, SDL_bool *okay)
+{
+    void *retval = NULL;
+    if (*okay) {
+        retval = SDL3_GL_GetProcAddress(fn);
+        if (retval == NULL) {
+            *okay = SDL_FALSE;
+            SDL_SetError("Failed to find GL proc address of %s", fn);
+        }
+    }
+    return retval;
+}
+
+#define GLFN(fn) openglfn_##fn##_t p##fn = (openglfn_##fn##_t) getglfn(#fn, &okay)
+
+
+DECLSPEC int SDLCALL
+SDL_GL_BindTexture(SDL_Texture *texture, float *texw, float *texh)
+{
+    SDL_PropertiesID props;
+    SDL_Renderer *renderer;
+    Sint64 tex;
+
+    /* SDL3_GetTextureRenderer will do all the CHECK_TEXTURE_MAGIC stuff. */
+    renderer = SDL3_GetTextureRenderer(texture);
+    if (!renderer) {
+        return -1;
+    }
+
+    props = SDL3_GetTextureProperties(texture);
+    if (!props) {
+        return -1;
+    }
+
+    /* always flush the renderer here; good enough. SDL2 only flushed if the texture might have changed, but we'll be conservative. */
+    SDL3_FlushRenderer(renderer);
+
+    if ((tex = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_NUMBER, -1)) != -1) {  // opengl renderer.
+        const Sint64 target = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_TARGET, 0);
+        const Sint64 uv = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_UV_NUMBER, 0);
+        const Sint64 u = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_U_NUMBER, 0);
+        const Sint64 v = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_V_NUMBER, 0);
+
+        SDL_bool okay = SDL_TRUE;
+        GLFN(glEnable);
+        GLFN(glActiveTextureARB);
+        GLFN(glBindTexture);
+
+        if (!okay) {
+            return -1;
+        }
+
+        pglEnable((GLenum) target);
+
+        if (u & v) {
+            pglActiveTextureARB(GL_TEXTURE2_ARB);
+            pglBindTexture((GLenum) target, (GLuint) v);
+            pglActiveTextureARB(GL_TEXTURE1_ARB);
+            pglBindTexture((GLenum) target, (GLuint) u);
+            pglActiveTextureARB(GL_TEXTURE0_ARB);
+        } else if (uv) {
+            pglActiveTextureARB(GL_TEXTURE1_ARB);
+            pglBindTexture((GLenum) target, (GLuint) uv);
+            pglActiveTextureARB(GL_TEXTURE0_ARB);
+        }
+        pglBindTexture((GLenum) target, (GLuint) tex);
+
+        if (texw) {
+            *texw = SDL3_GetFloatProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEX_W_FLOAT, 0.0f);
+        }
+        if (texh) {
+            *texh = SDL3_GetFloatProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEX_H_FLOAT, 0.0f);
+        }
+    } else if ((tex = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER, -1)) != -1) {  // opengles2 renderer.
+        const Sint64 target = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_TARGET, 0);
+        const Sint64 uv = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER, 0);
+        const Sint64 u = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER, 0);
+        const Sint64 v = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER, 0);
+
+        SDL_bool okay = SDL_TRUE;
+        GLFN(glActiveTexture);
+        GLFN(glBindTexture);
+
+        if (!okay) {
+            return -1;
+        }
+
+        if (u & v) {
+            pglActiveTexture(GL_TEXTURE2);
+            pglBindTexture((GLenum) target, (GLuint) v);
+            pglActiveTexture(GL_TEXTURE1);
+            pglBindTexture((GLenum) target, (GLuint) u);
+            pglActiveTexture(GL_TEXTURE0);
+        } else if (uv) {
+            pglActiveTexture(GL_TEXTURE1);
+            pglBindTexture((GLenum) target, (GLuint) uv);
+            pglActiveTexture(GL_TEXTURE0);
+        }
+        pglBindTexture((GLenum) target, (GLuint) tex);
+
+        if (texw) {
+            *texw = 1.0f;
+        }
+        if (texh) {
+            *texh = 1.0f;
+        }
+    }
+
+    return 0;
+}
+
+DECLSPEC int SDLCALL
+SDL_GL_UnbindTexture(SDL_Texture *texture)
+{
+    SDL_PropertiesID props;
+    SDL_Renderer *renderer;
+    Sint64 tex;
+
+    /* SDL3_GetTextureRenderer will do all the CHECK_TEXTURE_MAGIC stuff. */
+    renderer = SDL3_GetTextureRenderer(texture);
+    if (!renderer) {
+        return -1;
+    }
+
+    props = SDL3_GetTextureProperties(texture);
+    if (!props) {
+        return -1;
+    }
+
+    if ((tex = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_NUMBER, -1)) != -1) {  // opengl renderer.
+        const Sint64 target = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_TARGET, 0);
+        const Sint64 uv = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_UV_NUMBER, 0);
+        const Sint64 u = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_U_NUMBER, 0);
+        const Sint64 v = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_V_NUMBER, 0);
+
+        SDL_bool okay = SDL_TRUE;
+        GLFN(glDisable);
+        GLFN(glActiveTextureARB);
+        GLFN(glBindTexture);
+
+        if (!okay) {
+            return -1;
+        }
+
+        if (u & v) {
+            pglActiveTextureARB(GL_TEXTURE2_ARB);
+            pglBindTexture((GLenum) target, 0);
+            pglDisable((GLenum) target);
+            pglActiveTextureARB(GL_TEXTURE1_ARB);
+            pglBindTexture((GLenum) target, 0);
+            pglDisable((GLenum) target);
+            pglActiveTextureARB(GL_TEXTURE0_ARB);
+        } else if (uv) {
+            pglActiveTextureARB(GL_TEXTURE1_ARB);
+            pglBindTexture((GLenum) target, 0);
+            pglDisable((GLenum) target);
+            pglActiveTextureARB(GL_TEXTURE0_ARB);
+        }
+        pglBindTexture((GLenum) target, 0);
+        pglDisable((GLenum) target);
+    } else if ((tex = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER, -1)) != -1) {  // opengles2 renderer.
+        const Sint64 target = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_TARGET, 0);
+        const Sint64 uv = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER, 0);
+        const Sint64 u = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER, 0);
+        const Sint64 v = SDL3_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER, 0);
+
+        SDL_bool okay = SDL_TRUE;
+        GLFN(glActiveTexture);
+        GLFN(glBindTexture);
+
+        if (!okay) {
+            return -1;
+        }
+
+        if (u & v) {
+            pglActiveTexture(GL_TEXTURE2);
+            pglBindTexture((GLenum) target, 0);
+            pglActiveTexture(GL_TEXTURE1);
+            pglBindTexture((GLenum) target, 0);
+            pglActiveTexture(GL_TEXTURE0);
+        } else if (uv) {
+            pglActiveTexture(GL_TEXTURE1);
+            pglBindTexture((GLenum) target, 0);
+            pglActiveTexture(GL_TEXTURE0);
+        }
+        pglBindTexture((GLenum) target, 0);
+    }
+
+    /* always flush the renderer here, in case of app shenanigans. */
+    SDL3_FlushRenderer(renderer);
+
+    return 0;
+}
+
+#undef GLFN
+
 DECLSPEC void SDLCALL
 SDL_GetClipRect(SDL_Surface *surface, SDL_Rect *rect)
 {
diff --git a/src/sdl3_include_wrapper.h b/src/sdl3_include_wrapper.h
index 140b534..9fd6bce 100644
--- a/src/sdl3_include_wrapper.h
+++ b/src/sdl3_include_wrapper.h
@@ -136,7 +136,6 @@
 #define SDL_FlushRenderer IGNORE_THIS_VERSION_OF_SDL_FlushRenderer
 #define SDL_GDKGetTaskQueue IGNORE_THIS_VERSION_OF_SDL_GDKGetTaskQueue
 #define SDL_GDKSuspendComplete IGNORE_THIS_VERSION_OF_SDL_GDKSuspendComplete
-#define SDL_GL_BindTexture IGNORE_THIS_VERSION_OF_SDL_GL_BindTexture
 #define SDL_GL_CreateContext IGNORE_THIS_VERSION_OF_SDL_GL_CreateContext
 #define SDL_GL_DeleteContext IGNORE_THIS_VERSION_OF_SDL_GL_DeleteContext
 #define SDL_GL_ExtensionSupported IGNORE_THIS_VERSION_OF_SDL_GL_ExtensionSupported
@@ -151,7 +150,6 @@
 #define SDL_GL_SetAttribute IGNORE_THIS_VERSION_OF_SDL_GL_SetAttribute
 #define SDL_GL_SetSwapInterval IGNORE_THIS_VERSION_OF_SDL_GL_SetSwapInterval
 #define SDL_GL_SwapWindow IGNORE_THIS_VERSION_OF_SDL_GL_SwapWindow
-#define SDL_GL_UnbindTexture IGNORE_THIS_VERSION_OF_SDL_GL_UnbindTexture
 #define SDL_GL_UnloadLibrary IGNORE_THIS_VERSION_OF_SDL_GL_UnloadLibrary
 #define SDL_GUIDFromString IGNORE_THIS_VERSION_OF_SDL_GUIDFromString
 #define SDL_GUIDToString IGNORE_THIS_VERSION_OF_SDL_GUIDToString
@@ -347,6 +345,7 @@
 #define SDL_GetTextureAlphaMod IGNORE_THIS_VERSION_OF_SDL_GetTextureAlphaMod
 #define SDL_GetTextureBlendMode IGNORE_THIS_VERSION_OF_SDL_GetTextureBlendMode
 #define SDL_GetTextureColorMod IGNORE_THIS_VERSION_OF_SDL_GetTextureColorMod
+#define SDL_GetTextureRenderer IGNORE_THIS_VERSION_OF_SDL_GetTextureRenderer
 #define SDL_GetTextureScaleMode IGNORE_THIS_VERSION_OF_SDL_GetTextureScaleMode
 #define SDL_GetThreadID IGNORE_THIS_VERSION_OF_SDL_GetThreadID
 #define SDL_GetThreadName IGNORE_THIS_VERSION_OF_SDL_GetThreadName
@@ -1448,10 +1447,6 @@
 #undef SDL_GDKSuspendComplete
 #endif
 
-#ifdef SDL_GL_BindTexture
-#undef SDL_GL_BindTexture
-#endif
-
 #ifdef SDL_GL_CreateContext
 #undef SDL_GL_CreateContext
 #endif
@@ -1508,10 +1503,6 @@
 #undef SDL_GL_SwapWindow
 #endif
 
-#ifdef SDL_GL_UnbindTexture
-#undef SDL_GL_UnbindTexture
-#endif
-
 #ifdef SDL_GL_UnloadLibrary
 #undef SDL_GL_UnloadLibrary
 #endif
@@ -2292,6 +2283,10 @@
 #undef SDL_GetTextureColorMod
 #endif
 
+#ifdef SDL_GetTextureRenderer
+#undef SDL_GetTextureRenderer
+#endif
+
 #ifdef SDL_GetTextureScaleMode
 #undef SDL_GetTextureScaleMode
 #endif
diff --git a/src/sdl3_syms.h b/src/sdl3_syms.h
index 1278101..cd39816 100644
--- a/src/sdl3_syms.h
+++ b/src/sdl3_syms.h
@@ -323,6 +323,7 @@ SDL3_SYM_PASSTHROUGH(int,SetTextureAlphaMod,(SDL_Texture *a, Uint8 b),(a,b),retu
 SDL3_SYM_PASSTHROUGH(int,GetTextureAlphaMod,(SDL_Texture *a, Uint8 *b),(a,b),return)
 SDL3_SYM_PASSTHROUGH(int,SetTextureBlendMode,(SDL_Texture *a, SDL_BlendMode b),(a,b),return)
 SDL3_SYM_PASSTHROUGH(int,GetTextureBlendMode,(SDL_Texture *a, SDL_BlendMode *b),(a,b),return)
+SDL3_SYM(SDL_Renderer *,GetTextureRenderer,(SDL_Texture *a),(a),return)
 SDL3_SYM_PASSTHROUGH(int,UpdateTexture,(SDL_Texture *a, const SDL_Rect *b, const void *c, int d),(a,b,c,d),return)
 SDL3_SYM_PASSTHROUGH(int,UpdateYUVTexture,(SDL_Texture *a, const SDL_Rect *b, const Uint8 *c, int d, const Uint8 *e, int f, const Uint8 *g, int h),(a,b,c,d,e,f,g,h),return)
 SDL3_SYM_PASSTHROUGH(int,LockTexture,(SDL_Texture *a, const SDL_Rect *b, void **c, int *d),(a,b,c,d),return)
@@ -344,8 +345,6 @@ SDL3_SYM_PASSTHROUGH(int,RenderReadPixels,(SDL_Renderer *a, const SDL_Rect *b, U
 SDL3_SYM(int,RenderPresent,(SDL_Renderer *a),(a),return)
 SDL3_SYM(void,DestroyTexture,(SDL_Texture *a),(a),)
 SDL3_SYM(void,DestroyRenderer,(SDL_Renderer *a),(a),)
-SDL3_SYM_PASSTHROUGH(int,GL_BindTexture,(SDL_Texture *a, float *b, float *c),(a,b,c),return)
-SDL3_SYM_PASSTHROUGH(int,GL_UnbindTexture,(SDL_Texture *a),(a),return)
 SDL3_SYM(SDL_RWops*,RWFromFile,(const char *a, const char *b),(a,b),return)
 SDL3_SYM(SDL_RWops*,RWFromMem,(void *a, size_t b),(a,b),return)
 SDL3_SYM(SDL_RWops*,RWFromConstMem,(const void *a, size_t b),(a,b),return)
@@ -858,6 +857,7 @@ SDL3_SYM(SDL_PropertiesID,GetRendererProperties,(SDL_Renderer *a),(a),return)
 SDL3_SYM(SDL_GamepadButtonLabel,GetGamepadButtonLabel,(SDL_Gamepad *a, SDL_GamepadButton b),(a,b),return)
 SDL3_SYM(Sint64,GetNumberProperty,(SDL_PropertiesID a, const char *b, Sint64 c),(a,b,c),return)
 SDL3_SYM(SDL_bool,GetBooleanProperty,(SDL_PropertiesID a, const char *b, SDL_bool c),(a,b,c),return)
+SDL3_SYM(SDL_bool,GetFloatProperty,(SDL_PropertiesID a, const char *b, float c),(a,b,c),return)
 SDL3_SYM(SDL_PropertiesID,CreateProperties,(void),(),return)
 SDL3_SYM(int,SetBooleanProperty,(SDL_PropertiesID a, const char *b, SDL_bool c),(a,b,c),return)
 SDL3_SYM(int,SetNumberProperty,(SDL_PropertiesID a, const char *b, Sint64 c),(a,b,c),return)