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