SDL: Vita: refactor gxm texture render and add SDL_RenderGeometry support

From 79ec8986d322edfd1e95c3a7dc6ed05a75f53f97 Mon Sep 17 00:00:00 2001
From: Ivan Epifanov <[EMAIL REDACTED]>
Date: Thu, 16 Sep 2021 12:47:45 +0300
Subject: [PATCH] Vita: refactor gxm texture render and add SDL_RenderGeometry
 support

---
 src/render/vitagxm/SDL_render_vita_gxm.c      | 219 ++++++++++++------
 .../vitagxm/SDL_render_vita_gxm_shaders.h     | 170 ++++++--------
 .../vitagxm/SDL_render_vita_gxm_tools.c       |  61 ++---
 .../vitagxm/SDL_render_vita_gxm_types.h       |   8 +-
 src/render/vitagxm/shader_src/color_v.cg      |   4 +-
 src/render/vitagxm/shader_src/texture_f.cg    |   4 +-
 .../vitagxm/shader_src/texture_tint_f.cg      |   4 -
 src/render/vitagxm/shader_src/texture_v.cg    |   7 +-
 8 files changed, 236 insertions(+), 241 deletions(-)
 delete mode 100644 src/render/vitagxm/shader_src/texture_tint_f.cg

diff --git a/src/render/vitagxm/SDL_render_vita_gxm.c b/src/render/vitagxm/SDL_render_vita_gxm.c
index bf3af3962f..67a834ba0e 100644
--- a/src/render/vitagxm/SDL_render_vita_gxm.c
+++ b/src/render/vitagxm/SDL_render_vita_gxm.c
@@ -88,6 +88,14 @@ static int VITA_GXM_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd,
     const SDL_Rect * srcrect, const SDL_FRect * dstrect,
     const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
 
+#if SDL_HAVE_RENDER_GEOMETRY
+static int
+VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
+        const float *xy, int xy_stride, const int *color, int color_stride, const float *uv, int uv_stride,
+        int num_vertices, const void *indices, int num_indices, int size_indices,
+        float scale_x, float scale_y);
+#endif
+
 static int VITA_GXM_RenderClear(SDL_Renderer *renderer, SDL_RenderCommand *cmd);
 
 static int VITA_GXM_RenderDrawPoints(SDL_Renderer *renderer, const SDL_RenderCommand *cmd);
@@ -160,7 +168,6 @@ StartDrawing(SDL_Renderer *renderer)
     data->drawstate.vertex_program = NULL;
     data->drawstate.fragment_program = NULL;
     data->drawstate.last_command = -1;
-    data->drawstate.texture_color = 0xFFFFFFFF;
     data->drawstate.viewport_dirty = SDL_TRUE;
 
     // reset blend mode
@@ -168,7 +175,6 @@ StartDrawing(SDL_Renderer *renderer)
 //    fragment_programs *in = &data->blendFragmentPrograms.blend_mode_blend;
 //    data->colorFragmentProgram = in->color;
 //    data->textureFragmentProgram = in->texture;
-//    data->textureTintFragmentProgram = in->textureTint;
 
     if (renderer->target == NULL) {
         sceGxmBeginScene(
@@ -250,6 +256,9 @@ VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags)
     renderer->QueueFillRects = VITA_GXM_QueueFillRects;
     renderer->QueueCopy = VITA_GXM_QueueCopy;
     renderer->QueueCopyEx = VITA_GXM_QueueCopyEx;
+#if SDL_HAVE_RENDER_GEOMETRY
+    renderer->QueueGeometry = VITA_GXM_QueueGeometry;
+#endif
     renderer->RunCommandQueue = VITA_GXM_RunCommandQueue;
     renderer->RenderReadPixels = VITA_GXM_RenderReadPixels;
     renderer->RenderPresent = VITA_GXM_RenderPresent;
@@ -434,7 +443,6 @@ VITA_GXM_SetBlendMode(VITA_GXM_RenderData *data, int blendMode)
         }
         data->colorFragmentProgram = in->color;
         data->textureFragmentProgram = in->texture;
-        data->textureTintFragmentProgram = in->textureTint;
         data->currentBlendMode = blendMode;
     }
 }
