SDL: Vita: add native YUV textures support.

From eadc064e2c5f18a6d1cfd1b5bbd436c8945ae722 Mon Sep 17 00:00:00 2001
From: Ivan Epifanov <[EMAIL REDACTED]>
Date: Wed, 23 Mar 2022 19:14:28 +0300
Subject: [PATCH] Vita: add native YUV textures support.

* Fail if texture init fails.
* Refactor and cleanup.
---
 src/render/vitagxm/SDL_render_vita_gxm.c      | 285 ++++++++++++++++--
 .../vitagxm/SDL_render_vita_gxm_tools.c       |  57 ++--
 .../vitagxm/SDL_render_vita_gxm_tools.h       |   5 +-
 .../vitagxm/SDL_render_vita_gxm_types.h       |   9 +-
 4 files changed, 298 insertions(+), 58 deletions(-)

diff --git a/src/render/vitagxm/SDL_render_vita_gxm.c b/src/render/vitagxm/SDL_render_vita_gxm.c
index 8a887784950..4d5530443c8 100644
--- a/src/render/vitagxm/SDL_render_vita_gxm.c
+++ b/src/render/vitagxm/SDL_render_vita_gxm.c
@@ -61,6 +61,11 @@ static int VITA_GXM_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * text
     const Uint8 *Uplane, int Upitch,
     const Uint8 *Vplane, int Vpitch);
 
+static int VITA_GXM_UpdateTextureNV(SDL_Renderer * renderer, SDL_Texture * texture,
+    const SDL_Rect * rect,
+    const Uint8 *Yplane, int Ypitch,
+    const Uint8 *UVplane, int UVpitch);
+
 static int VITA_GXM_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
     const SDL_Rect *rect, void **pixels, int *pitch);
 
@@ -105,12 +110,16 @@ SDL_RenderDriver VITA_GXM_RenderDriver = {
     .info = {
         .name = "VITA gxm",
         .flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE,
-        .num_texture_formats = 4,
+        .num_texture_formats = 8,
         .texture_formats = {
             [0] = SDL_PIXELFORMAT_ABGR8888,
             [1] = SDL_PIXELFORMAT_ARGB8888,
             [2] = SDL_PIXELFORMAT_RGB565,
-            [3] = SDL_PIXELFORMAT_BGR565
+            [3] = SDL_PIXELFORMAT_BGR565,
+            [4] = SDL_PIXELFORMAT_YV12,
+            [5] = SDL_PIXELFORMAT_IYUV,
+            [6] = SDL_PIXELFORMAT_NV12,
+            [7] = SDL_PIXELFORMAT_NV21,
         },
         .max_texture_width = 4096,
         .max_texture_height = 4096,
@@ -133,6 +142,15 @@ PixelFormatToVITAFMT(Uint32 format)
         return SCE_GXM_TEXTURE_FORMAT_U5U6U5_RGB;
     case SDL_PIXELFORMAT_BGR565:
         return SCE_GXM_TEXTURE_FORMAT_U5U6U5_BGR;
+    case SDL_PIXELFORMAT_YV12:
+        return SCE_GXM_TEXTURE_FORMAT_YVU420P3_CSC0;
+    case SDL_PIXELFORMAT_IYUV:
+        return SCE_GXM_TEXTURE_FORMAT_YUV420P3_CSC0;
+    // should be the other way around. looks like SCE bug.
+    case SDL_PIXELFORMAT_NV12:
+        return SCE_GXM_TEXTURE_FORMAT_YVU420P2_CSC0;
+    case SDL_PIXELFORMAT_NV21:
+        return SCE_GXM_TEXTURE_FORMAT_YUV420P2_CSC0;
     default:
         return SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ABGR;
     }
@@ -228,6 +246,7 @@ VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags)
     renderer->UpdateTexture = VITA_GXM_UpdateTexture;
 #if SDL_HAVE_YUV
     renderer->UpdateTextureYUV = VITA_GXM_UpdateTextureYUV;
