SDL: Removed SDL_GL_BindTexture() and SDL_GL_UnbindTexture()

From 7eae08cfc4d7bb7642590a573c1263247c95ea22 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sun, 7 Jan 2024 18:02:49 -0800
Subject: [PATCH] Removed SDL_GL_BindTexture() and SDL_GL_UnbindTexture()

Now that we have the OpenGL texture properties, you can directly bind them yourself.

Fixes https://github.com/libsdl-org/SDL/issues/2124
---
 docs/README-migration.md                |   2 +
 include/SDL3/SDL_render.h               |  54 -------------
 src/dynapi/SDL_dynapi.sym               |   2 -
 src/dynapi/SDL_dynapi_overrides.h       |   2 -
 src/dynapi/SDL_dynapi_procs.h           |   2 -
 src/render/SDL_render.c                 |  32 --------
 src/render/SDL_sysrender.h              |   3 -
 src/render/opengl/SDL_render_gl.c       | 103 +-----------------------
 src/render/opengles2/SDL_render_gles2.c |  53 ------------
 test/testffmpeg.c                       |  14 +++-
 10 files changed, 13 insertions(+), 254 deletions(-)

diff --git a/docs/README-migration.md b/docs/README-migration.md
index 20c7216841e1..959fd0def252 100644
--- a/docs/README-migration.md
+++ b/docs/README-migration.md
@@ -959,6 +959,8 @@ The following functions have been renamed:
 * SDL_RenderWindowToLogical() => SDL_RenderCoordinatesFromWindow()
 
 The following functions have been removed:
+* SDL_GL_BindTexture() - use SDL_GetTextureProperties() to get the OpenGL texture ID and bind the texture directly
+* SDL_GL_UnbindTexture() - use SDL_GetTextureProperties() to get the OpenGL texture ID and unbind the texture directly
 * SDL_GetTextureUserData() - use SDL_GetTextureProperties() instead
 * SDL_RenderGetIntegerScale()
 * SDL_RenderSetIntegerScale() - this is now explicit with SDL_LOGICAL_PRESENTATION_INTEGER_SCALE
diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h
index 5780c29b904d..e689b94c202d 100644
--- a/include/SDL3/SDL_render.h
+++ b/include/SDL3/SDL_render.h
@@ -1746,60 +1746,6 @@ extern DECLSPEC void SDLCALL SDL_DestroyRenderer(SDL_Renderer *renderer);
  */
 extern DECLSPEC int SDLCALL SDL_FlushRenderer(SDL_Renderer *renderer);
 