@@ -479,7 +487,6 @@ VITA_GXM_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const
     {
         vertex[i].x = points[i].x;
         vertex[i].y = points[i].y;
-        vertex[i].z = +0.5f;
         vertex[i].color = color;
     }
 
@@ -505,12 +512,10 @@ VITA_GXM_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const S
     {
         vertex[i*2].x = points[i].x;
         vertex[i*2].y = points[i].y;
-        vertex[i*2].z = +0.5f;
         vertex[i*2].color = color;
 
         vertex[i*2+1].x = points[i+1].x;
         vertex[i*2+1].y = points[i+1].y;
-        vertex[i*2+1].z = +0.5f;
         vertex[i*2+1].color = color;
     }
 
@@ -538,22 +543,18 @@ VITA_GXM_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const S
 
         vertices[4*i+0].x = rect->x;
         vertices[4*i+0].y = rect->y;
-        vertices[4*i+0].z = +0.5f;
         vertices[4*i+0].color = color;
 
         vertices[4*i+1].x = rect->x + rect->w;
         vertices[4*i+1].y = rect->y;
-        vertices[4*i+1].z = +0.5f;
         vertices[4*i+1].color = color;
 
         vertices[4*i+2].x = rect->x;
         vertices[4*i+2].y = rect->y + rect->h;
-        vertices[4*i+2].z = +0.5f;
         vertices[4*i+2].color = color;
 
         vertices[4*i+3].x = rect->x + rect->w;
         vertices[4*i+3].y = rect->y + rect->h;
-        vertices[4*i+3].z = +0.5f;
         vertices[4*i+3].color = color;
     }
 
@@ -577,6 +578,7 @@ VITA_GXM_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture
     texture_vertex *vertices;
     float u0, v0, u1, v1;
     VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
+    Uint32 texture_color = (cmd->data.draw.r << 0) | (cmd->data.draw.g << 8) | (cmd->data.draw.b << 16) | (cmd->data.draw.a << 24);
 
     cmd->data.draw.count = 1;
 
@@ -595,25 +597,25 @@ VITA_GXM_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture
 
     vertices[0].x = dstrect->x;
     vertices[0].y = dstrect->y;
-    vertices[0].z = +0.5f;
+    vertices[0].color = texture_color;
     vertices[0].u = u0;
     vertices[0].v = v0;
 
     vertices[1].x = dstrect->x + dstrect->w;
     vertices[1].y = dstrect->y;
-    vertices[1].z = +0.5f;
+    vertices[1].color = texture_color;
     vertices[1].u = u1;
     vertices[1].v = v0;
 
     vertices[2].x = dstrect->x;
     vertices[2].y = dstrect->y + dstrect->h;
-    vertices[2].z = +0.5f;
+    vertices[2].color = texture_color;
     vertices[2].u = u0;
     vertices[2].v = v1;
 
     vertices[3].x = dstrect->x + dstrect->w;
     vertices[3].y = dstrect->y + dstrect->h;
-    vertices[3].z = +0.5f;
+    vertices[3].color = texture_color;
     vertices[3].u = u1;
     vertices[3].v = v1;
 
@@ -633,6 +635,7 @@ VITA_GXM_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Textur
     float s, c;
     const float centerx = center->x + dstrect->x;
     const float centery = center->y + dstrect->y;
+    Uint32 texture_color = (cmd->data.draw.r << 0) | (cmd->data.draw.g << 8) | (cmd->data.draw.b << 16) | (cmd->data.draw.a << 24);
 
     cmd->data.draw.count = 1;
 
@@ -669,28 +672,27 @@ VITA_GXM_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Textur
 
     vertices[0].x = x0 - centerx;
     vertices[0].y = y0 - centery;
-    vertices[0].z = +0.5f;
     vertices[0].u = u0;
     vertices[0].v = v0;
+    vertices[0].color = texture_color;
 
     vertices[1].x = x1 - centerx;
     vertices[1].y = y0 - centery;
-    vertices[1].z = +0.5f;
     vertices[1].u = u1;
     vertices[1].v = v0;
-
+    vertices[1].color = texture_color;
 
     vertices[2].x = x0 - centerx;
     vertices[2].y = y1 - centery;
-    vertices[2].z = +0.5f;
     vertices[2].u = u0;
     vertices[2].v = v1;
+    vertices[2].color = texture_color;
 
     vertices[3].x = x1 - centerx;
     vertices[3].y = y1 - centery;
