SDL: Added a hint for alternate OpenGL NV12 data format (c55ab)

From c55ab9631f38583092b9e609f4441fc4bdb11ca9 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sat, 13 Nov 2021 22:21:57 -0800
Subject: [PATCH] Added a hint for alternate OpenGL NV12 data format

---
 src/render/opengles2/SDL_render_gles2.c  | 12 ++++-
 src/render/opengles2/SDL_shaders_gles2.c | 62 ++++++++++++++++++------
 src/render/opengles2/SDL_shaders_gles2.h |  6 ++-
 3 files changed, 62 insertions(+), 18 deletions(-)

diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c
index 972f11f17a..1c60d4e5dc 100644
--- a/src/render/opengles2/SDL_render_gles2.c
+++ b/src/render/opengles2/SDL_render_gles2.c
@@ -569,10 +569,18 @@ GLES2_SelectProgram(GLES2_RenderData *data, GLES2_ImageSource source, int w, int
             ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_JPEG;
             break;
         case SDL_YUV_CONVERSION_BT601:
-            ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT601;
+            if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", SDL_FALSE)) {
+                ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RG_BT601;
+            } else {
+                ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RA_BT601;
+            }
             break;
         case SDL_YUV_CONVERSION_BT709:
-            ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT709;
+            if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", SDL_FALSE)) {
+                ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RG_BT709;
+            } else {
+                ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RA_BT709;
+            }
             break;
         default:
             SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h));
diff --git a/src/render/opengles2/SDL_shaders_gles2.c b/src/render/opengles2/SDL_shaders_gles2.c
index 0a2b1a7d59..886b8eda12 100644
--- a/src/render/opengles2/SDL_shaders_gles2.c
+++ b/src/render/opengles2/SDL_shaders_gles2.c
@@ -154,7 +154,7 @@ static const Uint8 GLES2_Fragment_TextureBGR[] = " \
 "uniform sampler2D u_texture;\n"                                \
 "uniform sampler2D u_texture_u;\n"                              \
 "uniform sampler2D u_texture_v;\n"                              \
-"varying vec4 v_color;\n"                                  \
+"varying vec4 v_color;\n"                                       \
 "varying vec2 v_texCoord;\n"                                    \
 "\n"                                                            \
 
@@ -176,10 +176,10 @@ static const Uint8 GLES2_Fragment_TextureBGR[] = " \
 "\n"                                                            \
 "    // That was easy. :) \n"                                   \
 "    gl_FragColor = vec4(rgb, 1);\n"                            \
-"    gl_FragColor *= v_color;\n"                           \
+"    gl_FragColor *= v_color;\n"                                \
 "}"                                                             \
 
-#define NV12_SHADER_BODY                                        \
+#define NV12_RA_SHADER_BODY                                     \
 "\n"                                                            \
 "void main()\n"                                                 \
 "{\n"                                                           \
@@ -196,7 +196,27 @@ static const Uint8 GLES2_Fragment_TextureBGR[] = " \
 "\n"                                                            \
 "    // That was easy. :) \n"                                   \
 "    gl_FragColor = vec4(rgb, 1);\n"                            \
-"    gl_FragColor *= v_color;\n"                           \
+"    gl_FragColor *= v_color;\n"                                \
+"}"                                                             \
+
+#define NV12_RG_SHADER_BODY                                     \
+"\n"                                                            \
+"void main()\n"                                                 \
+"{\n"                                                           \
+"    mediump vec3 yuv;\n"                                       \
+"    lowp vec3 rgb;\n"                                          \
+"\n"                                                            \
+"    // Get the YUV values \n"                                  \
+"    yuv.x = texture2D(u_texture,   v_texCoord).r;\n"           \
+"    yuv.yz = texture2D(u_texture_u, v_texCoord).rg;\n"         \
+"\n"                                                            \
+"    // Do the color transform \n"                              \
+"    yuv += offset;\n"                                          \
+"    rgb = matrix * yuv;\n"                                     \
+"\n"                                                            \
+"    // That was easy. :) \n"                                   \
+"    gl_FragColor = vec4(rgb, 1);\n"                            \
+"    gl_FragColor *= v_color;\n"                                \
 "}"                                                             \
 
 #define NV21_SHADER_BODY                                        \