+    renderer->UpdateTextureNV = VITA_GXM_UpdateTextureNV;
 #endif
     renderer->LockTexture = VITA_GXM_LockTexture;
     renderer->UnlockTexture = VITA_GXM_UnlockTexture;
@@ -295,7 +314,17 @@ VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
         return SDL_OutOfMemory();
     }
 
-    vita_texture->tex = create_gxm_texture(data, texture->w, texture->h, PixelFormatToVITAFMT(texture->format), (texture->access == SDL_TEXTUREACCESS_TARGET));
+    vita_texture->tex = create_gxm_texture(
+        data,
+        texture->w,
+        texture->h,
+        PixelFormatToVITAFMT(texture->format),
+        (texture->access == SDL_TEXTUREACCESS_TARGET),
+        &(vita_texture->w),
+        &(vita_texture->h),
+        &(vita_texture->pitch),
+        &(vita_texture->wscale)
+    );
 
     if (!vita_texture->tex) {
         SDL_free(vita_texture);
@@ -306,38 +335,129 @@ VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
 
     VITA_GXM_SetTextureScaleMode(renderer, texture, texture->scaleMode);
 
-    vita_texture->w = gxm_texture_get_width(vita_texture->tex);
-    vita_texture->h = gxm_texture_get_height(vita_texture->tex);
-    vita_texture->pitch = gxm_texture_get_stride(vita_texture->tex);
+#if SDL_HAVE_YUV
+    vita_texture->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
+    vita_texture->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21));
+#endif
 
     return 0;
 }
 
+static void VITA_GXM_SetYUVProfile(SDL_Renderer * renderer, SDL_Texture *texture)
+{
+    VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
+    int ret = 0;
+    switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
+    case SDL_YUV_CONVERSION_BT601:
+        ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT601_STANDARD);
+        break;
+    case SDL_YUV_CONVERSION_BT709:
+        ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT709_STANDARD);
+        break;
+    case SDL_YUV_CONVERSION_JPEG:
+    default:
+        SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Unsupported YUV profile: %d\n", SDL_GetYUVConversionModeForResolution(texture->w, texture->h));
+        break;
+  }
+
+  if (ret < 0) {
+      SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Setting YUV profile failed: %x\n", ret);
+  }
+}
 
 static int
 VITA_GXM_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
     const SDL_Rect *rect, const void *pixels, int pitch)
 {
-    const Uint8 *src;
+    VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *) texture->driverdata;
     Uint8 *dst;
-    int row, length,dpitch;
-    src = pixels;
+    int row, length, dpitch;
+
+#if SDL_HAVE_YUV
+    if (vita_texture->yuv || vita_texture->nv12) {
+        VITA_GXM_SetYUVProfile(renderer, texture);
+    }
+#endif
 
     VITA_GXM_LockTexture(renderer, texture, rect, (void **)&dst, &dpitch);
     length = rect->w * SDL_BYTESPERPIXEL(texture->format);
     if (length == pitch && length == dpitch) {
-        SDL_memcpy(dst, src, length*rect->h);
+        SDL_memcpy(dst, pixels, length*rect->h);
     } else {
         for (row = 0; row < rect->h; ++row) {
-            SDL_memcpy(dst, src, length);
-            src += pitch;
+            SDL_memcpy(dst, pixels, length);
+            pixels += pitch;
             dst += dpitch;
         }
     }
 