-    vertices[3].z = +0.5f;
     vertices[3].u = u1;
     vertices[3].v = v1;
+    vertices[3].color = texture_color;
 
     for (int i = 0; i < 4; ++i)
     {
@@ -704,6 +706,103 @@ VITA_GXM_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Textur
 }
 
 
+#if SDL_HAVE_RENDER_GEOMETRY
+static int
+VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
+        const float *xy, int xy_stride, const int *color, int color_stride, const float *uv, int uv_stride,
+        int num_vertices, const void *indices, int num_indices, int size_indices,
+        float scale_x, float scale_y)
+{
+    VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
+    int i;
+    int count = indices ? num_indices : num_vertices;
+
+    cmd->data.draw.count = count;
+    size_indices = indices ? size_indices : 0;
+
+    if (texture) {
+        texture_vertex *vertices;
+
+        vertices = (texture_vertex *)pool_memalign(
+                data,
+                count * sizeof(texture_vertex),
+                sizeof(texture_vertex));
+
+        if (!vertices) {
+            return -1;
+        }
+
+
+        for (i = 0; i < count; i++) {
+            int j;
+            float *xy_;
+            float *uv_;
+            int col_;
+            if (size_indices == 4) {
+                j = ((const Uint32 *)indices)[i];
+            } else if (size_indices == 2) {
+                j = ((const Uint16 *)indices)[i];
+            } else if (size_indices == 1) {
+                j = ((const Uint8 *)indices)[i];
+            } else {
+                j = i;
+            }
+
+            xy_ = (float *)((char*)xy + j * xy_stride);
+            col_ = *(int *)((char*)color + j * color_stride);
+            uv_ = (float *)((char*)uv + j * uv_stride);
+
+            vertices[i].x = xy_[0] * scale_x;
+            vertices[i].y = xy_[1] * scale_y;
+            vertices[i].u = uv_[0];
+            vertices[i].v = uv_[1];
+            vertices[i].color = col_;
+        }
+
+        cmd->data.draw.first = (size_t)vertices;
+
+    } else {
+        color_vertex *vertices;
+
+        vertices = (color_vertex *)pool_memalign(
+                data,
+                count * sizeof(color_vertex),
+                sizeof(color_vertex));
+
+        if (!vertices) {
+            return -1;
+        }
+
+
+        for (i = 0; i < count; i++) {
+            int j;
+            float *xy_;
+            int col_;
+            if (size_indices == 4) {
+                j = ((const Uint32 *)indices)[i];
+            } else if (size_indices == 2) {
+                j = ((const Uint16 *)indices)[i];
+            } else if (size_indices == 1) {
+                j = ((const Uint8 *)indices)[i];
+            } else {
+                j = i;
+            }
+
+            xy_ = (float *)((char*)xy + j * xy_stride);
+            col_ = *(int *)((char*)color + j * color_stride);
+
+            vertices[i].x = xy_[0] * scale_x;
+            vertices[i].y = xy_[1] * scale_y;
+            vertices[i].color = col_;
+        }
+        cmd->data.draw.first = (size_t)vertices;
+    }
+
+
+    return 0;
+}
+#endif
+
 static int
 VITA_GXM_RenderClear(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
 {
@@ -774,7 +873,7 @@ VITA_GXM_RenderFillRects(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
 
 
 static int
-SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd, SDL_bool solid)
+SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd)
 {
     SDL_Texture *texture = cmd->data.draw.texture;
     const SDL_BlendMode blend = cmd->data.draw.blend;
@@ -782,13 +881,6 @@ SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd, SDL_bool s
     SceGxmVertexProgram *vertex_program;
     SDL_bool matrix_updated = SDL_FALSE;
     SDL_bool program_updated = SDL_FALSE;
-    Uint32 texture_color;
-
-    Uint8 r, g, b, a;
-    r = cmd->data.draw.r;
-    g = cmd->data.draw.g;
-    b = cmd->data.draw.b;
-    a = cmd->data.draw.a;
 
     if (data->drawstate.viewport_dirty) {
         const SDL_Rect *viewport = &data->drawstate.viewport;
@@ -834,11 +926,7 @@ SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd, SDL_bool s
 
     if (texture) {
         vertex_program = data->textureVertexProgram;
-        if(cmd->data.draw.r == 255 && cmd->data.draw.g == 255 && cmd->data.draw.b == 255 && cmd->data.draw.a == 255) {
-            fragment_program = data->textureFragmentProgram;
-        } else {
-            fragment_program = data->textureTintFragmentProgram;
-        }
+        fragment_program = data->textureFragmentProgram;
     } else {
         vertex_program = data->colorVertexProgram;
         fragment_program = data->colorFragmentProgram;
@@ -856,58 +944,17 @@ SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd, SDL_bool s
         program_updated = SDL_TRUE;
     }
 
-    texture_color = ((a << 24) | (b << 16) | (g << 8) | r);
 
     if (program_updated || matrix_updated) {
         if (data->drawstate.fragment_program == data->textureFragmentProgram) {
             void *vertex_wvp_buffer;
             sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertex_wvp_buffer);
             sceGxmSetUniformDataF(vertex_wvp_buffer, data->textureWvpParam, 0, 16, data->ortho_matrix);
-        } else if (data->drawstate.fragment_program == data->textureTintFragmentProgram) {
-            void *vertex_wvp_buffer;
-            void *texture_tint_color_buffer;
-            float *tint_color;
-            sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertex_wvp_buffer);
-            sceGxmSetUniformDataF(vertex_wvp_buffer, data->textureWvpParam, 0, 16, data->ortho_matrix);
-
-            sceGxmReserveFragmentDefaultUniformBuffer(data->gxm_context, &texture_tint_color_buffer);
-
-            tint_color = pool_memalign(
-                data,
-                4 * sizeof(float), // RGBA
-                sizeof(float)
-            );
-
-            tint_color[0] = r / 255.0f;
-            tint_color[1] = g / 255.0f;
-            tint_color[2] = b / 255.0f;
-            tint_color[3] = a / 255.0f;
-            sceGxmSetUniformDataF(texture_tint_color_buffer, data->textureTintColorParam, 0, 4, tint_color);
-            data->drawstate.texture_color = texture_color;
         } else { // color
             void *vertexDefaultBuffer;
             sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertexDefaultBuffer);
             sceGxmSetUniformDataF(vertexDefaultBuffer, data->colorWvpParam, 0, 16, data->ortho_matrix);
         }
-    } else {
-        if (data->drawstate.fragment_program == data->textureTintFragmentProgram && data->drawstate.texture_color != texture_color) {
-            void *texture_tint_color_buffer;
-            float *tint_color;
-            sceGxmReserveFragmentDefaultUniformBuffer(data->gxm_context, &texture_tint_color_buffer);
-
-            tint_color = pool_memalign(
-                data,
-                4 * sizeof(float), // RGBA
-                sizeof(float)
-            );
-
-            tint_color[0] = r / 255.0f;
-            tint_color[1] = g / 255.0f;
-            tint_color[2] = b / 255.0f;
-            tint_color[3] = a / 255.0f;
-            sceGxmSetUniformDataF(texture_tint_color_buffer, data->textureTintColorParam, 0, 4, tint_color);
-            data->drawstate.texture_color = texture_color;
-        }
     }
 
     if (texture != data->drawstate.texture) {
@@ -929,7 +976,7 @@ SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
 {
     VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
 
-    return SetDrawState(data, cmd, SDL_FALSE);
+    return SetDrawState(data, cmd);
 }
 
 static int
@@ -979,19 +1026,19 @@ VITA_GXM_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *
             }
 
             case SDL_RENDERCMD_DRAW_POINTS: {
-                SetDrawState(data, cmd, SDL_FALSE);
+                SetDrawState(data, cmd);
                 VITA_GXM_RenderDrawPoints(renderer, cmd);
                 break;
             }
 
             case SDL_RENDERCMD_DRAW_LINES: {
-                SetDrawState(data, cmd, SDL_FALSE);
+                SetDrawState(data, cmd);
                 VITA_GXM_RenderDrawLines(renderer, cmd);
                 break;
             }
 
             case SDL_RENDERCMD_FILL_RECTS: {
-                SetDrawState(data, cmd, SDL_FALSE);
+                SetDrawState(data, cmd);
                 VITA_GXM_RenderFillRects(renderer, cmd);
                 break;
             }
