1 #include <psp2/kernel/sysmem.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <math.h>
5 #include "../include/vita2d.h"
6 #include "../include/utils.h"
7 #include "../include/shared.h"
8
9 #define GXM_TEX_MAX_SIZE 4096
10 static SceKernelMemBlockType MemBlockType = SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW;
11
tex_format_to_bytespp(SceGxmTextureFormat format)12 static int tex_format_to_bytespp(SceGxmTextureFormat format)
13 {
14 switch (format & 0x9f000000U) {
15 case SCE_GXM_TEXTURE_BASE_FORMAT_U8:
16 case SCE_GXM_TEXTURE_BASE_FORMAT_S8:
17 case SCE_GXM_TEXTURE_BASE_FORMAT_P8:
18 return 1;
19 case SCE_GXM_TEXTURE_BASE_FORMAT_U4U4U4U4:
20 case SCE_GXM_TEXTURE_BASE_FORMAT_U8U3U3U2:
21 case SCE_GXM_TEXTURE_BASE_FORMAT_U1U5U5U5:
22 case SCE_GXM_TEXTURE_BASE_FORMAT_U5U6U5:
23 case SCE_GXM_TEXTURE_BASE_FORMAT_S5S5U6:
24 case SCE_GXM_TEXTURE_BASE_FORMAT_U8U8:
25 case SCE_GXM_TEXTURE_BASE_FORMAT_S8S8:
26 return 2;
27 case SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8:
28 case SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8:
29 return 3;
30 case SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8U8:
31 case SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8S8:
32 case SCE_GXM_TEXTURE_BASE_FORMAT_F32:
33 case SCE_GXM_TEXTURE_BASE_FORMAT_U32:
34 case SCE_GXM_TEXTURE_BASE_FORMAT_S32:
35 default:
36 return 4;
37 }
38 }
39
vita2d_texture_set_alloc_memblock_type(SceKernelMemBlockType type)40 void vita2d_texture_set_alloc_memblock_type(SceKernelMemBlockType type)
41 {
42 MemBlockType = (type == 0) ? SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW : type;
43 }
44
vita2d_texture_get_alloc_memblock_type()45 SceKernelMemBlockType vita2d_texture_get_alloc_memblock_type()
46 {
47 return MemBlockType;
48 }
49
vita2d_create_empty_texture(unsigned int w,unsigned int h)50 vita2d_texture *vita2d_create_empty_texture(unsigned int w, unsigned int h)
51 {
52 return vita2d_create_empty_texture_format(w, h, SCE_GXM_TEXTURE_FORMAT_A8B8G8R8);
53 }
54
_vita2d_create_empty_texture_format_advanced(unsigned int w,unsigned int h,SceGxmTextureFormat format,unsigned int isRenderTarget)55 static vita2d_texture *_vita2d_create_empty_texture_format_advanced(unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget)
56 {
57 if (w > GXM_TEX_MAX_SIZE || h > GXM_TEX_MAX_SIZE)
58 return NULL;
59
60 vita2d_texture *texture = malloc(sizeof(*texture));
61 if (!texture)
62 return NULL;
63
64 memset(texture, 0, sizeof(vita2d_texture));
65
66 const int tex_size = w * h * tex_format_to_bytespp(format);
67
68 /* Allocate a GPU buffer for the texture */
69 void *texture_data = gpu_alloc(
70 MemBlockType,
71 tex_size,
72 SCE_GXM_TEXTURE_ALIGNMENT,
73 SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
74 &texture->data_UID);
75
76 if (!texture_data) {
77 free(texture);
78 return NULL;
79 }
80
81 /* Clear the texture */
82 memset(texture_data, 0, tex_size);
83
84 /* Create the gxm texture */
85 sceGxmTextureInitLinear(
86 &texture->gxm_tex,
87 texture_data,
88 format,
89 w,
90 h,
91 0);
92
93 if ((format & 0x9f000000U) == SCE_GXM_TEXTURE_BASE_FORMAT_P8) {
94
95 const int pal_size = 256 * sizeof(uint32_t);
96
97 void *texture_palette = gpu_alloc(
98 MemBlockType,
99 pal_size,
100 SCE_GXM_PALETTE_ALIGNMENT,
101 SCE_GXM_MEMORY_ATTRIB_READ,
102 &texture->palette_UID);
103
104 if (!texture_palette) {
105 texture->palette_UID = 0;
106 vita2d_free_texture(texture);
107 return NULL;
108 }
109
110 memset(texture_palette, 0, pal_size);
111
112 sceGxmTextureSetPalette(&texture->gxm_tex, texture_palette);
113 } else {
114 texture->palette_UID = 0;
115 }
116
117 if (isRenderTarget) {
118
119 int err = sceGxmColorSurfaceInit(
120 &texture->gxm_sfc,
121 SCE_GXM_COLOR_FORMAT_A8B8G8R8,
122 SCE_GXM_COLOR_SURFACE_LINEAR,
123 SCE_GXM_COLOR_SURFACE_SCALE_NONE,
124 SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT,
125 w,
126 h,
127 w,
128 texture_data
129 );
130
131 if (err < 0) {
132 vita2d_free_texture(texture);
133 return NULL;
134 }
135
136 // create the depth/stencil surface
137 const uint32_t alignedWidth = ALIGN(w, SCE_GXM_TILE_SIZEX);
138 const uint32_t alignedHeight = ALIGN(h, SCE_GXM_TILE_SIZEY);
139 uint32_t sampleCount = alignedWidth*alignedHeight;
140 uint32_t depthStrideInSamples = alignedWidth;
141
142 // allocate it
143 void *depthBufferData = gpu_alloc(
144 SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
145 4*sampleCount,
146 SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT,
147 SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
148 &texture->depth_UID);
149
150 // create the SceGxmDepthStencilSurface structure
151 err = sceGxmDepthStencilSurfaceInit(
152 &texture->gxm_sfd,
153 SCE_GXM_DEPTH_STENCIL_FORMAT_S8D24,
154 SCE_GXM_DEPTH_STENCIL_SURFACE_TILED,
155 depthStrideInSamples,
156 depthBufferData,
157 NULL);
158
159 if (err < 0) {
160 vita2d_free_texture(texture);
161 return NULL;
162 }
163
164 SceGxmRenderTarget *tgt = NULL;
165
166 // set up parameters
167 SceGxmRenderTargetParams renderTargetParams;
168 memset(&renderTargetParams, 0, sizeof(SceGxmRenderTargetParams));
169 renderTargetParams.flags = 0;
170 renderTargetParams.width = w;
171 renderTargetParams.height = h;
172 renderTargetParams.scenesPerFrame = 1;
173 renderTargetParams.multisampleMode = SCE_GXM_MULTISAMPLE_NONE;
174 renderTargetParams.multisampleLocations = 0;
175 renderTargetParams.driverMemBlock = -1;
176
177 // create the render target
178 err = sceGxmCreateRenderTarget(&renderTargetParams, &tgt);
179
180 texture->gxm_rtgt = tgt;
181
182 if (err < 0) {
183 vita2d_free_texture(texture);
184 return NULL;
185 }
186
187 }
188
189 return texture;
190 }
191
vita2d_create_empty_texture_format(unsigned int w,unsigned int h,SceGxmTextureFormat format)192 vita2d_texture * vita2d_create_empty_texture_format(unsigned int w, unsigned int h, SceGxmTextureFormat format)
193 {
194 return _vita2d_create_empty_texture_format_advanced(w, h, format, 0);
195 }
196
vita2d_create_empty_texture_rendertarget(unsigned int w,unsigned int h,SceGxmTextureFormat format)197 vita2d_texture * vita2d_create_empty_texture_rendertarget(unsigned int w, unsigned int h, SceGxmTextureFormat format)
198 {
199 return _vita2d_create_empty_texture_format_advanced(w, h, format, 1);
200 }
201
vita2d_free_texture(vita2d_texture * texture)202 void vita2d_free_texture(vita2d_texture *texture)
203 {
204 if (texture) {
205 if (texture->gxm_rtgt) {
206 sceGxmDestroyRenderTarget(texture->gxm_rtgt);
207 }
208 if (texture->depth_UID) {
209 gpu_free(texture->depth_UID);
210 }
211 if (texture->palette_UID) {
212 gpu_free(texture->palette_UID);
213 }
214 gpu_free(texture->data_UID);
215 free(texture);
216 }
217 }
218
vita2d_texture_get_width(const vita2d_texture * texture)219 unsigned int vita2d_texture_get_width(const vita2d_texture *texture)
220 {
221 return sceGxmTextureGetWidth(&texture->gxm_tex);
222 }
223
vita2d_texture_get_height(const vita2d_texture * texture)224 unsigned int vita2d_texture_get_height(const vita2d_texture *texture)
225 {
226 return sceGxmTextureGetHeight(&texture->gxm_tex);
227 }
228
vita2d_texture_get_stride(const vita2d_texture * texture)229 unsigned int vita2d_texture_get_stride(const vita2d_texture *texture)
230 {
231 return ((vita2d_texture_get_width(texture) + 7) & ~7)
232 * tex_format_to_bytespp(vita2d_texture_get_format(texture));
233 }
234
vita2d_texture_get_format(const vita2d_texture * texture)235 SceGxmTextureFormat vita2d_texture_get_format(const vita2d_texture *texture)
236 {
237 return sceGxmTextureGetFormat(&texture->gxm_tex);
238 }
239
vita2d_texture_get_datap(const vita2d_texture * texture)240 void *vita2d_texture_get_datap(const vita2d_texture *texture)
241 {
242 return sceGxmTextureGetData(&texture->gxm_tex);
243 }
244
vita2d_texture_get_palette(const vita2d_texture * texture)245 void *vita2d_texture_get_palette(const vita2d_texture *texture)
246 {
247 return sceGxmTextureGetPalette(&texture->gxm_tex);
248 }
249
vita2d_texture_get_min_filter(const vita2d_texture * texture)250 SceGxmTextureFilter vita2d_texture_get_min_filter(const vita2d_texture *texture)
251 {
252 return sceGxmTextureGetMinFilter(&texture->gxm_tex);
253 }
254
vita2d_texture_get_mag_filter(const vita2d_texture * texture)255 SceGxmTextureFilter vita2d_texture_get_mag_filter(const vita2d_texture *texture)
256 {
257 return sceGxmTextureGetMagFilter(&texture->gxm_tex);
258 }
259
vita2d_texture_set_filters(vita2d_texture * texture,SceGxmTextureFilter min_filter,SceGxmTextureFilter mag_filter)260 void vita2d_texture_set_filters(vita2d_texture *texture, SceGxmTextureFilter min_filter, SceGxmTextureFilter mag_filter)
261 {
262 sceGxmTextureSetMinFilter(&texture->gxm_tex, min_filter);
263 sceGxmTextureSetMagFilter(&texture->gxm_tex, mag_filter);
264 }
265
set_texture_program()266 static inline void set_texture_program()
267 {
268 sceGxmSetVertexProgram(_vita2d_context, _vita2d_textureVertexProgram);
269 sceGxmSetFragmentProgram(_vita2d_context, _vita2d_textureFragmentProgram);
270 }
271
set_texture_tint_program()272 static inline void set_texture_tint_program()
273 {
274 sceGxmSetVertexProgram(_vita2d_context, _vita2d_textureTintVertexProgram);
275 sceGxmSetFragmentProgram(_vita2d_context, _vita2d_textureTintFragmentProgram);
276 }
277
set_texture_wvp_uniform()278 static inline void set_texture_wvp_uniform()
279 {
280 void *vertex_wvp_buffer;
281 sceGxmReserveVertexDefaultUniformBuffer(_vita2d_context, &vertex_wvp_buffer);
282 sceGxmSetUniformDataF(vertex_wvp_buffer, _vita2d_textureWvpParam, 0, 16, _vita2d_ortho_matrix);
283 }
284
set_texture_tint_wvp_uniform()285 static inline void set_texture_tint_wvp_uniform()
286 {
287 void *vertex_wvp_buffer;
288 sceGxmReserveVertexDefaultUniformBuffer(_vita2d_context, &vertex_wvp_buffer);
289 sceGxmSetUniformDataF(vertex_wvp_buffer, _vita2d_textureTintWvpParam, 0, 16, _vita2d_ortho_matrix);
290 }
291
draw_texture_generic(const vita2d_texture * texture,float x,float y)292 static inline void draw_texture_generic(const vita2d_texture *texture, float x, float y)
293 {
294 vita2d_texture_vertex *vertices = (vita2d_texture_vertex *)vita2d_pool_memalign(
295 4 * sizeof(vita2d_texture_vertex), // 4 vertices
296 sizeof(vita2d_texture_vertex));
297
298 const float w = vita2d_texture_get_width(texture);
299 const float h = vita2d_texture_get_height(texture);
300
301 vertices[0].x = x;
302 vertices[0].y = y;
303 vertices[0].z = +0.5f;
304 vertices[0].u = 0.0f;
305 vertices[0].v = 0.0f;
306
307 vertices[1].x = x + w;
308 vertices[1].y = y;
309 vertices[1].z = +0.5f;
310 vertices[1].u = 1.0f;
311 vertices[1].v = 0.0f;
312
313 vertices[2].x = x;
314 vertices[2].y = y + h;
315 vertices[2].z = +0.5f;
316 vertices[2].u = 0.0f;
317 vertices[2].v = 1.0f;
318
319 vertices[3].x = x + w;
320 vertices[3].y = y + h;
321 vertices[3].z = +0.5f;
322 vertices[3].u = 1.0f;
323 vertices[3].v = 1.0f;
324
325 // Set the texture to the TEXUNIT0
326 sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
327
328 sceGxmSetVertexStream(_vita2d_context, 0, vertices);
329 sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
330 }
331
vita2d_draw_texture(const vita2d_texture * texture,float x,float y)332 void vita2d_draw_texture(const vita2d_texture *texture, float x, float y)
333 {
334 set_texture_program();
335 set_texture_wvp_uniform();
336 draw_texture_generic(texture, x, y);
337 }
338
vita2d_draw_texture_tint(const vita2d_texture * texture,float x,float y,unsigned int color)339 void vita2d_draw_texture_tint(const vita2d_texture *texture, float x, float y, unsigned int color)
340 {
341 set_texture_tint_program();
342 set_texture_wvp_uniform();
343 draw_texture_generic(texture, x, y);
344 }
345
vita2d_draw_texture_rotate(const vita2d_texture * texture,float x,float y,float rad)346 void vita2d_draw_texture_rotate(const vita2d_texture *texture, float x, float y, float rad)
347 {
348 vita2d_draw_texture_rotate_hotspot(texture, x, y, rad,
349 vita2d_texture_get_width(texture)/2.0f,
350 vita2d_texture_get_height(texture)/2.0f);
351 }
352
vita2d_draw_texture_tint_rotate(const vita2d_texture * texture,float x,float y,float rad,unsigned int color)353 void vita2d_draw_texture_tint_rotate(const vita2d_texture *texture, float x, float y, float rad, unsigned int color)
354 {
355 vita2d_draw_texture_tint_rotate_hotspot(texture, x, y, rad,
356 vita2d_texture_get_width(texture)/2.0f,
357 vita2d_texture_get_height(texture)/2.0f,
358 color);
359 }
360
draw_texture_rotate_hotspot_generic(const vita2d_texture * texture,float x,float y,float rad,float center_x,float center_y)361 static inline void draw_texture_rotate_hotspot_generic(const vita2d_texture *texture, float x, float y, float rad, float center_x, float center_y)
362 {
363 vita2d_texture_vertex *vertices = (vita2d_texture_vertex *)vita2d_pool_memalign(
364 4 * sizeof(vita2d_texture_vertex), // 4 vertices
365 sizeof(vita2d_texture_vertex));
366
367 const float w = vita2d_texture_get_width(texture);
368 const float h = vita2d_texture_get_height(texture);
369
370 vertices[0].x = -center_x;
371 vertices[0].y = -center_y;
372 vertices[0].z = +0.5f;
373 vertices[0].u = 0.0f;
374 vertices[0].v = 0.0f;
375
376 vertices[1].x = w - center_x;
377 vertices[1].y = -center_y;
378 vertices[1].z = +0.5f;
379 vertices[1].u = 1.0f;
380 vertices[1].v = 0.0f;
381
382 vertices[2].x = -center_x;
383 vertices[2].y = h - center_y;
384 vertices[2].z = +0.5f;
385 vertices[2].u = 0.0f;
386 vertices[2].v = 1.0f;
387
388 vertices[3].x = w - center_x;
389 vertices[3].y = h - center_y;
390 vertices[3].z = +0.5f;
391 vertices[3].u = 1.0f;
392 vertices[3].v = 1.0f;
393
394 float c = cosf(rad);
395 float s = sinf(rad);
396 int i;
397 for (i = 0; i < 4; ++i) { // Rotate and translate
398 float _x = vertices[i].x;
399 float _y = vertices[i].y;
400 vertices[i].x = _x*c - _y*s + x;
401 vertices[i].y = _x*s + _y*c + y;
402 }
403
404 // Set the texture to the TEXUNIT0
405 sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
406
407 sceGxmSetVertexStream(_vita2d_context, 0, vertices);
408 sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
409 }
410
vita2d_draw_texture_rotate_hotspot(const vita2d_texture * texture,float x,float y,float rad,float center_x,float center_y)411 void vita2d_draw_texture_rotate_hotspot(const vita2d_texture *texture, float x, float y, float rad, float center_x, float center_y)
412 {
413 set_texture_program();
414 set_texture_wvp_uniform();
415 draw_texture_rotate_hotspot_generic(texture, x, y, rad, center_x, center_y);
416 }
417
vita2d_draw_texture_tint_rotate_hotspot(const vita2d_texture * texture,float x,float y,float rad,float center_x,float center_y,unsigned int color)418 void vita2d_draw_texture_tint_rotate_hotspot(const vita2d_texture *texture, float x, float y, float rad, float center_x, float center_y, unsigned int color)
419 {
420 set_texture_tint_program();
421 set_texture_wvp_uniform();
422 draw_texture_rotate_hotspot_generic(texture, x, y, rad, center_x, center_y);
423 }
424
draw_texture_scale_generic(const vita2d_texture * texture,float x,float y,float x_scale,float y_scale)425 static inline void draw_texture_scale_generic(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale)
426 {
427 vita2d_texture_vertex *vertices = (vita2d_texture_vertex *)vita2d_pool_memalign(
428 4 * sizeof(vita2d_texture_vertex), // 4 vertices
429 sizeof(vita2d_texture_vertex));
430
431 const float w = x_scale * vita2d_texture_get_width(texture);
432 const float h = y_scale * vita2d_texture_get_height(texture);
433
434 vertices[0].x = x;
435 vertices[0].y = y;
436 vertices[0].z = +0.5f;
437 vertices[0].u = 0.0f;
438 vertices[0].v = 0.0f;
439
440 vertices[1].x = x + w;
441 vertices[1].y = y;
442 vertices[1].z = +0.5f;
443 vertices[1].u = 1.0f;
444 vertices[1].v = 0.0f;
445
446 vertices[2].x = x;
447 vertices[2].y = y + h;
448 vertices[2].z = +0.5f;
449 vertices[2].u = 0.0f;
450 vertices[2].v = 1.0f;
451
452 vertices[3].x = x + w;
453 vertices[3].y = y + h;
454 vertices[3].z = +0.5f;
455 vertices[3].u = 1.0f;
456 vertices[3].v = 1.0f;
457
458 // Set the texture to the TEXUNIT0
459 sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
460
461 sceGxmSetVertexStream(_vita2d_context, 0, vertices);
462 sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
463 }
464
draw_texture_tint_scale_generic(const vita2d_texture * texture,float x,float y,float x_scale,float y_scale,const float * color)465 static inline void draw_texture_tint_scale_generic(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, const float *color)
466 {
467 vita2d_texture_tint_vertex *vertices = (vita2d_texture_tint_vertex *)vita2d_pool_memalign(
468 4 * sizeof(vita2d_texture_tint_vertex), // 4 vertices
469 sizeof(vita2d_texture_tint_vertex));
470
471 const float w = x_scale * vita2d_texture_get_width(texture);
472 const float h = y_scale * vita2d_texture_get_height(texture);
473
474 vertices[0].x = x;
475 vertices[0].y = y;
476 vertices[0].z = +0.5f;
477 vertices[0].u = 0.0f;
478 vertices[0].v = 0.0f;
479
480 vertices[1].x = x + w;
481 vertices[1].y = y;
482 vertices[1].z = +0.5f;
483 vertices[1].u = 1.0f;
484 vertices[1].v = 0.0f;
485
486 vertices[2].x = x;
487 vertices[2].y = y + h;
488 vertices[2].z = +0.5f;
489 vertices[2].u = 0.0f;
490 vertices[2].v = 1.0f;
491
492 vertices[3].x = x + w;
493 vertices[3].y = y + h;
494 vertices[3].z = +0.5f;
495 vertices[3].u = 1.0f;
496 vertices[3].v = 1.0f;
497
498 for(int n = 0; n < 4; n++){
499 int k = (n + 2) % 4 ;
500 vertices[n].r = color[4*k+0];
501 vertices[n].g = color[4*k+1];
502 vertices[n].b = color[4*k+2];
503 vertices[n].a = color[4*k+3];
504 }
505
506 // Set the texture to the TEXUNIT0
507 sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
508
509 sceGxmSetVertexStream(_vita2d_context, 0, vertices);
510 sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
511 }
512
vita2d_draw_texture_scale(const vita2d_texture * texture,float x,float y,float x_scale,float y_scale)513 void vita2d_draw_texture_scale(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale)
514 {
515 set_texture_program();
516 set_texture_wvp_uniform();
517 draw_texture_scale_generic(texture, x, y, x_scale, y_scale);
518 }
519
vita2d_draw_texture_tint_scale(const vita2d_texture * texture,float x,float y,float x_scale,float y_scale,const float * color)520 void vita2d_draw_texture_tint_scale(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, const float *color)
521 {
522 set_texture_tint_program();
523 set_texture_tint_wvp_uniform();
524 draw_texture_tint_scale_generic(texture, x, y, x_scale, y_scale, color);
525 }
526
527
draw_texture_part_generic(const vita2d_texture * texture,float x,float y,float tex_x,float tex_y,float tex_w,float tex_h)528 static inline void draw_texture_part_generic(const vita2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h)
529 {
530 vita2d_texture_vertex *vertices = (vita2d_texture_vertex *)vita2d_pool_memalign(
531 4 * sizeof(vita2d_texture_vertex), // 4 vertices
532 sizeof(vita2d_texture_vertex));
533
534 const float w = vita2d_texture_get_width(texture);
535 const float h = vita2d_texture_get_height(texture);
536
537 const float u0 = tex_x/w;
538 const float v0 = tex_y/h;
539 const float u1 = (tex_x+tex_w)/w;
540 const float v1 = (tex_y+tex_h)/h;
541
542 vertices[0].x = x;
543 vertices[0].y = y;
544 vertices[0].z = +0.5f;
545 vertices[0].u = u0;
546 vertices[0].v = v0;
547
548 vertices[1].x = x + tex_w;
549 vertices[1].y = y;
550 vertices[1].z = +0.5f;
551 vertices[1].u = u1;
552 vertices[1].v = v0;
553
554 vertices[2].x = x;
555 vertices[2].y = y + tex_h;
556 vertices[2].z = +0.5f;
557 vertices[2].u = u0;
558 vertices[2].v = v1;
559
560 vertices[3].x = x + tex_w;
561 vertices[3].y = y + tex_h;
562 vertices[3].z = +0.5f;
563 vertices[3].u = u1;
564 vertices[3].v = v1;
565
566 // Set the texture to the TEXUNIT0
567 sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
568
569 sceGxmSetVertexStream(_vita2d_context, 0, vertices);
570 sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
571 }
572
vita2d_draw_texture_part(const vita2d_texture * texture,float x,float y,float tex_x,float tex_y,float tex_w,float tex_h)573 void vita2d_draw_texture_part(const vita2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h)
574 {
575 set_texture_program();
576 set_texture_wvp_uniform();
577 draw_texture_part_generic(texture, x, y, tex_x, tex_y, tex_w, tex_h);
578 }
579
vita2d_draw_texture_tint_part(const vita2d_texture * texture,float x,float y,float tex_x,float tex_y,float tex_w,float tex_h,unsigned int color)580 void vita2d_draw_texture_tint_part(const vita2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, unsigned int color)
581 {
582 set_texture_tint_program();
583 set_texture_wvp_uniform();
584 draw_texture_part_generic(texture, x, y, tex_x, tex_y, tex_w, tex_h);
585 }
586
draw_texture_part_scale_generic(const vita2d_texture * texture,float x,float y,float tex_x,float tex_y,float tex_w,float tex_h,float x_scale,float y_scale)587 static inline void draw_texture_part_scale_generic(const vita2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale)
588 {
589 vita2d_texture_vertex *vertices = (vita2d_texture_vertex *)vita2d_pool_memalign(
590 4 * sizeof(vita2d_texture_vertex), // 4 vertices
591 sizeof(vita2d_texture_vertex));
592
593 const float w = vita2d_texture_get_width(texture);
594 const float h = vita2d_texture_get_height(texture);
595
596 const float u0 = tex_x/w;
597 const float v0 = tex_y/h;
598 const float u1 = (tex_x+tex_w)/w;
599 const float v1 = (tex_y+tex_h)/h;
600
601 tex_w *= x_scale;
602 tex_h *= y_scale;
603
604 vertices[0].x = x;
605 vertices[0].y = y;
606 vertices[0].z = +0.5f;
607 vertices[0].u = u0;
608 vertices[0].v = v0;
609
610 vertices[1].x = x + tex_w;
611 vertices[1].y = y;
612 vertices[1].z = +0.5f;
613 vertices[1].u = u1;
614 vertices[1].v = v0;
615
616 vertices[2].x = x;
617 vertices[2].y = y + tex_h;
618 vertices[2].z = +0.5f;
619 vertices[2].u = u0;
620 vertices[2].v = v1;
621
622 vertices[3].x = x + tex_w;
623 vertices[3].y = y + tex_h;
624 vertices[3].z = +0.5f;
625 vertices[3].u = u1;
626 vertices[3].v = v1;
627
628 // Set the texture to the TEXUNIT0
629 sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
630
631 sceGxmSetVertexStream(_vita2d_context, 0, vertices);
632 sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
633 }
634
draw_texture_tint_part_scale_generic(const vita2d_texture * texture,float x,float y,float tex_x,float tex_y,float tex_w,float tex_h,float x_scale,float y_scale,unsigned int color)635 static inline void draw_texture_tint_part_scale_generic(const vita2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale, unsigned int color)
636 {
637 vita2d_texture_tint_vertex *vertices = (vita2d_texture_tint_vertex *)vita2d_pool_memalign(
638 4 * sizeof(vita2d_texture_tint_vertex), // 4 vertices
639 sizeof(vita2d_texture_tint_vertex));
640
641 const float w = vita2d_texture_get_width(texture);
642 const float h = vita2d_texture_get_height(texture);
643
644 const float u0 = tex_x/w;
645 const float v0 = tex_y/h;
646 const float u1 = (tex_x+tex_w)/w;
647 const float v1 = (tex_y+tex_h)/h;
648
649 tex_w *= x_scale;
650 tex_h *= y_scale;
651
652 vertices[0].x = x;
653 vertices[0].y = y;
654 vertices[0].z = +0.5f;
655 vertices[0].u = u0;
656 vertices[0].v = v0;
657
658 vertices[1].x = x + tex_w;
659 vertices[1].y = y;
660 vertices[1].z = +0.5f;
661 vertices[1].u = u1;
662 vertices[1].v = v0;
663
664 vertices[2].x = x;
665 vertices[2].y = y + tex_h;
666 vertices[2].z = +0.5f;
667 vertices[2].u = u0;
668 vertices[2].v = v1;
669
670 vertices[3].x = x + tex_w;
671 vertices[3].y = y + tex_h;
672 vertices[3].z = +0.5f;
673 vertices[3].u = u1;
674 vertices[3].v = v1;
675
676 for(int n = 0; n < 4; n++){
677 vertices[n].r = ((color >> 8*0) & 0xFF)/255.0f;
678 vertices[n].g = ((color >> 8*1) & 0xFF)/255.0f;
679 vertices[n].b = ((color >> 8*2) & 0xFF)/255.0f;
680 vertices[n].a = ((color >> 8*3) & 0xFF)/255.0f;
681 }
682
683 // Set the texture to the TEXUNIT0
684 sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
685
686 sceGxmSetVertexStream(_vita2d_context, 0, vertices);
687 sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
688 }
689
vita2d_draw_texture_part_scale(const vita2d_texture * texture,float x,float y,float tex_x,float tex_y,float tex_w,float tex_h,float x_scale,float y_scale)690 void vita2d_draw_texture_part_scale(const vita2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale)
691 {
692 set_texture_program();
693 set_texture_wvp_uniform();
694 draw_texture_part_scale_generic(texture, x, y, tex_x, tex_y, tex_w, tex_h, x_scale, y_scale);
695 }
696
vita2d_draw_texture_tint_part_scale(const vita2d_texture * texture,float x,float y,float tex_x,float tex_y,float tex_w,float tex_h,float x_scale,float y_scale,unsigned int color)697 void vita2d_draw_texture_tint_part_scale(const vita2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale, unsigned int color)
698 {
699 set_texture_tint_program();
700 set_texture_wvp_uniform();
701 draw_texture_tint_part_scale_generic(texture, x, y, tex_x, tex_y, tex_w, tex_h, x_scale, y_scale, color);
702 }
703
draw_texture_scale_rotate_hotspot_generic(const vita2d_texture * texture,float x,float y,float x_scale,float y_scale,float rad,float center_x,float center_y)704 static inline void draw_texture_scale_rotate_hotspot_generic(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, float rad, float center_x, float center_y)
705 {
706 vita2d_texture_vertex *vertices = (vita2d_texture_vertex *)vita2d_pool_memalign(
707 4 * sizeof(vita2d_texture_vertex), // 4 vertices
708 sizeof(vita2d_texture_vertex));
709
710 const float w = x_scale * vita2d_texture_get_width(texture);
711 const float h = y_scale * vita2d_texture_get_height(texture);
712 const float center_x_scaled = x_scale * center_x;
713 const float center_y_scaled = y_scale * center_y;
714
715 vertices[0].x = -center_x_scaled;
716 vertices[0].y = -center_y_scaled;
717 vertices[0].z = +0.5f;
718 vertices[0].u = 0.0f;
719 vertices[0].v = 0.0f;
720
721 vertices[1].x = -center_x_scaled + w;
722 vertices[1].y = -center_y_scaled;
723 vertices[1].z = +0.5f;
724 vertices[1].u = 1.0f;
725 vertices[1].v = 0.0f;
726
727 vertices[2].x = -center_x_scaled;
728 vertices[2].y = -center_y_scaled + h;
729 vertices[2].z = +0.5f;
730 vertices[2].u = 0.0f;
731 vertices[2].v = 1.0f;
732
733 vertices[3].x = -center_x_scaled + w;
734 vertices[3].y = -center_y_scaled + h;
735 vertices[3].z = +0.5f;
736 vertices[3].u = 1.0f;
737 vertices[3].v = 1.0f;
738
739 float c = cosf(rad);
740 float s = sinf(rad);
741 int i;
742 for (i = 0; i < 4; ++i) { // Rotate and translate
743 float _x = vertices[i].x;
744 float _y = vertices[i].y;
745 vertices[i].x = _x*c - _y*s + x + center_x_scaled;
746 vertices[i].y = _x*s + _y*c + y + center_y_scaled;
747 }
748
749 // Set the texture to the TEXUNIT0
750 sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
751
752 sceGxmSetVertexStream(_vita2d_context, 0, vertices);
753 sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
754 }
755
vita2d_draw_texture_scale_rotate_hotspot(const vita2d_texture * texture,float x,float y,float x_scale,float y_scale,float rad,float center_x,float center_y)756 void vita2d_draw_texture_scale_rotate_hotspot(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, float rad, float center_x, float center_y)
757 {
758 set_texture_program();
759 set_texture_wvp_uniform();
760 draw_texture_scale_rotate_hotspot_generic(texture, x, y, x_scale, y_scale,
761 rad, center_x, center_y);
762 }
763
vita2d_draw_texture_scale_rotate(const vita2d_texture * texture,float x,float y,float x_scale,float y_scale,float rad)764 void vita2d_draw_texture_scale_rotate(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, float rad)
765 {
766 vita2d_draw_texture_scale_rotate_hotspot(texture, x, y, x_scale, y_scale,
767 rad, vita2d_texture_get_width(texture)/2.0f,
768 vita2d_texture_get_height(texture)/2.0f);
769 }
770
vita2d_draw_texture_tint_scale_rotate_hotspot(const vita2d_texture * texture,float x,float y,float x_scale,float y_scale,float rad,float center_x,float center_y,unsigned int color)771 void vita2d_draw_texture_tint_scale_rotate_hotspot(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, float rad, float center_x, float center_y, unsigned int color)
772 {
773 set_texture_tint_program();
774 set_texture_wvp_uniform();
775 draw_texture_scale_rotate_hotspot_generic(texture, x, y, x_scale, y_scale,
776 rad, center_x, center_y);
777 }
778
vita2d_draw_texture_tint_scale_rotate(const vita2d_texture * texture,float x,float y,float x_scale,float y_scale,float rad,unsigned int color)779 void vita2d_draw_texture_tint_scale_rotate(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, float rad, unsigned int color)
780 {
781 vita2d_draw_texture_tint_scale_rotate_hotspot(texture, x, y, x_scale, y_scale,
782 rad, vita2d_texture_get_width(texture)/2.0f,
783 vita2d_texture_get_height(texture)/2.0f, color);
784 }
785
draw_texture_part_scale_rotate_generic(const vita2d_texture * texture,float x,float y,float tex_x,float tex_y,float tex_w,float tex_h,float x_scale,float y_scale,float rad)786 static inline void draw_texture_part_scale_rotate_generic(const vita2d_texture *texture, float x, float y,
787 float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale, float rad)
788 {
789 vita2d_texture_vertex *vertices = (vita2d_texture_vertex *)vita2d_pool_memalign(
790 4 * sizeof(vita2d_texture_vertex), // 4 vertices
791 sizeof(vita2d_texture_vertex));
792
793 const float w_full = vita2d_texture_get_width(texture);
794 const float h_full = vita2d_texture_get_height(texture);
795
796 const float w_half = (tex_w * x_scale) / 2.0f;
797 const float h_half = (tex_h * y_scale) / 2.0f;
798
799 const float u0 = tex_x / w_full;
800 const float v0 = tex_y / h_full;
801 const float u1 = (tex_x + tex_w) / w_full;
802 const float v1 = (tex_y + tex_h) / h_full;
803
804 vertices[0].x = -w_half;
805 vertices[0].y = -h_half;
806 vertices[0].z = +0.5f;
807 vertices[0].u = u0;
808 vertices[0].v = v0;
809
810 vertices[1].x = w_half;
811 vertices[1].y = -h_half;
812 vertices[1].z = +0.5f;
813 vertices[1].u = u1;
814 vertices[1].v = v0;
815
816 vertices[2].x = -w_half;
817 vertices[2].y = h_half;
818 vertices[2].z = +0.5f;
819 vertices[2].u = u0;
820 vertices[2].v = v1;
821
822 vertices[3].x = w_half;
823 vertices[3].y = h_half;
824 vertices[3].z = +0.5f;
825 vertices[3].u = u1;
826 vertices[3].v = v1;
827
828 const float c = cosf(rad);
829 const float s = sinf(rad);
830 int i;
831 for (i = 0; i < 4; ++i) { // Rotate and translate
832 float _x = vertices[i].x;
833 float _y = vertices[i].y;
834 vertices[i].x = _x*c - _y*s + x;
835 vertices[i].y = _x*s + _y*c + y;
836 }
837
838 // Set the texture to the TEXUNIT0
839 sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
840
841 sceGxmSetVertexStream(_vita2d_context, 0, vertices);
842 sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
843 }
844
vita2d_draw_texture_part_scale_rotate(const vita2d_texture * texture,float x,float y,float tex_x,float tex_y,float tex_w,float tex_h,float x_scale,float y_scale,float rad)845 void vita2d_draw_texture_part_scale_rotate(const vita2d_texture *texture, float x, float y,
846 float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale, float rad)
847 {
848 set_texture_program();
849 set_texture_wvp_uniform();
850 draw_texture_part_scale_rotate_generic(texture, x, y,
851 tex_x, tex_y, tex_w, tex_h, x_scale, y_scale, rad);
852 }
853
vita2d_draw_texture_part_tint_scale_rotate(const vita2d_texture * texture,float x,float y,float tex_x,float tex_y,float tex_w,float tex_h,float x_scale,float y_scale,float rad,unsigned int color)854 void vita2d_draw_texture_part_tint_scale_rotate(const vita2d_texture *texture, float x, float y,
855 float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale, float rad, unsigned int color)
856 {
857 set_texture_tint_program();
858 set_texture_wvp_uniform();
859 draw_texture_part_scale_rotate_generic(texture, x, y,
860 tex_x, tex_y, tex_w, tex_h, x_scale, y_scale, rad);
861 }
862
vita2d_draw_array_textured(const vita2d_texture * texture,SceGxmPrimitiveType mode,const vita2d_texture_vertex * vertices,size_t count,unsigned int color)863 void vita2d_draw_array_textured(const vita2d_texture *texture, SceGxmPrimitiveType mode, const vita2d_texture_vertex *vertices, size_t count, unsigned int color)
864 {
865 set_texture_tint_program();
866 set_texture_wvp_uniform();
867
868 sceGxmSetBackPolygonMode(_vita2d_context, SCE_GXM_POLYGON_MODE_TRIANGLE_FILL);
869
870 // Set the texture to the TEXUNIT0
871 sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
872
873 sceGxmSetVertexStream(_vita2d_context, 0, vertices);
874 sceGxmDraw(_vita2d_context, mode, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), count);
875 }
876
vita2d_draw_array_textured_mat(const vita2d_texture * texture,const vita2d_texture_tint_vertex * vertices,size_t count,float * mat)877 void vita2d_draw_array_textured_mat(const vita2d_texture *texture, const vita2d_texture_tint_vertex *vertices, size_t count, float *mat)
878 {
879 set_texture_tint_program();
880
881 void *vertex_wvp_buffer;
882 sceGxmReserveVertexDefaultUniformBuffer(_vita2d_context, &vertex_wvp_buffer);
883 sceGxmSetUniformDataF(vertex_wvp_buffer, _vita2d_textureWvpParam, 0, 16, mat);
884
885 // Set the texture to the TEXUNIT0
886 sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
887
888 sceGxmSetVertexStream(_vita2d_context, 0, vertices);
889 sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), count);
890 }