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 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
202 PixelFormatToPSPFMT(Uint32 format)
203 {
204  switch (format) {
206  return GU_PSM_5650;
208  return GU_PSM_5551;
210  return GU_PSM_4444;
212  return GU_PSM_8888;
213  default:
214  return GU_PSM_8888;
215  }
216 }
217 
218 void
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
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 }
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 *
342 PSP_CreateRenderer(SDL_Window * window, Uint32 flags)
343 {
344 
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;
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
455 PSP_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
456 {
457 
458 }
459 
460 
461 static int
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
508 PSP_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
509 {
510  return SDL_Unsupported();
511 }
512 
513 void
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
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
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
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
589 PSP_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
590 {
591 
592  return 0;
593 }
594 
595 static int
596 PSP_UpdateViewport(SDL_Renderer * renderer)
597 {
598 
599  return 0;
600 }
601 
602 
603 static void
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
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
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
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
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 
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 
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 
758 void Swap(float *a, float *b)
759 {
760  float n=*a;
761  *a = *b;
762  *b = n;
763 }
764 
765 static int
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
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
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_VERTICAL) {
953  Swap(&vertices[0].v, &vertices[2].v);
954  Swap(&vertices[1].v, &vertices[3].v);
955  }
956  if (flip & SDL_FLIP_HORIZONTAL) {
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
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
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
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 
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)
Definition: SDL_sysrender.h:98
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
#define SDL_HINT_RENDER_SCALE_QUALITY
A variable controlling the scaling quality.
Definition: SDL_hints.h:143
GLuint GLuint end
Definition: SDL_opengl.h:1571
void * driverdata
SDL_RenderDriver PSP_RenderDriver
SDL_EventEntry * free
Definition: SDL_events.c:84
#define SDL_GetHint
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
uint32_t Uint32
Definition: SDL_stdinc.h:181
#define SDL_strcasecmp
GLenum src
const char * name
Definition: SDL_render.h:80
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:90
int(* SetTextureColorMod)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:84
#define SDL_memcpy
GLenum GLenum GLuint texture
int SDL_RecreateWindow(SDL_Window *window, Uint32 flags)
Definition: SDL_video.c:1542
static int GetScaleQuality(void)
static SDL_Renderer * renderer
uint8_t Uint8
Definition: SDL_stdinc.h:157
#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:174
GLfloat v0
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:139
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:80
GLfloat angle
Uint32 format
Definition: SDL_sysrender.h:52
void * driverdata
Definition: SDL_sysrender.h:69
void(* DestroyTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:83
void(* RenderPresent)(SDL_Renderer *renderer)
EGLSurface EGLint * rects
Definition: eglext.h:282
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