• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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