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 }