summaryrefslogtreecommitdiff
path: root/SDL-3.2.8/src/render/vitagxm
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2026-03-06 13:26:57 -0800
committer3gg <3gg@shellblade.net>2026-03-06 13:26:57 -0800
commitf5c89b3bd5d74849757fd5b4d1a300068522a3ca (patch)
treed6f6e4c81745b393d7594b334710f30c0b2df3bd /SDL-3.2.8/src/render/vitagxm
Initial commitHEADmain
Diffstat (limited to 'SDL-3.2.8/src/render/vitagxm')
-rw-r--r--SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm.c1198
-rw-r--r--SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_memory.c179
-rw-r--r--SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_memory.h42
-rw-r--r--SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_shaders.h282
-rw-r--r--SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_tools.c1213
-rw-r--r--SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_tools.h63
-rw-r--r--SDL-3.2.8/src/render/vitagxm/SDL_render_vita_gxm_types.h210
-rw-r--r--SDL-3.2.8/src/render/vitagxm/shader_src/clear_f.cg4
-rw-r--r--SDL-3.2.8/src/render/vitagxm/shader_src/clear_v.cg4
-rw-r--r--SDL-3.2.8/src/render/vitagxm/shader_src/color_f.cg4
-rw-r--r--SDL-3.2.8/src/render/vitagxm/shader_src/color_v.cg13
-rw-r--r--SDL-3.2.8/src/render/vitagxm/shader_src/texture_f.cg4
-rw-r--r--SDL-3.2.8/src/render/vitagxm/shader_src/texture_v.cg14
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
45static bool VITA_GXM_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props);
46
47static void VITA_GXM_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event);
48
49static bool VITA_GXM_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode);
50
51static bool VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props);
52
53static bool VITA_GXM_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
54 const SDL_Rect *rect, const void *pixels, int pitch);
55
56static 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
62static 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
67static bool VITA_GXM_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
68 const SDL_Rect *rect, void **pixels, int *pitch);
69
70static void VITA_GXM_UnlockTexture(SDL_Renderer *renderer,
71 SDL_Texture *texture);
72
73static void VITA_GXM_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode);
74
75static bool VITA_GXM_SetRenderTarget(SDL_Renderer *renderer,
76 SDL_Texture *texture);
77
78static bool VITA_GXM_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd);
79
80static bool VITA_GXM_QueueSetDrawColor(SDL_Renderer *renderer, SDL_RenderCommand *cmd);
81
82static bool VITA_GXM_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count);
83static bool VITA_GXM_QueueDrawLines(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count);
84
85static 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
90static bool VITA_GXM_RenderClear(SDL_Renderer *renderer, SDL_RenderCommand *cmd);
91
92static void VITA_GXM_InvalidateCachedState(SDL_Renderer *renderer);
93
94static bool VITA_GXM_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize);
95
96static SDL_Surface *VITA_GXM_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect);
97
98static bool VITA_GXM_RenderPresent(SDL_Renderer *renderer);
99static void VITA_GXM_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture);
100static void VITA_GXM_DestroyRenderer(SDL_Renderer *renderer);
101
102SDL_RenderDriver VITA_GXM_RenderDriver = {
103 VITA_GXM_CreateRenderer, "VITA gxm"
104};
105
106static 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
135void 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
183static 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
194static 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
263static void VITA_GXM_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event)
264{
265}
266
267static 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
273static 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
310static 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
335static 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
429static 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
503static 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
560static 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
578static 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
585static 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
604static bool VITA_GXM_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
605{
606 return true;
607}
608
609static 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
637static bool VITA_GXM_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
638{
639 return true;
640}
641
642static 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
654static 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
676static 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
701static 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
800static 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
830static 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
926static 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
931static 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
1058void 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
1082static 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
1114static 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
1156static 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
1182static 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
28void *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
57void 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
67void *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
104void vita_gpu_mem_free(VITA_GXM_RenderData *data, void *ptr)
105{
106 if (data->texturePool) {
107 sceClibMspaceFree(data->texturePool, ptr);
108 }
109}
110
111void 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
125void *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
142void 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
152void *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
169void 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
32void *vita_mem_alloc(unsigned int type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid);
33void vita_mem_free(SceUID uid);
34void *vita_gpu_mem_alloc(VITA_GXM_RenderData *data, unsigned int size);
35void vita_gpu_mem_free(VITA_GXM_RenderData *data, void *ptr);
36void vita_gpu_mem_destroy(VITA_GXM_RenderData *data);
37void *vita_mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset);
38void vita_mem_vertex_usse_free(SceUID uid);
39void *vita_mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset);
40void 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
30static 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
63static 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
99static 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
130static 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
180static 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
220static 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
275static const SceGxmProgram *const clearVertexProgramGxp = (const SceGxmProgram *)gxm_shader_clear_v;
276static const SceGxmProgram *const clearFragmentProgramGxp = (const SceGxmProgram *)gxm_shader_clear_f;
277static const SceGxmProgram *const colorVertexProgramGxp = (const SceGxmProgram *)gxm_shader_color_v;
278static const SceGxmProgram *const colorFragmentProgramGxp = (const SceGxmProgram *)gxm_shader_color_f;
279static const SceGxmProgram *const textureVertexProgramGxp = (const SceGxmProgram *)gxm_shader_texture_v;
280static 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
46void 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
69static 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
76static void patcher_host_free(void *user_data, void *mem)
77{
78 (void)user_data;
79 SDL_free(mem);
80}
81
82void *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
94void *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
106static 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
136static 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
155static 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
161static 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
195static 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
243void 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
282void 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
294int 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
859void 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
934void 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
952SceGxmTextureFormat
953gxm_texture_get_format(const gxm_texture *texture)
954{
955 return sceGxmTextureGetFormat(&texture->gxm_tex);
956}
957
958void *gxm_texture_get_datap(const gxm_texture *texture)
959{
960 return sceGxmTextureGetData(&texture->gxm_tex);
961}
962
963static 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
983gxm_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
1125void 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
1131static unsigned int back_buffer_index_for_common_dialog = 0;
1132static unsigned int front_buffer_index_for_common_dialog = 0;
1133struct
1134{
1135 VITA_GXM_DisplayData displayData;
1136 SceGxmSyncObject *sync;
1137 SceGxmColorSurface surf;
1138 SceUID uid;
1139} buffer_for_common_dialog[VITA_GXM_BUFFERS];
1140
1141void 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
1153void gxm_minimal_term_for_common_dialog(void)
1154{
1155 sceGxmTerminate();
1156}
1157
1158void 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
1183void 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
1204void 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
38void init_orthographic_matrix(float *m, float left, float right, float bottom, float top, float near, float far);
39
40void *pool_malloc(VITA_GXM_RenderData *data, unsigned int size);
41void *pool_memalign(VITA_GXM_RenderData *data, unsigned int size, unsigned int alignment);
42
43void set_clip_rectangle(VITA_GXM_RenderData *data, int x_min, int y_min, int x_max, int y_max);
44void unset_clip_rectangle(VITA_GXM_RenderData *data);
45
46int gxm_init(SDL_Renderer *renderer);
47void gxm_finish(SDL_Renderer *renderer);
48
49gxm_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);
50void free_gxm_texture(VITA_GXM_RenderData *data, gxm_texture *texture);
51
52void gxm_texture_set_filters(gxm_texture *texture, SceGxmTextureFilter min_filter, SceGxmTextureFilter mag_filter);
53SceGxmTextureFormat gxm_texture_get_format(const gxm_texture *texture);
54
55void *gxm_texture_get_datap(const gxm_texture *texture);
56
57void gxm_minimal_init_for_common_dialog(void);
58void gxm_minimal_term_for_common_dialog(void);
59void gxm_init_for_common_dialog(void);
60void gxm_swap_for_common_dialog(void);
61void 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
50typedef struct
51{
52 void *address;
53 Uint8 wait_vblank;
54} VITA_GXM_DisplayData;
55
56typedef struct clear_vertex
57{
58 float x;
59 float y;
60} clear_vertex;
61
62typedef struct color_vertex
63{
64 float x;
65 float y;
66 SDL_FColor color;
67} color_vertex;
68
69typedef struct texture_vertex
70{
71 float x;
72 float y;
73 float u;
74 float v;
75 SDL_FColor color;
76} texture_vertex;
77
78typedef 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
89typedef struct fragment_programs
90{
91 SceGxmFragmentProgram *color;
92 SceGxmFragmentProgram *texture;
93} fragment_programs;
94
95typedef 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
104typedef 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
124typedef 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
199typedef 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 @@
1float4 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 @@
1float4 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 @@
1float4 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 @@
1void 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 @@
1float4 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 @@
1void 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}