| /* |
| Simple DirectMedia Layer |
| Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> |
| |
| This software is provided 'as-is', without any express or implied |
| warranty. In no event will the authors be held liable for any damages |
| arising from the use of this software. |
| |
| Permission is granted to anyone to use this software for any purpose, |
| including commercial applications, and to alter it and redistribute it |
| freely, subject to the following restrictions: |
| |
| 1. The origin of this software must not be misrepresented; you must not |
| claim that you wrote the original software. If you use this software |
| in a product, an acknowledgment in the product documentation would be |
| appreciated but is not required. |
| 2. Altered source versions must be plainly marked as such, and must not be |
| misrepresented as being the original software. |
| 3. This notice may not be removed or altered from any source distribution. |
| */ |
| #include "SDL_internal.h" |
| |
| #if SDL_VIDEO_RENDER_VITA_GXM |
| |
| #include "../SDL_sysrender.h" |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <math.h> |
| #include <stdarg.h> |
| #include <stdlib.h> |
| |
| #include "SDL_render_vita_gxm_types.h" |
| #include "SDL_render_vita_gxm_tools.h" |
| #include "SDL_render_vita_gxm_memory.h" |
| |
| #include <psp2/common_dialog.h> |
| |
| /* #define DEBUG_RAZOR */ |
| |
| #ifdef DEBUG_RAZOR |
| #include <psp2/sysmodule.h> |
| #endif |
| |
| static int VITA_GXM_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props); |
| |
| static void VITA_GXM_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event); |
| |
| static SDL_bool VITA_GXM_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode); |
| |
| static int VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props); |
| |
| static int VITA_GXM_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, |
| const SDL_Rect *rect, const void *pixels, int pitch); |
| |
| static int VITA_GXM_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture, |
| const SDL_Rect *rect, |
| const Uint8 *Yplane, int Ypitch, |
| 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); |
| |
| static void VITA_GXM_UnlockTexture(SDL_Renderer *renderer, |
| SDL_Texture *texture); |
| |
| static void VITA_GXM_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode); |
| |
| static int VITA_GXM_SetRenderTarget(SDL_Renderer *renderer, |
| SDL_Texture *texture); |
| |
| static int VITA_GXM_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd); |
| |
| static int VITA_GXM_QueueSetDrawColor(SDL_Renderer *renderer, SDL_RenderCommand *cmd); |
| |
| static int VITA_GXM_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count); |
| static int VITA_GXM_QueueDrawLines(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count); |
| |
| static int VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, |
| const float *xy, int xy_stride, const SDL_FColor *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); |
| |
| static int VITA_GXM_RenderClear(SDL_Renderer *renderer, SDL_RenderCommand *cmd); |
| |
| static void VITA_GXM_InvalidateCachedState(SDL_Renderer *renderer); |
| |
| static int VITA_GXM_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize); |
| |
| static SDL_Surface *VITA_GXM_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect); |
| |
| static int VITA_GXM_RenderPresent(SDL_Renderer *renderer); |
| static void VITA_GXM_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture); |
| static void VITA_GXM_DestroyRenderer(SDL_Renderer *renderer); |
| |
| SDL_RenderDriver VITA_GXM_RenderDriver = { |
| VITA_GXM_CreateRenderer, "VITA gxm" |
| }; |
| |
| static int PixelFormatToVITAFMT(Uint32 format) |
| { |
| switch (format) { |
| case SDL_PIXELFORMAT_ARGB8888: |
| return SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ARGB; |
| case SDL_PIXELFORMAT_XRGB8888: |
| return SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ARGB; |
| case SDL_PIXELFORMAT_XBGR8888: |
| return SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ABGR; |
| case SDL_PIXELFORMAT_ABGR8888: |
| return SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ABGR; |
| case SDL_PIXELFORMAT_RGB565: |
| 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; |
| } |
| } |
| |
| void StartDrawing(SDL_Renderer *renderer) |
| { |
| VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata; |
| if (data->drawing) { |
| return; |
| } |
| |
| data->drawstate.texture = NULL; |
| data->drawstate.vertex_program = NULL; |
| data->drawstate.fragment_program = NULL; |
| data->drawstate.last_command = -1; |
| data->drawstate.viewport_dirty = SDL_TRUE; |
| |
| // reset blend mode |
| // data->currentBlendMode = SDL_BLENDMODE_BLEND; |
| // fragment_programs *in = &data->blendFragmentPrograms.blend_mode_blend; |
| // data->colorFragmentProgram = in->color; |
| // data->textureFragmentProgram = in->texture; |
| |
| if (!renderer->target) { |
| sceGxmBeginScene( |
| data->gxm_context, |
| 0, |
| data->renderTarget, |
| NULL, |
| NULL, |
| data->displayBufferSync[data->backBufferIndex], |
| &data->displaySurface[data->backBufferIndex], |
| &data->depthSurface); |
| } else { |
| VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)renderer->target->driverdata; |
| |
| sceGxmBeginScene( |
| data->gxm_context, |
| 0, |
| vita_texture->tex->gxm_rendertarget, |
| NULL, |
| NULL, |
| NULL, |
| &vita_texture->tex->gxm_colorsurface, |
| &vita_texture->tex->gxm_depthstencil); |
| } |
| |
| // unset_clip_rectangle(data); |
| |
| data->drawing = SDL_TRUE; |
| } |
| |
| static int VITA_GXM_SetVSync(SDL_Renderer *renderer, const int vsync) |
| { |
| VITA_GXM_RenderData *data = renderer->driverdata; |
| if (vsync) { |
| data->displayData.wait_vblank = SDL_TRUE; |
| } else { |
| data->displayData.wait_vblank = SDL_FALSE; |
| } |
| return 0; |
| } |
| |
| static int VITA_GXM_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props) |
| { |
| VITA_GXM_RenderData *data; |
| |
| SDL_SetupRendererColorspace(renderer, create_props); |
| |
| if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) { |
| return SDL_SetError("Unsupported output colorspace"); |
| } |
| |
| data = (VITA_GXM_RenderData *)SDL_calloc(1, sizeof(VITA_GXM_RenderData)); |
| if (!data) { |
| return -1; |
| } |
| |
| renderer->WindowEvent = VITA_GXM_WindowEvent; |
| renderer->SupportsBlendMode = VITA_GXM_SupportsBlendMode; |
| renderer->CreateTexture = VITA_GXM_CreateTexture; |
| 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; |
| renderer->SetTextureScaleMode = VITA_GXM_SetTextureScaleMode; |
| renderer->SetRenderTarget = VITA_GXM_SetRenderTarget; |
| renderer->QueueSetViewport = VITA_GXM_QueueNoOp; |
| renderer->QueueSetDrawColor = VITA_GXM_QueueSetDrawColor; |
| renderer->QueueDrawPoints = VITA_GXM_QueueDrawPoints; |
| renderer->QueueDrawLines = VITA_GXM_QueueDrawLines; |
| renderer->QueueGeometry = VITA_GXM_QueueGeometry; |
| renderer->InvalidateCachedState = VITA_GXM_InvalidateCachedState; |
| renderer->RunCommandQueue = VITA_GXM_RunCommandQueue; |
| renderer->RenderReadPixels = VITA_GXM_RenderReadPixels; |
| renderer->RenderPresent = VITA_GXM_RenderPresent; |
| renderer->DestroyTexture = VITA_GXM_DestroyTexture; |
| renderer->DestroyRenderer = VITA_GXM_DestroyRenderer; |
| renderer->SetVSync = VITA_GXM_SetVSync; |
| |
| renderer->driverdata = data; |
| VITA_GXM_InvalidateCachedState(renderer); |
| renderer->window = window; |
| |
| renderer->info.name = VITA_GXM_RenderDriver.name; |
| SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR8888); |
| SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888); |
| SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGB565); |
| SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGR565); |
| SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12); |
| SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV); |
| SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV12); |
| SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21); |
| SDL_SetNumberProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER, 4096); |
| |
| data->initialized = SDL_TRUE; |
| |
| #ifdef DEBUG_RAZOR |
| sceSysmoduleLoadModule(SCE_SYSMODULE_RAZOR_HUD); |
| sceSysmoduleLoadModule(SCE_SYSMODULE_RAZOR_CAPTURE); |
| #endif |
| |
| if (gxm_init(renderer) != 0) { |
| SDL_free(data); |
| return SDL_SetError("gxm_init failed"); |
| } |
| |
| return 0; |
| } |
| |
| static void VITA_GXM_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event) |
| { |
| } |
| |
| static SDL_bool VITA_GXM_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode) |
| { |
| // only for custom modes. we build all modes on init, so no custom modes, sorry |
| return SDL_FALSE; |
| } |
| |
| static int VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) |
| { |
| VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata; |
| VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)SDL_calloc(1, sizeof(VITA_GXM_TextureData)); |
| |
| if (!vita_texture) { |
| return -1; |
| } |
| |
| 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); |
| return SDL_OutOfMemory(); |
| } |
| |
| texture->driverdata = vita_texture; |
| |
| VITA_GXM_SetTextureScaleMode(renderer, texture, texture->scaleMode); |
| |
| #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; |
| if (SDL_ISCOLORSPACE_MATRIX_BT601(texture->colorspace)) { |
| if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) { |
| ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT601_STANDARD); |
| } else { |
| ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT601_FULL_RANGE); |
| } |
| } else if (SDL_ISCOLORSPACE_MATRIX_BT709(texture->colorspace)) { |
| if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) { |
| ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT709_STANDARD); |
| } else { |
| ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT709_FULL_RANGE); |
| } |
| } else { |
| SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Unsupported YUV colorspace\n"); |
| } |
| |
| 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) |
| { |
| VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->driverdata; |
| Uint8 *dst; |
| 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, pixels, length * rect->h); |
| } else { |
| for (row = 0; row < rect->h; ++row) { |
| 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, |
| const Uint8 *Yplane, int Ypitch, |
| 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) |
| { |
| VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata; |
| VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->driverdata; |
| |
| *pixels = |
| (void *)((Uint8 *)gxm_texture_get_datap(vita_texture->tex) + (rect->y * vita_texture->pitch) + rect->x * SDL_BYTESPERPIXEL(texture->format)); |
| *pitch = vita_texture->pitch; |
| |
| // make sure that rendering is finished on render target textures |
| if (vita_texture->tex->gxm_rendertarget) { |
| sceGxmFinish(data->gxm_context); |
| } |
| |
| return 0; |
| } |
| |
| static void VITA_GXM_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture) |
| { |
| // No need to update texture data on ps vita. |
| // VITA_GXM_LockTexture already returns a pointer to the texture pixels buffer. |
| // This really improves framerate when using lock/unlock. |
| } |
| |
| static void VITA_GXM_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode) |
| { |
| VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->driverdata; |
| |
| /* |
| set texture filtering according to scaleMode |
| supported hint values are nearest (0, default) or linear (1) |
| vitaScaleMode is either SCE_GXM_TEXTURE_FILTER_POINT (good for tile-map) |
| or SCE_GXM_TEXTURE_FILTER_LINEAR (good for scaling) |
| */ |
| |
| int vitaScaleMode = (scaleMode == SDL_SCALEMODE_NEAREST |
| ? SCE_GXM_TEXTURE_FILTER_POINT |
| : SCE_GXM_TEXTURE_FILTER_LINEAR); |
| gxm_texture_set_filters(vita_texture->tex, vitaScaleMode, vitaScaleMode); |
| |
| return; |
| } |
| |
| static int VITA_GXM_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) |
| { |
| return 0; |
| } |
| |
| static void VITA_GXM_SetBlendMode(VITA_GXM_RenderData *data, int blendMode) |
| { |
| if (blendMode != data->currentBlendMode) { |
| fragment_programs *in = &data->blendFragmentPrograms.blend_mode_blend; |
| |
| switch (blendMode) { |
| case SDL_BLENDMODE_NONE: |
| in = &data->blendFragmentPrograms.blend_mode_none; |
| break; |
| case SDL_BLENDMODE_BLEND: |
| in = &data->blendFragmentPrograms.blend_mode_blend; |
| break; |
| case SDL_BLENDMODE_ADD: |
| in = &data->blendFragmentPrograms.blend_mode_add; |
| break; |
| case SDL_BLENDMODE_MOD: |
| in = &data->blendFragmentPrograms.blend_mode_mod; |
| break; |
| case SDL_BLENDMODE_MUL: |
| in = &data->blendFragmentPrograms.blend_mode_mul; |
| break; |
| } |
| data->colorFragmentProgram = in->color; |
| data->textureFragmentProgram = in->texture; |
| data->currentBlendMode = blendMode; |
| } |
| } |
| |
| static int VITA_GXM_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd) |
| { |
| return 0; |
| } |
| |
| static int VITA_GXM_QueueSetDrawColor(SDL_Renderer *renderer, SDL_RenderCommand *cmd) |
| { |
| VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata; |
| |
| data->drawstate.color.r = cmd->data.color.color.r * cmd->data.color.color_scale; |
| data->drawstate.color.g = cmd->data.color.color.g * cmd->data.color.color_scale; |
| data->drawstate.color.b = cmd->data.color.color.b * cmd->data.color.color_scale; |
| data->drawstate.color.a = cmd->data.color.color.a; |
| |
| return 0; |
| } |
| |
| static int VITA_GXM_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count) |
| { |
| VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata; |
| |
| SDL_FColor color = data->drawstate.color; |
| |
| color_vertex *vertex = (color_vertex *)pool_malloc( |
| data, |
| count * sizeof(color_vertex)); |
| |
| cmd->data.draw.first = (size_t)vertex; |
| cmd->data.draw.count = count; |
| |
| for (int i = 0; i < count; i++) { |
| vertex[i].x = points[i].x; |
| vertex[i].y = points[i].y; |
| vertex[i].color = color; |
| } |
| |
| return 0; |
| } |
| |
| static int VITA_GXM_QueueDrawLines(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count) |
| { |
| VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata; |
| SDL_FColor color = data->drawstate.color; |
| |
| color_vertex *vertex = (color_vertex *)pool_malloc( |
| data, |
| (count - 1) * 2 * sizeof(color_vertex)); |
| |
| cmd->data.draw.first = (size_t)vertex; |
| cmd->data.draw.count = (count - 1) * 2; |
| |
| for (int i = 0; i < count - 1; i++) { |
| vertex[i * 2].x = points[i].x; |
| vertex[i * 2].y = points[i].y; |
| 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].color = color; |
| } |
| |
| return 0; |
| } |
| |
| static int VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, |
| const float *xy, int xy_stride, const SDL_FColor *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; |
| const float color_scale = cmd->data.draw.color_scale; |
| |
| cmd->data.draw.count = count; |
| size_indices = indices ? size_indices : 0; |
| |
| if (texture) { |
| VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->driverdata; |
| texture_vertex *vertices; |
| |
| vertices = (texture_vertex *)pool_malloc( |
| data, |
| count * sizeof(texture_vertex)); |
| |
| if (!vertices) { |
| return -1; |
| } |
| |
| for (i = 0; i < count; i++) { |
| int j; |
| float *xy_; |
| float *uv_; |
| SDL_FColor 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_ = *(SDL_FColor *)((char *)color + j * color_stride); |
| uv_ = (float *)((char *)uv + j * uv_stride); |
| |
| col_.r *= color_scale; |
| col_.g *= color_scale; |
| col_.b *= color_scale; |
| |
| vertices[i].x = xy_[0] * scale_x; |
| vertices[i].y = xy_[1] * scale_y; |
| vertices[i].u = uv_[0] * vita_texture->wscale; |
| vertices[i].v = uv_[1]; |
| vertices[i].color = col_; |
| } |
| |
| cmd->data.draw.first = (size_t)vertices; |
| |
| } else { |
| color_vertex *vertices; |
| |
| vertices = (color_vertex *)pool_malloc( |
| data, |
| count * sizeof(color_vertex)); |
| |
| if (!vertices) { |
| return -1; |
| } |
| |
| for (i = 0; i < count; i++) { |
| int j; |
| float *xy_; |
| SDL_FColor 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_ = *(SDL_FColor *)((char *)color + j * color_stride); |
| |
| col_.r *= color_scale; |
| col_.g *= color_scale; |
| col_.b *= color_scale; |
| |
| 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; |
| } |
| |
| static int VITA_GXM_RenderClear(SDL_Renderer *renderer, SDL_RenderCommand *cmd) |
| { |
| void *color_buffer; |
| SDL_FColor color; |
| |
| VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata; |
| unset_clip_rectangle(data); |
| |
| // set clear shaders |
| data->drawstate.fragment_program = data->clearFragmentProgram; |
| data->drawstate.vertex_program = data->clearVertexProgram; |
| sceGxmSetVertexProgram(data->gxm_context, data->clearVertexProgram); |
| sceGxmSetFragmentProgram(data->gxm_context, data->clearFragmentProgram); |
| |
| // set the clear color |
| color = cmd->data.color.color; |
| color.r *= cmd->data.color.color_scale; |
| color.g *= cmd->data.color.color_scale; |
| color.b *= cmd->data.color.color_scale; |
| sceGxmReserveFragmentDefaultUniformBuffer(data->gxm_context, &color_buffer); |
| sceGxmSetUniformDataF(color_buffer, data->clearClearColorParam, 0, 4, &color.r); |
| |
| // draw the clear triangle |
| sceGxmSetVertexStream(data->gxm_context, 0, data->clearVertices); |
| sceGxmDraw(data->gxm_context, SCE_GXM_PRIMITIVE_TRIANGLES, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, 3); |
| |
| data->drawstate.cliprect_dirty = SDL_TRUE; |
| return 0; |
| } |
| |
| static int SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd) |
| { |
| SDL_Texture *texture = cmd->data.draw.texture; |
| const SDL_BlendMode blend = cmd->data.draw.blend; |
| SceGxmFragmentProgram *fragment_program; |
| SceGxmVertexProgram *vertex_program; |
| SDL_bool matrix_updated = SDL_FALSE; |
| SDL_bool program_updated = SDL_FALSE; |
| |
| if (data->drawstate.viewport_dirty) { |
| const SDL_Rect *viewport = &data->drawstate.viewport; |
| |
| float sw = viewport->w / 2.; |
| float sh = viewport->h / 2.; |
| |
| float x_scale = sw; |
| float x_off = viewport->x + sw; |
| float y_scale = -(sh); |
| float y_off = viewport->y + sh; |
| |
| sceGxmSetViewport(data->gxm_context, x_off, x_scale, y_off, y_scale, 0.5f, 0.5f); |
| |
| if (viewport->w && viewport->h) { |
| init_orthographic_matrix(data->ortho_matrix, |
| (float)0, |
| (float)viewport->w, |
| (float)viewport->h, |
| (float)0, |
| 0.0f, 1.0f); |
| matrix_updated = SDL_TRUE; |
| } |
| |
| data->drawstate.viewport_dirty = SDL_FALSE; |
| } |
| |
| if (data->drawstate.cliprect_enabled_dirty) { |
| if (!data->drawstate.cliprect_enabled) { |
| unset_clip_rectangle(data); |
| } |
| data->drawstate.cliprect_enabled_dirty = SDL_FALSE; |
| } |
| |
| if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) { |
| const SDL_Rect *rect = &data->drawstate.cliprect; |
| set_clip_rectangle(data, rect->x, rect->y, rect->x + rect->w, rect->y + rect->h); |
| data->drawstate.cliprect_dirty = SDL_FALSE; |
| } |
| |
| VITA_GXM_SetBlendMode(data, blend); // do that first, to select appropriate shaders |
| |
| if (texture) { |
| vertex_program = data->textureVertexProgram; |
| fragment_program = data->textureFragmentProgram; |
| } else { |
| vertex_program = data->colorVertexProgram; |
| fragment_program = data->colorFragmentProgram; |
| } |
| |
| if (data->drawstate.vertex_program != vertex_program) { |
| data->drawstate.vertex_program = vertex_program; |
| sceGxmSetVertexProgram(data->gxm_context, vertex_program); |
| program_updated = SDL_TRUE; |
| } |
| |
| if (data->drawstate.fragment_program != fragment_program) { |
| data->drawstate.fragment_program = fragment_program; |
| sceGxmSetFragmentProgram(data->gxm_context, fragment_program); |
| program_updated = SDL_TRUE; |
| } |
| |
| 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 { // color |
| void *vertexDefaultBuffer; |
| sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertexDefaultBuffer); |
| sceGxmSetUniformDataF(vertexDefaultBuffer, data->colorWvpParam, 0, 16, data->ortho_matrix); |
| } |
| } |
| |
| if (texture != data->drawstate.texture) { |
| if (texture) { |
| VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)cmd->data.draw.texture->driverdata; |
| sceGxmSetFragmentTexture(data->gxm_context, 0, &vita_texture->tex->gxm_tex); |
| } |
| data->drawstate.texture = texture; |
| } |
| |
| /* all drawing commands use this */ |
| sceGxmSetVertexStream(data->gxm_context, 0, (const void *)cmd->data.draw.first); |
| |
| return 0; |
| } |
| |
| static void VITA_GXM_InvalidateCachedState(SDL_Renderer *renderer) |
| { |
| /* currently this doesn't do anything. If this needs to do something (and someone is mixing their own rendering calls in!), update this. */ |
| } |
| |
| static int VITA_GXM_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) |
| { |
| VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata; |
| StartDrawing(renderer); |
| |
| data->drawstate.target = renderer->target; |
| if (!data->drawstate.target) { |
| int w, h; |
| SDL_GetWindowSizeInPixels(renderer->window, &w, &h); |
| if ((w != data->drawstate.drawablew) || (h != data->drawstate.drawableh)) { |
| data->drawstate.viewport_dirty = SDL_TRUE; // if the window dimensions changed, invalidate the current viewport, etc. |
| data->drawstate.cliprect_dirty = SDL_TRUE; |
| data->drawstate.drawablew = w; |
| data->drawstate.drawableh = h; |
| } |
| } |
| |
| while (cmd) { |
| switch (cmd->command) { |
| |
| case SDL_RENDERCMD_SETVIEWPORT: |
| { |
| SDL_Rect *viewport = &data->drawstate.viewport; |
| if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof(cmd->data.viewport.rect)) != 0) { |
| SDL_copyp(viewport, &cmd->data.viewport.rect); |
| data->drawstate.viewport_dirty = SDL_TRUE; |
| data->drawstate.cliprect_dirty = SDL_TRUE; |
| } |
| break; |
| } |
| |
| case SDL_RENDERCMD_SETCLIPRECT: |
| { |
| const SDL_Rect *rect = &cmd->data.cliprect.rect; |
| if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) { |
| data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled; |
| data->drawstate.cliprect_enabled_dirty = SDL_TRUE; |
| } |
| |
| if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof(*rect)) != 0) { |
| SDL_copyp(&data->drawstate.cliprect, rect); |
| data->drawstate.cliprect_dirty = SDL_TRUE; |
| } |
| break; |
| } |
| |
| case SDL_RENDERCMD_SETDRAWCOLOR: |
| { |
| break; |
| } |
| |
| case SDL_RENDERCMD_CLEAR: |
| { |
| VITA_GXM_RenderClear(renderer, cmd); |
| break; |
| } |
| |
| case SDL_RENDERCMD_FILL_RECTS: /* unused */ |
| break; |
| |
| case SDL_RENDERCMD_COPY: /* unused */ |
| break; |
| |
| case SDL_RENDERCMD_COPY_EX: /* unused */ |
| break; |
| |
| case SDL_RENDERCMD_DRAW_POINTS: |
| case SDL_RENDERCMD_DRAW_LINES: |
| case SDL_RENDERCMD_GEOMETRY: |
| { |
| SDL_Texture *thistexture = cmd->data.draw.texture; |
| SDL_BlendMode thisblend = cmd->data.draw.blend; |
| const SDL_RenderCommandType thiscmdtype = cmd->command; |
| SDL_RenderCommand *finalcmd = cmd; |
| SDL_RenderCommand *nextcmd = cmd->next; |
| size_t count = cmd->data.draw.count; |
| int ret; |
| while (nextcmd) { |
| const SDL_RenderCommandType nextcmdtype = nextcmd->command; |
| if (nextcmdtype != thiscmdtype) { |
| break; /* can't go any further on this draw call, different render command up next. */ |
| } else if (nextcmd->data.draw.texture != thistexture || nextcmd->data.draw.blend != thisblend) { |
| break; /* can't go any further on this draw call, different texture/blendmode copy up next. */ |
| } else { |
| finalcmd = nextcmd; /* we can combine copy operations here. Mark this one as the furthest okay command. */ |
| count += nextcmd->data.draw.count; |
| } |
| nextcmd = nextcmd->next; |
| } |
| |
| ret = SetDrawState(data, cmd); |
| |
| if (ret == 0) { |
| int op = SCE_GXM_PRIMITIVE_TRIANGLES; |
| |
| if (thiscmdtype == SDL_RENDERCMD_DRAW_POINTS) { |
| sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_POINT); |
| op = SCE_GXM_PRIMITIVE_POINTS; |
| } else if (thiscmdtype == SDL_RENDERCMD_DRAW_LINES) { |
| sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_LINE); |
| op = SCE_GXM_PRIMITIVE_LINES; |
| } |
| |
| sceGxmDraw(data->gxm_context, op, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, count); |
| |
| if (thiscmdtype == SDL_RENDERCMD_DRAW_POINTS || thiscmdtype == SDL_RENDERCMD_DRAW_LINES) { |
| sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_TRIANGLE_FILL); |
| } |
| } |
| |
| cmd = finalcmd; /* skip any copy commands we just combined in here. */ |
| break; |
| } |
| |
| case SDL_RENDERCMD_NO_OP: |
| break; |
| } |
| data->drawstate.last_command = cmd->command; |
| cmd = cmd->next; |
| } |
| |
| sceGxmEndScene(data->gxm_context, NULL, NULL); |
| data->drawing = SDL_FALSE; |
| |
| return 0; |
| } |
| |
| void read_pixels(int x, int y, size_t width, size_t height, void *data) |
| { |
| SceDisplayFrameBuf pParam; |
| int i, j; |
| Uint32 *out32; |
| Uint32 *in32; |
| |
| pParam.size = sizeof(SceDisplayFrameBuf); |
| |
| sceDisplayGetFrameBuf(&pParam, SCE_DISPLAY_SETBUF_NEXTFRAME); |
| |
| out32 = (Uint32 *)data; |
| in32 = (Uint32 *)pParam.base; |
| |
| in32 += (x + y * pParam.pitch); |
| |
| for (i = 0; i < height; i++) { |
| for (j = 0; j < width; j++) { |
| out32[(height - (i + 1)) * width + j] = in32[j]; |
| } |
| in32 += pParam.pitch; |
| } |
| } |
| |
| static SDL_Surface *VITA_GXM_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect) |
| { |
| Uint32 format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888; |
| int w, h; |
| SDL_Surface *surface; |
| |
| // TODO: read from texture rendertarget. |
| if (renderer->target) { |
| SDL_Unsupported(); |
| return NULL; |
| } |
| |
| surface = SDL_CreateSurface(rect->w, rect->h, format); |
| if (!surface) { |
| return NULL; |
| } |
| |
| SDL_GetCurrentRenderOutputSize(renderer, &w, &h); |
| |
| read_pixels(rect->x, renderer->target ? rect->y : (h - rect->y) - rect->h, |
| rect->w, rect->h, surface->pixels); |
| |
| /* Flip the rows to be top-down if necessary */ |
| |
| if (!renderer->target) { |
| SDL_bool isstack; |
| int length = rect->w * SDL_BYTESPERPIXEL(format); |
| Uint8 *src = (Uint8 *)surface->pixels + (rect->h - 1) * surface->pitch; |
| Uint8 *dst = (Uint8 *)surface->pixels; |
| Uint8 *tmp = SDL_small_alloc(Uint8, length, &isstack); |
| int rows = rect->h / 2; |
| while (rows--) { |
| SDL_memcpy(tmp, dst, length); |
| SDL_memcpy(dst, src, length); |
| SDL_memcpy(src, tmp, length); |
| dst += surface->pitch; |
| src -= surface->pitch; |
| } |
| SDL_small_free(tmp, isstack); |
| } |
| return surface; |
| } |
| |
| static int VITA_GXM_RenderPresent(SDL_Renderer *renderer) |
| { |
| VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata; |
| SceCommonDialogUpdateParam updateParam; |
| |
| data->displayData.address = data->displayBufferData[data->backBufferIndex]; |
| |
| SDL_memset(&updateParam, 0, sizeof(updateParam)); |
| |
| updateParam.renderTarget.colorFormat = VITA_GXM_COLOR_FORMAT; |
| updateParam.renderTarget.surfaceType = SCE_GXM_COLOR_SURFACE_LINEAR; |
| updateParam.renderTarget.width = VITA_GXM_SCREEN_WIDTH; |
| updateParam.renderTarget.height = VITA_GXM_SCREEN_HEIGHT; |
| updateParam.renderTarget.strideInPixels = VITA_GXM_SCREEN_STRIDE; |
| |
| updateParam.renderTarget.colorSurfaceData = data->displayBufferData[data->backBufferIndex]; |
| updateParam.renderTarget.depthSurfaceData = data->depthBufferData; |
| |
| updateParam.displaySyncObject = (SceGxmSyncObject *)data->displayBufferSync[data->backBufferIndex]; |
| |
| sceCommonDialogUpdate(&updateParam); |
| |
| #ifdef DEBUG_RAZOR |
| sceGxmPadHeartbeat( |
| (const SceGxmColorSurface *)&data->displaySurface[data->backBufferIndex], |
| (SceGxmSyncObject *)data->displayBufferSync[data->backBufferIndex]); |
| #endif |
| |
| sceGxmDisplayQueueAddEntry( |
| data->displayBufferSync[data->frontBufferIndex], // OLD fb |
| data->displayBufferSync[data->backBufferIndex], // NEW fb |
| &data->displayData); |
| |
| // update buffer indices |
| data->frontBufferIndex = data->backBufferIndex; |
| data->backBufferIndex = (data->backBufferIndex + 1) % VITA_GXM_BUFFERS; |
| data->pool_index = 0; |
| |
| data->current_pool = (data->current_pool + 1) % 2; |
| return 0; |
| } |
| |
| static void VITA_GXM_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture) |
| { |
| VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata; |
| VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->driverdata; |
| |
| if (!data) { |
| return; |
| } |
| |
| if (!vita_texture) { |
| return; |
| } |
| |
| if (!vita_texture->tex) { |
| return; |
| } |
| |
| sceGxmFinish(data->gxm_context); |
| |
| free_gxm_texture(data, vita_texture->tex); |
| |
| SDL_free(vita_texture); |
| |
| texture->driverdata = NULL; |
| } |
| |
| static void VITA_GXM_DestroyRenderer(SDL_Renderer *renderer) |
| { |
| VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata; |
| if (data) { |
| if (!data->initialized) { |
| return; |
| } |
| |
| gxm_finish(renderer); |
| |
| data->initialized = SDL_FALSE; |
| data->drawing = SDL_FALSE; |
| SDL_free(data); |
| } |
| } |
| |
| #endif /* SDL_VIDEO_RENDER_VITA_GXM */ |