diff options
Diffstat (limited to 'SDL-3.2.8/src/render/vitagxm')
13 files changed, 3230 insertions, 0 deletions
diff --git a/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm.c b/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm.c new file mode 100644 index 0000000..acf31c3 --- /dev/null +++ b/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm.c | |||
| @@ -0,0 +1,1198 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
| 4 | |||
| 5 | This software is provided 'as-is', without any express or implied | ||
| 6 | warranty. In no event will the authors be held liable for any damages | ||
| 7 | arising from the use of this software. | ||
| 8 | |||
| 9 | Permission is granted to anyone to use this software for any purpose, | ||
| 10 | including commercial applications, and to alter it and redistribute it | ||
| 11 | freely, subject to the following restrictions: | ||
| 12 | |||
| 13 | 1. The origin of this software must not be misrepresented; you must not | ||
| 14 | claim that you wrote the original software. If you use this software | ||
| 15 | in a product, an acknowledgment in the product documentation would be | ||
| 16 | appreciated but is not required. | ||
| 17 | 2. Altered source versions must be plainly marked as such, and must not be | ||
| 18 | misrepresented as being the original software. | ||
| 19 | 3. This notice may not be removed or altered from any source distribution. | ||
| 20 | */ | ||
| 21 | #include "SDL_internal.h" | ||
| 22 | |||
| 23 | #ifdef SDL_VIDEO_RENDER_VITA_GXM | ||
| 24 | |||
| 25 | #include "../SDL_sysrender.h" | ||
| 26 | |||
| 27 | #include <stdio.h> | ||
| 28 | #include <string.h> | ||
| 29 | #include <math.h> | ||
| 30 | #include <stdarg.h> | ||
| 31 | #include <stdlib.h> | ||
| 32 | |||
| 33 | #include "SDL_render_vita_gxm_types.h" | ||
| 34 | #include "SDL_render_vita_gxm_tools.h" | ||
| 35 | #include "SDL_render_vita_gxm_memory.h" | ||
| 36 | |||
| 37 | #include <psp2/common_dialog.h> | ||
| 38 | |||
| 39 | // #define DEBUG_RAZOR | ||
| 40 | |||
| 41 | #ifdef DEBUG_RAZOR | ||
| 42 | #include <psp2/sysmodule.h> | ||
| 43 | #endif | ||
| 44 | |||
| 45 | static bool VITA_GXM_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props); | ||
| 46 | |||
| 47 | static void VITA_GXM_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event); | ||
| 48 | |||
| 49 | static bool VITA_GXM_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode); | ||
| 50 | |||
| 51 | static bool VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props); | ||
| 52 | |||
| 53 | static bool VITA_GXM_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, | ||
| 54 | const SDL_Rect *rect, const void *pixels, int pitch); | ||
| 55 | |||
| 56 | static bool VITA_GXM_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture, | ||
| 57 | const SDL_Rect *rect, | ||
| 58 | const Uint8 *Yplane, int Ypitch, | ||
| 59 | const Uint8 *Uplane, int Upitch, | ||
| 60 | const Uint8 *Vplane, int Vpitch); | ||
| 61 | |||
| 62 | static bool VITA_GXM_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture, | ||
| 63 | const SDL_Rect *rect, | ||
| 64 | const Uint8 *Yplane, int Ypitch, | ||
| 65 | const Uint8 *UVplane, int UVpitch); | ||
| 66 | |||
| 67 | static bool VITA_GXM_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, | ||
| 68 | const SDL_Rect *rect, void **pixels, int *pitch); | ||
| 69 | |||
| 70 | static void VITA_GXM_UnlockTexture(SDL_Renderer *renderer, | ||
| 71 | SDL_Texture *texture); | ||
| 72 | |||
| 73 | static void VITA_GXM_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode); | ||
| 74 | |||
| 75 | static bool VITA_GXM_SetRenderTarget(SDL_Renderer *renderer, | ||
| 76 | SDL_Texture *texture); | ||
| 77 | |||
| 78 | static bool VITA_GXM_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd); | ||
| 79 | |||
| 80 | static bool VITA_GXM_QueueSetDrawColor(SDL_Renderer *renderer, SDL_RenderCommand *cmd); | ||
| 81 | |||
| 82 | static bool VITA_GXM_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count); | ||
| 83 | static bool VITA_GXM_QueueDrawLines(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count); | ||
| 84 | |||
| 85 | static bool VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, | ||
| 86 | const float *xy, int xy_stride, const SDL_FColor *color, int color_stride, const float *uv, int uv_stride, | ||
| 87 | int num_vertices, const void *indices, int num_indices, int size_indices, | ||
| 88 | float scale_x, float scale_y); | ||
| 89 | |||
| 90 | static bool VITA_GXM_RenderClear(SDL_Renderer *renderer, SDL_RenderCommand *cmd); | ||
| 91 | |||
| 92 | static void VITA_GXM_InvalidateCachedState(SDL_Renderer *renderer); | ||
| 93 | |||
| 94 | static bool VITA_GXM_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize); | ||
| 95 | |||
| 96 | static SDL_Surface *VITA_GXM_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect); | ||
| 97 | |||
| 98 | static bool VITA_GXM_RenderPresent(SDL_Renderer *renderer); | ||
| 99 | static void VITA_GXM_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture); | ||
| 100 | static void VITA_GXM_DestroyRenderer(SDL_Renderer *renderer); | ||
| 101 | |||
| 102 | SDL_RenderDriver VITA_GXM_RenderDriver = { | ||
| 103 | VITA_GXM_CreateRenderer, "VITA gxm" | ||
| 104 | }; | ||
| 105 | |||
| 106 | static int PixelFormatToVITAFMT(Uint32 format) | ||
| 107 | { | ||
| 108 | switch (format) { | ||
| 109 | case SDL_PIXELFORMAT_ARGB8888: | ||
| 110 | return SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ARGB; | ||
| 111 | case SDL_PIXELFORMAT_XRGB8888: | ||
| 112 | return SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ARGB; | ||
| 113 | case SDL_PIXELFORMAT_XBGR8888: | ||
| 114 | return SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ABGR; | ||
| 115 | case SDL_PIXELFORMAT_ABGR8888: | ||
| 116 | return SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ABGR; | ||
| 117 | case SDL_PIXELFORMAT_RGB565: | ||
| 118 | return SCE_GXM_TEXTURE_FORMAT_U5U6U5_RGB; | ||
| 119 | case SDL_PIXELFORMAT_BGR565: | ||
| 120 | return SCE_GXM_TEXTURE_FORMAT_U5U6U5_BGR; | ||
| 121 | case SDL_PIXELFORMAT_YV12: | ||
| 122 | return SCE_GXM_TEXTURE_FORMAT_YVU420P3_CSC0; | ||
| 123 | case SDL_PIXELFORMAT_IYUV: | ||
| 124 | return SCE_GXM_TEXTURE_FORMAT_YUV420P3_CSC0; | ||
| 125 | // should be the other way around. looks like SCE bug. | ||
| 126 | case SDL_PIXELFORMAT_NV12: | ||
| 127 | return SCE_GXM_TEXTURE_FORMAT_YVU420P2_CSC0; | ||
| 128 | case SDL_PIXELFORMAT_NV21: | ||
| 129 | return SCE_GXM_TEXTURE_FORMAT_YUV420P2_CSC0; | ||
| 130 | default: | ||
| 131 | return SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ABGR; | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | void StartDrawing(SDL_Renderer *renderer) | ||
| 136 | { | ||
| 137 | VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->internal; | ||
| 138 | if (data->drawing) { | ||
| 139 | return; | ||
| 140 | } | ||
| 141 | |||
| 142 | data->drawstate.texture = NULL; | ||
| 143 | data->drawstate.vertex_program = NULL; | ||
| 144 | data->drawstate.fragment_program = NULL; | ||
| 145 | data->drawstate.last_command = -1; | ||
| 146 | data->drawstate.viewport_dirty = true; | ||
| 147 | |||
| 148 | // reset blend mode | ||
| 149 | // data->currentBlendMode = SDL_BLENDMODE_BLEND; | ||
| 150 | // fragment_programs *in = &data->blendFragmentPrograms.blend_mode_blend; | ||
| 151 | // data->colorFragmentProgram = in->color; | ||
| 152 | // data->textureFragmentProgram = in->texture; | ||
| 153 | |||
| 154 | if (!renderer->target) { | ||
| 155 | sceGxmBeginScene( | ||
| 156 | data->gxm_context, | ||
| 157 | 0, | ||
| 158 | data->renderTarget, | ||
| 159 | NULL, | ||
| 160 | NULL, | ||
| 161 | data->displayBufferSync[data->backBufferIndex], | ||
| 162 | &data->displaySurface[data->backBufferIndex], | ||
| 163 | &data->depthSurface); | ||
| 164 | } else { | ||
| 165 | VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)renderer->target->internal; | ||
| 166 | |||
| 167 | sceGxmBeginScene( | ||
| 168 | data->gxm_context, | ||
| 169 | 0, | ||
| 170 | vita_texture->tex->gxm_rendertarget, | ||
| 171 | NULL, | ||
| 172 | NULL, | ||
| 173 | NULL, | ||
| 174 | &vita_texture->tex->gxm_colorsurface, | ||
| 175 | &vita_texture->tex->gxm_depthstencil); | ||
| 176 | } | ||
| 177 | |||
| 178 | // unset_clip_rectangle(data); | ||
| 179 | |||
| 180 | data->drawing = true; | ||
| 181 | } | ||
| 182 | |||
| 183 | static bool VITA_GXM_SetVSync(SDL_Renderer *renderer, const int vsync) | ||
| 184 | { | ||
| 185 | VITA_GXM_RenderData *data = renderer->internal; | ||
| 186 | if (vsync) { | ||
| 187 | data->displayData.wait_vblank = true; | ||
| 188 | } else { | ||
| 189 | data->displayData.wait_vblank = false; | ||
| 190 | } | ||
| 191 | return true; | ||
| 192 | } | ||
| 193 | |||
| 194 | static bool VITA_GXM_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props) | ||
| 195 | { | ||
| 196 | VITA_GXM_RenderData *data; | ||
| 197 | |||
| 198 | SDL_SetupRendererColorspace(renderer, create_props); | ||
| 199 | |||
| 200 | if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) { | ||
| 201 | return SDL_SetError("Unsupported output colorspace"); | ||
| 202 | } | ||
| 203 | |||
| 204 | data = (VITA_GXM_RenderData *)SDL_calloc(1, sizeof(VITA_GXM_RenderData)); | ||
| 205 | if (!data) { | ||
| 206 | return false; | ||
| 207 | } | ||
| 208 | |||
| 209 | renderer->WindowEvent = VITA_GXM_WindowEvent; | ||
| 210 | renderer->SupportsBlendMode = VITA_GXM_SupportsBlendMode; | ||
| 211 | renderer->CreateTexture = VITA_GXM_CreateTexture; | ||
| 212 | renderer->UpdateTexture = VITA_GXM_UpdateTexture; | ||
| 213 | #ifdef SDL_HAVE_YUV | ||
| 214 | renderer->UpdateTextureYUV = VITA_GXM_UpdateTextureYUV; | ||
| 215 | renderer->UpdateTextureNV = VITA_GXM_UpdateTextureNV; | ||
| 216 | #endif | ||
| 217 | renderer->LockTexture = VITA_GXM_LockTexture; | ||
| 218 | renderer->UnlockTexture = VITA_GXM_UnlockTexture; | ||
| 219 | renderer->SetTextureScaleMode = VITA_GXM_SetTextureScaleMode; | ||
| 220 | renderer->SetRenderTarget = VITA_GXM_SetRenderTarget; | ||
| 221 | renderer->QueueSetViewport = VITA_GXM_QueueNoOp; | ||
| 222 | renderer->QueueSetDrawColor = VITA_GXM_QueueSetDrawColor; | ||
| 223 | renderer->QueueDrawPoints = VITA_GXM_QueueDrawPoints; | ||
| 224 | renderer->QueueDrawLines = VITA_GXM_QueueDrawLines; | ||
| 225 | renderer->QueueGeometry = VITA_GXM_QueueGeometry; | ||
| 226 | renderer->InvalidateCachedState = VITA_GXM_InvalidateCachedState; | ||
| 227 | renderer->RunCommandQueue = VITA_GXM_RunCommandQueue; | ||
| 228 | renderer->RenderReadPixels = VITA_GXM_RenderReadPixels; | ||
| 229 | renderer->RenderPresent = VITA_GXM_RenderPresent; | ||
| 230 | renderer->DestroyTexture = VITA_GXM_DestroyTexture; | ||
| 231 | renderer->DestroyRenderer = VITA_GXM_DestroyRenderer; | ||
| 232 | renderer->SetVSync = VITA_GXM_SetVSync; | ||
| 233 | |||
| 234 | renderer->internal = data; | ||
| 235 | VITA_GXM_InvalidateCachedState(renderer); | ||
| 236 | renderer->window = window; | ||
| 237 | |||
| 238 | renderer->name = VITA_GXM_RenderDriver.name; | ||
| 239 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR8888); | ||
| 240 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888); | ||
| 241 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGB565); | ||
| 242 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGR565); | ||
| 243 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12); | ||
| 244 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV); | ||
| 245 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV12); | ||
| 246 | SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21); | ||
| 247 | SDL_SetNumberProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER, 4096); | ||
| 248 | |||
| 249 | data->initialized = true; | ||
| 250 | |||
| 251 | #ifdef DEBUG_RAZOR | ||
| 252 | sceSysmoduleLoadModule(SCE_SYSMODULE_RAZOR_HUD); | ||
| 253 | sceSysmoduleLoadModule(SCE_SYSMODULE_RAZOR_CAPTURE); | ||
| 254 | #endif | ||
| 255 | |||
| 256 | if (gxm_init(renderer) != 0) { | ||
| 257 | return SDL_SetError("gxm_init failed"); | ||
| 258 | } | ||
| 259 | |||
| 260 | return true; | ||
| 261 | } | ||
| 262 | |||
| 263 | static void VITA_GXM_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event) | ||
| 264 | { | ||
| 265 | } | ||
| 266 | |||
| 267 | static bool VITA_GXM_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode) | ||
| 268 | { | ||
| 269 | // only for custom modes. we build all modes on init, so no custom modes, sorry | ||
| 270 | return false; | ||
| 271 | } | ||
| 272 | |||
| 273 | static bool VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) | ||
| 274 | { | ||
| 275 | VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->internal; | ||
| 276 | VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)SDL_calloc(1, sizeof(VITA_GXM_TextureData)); | ||
| 277 | |||
| 278 | if (!vita_texture) { | ||
| 279 | return false; | ||
| 280 | } | ||
| 281 | |||
| 282 | vita_texture->tex = create_gxm_texture( | ||
| 283 | data, | ||
| 284 | texture->w, | ||
| 285 | texture->h, | ||
| 286 | PixelFormatToVITAFMT(texture->format), | ||
| 287 | (texture->access == SDL_TEXTUREACCESS_TARGET), | ||
| 288 | &(vita_texture->w), | ||
| 289 | &(vita_texture->h), | ||
| 290 | &(vita_texture->pitch), | ||
| 291 | &(vita_texture->wscale)); | ||
| 292 | |||
| 293 | if (!vita_texture->tex) { | ||
| 294 | SDL_free(vita_texture); | ||
| 295 | return SDL_OutOfMemory(); | ||
| 296 | } | ||
| 297 | |||
| 298 | texture->internal = vita_texture; | ||
| 299 | |||
| 300 | VITA_GXM_SetTextureScaleMode(renderer, texture, texture->scaleMode); | ||
| 301 | |||
| 302 | #ifdef SDL_HAVE_YUV | ||
| 303 | vita_texture->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12)); | ||
| 304 | vita_texture->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21)); | ||
| 305 | #endif | ||
| 306 | |||
| 307 | return true; | ||
| 308 | } | ||
| 309 | |||
| 310 | static void VITA_GXM_SetYUVProfile(SDL_Renderer *renderer, SDL_Texture *texture) | ||
| 311 | { | ||
| 312 | VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->internal; | ||
| 313 | int ret = 0; | ||
| 314 | if (SDL_ISCOLORSPACE_MATRIX_BT601(texture->colorspace)) { | ||
| 315 | if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) { | ||
| 316 | ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT601_STANDARD); | ||
| 317 | } else { | ||
| 318 | ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT601_FULL_RANGE); | ||
| 319 | } | ||
| 320 | } else if (SDL_ISCOLORSPACE_MATRIX_BT709(texture->colorspace)) { | ||
| 321 | if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) { | ||
| 322 | ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT709_STANDARD); | ||
| 323 | } else { | ||
| 324 | ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT709_FULL_RANGE); | ||
| 325 | } | ||
| 326 | } else { | ||
| 327 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Unsupported YUV colorspace"); | ||
| 328 | } | ||
| 329 | |||
| 330 | if (ret < 0) { | ||
| 331 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Setting YUV profile failed: %x", ret); | ||
| 332 | } | ||
| 333 | } | ||
| 334 | |||
| 335 | static bool VITA_GXM_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, | ||
| 336 | const SDL_Rect *rect, const void *pixels, int pitch) | ||
| 337 | { | ||
| 338 | VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->internal; | ||
| 339 | Uint8 *dst; | ||
| 340 | int row, length, dpitch; | ||
| 341 | |||
| 342 | #ifdef SDL_HAVE_YUV | ||
| 343 | if (vita_texture->yuv || vita_texture->nv12) { | ||
| 344 | VITA_GXM_SetYUVProfile(renderer, texture); | ||
| 345 | } | ||
| 346 | #endif | ||
| 347 | |||
| 348 | VITA_GXM_LockTexture(renderer, texture, rect, (void **)&dst, &dpitch); | ||
| 349 | length = rect->w * SDL_BYTESPERPIXEL(texture->format); | ||
| 350 | if (length == pitch && length == dpitch) { | ||
| 351 | SDL_memcpy(dst, pixels, length * rect->h); | ||
| 352 | pixels += pitch * rect->h; | ||
| 353 | } else { | ||
| 354 | for (row = 0; row < rect->h; ++row) { | ||
| 355 | SDL_memcpy(dst, pixels, length); | ||
| 356 | pixels += pitch; | ||
| 357 | dst += dpitch; | ||
| 358 | } | ||
| 359 | } | ||
| 360 | |||
| 361 | #ifdef SDL_HAVE_YUV | ||
| 362 | if (vita_texture->yuv) { | ||
| 363 | void *Udst; | ||
| 364 | void *Vdst; | ||
| 365 | int uv_pitch = (dpitch + 1) / 2; | ||
| 366 | int uv_src_pitch = (pitch + 1) / 2; | ||
| 367 | SDL_Rect UVrect = { rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2 }; | ||
| 368 | |||
| 369 | // skip Y plane | ||
| 370 | Uint8 *Dpixels = gxm_texture_get_datap(vita_texture->tex) + (vita_texture->pitch * vita_texture->h); | ||
| 371 | |||
| 372 | Udst = Dpixels + (UVrect.y * uv_pitch) + UVrect.x; | ||
| 373 | Vdst = Dpixels + (uv_pitch * ((vita_texture->h + 1) / 2)) + (UVrect.y * uv_pitch) + UVrect.x; | ||
| 374 | |||
| 375 | length = UVrect.w; | ||
| 376 | |||
| 377 | // U plane | ||
| 378 | if (length == uv_src_pitch && length == uv_pitch) { | ||
| 379 | SDL_memcpy(Udst, pixels, length * UVrect.h); | ||
| 380 | pixels += uv_src_pitch * UVrect.h; | ||
| 381 | } else { | ||
| 382 | for (row = 0; row < UVrect.h; ++row) { | ||
| 383 | SDL_memcpy(Udst, pixels, length); | ||
| 384 | pixels += uv_src_pitch; | ||
| 385 | Udst += uv_pitch; | ||
| 386 | } | ||
| 387 | } | ||
| 388 | |||
| 389 | // V plane | ||
| 390 | if (length == uv_src_pitch && length == uv_pitch) { | ||
| 391 | SDL_memcpy(Vdst, pixels, length * UVrect.h); | ||
| 392 | } else { | ||
| 393 | for (row = 0; row < UVrect.h; ++row) { | ||
| 394 | SDL_memcpy(Vdst, pixels, length); | ||
| 395 | pixels += uv_src_pitch; | ||
| 396 | Vdst += uv_pitch; | ||
| 397 | } | ||
| 398 | } | ||
| 399 | |||
| 400 | } else if (vita_texture->nv12) { | ||
| 401 | void *UVdst; | ||
| 402 | int uv_pitch = 2 * ((dpitch + 1) / 2); | ||
| 403 | int uv_src_pitch = 2 * ((pitch + 1) / 2); | ||
| 404 | SDL_Rect UVrect = { rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2 }; | ||
| 405 | |||
| 406 | // skip Y plane | ||
| 407 | void *Dpixels = (void *)((Uint8 *)gxm_texture_get_datap(vita_texture->tex) + (vita_texture->pitch * vita_texture->h)); | ||
| 408 | UVdst = Dpixels + (UVrect.y * uv_pitch) + UVrect.x; | ||
| 409 | |||
| 410 | length = UVrect.w * 2; | ||
| 411 | |||
| 412 | // UV plane | ||
| 413 | if (length == uv_src_pitch && length == uv_pitch) { | ||
| 414 | SDL_memcpy(UVdst, pixels, length * UVrect.h); | ||
| 415 | } else { | ||
| 416 | for (row = 0; row < UVrect.h; ++row) { | ||
| 417 | SDL_memcpy(UVdst, pixels, length); | ||
| 418 | pixels += uv_src_pitch; | ||
| 419 | UVdst += uv_pitch; | ||
| 420 | } | ||
| 421 | } | ||
| 422 | } | ||
| 423 | #endif | ||
| 424 | |||
| 425 | return true; | ||
| 426 | } | ||
| 427 | |||
| 428 | #ifdef SDL_HAVE_YUV | ||
| 429 | static bool VITA_GXM_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture, | ||
| 430 | const SDL_Rect *rect, | ||
| 431 | const Uint8 *Yplane, int Ypitch, | ||
| 432 | const Uint8 *Uplane, int Upitch, | ||
| 433 | const Uint8 *Vplane, int Vpitch) | ||
| 434 | { | ||
| 435 | Uint8 *dst; | ||
| 436 | int row, length, dpitch; | ||
| 437 | SDL_Rect UVrect = { rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2 }; | ||
| 438 | |||
| 439 | VITA_GXM_SetYUVProfile(renderer, texture); | ||
| 440 | |||
| 441 | // copy Y plane | ||
| 442 | // obtain pixels via locking so that texture is flushed | ||
| 443 | VITA_GXM_LockTexture(renderer, texture, rect, (void **)&dst, &dpitch); | ||
| 444 | |||
| 445 | length = rect->w; | ||
| 446 | |||
| 447 | if (length == Ypitch && length == dpitch) { | ||
| 448 | SDL_memcpy(dst, Yplane, length * rect->h); | ||
| 449 | } else { | ||
| 450 | for (row = 0; row < rect->h; ++row) { | ||
| 451 | SDL_memcpy(dst, Yplane, length); | ||
| 452 | Yplane += Ypitch; | ||
| 453 | dst += dpitch; | ||
| 454 | } | ||
| 455 | } | ||
| 456 | |||
| 457 | // U/V planes | ||
| 458 | { | ||
| 459 | void *Udst; | ||
| 460 | void *Vdst; | ||
| 461 | VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->internal; | ||
| 462 | int uv_pitch = (dpitch + 1) / 2; | ||
| 463 | |||
| 464 | // skip Y plane | ||
| 465 | void *pixels = (void *)((Uint8 *)gxm_texture_get_datap(vita_texture->tex) + (vita_texture->pitch * vita_texture->h)); | ||
| 466 | |||
| 467 | if (texture->format == SDL_PIXELFORMAT_YV12) { // YVU | ||
| 468 | Vdst = pixels + (UVrect.y * uv_pitch) + UVrect.x; | ||
| 469 | Udst = pixels + (uv_pitch * ((vita_texture->h + 1) / 2)) + (UVrect.y * uv_pitch) + UVrect.x; | ||
| 470 | } else { // YUV | ||
| 471 | Udst = pixels + (UVrect.y * uv_pitch) + UVrect.x; | ||
| 472 | Vdst = pixels + (uv_pitch * ((vita_texture->h + 1) / 2)) + (UVrect.y * uv_pitch) + UVrect.x; | ||
| 473 | } | ||
| 474 | |||
| 475 | length = UVrect.w; | ||
| 476 | |||
| 477 | // U plane | ||
| 478 | if (length == Upitch && length == uv_pitch) { | ||
| 479 | SDL_memcpy(Udst, Uplane, length * UVrect.h); | ||
| 480 | } else { | ||
| 481 | for (row = 0; row < UVrect.h; ++row) { | ||
| 482 | SDL_memcpy(Udst, Uplane, length); | ||
| 483 | Uplane += Upitch; | ||
| 484 | Udst += uv_pitch; | ||
| 485 | } | ||
| 486 | } | ||
| 487 | |||
| 488 | // V plane | ||
| 489 | if (length == Vpitch && length == uv_pitch) { | ||
| 490 | SDL_memcpy(Vdst, Vplane, length * UVrect.h); | ||
| 491 | } else { | ||
| 492 | for (row = 0; row < UVrect.h; ++row) { | ||
| 493 | SDL_memcpy(Vdst, Vplane, length); | ||
| 494 | Vplane += Vpitch; | ||
| 495 | Vdst += uv_pitch; | ||
| 496 | } | ||
| 497 | } | ||
| 498 | } | ||
| 499 | |||
| 500 | return true; | ||
| 501 | } | ||
| 502 | |||
| 503 | static bool VITA_GXM_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture, | ||
| 504 | const SDL_Rect *rect, | ||
| 505 | const Uint8 *Yplane, int Ypitch, | ||
| 506 | const Uint8 *UVplane, int UVpitch) | ||
| 507 | { | ||
| 508 | |||
| 509 | Uint8 *dst; | ||
| 510 | int row, length, dpitch; | ||
| 511 | SDL_Rect UVrect = { rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2 }; | ||
| 512 | |||
| 513 | VITA_GXM_SetYUVProfile(renderer, texture); | ||
| 514 | |||
| 515 | // copy Y plane | ||
| 516 | VITA_GXM_LockTexture(renderer, texture, rect, (void **)&dst, &dpitch); | ||
| 517 | |||
| 518 | length = rect->w * SDL_BYTESPERPIXEL(texture->format); | ||
| 519 | |||
| 520 | if (length == Ypitch && length == dpitch) { | ||
| 521 | SDL_memcpy(dst, Yplane, length * rect->h); | ||
| 522 | } else { | ||
| 523 | for (row = 0; row < rect->h; ++row) { | ||
| 524 | SDL_memcpy(dst, Yplane, length); | ||
| 525 | Yplane += Ypitch; | ||
| 526 | dst += dpitch; | ||
| 527 | } | ||
| 528 | } | ||
| 529 | |||
| 530 | // UV plane | ||
| 531 | { | ||
| 532 | void *UVdst; | ||
| 533 | VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->internal; | ||
| 534 | int uv_pitch = 2 * ((dpitch + 1) / 2); | ||
| 535 | |||
| 536 | // skip Y plane | ||
| 537 | void *pixels = (void *)((Uint8 *)gxm_texture_get_datap(vita_texture->tex) + (vita_texture->pitch * vita_texture->h)); | ||
| 538 | |||
| 539 | UVdst = pixels + (UVrect.y * uv_pitch) + UVrect.x; | ||
| 540 | |||
| 541 | length = UVrect.w * 2; | ||
| 542 | |||
| 543 | // UV plane | ||
| 544 | if (length == UVpitch && length == uv_pitch) { | ||
| 545 | SDL_memcpy(UVdst, UVplane, length * UVrect.h); | ||
| 546 | } else { | ||
| 547 | for (row = 0; row < UVrect.h; ++row) { | ||
| 548 | SDL_memcpy(UVdst, UVplane, length); | ||
| 549 | UVplane += UVpitch; | ||
| 550 | UVdst += uv_pitch; | ||
| 551 | } | ||
| 552 | } | ||
| 553 | } | ||
| 554 | |||
| 555 | return true; | ||
| 556 | } | ||
| 557 | |||
| 558 | #endif | ||
| 559 | |||
| 560 | static bool VITA_GXM_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, | ||
| 561 | const SDL_Rect *rect, void **pixels, int *pitch) | ||
| 562 | { | ||
| 563 | VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->internal; | ||
| 564 | VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->internal; | ||
| 565 | |||
| 566 | *pixels = | ||
| 567 | (void *)((Uint8 *)gxm_texture_get_datap(vita_texture->tex) + (rect->y * vita_texture->pitch) + rect->x * SDL_BYTESPERPIXEL(texture->format)); | ||
| 568 | *pitch = vita_texture->pitch; | ||
| 569 | |||
| 570 | // make sure that rendering is finished on render target textures | ||
| 571 | if (vita_texture->tex->gxm_rendertarget) { | ||
| 572 | sceGxmFinish(data->gxm_context); | ||
| 573 | } | ||
| 574 | |||
| 575 | return true; | ||
| 576 | } | ||
| 577 | |||
| 578 | static void VITA_GXM_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture) | ||
| 579 | { | ||
| 580 | // No need to update texture data on ps vita. | ||
| 581 | // VITA_GXM_LockTexture already returns a pointer to the texture pixels buffer. | ||
| 582 | // This really improves framerate when using lock/unlock. | ||
| 583 | } | ||
| 584 | |||
| 585 | static void VITA_GXM_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode) | ||
| 586 | { | ||
| 587 | VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->internal; | ||
| 588 | |||
| 589 | /* | ||
| 590 | set texture filtering according to scaleMode | ||
| 591 | supported hint values are nearest (0, default) or linear (1) | ||
| 592 | vitaScaleMode is either SCE_GXM_TEXTURE_FILTER_POINT (good for tile-map) | ||
| 593 | or SCE_GXM_TEXTURE_FILTER_LINEAR (good for scaling) | ||
| 594 | */ | ||
| 595 | |||
| 596 | int vitaScaleMode = (scaleMode == SDL_SCALEMODE_NEAREST | ||
| 597 | ? SCE_GXM_TEXTURE_FILTER_POINT | ||
| 598 | : SCE_GXM_TEXTURE_FILTER_LINEAR); | ||
| 599 | gxm_texture_set_filters(vita_texture->tex, vitaScaleMode, vitaScaleMode); | ||
| 600 | |||
| 601 | return; | ||
| 602 | } | ||
| 603 | |||
| 604 | static bool VITA_GXM_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) | ||
| 605 | { | ||
| 606 | return true; | ||
| 607 | } | ||
| 608 | |||
| 609 | static void VITA_GXM_SetBlendMode(VITA_GXM_RenderData *data, int blendMode) | ||
| 610 | { | ||
| 611 | if (blendMode != data->currentBlendMode) { | ||
| 612 | fragment_programs *in = &data->blendFragmentPrograms.blend_mode_blend; | ||
| 613 | |||
| 614 | switch (blendMode) { | ||
| 615 | case SDL_BLENDMODE_NONE: | ||
| 616 | in = &data->blendFragmentPrograms.blend_mode_none; | ||
| 617 | break; | ||
| 618 | case SDL_BLENDMODE_BLEND: | ||
| 619 | in = &data->blendFragmentPrograms.blend_mode_blend; | ||
| 620 | break; | ||
| 621 | case SDL_BLENDMODE_ADD: | ||
| 622 | in = &data->blendFragmentPrograms.blend_mode_add; | ||
| 623 | break; | ||
| 624 | case SDL_BLENDMODE_MOD: | ||
| 625 | in = &data->blendFragmentPrograms.blend_mode_mod; | ||
| 626 | break; | ||
| 627 | case SDL_BLENDMODE_MUL: | ||
| 628 | in = &data->blendFragmentPrograms.blend_mode_mul; | ||
| 629 | break; | ||
| 630 | } | ||
| 631 | data->colorFragmentProgram = in->color; | ||
| 632 | data->textureFragmentProgram = in->texture; | ||
| 633 | data->currentBlendMode = blendMode; | ||
| 634 | } | ||
| 635 | } | ||
| 636 | |||
| 637 | static bool VITA_GXM_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd) | ||
| 638 | { | ||
| 639 | return true; | ||
| 640 | } | ||
| 641 | |||
| 642 | static bool VITA_GXM_QueueSetDrawColor(SDL_Renderer *renderer, SDL_RenderCommand *cmd) | ||
| 643 | { | ||
| 644 | VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->internal; | ||
| 645 | |||
| 646 | data->drawstate.color.r = cmd->data.color.color.r * cmd->data.color.color_scale; | ||
| 647 | data->drawstate.color.g = cmd->data.color.color.g * cmd->data.color.color_scale; | ||
| 648 | data->drawstate.color.b = cmd->data.color.color.b * cmd->data.color.color_scale; | ||
| 649 | data->drawstate.color.a = cmd->data.color.color.a; | ||
| 650 | |||
| 651 | return true; | ||
| 652 | } | ||
| 653 | |||
| 654 | static bool VITA_GXM_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count) | ||
| 655 | { | ||
| 656 | VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->internal; | ||
| 657 | |||
| 658 | SDL_FColor color = data->drawstate.color; | ||
| 659 | |||
| 660 | color_vertex *vertex = (color_vertex *)pool_malloc( | ||
| 661 | data, | ||
| 662 | count * sizeof(color_vertex)); | ||
| 663 | |||
| 664 | cmd->data.draw.first = (size_t)vertex; | ||
| 665 | cmd->data.draw.count = count; | ||
| 666 | |||
| 667 | for (int i = 0; i < count; i++) { | ||
| 668 | vertex[i].x = points[i].x; | ||
| 669 | vertex[i].y = points[i].y; | ||
| 670 | vertex[i].color = color; | ||
| 671 | } | ||
| 672 | |||
| 673 | return true; | ||
| 674 | } | ||
| 675 | |||
| 676 | static bool VITA_GXM_QueueDrawLines(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count) | ||
| 677 | { | ||
| 678 | VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->internal; | ||
| 679 | SDL_FColor color = data->drawstate.color; | ||
| 680 | |||
| 681 | color_vertex *vertex = (color_vertex *)pool_malloc( | ||
| 682 | data, | ||
| 683 | (count - 1) * 2 * sizeof(color_vertex)); | ||
| 684 | |||
| 685 | cmd->data.draw.first = (size_t)vertex; | ||
| 686 | cmd->data.draw.count = (count - 1) * 2; | ||
| 687 | |||
| 688 | for (int i = 0; i < count - 1; i++) { | ||
| 689 | vertex[i * 2].x = points[i].x; | ||
| 690 | vertex[i * 2].y = points[i].y; | ||
| 691 | vertex[i * 2].color = color; | ||
| 692 | |||
| 693 | vertex[i * 2 + 1].x = points[i + 1].x; | ||
| 694 | vertex[i * 2 + 1].y = points[i + 1].y; | ||
| 695 | vertex[i * 2 + 1].color = color; | ||
| 696 | } | ||
| 697 | |||
| 698 | return true; | ||
| 699 | } | ||
| 700 | |||
| 701 | static bool VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, | ||
| 702 | const float *xy, int xy_stride, const SDL_FColor *color, int color_stride, const float *uv, int uv_stride, | ||
| 703 | int num_vertices, const void *indices, int num_indices, int size_indices, | ||
| 704 | float scale_x, float scale_y) | ||
| 705 | { | ||
| 706 | VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->internal; | ||
| 707 | int i; | ||
| 708 | int count = indices ? num_indices : num_vertices; | ||
| 709 | const float color_scale = cmd->data.draw.color_scale; | ||
| 710 | |||
| 711 | cmd->data.draw.count = count; | ||
| 712 | size_indices = indices ? size_indices : 0; | ||
| 713 | |||
| 714 | if (texture) { | ||
| 715 | VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->internal; | ||
| 716 | texture_vertex *vertices; | ||
| 717 | |||
| 718 | vertices = (texture_vertex *)pool_malloc( | ||
| 719 | data, | ||
| 720 | count * sizeof(texture_vertex)); | ||
| 721 | |||
| 722 | if (!vertices) { | ||
| 723 | return false; | ||
| 724 | } | ||
| 725 | |||
| 726 | for (i = 0; i < count; i++) { | ||
| 727 | int j; | ||
| 728 | float *xy_; | ||
| 729 | float *uv_; | ||
| 730 | SDL_FColor col_; | ||
| 731 | if (size_indices == 4) { | ||
| 732 | j = ((const Uint32 *)indices)[i]; | ||
| 733 | } else if (size_indices == 2) { | ||
| 734 | j = ((const Uint16 *)indices)[i]; | ||
| 735 | } else if (size_indices == 1) { | ||
| 736 | j = ((const Uint8 *)indices)[i]; | ||
| 737 | } else { | ||
| 738 | j = i; | ||
| 739 | } | ||
| 740 | |||
| 741 | xy_ = (float *)((char *)xy + j * xy_stride); | ||
| 742 | col_ = *(SDL_FColor *)((char *)color + j * color_stride); | ||
| 743 | uv_ = (float *)((char *)uv + j * uv_stride); | ||
| 744 | |||
| 745 | col_.r *= color_scale; | ||
| 746 | col_.g *= color_scale; | ||
| 747 | col_.b *= color_scale; | ||
| 748 | |||
| 749 | vertices[i].x = xy_[0] * scale_x; | ||
| 750 | vertices[i].y = xy_[1] * scale_y; | ||
| 751 | vertices[i].u = uv_[0] * vita_texture->wscale; | ||
| 752 | vertices[i].v = uv_[1]; | ||
| 753 | vertices[i].color = col_; | ||
| 754 | } | ||
| 755 | |||
| 756 | cmd->data.draw.first = (size_t)vertices; | ||
| 757 | |||
| 758 | } else { | ||
| 759 | color_vertex *vertices; | ||
| 760 | |||
| 761 | vertices = (color_vertex *)pool_malloc( | ||
| 762 | data, | ||
| 763 | count * sizeof(color_vertex)); | ||
| 764 | |||
| 765 | if (!vertices) { | ||
| 766 | return false; | ||
| 767 | } | ||
| 768 | |||
| 769 | for (i = 0; i < count; i++) { | ||
| 770 | int j; | ||
| 771 | float *xy_; | ||
| 772 | SDL_FColor col_; | ||
| 773 | if (size_indices == 4) { | ||
| 774 | j = ((const Uint32 *)indices)[i]; | ||
| 775 | } else if (size_indices == 2) { | ||
| 776 | j = ((const Uint16 *)indices)[i]; | ||
| 777 | } else if (size_indices == 1) { | ||
| 778 | j = ((const Uint8 *)indices)[i]; | ||
| 779 | } else { | ||
| 780 | j = i; | ||
| 781 | } | ||
| 782 | |||
| 783 | xy_ = (float *)((char *)xy + j * xy_stride); | ||
| 784 | col_ = *(SDL_FColor *)((char *)color + j * color_stride); | ||
| 785 | |||
| 786 | col_.r *= color_scale; | ||
| 787 | col_.g *= color_scale; | ||
| 788 | col_.b *= color_scale; | ||
| 789 | |||
| 790 | vertices[i].x = xy_[0] * scale_x; | ||
| 791 | vertices[i].y = xy_[1] * scale_y; | ||
| 792 | vertices[i].color = col_; | ||
| 793 | } | ||
| 794 | cmd->data.draw.first = (size_t)vertices; | ||
| 795 | } | ||
| 796 | |||
| 797 | return true; | ||
| 798 | } | ||
| 799 | |||
| 800 | static bool VITA_GXM_RenderClear(SDL_Renderer *renderer, SDL_RenderCommand *cmd) | ||
| 801 | { | ||
| 802 | void *color_buffer; | ||
| 803 | SDL_FColor color; | ||
| 804 | |||
| 805 | VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->internal; | ||
| 806 | unset_clip_rectangle(data); | ||
| 807 | |||
| 808 | // set clear shaders | ||
| 809 | data->drawstate.fragment_program = data->clearFragmentProgram; | ||
| 810 | data->drawstate.vertex_program = data->clearVertexProgram; | ||
| 811 | sceGxmSetVertexProgram(data->gxm_context, data->clearVertexProgram); | ||
| 812 | sceGxmSetFragmentProgram(data->gxm_context, data->clearFragmentProgram); | ||
| 813 | |||
| 814 | // set the clear color | ||
| 815 | color = cmd->data.color.color; | ||
| 816 | color.r *= cmd->data.color.color_scale; | ||
| 817 | color.g *= cmd->data.color.color_scale; | ||
| 818 | color.b *= cmd->data.color.color_scale; | ||
| 819 | sceGxmReserveFragmentDefaultUniformBuffer(data->gxm_context, &color_buffer); | ||
| 820 | sceGxmSetUniformDataF(color_buffer, data->clearClearColorParam, 0, 4, &color.r); | ||
| 821 | |||
| 822 | // draw the clear triangle | ||
| 823 | sceGxmSetVertexStream(data->gxm_context, 0, data->clearVertices); | ||
| 824 | sceGxmDraw(data->gxm_context, SCE_GXM_PRIMITIVE_TRIANGLES, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, 3); | ||
| 825 | |||
| 826 | data->drawstate.cliprect_dirty = true; | ||
| 827 | return true; | ||
| 828 | } | ||
| 829 | |||
| 830 | static bool SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd) | ||
| 831 | { | ||
| 832 | SDL_Texture *texture = cmd->data.draw.texture; | ||
| 833 | const SDL_BlendMode blend = cmd->data.draw.blend; | ||
| 834 | SceGxmFragmentProgram *fragment_program; | ||
| 835 | SceGxmVertexProgram *vertex_program; | ||
| 836 | bool matrix_updated = false; | ||
| 837 | bool program_updated = false; | ||
| 838 | |||
| 839 | if (data->drawstate.viewport_dirty) { | ||
| 840 | const SDL_Rect *viewport = &data->drawstate.viewport; | ||
| 841 | |||
| 842 | float sw = viewport->w / 2.f; | ||
| 843 | float sh = viewport->h / 2.f; | ||
| 844 | |||
| 845 | float x_scale = sw; | ||
| 846 | float x_off = viewport->x + sw; | ||
| 847 | float y_scale = -(sh); | ||
| 848 | float y_off = viewport->y + sh; | ||
| 849 | |||
| 850 | sceGxmSetViewport(data->gxm_context, x_off, x_scale, y_off, y_scale, 0.5f, 0.5f); | ||
| 851 | |||
| 852 | if (viewport->w && viewport->h) { | ||
| 853 | init_orthographic_matrix(data->ortho_matrix, | ||
| 854 | (float)0, | ||
| 855 | (float)viewport->w, | ||
| 856 | (float)viewport->h, | ||
| 857 | (float)0, | ||
| 858 | 0.0f, 1.0f); | ||
| 859 | matrix_updated = true; | ||
| 860 | } | ||
| 861 | |||
| 862 | data->drawstate.viewport_dirty = false; | ||
| 863 | } | ||
| 864 | |||
| 865 | if (data->drawstate.cliprect_enabled_dirty) { | ||
| 866 | if (!data->drawstate.cliprect_enabled) { | ||
| 867 | unset_clip_rectangle(data); | ||
| 868 | } | ||
| 869 | data->drawstate.cliprect_enabled_dirty = false; | ||
| 870 | } | ||
| 871 | |||
| 872 | if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) { | ||
| 873 | const SDL_Rect *rect = &data->drawstate.cliprect; | ||
| 874 | set_clip_rectangle(data, rect->x, rect->y, rect->x + rect->w, rect->y + rect->h); | ||
| 875 | data->drawstate.cliprect_dirty = false; | ||
| 876 | } | ||
| 877 | |||
| 878 | VITA_GXM_SetBlendMode(data, blend); // do that first, to select appropriate shaders | ||
| 879 | |||
| 880 | if (texture) { | ||
| 881 | vertex_program = data->textureVertexProgram; | ||
| 882 | fragment_program = data->textureFragmentProgram; | ||
| 883 | } else { | ||
| 884 | vertex_program = data->colorVertexProgram; | ||
| 885 | fragment_program = data->colorFragmentProgram; | ||
| 886 | } | ||
| 887 | |||
| 888 | if (data->drawstate.vertex_program != vertex_program) { | ||
| 889 | data->drawstate.vertex_program = vertex_program; | ||
| 890 | sceGxmSetVertexProgram(data->gxm_context, vertex_program); | ||
| 891 | program_updated = true; | ||
| 892 | } | ||
| 893 | |||
| 894 | if (data->drawstate.fragment_program != fragment_program) { | ||
| 895 | data->drawstate.fragment_program = fragment_program; | ||
| 896 | sceGxmSetFragmentProgram(data->gxm_context, fragment_program); | ||
| 897 | program_updated = true; | ||
| 898 | } | ||
| 899 | |||
| 900 | if (program_updated || matrix_updated) { | ||
| 901 | if (data->drawstate.fragment_program == data->textureFragmentProgram) { | ||
| 902 | void *vertex_wvp_buffer; | ||
| 903 | sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertex_wvp_buffer); | ||
| 904 | sceGxmSetUniformDataF(vertex_wvp_buffer, data->textureWvpParam, 0, 16, data->ortho_matrix); | ||
| 905 | } else { // color | ||
| 906 | void *vertexDefaultBuffer; | ||
| 907 | sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertexDefaultBuffer); | ||
| 908 | sceGxmSetUniformDataF(vertexDefaultBuffer, data->colorWvpParam, 0, 16, data->ortho_matrix); | ||
| 909 | } | ||
| 910 | } | ||
| 911 | |||
| 912 | if (texture != data->drawstate.texture) { | ||
| 913 | if (texture) { | ||
| 914 | VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)cmd->data.draw.texture->internal; | ||
| 915 | sceGxmSetFragmentTexture(data->gxm_context, 0, &vita_texture->tex->gxm_tex); | ||
| 916 | } | ||
| 917 | data->drawstate.texture = texture; | ||
| 918 | } | ||
| 919 | |||
| 920 | // all drawing commands use this | ||
| 921 | sceGxmSetVertexStream(data->gxm_context, 0, (const void *)cmd->data.draw.first); | ||
| 922 | |||
| 923 | return true; | ||
| 924 | } | ||
| 925 | |||
| 926 | static void VITA_GXM_InvalidateCachedState(SDL_Renderer *renderer) | ||
| 927 | { | ||
| 928 | // currently this doesn't do anything. If this needs to do something (and someone is mixing their own rendering calls in!), update this. | ||
| 929 | } | ||
| 930 | |||
| 931 | static bool VITA_GXM_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) | ||
| 932 | { | ||
| 933 | VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->internal; | ||
| 934 | StartDrawing(renderer); | ||
| 935 | |||
| 936 | data->drawstate.target = renderer->target; | ||
| 937 | if (!data->drawstate.target) { | ||
| 938 | int w, h; | ||
| 939 | SDL_GetWindowSizeInPixels(renderer->window, &w, &h); | ||
| 940 | if ((w != data->drawstate.drawablew) || (h != data->drawstate.drawableh)) { | ||
| 941 | data->drawstate.viewport_dirty = true; // if the window dimensions changed, invalidate the current viewport, etc. | ||
| 942 | data->drawstate.cliprect_dirty = true; | ||
| 943 | data->drawstate.drawablew = w; | ||
| 944 | data->drawstate.drawableh = h; | ||
| 945 | } | ||
| 946 | } | ||
| 947 | |||
| 948 | while (cmd) { | ||
| 949 | switch (cmd->command) { | ||
| 950 | |||
| 951 | case SDL_RENDERCMD_SETVIEWPORT: | ||
| 952 | { | ||
| 953 | SDL_Rect *viewport = &data->drawstate.viewport; | ||
| 954 | if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof(cmd->data.viewport.rect)) != 0) { | ||
| 955 | SDL_copyp(viewport, &cmd->data.viewport.rect); | ||
| 956 | data->drawstate.viewport_dirty = true; | ||
| 957 | data->drawstate.cliprect_dirty = true; | ||
| 958 | } | ||
| 959 | break; | ||
| 960 | } | ||
| 961 | |||
| 962 | case SDL_RENDERCMD_SETCLIPRECT: | ||
| 963 | { | ||
| 964 | const SDL_Rect *rect = &cmd->data.cliprect.rect; | ||
| 965 | if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) { | ||
| 966 | data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled; | ||
| 967 | data->drawstate.cliprect_enabled_dirty = true; | ||
| 968 | } | ||
| 969 | |||
| 970 | if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof(*rect)) != 0) { | ||
| 971 | SDL_copyp(&data->drawstate.cliprect, rect); | ||
| 972 | data->drawstate.cliprect_dirty = true; | ||
| 973 | } | ||
| 974 | break; | ||
| 975 | } | ||
| 976 | |||
| 977 | case SDL_RENDERCMD_SETDRAWCOLOR: | ||
| 978 | { | ||
| 979 | break; | ||
| 980 | } | ||
| 981 | |||
| 982 | case SDL_RENDERCMD_CLEAR: | ||
| 983 | { | ||
| 984 | VITA_GXM_RenderClear(renderer, cmd); | ||
| 985 | break; | ||
| 986 | } | ||
| 987 | |||
| 988 | case SDL_RENDERCMD_FILL_RECTS: // unused | ||
| 989 | break; | ||
| 990 | |||
| 991 | case SDL_RENDERCMD_COPY: // unused | ||
| 992 | break; | ||
| 993 | |||
| 994 | case SDL_RENDERCMD_COPY_EX: // unused | ||
| 995 | break; | ||
| 996 | |||
| 997 | case SDL_RENDERCMD_DRAW_POINTS: | ||
| 998 | case SDL_RENDERCMD_DRAW_LINES: | ||
| 999 | case SDL_RENDERCMD_GEOMETRY: | ||
| 1000 | { | ||
| 1001 | SDL_Texture *thistexture = cmd->data.draw.texture; | ||
| 1002 | SDL_BlendMode thisblend = cmd->data.draw.blend; | ||
| 1003 | const SDL_RenderCommandType thiscmdtype = cmd->command; | ||
| 1004 | SDL_RenderCommand *finalcmd = cmd; | ||
| 1005 | SDL_RenderCommand *nextcmd = cmd->next; | ||
| 1006 | size_t count = cmd->data.draw.count; | ||
| 1007 | int ret; | ||
| 1008 | while (nextcmd) { | ||
| 1009 | const SDL_RenderCommandType nextcmdtype = nextcmd->command; | ||
| 1010 | if (nextcmdtype != thiscmdtype) { | ||
| 1011 | break; // can't go any further on this draw call, different render command up next. | ||
| 1012 | } else if (nextcmd->data.draw.texture != thistexture || nextcmd->data.draw.blend != thisblend) { | ||
| 1013 | break; // can't go any further on this draw call, different texture/blendmode copy up next. | ||
| 1014 | } else { | ||
| 1015 | finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command. | ||
| 1016 | count += nextcmd->data.draw.count; | ||
| 1017 | } | ||
| 1018 | nextcmd = nextcmd->next; | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | ret = SetDrawState(data, cmd); | ||
| 1022 | |||
| 1023 | if (ret) { | ||
| 1024 | int op = SCE_GXM_PRIMITIVE_TRIANGLES; | ||
| 1025 | |||
| 1026 | if (thiscmdtype == SDL_RENDERCMD_DRAW_POINTS) { | ||
| 1027 | sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_POINT); | ||
| 1028 | op = SCE_GXM_PRIMITIVE_POINTS; | ||
| 1029 | } else if (thiscmdtype == SDL_RENDERCMD_DRAW_LINES) { | ||
| 1030 | sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_LINE); | ||
| 1031 | op = SCE_GXM_PRIMITIVE_LINES; | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | sceGxmDraw(data->gxm_context, op, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, count); | ||
| 1035 | |||
| 1036 | if (thiscmdtype == SDL_RENDERCMD_DRAW_POINTS || thiscmdtype == SDL_RENDERCMD_DRAW_LINES) { | ||
| 1037 | sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_TRIANGLE_FILL); | ||
| 1038 | } | ||
| 1039 | } | ||
| 1040 | |||
| 1041 | cmd = finalcmd; // skip any copy commands we just combined in here. | ||
| 1042 | break; | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | case SDL_RENDERCMD_NO_OP: | ||
| 1046 | break; | ||
| 1047 | } | ||
| 1048 | data->drawstate.last_command = cmd->command; | ||
| 1049 | cmd = cmd->next; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | sceGxmEndScene(data->gxm_context, NULL, NULL); | ||
| 1053 | data->drawing = false; | ||
| 1054 | |||
| 1055 | return true; | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | void read_pixels(int x, int y, size_t width, size_t height, void *data) | ||
| 1059 | { | ||
| 1060 | SceDisplayFrameBuf pParam; | ||
| 1061 | int i, j; | ||
| 1062 | Uint32 *out32; | ||
| 1063 | Uint32 *in32; | ||
| 1064 | |||
| 1065 | pParam.size = sizeof(SceDisplayFrameBuf); | ||
| 1066 | |||
| 1067 | sceDisplayGetFrameBuf(&pParam, SCE_DISPLAY_SETBUF_NEXTFRAME); | ||
| 1068 | |||
| 1069 | out32 = (Uint32 *)data; | ||
| 1070 | in32 = (Uint32 *)pParam.base; | ||
| 1071 | |||
| 1072 | in32 += (x + y * pParam.pitch); | ||
| 1073 | |||
| 1074 | for (i = 0; i < height; i++) { | ||
| 1075 | for (j = 0; j < width; j++) { | ||
| 1076 | out32[(height - (i + 1)) * width + j] = in32[j]; | ||
| 1077 | } | ||
| 1078 | in32 += pParam.pitch; | ||
| 1079 | } | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | static SDL_Surface *VITA_GXM_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect) | ||
| 1083 | { | ||
| 1084 | Uint32 format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888; | ||
| 1085 | SDL_Surface *surface; | ||
| 1086 | |||
| 1087 | // TODO: read from texture rendertarget. | ||
| 1088 | if (renderer->target) { | ||
| 1089 | SDL_Unsupported(); | ||
| 1090 | return NULL; | ||
| 1091 | } | ||
| 1092 | |||
| 1093 | surface = SDL_CreateSurface(rect->w, rect->h, format); | ||
| 1094 | if (!surface) { | ||
| 1095 | return NULL; | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | int y = rect->y; | ||
| 1099 | if (!renderer->target) { | ||
| 1100 | int w, h; | ||
| 1101 | SDL_GetRenderOutputSize(renderer, &w, &h); | ||
| 1102 | y = (h - y) - rect->h; | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | read_pixels(rect->x, y, rect->w, rect->h, surface->pixels); | ||
| 1106 | |||
| 1107 | // Flip the rows to be top-down if necessary | ||
| 1108 | if (!renderer->target) { | ||
| 1109 | SDL_FlipSurface(surface, SDL_FLIP_VERTICAL); | ||
| 1110 | } | ||
| 1111 | return surface; | ||
| 1112 | } | ||
| 1113 | |||
| 1114 | static bool VITA_GXM_RenderPresent(SDL_Renderer *renderer) | ||
| 1115 | { | ||
| 1116 | VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->internal; | ||
| 1117 | SceCommonDialogUpdateParam updateParam; | ||
| 1118 | |||
| 1119 | data->displayData.address = data->displayBufferData[data->backBufferIndex]; | ||
| 1120 | |||
| 1121 | SDL_memset(&updateParam, 0, sizeof(updateParam)); | ||
| 1122 | |||
| 1123 | updateParam.renderTarget.colorFormat = VITA_GXM_COLOR_FORMAT; | ||
| 1124 | updateParam.renderTarget.surfaceType = SCE_GXM_COLOR_SURFACE_LINEAR; | ||
| 1125 | updateParam.renderTarget.width = VITA_GXM_SCREEN_WIDTH; | ||
| 1126 | updateParam.renderTarget.height = VITA_GXM_SCREEN_HEIGHT; | ||
| 1127 | updateParam.renderTarget.strideInPixels = VITA_GXM_SCREEN_STRIDE; | ||
| 1128 | |||
| 1129 | updateParam.renderTarget.colorSurfaceData = data->displayBufferData[data->backBufferIndex]; | ||
| 1130 | updateParam.renderTarget.depthSurfaceData = data->depthBufferData; | ||
| 1131 | |||
| 1132 | updateParam.displaySyncObject = (SceGxmSyncObject *)data->displayBufferSync[data->backBufferIndex]; | ||
| 1133 | |||
| 1134 | sceCommonDialogUpdate(&updateParam); | ||
| 1135 | |||
| 1136 | #ifdef DEBUG_RAZOR | ||
| 1137 | sceGxmPadHeartbeat( | ||
| 1138 | (const SceGxmColorSurface *)&data->displaySurface[data->backBufferIndex], | ||
| 1139 | (SceGxmSyncObject *)data->displayBufferSync[data->backBufferIndex]); | ||
| 1140 | #endif | ||
| 1141 | |||
| 1142 | sceGxmDisplayQueueAddEntry( | ||
| 1143 | data->displayBufferSync[data->frontBufferIndex], // OLD fb | ||
| 1144 | data->displayBufferSync[data->backBufferIndex], // NEW fb | ||
| 1145 | &data->displayData); | ||
| 1146 | |||
| 1147 | // update buffer indices | ||
| 1148 | data->frontBufferIndex = data->backBufferIndex; | ||
| 1149 | data->backBufferIndex = (data->backBufferIndex + 1) % VITA_GXM_BUFFERS; | ||
| 1150 | data->pool_index = 0; | ||
| 1151 | |||
| 1152 | data->current_pool = (data->current_pool + 1) % 2; | ||
| 1153 | return true; | ||
| 1154 | } | ||
| 1155 | |||
| 1156 | static void VITA_GXM_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture) | ||
| 1157 | { | ||
| 1158 | VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->internal; | ||
| 1159 | VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->internal; | ||
| 1160 | |||
| 1161 | if (!data) { | ||
| 1162 | return; | ||
| 1163 | } | ||
| 1164 | |||
| 1165 | if (!vita_texture) { | ||
| 1166 | return; | ||
| 1167 | } | ||
| 1168 | |||
| 1169 | if (!vita_texture->tex) { | ||
| 1170 | return; | ||
| 1171 | } | ||
| 1172 | |||
| 1173 | sceGxmFinish(data->gxm_context); | ||
| 1174 | |||
| 1175 | free_gxm_texture(data, vita_texture->tex); | ||
| 1176 | |||
| 1177 | SDL_free(vita_texture); | ||
| 1178 | |||
| 1179 | texture->internal = NULL; | ||
| 1180 | } | ||
| 1181 | |||
| 1182 | static void VITA_GXM_DestroyRenderer(SDL_Renderer *renderer) | ||
| 1183 | { | ||
| 1184 | VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->internal; | ||
| 1185 | if (data) { | ||
| 1186 | if (!data->initialized) { | ||
| 1187 | return; | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | gxm_finish(renderer); | ||
| 1191 | |||
| 1192 | data->initialized = false; | ||
| 1193 | data->drawing = false; | ||
| 1194 | SDL_free(data); | ||
| 1195 | } | ||
| 1196 | } | ||
| 1197 | |||
| 1198 | #endif // SDL_VIDEO_RENDER_VITA_GXM | ||
diff --git a/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_memory.c b/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_memory.c new file mode 100644 index 0000000..e37a345 --- /dev/null +++ b/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_memory.c | |||
| @@ -0,0 +1,179 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
| 4 | |||
| 5 | This software is provided 'as-is', without any express or implied | ||
| 6 | warranty. In no event will the authors be held liable for any damages | ||
| 7 | arising from the use of this software. | ||
| 8 | |||
| 9 | Permission is granted to anyone to use this software for any purpose, | ||
| 10 | including commercial applications, and to alter it and redistribute it | ||
| 11 | freely, subject to the following restrictions: | ||
| 12 | |||
| 13 | 1. The origin of this software must not be misrepresented; you must not | ||
| 14 | claim that you wrote the original software. If you use this software | ||
| 15 | in a product, an acknowledgment in the product documentation would be | ||
| 16 | appreciated but is not required. | ||
| 17 | 2. Altered source versions must be plainly marked as such, and must not be | ||
| 18 | misrepresented as being the original software. | ||
| 19 | 3. This notice may not be removed or altered from any source distribution. | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include "SDL_internal.h" | ||
| 23 | |||
| 24 | #ifdef SDL_VIDEO_RENDER_VITA_GXM | ||
| 25 | |||
| 26 | #include "SDL_render_vita_gxm_memory.h" | ||
| 27 | |||
| 28 | void *vita_mem_alloc(unsigned int type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid) | ||
| 29 | { | ||
| 30 | void *mem; | ||
| 31 | |||
| 32 | if (type == SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW) { | ||
| 33 | size = ALIGN(size, 256 * 1024); | ||
| 34 | } else if (type == SCE_KERNEL_MEMBLOCK_TYPE_USER_MAIN_PHYCONT_NC_RW) { | ||
| 35 | size = ALIGN(size, 1024 * 1024); | ||
| 36 | } else { | ||
| 37 | size = ALIGN(size, 4 * 1024); | ||
| 38 | } | ||
| 39 | |||
| 40 | *uid = sceKernelAllocMemBlock("gpu_mem", type, size, NULL); | ||
| 41 | |||
| 42 | if (*uid < 0) { | ||
| 43 | return NULL; | ||
| 44 | } | ||
| 45 | |||
| 46 | if (sceKernelGetMemBlockBase(*uid, &mem) < 0) { | ||
| 47 | return NULL; | ||
| 48 | } | ||
| 49 | |||
| 50 | if (sceGxmMapMemory(mem, size, attribs) < 0) { | ||
| 51 | return NULL; | ||
| 52 | } | ||
| 53 | |||
| 54 | return mem; | ||
| 55 | } | ||
| 56 | |||
| 57 | void vita_mem_free(SceUID uid) | ||
| 58 | { | ||
| 59 | void *mem = NULL; | ||
| 60 | if (sceKernelGetMemBlockBase(uid, &mem) < 0) { | ||
| 61 | return; | ||
| 62 | } | ||
| 63 | sceGxmUnmapMemory(mem); | ||
| 64 | sceKernelFreeMemBlock(uid); | ||
| 65 | } | ||
| 66 | |||
| 67 | void *vita_gpu_mem_alloc(VITA_GXM_RenderData *data, unsigned int size) | ||
| 68 | { | ||
| 69 | void *mem; | ||
| 70 | |||
| 71 | if (!data->texturePool) { | ||
| 72 | int poolsize; | ||
| 73 | int ret; | ||
| 74 | SceKernelFreeMemorySizeInfo info; | ||
| 75 | info.size = sizeof(SceKernelFreeMemorySizeInfo); | ||
| 76 | sceKernelGetFreeMemorySize(&info); | ||
| 77 | |||
| 78 | poolsize = ALIGN(info.size_cdram, 256 * 1024); | ||
| 79 | if (poolsize > info.size_cdram) { | ||
| 80 | poolsize = ALIGN(info.size_cdram - 256 * 1024, 256 * 1024); | ||
| 81 | } | ||
| 82 | data->texturePoolUID = sceKernelAllocMemBlock("gpu_texture_pool", SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, poolsize, NULL); | ||
| 83 | if (data->texturePoolUID < 0) { | ||
| 84 | return NULL; | ||
| 85 | } | ||
| 86 | |||
| 87 | ret = sceKernelGetMemBlockBase(data->texturePoolUID, &mem); | ||
| 88 | if (ret < 0) { | ||
| 89 | return NULL; | ||
| 90 | } | ||
| 91 | data->texturePool = sceClibMspaceCreate(mem, poolsize); | ||
| 92 | |||
| 93 | if (!data->texturePool) { | ||
| 94 | return NULL; | ||
| 95 | } | ||
| 96 | ret = sceGxmMapMemory(mem, poolsize, SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE); | ||
| 97 | if (ret < 0) { | ||
| 98 | return NULL; | ||
| 99 | } | ||
| 100 | } | ||
| 101 | return sceClibMspaceMemalign(data->texturePool, SCE_GXM_TEXTURE_ALIGNMENT, size); | ||
| 102 | } | ||
| 103 | |||
| 104 | void vita_gpu_mem_free(VITA_GXM_RenderData *data, void *ptr) | ||
| 105 | { | ||
| 106 | if (data->texturePool) { | ||
| 107 | sceClibMspaceFree(data->texturePool, ptr); | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | void vita_gpu_mem_destroy(VITA_GXM_RenderData *data) | ||
| 112 | { | ||
| 113 | void *mem = NULL; | ||
| 114 | if (data->texturePool) { | ||
| 115 | sceClibMspaceDestroy(data->texturePool); | ||
| 116 | data->texturePool = NULL; | ||
| 117 | if (sceKernelGetMemBlockBase(data->texturePoolUID, &mem) < 0) { | ||
| 118 | return; | ||
| 119 | } | ||
| 120 | sceGxmUnmapMemory(mem); | ||
| 121 | sceKernelFreeMemBlock(data->texturePoolUID); | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | void *vita_mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset) | ||
| 126 | { | ||
| 127 | void *mem = NULL; | ||
| 128 | |||
| 129 | size = ALIGN(size, 4096); | ||
| 130 | *uid = sceKernelAllocMemBlock("vertex_usse", SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, size, NULL); | ||
| 131 | |||
| 132 | if (sceKernelGetMemBlockBase(*uid, &mem) < 0) { | ||
| 133 | return NULL; | ||
| 134 | } | ||
| 135 | if (sceGxmMapVertexUsseMemory(mem, size, usse_offset) < 0) { | ||
| 136 | return NULL; | ||
| 137 | } | ||
| 138 | |||
| 139 | return mem; | ||
| 140 | } | ||
| 141 | |||
| 142 | void vita_mem_vertex_usse_free(SceUID uid) | ||
| 143 | { | ||
| 144 | void *mem = NULL; | ||
| 145 | if (sceKernelGetMemBlockBase(uid, &mem) < 0) { | ||
| 146 | return; | ||
| 147 | } | ||
| 148 | sceGxmUnmapVertexUsseMemory(mem); | ||
| 149 | sceKernelFreeMemBlock(uid); | ||
| 150 | } | ||
| 151 | |||
| 152 | void *vita_mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset) | ||
| 153 | { | ||
| 154 | void *mem = NULL; | ||
| 155 | |||
| 156 | size = ALIGN(size, 4096); | ||
| 157 | *uid = sceKernelAllocMemBlock("fragment_usse", SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, size, NULL); | ||
| 158 | |||
| 159 | if (sceKernelGetMemBlockBase(*uid, &mem) < 0) { | ||
| 160 | return NULL; | ||
| 161 | } | ||
| 162 | if (sceGxmMapFragmentUsseMemory(mem, size, usse_offset) < 0) { | ||
| 163 | return NULL; | ||
| 164 | } | ||
| 165 | |||
| 166 | return mem; | ||
| 167 | } | ||
| 168 | |||
| 169 | void vita_mem_fragment_usse_free(SceUID uid) | ||
| 170 | { | ||
| 171 | void *mem = NULL; | ||
| 172 | if (sceKernelGetMemBlockBase(uid, &mem) < 0) { | ||
| 173 | return; | ||
| 174 | } | ||
| 175 | sceGxmUnmapFragmentUsseMemory(mem); | ||
| 176 | sceKernelFreeMemBlock(uid); | ||
| 177 | } | ||
| 178 | |||
| 179 | #endif // SDL_VIDEO_RENDER_VITA_GXM | ||
diff --git a/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_memory.h b/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_memory.h new file mode 100644 index 0000000..cc548b3 --- /dev/null +++ b/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_memory.h | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
| 4 | |||
| 5 | This software is provided 'as-is', without any express or implied | ||
| 6 | warranty. In no event will the authors be held liable for any damages | ||
| 7 | arising from the use of this software. | ||
| 8 | |||
| 9 | Permission is granted to anyone to use this software for any purpose, | ||
| 10 | including commercial applications, and to alter it and redistribute it | ||
| 11 | freely, subject to the following restrictions: | ||
| 12 | |||
| 13 | 1. The origin of this software must not be misrepresented; you must not | ||
| 14 | claim that you wrote the original software. If you use this software | ||
| 15 | in a product, an acknowledgment in the product documentation would be | ||
| 16 | appreciated but is not required. | ||
| 17 | 2. Altered source versions must be plainly marked as such, and must not be | ||
| 18 | misrepresented as being the original software. | ||
| 19 | 3. This notice may not be removed or altered from any source distribution. | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifndef SDL_RENDER_VITA_GXM_MEMORY_H | ||
| 23 | #define SDL_RENDER_VITA_GXM_MEMORY_H | ||
| 24 | |||
| 25 | #include <psp2/gxm.h> | ||
| 26 | #include <psp2/types.h> | ||
| 27 | #include <psp2/kernel/sysmem.h> | ||
| 28 | #include "SDL_render_vita_gxm_types.h" | ||
| 29 | |||
| 30 | #define ALIGN(x, a) (((x) + ((a)-1)) & ~((a)-1)) | ||
| 31 | |||
| 32 | void *vita_mem_alloc(unsigned int type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid); | ||
| 33 | void vita_mem_free(SceUID uid); | ||
| 34 | void *vita_gpu_mem_alloc(VITA_GXM_RenderData *data, unsigned int size); | ||
| 35 | void vita_gpu_mem_free(VITA_GXM_RenderData *data, void *ptr); | ||
| 36 | void vita_gpu_mem_destroy(VITA_GXM_RenderData *data); | ||
| 37 | void *vita_mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset); | ||
| 38 | void vita_mem_vertex_usse_free(SceUID uid); | ||
| 39 | void *vita_mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset); | ||
| 40 | void vita_mem_fragment_usse_free(SceUID uid); | ||
| 41 | |||
| 42 | #endif // SDL_RENDER_VITA_GXM_MEMORY_H | ||
diff --git a/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_shaders.h b/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_shaders.h new file mode 100644 index 0000000..ef80e03 --- /dev/null +++ b/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_shaders.h | |||
| @@ -0,0 +1,282 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
| 4 | |||
| 5 | This software is provided 'as-is', without any express or implied | ||
| 6 | warranty. In no event will the authors be held liable for any damages | ||
| 7 | arising from the use of this software. | ||
| 8 | |||
| 9 | Permission is granted to anyone to use this software for any purpose, | ||
| 10 | including commercial applications, and to alter it and redistribute it | ||
| 11 | freely, subject to the following restrictions: | ||
| 12 | |||
| 13 | 1. The origin of this software must not be misrepresented; you must not | ||
| 14 | claim that you wrote the original software. If you use this software | ||
| 15 | in a product, an acknowledgment in the product documentation would be | ||
| 16 | appreciated but is not required. | ||
| 17 | 2. Altered source versions must be plainly marked as such, and must not be | ||
| 18 | misrepresented as being the original software. | ||
| 19 | 3. This notice may not be removed or altered from any source distribution. | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifndef SDL_RENDER_VITA_GXM_SHADERS_H | ||
| 23 | #define SDL_RENDER_VITA_GXM_SHADERS_H | ||
| 24 | |||
| 25 | #include <psp2/gxm.h> | ||
| 26 | |||
| 27 | /* *INDENT-OFF* */ /* clang-format off */ | ||
| 28 | |||
| 29 | #define gxm_shader_clear_f_size 232 | ||
| 30 | static const unsigned char gxm_shader_clear_f[gxm_shader_clear_f_size] = { | ||
| 31 | 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, | ||
| 32 | 0xe8, 0x00, 0x00, 0x00, 0xa2, 0x55, 0x22, 0x3e, | ||
| 33 | 0xc6, 0x7e, 0x77, 0xf1, 0x01, 0x00, 0x18, 0x00, | ||
| 34 | 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, | ||
| 35 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, | ||
| 36 | 0xa4, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, | ||
| 37 | 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 38 | 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, | ||
| 39 | 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 40 | 0x68, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, | ||
| 41 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 42 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 43 | 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, | ||
| 44 | 0x5c, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, | ||
| 45 | 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, | ||
| 46 | 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, | ||
| 47 | 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, | ||
| 48 | 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, | ||
| 49 | 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, | ||
| 50 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 51 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, | ||
| 52 | 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, | ||
| 53 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 54 | 0x00, 0x07, 0x44, 0xfa, 0x02, 0x80, 0x19, 0xf0, | ||
| 55 | 0x7e, 0x0d, 0x80, 0x40, 0x0e, 0x00, 0x00, 0x00, | ||
| 56 | 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, | ||
| 57 | 0x01, 0xe4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, | ||
| 58 | 0x00, 0x00, 0x00, 0x00, 0x75, 0x43, 0x6c, 0x65, | ||
| 59 | 0x61, 0x72, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, | ||
| 60 | }; | ||
| 61 | |||
| 62 | #define gxm_shader_clear_v_size 252 | ||
| 63 | static const unsigned char gxm_shader_clear_v[gxm_shader_clear_v_size] = { | ||
| 64 | 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, | ||
| 65 | 0xfa, 0x00, 0x00, 0x00, 0xdc, 0x25, 0x34, 0x74, | ||
| 66 | 0x53, 0x4a, 0x7a, 0x5b, 0x04, 0x00, 0x19, 0x00, | ||
| 67 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 68 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, | ||
| 69 | 0xb8, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, | ||
| 70 | 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 71 | 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, | ||
| 72 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 73 | 0x74, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, | ||
| 74 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 75 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 76 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 77 | 0x78, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, | ||
| 78 | 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, | ||
| 79 | 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, | ||
| 80 | 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, | ||
| 81 | 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, | ||
| 82 | 0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, | ||
| 83 | 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, | ||
| 84 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 85 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, | ||
| 86 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 87 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 88 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa, | ||
| 89 | 0x01, 0x00, 0x04, 0x90, 0x85, 0x11, 0xa5, 0x08, | ||
| 90 | 0x01, 0x80, 0x56, 0x90, 0x81, 0x11, 0x83, 0x08, | ||
| 91 | 0x00, 0x00, 0x20, 0xa0, 0x00, 0x50, 0x27, 0xfb, | ||
| 92 | 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, | ||
| 93 | 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 94 | 0x61, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, | ||
| 95 | 0x6e, 0x00, 0x00, 0x00, | ||
| 96 | }; | ||
| 97 | |||
| 98 | #define gxm_shader_color_f_size 212 | ||
| 99 | static const unsigned char gxm_shader_color_f[gxm_shader_color_f_size] = { | ||
| 100 | 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, | ||
| 101 | 0xd4, 0x00, 0x00, 0x00, 0x9c, 0xd6, 0x9b, 0xf7, | ||
| 102 | 0x78, 0x00, 0x5d, 0x31, 0x01, 0x10, 0x18, 0x00, | ||
| 103 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 104 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 105 | 0xac, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, | ||
| 106 | 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 107 | 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, | ||
| 108 | 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 109 | 0x78, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, | ||
| 110 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 111 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 112 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 113 | 0x6c, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, | ||
| 114 | 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, | ||
| 115 | 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, | ||
| 116 | 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, | ||
| 117 | 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, | ||
| 118 | 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, | ||
| 119 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 120 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, | ||
| 121 | 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, | ||
| 122 | 0x0f, 0xa0, 0xd0, 0x0e, 0x00, 0x00, 0x00, 0x00, | ||
| 123 | 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 124 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 125 | 0x00, 0x07, 0x44, 0xfa, 0x02, 0x80, 0x19, 0xa0, | ||
| 126 | 0x7e, 0x0d, 0x80, 0x40, | ||
| 127 | }; | ||
| 128 | |||
| 129 | #define gxm_shader_color_v_size 368 | ||
| 130 | static const unsigned char gxm_shader_color_v[gxm_shader_color_v_size] = { | ||
| 131 | 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, | ||
| 132 | 0x6d, 0x01, 0x00, 0x00, 0x09, 0xce, 0x4e, 0xc2, | ||
| 133 | 0xe1, 0xcd, 0x24, 0xbc, 0x00, 0x00, 0x19, 0x00, | ||
| 134 | 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, | ||
| 135 | 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, | ||
| 136 | 0x00, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, | ||
| 137 | 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 138 | 0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00, | ||
| 139 | 0x98, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, | ||
| 140 | 0x74, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, | ||
| 141 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 142 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 143 | 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, | ||
| 144 | 0xb8, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, | ||
| 145 | 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, | ||
| 146 | 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, | ||
| 147 | 0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, | ||
| 148 | 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, | ||
| 149 | 0x01, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, | ||
| 150 | 0x00, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x00, 0x00, | ||
| 151 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 152 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, | ||
| 153 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 154 | 0x00, 0x00, 0x00, 0x00, 0x06, 0x43, 0x00, 0x61, | ||
| 155 | 0x86, 0x81, 0xa2, 0x00, 0x07, 0x53, 0x40, 0x61, | ||
| 156 | 0x86, 0x81, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 157 | 0x40, 0x01, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, | ||
| 158 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa, | ||
| 159 | 0x80, 0x00, 0x08, 0x83, 0x21, 0x1d, 0x80, 0x38, | ||
| 160 | 0x00, 0x00, 0xf0, 0x83, 0x20, 0x0d, 0x80, 0x38, | ||
| 161 | 0x0a, 0x84, 0xb9, 0xff, 0xbc, 0x0d, 0xc0, 0x40, | ||
| 162 | 0x02, 0x11, 0x45, 0xcf, 0x80, 0x8f, 0xb1, 0x18, | ||
| 163 | 0x00, 0x11, 0x01, 0xc0, 0x81, 0x81, 0xb1, 0x18, | ||
| 164 | 0x01, 0xd1, 0x42, 0xc0, 0x81, 0x81, 0xb1, 0x18, | ||
| 165 | 0x40, 0x00, 0x10, 0x41, 0x09, 0x05, 0x82, 0x38, | ||
| 166 | 0x00, 0x00, 0x20, 0xa0, 0x00, 0x50, 0x27, 0xfb, | ||
| 167 | 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, | ||
| 168 | 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, | ||
| 169 | 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 170 | 0x2a, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, | ||
| 171 | 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, | ||
| 172 | 0x21, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, | ||
| 173 | 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 174 | 0x61, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, | ||
| 175 | 0x6e, 0x00, 0x61, 0x43, 0x6f, 0x6c, 0x6f, 0x72, | ||
| 176 | 0x00, 0x77, 0x76, 0x70, 0x00, 0x00, 0x00, 0x00, | ||
| 177 | }; | ||
| 178 | |||
| 179 | #define gxm_shader_texture_f_size 288 | ||
| 180 | static const unsigned char gxm_shader_texture_f[gxm_shader_texture_f_size] = { | ||
| 181 | 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, | ||
| 182 | 0x20, 0x01, 0x00, 0x00, 0xeb, 0x4f, 0xb5, 0xba, | ||
| 183 | 0x60, 0xb2, 0xd0, 0x8d, 0x05, 0x18, 0x18, 0x00, | ||
| 184 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, | ||
| 185 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, | ||
| 186 | 0xc4, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, | ||
| 187 | 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 188 | 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, | ||
| 189 | 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 190 | 0x78, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, | ||
| 191 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 192 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 193 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 194 | 0x84, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, | ||
| 195 | 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, | ||
| 196 | 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, | ||
| 197 | 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, | ||
| 198 | 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, | ||
| 199 | 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, | ||
| 200 | 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 201 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, | ||
| 202 | 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, | ||
| 203 | 0x00, 0xa9, 0xd0, 0x0e, 0x00, 0x00, 0x00, 0x00, | ||
| 204 | 0xf0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, | ||
| 205 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 206 | 0x00, 0x07, 0x44, 0xfa, 0x00, 0x00, 0x00, 0x00, | ||
| 207 | 0x40, 0x09, 0x00, 0xf8, 0x02, 0x80, 0x99, 0xaf, | ||
| 208 | 0xbc, 0x0d, 0xc0, 0x40, 0x06, 0x82, 0xb9, 0xaf, | ||
| 209 | 0xbc, 0x0d, 0x80, 0x40, 0x7c, 0x0f, 0x04, 0x00, | ||
| 210 | 0x86, 0x47, 0xa4, 0x10, 0x30, 0x00, 0x00, 0x00, | ||
| 211 | 0x02, 0x04, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, | ||
| 212 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, | ||
| 213 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 214 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 215 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 216 | 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x00, | ||
| 217 | }; | ||
| 218 | |||
| 219 | #define gxm_shader_texture_v_size 400 | ||
| 220 | static const unsigned char gxm_shader_texture_v[gxm_shader_texture_v_size] = { | ||
| 221 | 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, | ||
| 222 | 0x8f, 0x01, 0x00, 0x00, 0x60, 0x1e, 0x69, 0x97, | ||
| 223 | 0x82, 0x7e, 0x0c, 0xac, 0x00, 0x00, 0x19, 0x00, | ||
| 224 | 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, | ||
| 225 | 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, | ||
| 226 | 0x08, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, | ||
| 227 | 0x0c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 228 | 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00, | ||
| 229 | 0x98, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, | ||
| 230 | 0x74, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, | ||
| 231 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 232 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 233 | 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, | ||
| 234 | 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, | ||
| 235 | 0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, | ||
| 236 | 0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, | ||
| 237 | 0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, | ||
| 238 | 0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, | ||
| 239 | 0x01, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, | ||
| 240 | 0x00, 0x00, 0x00, 0x00, 0x33, 0x0f, 0x00, 0x00, | ||
| 241 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 242 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x0a, | ||
| 243 | 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 244 | 0x00, 0x00, 0x00, 0x00, 0x06, 0x43, 0x00, 0x61, | ||
| 245 | 0x86, 0x81, 0xa2, 0x00, 0x07, 0x53, 0x40, 0x61, | ||
| 246 | 0x86, 0x81, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 247 | 0x40, 0x01, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, | ||
| 248 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa, | ||
| 249 | 0x01, 0x0e, 0x01, 0x01, 0x02, 0x00, 0x10, 0xfa, | ||
| 250 | 0x80, 0x00, 0x08, 0x83, 0x21, 0x25, 0x80, 0x38, | ||
| 251 | 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x14, 0xfa, | ||
| 252 | 0x00, 0x00, 0xf0, 0x83, 0x20, 0x0d, 0x80, 0x38, | ||
| 253 | 0x0a, 0x84, 0xb9, 0xff, 0xbc, 0x0d, 0xc0, 0x40, | ||
| 254 | 0x02, 0x11, 0x45, 0xcf, 0x80, 0x8f, 0xb1, 0x18, | ||
| 255 | 0x00, 0x11, 0x01, 0xc0, 0x81, 0x81, 0xb1, 0x18, | ||
| 256 | 0x01, 0xd1, 0x42, 0xc0, 0x81, 0x81, 0xb1, 0x18, | ||
| 257 | 0x00, 0x00, 0x20, 0xa0, 0x00, 0x50, 0x27, 0xfb, | ||
| 258 | 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, | ||
| 259 | 0x40, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, | ||
| 260 | 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 261 | 0x3a, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, | ||
| 262 | 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, | ||
| 263 | 0x34, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, | ||
| 264 | 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, | ||
| 265 | 0x2b, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, | ||
| 266 | 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 267 | 0x61, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, | ||
| 268 | 0x6e, 0x00, 0x61, 0x54, 0x65, 0x78, 0x63, 0x6f, | ||
| 269 | 0x6f, 0x72, 0x64, 0x00, 0x61, 0x43, 0x6f, 0x6c, | ||
| 270 | 0x6f, 0x72, 0x00, 0x77, 0x76, 0x70, 0x00, 0x00, | ||
| 271 | }; | ||
| 272 | |||
| 273 | /* *INDENT-ON* */ /* clang-format on */ | ||
| 274 | |||
| 275 | static const SceGxmProgram *const clearVertexProgramGxp = (const SceGxmProgram *)gxm_shader_clear_v; | ||
| 276 | static const SceGxmProgram *const clearFragmentProgramGxp = (const SceGxmProgram *)gxm_shader_clear_f; | ||
| 277 | static const SceGxmProgram *const colorVertexProgramGxp = (const SceGxmProgram *)gxm_shader_color_v; | ||
| 278 | static const SceGxmProgram *const colorFragmentProgramGxp = (const SceGxmProgram *)gxm_shader_color_f; | ||
| 279 | static const SceGxmProgram *const textureVertexProgramGxp = (const SceGxmProgram *)gxm_shader_texture_v; | ||
| 280 | static const SceGxmProgram *const textureFragmentProgramGxp = (const SceGxmProgram *)gxm_shader_texture_f; | ||
| 281 | |||
| 282 | #endif // SDL_RENDER_VITA_GXM_SHADERS_H | ||
diff --git a/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_tools.c b/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_tools.c new file mode 100644 index 0000000..9140a62 --- /dev/null +++ b/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_tools.c | |||
| @@ -0,0 +1,1213 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
| 4 | |||
| 5 | This software is provided 'as-is', without any express or implied | ||
| 6 | warranty. In no event will the authors be held liable for any damages | ||
| 7 | arising from the use of this software. | ||
| 8 | |||
| 9 | Permission is granted to anyone to use this software for any purpose, | ||
| 10 | including commercial applications, and to alter it and redistribute it | ||
| 11 | freely, subject to the following restrictions: | ||
| 12 | |||
| 13 | 1. The origin of this software must not be misrepresented; you must not | ||
| 14 | claim that you wrote the original software. If you use this software | ||
| 15 | in a product, an acknowledgment in the product documentation would be | ||
| 16 | appreciated but is not required. | ||
| 17 | 2. Altered source versions must be plainly marked as such, and must not be | ||
| 18 | misrepresented as being the original software. | ||
| 19 | 3. This notice may not be removed or altered from any source distribution. | ||
| 20 | */ | ||
| 21 | #include "SDL_internal.h" | ||
| 22 | |||
| 23 | #ifdef SDL_VIDEO_RENDER_VITA_GXM | ||
| 24 | |||
| 25 | #include "../SDL_sysrender.h" | ||
| 26 | |||
| 27 | #include <psp2/kernel/processmgr.h> | ||
| 28 | #include <psp2/appmgr.h> | ||
| 29 | #include <psp2/display.h> | ||
| 30 | #include <psp2/gxm.h> | ||
| 31 | #include <psp2/types.h> | ||
| 32 | #include <psp2/kernel/sysmem.h> | ||
| 33 | #include <psp2/message_dialog.h> | ||
| 34 | |||
| 35 | #include <stdio.h> | ||
| 36 | #include <string.h> | ||
| 37 | #include <math.h> | ||
| 38 | #include <stdarg.h> | ||
| 39 | #include <stdlib.h> | ||
| 40 | |||
| 41 | #include "SDL_render_vita_gxm_tools.h" | ||
| 42 | #include "SDL_render_vita_gxm_types.h" | ||
| 43 | #include "SDL_render_vita_gxm_memory.h" | ||
| 44 | #include "SDL_render_vita_gxm_shaders.h" | ||
| 45 | |||
| 46 | void init_orthographic_matrix(float *m, float left, float right, float bottom, float top, float near, float far) | ||
| 47 | { | ||
| 48 | m[0x0] = 2.0f / (right - left); | ||
| 49 | m[0x4] = 0.0f; | ||
| 50 | m[0x8] = 0.0f; | ||
| 51 | m[0xC] = -(right + left) / (right - left); | ||
| 52 | |||
| 53 | m[0x1] = 0.0f; | ||
| 54 | m[0x5] = 2.0f / (top - bottom); | ||
| 55 | m[0x9] = 0.0f; | ||
| 56 | m[0xD] = -(top + bottom) / (top - bottom); | ||
| 57 | |||
| 58 | m[0x2] = 0.0f; | ||
| 59 | m[0x6] = 0.0f; | ||
| 60 | m[0xA] = -2.0f / (far - near); | ||
| 61 | m[0xE] = (far + near) / (far - near); | ||
| 62 | |||
| 63 | m[0x3] = 0.0f; | ||
| 64 | m[0x7] = 0.0f; | ||
| 65 | m[0xB] = 0.0f; | ||
| 66 | m[0xF] = 1.0f; | ||
| 67 | } | ||
| 68 | |||
| 69 | static void *patcher_host_alloc(void *user_data, unsigned int size) | ||
| 70 | { | ||
| 71 | void *mem = SDL_malloc(size); | ||
| 72 | (void)user_data; | ||
| 73 | return mem; | ||
| 74 | } | ||
| 75 | |||
| 76 | static void patcher_host_free(void *user_data, void *mem) | ||
| 77 | { | ||
| 78 | (void)user_data; | ||
| 79 | SDL_free(mem); | ||
| 80 | } | ||
| 81 | |||
| 82 | void *pool_malloc(VITA_GXM_RenderData *data, unsigned int size) | ||
| 83 | { | ||
| 84 | |||
| 85 | if ((data->pool_index + size) < VITA_GXM_POOL_SIZE) { | ||
| 86 | void *addr = (void *)((unsigned int)data->pool_addr[data->current_pool] + data->pool_index); | ||
| 87 | data->pool_index += size; | ||
| 88 | return addr; | ||
| 89 | } | ||
| 90 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "POOL OVERFLOW"); | ||
| 91 | return NULL; | ||
| 92 | } | ||
| 93 | |||
| 94 | void *pool_memalign(VITA_GXM_RenderData *data, unsigned int size, unsigned int alignment) | ||
| 95 | { | ||
| 96 | unsigned int new_index = (data->pool_index + alignment - 1) & ~(alignment - 1); | ||
| 97 | if ((new_index + size) < VITA_GXM_POOL_SIZE) { | ||
| 98 | void *addr = (void *)((unsigned int)data->pool_addr[data->current_pool] + new_index); | ||
| 99 | data->pool_index = new_index + size; | ||
| 100 | return addr; | ||
| 101 | } | ||
| 102 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "POOL OVERFLOW"); | ||
| 103 | return NULL; | ||
| 104 | } | ||
| 105 | |||
| 106 | static int tex_format_to_bytespp(SceGxmTextureFormat format) | ||
| 107 | { | ||
| 108 | switch (format & 0x9f000000U) { | ||
| 109 | case SCE_GXM_TEXTURE_BASE_FORMAT_U8: | ||
| 110 | case SCE_GXM_TEXTURE_BASE_FORMAT_S8: | ||
| 111 | case SCE_GXM_TEXTURE_BASE_FORMAT_P8: | ||
| 112 | case SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P2: // YUV actually uses 12 bits per pixel. UV planes bits/mem are handled elsewhere | ||
| 113 | case SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P3: | ||
| 114 | return 1; | ||
| 115 | case SCE_GXM_TEXTURE_BASE_FORMAT_U4U4U4U4: | ||
| 116 | case SCE_GXM_TEXTURE_BASE_FORMAT_U8U3U3U2: | ||
| 117 | case SCE_GXM_TEXTURE_BASE_FORMAT_U1U5U5U5: | ||
| 118 | case SCE_GXM_TEXTURE_BASE_FORMAT_U5U6U5: | ||
| 119 | case SCE_GXM_TEXTURE_BASE_FORMAT_S5S5U6: | ||
| 120 | case SCE_GXM_TEXTURE_BASE_FORMAT_U8U8: | ||
| 121 | case SCE_GXM_TEXTURE_BASE_FORMAT_S8S8: | ||
| 122 | return 2; | ||
| 123 | case SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8: | ||
| 124 | case SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8: | ||
| 125 | return 3; | ||
| 126 | case SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8U8: | ||
| 127 | case SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8S8: | ||
| 128 | case SCE_GXM_TEXTURE_BASE_FORMAT_F32: | ||
| 129 | case SCE_GXM_TEXTURE_BASE_FORMAT_U32: | ||
| 130 | case SCE_GXM_TEXTURE_BASE_FORMAT_S32: | ||
| 131 | default: | ||
| 132 | return 4; | ||
| 133 | } | ||
| 134 | } | ||
| 135 | |||
| 136 | static void display_callback(const void *callback_data) | ||
| 137 | { | ||
| 138 | SceDisplayFrameBuf framebuf; | ||
| 139 | const VITA_GXM_DisplayData *display_data = (const VITA_GXM_DisplayData *)callback_data; | ||
| 140 | |||
| 141 | SDL_memset(&framebuf, 0x00, sizeof(SceDisplayFrameBuf)); | ||
| 142 | framebuf.size = sizeof(SceDisplayFrameBuf); | ||
| 143 | framebuf.base = display_data->address; | ||
| 144 | framebuf.pitch = VITA_GXM_SCREEN_STRIDE; | ||
| 145 | framebuf.pixelformat = VITA_GXM_PIXEL_FORMAT; | ||
| 146 | framebuf.width = VITA_GXM_SCREEN_WIDTH; | ||
| 147 | framebuf.height = VITA_GXM_SCREEN_HEIGHT; | ||
| 148 | sceDisplaySetFrameBuf(&framebuf, SCE_DISPLAY_SETBUF_NEXTFRAME); | ||
| 149 | |||
| 150 | if (display_data->wait_vblank) { | ||
| 151 | sceDisplayWaitVblankStart(); | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | static void free_fragment_programs(VITA_GXM_RenderData *data, fragment_programs *out) | ||
| 156 | { | ||
| 157 | sceGxmShaderPatcherReleaseFragmentProgram(data->shaderPatcher, out->color); | ||
| 158 | sceGxmShaderPatcherReleaseFragmentProgram(data->shaderPatcher, out->texture); | ||
| 159 | } | ||
| 160 | |||
| 161 | static void make_fragment_programs(VITA_GXM_RenderData *data, fragment_programs *out, | ||
| 162 | const SceGxmBlendInfo *blend_info) | ||
| 163 | { | ||
| 164 | int err; | ||
| 165 | |||
| 166 | err = sceGxmShaderPatcherCreateFragmentProgram( | ||
| 167 | data->shaderPatcher, | ||
| 168 | data->colorFragmentProgramId, | ||
| 169 | SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, | ||
| 170 | 0, | ||
| 171 | blend_info, | ||
| 172 | colorVertexProgramGxp, | ||
| 173 | &out->color); | ||
| 174 | |||
| 175 | if (err != 0) { | ||
| 176 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Patcher create fragment failed: %d", err); | ||
| 177 | return; | ||
| 178 | } | ||
| 179 | |||
| 180 | err = sceGxmShaderPatcherCreateFragmentProgram( | ||
| 181 | data->shaderPatcher, | ||
| 182 | data->textureFragmentProgramId, | ||
| 183 | SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, | ||
| 184 | 0, | ||
| 185 | blend_info, | ||
| 186 | textureVertexProgramGxp, | ||
| 187 | &out->texture); | ||
| 188 | |||
| 189 | if (err != 0) { | ||
| 190 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Patcher create fragment failed: %d", err); | ||
| 191 | return; | ||
| 192 | } | ||
| 193 | } | ||
| 194 | |||
| 195 | static void set_stencil_mask(VITA_GXM_RenderData *data, float x, float y, float w, float h) | ||
| 196 | { | ||
| 197 | void *vertexDefaultBuffer; | ||
| 198 | color_vertex *vertices = (color_vertex *)pool_memalign( | ||
| 199 | data, | ||
| 200 | 4 * sizeof(color_vertex), // 4 vertices | ||
| 201 | sizeof(color_vertex)); | ||
| 202 | |||
| 203 | vertices[0].x = x; | ||
| 204 | vertices[0].y = y; | ||
| 205 | vertices[0].color.r = 0; | ||
| 206 | vertices[0].color.g = 0; | ||
| 207 | vertices[0].color.b = 0; | ||
| 208 | vertices[0].color.a = 0; | ||
| 209 | |||
| 210 | vertices[1].x = x + w; | ||
| 211 | vertices[1].y = y; | ||
| 212 | vertices[1].color.r = 0; | ||
| 213 | vertices[1].color.g = 0; | ||
| 214 | vertices[1].color.b = 0; | ||
| 215 | vertices[1].color.a = 0; | ||
| 216 | |||
| 217 | vertices[2].x = x; | ||
| 218 | vertices[2].y = y + h; | ||
| 219 | vertices[2].color.r = 0; | ||
| 220 | vertices[2].color.g = 0; | ||
| 221 | vertices[2].color.b = 0; | ||
| 222 | vertices[2].color.a = 0; | ||
| 223 | |||
| 224 | vertices[3].x = x + w; | ||
| 225 | vertices[3].y = y + h; | ||
| 226 | vertices[3].color.r = 0; | ||
| 227 | vertices[3].color.g = 0; | ||
| 228 | vertices[3].color.b = 0; | ||
| 229 | vertices[3].color.a = 0; | ||
| 230 | |||
| 231 | data->drawstate.fragment_program = data->colorFragmentProgram; | ||
| 232 | data->drawstate.vertex_program = data->colorVertexProgram; | ||
| 233 | sceGxmSetVertexProgram(data->gxm_context, data->colorVertexProgram); | ||
| 234 | sceGxmSetFragmentProgram(data->gxm_context, data->colorFragmentProgram); | ||
| 235 | |||
| 236 | sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertexDefaultBuffer); | ||
| 237 | sceGxmSetUniformDataF(vertexDefaultBuffer, data->colorWvpParam, 0, 16, data->ortho_matrix); | ||
| 238 | |||
| 239 | sceGxmSetVertexStream(data->gxm_context, 0, vertices); | ||
| 240 | sceGxmDraw(data->gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, 4); | ||
| 241 | } | ||
| 242 | |||
| 243 | void set_clip_rectangle(VITA_GXM_RenderData *data, int x_min, int y_min, int x_max, int y_max) | ||
| 244 | { | ||
| 245 | if (data->drawing) { | ||
| 246 | // clear the stencil buffer to 0 | ||
| 247 | sceGxmSetFrontStencilFunc( | ||
| 248 | data->gxm_context, | ||
| 249 | SCE_GXM_STENCIL_FUNC_NEVER, | ||
| 250 | SCE_GXM_STENCIL_OP_ZERO, | ||
| 251 | SCE_GXM_STENCIL_OP_ZERO, | ||
| 252 | SCE_GXM_STENCIL_OP_ZERO, | ||
| 253 | 0xFF, | ||
| 254 | 0xFF); | ||
| 255 | |||
| 256 | set_stencil_mask(data, 0, 0, VITA_GXM_SCREEN_WIDTH, VITA_GXM_SCREEN_HEIGHT); | ||
| 257 | |||
| 258 | // set the stencil to 1 in the desired region | ||
| 259 | sceGxmSetFrontStencilFunc( | ||
| 260 | data->gxm_context, | ||
| 261 | SCE_GXM_STENCIL_FUNC_NEVER, | ||
| 262 | SCE_GXM_STENCIL_OP_REPLACE, | ||
| 263 | SCE_GXM_STENCIL_OP_REPLACE, | ||
| 264 | SCE_GXM_STENCIL_OP_REPLACE, | ||
| 265 | 0xFF, | ||
| 266 | 0xFF); | ||
| 267 | |||
| 268 | set_stencil_mask(data, x_min, y_min, x_max - x_min, y_max - y_min); | ||
| 269 | |||
| 270 | // set the stencil function to only accept pixels where the stencil is 1 | ||
| 271 | sceGxmSetFrontStencilFunc( | ||
| 272 | data->gxm_context, | ||
| 273 | SCE_GXM_STENCIL_FUNC_EQUAL, | ||
| 274 | SCE_GXM_STENCIL_OP_KEEP, | ||
| 275 | SCE_GXM_STENCIL_OP_KEEP, | ||
| 276 | SCE_GXM_STENCIL_OP_KEEP, | ||
| 277 | 0xFF, | ||
| 278 | 0xFF); | ||
| 279 | } | ||
| 280 | } | ||
| 281 | |||
| 282 | void unset_clip_rectangle(VITA_GXM_RenderData *data) | ||
| 283 | { | ||
| 284 | sceGxmSetFrontStencilFunc( | ||
| 285 | data->gxm_context, | ||
| 286 | SCE_GXM_STENCIL_FUNC_ALWAYS, | ||
| 287 | SCE_GXM_STENCIL_OP_KEEP, | ||
| 288 | SCE_GXM_STENCIL_OP_KEEP, | ||
| 289 | SCE_GXM_STENCIL_OP_KEEP, | ||
| 290 | 0xFF, | ||
| 291 | 0xFF); | ||
| 292 | } | ||
| 293 | |||
| 294 | int gxm_init(SDL_Renderer *renderer) | ||
| 295 | { | ||
| 296 | unsigned int i, x, y; | ||
| 297 | int err; | ||
| 298 | void *vdmRingBuffer; | ||
| 299 | void *vertexRingBuffer; | ||
| 300 | void *fragmentRingBuffer; | ||
| 301 | unsigned int fragmentUsseRingBufferOffset; | ||
| 302 | void *fragmentUsseRingBuffer; | ||
| 303 | unsigned int patcherVertexUsseOffset; | ||
| 304 | unsigned int patcherFragmentUsseOffset; | ||
| 305 | void *patcherBuffer; | ||
| 306 | void *patcherVertexUsse; | ||
| 307 | void *patcherFragmentUsse; | ||
| 308 | |||
| 309 | SceGxmRenderTargetParams renderTargetParams; | ||
| 310 | SceGxmShaderPatcherParams patcherParams; | ||
| 311 | |||
| 312 | // compute the memory footprint of the depth buffer | ||
| 313 | const unsigned int alignedWidth = ALIGN(VITA_GXM_SCREEN_WIDTH, SCE_GXM_TILE_SIZEX); | ||
| 314 | const unsigned int alignedHeight = ALIGN(VITA_GXM_SCREEN_HEIGHT, SCE_GXM_TILE_SIZEY); | ||
| 315 | |||
| 316 | unsigned int sampleCount = alignedWidth * alignedHeight; | ||
| 317 | unsigned int depthStrideInSamples = alignedWidth; | ||
| 318 | |||
| 319 | // set buffer sizes for this sample | ||
| 320 | const unsigned int patcherBufferSize = 64 * 1024; | ||
| 321 | const unsigned int patcherVertexUsseSize = 64 * 1024; | ||
| 322 | const unsigned int patcherFragmentUsseSize = 64 * 1024; | ||
| 323 | |||
| 324 | // Fill SceGxmBlendInfo | ||
| 325 | static const SceGxmBlendInfo blend_info_none = { | ||
| 326 | .colorFunc = SCE_GXM_BLEND_FUNC_NONE, | ||
| 327 | .alphaFunc = SCE_GXM_BLEND_FUNC_NONE, | ||
| 328 | .colorSrc = SCE_GXM_BLEND_FACTOR_ZERO, | ||
| 329 | .colorDst = SCE_GXM_BLEND_FACTOR_ZERO, | ||
| 330 | .alphaSrc = SCE_GXM_BLEND_FACTOR_ZERO, | ||
| 331 | .alphaDst = SCE_GXM_BLEND_FACTOR_ZERO, | ||
| 332 | .colorMask = SCE_GXM_COLOR_MASK_ALL | ||
| 333 | }; | ||
| 334 | |||
| 335 | static const SceGxmBlendInfo blend_info_blend = { | ||
| 336 | .colorFunc = SCE_GXM_BLEND_FUNC_ADD, | ||
| 337 | .alphaFunc = SCE_GXM_BLEND_FUNC_ADD, | ||
| 338 | .colorSrc = SCE_GXM_BLEND_FACTOR_SRC_ALPHA, | ||
| 339 | .colorDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, | ||
| 340 | .alphaSrc = SCE_GXM_BLEND_FACTOR_ONE, | ||
| 341 | .alphaDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, | ||
| 342 | .colorMask = SCE_GXM_COLOR_MASK_ALL | ||
| 343 | }; | ||
| 344 | |||
| 345 | static const SceGxmBlendInfo blend_info_add = { | ||
| 346 | .colorFunc = SCE_GXM_BLEND_FUNC_ADD, | ||
| 347 | .alphaFunc = SCE_GXM_BLEND_FUNC_ADD, | ||
| 348 | .colorSrc = SCE_GXM_BLEND_FACTOR_SRC_ALPHA, | ||
| 349 | .colorDst = SCE_GXM_BLEND_FACTOR_ONE, | ||
| 350 | .alphaSrc = SCE_GXM_BLEND_FACTOR_ZERO, | ||
| 351 | .alphaDst = SCE_GXM_BLEND_FACTOR_ONE, | ||
| 352 | .colorMask = SCE_GXM_COLOR_MASK_ALL | ||
| 353 | }; | ||
| 354 | |||
| 355 | static const SceGxmBlendInfo blend_info_mod = { | ||
| 356 | .colorFunc = SCE_GXM_BLEND_FUNC_ADD, | ||
| 357 | .alphaFunc = SCE_GXM_BLEND_FUNC_ADD, | ||
| 358 | |||
| 359 | .colorSrc = SCE_GXM_BLEND_FACTOR_ZERO, | ||
| 360 | .colorDst = SCE_GXM_BLEND_FACTOR_SRC_COLOR, | ||
| 361 | |||
| 362 | .alphaSrc = SCE_GXM_BLEND_FACTOR_ZERO, | ||
| 363 | .alphaDst = SCE_GXM_BLEND_FACTOR_ONE, | ||
| 364 | .colorMask = SCE_GXM_COLOR_MASK_ALL | ||
| 365 | }; | ||
| 366 | |||
| 367 | static const SceGxmBlendInfo blend_info_mul = { | ||
| 368 | .colorFunc = SCE_GXM_BLEND_FUNC_ADD, | ||
| 369 | .alphaFunc = SCE_GXM_BLEND_FUNC_ADD, | ||
| 370 | .colorSrc = SCE_GXM_BLEND_FACTOR_DST_COLOR, | ||
| 371 | .colorDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, | ||
| 372 | .alphaSrc = SCE_GXM_BLEND_FACTOR_DST_ALPHA, | ||
| 373 | .alphaDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, | ||
| 374 | .colorMask = SCE_GXM_COLOR_MASK_ALL | ||
| 375 | }; | ||
| 376 | |||
| 377 | VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->internal; | ||
| 378 | |||
| 379 | SceGxmInitializeParams initializeParams; | ||
| 380 | SDL_memset(&initializeParams, 0, sizeof(SceGxmInitializeParams)); | ||
| 381 | initializeParams.flags = 0; | ||
| 382 | initializeParams.displayQueueMaxPendingCount = VITA_GXM_PENDING_SWAPS; | ||
| 383 | initializeParams.displayQueueCallback = display_callback; | ||
| 384 | initializeParams.displayQueueCallbackDataSize = sizeof(VITA_GXM_DisplayData); | ||
| 385 | initializeParams.parameterBufferSize = SCE_GXM_DEFAULT_PARAMETER_BUFFER_SIZE; | ||
| 386 | |||
| 387 | err = sceGxmInitialize(&initializeParams); | ||
| 388 | |||
| 389 | if (err != 0) { | ||
| 390 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "gxm init failed: %d", err); | ||
| 391 | return err; | ||
| 392 | } | ||
| 393 | |||
| 394 | // allocate ring buffer memory using default sizes | ||
| 395 | vdmRingBuffer = vita_mem_alloc( | ||
| 396 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, | ||
| 397 | SCE_GXM_DEFAULT_VDM_RING_BUFFER_SIZE, | ||
| 398 | 4, | ||
| 399 | SCE_GXM_MEMORY_ATTRIB_READ, | ||
| 400 | &data->vdmRingBufferUid); | ||
| 401 | |||
| 402 | vertexRingBuffer = vita_mem_alloc( | ||
| 403 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, | ||
| 404 | SCE_GXM_DEFAULT_VERTEX_RING_BUFFER_SIZE, | ||
| 405 | 4, | ||
| 406 | SCE_GXM_MEMORY_ATTRIB_READ, | ||
| 407 | &data->vertexRingBufferUid); | ||
| 408 | |||
| 409 | fragmentRingBuffer = vita_mem_alloc( | ||
| 410 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, | ||
| 411 | SCE_GXM_DEFAULT_FRAGMENT_RING_BUFFER_SIZE, | ||
| 412 | 4, | ||
| 413 | SCE_GXM_MEMORY_ATTRIB_READ, | ||
| 414 | &data->fragmentRingBufferUid); | ||
| 415 | |||
| 416 | fragmentUsseRingBuffer = vita_mem_fragment_usse_alloc( | ||
| 417 | SCE_GXM_DEFAULT_FRAGMENT_USSE_RING_BUFFER_SIZE, | ||
| 418 | &data->fragmentUsseRingBufferUid, | ||
| 419 | &fragmentUsseRingBufferOffset); | ||
| 420 | |||
| 421 | SDL_memset(&data->contextParams, 0, sizeof(SceGxmContextParams)); | ||
| 422 | data->contextParams.hostMem = SDL_malloc(SCE_GXM_MINIMUM_CONTEXT_HOST_MEM_SIZE); | ||
| 423 | data->contextParams.hostMemSize = SCE_GXM_MINIMUM_CONTEXT_HOST_MEM_SIZE; | ||
| 424 | data->contextParams.vdmRingBufferMem = vdmRingBuffer; | ||
| 425 | data->contextParams.vdmRingBufferMemSize = SCE_GXM_DEFAULT_VDM_RING_BUFFER_SIZE; | ||
| 426 | data->contextParams.vertexRingBufferMem = vertexRingBuffer; | ||
| 427 | data->contextParams.vertexRingBufferMemSize = SCE_GXM_DEFAULT_VERTEX_RING_BUFFER_SIZE; | ||
| 428 | data->contextParams.fragmentRingBufferMem = fragmentRingBuffer; | ||
| 429 | data->contextParams.fragmentRingBufferMemSize = SCE_GXM_DEFAULT_FRAGMENT_RING_BUFFER_SIZE; | ||
| 430 | data->contextParams.fragmentUsseRingBufferMem = fragmentUsseRingBuffer; | ||
| 431 | data->contextParams.fragmentUsseRingBufferMemSize = SCE_GXM_DEFAULT_FRAGMENT_USSE_RING_BUFFER_SIZE; | ||
| 432 | data->contextParams.fragmentUsseRingBufferOffset = fragmentUsseRingBufferOffset; | ||
| 433 | |||
| 434 | err = sceGxmCreateContext(&data->contextParams, &data->gxm_context); | ||
| 435 | if (err != 0) { | ||
| 436 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create context failed: %d", err); | ||
| 437 | return err; | ||
| 438 | } | ||
| 439 | |||
| 440 | // set up parameters | ||
| 441 | SDL_memset(&renderTargetParams, 0, sizeof(SceGxmRenderTargetParams)); | ||
| 442 | renderTargetParams.flags = 0; | ||
| 443 | renderTargetParams.width = VITA_GXM_SCREEN_WIDTH; | ||
| 444 | renderTargetParams.height = VITA_GXM_SCREEN_HEIGHT; | ||
| 445 | renderTargetParams.scenesPerFrame = 1; | ||
| 446 | renderTargetParams.multisampleMode = 0; | ||
| 447 | renderTargetParams.multisampleLocations = 0; | ||
| 448 | renderTargetParams.driverMemBlock = -1; // Invalid UID | ||
| 449 | |||
| 450 | // create the render target | ||
| 451 | err = sceGxmCreateRenderTarget(&renderTargetParams, &data->renderTarget); | ||
| 452 | if (err != 0) { | ||
| 453 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "render target creation failed: %d", err); | ||
| 454 | return err; | ||
| 455 | } | ||
| 456 | |||
| 457 | // allocate memory and sync objects for display buffers | ||
| 458 | for (i = 0; i < VITA_GXM_BUFFERS; i++) { | ||
| 459 | |||
| 460 | // allocate memory for display | ||
| 461 | data->displayBufferData[i] = vita_mem_alloc( | ||
| 462 | SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, | ||
| 463 | 4 * VITA_GXM_SCREEN_STRIDE * VITA_GXM_SCREEN_HEIGHT, | ||
| 464 | SCE_GXM_COLOR_SURFACE_ALIGNMENT, | ||
| 465 | SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE, | ||
| 466 | &data->displayBufferUid[i]); | ||
| 467 | |||
| 468 | // SDL_memset the buffer to black | ||
| 469 | for (y = 0; y < VITA_GXM_SCREEN_HEIGHT; y++) { | ||
| 470 | unsigned int *row = (unsigned int *)data->displayBufferData[i] + y * VITA_GXM_SCREEN_STRIDE; | ||
| 471 | for (x = 0; x < VITA_GXM_SCREEN_WIDTH; x++) { | ||
| 472 | row[x] = 0xff000000; | ||
| 473 | } | ||
| 474 | } | ||
| 475 | |||
| 476 | // initialize a color surface for this display buffer | ||
| 477 | err = sceGxmColorSurfaceInit( | ||
| 478 | &data->displaySurface[i], | ||
| 479 | VITA_GXM_COLOR_FORMAT, | ||
| 480 | SCE_GXM_COLOR_SURFACE_LINEAR, | ||
| 481 | SCE_GXM_COLOR_SURFACE_SCALE_NONE, | ||
| 482 | SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT, | ||
| 483 | VITA_GXM_SCREEN_WIDTH, | ||
| 484 | VITA_GXM_SCREEN_HEIGHT, | ||
| 485 | VITA_GXM_SCREEN_STRIDE, | ||
| 486 | data->displayBufferData[i]); | ||
| 487 | |||
| 488 | if (err != 0) { | ||
| 489 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "color surface init failed: %d", err); | ||
| 490 | return err; | ||
| 491 | } | ||
| 492 | |||
| 493 | // create a sync object that we will associate with this buffer | ||
| 494 | err = sceGxmSyncObjectCreate(&data->displayBufferSync[i]); | ||
| 495 | if (err != 0) { | ||
| 496 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "sync object creation failed: %d", err); | ||
| 497 | return err; | ||
| 498 | } | ||
| 499 | } | ||
| 500 | |||
| 501 | // allocate the depth buffer | ||
| 502 | data->depthBufferData = vita_mem_alloc( | ||
| 503 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, | ||
| 504 | 4 * sampleCount, | ||
| 505 | SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT, | ||
| 506 | SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE, | ||
| 507 | &data->depthBufferUid); | ||
| 508 | |||
| 509 | // allocate the stencil buffer | ||
| 510 | data->stencilBufferData = vita_mem_alloc( | ||
| 511 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, | ||
| 512 | 4 * sampleCount, | ||
| 513 | SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT, | ||
| 514 | SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE, | ||
| 515 | &data->stencilBufferUid); | ||
| 516 | |||
| 517 | // create the SceGxmDepthStencilSurface structure | ||
| 518 | err = sceGxmDepthStencilSurfaceInit( | ||
| 519 | &data->depthSurface, | ||
| 520 | SCE_GXM_DEPTH_STENCIL_FORMAT_S8D24, | ||
| 521 | SCE_GXM_DEPTH_STENCIL_SURFACE_TILED, | ||
| 522 | depthStrideInSamples, | ||
| 523 | data->depthBufferData, | ||
| 524 | data->stencilBufferData); | ||
| 525 | |||
| 526 | // set the stencil test reference (this is currently assumed to always remain 1 after here for region clipping) | ||
| 527 | sceGxmSetFrontStencilRef(data->gxm_context, 1); | ||
| 528 | |||
| 529 | // set the stencil function (this wouldn't actually be needed, as the set clip rectangle function has to call this at the beginning of every scene) | ||
| 530 | sceGxmSetFrontStencilFunc( | ||
| 531 | data->gxm_context, | ||
| 532 | SCE_GXM_STENCIL_FUNC_ALWAYS, | ||
| 533 | SCE_GXM_STENCIL_OP_KEEP, | ||
| 534 | SCE_GXM_STENCIL_OP_KEEP, | ||
| 535 | SCE_GXM_STENCIL_OP_KEEP, | ||
| 536 | 0xFF, | ||
| 537 | 0xFF); | ||
| 538 | |||
| 539 | // allocate memory for buffers and USSE code | ||
| 540 | patcherBuffer = vita_mem_alloc( | ||
| 541 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, | ||
| 542 | patcherBufferSize, | ||
| 543 | 4, | ||
| 544 | SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE, | ||
| 545 | &data->patcherBufferUid); | ||
| 546 | |||
| 547 | patcherVertexUsse = vita_mem_vertex_usse_alloc( | ||
| 548 | patcherVertexUsseSize, | ||
| 549 | &data->patcherVertexUsseUid, | ||
| 550 | &patcherVertexUsseOffset); | ||
| 551 | |||
| 552 | patcherFragmentUsse = vita_mem_fragment_usse_alloc( | ||
| 553 | patcherFragmentUsseSize, | ||
| 554 | &data->patcherFragmentUsseUid, | ||
| 555 | &patcherFragmentUsseOffset); | ||
| 556 | |||
| 557 | // create a shader patcher | ||
| 558 | SDL_memset(&patcherParams, 0, sizeof(SceGxmShaderPatcherParams)); | ||
| 559 | patcherParams.userData = NULL; | ||
| 560 | patcherParams.hostAllocCallback = &patcher_host_alloc; | ||
| 561 | patcherParams.hostFreeCallback = &patcher_host_free; | ||
| 562 | patcherParams.bufferAllocCallback = NULL; | ||
| 563 | patcherParams.bufferFreeCallback = NULL; | ||
| 564 | patcherParams.bufferMem = patcherBuffer; | ||
| 565 | patcherParams.bufferMemSize = patcherBufferSize; | ||
| 566 | patcherParams.vertexUsseAllocCallback = NULL; | ||
| 567 | patcherParams.vertexUsseFreeCallback = NULL; | ||
| 568 | patcherParams.vertexUsseMem = patcherVertexUsse; | ||
| 569 | patcherParams.vertexUsseMemSize = patcherVertexUsseSize; | ||
| 570 | patcherParams.vertexUsseOffset = patcherVertexUsseOffset; | ||
| 571 | patcherParams.fragmentUsseAllocCallback = NULL; | ||
| 572 | patcherParams.fragmentUsseFreeCallback = NULL; | ||
| 573 | patcherParams.fragmentUsseMem = patcherFragmentUsse; | ||
| 574 | patcherParams.fragmentUsseMemSize = patcherFragmentUsseSize; | ||
| 575 | patcherParams.fragmentUsseOffset = patcherFragmentUsseOffset; | ||
| 576 | |||
| 577 | err = sceGxmShaderPatcherCreate(&patcherParams, &data->shaderPatcher); | ||
| 578 | if (err != 0) { | ||
| 579 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "shader patcher creation failed: %d", err); | ||
| 580 | return err; | ||
| 581 | } | ||
| 582 | |||
| 583 | // check the shaders | ||
| 584 | err = sceGxmProgramCheck(clearVertexProgramGxp); | ||
| 585 | if (err != 0) { | ||
| 586 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "check program (clear vertex) failed: %d", err); | ||
| 587 | return err; | ||
| 588 | } | ||
| 589 | |||
| 590 | err = sceGxmProgramCheck(clearFragmentProgramGxp); | ||
| 591 | if (err != 0) { | ||
| 592 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "check program (clear fragment) failed: %d", err); | ||
| 593 | return err; | ||
| 594 | } | ||
| 595 | |||
| 596 | err = sceGxmProgramCheck(colorVertexProgramGxp); | ||
| 597 | if (err != 0) { | ||
| 598 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "check program (color vertex) failed: %d", err); | ||
| 599 | return err; | ||
| 600 | } | ||
| 601 | |||
| 602 | err = sceGxmProgramCheck(colorFragmentProgramGxp); | ||
| 603 | if (err != 0) { | ||
| 604 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "check program (color fragment) failed: %d", err); | ||
| 605 | return err; | ||
| 606 | } | ||
| 607 | |||
| 608 | err = sceGxmProgramCheck(textureVertexProgramGxp); | ||
| 609 | if (err != 0) { | ||
| 610 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "check program (texture vertex) failed: %d", err); | ||
| 611 | return err; | ||
| 612 | } | ||
| 613 | |||
| 614 | err = sceGxmProgramCheck(textureFragmentProgramGxp); | ||
| 615 | if (err != 0) { | ||
| 616 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "check program (texture fragment) failed: %d", err); | ||
| 617 | return err; | ||
| 618 | } | ||
| 619 | |||
| 620 | // register programs with the patcher | ||
| 621 | err = sceGxmShaderPatcherRegisterProgram(data->shaderPatcher, clearVertexProgramGxp, &data->clearVertexProgramId); | ||
| 622 | if (err != 0) { | ||
| 623 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "register program (clear vertex) failed: %d", err); | ||
| 624 | return err; | ||
| 625 | } | ||
| 626 | |||
| 627 | err = sceGxmShaderPatcherRegisterProgram(data->shaderPatcher, clearFragmentProgramGxp, &data->clearFragmentProgramId); | ||
| 628 | if (err != 0) { | ||
| 629 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "register program (clear fragment) failed: %d", err); | ||
| 630 | return err; | ||
| 631 | } | ||
| 632 | |||
| 633 | err = sceGxmShaderPatcherRegisterProgram(data->shaderPatcher, colorVertexProgramGxp, &data->colorVertexProgramId); | ||
| 634 | if (err != 0) { | ||
| 635 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "register program (color vertex) failed: %d", err); | ||
| 636 | return err; | ||
| 637 | } | ||
| 638 | |||
| 639 | err = sceGxmShaderPatcherRegisterProgram(data->shaderPatcher, colorFragmentProgramGxp, &data->colorFragmentProgramId); | ||
| 640 | if (err != 0) { | ||
| 641 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "register program (color fragment) failed: %d", err); | ||
| 642 | return err; | ||
| 643 | } | ||
| 644 | |||
| 645 | err = sceGxmShaderPatcherRegisterProgram(data->shaderPatcher, textureVertexProgramGxp, &data->textureVertexProgramId); | ||
| 646 | if (err != 0) { | ||
| 647 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "register program (texture vertex) failed: %d", err); | ||
| 648 | return err; | ||
| 649 | } | ||
| 650 | |||
| 651 | err = sceGxmShaderPatcherRegisterProgram(data->shaderPatcher, textureFragmentProgramGxp, &data->textureFragmentProgramId); | ||
| 652 | if (err != 0) { | ||
| 653 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "register program (texture fragment) failed: %d", err); | ||
| 654 | return err; | ||
| 655 | } | ||
| 656 | |||
| 657 | { | ||
| 658 | // get attributes by name to create vertex format bindings | ||
| 659 | const SceGxmProgramParameter *paramClearPositionAttribute = sceGxmProgramFindParameterByName(clearVertexProgramGxp, "aPosition"); | ||
| 660 | |||
| 661 | // create clear vertex format | ||
| 662 | SceGxmVertexAttribute clearVertexAttributes[1]; | ||
| 663 | SceGxmVertexStream clearVertexStreams[1]; | ||
| 664 | clearVertexAttributes[0].streamIndex = 0; | ||
| 665 | clearVertexAttributes[0].offset = 0; | ||
| 666 | clearVertexAttributes[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; | ||
| 667 | clearVertexAttributes[0].componentCount = 2; | ||
| 668 | clearVertexAttributes[0].regIndex = sceGxmProgramParameterGetResourceIndex(paramClearPositionAttribute); | ||
| 669 | clearVertexStreams[0].stride = sizeof(clear_vertex); | ||
| 670 | clearVertexStreams[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; | ||
| 671 | |||
| 672 | // create clear programs | ||
| 673 | err = sceGxmShaderPatcherCreateVertexProgram( | ||
| 674 | data->shaderPatcher, | ||
| 675 | data->clearVertexProgramId, | ||
| 676 | clearVertexAttributes, | ||
| 677 | 1, | ||
| 678 | clearVertexStreams, | ||
| 679 | 1, | ||
| 680 | &data->clearVertexProgram); | ||
| 681 | if (err != 0) { | ||
| 682 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create program (clear vertex) failed: %d", err); | ||
| 683 | return err; | ||
| 684 | } | ||
| 685 | |||
| 686 | err = sceGxmShaderPatcherCreateFragmentProgram( | ||
| 687 | data->shaderPatcher, | ||
| 688 | data->clearFragmentProgramId, | ||
| 689 | SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, | ||
| 690 | 0, | ||
| 691 | NULL, | ||
| 692 | clearVertexProgramGxp, | ||
| 693 | &data->clearFragmentProgram); | ||
| 694 | if (err != 0) { | ||
| 695 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create program (clear fragment) failed: %d", err); | ||
| 696 | return err; | ||
| 697 | } | ||
| 698 | |||
| 699 | // create the clear triangle vertex/index data | ||
| 700 | data->clearVertices = (clear_vertex *)vita_mem_alloc( | ||
| 701 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, | ||
| 702 | 3 * sizeof(clear_vertex), | ||
| 703 | 4, | ||
| 704 | SCE_GXM_MEMORY_ATTRIB_READ, | ||
| 705 | &data->clearVerticesUid); | ||
| 706 | } | ||
| 707 | |||
| 708 | // Allocate a 64k * 2 bytes = 128 KiB buffer and store all possible | ||
| 709 | // 16-bit indices in linear ascending order, so we can use this for | ||
| 710 | // all drawing operations where we don't want to use indexing. | ||
| 711 | data->linearIndices = (uint16_t *)vita_mem_alloc( | ||
| 712 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, | ||
| 713 | UINT16_MAX * sizeof(uint16_t), | ||
| 714 | sizeof(uint16_t), | ||
| 715 | SCE_GXM_MEMORY_ATTRIB_READ, | ||
| 716 | &data->linearIndicesUid); | ||
| 717 | |||
| 718 | for (i = 0; i <= UINT16_MAX; ++i) { | ||
| 719 | data->linearIndices[i] = i; | ||
| 720 | } | ||
| 721 | |||
| 722 | data->clearVertices[0].x = -1.0f; | ||
| 723 | data->clearVertices[0].y = -1.0f; | ||
| 724 | data->clearVertices[1].x = 3.0f; | ||
| 725 | data->clearVertices[1].y = -1.0f; | ||
| 726 | data->clearVertices[2].x = -1.0f; | ||
| 727 | data->clearVertices[2].y = 3.0f; | ||
| 728 | |||
| 729 | { | ||
| 730 | const SceGxmProgramParameter *paramColorPositionAttribute = sceGxmProgramFindParameterByName(colorVertexProgramGxp, "aPosition"); | ||
| 731 | |||
| 732 | const SceGxmProgramParameter *paramColorColorAttribute = sceGxmProgramFindParameterByName(colorVertexProgramGxp, "aColor"); | ||
| 733 | |||
| 734 | // create color vertex format | ||
| 735 | SceGxmVertexAttribute colorVertexAttributes[2]; | ||
| 736 | SceGxmVertexStream colorVertexStreams[1]; | ||
| 737 | // x,y: 2 float 32 bits | ||
| 738 | colorVertexAttributes[0].streamIndex = 0; | ||
| 739 | colorVertexAttributes[0].offset = 0; | ||
| 740 | colorVertexAttributes[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; | ||
| 741 | colorVertexAttributes[0].componentCount = 2; // (x, y) | ||
| 742 | colorVertexAttributes[0].regIndex = sceGxmProgramParameterGetResourceIndex(paramColorPositionAttribute); | ||
| 743 | // color: 4 floats = 4*32 bits | ||
| 744 | colorVertexAttributes[1].streamIndex = 0; | ||
| 745 | colorVertexAttributes[1].offset = 8; // (x, y) * 4 = 8 bytes | ||
| 746 | colorVertexAttributes[1].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; | ||
| 747 | colorVertexAttributes[1].componentCount = 4; // (color) | ||
| 748 | colorVertexAttributes[1].regIndex = sceGxmProgramParameterGetResourceIndex(paramColorColorAttribute); | ||
| 749 | // 16 bit (short) indices | ||
| 750 | colorVertexStreams[0].stride = sizeof(color_vertex); | ||
| 751 | colorVertexStreams[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; | ||
| 752 | |||
| 753 | // create color shaders | ||
| 754 | err = sceGxmShaderPatcherCreateVertexProgram( | ||
| 755 | data->shaderPatcher, | ||
| 756 | data->colorVertexProgramId, | ||
| 757 | colorVertexAttributes, | ||
| 758 | 2, | ||
| 759 | colorVertexStreams, | ||
| 760 | 1, | ||
| 761 | &data->colorVertexProgram); | ||
| 762 | if (err != 0) { | ||
| 763 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create program (color vertex) failed: %d", err); | ||
| 764 | return err; | ||
| 765 | } | ||
| 766 | } | ||
| 767 | |||
| 768 | { | ||
| 769 | const SceGxmProgramParameter *paramTexturePositionAttribute = sceGxmProgramFindParameterByName(textureVertexProgramGxp, "aPosition"); | ||
| 770 | const SceGxmProgramParameter *paramTextureTexcoordAttribute = sceGxmProgramFindParameterByName(textureVertexProgramGxp, "aTexcoord"); | ||
| 771 | const SceGxmProgramParameter *paramTextureColorAttribute = sceGxmProgramFindParameterByName(textureVertexProgramGxp, "aColor"); | ||
| 772 | |||
| 773 | // create texture vertex format | ||
| 774 | SceGxmVertexAttribute textureVertexAttributes[3]; | ||
| 775 | SceGxmVertexStream textureVertexStreams[1]; | ||
| 776 | // x,y: 2 float 32 bits | ||
| 777 | textureVertexAttributes[0].streamIndex = 0; | ||
| 778 | textureVertexAttributes[0].offset = 0; | ||
| 779 | textureVertexAttributes[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; | ||
| 780 | textureVertexAttributes[0].componentCount = 2; // (x, y) | ||
| 781 | textureVertexAttributes[0].regIndex = sceGxmProgramParameterGetResourceIndex(paramTexturePositionAttribute); | ||
| 782 | // u,v: 2 floats 32 bits | ||
| 783 | textureVertexAttributes[1].streamIndex = 0; | ||
| 784 | textureVertexAttributes[1].offset = 8; // (x, y) * 4 = 8 bytes | ||
| 785 | textureVertexAttributes[1].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; | ||
| 786 | textureVertexAttributes[1].componentCount = 2; // (u, v) | ||
| 787 | textureVertexAttributes[1].regIndex = sceGxmProgramParameterGetResourceIndex(paramTextureTexcoordAttribute); | ||
| 788 | // r,g,b,a: 4 floats 4*32 bits | ||
| 789 | textureVertexAttributes[2].streamIndex = 0; | ||
| 790 | textureVertexAttributes[2].offset = 16; // (x, y, u, v) * 4 = 16 bytes | ||
| 791 | textureVertexAttributes[2].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; | ||
| 792 | textureVertexAttributes[2].componentCount = 4; // (r, g, b, a) | ||
| 793 | textureVertexAttributes[2].regIndex = sceGxmProgramParameterGetResourceIndex(paramTextureColorAttribute); | ||
| 794 | // 16 bit (short) indices | ||
| 795 | textureVertexStreams[0].stride = sizeof(texture_vertex); | ||
| 796 | textureVertexStreams[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; | ||
| 797 | |||
| 798 | // create texture shaders | ||
| 799 | err = sceGxmShaderPatcherCreateVertexProgram( | ||
| 800 | data->shaderPatcher, | ||
| 801 | data->textureVertexProgramId, | ||
| 802 | textureVertexAttributes, | ||
| 803 | 3, | ||
| 804 | textureVertexStreams, | ||
| 805 | 1, | ||
| 806 | &data->textureVertexProgram); | ||
| 807 | if (err != 0) { | ||
| 808 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create program (texture vertex) failed: %x", err); | ||
| 809 | return err; | ||
| 810 | } | ||
| 811 | } | ||
| 812 | |||
| 813 | // Create variations of the fragment program based on blending mode | ||
| 814 | make_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_none, &blend_info_none); | ||
| 815 | make_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_blend, &blend_info_blend); | ||
| 816 | make_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_add, &blend_info_add); | ||
| 817 | make_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_mod, &blend_info_mod); | ||
| 818 | make_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_mul, &blend_info_mul); | ||
| 819 | |||
| 820 | { | ||
| 821 | // Default to blend blending mode | ||
| 822 | fragment_programs *in = &data->blendFragmentPrograms.blend_mode_blend; | ||
| 823 | |||
| 824 | data->colorFragmentProgram = in->color; | ||
| 825 | data->textureFragmentProgram = in->texture; | ||
| 826 | } | ||
| 827 | |||
| 828 | // find vertex uniforms by name and cache parameter information | ||
| 829 | data->clearClearColorParam = (SceGxmProgramParameter *)sceGxmProgramFindParameterByName(clearFragmentProgramGxp, "uClearColor"); | ||
| 830 | data->colorWvpParam = (SceGxmProgramParameter *)sceGxmProgramFindParameterByName(colorVertexProgramGxp, "wvp"); | ||
| 831 | data->textureWvpParam = (SceGxmProgramParameter *)sceGxmProgramFindParameterByName(textureVertexProgramGxp, "wvp"); | ||
| 832 | |||
| 833 | // Allocate memory for the memory pool | ||
| 834 | data->pool_addr[0] = vita_mem_alloc( | ||
| 835 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW, | ||
| 836 | VITA_GXM_POOL_SIZE, | ||
| 837 | sizeof(void *), | ||
| 838 | SCE_GXM_MEMORY_ATTRIB_READ, | ||
| 839 | &data->poolUid[0]); | ||
| 840 | |||
| 841 | data->pool_addr[1] = vita_mem_alloc( | ||
| 842 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW, | ||
| 843 | VITA_GXM_POOL_SIZE, | ||
| 844 | sizeof(void *), | ||
| 845 | SCE_GXM_MEMORY_ATTRIB_READ, | ||
| 846 | &data->poolUid[1]); | ||
| 847 | |||
| 848 | init_orthographic_matrix(data->ortho_matrix, 0.0f, VITA_GXM_SCREEN_WIDTH, VITA_GXM_SCREEN_HEIGHT, 0.0f, 0.0f, 1.0f); | ||
| 849 | |||
| 850 | data->backBufferIndex = 0; | ||
| 851 | data->frontBufferIndex = 0; | ||
| 852 | data->pool_index = 0; | ||
| 853 | data->current_pool = 0; | ||
| 854 | data->currentBlendMode = SDL_BLENDMODE_BLEND; | ||
| 855 | |||
| 856 | return 0; | ||
| 857 | } | ||
| 858 | |||
| 859 | void gxm_finish(SDL_Renderer *renderer) | ||
| 860 | { | ||
| 861 | VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->internal; | ||
| 862 | |||
| 863 | // wait until rendering is done | ||
| 864 | sceGxmFinish(data->gxm_context); | ||
| 865 | |||
| 866 | // clean up allocations | ||
| 867 | sceGxmShaderPatcherReleaseFragmentProgram(data->shaderPatcher, data->clearFragmentProgram); | ||
| 868 | sceGxmShaderPatcherReleaseVertexProgram(data->shaderPatcher, data->clearVertexProgram); | ||
| 869 | sceGxmShaderPatcherReleaseVertexProgram(data->shaderPatcher, data->colorVertexProgram); | ||
| 870 | sceGxmShaderPatcherReleaseVertexProgram(data->shaderPatcher, data->textureVertexProgram); | ||
| 871 | |||
| 872 | free_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_none); | ||
| 873 | free_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_blend); | ||
| 874 | free_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_add); | ||
| 875 | free_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_mod); | ||
| 876 | free_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_mul); | ||
| 877 | |||
| 878 | vita_mem_free(data->linearIndicesUid); | ||
| 879 | vita_mem_free(data->clearVerticesUid); | ||
| 880 | |||
| 881 | // wait until display queue is finished before deallocating display buffers | ||
| 882 | sceGxmDisplayQueueFinish(); | ||
| 883 | |||
| 884 | // clean up display queue | ||
| 885 | vita_mem_free(data->depthBufferUid); | ||
| 886 | |||
| 887 | for (size_t i = 0; i < VITA_GXM_BUFFERS; i++) { | ||
| 888 | // clear the buffer then deallocate | ||
| 889 | SDL_memset(data->displayBufferData[i], 0, VITA_GXM_SCREEN_HEIGHT * VITA_GXM_SCREEN_STRIDE * 4); | ||
| 890 | vita_mem_free(data->displayBufferUid[i]); | ||
| 891 | |||
| 892 | // destroy the sync object | ||
| 893 | sceGxmSyncObjectDestroy(data->displayBufferSync[i]); | ||
| 894 | } | ||
| 895 | |||
| 896 | // Free the depth and stencil buffer | ||
| 897 | vita_mem_free(data->depthBufferUid); | ||
| 898 | vita_mem_free(data->stencilBufferUid); | ||
| 899 | |||
| 900 | // unregister programs and destroy shader patcher | ||
| 901 | sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->clearFragmentProgramId); | ||
| 902 | sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->clearVertexProgramId); | ||
| 903 | sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->colorFragmentProgramId); | ||
| 904 | sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->colorVertexProgramId); | ||
| 905 | sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->textureFragmentProgramId); | ||
| 906 | sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->textureVertexProgramId); | ||
| 907 | |||
| 908 | sceGxmShaderPatcherDestroy(data->shaderPatcher); | ||
| 909 | vita_mem_fragment_usse_free(data->patcherFragmentUsseUid); | ||
| 910 | vita_mem_vertex_usse_free(data->patcherVertexUsseUid); | ||
| 911 | vita_mem_free(data->patcherBufferUid); | ||
| 912 | |||
| 913 | // destroy the render target | ||
| 914 | sceGxmDestroyRenderTarget(data->renderTarget); | ||
| 915 | |||
| 916 | // destroy the gxm context | ||
| 917 | sceGxmDestroyContext(data->gxm_context); | ||
| 918 | vita_mem_fragment_usse_free(data->fragmentUsseRingBufferUid); | ||
| 919 | vita_mem_free(data->fragmentRingBufferUid); | ||
| 920 | vita_mem_free(data->vertexRingBufferUid); | ||
| 921 | vita_mem_free(data->vdmRingBufferUid); | ||
| 922 | SDL_free(data->contextParams.hostMem); | ||
| 923 | |||
| 924 | vita_mem_free(data->poolUid[0]); | ||
| 925 | vita_mem_free(data->poolUid[1]); | ||
| 926 | vita_gpu_mem_destroy(data); | ||
| 927 | |||
| 928 | // terminate libgxm | ||
| 929 | sceGxmTerminate(); | ||
| 930 | } | ||
| 931 | |||
| 932 | // textures | ||
| 933 | |||
| 934 | void free_gxm_texture(VITA_GXM_RenderData *data, gxm_texture *texture) | ||
| 935 | { | ||
| 936 | if (texture) { | ||
| 937 | if (texture->gxm_rendertarget) { | ||
| 938 | sceGxmDestroyRenderTarget(texture->gxm_rendertarget); | ||
| 939 | } | ||
| 940 | if (texture->depth_UID) { | ||
| 941 | vita_mem_free(texture->depth_UID); | ||
| 942 | } | ||
| 943 | if (texture->cdram) { | ||
| 944 | vita_gpu_mem_free(data, sceGxmTextureGetData(&texture->gxm_tex)); | ||
| 945 | } else { | ||
| 946 | vita_mem_free(texture->data_UID); | ||
| 947 | } | ||
| 948 | SDL_free(texture); | ||
| 949 | } | ||
| 950 | } | ||
| 951 | |||
| 952 | SceGxmTextureFormat | ||
| 953 | gxm_texture_get_format(const gxm_texture *texture) | ||
| 954 | { | ||
| 955 | return sceGxmTextureGetFormat(&texture->gxm_tex); | ||
| 956 | } | ||
| 957 | |||
| 958 | void *gxm_texture_get_datap(const gxm_texture *texture) | ||
| 959 | { | ||
| 960 | return sceGxmTextureGetData(&texture->gxm_tex); | ||
| 961 | } | ||
| 962 | |||
| 963 | static SceGxmColorFormat tex_format_to_color_format(SceGxmTextureFormat format) | ||
| 964 | { | ||
| 965 | switch (format) { | ||
| 966 | case SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ARGB: | ||
| 967 | return SCE_GXM_COLOR_FORMAT_U8U8U8U8_ARGB; | ||
| 968 | case SCE_GXM_TEXTURE_FORMAT_U8U8U8_RGB: | ||
| 969 | return SCE_GXM_COLOR_FORMAT_U8U8U8_RGB; | ||
| 970 | case SCE_GXM_TEXTURE_FORMAT_U8U8U8_BGR: | ||
| 971 | return SCE_GXM_COLOR_FORMAT_U8U8U8_BGR; | ||
| 972 | case SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ABGR: | ||
| 973 | return SCE_GXM_COLOR_FORMAT_U8U8U8U8_ABGR; | ||
| 974 | case SCE_GXM_TEXTURE_FORMAT_U5U6U5_RGB: | ||
| 975 | return SCE_GXM_COLOR_FORMAT_U5U6U5_RGB; | ||
| 976 | case SCE_GXM_TEXTURE_FORMAT_U5U6U5_BGR: | ||
| 977 | return SCE_GXM_COLOR_FORMAT_U5U6U5_BGR; | ||
| 978 | default: | ||
| 979 | return SCE_GXM_COLOR_FORMAT_U8U8U8U8_ABGR; | ||
| 980 | } | ||
| 981 | } | ||
| 982 | |||
| 983 | 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) | ||
| 984 | { | ||
| 985 | gxm_texture *texture = SDL_calloc(1, sizeof(gxm_texture)); | ||
| 986 | int aligned_w = ALIGN(w, 8); | ||
| 987 | int texture_w = w; | ||
| 988 | int tex_size = aligned_w * h * tex_format_to_bytespp(format); | ||
| 989 | void *texture_data; | ||
| 990 | int ret; | ||
| 991 | |||
| 992 | *return_wscale = 1.0f; | ||
| 993 | |||
| 994 | // SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P3/P2 based formats require width aligned to 16 | ||
| 995 | if ((format & 0x9f000000U) == SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P3 || (format & 0x9f000000U) == SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P2) { | ||
| 996 | aligned_w = ALIGN(w, 16); | ||
| 997 | texture_w = aligned_w; | ||
| 998 | tex_size = aligned_w * h * tex_format_to_bytespp(format); | ||
| 999 | *return_wscale = (float)(w) / texture_w; | ||
| 1000 | // add storage for UV planes | ||
| 1001 | tex_size += (((aligned_w + 1) / 2) * ((h + 1) / 2)) * 2; | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | if (!texture) { | ||
| 1005 | return NULL; | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | *return_w = w; | ||
| 1009 | *return_h = h; | ||
| 1010 | *return_pitch = aligned_w * tex_format_to_bytespp(format); | ||
| 1011 | |||
| 1012 | // Allocate a GPU buffer for the texture | ||
| 1013 | texture_data = vita_gpu_mem_alloc( | ||
| 1014 | data, | ||
| 1015 | tex_size); | ||
| 1016 | |||
| 1017 | // Try SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE in case we're out of VRAM | ||
| 1018 | if (!texture_data) { | ||
| 1019 | SDL_LogWarn(SDL_LOG_CATEGORY_RENDER, "CDRAM texture allocation failed"); | ||
| 1020 | texture_data = vita_mem_alloc( | ||
| 1021 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, | ||
| 1022 | tex_size, | ||
| 1023 | SCE_GXM_TEXTURE_ALIGNMENT, | ||
| 1024 | SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE, | ||
| 1025 | &texture->data_UID); | ||
| 1026 | texture->cdram = 0; | ||
| 1027 | } else { | ||
| 1028 | texture->cdram = 1; | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | if (!texture_data) { | ||
| 1032 | SDL_free(texture); | ||
| 1033 | return NULL; | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | // Clear the texture | ||
| 1037 | SDL_memset(texture_data, 0, tex_size); | ||
| 1038 | |||
| 1039 | // Create the gxm texture | ||
| 1040 | ret = sceGxmTextureInitLinear(&texture->gxm_tex, texture_data, format, texture_w, h, 0); | ||
| 1041 | if (ret < 0) { | ||
| 1042 | free_gxm_texture(data, texture); | ||
| 1043 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "texture init failed: %x", ret); | ||
| 1044 | return NULL; | ||
| 1045 | } | ||
| 1046 | |||
| 1047 | if (isRenderTarget) { | ||
| 1048 | void *depthBufferData; | ||
| 1049 | const uint32_t alignedWidth = ALIGN(w, SCE_GXM_TILE_SIZEX); | ||
| 1050 | const uint32_t alignedHeight = ALIGN(h, SCE_GXM_TILE_SIZEY); | ||
| 1051 | uint32_t sampleCount = alignedWidth * alignedHeight; | ||
| 1052 | uint32_t depthStrideInSamples = alignedWidth; | ||
| 1053 | const uint32_t alignedColorSurfaceStride = ALIGN(w, 8); | ||
| 1054 | |||
| 1055 | int err = sceGxmColorSurfaceInit( | ||
| 1056 | &texture->gxm_colorsurface, | ||
| 1057 | tex_format_to_color_format(format), | ||
| 1058 | SCE_GXM_COLOR_SURFACE_LINEAR, | ||
| 1059 | SCE_GXM_COLOR_SURFACE_SCALE_NONE, | ||
| 1060 | SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT, | ||
| 1061 | w, | ||
| 1062 | h, | ||
| 1063 | alignedColorSurfaceStride, | ||
| 1064 | texture_data); | ||
| 1065 | |||
| 1066 | if (err < 0) { | ||
| 1067 | free_gxm_texture(data, texture); | ||
| 1068 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "color surface init failed: %x", err); | ||
| 1069 | return NULL; | ||
| 1070 | } | ||
| 1071 | |||
| 1072 | // allocate it | ||
| 1073 | depthBufferData = vita_mem_alloc( | ||
| 1074 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, | ||
| 1075 | 4 * sampleCount, | ||
| 1076 | SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT, | ||
| 1077 | SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE, | ||
| 1078 | &texture->depth_UID); | ||
| 1079 | |||
| 1080 | // create the SceGxmDepthStencilSurface structure | ||
| 1081 | err = sceGxmDepthStencilSurfaceInit( | ||
| 1082 | &texture->gxm_depthstencil, | ||
| 1083 | SCE_GXM_DEPTH_STENCIL_FORMAT_S8D24, | ||
| 1084 | SCE_GXM_DEPTH_STENCIL_SURFACE_TILED, | ||
| 1085 | depthStrideInSamples, | ||
| 1086 | depthBufferData, | ||
| 1087 | NULL); | ||
| 1088 | |||
| 1089 | if (err < 0) { | ||
| 1090 | free_gxm_texture(data, texture); | ||
| 1091 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "depth stencil init failed: %x", err); | ||
| 1092 | return NULL; | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | { | ||
| 1096 | SceGxmRenderTarget *tgt = NULL; | ||
| 1097 | |||
| 1098 | // set up parameters | ||
| 1099 | SceGxmRenderTargetParams renderTargetParams; | ||
| 1100 | SDL_memset(&renderTargetParams, 0, sizeof(SceGxmRenderTargetParams)); | ||
| 1101 | renderTargetParams.flags = 0; | ||
| 1102 | renderTargetParams.width = w; | ||
| 1103 | renderTargetParams.height = h; | ||
| 1104 | renderTargetParams.scenesPerFrame = 1; | ||
| 1105 | renderTargetParams.multisampleMode = SCE_GXM_MULTISAMPLE_NONE; | ||
| 1106 | renderTargetParams.multisampleLocations = 0; | ||
| 1107 | renderTargetParams.driverMemBlock = -1; | ||
| 1108 | |||
| 1109 | // create the render target | ||
| 1110 | err = sceGxmCreateRenderTarget(&renderTargetParams, &tgt); | ||
| 1111 | |||
| 1112 | texture->gxm_rendertarget = tgt; | ||
| 1113 | |||
| 1114 | if (err < 0) { | ||
| 1115 | free_gxm_texture(data, texture); | ||
| 1116 | SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create render target failed: %x", err); | ||
| 1117 | return NULL; | ||
| 1118 | } | ||
| 1119 | } | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | return texture; | ||
| 1123 | } | ||
| 1124 | |||
| 1125 | void gxm_texture_set_filters(gxm_texture *texture, SceGxmTextureFilter min_filter, SceGxmTextureFilter mag_filter) | ||
| 1126 | { | ||
| 1127 | sceGxmTextureSetMinFilter(&texture->gxm_tex, min_filter); | ||
| 1128 | sceGxmTextureSetMagFilter(&texture->gxm_tex, mag_filter); | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | static unsigned int back_buffer_index_for_common_dialog = 0; | ||
| 1132 | static unsigned int front_buffer_index_for_common_dialog = 0; | ||
| 1133 | struct | ||
| 1134 | { | ||
| 1135 | VITA_GXM_DisplayData displayData; | ||
| 1136 | SceGxmSyncObject *sync; | ||
| 1137 | SceGxmColorSurface surf; | ||
| 1138 | SceUID uid; | ||
| 1139 | } buffer_for_common_dialog[VITA_GXM_BUFFERS]; | ||
| 1140 | |||
| 1141 | void gxm_minimal_init_for_common_dialog(void) | ||
| 1142 | { | ||
| 1143 | SceGxmInitializeParams initializeParams; | ||
| 1144 | SDL_zero(initializeParams); | ||
| 1145 | initializeParams.flags = 0; | ||
| 1146 | initializeParams.displayQueueMaxPendingCount = VITA_GXM_PENDING_SWAPS; | ||
| 1147 | initializeParams.displayQueueCallback = display_callback; | ||
| 1148 | initializeParams.displayQueueCallbackDataSize = sizeof(VITA_GXM_DisplayData); | ||
| 1149 | initializeParams.parameterBufferSize = SCE_GXM_DEFAULT_PARAMETER_BUFFER_SIZE; | ||
| 1150 | sceGxmInitialize(&initializeParams); | ||
| 1151 | } | ||
| 1152 | |||
| 1153 | void gxm_minimal_term_for_common_dialog(void) | ||
| 1154 | { | ||
| 1155 | sceGxmTerminate(); | ||
| 1156 | } | ||
| 1157 | |||
| 1158 | void gxm_init_for_common_dialog(void) | ||
| 1159 | { | ||
| 1160 | for (int i = 0; i < VITA_GXM_BUFFERS; i += 1) { | ||
| 1161 | buffer_for_common_dialog[i].displayData.wait_vblank = true; | ||
| 1162 | buffer_for_common_dialog[i].displayData.address = vita_mem_alloc( | ||
| 1163 | SCE_KERNEL_MEMBLOCK_TYPE_USER_MAIN_PHYCONT_NC_RW, | ||
| 1164 | 4 * VITA_GXM_SCREEN_STRIDE * VITA_GXM_SCREEN_HEIGHT, | ||
| 1165 | SCE_GXM_COLOR_SURFACE_ALIGNMENT, | ||
| 1166 | SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE, | ||
| 1167 | &buffer_for_common_dialog[i].uid); | ||
| 1168 | sceGxmColorSurfaceInit( | ||
| 1169 | &buffer_for_common_dialog[i].surf, | ||
| 1170 | VITA_GXM_PIXEL_FORMAT, | ||
| 1171 | SCE_GXM_COLOR_SURFACE_LINEAR, | ||
| 1172 | SCE_GXM_COLOR_SURFACE_SCALE_NONE, | ||
| 1173 | SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT, | ||
| 1174 | VITA_GXM_SCREEN_WIDTH, | ||
| 1175 | VITA_GXM_SCREEN_HEIGHT, | ||
| 1176 | VITA_GXM_SCREEN_STRIDE, | ||
| 1177 | buffer_for_common_dialog[i].displayData.address); | ||
| 1178 | sceGxmSyncObjectCreate(&buffer_for_common_dialog[i].sync); | ||
| 1179 | } | ||
| 1180 | sceGxmDisplayQueueFinish(); | ||
| 1181 | } | ||
| 1182 | |||
| 1183 | void gxm_swap_for_common_dialog(void) | ||
| 1184 | { | ||
| 1185 | SceCommonDialogUpdateParam updateParam; | ||
| 1186 | SDL_zero(updateParam); | ||
| 1187 | updateParam.renderTarget.colorFormat = VITA_GXM_PIXEL_FORMAT; | ||
| 1188 | updateParam.renderTarget.surfaceType = SCE_GXM_COLOR_SURFACE_LINEAR; | ||
| 1189 | updateParam.renderTarget.width = VITA_GXM_SCREEN_WIDTH; | ||
| 1190 | updateParam.renderTarget.height = VITA_GXM_SCREEN_HEIGHT; | ||
| 1191 | updateParam.renderTarget.strideInPixels = VITA_GXM_SCREEN_STRIDE; | ||
| 1192 | |||
| 1193 | updateParam.renderTarget.colorSurfaceData = buffer_for_common_dialog[back_buffer_index_for_common_dialog].displayData.address; | ||
| 1194 | |||
| 1195 | updateParam.displaySyncObject = buffer_for_common_dialog[back_buffer_index_for_common_dialog].sync; | ||
| 1196 | SDL_memset(buffer_for_common_dialog[back_buffer_index_for_common_dialog].displayData.address, 0, 4 * VITA_GXM_SCREEN_STRIDE * VITA_GXM_SCREEN_HEIGHT); | ||
| 1197 | sceCommonDialogUpdate(&updateParam); | ||
| 1198 | |||
| 1199 | sceGxmDisplayQueueAddEntry(buffer_for_common_dialog[front_buffer_index_for_common_dialog].sync, buffer_for_common_dialog[back_buffer_index_for_common_dialog].sync, &buffer_for_common_dialog[back_buffer_index_for_common_dialog].displayData); | ||
| 1200 | front_buffer_index_for_common_dialog = back_buffer_index_for_common_dialog; | ||
| 1201 | back_buffer_index_for_common_dialog = (back_buffer_index_for_common_dialog + 1) % VITA_GXM_BUFFERS; | ||
| 1202 | } | ||
| 1203 | |||
| 1204 | void gxm_term_for_common_dialog(void) | ||
| 1205 | { | ||
| 1206 | sceGxmDisplayQueueFinish(); | ||
| 1207 | for (int i = 0; i < VITA_GXM_BUFFERS; i += 1) { | ||
| 1208 | vita_mem_free(buffer_for_common_dialog[i].uid); | ||
| 1209 | sceGxmSyncObjectDestroy(buffer_for_common_dialog[i].sync); | ||
| 1210 | } | ||
| 1211 | } | ||
| 1212 | |||
| 1213 | #endif // SDL_VIDEO_RENDER_VITA_GXM | ||
diff --git a/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_tools.h b/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_tools.h new file mode 100644 index 0000000..023f859 --- /dev/null +++ b/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_tools.h | |||
| @@ -0,0 +1,63 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
| 4 | |||
| 5 | This software is provided 'as-is', without any express or implied | ||
| 6 | warranty. In no event will the authors be held liable for any damages | ||
| 7 | arising from the use of this software. | ||
| 8 | |||
| 9 | Permission is granted to anyone to use this software for any purpose, | ||
| 10 | including commercial applications, and to alter it and redistribute it | ||
| 11 | freely, subject to the following restrictions: | ||
| 12 | |||
| 13 | 1. The origin of this software must not be misrepresented; you must not | ||
| 14 | claim that you wrote the original software. If you use this software | ||
| 15 | in a product, an acknowledgment in the product documentation would be | ||
| 16 | appreciated but is not required. | ||
| 17 | 2. Altered source versions must be plainly marked as such, and must not be | ||
| 18 | misrepresented as being the original software. | ||
| 19 | 3. This notice may not be removed or altered from any source distribution. | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifndef SDL_RENDER_VITA_GXM_TOOLS_H | ||
| 23 | #define SDL_RENDER_VITA_GXM_TOOLS_H | ||
| 24 | |||
| 25 | #include "SDL_internal.h" | ||
| 26 | |||
| 27 | #include "../SDL_sysrender.h" | ||
| 28 | |||
| 29 | #include <psp2/kernel/processmgr.h> | ||
| 30 | #include <psp2/appmgr.h> | ||
| 31 | #include <psp2/display.h> | ||
| 32 | #include <psp2/gxm.h> | ||
| 33 | #include <psp2/types.h> | ||
| 34 | #include <psp2/kernel/sysmem.h> | ||
| 35 | |||
| 36 | #include "SDL_render_vita_gxm_types.h" | ||
| 37 | |||
| 38 | void init_orthographic_matrix(float *m, float left, float right, float bottom, float top, float near, float far); | ||
| 39 | |||
| 40 | void *pool_malloc(VITA_GXM_RenderData *data, unsigned int size); | ||
| 41 | void *pool_memalign(VITA_GXM_RenderData *data, unsigned int size, unsigned int alignment); | ||
| 42 | |||
| 43 | void set_clip_rectangle(VITA_GXM_RenderData *data, int x_min, int y_min, int x_max, int y_max); | ||
| 44 | void unset_clip_rectangle(VITA_GXM_RenderData *data); | ||
| 45 | |||
| 46 | int gxm_init(SDL_Renderer *renderer); | ||
| 47 | void gxm_finish(SDL_Renderer *renderer); | ||
| 48 | |||
| 49 | 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); | ||
| 50 | void free_gxm_texture(VITA_GXM_RenderData *data, gxm_texture *texture); | ||
| 51 | |||
| 52 | void gxm_texture_set_filters(gxm_texture *texture, SceGxmTextureFilter min_filter, SceGxmTextureFilter mag_filter); | ||
| 53 | SceGxmTextureFormat gxm_texture_get_format(const gxm_texture *texture); | ||
| 54 | |||
| 55 | void *gxm_texture_get_datap(const gxm_texture *texture); | ||
| 56 | |||
| 57 | void gxm_minimal_init_for_common_dialog(void); | ||
| 58 | void gxm_minimal_term_for_common_dialog(void); | ||
| 59 | void gxm_init_for_common_dialog(void); | ||
| 60 | void gxm_swap_for_common_dialog(void); | ||
| 61 | void gxm_term_for_common_dialog(void); | ||
| 62 | |||
| 63 | #endif // SDL_RENDER_VITA_GXM_TOOLS_H | ||
diff --git a/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_types.h b/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_types.h new file mode 100644 index 0000000..19962c7 --- /dev/null +++ b/SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_types.h | |||
| @@ -0,0 +1,210 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
| 4 | |||
| 5 | This software is provided 'as-is', without any express or implied | ||
| 6 | warranty. In no event will the authors be held liable for any damages | ||
| 7 | arising from the use of this software. | ||
| 8 | |||
| 9 | Permission is granted to anyone to use this software for any purpose, | ||
| 10 | including commercial applications, and to alter it and redistribute it | ||
| 11 | freely, subject to the following restrictions: | ||
| 12 | |||
| 13 | 1. The origin of this software must not be misrepresented; you must not | ||
| 14 | claim that you wrote the original software. If you use this software | ||
| 15 | in a product, an acknowledgment in the product documentation would be | ||
| 16 | appreciated but is not required. | ||
| 17 | 2. Altered source versions must be plainly marked as such, and must not be | ||
| 18 | misrepresented as being the original software. | ||
| 19 | 3. This notice may not be removed or altered from any source distribution. | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifndef SDL_RENDER_VITA_GXM_TYPES_H | ||
| 23 | #define SDL_RENDER_VITA_GXM_TYPES_H | ||
| 24 | |||
| 25 | #include "SDL_internal.h" | ||
| 26 | |||
| 27 | #include "../SDL_sysrender.h" | ||
| 28 | |||
| 29 | #include <psp2/kernel/processmgr.h> | ||
| 30 | #include <psp2/appmgr.h> | ||
| 31 | #include <psp2/display.h> | ||
| 32 | #include <psp2/gxm.h> | ||
| 33 | #include <psp2/types.h> | ||
| 34 | #include <psp2/kernel/sysmem.h> | ||
| 35 | #include <psp2/kernel/clib.h> | ||
| 36 | |||
| 37 | #include <string.h> | ||
| 38 | |||
| 39 | #define VITA_GXM_SCREEN_WIDTH 960 | ||
| 40 | #define VITA_GXM_SCREEN_HEIGHT 544 | ||
| 41 | #define VITA_GXM_SCREEN_STRIDE 960 | ||
| 42 | |||
| 43 | #define VITA_GXM_COLOR_FORMAT SCE_GXM_COLOR_FORMAT_A8B8G8R8 | ||
| 44 | #define VITA_GXM_PIXEL_FORMAT SCE_DISPLAY_PIXELFORMAT_A8B8G8R8 | ||
| 45 | |||
| 46 | #define VITA_GXM_BUFFERS 3 | ||
| 47 | #define VITA_GXM_PENDING_SWAPS 2 | ||
| 48 | #define VITA_GXM_POOL_SIZE 2 * 1024 * 1024 | ||
| 49 | |||
| 50 | typedef struct | ||
| 51 | { | ||
| 52 | void *address; | ||
| 53 | Uint8 wait_vblank; | ||
| 54 | } VITA_GXM_DisplayData; | ||
| 55 | |||
| 56 | typedef struct clear_vertex | ||
| 57 | { | ||
| 58 | float x; | ||
| 59 | float y; | ||
| 60 | } clear_vertex; | ||
| 61 | |||
| 62 | typedef struct color_vertex | ||
| 63 | { | ||
| 64 | float x; | ||
| 65 | float y; | ||
| 66 | SDL_FColor color; | ||
| 67 | } color_vertex; | ||
| 68 | |||
| 69 | typedef struct texture_vertex | ||
| 70 | { | ||
| 71 | float x; | ||
| 72 | float y; | ||
| 73 | float u; | ||
| 74 | float v; | ||
| 75 | SDL_FColor color; | ||
| 76 | } texture_vertex; | ||
| 77 | |||
| 78 | typedef struct gxm_texture | ||
| 79 | { | ||
| 80 | SceGxmTexture gxm_tex; | ||
| 81 | SceUID data_UID; | ||
| 82 | SceGxmRenderTarget *gxm_rendertarget; | ||
| 83 | SceGxmColorSurface gxm_colorsurface; | ||
| 84 | SceGxmDepthStencilSurface gxm_depthstencil; | ||
| 85 | SceUID depth_UID; | ||
| 86 | bool cdram; | ||
| 87 | } gxm_texture; | ||
| 88 | |||
| 89 | typedef struct fragment_programs | ||
| 90 | { | ||
| 91 | SceGxmFragmentProgram *color; | ||
| 92 | SceGxmFragmentProgram *texture; | ||
| 93 | } fragment_programs; | ||
| 94 | |||
| 95 | typedef struct blend_fragment_programs | ||
| 96 | { | ||
| 97 | fragment_programs blend_mode_none; | ||
| 98 | fragment_programs blend_mode_blend; | ||
| 99 | fragment_programs blend_mode_add; | ||
| 100 | fragment_programs blend_mode_mod; | ||
| 101 | fragment_programs blend_mode_mul; | ||
| 102 | } blend_fragment_programs; | ||
| 103 | |||
| 104 | typedef struct | ||
| 105 | { | ||
| 106 | SDL_Rect viewport; | ||
| 107 | bool viewport_dirty; | ||
| 108 | SDL_Texture *texture; | ||
| 109 | SDL_Texture *target; | ||
| 110 | SDL_FColor color; | ||
| 111 | SceGxmFragmentProgram *fragment_program; | ||
| 112 | SceGxmVertexProgram *vertex_program; | ||
| 113 | int last_command; | ||
| 114 | |||
| 115 | bool cliprect_enabled_dirty; | ||
| 116 | bool cliprect_enabled; | ||
| 117 | bool cliprect_dirty; | ||
| 118 | SDL_Rect cliprect; | ||
| 119 | bool texturing; | ||
| 120 | int drawablew; | ||
| 121 | int drawableh; | ||
| 122 | } gxm_drawstate_cache; | ||
| 123 | |||
| 124 | typedef struct | ||
| 125 | { | ||
| 126 | bool initialized; | ||
| 127 | bool drawing; | ||
| 128 | |||
| 129 | unsigned int psm; | ||
| 130 | unsigned int bpp; | ||
| 131 | |||
| 132 | int currentBlendMode; | ||
| 133 | |||
| 134 | VITA_GXM_DisplayData displayData; | ||
| 135 | |||
| 136 | SceUID vdmRingBufferUid; | ||
| 137 | SceUID vertexRingBufferUid; | ||
| 138 | SceUID fragmentRingBufferUid; | ||
| 139 | SceUID fragmentUsseRingBufferUid; | ||
| 140 | SceGxmContextParams contextParams; | ||
| 141 | SceGxmContext *gxm_context; | ||
| 142 | SceGxmRenderTarget *renderTarget; | ||
| 143 | SceUID displayBufferUid[VITA_GXM_BUFFERS]; | ||
| 144 | void *displayBufferData[VITA_GXM_BUFFERS]; | ||
| 145 | SceGxmColorSurface displaySurface[VITA_GXM_BUFFERS]; | ||
| 146 | SceGxmSyncObject *displayBufferSync[VITA_GXM_BUFFERS]; | ||
| 147 | |||
| 148 | SceUID depthBufferUid; | ||
| 149 | SceUID stencilBufferUid; | ||
| 150 | SceGxmDepthStencilSurface depthSurface; | ||
| 151 | void *depthBufferData; | ||
| 152 | void *stencilBufferData; | ||
| 153 | |||
| 154 | unsigned int backBufferIndex; | ||
| 155 | unsigned int frontBufferIndex; | ||
| 156 | |||
| 157 | void *pool_addr[2]; | ||
| 158 | SceUID poolUid[2]; | ||
| 159 | unsigned int pool_index; | ||
| 160 | unsigned int current_pool; | ||
| 161 | |||
| 162 | float ortho_matrix[4 * 4]; | ||
| 163 | |||
| 164 | SceGxmVertexProgram *colorVertexProgram; | ||
| 165 | SceGxmFragmentProgram *colorFragmentProgram; | ||
| 166 | SceGxmVertexProgram *textureVertexProgram; | ||
| 167 | SceGxmFragmentProgram *textureFragmentProgram; | ||
| 168 | SceGxmProgramParameter *clearClearColorParam; | ||
| 169 | SceGxmProgramParameter *colorWvpParam; | ||
| 170 | SceGxmProgramParameter *textureWvpParam; | ||
| 171 | |||
| 172 | SceGxmShaderPatcher *shaderPatcher; | ||
| 173 | SceGxmVertexProgram *clearVertexProgram; | ||
| 174 | SceGxmFragmentProgram *clearFragmentProgram; | ||
| 175 | |||
| 176 | SceGxmShaderPatcherId clearVertexProgramId; | ||
| 177 | SceGxmShaderPatcherId clearFragmentProgramId; | ||
| 178 | SceGxmShaderPatcherId colorVertexProgramId; | ||
| 179 | SceGxmShaderPatcherId colorFragmentProgramId; | ||
| 180 | SceGxmShaderPatcherId textureVertexProgramId; | ||
| 181 | SceGxmShaderPatcherId textureFragmentProgramId; | ||
| 182 | |||
| 183 | SceUID patcherBufferUid; | ||
| 184 | SceUID patcherVertexUsseUid; | ||
| 185 | SceUID patcherFragmentUsseUid; | ||
| 186 | |||
| 187 | SceUID clearVerticesUid; | ||
| 188 | SceUID linearIndicesUid; | ||
| 189 | clear_vertex *clearVertices; | ||
| 190 | uint16_t *linearIndices; | ||
| 191 | |||
| 192 | blend_fragment_programs blendFragmentPrograms; | ||
| 193 | |||
| 194 | gxm_drawstate_cache drawstate; | ||
| 195 | SceClibMspace texturePool; | ||
| 196 | SceUID texturePoolUID; | ||
| 197 | } VITA_GXM_RenderData; | ||
| 198 | |||
| 199 | typedef struct | ||
| 200 | { | ||
| 201 | gxm_texture *tex; | ||
| 202 | unsigned int pitch; | ||
| 203 | unsigned int w; | ||
| 204 | unsigned int h; | ||
| 205 | float wscale; | ||
| 206 | bool yuv; | ||
| 207 | bool nv12; | ||
| 208 | } VITA_GXM_TextureData; | ||
| 209 | |||
| 210 | #endif // SDL_RENDER_VITA_GXM_TYPES_H | ||
diff --git a/SDL-3.2.8/src/render/vitagxm/shader_src/clear_f.cg b/SDL-3.2.8/src/render/vitagxm/shader_src/clear_f.cg new file mode 100644 index 0000000..6d8fb3b --- /dev/null +++ b/SDL-3.2.8/src/render/vitagxm/shader_src/clear_f.cg | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | float4 main( uniform float4 uClearColor) : COLOR | ||
| 2 | { | ||
| 3 | return uClearColor; | ||
| 4 | } | ||
diff --git a/SDL-3.2.8/src/render/vitagxm/shader_src/clear_v.cg b/SDL-3.2.8/src/render/vitagxm/shader_src/clear_v.cg new file mode 100644 index 0000000..ee5aa9f --- /dev/null +++ b/SDL-3.2.8/src/render/vitagxm/shader_src/clear_v.cg | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | float4 main(float2 aPosition) : POSITION | ||
| 2 | { | ||
| 3 | return float4(aPosition, 1.f, 1.f); | ||
| 4 | } | ||
diff --git a/SDL-3.2.8/src/render/vitagxm/shader_src/color_f.cg b/SDL-3.2.8/src/render/vitagxm/shader_src/color_f.cg new file mode 100644 index 0000000..dc87c2a --- /dev/null +++ b/SDL-3.2.8/src/render/vitagxm/shader_src/color_f.cg | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | float4 main(float4 vColor : COLOR) | ||
| 2 | { | ||
| 3 | return vColor; | ||
| 4 | } | ||
diff --git a/SDL-3.2.8/src/render/vitagxm/shader_src/color_v.cg b/SDL-3.2.8/src/render/vitagxm/shader_src/color_v.cg new file mode 100644 index 0000000..4966099 --- /dev/null +++ b/SDL-3.2.8/src/render/vitagxm/shader_src/color_v.cg | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | void main( | ||
| 2 | float2 aPosition, | ||
| 3 | float4 aColor, | ||
| 4 | uniform float4x4 wvp, | ||
| 5 | out float4 vPosition : POSITION, | ||
| 6 | out float4 vColor : COLOR, | ||
| 7 | out float pSize : PSIZE | ||
| 8 | ) | ||
| 9 | { | ||
| 10 | vPosition = mul(float4(aPosition, 1.f, 0.5f), wvp); | ||
| 11 | vColor = aColor; | ||
| 12 | pSize = 1.f; | ||
| 13 | } | ||
diff --git a/SDL-3.2.8/src/render/vitagxm/shader_src/texture_f.cg b/SDL-3.2.8/src/render/vitagxm/shader_src/texture_f.cg new file mode 100644 index 0000000..a1f63b8 --- /dev/null +++ b/SDL-3.2.8/src/render/vitagxm/shader_src/texture_f.cg | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | float4 main(float2 vTexcoord : TEXCOORD0, float4 vColor : COLOR, uniform sampler2D tex) | ||
| 2 | { | ||
| 3 | return tex2D(tex, vTexcoord) * vColor; | ||
| 4 | } | ||
diff --git a/SDL-3.2.8/src/render/vitagxm/shader_src/texture_v.cg b/SDL-3.2.8/src/render/vitagxm/shader_src/texture_v.cg new file mode 100644 index 0000000..9e05e9a --- /dev/null +++ b/SDL-3.2.8/src/render/vitagxm/shader_src/texture_v.cg | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | void main( | ||
| 2 | float2 aPosition, | ||
| 3 | float2 aTexcoord, | ||
| 4 | float4 aColor, | ||
| 5 | uniform float4x4 wvp, | ||
| 6 | out float4 vPosition : POSITION, | ||
| 7 | out float4 vColor : COLOR, | ||
| 8 | out float2 vTexcoord : TEXCOORD0 | ||
| 9 | ) | ||
| 10 | { | ||
| 11 | vPosition = mul(float4(aPosition, 1.f, 0.5f), wvp); | ||
| 12 | vTexcoord = aTexcoord; | ||
| 13 | vColor = aColor; | ||
| 14 | } | ||
