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