+#if SDL_HAVE_YUV
+    if (vita_texture->yuv) {
+        void *Udst;
+        void *Vdst;
+        int uv_pitch = (dpitch+1) / 2;
+        int uv_src_pitch = (pitch+1) / 2;
+        SDL_Rect UVrect = {rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2};
+
+        // skip Y plane
+        Uint8 *Dpixels = gxm_texture_get_datap(vita_texture->tex) + (vita_texture->pitch * vita_texture->h);
+
+        Udst = Dpixels + (UVrect.y * uv_pitch) + UVrect.x;
+        Vdst = Dpixels + (uv_pitch * ((vita_texture->h + 1) / 2)) + (UVrect.y * uv_pitch) + UVrect.x;
+
+        length = UVrect.w;
+
+        // U plane
+        if (length == uv_src_pitch && length == uv_pitch) {
+            SDL_memcpy(Udst, pixels, length*UVrect.h);
+        } else {
+            for (row = 0; row < UVrect.h; ++row) {
+                SDL_memcpy(Udst, pixels, length);
+                pixels += uv_src_pitch;
+                Udst += uv_pitch;
+            }
+        }
+
+        // V plane
+        if (length == uv_src_pitch && length == uv_pitch) {
+            SDL_memcpy(Vdst, pixels, length*UVrect.h);
+        } else {
+            for (row = 0; row < UVrect.h; ++row) {
+                SDL_memcpy(Vdst, pixels, length);
+                pixels += uv_src_pitch;
+                Vdst += uv_pitch;
+            }
+        }
+
+    } else if (vita_texture->nv12) {
+        void *UVdst;
+        int uv_pitch = 2 * ((dpitch+1) / 2);
+        int uv_src_pitch = 2 * ((pitch+1) / 2);
+        SDL_Rect UVrect = {rect->x / 2, rect->y / 2, (rect->w + 1) / 2 , (rect->h + 1) / 2};
+
+        // skip Y plane
+        void *Dpixels = (void *) ((Uint8 *) gxm_texture_get_datap(vita_texture->tex) + (vita_texture->pitch * vita_texture->h));
+        UVdst = Dpixels + (UVrect.y * uv_pitch) + UVrect.x;
+
+        length = UVrect.w*2;
+
+        // UV plane
+        if (length == uv_src_pitch && length == uv_pitch) {
+            SDL_memcpy(UVdst, pixels, length*UVrect.h);
+        } else {
+            for (row = 0; row < UVrect.h; ++row) {
+                SDL_memcpy(UVdst, pixels, length);
+                pixels += uv_src_pitch;
+                UVdst += uv_pitch;
+            }
+        }
+    }
+#endif
+
     return 0;
 }
 
+#if SDL_HAVE_YUV
 static int
 VITA_GXM_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
     const SDL_Rect * rect,
