1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2016 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 #if SDL_VIDEO_RENDER_PSP
24
25 #include "SDL_hints.h"
26 #include "../SDL_sysrender.h"
27
28 #include <pspkernel.h>
29 #include <pspdisplay.h>
30 #include <pspgu.h>
31 #include <pspgum.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <math.h>
35 #include <pspge.h>
36 #include <stdarg.h>
37 #include <stdlib.h>
38 #include <vram.h>
39
40
41
42
43 /* PSP renderer implementation, based on the PGE */
44
45
46 extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
47
48
49 static SDL_Renderer *PSP_CreateRenderer(SDL_Window * window, Uint32 flags);
50 static void PSP_WindowEvent(SDL_Renderer * renderer,
51 const SDL_WindowEvent *event);
52 static int PSP_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
53 static int PSP_SetTextureColorMod(SDL_Renderer * renderer,
54 SDL_Texture * texture);
55 static int PSP_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
56 const SDL_Rect * rect, const void *pixels,
57 int pitch);
58 static int PSP_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
59 const SDL_Rect * rect, void **pixels, int *pitch);
60 static void PSP_UnlockTexture(SDL_Renderer * renderer,
61 SDL_Texture * texture);
62 static int PSP_SetRenderTarget(SDL_Renderer * renderer,
63 SDL_Texture * texture);
64 static int PSP_UpdateViewport(SDL_Renderer * renderer);
65 static int PSP_RenderClear(SDL_Renderer * renderer);
66 static int PSP_RenderDrawPoints(SDL_Renderer * renderer,
67 const SDL_FPoint * points, int count);
68 static int PSP_RenderDrawLines(SDL_Renderer * renderer,
69 const SDL_FPoint * points, int count);
70 static int PSP_RenderFillRects(SDL_Renderer * renderer,
71 const SDL_FRect * rects, int count);
72 static int PSP_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
73 const SDL_Rect * srcrect,
74 const SDL_FRect * dstrect);
75 static int PSP_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
76 Uint32 pixel_format, void * pixels, int pitch);
77 static int PSP_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
78 const SDL_Rect * srcrect, const SDL_FRect * dstrect,
79 const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
80 static void PSP_RenderPresent(SDL_Renderer * renderer);
81 static void PSP_DestroyTexture(SDL_Renderer * renderer,
82 SDL_Texture * texture);
83 static void PSP_DestroyRenderer(SDL_Renderer * renderer);
84
85 /*
86 SDL_RenderDriver PSP_RenderDriver = {
87 PSP_CreateRenderer,
88 {
89 "PSP",
90 (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
91 1,
92 {SDL_PIXELFORMAT_ABGR8888},
93 0,
94 0}
95 };
96 */
97 SDL_RenderDriver PSP_RenderDriver = {
98 .CreateRenderer = PSP_CreateRenderer,
99 .info = {
100 .name = "PSP",
101 .flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE,
102 .num_texture_formats = 4,
103 .texture_formats = { [0] = SDL_PIXELFORMAT_BGR565,
104 [1] = SDL_PIXELFORMAT_ABGR1555,
105 [2] = SDL_PIXELFORMAT_ABGR4444,
106 [3] = SDL_PIXELFORMAT_ABGR8888,
107 },
108 .max_texture_width = 512,
109 .max_texture_height = 512,
110 }
111 };
112
113 #define PSP_SCREEN_WIDTH 480
114 #define PSP_SCREEN_HEIGHT 272
115
116 #define PSP_FRAME_BUFFER_WIDTH 512
117 #define PSP_FRAME_BUFFER_SIZE (PSP_FRAME_BUFFER_WIDTH*PSP_SCREEN_HEIGHT)
118
119 static unsigned int __attribute__((aligned(16))) DisplayList[262144];
120
121
122 #define COL5650(r,g,b,a) ((r>>3) | ((g>>2)<<5) | ((b>>3)<<11))
123 #define COL5551(r,g,b,a) ((r>>3) | ((g>>3)<<5) | ((b>>3)<<10) | (a>0?0x7000:0))
124 #define COL4444(r,g,b,a) ((r>>4) | ((g>>4)<<4) | ((b>>4)<<8) | ((a>>4)<<12))
125 #define COL8888(r,g,b,a) ((r) | ((g)<<8) | ((b)<<16) | ((a)<<24))
126
127
128 typedef struct
129 {
130 void* frontbuffer ;
131 void* backbuffer ;
132 SDL_bool initialized ;
133 SDL_bool displayListAvail ;
134 unsigned int psm ;
135 unsigned int bpp ;
136
137 SDL_bool vsync;
138 unsigned int currentColor;
139 int currentBlendMode;
140
141 } PSP_RenderData;
142
143
144 typedef struct
145 {
146 void *data; /**< Image data. */
147 unsigned int size; /**< Size of data in bytes. */
148 unsigned int width; /**< Image width. */
149 unsigned int height; /**< Image height. */
150 unsigned int textureWidth; /**< Texture width (power of two). */
151 unsigned int textureHeight; /**< Texture height (power of two). */
152 unsigned int bits; /**< Image bits per pixel. */
153 unsigned int format; /**< Image format - one of ::pgePixelFormat. */
154 unsigned int pitch;
155 SDL_bool swizzled; /**< Is image swizzled. */
156
157 } PSP_TextureData;
158
159 typedef struct
160 {
161 float x, y, z;
162 } VertV;
163
164
165 typedef struct
166 {
167 float u, v;
168 float x, y, z;
169
170 } VertTV;
171
172
173 /* Return next power of 2 */
174 static int
TextureNextPow2(unsigned int w)175 TextureNextPow2(unsigned int w)
176 {
177 if(w == 0)
178 return 0;
179
180 unsigned int n = 2;
181
182 while(w > n)
183 n <<= 1;
184
185 return n;
186 }
187
188
189 static int
GetScaleQuality(void)190 GetScaleQuality(void)
191 {
192 const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
193
194 if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
195 return GU_NEAREST; /* GU_NEAREST good for tile-map */
196 } else {
197 return GU_LINEAR; /* GU_LINEAR good for scaling */
198 }
199 }
200
201 static int
PixelFormatToPSPFMT(Uint32 format)202 PixelFormatToPSPFMT(Uint32 format)
203 {
204 switch (format) {
205 case SDL_PIXELFORMAT_BGR565:
206 return GU_PSM_5650;
207 case SDL_PIXELFORMAT_ABGR1555:
208 return GU_PSM_5551;
209 case SDL_PIXELFORMAT_ABGR4444:
210 return GU_PSM_4444;
211 case SDL_PIXELFORMAT_ABGR8888:
212 return GU_PSM_8888;
213 default:
214 return GU_PSM_8888;
215 }
216 }
217
218 void
StartDrawing(SDL_Renderer * renderer)219 StartDrawing(SDL_Renderer * renderer)
220 {
221 PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;
222 if(data->displayListAvail)
223 return;
224
225 sceGuStart(GU_DIRECT, DisplayList);
226 data->displayListAvail = SDL_TRUE;
227 }
228
229
230 int
TextureSwizzle(PSP_TextureData * psp_texture)231 TextureSwizzle(PSP_TextureData *psp_texture)
232 {
233 if(psp_texture->swizzled)
234 return 1;
235
236 int bytewidth = psp_texture->textureWidth*(psp_texture->bits>>3);
237 int height = psp_texture->size / bytewidth;
238
239 int rowblocks = (bytewidth>>4);
240 int rowblocksadd = (rowblocks-1)<<7;
241 unsigned int blockaddress = 0;
242 unsigned int *src = (unsigned int*) psp_texture->data;
243
244 unsigned char *data = NULL;
245 data = malloc(psp_texture->size);
246
247 int j;
248
249 for(j = 0; j < height; j++, blockaddress += 16)
250 {
251 unsigned int *block;
252
253 block = (unsigned int*)&data[blockaddress];
254
255 int i;
256
257 for(i = 0; i < rowblocks; i++)
258 {
259 *block++ = *src++;
260 *block++ = *src++;
261 *block++ = *src++;
262 *block++ = *src++;
263 block += 28;
264 }
265
266 if((j & 0x7) == 0x7)
267 blockaddress += rowblocksadd;
268 }
269
270 free(psp_texture->data);
271 psp_texture->data = data;
272 psp_texture->swizzled = SDL_TRUE;
273
274 return 1;
275 }
TextureUnswizzle(PSP_TextureData * psp_texture)276 int TextureUnswizzle(PSP_TextureData *psp_texture)
277 {
278 if(!psp_texture->swizzled)
279 return 1;
280
281 int blockx, blocky;
282
283 int bytewidth = psp_texture->textureWidth*(psp_texture->bits>>3);
284 int height = psp_texture->size / bytewidth;
285
286 int widthblocks = bytewidth/16;
287 int heightblocks = height/8;
288
289 int dstpitch = (bytewidth - 16)/4;
290 int dstrow = bytewidth * 8;
291
292 unsigned int *src = (unsigned int*) psp_texture->data;
293
294 unsigned char *data = NULL;
295
296 data = malloc(psp_texture->size);
297
298 if(!data)
299 return 0;
300
301 sceKernelDcacheWritebackAll();
302
303 int j;
304
305 unsigned char *ydst = (unsigned char *)data;
306
307 for(blocky = 0; blocky < heightblocks; ++blocky)
308 {
309 unsigned char *xdst = ydst;
310
311 for(blockx = 0; blockx < widthblocks; ++blockx)
312 {
313 unsigned int *block;
314
315 block = (unsigned int*)xdst;
316
317 for(j = 0; j < 8; ++j)
318 {
319 *(block++) = *(src++);
320 *(block++) = *(src++);
321 *(block++) = *(src++);
322 *(block++) = *(src++);
323 block += dstpitch;
324 }
325
326 xdst += 16;
327 }
328
329 ydst += dstrow;
330 }
331
332 free(psp_texture->data);
333
334 psp_texture->data = data;
335
336 psp_texture->swizzled = SDL_FALSE;
337
338 return 1;
339 }
340
341 SDL_Renderer *
PSP_CreateRenderer(SDL_Window * window,Uint32 flags)342 PSP_CreateRenderer(SDL_Window * window, Uint32 flags)
343 {
344
345 SDL_Renderer *renderer;
346 PSP_RenderData *data;
347 int pixelformat;
348 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
349 if (!renderer) {
350 SDL_OutOfMemory();
351 return NULL;
352 }
353
354 data = (PSP_RenderData *) SDL_calloc(1, sizeof(*data));
355 if (!data) {
356 PSP_DestroyRenderer(renderer);
357 SDL_OutOfMemory();
358 return NULL;
359 }
360
361
362 renderer->WindowEvent = PSP_WindowEvent;
363 renderer->CreateTexture = PSP_CreateTexture;
364 renderer->SetTextureColorMod = PSP_SetTextureColorMod;
365 renderer->UpdateTexture = PSP_UpdateTexture;
366 renderer->LockTexture = PSP_LockTexture;
367 renderer->UnlockTexture = PSP_UnlockTexture;
368 renderer->SetRenderTarget = PSP_SetRenderTarget;
369 renderer->UpdateViewport = PSP_UpdateViewport;
370 renderer->RenderClear = PSP_RenderClear;
371 renderer->RenderDrawPoints = PSP_RenderDrawPoints;
372 renderer->RenderDrawLines = PSP_RenderDrawLines;
373 renderer->RenderFillRects = PSP_RenderFillRects;
374 renderer->RenderCopy = PSP_RenderCopy;
375 renderer->RenderReadPixels = PSP_RenderReadPixels;
376 renderer->RenderCopyEx = PSP_RenderCopyEx;
377 renderer->RenderPresent = PSP_RenderPresent;
378 renderer->DestroyTexture = PSP_DestroyTexture;
379 renderer->DestroyRenderer = PSP_DestroyRenderer;
380 renderer->info = PSP_RenderDriver.info;
381 renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
382 renderer->driverdata = data;
383 renderer->window = window;
384
385 if (data->initialized != SDL_FALSE)
386 return 0;
387 data->initialized = SDL_TRUE;
388
389 if (flags & SDL_RENDERER_PRESENTVSYNC) {
390 data->vsync = SDL_TRUE;
391 } else {
392 data->vsync = SDL_FALSE;
393 }
394
395 pixelformat=PixelFormatToPSPFMT(SDL_GetWindowPixelFormat(window));
396 switch(pixelformat)
397 {
398 case GU_PSM_4444:
399 case GU_PSM_5650:
400 case GU_PSM_5551:
401 data->frontbuffer = (unsigned int *)(PSP_FRAME_BUFFER_SIZE<<1);
402 data->backbuffer = (unsigned int *)(0);
403 data->bpp = 2;
404 data->psm = pixelformat;
405 break;
406 default:
407 data->frontbuffer = (unsigned int *)(PSP_FRAME_BUFFER_SIZE<<2);
408 data->backbuffer = (unsigned int *)(0);
409 data->bpp = 4;
410 data->psm = GU_PSM_8888;
411 break;
412 }
413
414 sceGuInit();
415 /* setup GU */
416 sceGuStart(GU_DIRECT, DisplayList);
417 sceGuDrawBuffer(data->psm, data->frontbuffer, PSP_FRAME_BUFFER_WIDTH);
418 sceGuDispBuffer(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT, data->backbuffer, PSP_FRAME_BUFFER_WIDTH);
419
420
421 sceGuOffset(2048 - (PSP_SCREEN_WIDTH>>1), 2048 - (PSP_SCREEN_HEIGHT>>1));
422 sceGuViewport(2048, 2048, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT);
423
424 data->frontbuffer = vabsptr(data->frontbuffer);
425 data->backbuffer = vabsptr(data->backbuffer);
426
427 /* Scissoring */
428 sceGuScissor(0, 0, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT);
429 sceGuEnable(GU_SCISSOR_TEST);
430
431 /* Backface culling */
432 sceGuFrontFace(GU_CCW);
433 sceGuEnable(GU_CULL_FACE);
434
435 /* Texturing */
436 sceGuEnable(GU_TEXTURE_2D);
437 sceGuShadeModel(GU_SMOOTH);
438 sceGuTexWrap(GU_REPEAT, GU_REPEAT);
439
440 /* Blending */
441 sceGuEnable(GU_BLEND);
442 sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0);
443
444 sceGuTexFilter(GU_LINEAR,GU_LINEAR);
445
446 sceGuFinish();
447 sceGuSync(0,0);
448 sceDisplayWaitVblankStartCB();
449 sceGuDisplay(GU_TRUE);
450
451 return renderer;
452 }
453
454 static void
PSP_WindowEvent(SDL_Renderer * renderer,const SDL_WindowEvent * event)455 PSP_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
456 {
457
458 }
459
460
461 static int
PSP_CreateTexture(SDL_Renderer * renderer,SDL_Texture * texture)462 PSP_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
463 {
464 /* PSP_RenderData *renderdata = (PSP_RenderData *) renderer->driverdata; */
465 PSP_TextureData* psp_texture = (PSP_TextureData*) SDL_calloc(1, sizeof(*psp_texture));
466
467 if(!psp_texture)
468 return -1;
469
470 psp_texture->swizzled = SDL_FALSE;
471 psp_texture->width = texture->w;
472 psp_texture->height = texture->h;
473 psp_texture->textureHeight = TextureNextPow2(texture->h);
474 psp_texture->textureWidth = TextureNextPow2(texture->w);
475 psp_texture->format = PixelFormatToPSPFMT(texture->format);
476
477 switch(psp_texture->format)
478 {
479 case GU_PSM_5650:
480 case GU_PSM_5551:
481 case GU_PSM_4444:
482 psp_texture->bits = 16;
483 break;
484
485 case GU_PSM_8888:
486 psp_texture->bits = 32;
487 break;
488
489 default:
490 return -1;
491 }
492
493 psp_texture->pitch = psp_texture->textureWidth * SDL_BYTESPERPIXEL(texture->format);
494 psp_texture->size = psp_texture->textureHeight*psp_texture->pitch;
495 psp_texture->data = SDL_calloc(1, psp_texture->size);
496
497 if(!psp_texture->data)
498 {
499 SDL_free(psp_texture);
500 return SDL_OutOfMemory();
501 }
502 texture->driverdata = psp_texture;
503
504 return 0;
505 }
506
507 static int
PSP_SetTextureColorMod(SDL_Renderer * renderer,SDL_Texture * texture)508 PSP_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
509 {
510 return SDL_Unsupported();
511 }
512
513 void
TextureActivate(SDL_Texture * texture)514 TextureActivate(SDL_Texture * texture)
515 {
516 PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
517 int scaleMode = GetScaleQuality();
518
519 /* Swizzling is useless with small textures. */
520 if (texture->w >= 16 || texture->h >= 16)
521 {
522 TextureSwizzle(psp_texture);
523 }
524
525 sceGuEnable(GU_TEXTURE_2D);
526 sceGuTexWrap(GU_REPEAT, GU_REPEAT);
527 sceGuTexMode(psp_texture->format, 0, 0, psp_texture->swizzled);
528 sceGuTexFilter(scaleMode, scaleMode); /* GU_NEAREST good for tile-map */
529 /* GU_LINEAR good for scaling */
530 sceGuTexImage(0, psp_texture->textureWidth, psp_texture->textureHeight, psp_texture->textureWidth, psp_texture->data);
531 sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
532 }
533
534
535 static int
PSP_UpdateTexture(SDL_Renderer * renderer,SDL_Texture * texture,const SDL_Rect * rect,const void * pixels,int pitch)536 PSP_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
537 const SDL_Rect * rect, const void *pixels, int pitch)
538 {
539 /* PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata; */
540 const Uint8 *src;
541 Uint8 *dst;
542 int row, length,dpitch;
543 src = pixels;
544
545 PSP_LockTexture(renderer, texture,rect,(void **)&dst, &dpitch);
546 length = rect->w * SDL_BYTESPERPIXEL(texture->format);
547 if (length == pitch && length == dpitch) {
548 SDL_memcpy(dst, src, length*rect->h);
549 } else {
550 for (row = 0; row < rect->h; ++row) {
551 SDL_memcpy(dst, src, length);
552 src += pitch;
553 dst += dpitch;
554 }
555 }
556
557 sceKernelDcacheWritebackAll();
558 return 0;
559 }
560
561 static int
PSP_LockTexture(SDL_Renderer * renderer,SDL_Texture * texture,const SDL_Rect * rect,void ** pixels,int * pitch)562 PSP_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
563 const SDL_Rect * rect, void **pixels, int *pitch)
564 {
565 PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
566
567 *pixels =
568 (void *) ((Uint8 *) psp_texture->data + rect->y * psp_texture->pitch +
569 rect->x * SDL_BYTESPERPIXEL(texture->format));
570 *pitch = psp_texture->pitch;
571 return 0;
572 }
573
574 static void
PSP_UnlockTexture(SDL_Renderer * renderer,SDL_Texture * texture)575 PSP_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
576 {
577 PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
578 SDL_Rect rect;
579
580 /* We do whole texture updates, at least for now */
581 rect.x = 0;
582 rect.y = 0;
583 rect.w = texture->w;
584 rect.h = texture->h;
585 PSP_UpdateTexture(renderer, texture, &rect, psp_texture->data, psp_texture->pitch);
586 }
587
588 static int
PSP_SetRenderTarget(SDL_Renderer * renderer,SDL_Texture * texture)589 PSP_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
590 {
591
592 return 0;
593 }
594
595 static int
PSP_UpdateViewport(SDL_Renderer * renderer)596 PSP_UpdateViewport(SDL_Renderer * renderer)
597 {
598
599 return 0;
600 }
601
602
603 static void
PSP_SetBlendMode(SDL_Renderer * renderer,int blendMode)604 PSP_SetBlendMode(SDL_Renderer * renderer, int blendMode)
605 {
606 PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;
607 if (blendMode != data-> currentBlendMode) {
608 switch (blendMode) {
609 case SDL_BLENDMODE_NONE:
610 sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
611 sceGuDisable(GU_BLEND);
612 break;
613 case SDL_BLENDMODE_BLEND:
614 sceGuTexFunc(GU_TFX_MODULATE , GU_TCC_RGBA);
615 sceGuEnable(GU_BLEND);
616 sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
617 break;
618 case SDL_BLENDMODE_ADD:
619 sceGuTexFunc(GU_TFX_MODULATE , GU_TCC_RGBA);
620 sceGuEnable(GU_BLEND);
621 sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_FIX, 0, 0x00FFFFFF );
622 break;
623 case SDL_BLENDMODE_MOD:
624 sceGuTexFunc(GU_TFX_MODULATE , GU_TCC_RGBA);
625 sceGuEnable(GU_BLEND);
626 sceGuBlendFunc( GU_ADD, GU_FIX, GU_SRC_COLOR, 0, 0);
627 break;
628 }
629 data->currentBlendMode = blendMode;
630 }
631 }
632
633
634
635 static int
PSP_RenderClear(SDL_Renderer * renderer)636 PSP_RenderClear(SDL_Renderer * renderer)
637 {
638 /* start list */
639 StartDrawing(renderer);
640 int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r;
641 sceGuClearColor(color);
642 sceGuClearDepth(0);
643 sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT|GU_FAST_CLEAR_BIT);
644
645 return 0;
646 }
647
648 static int
PSP_RenderDrawPoints(SDL_Renderer * renderer,const SDL_FPoint * points,int count)649 PSP_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
650 int count)
651 {
652 int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r;
653 int i;
654 StartDrawing(renderer);
655 VertV* vertices = (VertV*)sceGuGetMemory(count*sizeof(VertV));
656
657 for (i = 0; i < count; ++i) {
658 vertices[i].x = points[i].x;
659 vertices[i].y = points[i].y;
660 vertices[i].z = 0.0f;
661 }
662 sceGuDisable(GU_TEXTURE_2D);
663 sceGuColor(color);
664 sceGuShadeModel(GU_FLAT);
665 sceGuDrawArray(GU_POINTS, GU_VERTEX_32BITF|GU_TRANSFORM_2D, count, 0, vertices);
666 sceGuShadeModel(GU_SMOOTH);
667 sceGuEnable(GU_TEXTURE_2D);
668
669 return 0;
670 }
671
672 static int
PSP_RenderDrawLines(SDL_Renderer * renderer,const SDL_FPoint * points,int count)673 PSP_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
674 int count)
675 {
676 int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r;
677 int i;
678 StartDrawing(renderer);
679 VertV* vertices = (VertV*)sceGuGetMemory(count*sizeof(VertV));
680
681 for (i = 0; i < count; ++i) {
682 vertices[i].x = points[i].x;
683 vertices[i].y = points[i].y;
684 vertices[i].z = 0.0f;
685 }
686
687 sceGuDisable(GU_TEXTURE_2D);
688 sceGuColor(color);
689 sceGuShadeModel(GU_FLAT);
690 sceGuDrawArray(GU_LINE_STRIP, GU_VERTEX_32BITF|GU_TRANSFORM_2D, count, 0, vertices);
691 sceGuShadeModel(GU_SMOOTH);
692 sceGuEnable(GU_TEXTURE_2D);
693
694 return 0;
695 }
696
697 static int
PSP_RenderFillRects(SDL_Renderer * renderer,const SDL_FRect * rects,int count)698 PSP_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects,
699 int count)
700 {
701 int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r;
702 int i;
703 StartDrawing(renderer);
704
705 for (i = 0; i < count; ++i) {
706 const SDL_FRect *rect = &rects[i];
707 VertV* vertices = (VertV*)sceGuGetMemory((sizeof(VertV)<<1));
708 vertices[0].x = rect->x;
709 vertices[0].y = rect->y;
710 vertices[0].z = 0.0f;
711
712 vertices[1].x = rect->x + rect->w;
713 vertices[1].y = rect->y + rect->h;
714 vertices[1].z = 0.0f;
715
716 sceGuDisable(GU_TEXTURE_2D);
717 sceGuColor(color);
718 sceGuShadeModel(GU_FLAT);
719 sceGuDrawArray(GU_SPRITES, GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices);
720 sceGuShadeModel(GU_SMOOTH);
721 sceGuEnable(GU_TEXTURE_2D);
722 }
723
724 return 0;
725 }
726
727
728 #define PI 3.14159265358979f
729
730 #define radToDeg(x) ((x)*180.f/PI)
731 #define degToRad(x) ((x)*PI/180.f)
732
MathAbs(float x)733 float MathAbs(float x)
734 {
735 float result;
736
737 __asm__ volatile (
738 "mtv %1, S000\n"
739 "vabs.s S000, S000\n"
740 "mfv %0, S000\n"
741 : "=r"(result) : "r"(x));
742
743 return result;
744 }
745
MathSincos(float r,float * s,float * c)746 void MathSincos(float r, float *s, float *c)
747 {
748 __asm__ volatile (
749 "mtv %2, S002\n"
750 "vcst.s S003, VFPU_2_PI\n"
751 "vmul.s S002, S002, S003\n"
752 "vrot.p C000, S002, [s, c]\n"
753 "mfv %0, S000\n"
754 "mfv %1, S001\n"
755 : "=r"(*s), "=r"(*c): "r"(r));
756 }
757
Swap(float * a,float * b)758 void Swap(float *a, float *b)
759 {
760 float n=*a;
761 *a = *b;
762 *b = n;
763 }
764
765 static int
PSP_RenderCopy(SDL_Renderer * renderer,SDL_Texture * texture,const SDL_Rect * srcrect,const SDL_FRect * dstrect)766 PSP_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
767 const SDL_Rect * srcrect, const SDL_FRect * dstrect)
768 {
769 float x, y, width, height;
770 float u0, v0, u1, v1;
771 unsigned char alpha;
772
773 x = dstrect->x;
774 y = dstrect->y;
775 width = dstrect->w;
776 height = dstrect->h;
777
778 u0 = srcrect->x;
779 v0 = srcrect->y;
780 u1 = srcrect->x + srcrect->w;
781 v1 = srcrect->y + srcrect->h;
782
783 alpha = texture->a;
784
785 StartDrawing(renderer);
786 TextureActivate(texture);
787 PSP_SetBlendMode(renderer, renderer->blendMode);
788
789 if(alpha != 255)
790 {
791 sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA);
792 sceGuColor(GU_RGBA(255, 255, 255, alpha));
793 }else{
794 sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
795 sceGuColor(0xFFFFFFFF);
796 }
797
798 if((MathAbs(u1) - MathAbs(u0)) < 64.0f)
799 {
800 VertTV* vertices = (VertTV*)sceGuGetMemory((sizeof(VertTV))<<1);
801
802 vertices[0].u = u0;
803 vertices[0].v = v0;
804 vertices[0].x = x;
805 vertices[0].y = y;
806 vertices[0].z = 0;
807
808 vertices[1].u = u1;
809 vertices[1].v = v1;
810 vertices[1].x = x + width;
811 vertices[1].y = y + height;
812 vertices[1].z = 0;
813
814 sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices);
815 }
816 else
817 {
818 float start, end;
819 float curU = u0;
820 float curX = x;
821 float endX = x + width;
822 float slice = 64.0f;
823 float ustep = (u1 - u0)/width * slice;
824
825 if(ustep < 0.0f)
826 ustep = -ustep;
827
828 for(start = 0, end = width; start < end; start += slice)
829 {
830 VertTV* vertices = (VertTV*)sceGuGetMemory((sizeof(VertTV))<<1);
831
832 float polyWidth = ((curX + slice) > endX) ? (endX - curX) : slice;
833 float sourceWidth = ((curU + ustep) > u1) ? (u1 - curU) : ustep;
834
835 vertices[0].u = curU;
836 vertices[0].v = v0;
837 vertices[0].x = curX;
838 vertices[0].y = y;
839 vertices[0].z = 0;
840
841 curU += sourceWidth;
842 curX += polyWidth;
843
844 vertices[1].u = curU;
845 vertices[1].v = v1;
846 vertices[1].x = curX;
847 vertices[1].y = (y + height);
848 vertices[1].z = 0;
849
850 sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices);
851 }
852 }
853
854 if(alpha != 255)
855 sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
856 return 0;
857 }
858
859 static int
PSP_RenderReadPixels(SDL_Renderer * renderer,const SDL_Rect * rect,Uint32 pixel_format,void * pixels,int pitch)860 PSP_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
861 Uint32 pixel_format, void * pixels, int pitch)
862
863 {
864 return SDL_Unsupported();
865 }
866
867
868 static int
PSP_RenderCopyEx(SDL_Renderer * renderer,SDL_Texture * texture,const SDL_Rect * srcrect,const SDL_FRect * dstrect,const double angle,const SDL_FPoint * center,const SDL_RendererFlip flip)869 PSP_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
870 const SDL_Rect * srcrect, const SDL_FRect * dstrect,
871 const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
872 {
873 float x, y, width, height;
874 float u0, v0, u1, v1;
875 unsigned char alpha;
876 float centerx, centery;
877
878 x = dstrect->x;
879 y = dstrect->y;
880 width = dstrect->w;
881 height = dstrect->h;
882
883 u0 = srcrect->x;
884 v0 = srcrect->y;
885 u1 = srcrect->x + srcrect->w;
886 v1 = srcrect->y + srcrect->h;
887
888 centerx = center->x;
889 centery = center->y;
890
891 alpha = texture->a;
892
893 StartDrawing(renderer);
894 TextureActivate(texture);
895 PSP_SetBlendMode(renderer, renderer->blendMode);
896
897 if(alpha != 255)
898 {
899 sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA);
900 sceGuColor(GU_RGBA(255, 255, 255, alpha));
901 }else{
902 sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
903 sceGuColor(0xFFFFFFFF);
904 }
905
906 /* x += width * 0.5f; */
907 /* y += height * 0.5f; */
908 x += centerx;
909 y += centery;
910
911 float c, s;
912
913 MathSincos(degToRad(angle), &s, &c);
914
915 /* width *= 0.5f; */
916 /* height *= 0.5f; */
917 width -= centerx;
918 height -= centery;
919
920
921 float cw = c*width;
922 float sw = s*width;
923 float ch = c*height;
924 float sh = s*height;
925
926 VertTV* vertices = (VertTV*)sceGuGetMemory(sizeof(VertTV)<<2);
927
928 vertices[0].u = u0;
929 vertices[0].v = v0;
930 vertices[0].x = x - cw + sh;
931 vertices[0].y = y - sw - ch;
932 vertices[0].z = 0;
933
934 vertices[1].u = u0;
935 vertices[1].v = v1;
936 vertices[1].x = x - cw - sh;
937 vertices[1].y = y - sw + ch;
938 vertices[1].z = 0;
939
940 vertices[2].u = u1;
941 vertices[2].v = v1;
942 vertices[2].x = x + cw - sh;
943 vertices[2].y = y + sw + ch;
944 vertices[2].z = 0;
945
946 vertices[3].u = u1;
947 vertices[3].v = v0;
948 vertices[3].x = x + cw + sh;
949 vertices[3].y = y + sw - ch;
950 vertices[3].z = 0;
951
952 if (flip & SDL_FLIP_HORIZONTAL) {
953 Swap(&vertices[0].v, &vertices[2].v);
954 Swap(&vertices[1].v, &vertices[3].v);
955 }
956 if (flip & SDL_FLIP_VERTICAL) {
957 Swap(&vertices[0].u, &vertices[2].u);
958 Swap(&vertices[1].u, &vertices[3].u);
959 }
960
961 sceGuDrawArray(GU_TRIANGLE_FAN, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 4, 0, vertices);
962
963 if(alpha != 255)
964 sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
965 return 0;
966 }
967
968 static void
PSP_RenderPresent(SDL_Renderer * renderer)969 PSP_RenderPresent(SDL_Renderer * renderer)
970 {
971 PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;
972 if(!data->displayListAvail)
973 return;
974
975 data->displayListAvail = SDL_FALSE;
976 sceGuFinish();
977 sceGuSync(0,0);
978
979 /* if(data->vsync) */
980 sceDisplayWaitVblankStart();
981
982 data->backbuffer = data->frontbuffer;
983 data->frontbuffer = vabsptr(sceGuSwapBuffers());
984
985 }
986
987 static void
PSP_DestroyTexture(SDL_Renderer * renderer,SDL_Texture * texture)988 PSP_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
989 {
990 PSP_RenderData *renderdata = (PSP_RenderData *) renderer->driverdata;
991 PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
992
993 if (renderdata == 0)
994 return;
995
996 if(psp_texture == 0)
997 return;
998
999 SDL_free(psp_texture->data);
1000 SDL_free(psp_texture);
1001 texture->driverdata = NULL;
1002 }
1003
1004 static void
PSP_DestroyRenderer(SDL_Renderer * renderer)1005 PSP_DestroyRenderer(SDL_Renderer * renderer)
1006 {
1007 PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;
1008 if (data) {
1009 if (!data->initialized)
1010 return;
1011
1012 StartDrawing(renderer);
1013
1014 sceGuTerm();
1015 /* vfree(data->backbuffer); */
1016 /* vfree(data->frontbuffer); */
1017
1018 data->initialized = SDL_FALSE;
1019 data->displayListAvail = SDL_FALSE;
1020 SDL_free(data);
1021 }
1022 SDL_free(renderer);
1023 }
1024
1025 #endif /* SDL_VIDEO_RENDER_PSP */
1026
1027 /* vi: set ts=4 sw=4 expandtab: */
1028
1029