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