@@ -345,9 +465,133 @@ VITA_GXM_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
     const Uint8 *Uplane, int Upitch,
     const Uint8 *Vplane, int Vpitch)
 {
+    Uint8 *dst;
+    int row, length, dpitch;
+    SDL_Rect UVrect = {rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2};
+
+    VITA_GXM_SetYUVProfile(renderer, texture);
+
+    // copy Y plane
+    // obtain pixels via locking so that texture is flushed
+    VITA_GXM_LockTexture(renderer, texture, rect, (void **)&dst, &dpitch);
+
+    length = rect->w;
+
+    if (length == Ypitch && length == dpitch) {
+        SDL_memcpy(dst, Yplane, length*rect->h);
+    } else {
+        for (row = 0; row < rect->h; ++row) {
+            SDL_memcpy(dst, Yplane, length);
+            Yplane += Ypitch;
+            dst += dpitch;
+        }
+    }
+
+    // U/V planes
+    {
+        void *Udst;
+        void *Vdst;
+        VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *) texture->driverdata;
+        int uv_pitch = (dpitch+1) / 2;
+
+        // skip Y plane
+        void *pixels = (void *) ((Uint8 *) gxm_texture_get_datap(vita_texture->tex) + (vita_texture->pitch * vita_texture->h));
+
+        if (texture->format == SDL_PIXELFORMAT_YV12) { // YVU
+            Vdst = pixels + (UVrect.y * uv_pitch) + UVrect.x;
+            Udst = pixels + (uv_pitch * ((vita_texture->h + 1) / 2)) + (UVrect.y * uv_pitch) + UVrect.x;
+        } else { // YUV
+            Udst = pixels + (UVrect.y * uv_pitch) + UVrect.x;
+            Vdst = pixels + (uv_pitch * ((vita_texture->h + 1) / 2)) + (UVrect.y * uv_pitch) + UVrect.x;
+        }
+
+        length = UVrect.w;
+
+        // U plane
+        if (length == Upitch && length == uv_pitch) {
+            SDL_memcpy(Udst, Uplane, length*UVrect.h);
+        } else {
+            for (row = 0; row < UVrect.h; ++row) {
+                SDL_memcpy(Udst, Uplane, length);
+                Uplane += Upitch;
+                Udst += uv_pitch;
+            }
+        }
+
+        // V plane
+        if (length == Vpitch && length == uv_pitch) {
+            SDL_memcpy(Vdst, Vplane, length*UVrect.h);
+        } else {
+            for (row = 0; row < UVrect.h; ++row) {
+                SDL_memcpy(Vdst, Vplane, length);
+                Vplane += Vpitch;
+                Vdst += uv_pitch;
+            }
+        }
+
+    }
+
+    return 0;
+}
+
+static int
+VITA_GXM_UpdateTextureNV(SDL_Renderer * renderer, SDL_Texture * texture,
+    const SDL_Rect * rect,
+    const Uint8 *Yplane, int Ypitch,
+    const Uint8 *UVplane, int UVpitch)
+{
+
+    Uint8 *dst;
+    int row, length, dpitch;
+    SDL_Rect UVrect = {rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2};
+
+    VITA_GXM_SetYUVProfile(renderer, texture);
+
+    // copy Y plane
+    VITA_GXM_LockTexture(renderer, texture, rect, (void **)&dst, &dpitch);
+
+    length = rect->w * SDL_BYTESPERPIXEL(texture->format);
+
+    if (length == Ypitch && length == dpitch) {
+      SDL_memcpy(dst, Yplane, length*rect->h);
+    } else {
+        for (row = 0; row < rect->h; ++row) {
+          SDL_memcpy(dst, Yplane, length);
+            Yplane += Ypitch;
+            dst += dpitch;
+        }
+    }
+
+    // UV plane
+    {
+        void *UVdst;
+        VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *) texture->driverdata;
+        int uv_pitch = 2 * ((dpitch+1) / 2);
+
+        // skip Y plane
+        void *pixels = (void *) ((Uint8 *) gxm_texture_get_datap(vita_texture->tex) + (vita_texture->pitch * vita_texture->h));
+
+        UVdst = pixels + (UVrect.y * uv_pitch) + UVrect.x;
+
+        length = UVrect.w * 2;
+
+        // UV plane
+        if (length == UVpitch && length == uv_pitch) {
+            SDL_memcpy(UVdst, UVplane, length*UVrect.h);
+        } else {
+            for (row = 0; row < UVrect.h; ++row) {
+                SDL_memcpy(UVdst, UVplane, length);
+                UVplane += UVpitch;
+                UVdst += uv_pitch;
+            }
+        }
+    }
+
     return 0;
 }
 
+#endif
+
 static int
 VITA_GXM_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
     const SDL_Rect *rect, void **pixels, int *pitch)
@@ -512,6 +756,7 @@ VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Textu
         float scale_x, float scale_y)
 {
     VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
+    VITA_GXM_TextureData* vita_texture = (VITA_GXM_TextureData*) texture->driverdata;
     int i;
     int count = indices ? num_indices : num_vertices;
 
@@ -551,7 +796,7 @@ VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Textu
 
             vertices[i].x = xy_[0] * scale_x;
             vertices[i].y = xy_[1] * scale_y;
-            vertices[i].u = uv_[0];
+            vertices[i].u = uv_[0] * vita_texture->wscale;
             vertices[i].v = uv_[1];
             vertices[i].color = col_;
         }
@@ -730,14 +975,6 @@ SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd)
     return 0;
 }
 
