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
52static 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
61typedef 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
77typedef 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
92typedef struct
93{
94 float x, y, z;
95} VertV;
96
97
98typedef 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
110float 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
123void 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
135void Swap(float *a, float *b)
136{
137 float n=*a;
138 *a = *b;
139 *b = n;
140}
141
142/* Return next power of 2 */
143static int
144TextureNextPow2(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
158static int
159PixelFormatToPSPFMT(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
175void
176StartDrawing(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
187int
188TextureSwizzle(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}
233int 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
298static void
299PSP_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
300{
301}
302
303
304static int
305PSP_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
350static int
351PSP_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
352{
353 return SDL_Unsupported();
354}
355
356void
357TextureActivate(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
378static int
379PSP_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) {
392 } else {
393 for (row = 0; row < rect->h; ++row) {
395 src += pitch;
396 dst += dpitch;
397 }
398 }
399
400 sceKernelDcacheWritebackAll();
401 return 0;
402}
403
404static int
405PSP_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
417static void
418PSP_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
419{
420 PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
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
431static int
432PSP_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
433{
434 return 0;
435}
436
437static int
438PSP_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
439{
440 return 0; /* nothing to do in this backend. */
441}
442
443static int
444PSP_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
464static int
465PSP_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
491static int
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
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
578static int
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
650static void
651PSP_SetBlendMode(SDL_Renderer * renderer, int blendMode)
652{
653 PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;
654 if (blendMode != data-> currentBlendMode) {
655 switch (blendMode) {
657 sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
658 sceGuDisable(GU_BLEND);
659 break;
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;
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;
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
680static int
681PSP_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
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
841 break;
842 }
843
844 cmd = cmd->next;
845 }
846
847 return 0;
848}
849
850static int
851PSP_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
852 Uint32 pixel_format, void * pixels, int pitch)
853{
854 return SDL_Unsupported();
855}
856
857static void
858PSP_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
876static void
877PSP_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
893static void
894PSP_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 }
912}
913
915PSP_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) {
924 return NULL;
925 }
926
927 data = (PSP_RenderData *) SDL_calloc(1, sizeof(*data));
928 if (!data) {
929 PSP_DestroyRenderer(renderer);
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;
958
959 if (data->initialized != SDL_FALSE)
960 return 0;
961 data->initialized = SDL_TRUE;
962
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",
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
#define SDL_assert(condition)
Definition: SDL_assert.h:169
@ SDL_BLENDMODE_NONE
Definition: SDL_blendmode.h:42
@ SDL_BLENDMODE_ADD
Definition: SDL_blendmode.h:47
@ SDL_BLENDMODE_BLEND
Definition: SDL_blendmode.h:44
@ SDL_BLENDMODE_MOD
Definition: SDL_blendmode.h:50
#define SDL_SetError
#define SDL_GetWindowPixelFormat
#define SDL_ceilf
#define SDL_free
#define SDL_memcmp
#define SDL_memcpy
#define SDL_calloc
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_Unsupported()
Definition: SDL_error.h:53
SDL_EventEntry * free
Definition: SDL_events.c:82
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
float GLfloat
Definition: SDL_opengl.h:187
GLuint GLuint end
Definition: SDL_opengl.h:1571
const GLdouble * v
Definition: SDL_opengl.h:2064
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: SDL_opengl.h:1572
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLint GLint GLsizei width
Definition: SDL_opengl.h:1572
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2079
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1572
GLuint start
Definition: SDL_opengl.h:1571
GLdouble s
Definition: SDL_opengl.h:2063
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
GLboolean GLboolean GLboolean b
struct _cl_event * event
GLfixed GLfixed GLint GLint GLfixed points
GLenum src
GLfixed u1
GLuint64EXT * result
GLuint color
GLboolean GLboolean GLboolean GLboolean a
const GLubyte * c
GLenum GLenum dst
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
GLdouble GLdouble z
GLenum GLenum void * row
GLboolean GLboolean g
GLfloat angle
GLsizeiptr size
GLfloat v0
GLbitfield flags
GLfloat GLfloat v1
GLenum GLenum GLuint texture
GLuint GLsizei GLsizei * length
GLfloat GLfloat GLfloat alpha
GLdouble n
GLubyte GLubyte GLubyte GLubyte w
#define SDL_BYTESPERPIXEL(X)
Definition: SDL_pixels.h:128
@ SDL_PIXELFORMAT_BGR565
Definition: SDL_pixels.h:227
@ SDL_PIXELFORMAT_ABGR4444
Definition: SDL_pixels.h:206
@ SDL_PIXELFORMAT_ABGR8888
Definition: SDL_pixels.h:254
@ SDL_PIXELFORMAT_ABGR1555
Definition: SDL_pixels.h:218
#define malloc
Definition: SDL_qsort.c:47
void * SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset)
Definition: SDL_render.c:284
@ SDL_RENDERER_ACCELERATED
Definition: SDL_render.h:67
@ SDL_RENDERER_PRESENTVSYNC
Definition: SDL_render.h:69
@ SDL_RENDERER_TARGETTEXTURE
Definition: SDL_render.h:71
SDL_RendererFlip
Flip constants for SDL_RenderCopyEx.
Definition: SDL_render.h:112
@ SDL_FLIP_VERTICAL
Definition: SDL_render.h:115
@ SDL_FLIP_HORIZONTAL
Definition: SDL_render.h:114
SDL_bool
Definition: SDL_stdinc.h:162
@ SDL_TRUE
Definition: SDL_stdinc.h:164
@ SDL_FALSE
Definition: SDL_stdinc.h:163
uint32_t Uint32
Definition: SDL_stdinc.h:203
uint8_t Uint8
Definition: SDL_stdinc.h:179
SDL_RenderDriver PSP_RenderDriver
@ SDL_ScaleModeNearest
Definition: SDL_sysrender.h:37
@ SDL_RENDERCMD_SETCLIPRECT
Definition: SDL_sysrender.h:76
@ SDL_RENDERCMD_DRAW_LINES
Definition: SDL_sysrender.h:80
@ SDL_RENDERCMD_SETVIEWPORT
Definition: SDL_sysrender.h:75
@ SDL_RENDERCMD_DRAW_POINTS
Definition: SDL_sysrender.h:79
@ SDL_RENDERCMD_NO_OP
Definition: SDL_sysrender.h:74
@ SDL_RENDERCMD_FILL_RECTS
Definition: SDL_sysrender.h:81
@ SDL_RENDERCMD_COPY
Definition: SDL_sysrender.h:82
@ SDL_RENDERCMD_CLEAR
Definition: SDL_sysrender.h:78
@ SDL_RENDERCMD_SETDRAWCOLOR
Definition: SDL_sysrender.h:77
@ SDL_RENDERCMD_COPY_EX
Definition: SDL_sysrender.h:83
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
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
#define NULL
Definition: begin_code.h:167
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
EGLSurface EGLint * rects
Definition: eglext.h:282
The structure that defines a point (floating point)
Definition: SDL_rect.h:61
float x
Definition: SDL_rect.h:62
float y
Definition: SDL_rect.h:63
A rectangle, with the origin at the upper left (floating point).
Definition: SDL_rect.h:88
float h
Definition: SDL_rect.h:92
float x
Definition: SDL_rect.h:89
float w
Definition: SDL_rect.h:91
float y
Definition: SDL_rect.h:90
A rectangle, with the origin at the upper left (integer).
Definition: SDL_rect.h:78
int h
Definition: SDL_rect.h:80
int w
Definition: SDL_rect.h:80
int y
Definition: SDL_rect.h:79
int x
Definition: SDL_rect.h:79
union SDL_RenderCommand::@30 data
struct SDL_RenderCommand * next
struct SDL_RenderCommand::@30::@33 draw
struct SDL_RenderCommand::@30::@31 viewport
SDL_BlendMode blend
SDL_RenderCommandType command
Definition: SDL_sysrender.h:88
struct SDL_RenderCommand::@30::@32 cliprect
SDL_Texture * texture
struct SDL_RenderCommand::@30::@34 color
SDL_RendererInfo info
SDL_Renderer *(* CreateRenderer)(SDL_Window *window, Uint32 flags)
int(* QueueCopy)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
int(* LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
SDL_Window * window
int(* QueueDrawLines)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
void(* UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
int(* SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture)
void(* DestroyRenderer)(SDL_Renderer *renderer)
void(* DestroyTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
void(* RenderPresent)(SDL_Renderer *renderer)
int(* RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
int(* QueueDrawPoints)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
int(* QueueFillRects)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FRect *rects, int count)
void(* WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event)
int(* RunCommandQueue)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
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)
int(* CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* QueueSetViewport)(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
SDL_RendererInfo info
void * driverdata
int(* QueueSetDrawColor)(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
const char * name
Definition: SDL_render.h:80
Window state change event data (event.window.*)
Definition: SDL_events.h:196
The type used to identify a window.
Definition: SDL_sysvideo.h:74
static SDL_Renderer * renderer
static SDL_BlendMode blendMode
Definition: testdraw2.c:34
SDL_Rect rect
Definition: testrelative.c:27
SDL_Rect viewport
Definition: testviewport.c:28