@@ -1004,6 +1051,24 @@ VITA_GXM_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *
                 break;
             }
 
+            case SDL_RENDERCMD_GEOMETRY: {
+#if SDL_HAVE_RENDER_GEOMETRY
+                SDL_Texture *texture = cmd->data.draw.texture;
+                int ret;
+
+                if (texture) {
+                    ret = SetCopyState(renderer, cmd);
+                } else {
+                    ret = SetDrawState(data, cmd);
+                }
+
+                if (ret == 0) {
+                    sceGxmDraw(data->gxm_context, SCE_GXM_PRIMITIVE_TRIANGLES, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, cmd->data.draw.count);
+                }
+#endif
+                break;
+            }
+
             case SDL_RENDERCMD_NO_OP:
                 break;
         }
diff --git a/src/render/vitagxm/SDL_render_vita_gxm_shaders.h b/src/render/vitagxm/SDL_render_vita_gxm_shaders.h
index 1341d328c1..9eb6913a09 100644
--- a/src/render/vitagxm/SDL_render_vita_gxm_shaders.h
+++ b/src/render/vitagxm/SDL_render_vita_gxm_shaders.h
@@ -124,37 +124,39 @@ static const unsigned char gxm_shader_color_f[gxm_shader_color_f_size] = {
     0x7e, 0x0d, 0x80, 0x40, 
 };
 