-static int
-SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
-{
-    VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
-
-    return SetDrawState(data, cmd);
-}
-
 static int
 VITA_GXM_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
 {
@@ -824,11 +1061,7 @@ VITA_GXM_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *
                     nextcmd = nextcmd->next;
                 }
 
-                if (thistexture) {
-                    ret = SetCopyState(renderer, cmd);
-                } else {
-                    ret = SetDrawState(data, cmd);
-                }
+                ret = SetDrawState(data, cmd);
 
                 if (ret == 0) {
                     int op = SCE_GXM_PRIMITIVE_TRIANGLES;
diff --git a/src/render/vitagxm/SDL_render_vita_gxm_tools.c b/src/render/vitagxm/SDL_render_vita_gxm_tools.c
index e043b55ab18..0ecae38394c 100644
--- a/src/render/vitagxm/SDL_render_vita_gxm_tools.c
+++ b/src/render/vitagxm/SDL_render_vita_gxm_tools.c
@@ -117,6 +117,8 @@ tex_format_to_bytespp(SceGxmTextureFormat format)
     case SCE_GXM_TEXTURE_BASE_FORMAT_U8:
     case SCE_GXM_TEXTURE_BASE_FORMAT_S8:
     case SCE_GXM_TEXTURE_BASE_FORMAT_P8:
+    case SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P2: // YUV actually uses 12 bits per pixel. UV planes bits/mem are handled elsewhere
+    case SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P3:
         return 1;
     case SCE_GXM_TEXTURE_BASE_FORMAT_U4U4U4U4:
     case SCE_GXM_TEXTURE_BASE_FORMAT_U8U3U3U2:
@@ -995,25 +997,6 @@ gxm_texture_get_format(const gxm_texture *texture)
     return sceGxmTextureGetFormat(&texture->gxm_tex);
 }
 
-unsigned int
-gxm_texture_get_width(const gxm_texture *texture)
-{
-    return sceGxmTextureGetWidth(&texture->gxm_tex);
-}
-
-unsigned int
-gxm_texture_get_height(const gxm_texture *texture)
-{
-    return sceGxmTextureGetHeight(&texture->gxm_tex);
-}
-
-unsigned int
-gxm_texture_get_stride(const gxm_texture *texture)
-{
-    return ((gxm_texture_get_width(texture) + 7) & ~7)
-        * tex_format_to_bytespp(gxm_texture_get_format(texture));
-}
-
 void *
 gxm_texture_get_datap(const gxm_texture *texture)
 {
@@ -1021,15 +1004,34 @@ gxm_texture_get_datap(const gxm_texture *texture)
 }
 
 gxm_texture *