-
-/**
- * Bind an OpenGL/ES/ES2 texture to the current context.
- *
- * This is for use with OpenGL instructions when rendering OpenGL primitives
- * directly.
- *
- * If not NULL, `texw` and `texh` will be filled with the width and height
- * values suitable for the provided texture. In most cases, both will be 1.0,
- * however, on systems that support the GL_ARB_texture_rectangle extension,
- * these values will actually be the pixel width and height used to create the
- * texture, so this factor needs to be taken into account when providing
- * texture coordinates to OpenGL.
- *
- * You need a renderer to create an SDL_Texture, therefore you can only use
- * this function with an implicit OpenGL context from SDL_CreateRenderer(),
- * not with your own OpenGL context. If you need control over your OpenGL
- * context, you need to write your own texture-loading methods.
- *
- * Also note that SDL may upload RGB textures as BGR (or vice-versa), and
- * re-order the color channels in the shaders phase, so the uploaded texture
- * may have swapped color channels.
- *
- * \param texture the texture to bind to the current OpenGL/ES/ES2 context
- * \param texw a pointer to a float value which will be filled with the
- *             texture width or NULL if you don't need that value
- * \param texh a pointer to a float value which will be filled with the
- *             texture height or NULL if you don't need that value
- * \returns 0 on success or a negative error code on failure; call
- *          SDL_GetError() for more information.
- *
- * \since This function is available since SDL 3.0.0.
- *
- * \sa SDL_GL_MakeCurrent
- * \sa SDL_GL_UnbindTexture
- */
-extern DECLSPEC int SDLCALL SDL_GL_BindTexture(SDL_Texture *texture, float *texw, float *texh);
-
-/**
- * Unbind an OpenGL/ES/ES2 texture from the current context.
- *
- * See SDL_GL_BindTexture() for examples on how to use these functions
- *
- * \param texture the texture to unbind from the current OpenGL/ES/ES2 context
- * \returns 0 on success or a negative error code on failure; call
- *          SDL_GetError() for more information.
- *
- * \since This function is available since SDL 3.0.0.
- *
- * \sa SDL_GL_BindTexture
- * \sa SDL_GL_MakeCurrent
- */
-extern DECLSPEC int SDLCALL SDL_GL_UnbindTexture(SDL_Texture *texture);
-
 /**
  * Get the CAMetalLayer associated with the given Metal renderer.
  *
diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym
index a72032cd281e..4e3ea9e52ae1 100644
--- a/src/dynapi/SDL_dynapi.sym
+++ b/src/dynapi/SDL_dynapi.sym
@@ -110,7 +110,6 @@ SDL3_0.0.0 {
     SDL_FlushRenderer;
     SDL_GDKGetTaskQueue;
     SDL_GDKSuspendComplete;
-    SDL_GL_BindTexture;
     SDL_GL_CreateContext;
     SDL_GL_DeleteContext;
     SDL_GL_ExtensionSupported;
@@ -125,7 +124,6 @@ SDL3_0.0.0 {
     SDL_GL_SetAttribute;
     SDL_GL_SetSwapInterval;
     SDL_GL_SwapWindow;
-    SDL_GL_UnbindTexture;
     SDL_GL_UnloadLibrary;
     SDL_GUIDFromString;
     SDL_GUIDToString;
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index 52abfed6b9c1..0e2636fa4f4f 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -134,7 +134,6 @@
 #define SDL_FlushRenderer SDL_FlushRenderer_REAL
 #define SDL_GDKGetTaskQueue SDL_GDKGetTaskQueue_REAL
 #define SDL_GDKSuspendComplete  SDL_GDKSuspendComplete_REAL
-#define SDL_GL_BindTexture SDL_GL_BindTexture_REAL
 #define SDL_GL_CreateContext SDL_GL_CreateContext_REAL
 #define SDL_GL_DeleteContext SDL_GL_DeleteContext_REAL
 #define SDL_GL_ExtensionSupported SDL_GL_ExtensionSupported_REAL
@@ -149,7 +148,6 @@
 #define SDL_GL_SetAttribute SDL_GL_SetAttribute_REAL
 #define SDL_GL_SetSwapInterval SDL_GL_SetSwapInterval_REAL
 #define SDL_GL_SwapWindow SDL_GL_SwapWindow_REAL
-#define SDL_GL_UnbindTexture SDL_GL_UnbindTexture_REAL
 #define SDL_GL_UnloadLibrary SDL_GL_UnloadLibrary_REAL
 #define SDL_GUIDFromString SDL_GUIDFromString_REAL
 #define SDL_GUIDToString SDL_GUIDToString_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index 04cb56bc7c10..fbd18f1b8ef8 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -194,7 +194,6 @@ SDL_DYNAPI_PROC(int,SDL_FlashWindow,(SDL_Window *a, SDL_FlashOperation b),(a,b),
 SDL_DYNAPI_PROC(void,SDL_FlushEvent,(Uint32 a),(a),)
 SDL_DYNAPI_PROC(void,SDL_FlushEvents,(Uint32 a, Uint32 b),(a,b),)
 SDL_DYNAPI_PROC(int,SDL_FlushRenderer,(SDL_Renderer *a),(a),return)
-SDL_DYNAPI_PROC(int,SDL_GL_BindTexture,(SDL_Texture *a, float *b, float *c),(a,b,c),return)
 SDL_DYNAPI_PROC(SDL_GLContext,SDL_GL_CreateContext,(SDL_Window *a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_GL_DeleteContext,(SDL_GLContext a),(a),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_GL_ExtensionSupported,(const char *a),(a),return)
@@ -209,7 +208,6 @@ SDL_DYNAPI_PROC(void,SDL_GL_ResetAttributes,(void),(),)
 SDL_DYNAPI_PROC(int,SDL_GL_SetAttribute,(SDL_GLattr a, int b),(a,b),return)
 SDL_DYNAPI_PROC(int,SDL_GL_SetSwapInterval,(int a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_GL_SwapWindow,(SDL_Window *a),(a),return)
-SDL_DYNAPI_PROC(int,SDL_GL_UnbindTexture,(SDL_Texture *a),(a),return)
 SDL_DYNAPI_PROC(void,SDL_GL_UnloadLibrary,(void),(),)
 SDL_DYNAPI_PROC(SDL_GUID,SDL_GUIDFromString,(const char *a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_GUIDToString,(SDL_GUID a, char *b, int c),(a,b,c),return)
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index 6c2a351202de..76f8074e8ae8 100644
--- a/src/render/SDL_render.c
+++ b/src/render/SDL_render.c
@@ -4153,38 +4153,6 @@ void SDL_DestroyRenderer(SDL_Renderer *renderer)
     renderer->DestroyRenderer(renderer);
 }
 
-int SDL_GL_BindTexture(SDL_Texture *texture, float *texw, float *texh)
-{
-    SDL_Renderer *renderer;
-
-    CHECK_TEXTURE_MAGIC(texture, -1);
-    renderer = texture->renderer;
-    if (texture->native) {
-        return SDL_GL_BindTexture(texture->native, texw, texh);
-    } else if (renderer && renderer->GL_BindTexture) {
-        FlushRenderCommandsIfTextureNeeded(texture); /* in case the app is going to mess with it. */
-        return renderer->GL_BindTexture(renderer, texture, texw, texh);
-    } else {
-        return SDL_Unsupported();
-    }
-}
-
-int SDL_GL_UnbindTexture(SDL_Texture *texture)
-{
-    SDL_Renderer *renderer;
-
-    CHECK_TEXTURE_MAGIC(texture, -1);
-    renderer = texture->renderer;
-    if (texture->native) {
-        return SDL_GL_UnbindTexture(texture->native);
-    } else if (renderer && renderer->GL_UnbindTexture) {
-        FlushRenderCommandsIfTextureNeeded(texture); /* in case the app messed with it. */
-        return renderer->GL_UnbindTexture(renderer, texture);
-    }
-
-    return SDL_Unsupported();
-}
-
 void *SDL_GetRenderMetalLayer(SDL_Renderer *renderer)
 {
     CHECK_RENDERER_MAGIC(renderer, NULL);
diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h
index b1f82cb8534a..ec4b34ab0bac 100644
--- a/src/render/SDL_sysrender.h
+++ b/src/render/SDL_sysrender.h
@@ -209,9 +209,6 @@ struct SDL_Renderer
 
     int (*SetVSync)(SDL_Renderer *renderer, int vsync);
 
-    int (*GL_BindTexture)(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh);
-    int (*GL_UnbindTexture)(SDL_Renderer *renderer, SDL_Texture *texture);
-
     void *(*GetMetalLayer)(SDL_Renderer *renderer);
     void *(*GetMetalCommandEncoder)(SDL_Renderer *renderer);
 
diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c
index dc66b18c076e..5baa89725536 100644
--- a/src/render/opengl/SDL_render_gl.c
+++ b/src/render/opengl/SDL_render_gl.c
@@ -1145,7 +1145,7 @@ static int SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const
     }
 
     /* This is a little awkward but should avoid texcoord arrays getting into
-       a bad state if SDL_GL_BindTexture/UnbindTexture are called. */
+       a bad state if the application is manually binding textures */
     if (texture_array != data->drawstate.texture_array) {
         if (texture_array) {
             data->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@@ -1610,105 +1610,6 @@ static void GL_DestroyRenderer(SDL_Renderer *renderer)
     SDL_free(renderer);
 }
 
-static int GL_BindTexture(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh)
-{
-    GL_RenderData *data = (GL_RenderData *)renderer->driverdata;
-    GL_TextureData *texturedata = (GL_TextureData *)texture->driverdata;
-    const GLenum textype = data->textype;
-
-    GL_ActivateRenderer(renderer);
-
-    data->glEnable(textype);
-#if SDL_HAVE_YUV
-    if (texturedata->yuv) {
-        if (data->GL_ARB_multitexture_supported) {
-            data->glActiveTextureARB(GL_TEXTURE2_ARB);
-        }
-        data->glBindTexture(textype, texturedata->vtexture);
-
-        if (data->GL_ARB_multitexture_supported) {
-            data->glActiveTextureARB(GL_TEXTURE1_ARB);
-        }
-        data->glBindTexture(textype, texturedata->utexture);
-
-        if (data->GL_ARB_multitexture_supported) {
-            data->glActiveTextureARB(GL_TEXTURE0_ARB);
-        }
-    }
-    if (texturedata->nv12) {
-        if (data->GL_ARB_multitexture_supported) {
-            data->glActiveTextureARB(GL_TEXTURE1_ARB);
-        }
-        data->glBindTexture(textype, texturedata->utexture);
-
-        if (data->GL_ARB_multitexture_supported) {
-            data->glActiveTextureARB(GL_TEXTURE0_ARB);
-        }
-    }
-#endif
-    data->glBindTexture(textype, texturedata->texture);
-
-    data->drawstate.texturing = SDL_TRUE;
-    data->drawstate.texture = texture;
-
-    if (texw) {
-        *texw = (float)texturedata->texw;
-    }
-    if (texh) {
-        *texh = (float)texturedata->texh;
-    }
-    return 0;
-}
-
-static int GL_UnbindTexture(SDL_Renderer *renderer, SDL_Texture *texture)
-{
-    GL_RenderData *data = (GL_RenderData *)renderer->driverdata;
-    const GLenum textype = data->textype;
-#if SDL_HAVE_YUV
-    GL_TextureData *texturedata = (GL_TextureData *)texture->driverdata;
-#endif
-
-    GL_ActivateRenderer(renderer);
-
-#if SDL_HAVE_YUV
-    if (texturedata->yuv) {
-        if (data->GL_ARB_multitexture_supported) {
-            data->glActiveTextureARB(GL_TEXTURE2_ARB);
-        }
-        data->glBindTexture(textype, 0);
-        data->glDisable(textype);
-
-        if (data->GL_ARB_multitexture_supported) {
-            data->glActiveTextureARB(GL_TEXTURE1_ARB);
-        }
-        data->glBindTexture(textype, 0);
-        data->glDisable(textype);
-
-        if (data->GL_ARB_multitexture_supported) {
-            data->glActiveTextureARB(GL_TEXTURE0_ARB);
-        }
-    }
-    if (texturedata->nv12) {
-        if (data->GL_ARB_multitexture_supported) {
-            data->glActiveTextureARB(GL_TEXTURE1_ARB);
-        }
-        data->glBindTexture(textype, 0);
-        data->glDisable(textype);
-
-        if (data->GL_ARB_multitexture_supported) {
-            data->glActiveTextureARB(GL_TEXTURE0_ARB);
-        }
-    }
-#endif
-    data->glBindTexture(textype, 0);
-    data->glDisable(textype);
-
-    data->drawstate.texturing = SDL_FALSE;
-    data->drawstate.texture = NULL;
-
-    return 0;
-}
-
 static int GL_SetVSync(SDL_Renderer *renderer, const int vsync)
 {
     int retval;
@@ -1828,8 +1729,6 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea
     renderer->DestroyTexture = GL_DestroyTexture;
     renderer->DestroyRenderer = GL_DestroyRenderer;
     renderer->SetVSync = GL_SetVSync;
-    renderer->GL_BindTexture = GL_BindTexture;
-    renderer->GL_UnbindTexture = GL_UnbindTexture;
     renderer->info = GL_RenderDriver.info;
     renderer->info.flags = 0; /* will set some flags below. */
     renderer->driverdata = data;
diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c
index fe6cf72cc308..49e0139c634b 100644
--- a/src/render/opengles2/SDL_render_gles2.c
+++ b/src/render/opengles2/SDL_render_gles2.c
@@ -2013,57 +2013,6 @@ static int GLES2_SetVSync(SDL_Renderer *renderer, const int vsync)
     return retval;
 }
 
-/*************************************************************************************************
- * Bind/unbinding of textures
- *************************************************************************************************/
-static int GLES2_BindTexture(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh)
-{
-    GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
-    GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
-    GLES2_ActivateRenderer(renderer);
-
-#if SDL_HAVE_YUV
-    if (texturedata->yuv) {
-        data->glActiveTexture(GL_TEXTURE2);
-        data->glBindTexture(texturedata->texture_type, texturedata->texture_v);
-
-        data->glActiveTexture(GL_TEXTURE1);
-        data->glBindTexture(texturedata->texture_type, texturedata->texture_u);
-
-        data->glActiveTexture(GL_TEXTURE0);
-    } else if (texturedata->nv12) {
-        data->glActiveTexture(GL_TEXTURE1);
-        data->glBindTexture(texturedata->texture_type, texturedata->texture_u);
-
-        data->glActiveTexture(GL_TEXTURE0);
-    }
-#endif
-
-    data->glBindTexture(texturedata->texture_type, texturedata->texture);
-    data->drawstate.texture = texture;
-
-    if (texw) {
-        *texw = 1.0;
-    }
-    if (texh) {
-        *texh = 1.0;
-    }
-
-    return 0;
-}
-
-static int GLES2_UnbindTexture(SDL_Renderer *renderer, SDL_Texture *texture)
-{
-    GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
-    GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
-    GLES2_ActivateRenderer(renderer);
-
-    data->glBindTexture(texturedata->texture_type, 0);
-    data->drawstate.texture = NULL;
-
-    return 0;
-}
-
 /*************************************************************************************************
  * Renderer instantiation                                                                        *
  *************************************************************************************************/
@@ -2220,8 +2169,6 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
     renderer->DestroyTexture = GLES2_DestroyTexture;
     renderer->DestroyRenderer = GLES2_DestroyRenderer;
     renderer->SetVSync = GLES2_SetVSync;
-    renderer->GL_BindTexture = GLES2_BindTexture;
-    renderer->GL_UnbindTexture = GLES2_UnbindTexture;
 #if SDL_HAVE_YUV
     renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
     renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
diff --git a/test/testffmpeg.c b/test/testffmpeg.c
index db7c2accb752..d865a8d30d29 100644
--- a/test/testffmpeg.c
+++ b/test/testffmpeg.c
@@ -508,6 +508,8 @@ static SDL_bool GetTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
     const AVDRMFrameDescriptor *desc = (const AVDRMFrameDescriptor *)frame->data[0];
     int i, j, image_index, num_planes;
     EGLDisplay display = eglGetCurrentDisplay();
+    SDL_PropertiesID props;
+    GLuint textures[2];
 
     /* FIXME: Assuming NV12 data format */
     num_planes = 0;
@@ -536,8 +538,13 @@ static SDL_bool GetTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
     SDL_SetTextureBlendMode(*texture, SDL_BLENDMODE_NONE);
     SDL_SetTextureScaleMode(*texture, SDL_SCALEMODE_LINEAR);
 
-    /* Bind the texture for importing */
-    SDL_GL_BindTexture(*texture, NULL, NULL);
+    props = SDL_GetTextureProperties(*texture);
+    textures[0] = (GLuint)SDL_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER, 0);
+    textures[1] = (GLuint)SDL_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER, 0);
+    if (!textures[0] || !textures[1]) {
+        SDL_SetError("Couldn't get NV12 OpenGL textures");
+        return SDL_FALSE;
+    }
 
     /* import the frame into OpenGL */
     image_index = 0;
@@ -559,13 +566,12 @@ static SDL_bool GetTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
             EGLImage pImage = eglCreateImage(display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, img_attr);
 
             glActiveTextureARBFunc(GL_TEXTURE0_ARB + image_index);
+            glBindTexture(GL_TEXTURE_2D, textures[image_index]);
             glEGLImageTargetTexture2DOESFunc(GL_TEXTURE_2D, pImage);
             ++image_index;
         }
     }
 
-    SDL_GL_UnbindTexture(*texture);
-
     return SDL_TRUE;
 #else
     return SDL_FALSE;