-#define gxm_shader_color_v_size 352
+#define gxm_shader_color_v_size 368
 static const unsigned char gxm_shader_color_v[gxm_shader_color_v_size] = {
     0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, 
-    0x5d, 0x01, 0x00, 0x00, 0x4a, 0xb6, 0x4f, 0x7b, 
-    0x51, 0x19, 0x1a, 0xae, 0x00, 0x00, 0x19, 0x00, 
+    0x6d, 0x01, 0x00, 0x00, 0x09, 0xce, 0x4e, 0xc2, 
+    0xe1, 0xcd, 0x24, 0xbc, 0x00, 0x00, 0x19, 0x00, 
     0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 
-    0xf0, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 
+    0x00, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 
     0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00, 
-    0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x74, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00, 
+    0x98, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 
+    0x74, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 
-    0xa8, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 
+    0xb8, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 
-    0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 
+    0x01, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x06, 0x43, 0x00, 0x61, 
+    0x86, 0x81, 0xa2, 0x00, 0x07, 0x53, 0x40, 0x61, 
+    0x86, 0x81, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x40, 0x01, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa, 
     0x80, 0x00, 0x08, 0x83, 0x21, 0x1d, 0x80, 0x38, 
-    0x02, 0x80, 0x81, 0xaf, 0x9c, 0x0d, 0xc0, 0x40, 
-    0x0e, 0x86, 0xb9, 0xff, 0xbc, 0x0d, 0xc0, 0x40, 
-    0x04, 0x11, 0x49, 0xcf, 0x80, 0x8f, 0xb1, 0x18, 
+    0x00, 0x00, 0xf0, 0x83, 0x20, 0x0d, 0x80, 0x38, 
+    0x0a, 0x84, 0xb9, 0xff, 0xbc, 0x0d, 0xc0, 0x40, 
     0x02, 0x11, 0x45, 0xcf, 0x80, 0x8f, 0xb1, 0x18, 
     0x00, 0x11, 0x01, 0xc0, 0x81, 0x81, 0xb1, 0x18, 
     0x01, 0xd1, 0x42, 0xc0, 0x81, 0x81, 0xb1, 0x18, 
@@ -172,142 +174,106 @@ static const unsigned char gxm_shader_color_v[gxm_shader_color_v_size] = {
     0x00, 0x77, 0x76, 0x70, 0x00, 0x00, 0x00, 0x00, 
 };
 
-#define gxm_shader_texture_f_size 256
+#define gxm_shader_texture_f_size 288
 static const unsigned char gxm_shader_texture_f[gxm_shader_texture_f_size] = {
     0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, 
-    0x00, 0x01, 0x00, 0x00, 0x2f, 0x18, 0xe0, 0x2b, 
-    0x1f, 0x21, 0x47, 0x49, 0x01, 0x08, 0x18, 0x00, 
+    0x20, 0x01, 0x00, 0x00, 0xeb, 0x4f, 0xb5, 0xba, 
+    0x60, 0xb2, 0xd0, 0x8d, 0x05, 0x18, 0x18, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
-    0xa4, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 
-    0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 
-    0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x78, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x64, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 
-    0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 
-    0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 
-    0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x40, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x07, 0x44, 0xfa, 0x30, 0x00, 0x00, 0x00, 
-    0x02, 0x04, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x00, 
-};
-
-#define gxm_shader_texture_tint_f_size 324
-static const unsigned char gxm_shader_texture_tint_f[gxm_shader_texture_tint_f_size] = {
-    0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, 
-    0x43, 0x01, 0x00, 0x00, 0x44, 0x2f, 0x5d, 0xfe, 
-    0x9e, 0xda, 0xf8, 0x6f, 0x05, 0x08, 0x18, 0x00, 
-    0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 
-    0xcc, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 
-    0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0xc4, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 
+    0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 
     0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x78, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x84, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 
-    0x01, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 
-    0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 
+    0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 
     0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 
-    0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0xc0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 
+    0x00, 0xa9, 0xd0, 0x0e, 0x00, 0x00, 0x00, 0x00, 
+    0xf0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x07, 0x44, 0xfa, 0x00, 0x00, 0x00, 0x00, 
-    0x40, 0x09, 0x00, 0xf8, 0x02, 0x80, 0x99, 0xff, 
-    0xbc, 0x0d, 0xc0, 0x40, 0x02, 0x80, 0xb9, 0xaf, 
+    0x40, 0x09, 0x00, 0xf8, 0x02, 0x80, 0x99, 0xaf, 
+    0xbc, 0x0d, 0xc0, 0x40, 0x06, 0x82, 0xb9, 0xaf, 
     0xbc, 0x0d, 0x80, 0x40, 0x7c, 0x0f, 0x04, 0x00, 
-    0x86, 0x47, 0xa4, 0x10, 0x0e, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x04, 0x00, 0x40, 0x00, 0x00, 0x00, 
-    0x01, 0xe4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 
+    0x86, 0x47, 0xa4, 0x10, 0x30, 0x00, 0x00, 0x00, 
     0x02, 0x04, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x75, 0x54, 0x69, 0x6e, 
-    0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x74, 
-    0x65, 0x78, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x00, 
 };
 
-#define gxm_shader_texture_v_size 344
+#define gxm_shader_texture_v_size 400
 static const unsigned char gxm_shader_texture_v[gxm_shader_texture_v_size] = {
     0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, 
-    0x58, 0x01, 0x00, 0x00, 0xa3, 0x36, 0x7b, 0x62, 
-    0x1b, 0x80, 0x1c, 0xb0, 0x00, 0x00, 0x19, 0x00, 
+    0x8f, 0x01, 0x00, 0x00, 0x60, 0x1e, 0x69, 0x97, 
+    0x82, 0x7e, 0x0c, 0xac, 0x00, 0x00, 0x19, 0x00, 
     0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 
-    0xe8, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 
-    0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00, 
-    0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x74, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 
+    0x08, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 
+    0x0c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00, 
+    0x98, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 
+    0x74, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 
-    0xa0, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 
-    0x01, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 
+    0xc0, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 
+    0x01, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x33, 0x0f, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06, 
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x0a, 
     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x00, 0x00, 0x00, 0x00, 0x06, 0x43, 0x00, 0x61, 
+    0x86, 0x81, 0xa2, 0x00, 0x07, 0x53, 0x40, 0x61, 
+    0x86, 0x81, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x40, 0x01, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa, 
-    0x80, 0x00, 0x08, 0x83, 0x21, 0x0d, 0x80, 0x38, 
-    0x02, 0x80, 0x81, 0xaf, 0x9c, 0x0d, 0xc0, 0x40, 
-    0x0e, 0x86, 0xb9, 0xff, 0xbc, 0x0d, 0xc0, 0x40, 
-    0x04, 0x11, 0x49, 0xcf, 0x80, 0x8f, 0xb1, 0x18, 
+    0x01, 0x0e, 0x01, 0x01, 0x02, 0x00, 0x10, 0xfa, 
+    0x80, 0x00, 0x08, 0x83, 0x21, 0x25, 0x80, 0x38, 
+    0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x14, 0xfa, 
+    0x00, 0x00, 0xf0, 0x83, 0x20, 0x0d, 0x80, 0x38, 
+    0x0a, 0x84, 0xb9, 0xff, 0xbc, 0x0d, 0xc0, 0x40, 
     0x02, 0x11, 0x45, 0xcf, 0x80, 0x8f, 0xb1, 0x18, 
     0x00, 0x11, 0x01, 0xc0, 0x81, 0x81, 0xb1, 0x18, 
     0x01, 0xd1, 0x42, 0xc0, 0x81, 0x81, 0xb1, 0x18, 
     0x00, 0x00, 0x20, 0xa0, 0x00, 0x50, 0x27, 0xfb, 
     0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 
-    0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 
+    0x40, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 
     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-    0x2a, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 
+    0x3a, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 
     0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 
-    0x24, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, 
+    0x34, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 
+    0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 
+    0x2b, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, 
     0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x61, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 
     0x6e, 0x00, 0x61, 0x54, 0x65, 0x78, 0x63, 0x6f, 
-    0x6f, 0x72, 0x64, 0x00, 0x77, 0x76, 0x70, 0x00, 
+    0x6f, 0x72, 0x64, 0x00, 0x61, 0x43, 0x6f, 0x6c, 
+    0x6f, 0x72, 0x00, 0x77, 0x76, 0x70, 0x00, 0x00, 
 };
 
-
-static const SceGxmProgram *const clearVertexProgramGxp         = (const SceGxmProgram*)gxm_shader_clear_v;
+static const SceGxmProgram *const clearVertexProgramGxp         = (const SceGxmProgram *)gxm_shader_clear_v;
 static const SceGxmProgram *const clearFragmentProgramGxp       = (const SceGxmProgram *)gxm_shader_clear_f;
 static const SceGxmProgram *const colorVertexProgramGxp         = (const SceGxmProgram *)gxm_shader_color_v;
 static const SceGxmProgram *const colorFragmentProgramGxp       = (const SceGxmProgram *)gxm_shader_color_f;
 static const SceGxmProgram *const textureVertexProgramGxp       = (const SceGxmProgram *)gxm_shader_texture_v;
 static const SceGxmProgram *const textureFragmentProgramGxp     = (const SceGxmProgram *)gxm_shader_texture_f;
-static const SceGxmProgram *const textureTintFragmentProgramGxp = (const SceGxmProgram *)gxm_shader_texture_tint_f;
 
 #endif // SDL_RENDER_VITA_GXM_SHADERS_H
 
diff --git a/src/render/vitagxm/SDL_render_vita_gxm_tools.c b/src/render/vitagxm/SDL_render_vita_gxm_tools.c
index fe9ff6137f..2190b66de3 100644
--- a/src/render/vitagxm/SDL_render_vita_gxm_tools.c
+++ b/src/render/vitagxm/SDL_render_vita_gxm_tools.c
@@ -164,7 +164,6 @@ free_fragment_programs(VITA_GXM_RenderData *data, fragment_programs *out)
 {
     sceGxmShaderPatcherReleaseFragmentProgram(data->shaderPatcher, out->color);
     sceGxmShaderPatcherReleaseFragmentProgram(data->shaderPatcher, out->texture);
-    sceGxmShaderPatcherReleaseFragmentProgram(data->shaderPatcher, out->textureTint);
 }
 
 static void
@@ -202,21 +201,6 @@ make_fragment_programs(VITA_GXM_RenderData *data, fragment_programs *out,
         SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Patcher create fragment failed: %d\n", err);
         return;
     }
-
-    err = sceGxmShaderPatcherCreateFragmentProgram(
-        data->shaderPatcher,
-        data->textureTintFragmentProgramId,
-        SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
-        0,
-        blend_info,
-        textureVertexProgramGxp,
-        &out->textureTint
-    );
-
-    if (err != 0) {
-        SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Patcher create fragment failed: %d\n", err);
-        return;
-    }
 }
 
 
@@ -232,22 +216,18 @@ set_stencil_mask(VITA_GXM_RenderData *data, float x, float y, float w, float h)
 
     vertices[0].x = x;
     vertices[0].y = y;
-    vertices[0].z = +0.5f;
     vertices[0].color = 0;
 
     vertices[1].x = x + w;
     vertices[1].y = y;
-    vert

(Patch may be truncated, please check the link at the top of this post.)