-create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget)
+create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget, unsigned int *return_w, unsigned int *return_h, unsigned int *return_pitch, float *return_wscale)
 {
     gxm_texture *texture = SDL_calloc(1, sizeof(gxm_texture));
-    const int tex_size =  ((w + 7) & ~ 7) * h * tex_format_to_bytespp(format);
+    int aligned_w = ALIGN(w, 8);
+    int texture_w = w;
+    int tex_size =  aligned_w * h * tex_format_to_bytespp(format);
     void *texture_data;
+    int ret;
+
+    *return_wscale = 1.0f;
+
+    // SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P3/P2 based formats require width aligned to 16
+    if ( (format & 0x9f000000U) == SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P3 || (format & 0x9f000000U) == SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P2) {
+        aligned_w = ALIGN(w, 16);
+        texture_w = aligned_w;
+        tex_size =  aligned_w * h * tex_format_to_bytespp(format);
+        *return_wscale = (float) (w) / texture_w;
+        // add storage for UV planes
+        tex_size += (((aligned_w + 1) / 2) * ((h + 1) / 2)) * 2;
+    }
 
     if (!texture)
         return NULL;
 
+    *return_w = w;
+    *return_h = h;
+    *return_pitch = aligned_w * tex_format_to_bytespp(format);
+
     /* Allocate a GPU buffer for the texture */
     texture_data = mem_gpu_alloc(
         SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
@@ -1060,7 +1062,12 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
     SDL_memset(texture_data, 0, tex_size);
 
     /* Create the gxm texture */
-    sceGxmTextureInitLinear( &texture->gxm_tex, texture_data, format, w, h, 0);
+    ret = sceGxmTextureInitLinear( &texture->gxm_tex, texture_data, format, texture_w, h, 0);
+    if (ret < 0) {
+      free_gxm_texture(texture);
+      SDL_LogError(SDL_LOG_CATEGORY_RENDER, "texture init failed: %x\n", ret);
+      return NULL;
+    }
 
     if (isRenderTarget) {
         void *depthBufferData;
@@ -1084,7 +1091,7 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
 
         if (err < 0) {
             free_gxm_texture(texture);
-            SDL_LogError(SDL_LOG_CATEGORY_RENDER, "color surface init failed: %d\n", err);
+            SDL_LogError(SDL_LOG_CATEGORY_RENDER, "color surface init failed: %x\n", err);
             return NULL;
         }
 
@@ -1107,7 +1114,7 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
 
         if (err < 0) {
             free_gxm_texture(texture);
-            SDL_LogError(SDL_LOG_CATEGORY_RENDER, "depth stencil init failed: %d\n", err);
+            SDL_LogError(SDL_LOG_CATEGORY_RENDER, "depth stencil init failed: %x\n", err);
             return NULL;
         }
 
@@ -1132,7 +1139,7 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
 
             if (err < 0) {
                 free_gxm_texture(texture);
-                SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create render target failed: %d\n", err);
+                SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create render target failed: %x\n", err);
                 return NULL;
             }
         }
diff --git a/src/render/vitagxm/SDL_render_vita_gxm_tools.h b/src/render/vitagxm/SDL_render_vita_gxm_tools.h
index 351bdc2e669..8e9caeb2102 100644
--- a/src/render/vitagxm/SDL_render_vita_gxm_tools.h
+++ b/src/render/vitagxm/SDL_render_vita_gxm_tools.h
@@ -48,15 +48,12 @@ void unset_clip_rectangle(VITA_GXM_RenderData *data);
 int gxm_init(SDL_Renderer *renderer);
 void gxm_finish(SDL_Renderer *renderer);
 
-gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget);
+gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget, unsigned int *return_w, unsigned int *return_h, unsigned int *return_pitch, float *return_wscale);
 void free_gxm_texture(gxm_texture *texture);
 
 void gxm_texture_set_filters(gxm_texture *texture, SceGxmTextureFilter min_filter, SceGxmTextureFilter mag_filter);
 SceGxmTextureFormat gxm_texture_get_format(const gxm_texture *texture);
 
-unsigned int gxm_texture_get_width(const gxm_texture *texture);
-unsigned int gxm_texture_get_height(const gxm_texture *texture);
-unsigned int gxm_texture_get_stride(const gxm_texture *texture);
 void *gxm_texture_get_datap(const gxm_texture *texture);
 
 void gxm_minimal_init_for_common_dialog(void);
diff --git a/src/render/vitagxm/SDL_render_vita_gxm_types.h b/src/render/vitagxm/SDL_render_vita_gxm_types.h
index 898a92d9c81..2bf8d358505 100644
--- a/src/render/vitagxm/SDL_render_vita_gxm_types.h
+++ b/src/render/vitagxm/SDL_render_vita_gxm_types.h
@@ -191,9 +191,12 @@ typedef struct
 typedef struct
 {
     gxm_texture  *tex;
-    unsigned int    pitch;
-    unsigned int    w;
-    unsigned int    h;
+    unsigned int pitch;
+    unsigned int w;
+    unsigned int h;
+    float wscale;
+    SDL_bool     yuv;
+    SDL_bool     nv12;
 } VITA_GXM_TextureData;
 
 #endif /* SDL_RENDER_VITA_GXM_TYPES_H */