@@ -216,7 +236,7 @@ static const Uint8 GLES2_Fragment_TextureBGR[] = " \
 "\n"                                                            \
 "    // That was easy. :) \n"                                   \
 "    gl_FragColor = vec4(rgb, 1);\n"                            \
-"    gl_FragColor *= v_color;\n"                           \
+"    gl_FragColor *= v_color;\n"                                \
 "}"                                                             \
 
 /* YUV to ABGR conversion */
@@ -240,17 +260,27 @@ static const Uint8 GLES2_Fragment_TextureYUVBT709[] = \
 static const Uint8 GLES2_Fragment_TextureNV12JPEG[] = \
         YUV_SHADER_PROLOGUE \
         JPEG_SHADER_CONSTANTS \
-        NV12_SHADER_BODY \
+        NV12_RA_SHADER_BODY \
 ;
-static const Uint8 GLES2_Fragment_TextureNV12BT601[] = \
+static const Uint8 GLES2_Fragment_TextureNV12BT601_RA[] = \
         YUV_SHADER_PROLOGUE \
         BT601_SHADER_CONSTANTS \
-        NV12_SHADER_BODY \
+        NV12_RA_SHADER_BODY \
+;
+static const Uint8 GLES2_Fragment_TextureNV12BT601_RG[] = \
+        YUV_SHADER_PROLOGUE \
+        BT601_SHADER_CONSTANTS \
+        NV12_RG_SHADER_BODY \
+;
+static const Uint8 GLES2_Fragment_TextureNV12BT709_RA[] = \
+        YUV_SHADER_PROLOGUE \
+        BT709_SHADER_CONSTANTS \
+        NV12_RA_SHADER_BODY \
 ;
-static const Uint8 GLES2_Fragment_TextureNV12BT709[] = \
+static const Uint8 GLES2_Fragment_TextureNV12BT709_RG[] = \
         YUV_SHADER_PROLOGUE \
         BT709_SHADER_CONSTANTS \
-        NV12_SHADER_BODY \
+        NV12_RG_SHADER_BODY \
 ;
 
 /* NV21 to ABGR conversion */
@@ -313,10 +343,14 @@ const Uint8 *GLES2_GetShader(GLES2_ShaderType type)
         return GLES2_Fragment_TextureYUVBT709;
     case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_JPEG:
         return GLES2_Fragment_TextureNV12JPEG;
-    case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT601:
-        return GLES2_Fragment_TextureNV12BT601;
-    case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT709:
-        return GLES2_Fragment_TextureNV12BT709;
+    case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RA_BT601:
+        return GLES2_Fragment_TextureNV12BT601_RA;
+    case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RG_BT601:
+        return GLES2_Fragment_TextureNV12BT601_RG;
+    case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RA_BT709:
+        return GLES2_Fragment_TextureNV12BT709_RA;
+    case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RG_BT709:
+        return GLES2_Fragment_TextureNV12BT709_RG;
     case GLES2_SHADER_FRAGMENT_TEXTURE_NV21_JPEG:
         return GLES2_Fragment_TextureNV21JPEG;
     case GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT601:
diff --git a/src/render/opengles2/SDL_shaders_gles2.h b/src/render/opengles2/SDL_shaders_gles2.h
index 5565d4aae5..a03a980fec 100644
--- a/src/render/opengles2/SDL_shaders_gles2.h
+++ b/src/render/opengles2/SDL_shaders_gles2.h
@@ -38,8 +38,10 @@ typedef enum
     GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT601,
     GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT709,
     GLES2_SHADER_FRAGMENT_TEXTURE_NV12_JPEG,
-    GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT601,
-    GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT709,
+    GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RA_BT601,
+    GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RG_BT601,
+    GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RA_BT709,
+    GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RG_BT709,
     GLES2_SHADER_FRAGMENT_TEXTURE_NV21_JPEG,
     GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT601,
     GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT709,