1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/render/psp/SDL_render_psp.c Sun Mar 17 20:07:02 2013 +0800
1.3 @@ -0,0 +1,1024 @@
1.4 +/*
1.5 + Simple DirectMedia Layer
1.6 + Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
1.7 +
1.8 + This software is provided 'as-is', without any express or implied
1.9 + warranty. In no event will the authors be held liable for any damages
1.10 + arising from the use of this software.
1.11 +
1.12 + Permission is granted to anyone to use this software for any purpose,
1.13 + including commercial applications, and to alter it and redistribute it
1.14 + freely, subject to the following restrictions:
1.15 +
1.16 + 1. The origin of this software must not be misrepresented; you must not
1.17 + claim that you wrote the original software. If you use this software
1.18 + in a product, an acknowledgment in the product documentation would be
1.19 + appreciated but is not required.
1.20 + 2. Altered source versions must be plainly marked as such, and must not be
1.21 + misrepresented as being the original software.
1.22 + 3. This notice may not be removed or altered from any source distribution.
1.23 +*/
1.24 +#include "SDL_config.h"
1.25 +
1.26 +#if SDL_VIDEO_RENDER_PSP
1.27 +
1.28 +#include "SDL_hints.h"
1.29 +#include "../SDL_sysrender.h"
1.30 +
1.31 +#include <pspkernel.h>
1.32 +#include <pspdisplay.h>
1.33 +#include <pspgu.h>
1.34 +#include <pspgum.h>
1.35 +#include <stdio.h>
1.36 +#include <string.h>
1.37 +#include <math.h>
1.38 +#include <pspge.h>
1.39 +#include <stdarg.h>
1.40 +#include <stdlib.h>
1.41 +#include <vram.h>
1.42 +
1.43 +
1.44 +
1.45 +
1.46 +/* PSP renderer implementation, based on the PGE */
1.47 +
1.48 +
1.49 +extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
1.50 +
1.51 +
1.52 +static SDL_Renderer *PSP_CreateRenderer(SDL_Window * window, Uint32 flags);
1.53 +static void PSP_WindowEvent(SDL_Renderer * renderer,
1.54 + const SDL_WindowEvent *event);
1.55 +static int PSP_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
1.56 +static int PSP_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
1.57 + const SDL_Rect * rect, const void *pixels,
1.58 + int pitch);
1.59 +static int PSP_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
1.60 + const SDL_Rect * rect, void **pixels, int *pitch);
1.61 +static void PSP_UnlockTexture(SDL_Renderer * renderer,
1.62 + SDL_Texture * texture);
1.63 +static int PSP_SetRenderTarget(SDL_Renderer * renderer,
1.64 + SDL_Texture * texture);
1.65 +static int PSP_UpdateViewport(SDL_Renderer * renderer);
1.66 +static int PSP_RenderClear(SDL_Renderer * renderer);
1.67 +static int PSP_RenderDrawPoints(SDL_Renderer * renderer,
1.68 + const SDL_FPoint * points, int count);
1.69 +static int PSP_RenderDrawLines(SDL_Renderer * renderer,
1.70 + const SDL_FPoint * points, int count);
1.71 +static int PSP_RenderFillRects(SDL_Renderer * renderer,
1.72 + const SDL_FRect * rects, int count);
1.73 +static int PSP_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
1.74 + const SDL_Rect * srcrect,
1.75 + const SDL_FRect * dstrect);
1.76 +static int PSP_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1.77 + Uint32 pixel_format, void * pixels, int pitch);
1.78 +static int PSP_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
1.79 + const SDL_Rect * srcrect, const SDL_FRect * dstrect,
1.80 + const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
1.81 +static void PSP_RenderPresent(SDL_Renderer * renderer);
1.82 +static void PSP_DestroyTexture(SDL_Renderer * renderer,
1.83 + SDL_Texture * texture);
1.84 +static void PSP_DestroyRenderer(SDL_Renderer * renderer);
1.85 +
1.86 +/*
1.87 +SDL_RenderDriver PSP_RenderDriver = {
1.88 + PSP_CreateRenderer,
1.89 + {
1.90 + "PSP",
1.91 + (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
1.92 + 1,
1.93 + {SDL_PIXELFORMAT_ABGR8888},
1.94 + 0,
1.95 + 0}
1.96 +};
1.97 +*/
1.98 +SDL_RenderDriver PSP_RenderDriver = {
1.99 + .CreateRenderer = PSP_CreateRenderer,
1.100 + .info = {
1.101 + .name = "PSP",
1.102 + .flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE,
1.103 + .num_texture_formats = 4,
1.104 + .texture_formats = { [0] = SDL_PIXELFORMAT_BGR565,
1.105 + [1] = SDL_PIXELFORMAT_ABGR1555,
1.106 + [2] = SDL_PIXELFORMAT_ABGR4444,
1.107 + [3] = SDL_PIXELFORMAT_ABGR8888,
1.108 + },
1.109 + .max_texture_width = 512,
1.110 + .max_texture_height = 512,
1.111 + }
1.112 +};
1.113 +
1.114 +#define PSP_SCREEN_WIDTH 480
1.115 +#define PSP_SCREEN_HEIGHT 272
1.116 +
1.117 +#define PSP_FRAME_BUFFER_WIDTH 512
1.118 +#define PSP_FRAME_BUFFER_SIZE (PSP_FRAME_BUFFER_WIDTH*PSP_SCREEN_HEIGHT)
1.119 +
1.120 +static unsigned int __attribute__((aligned(16))) DisplayList[262144];
1.121 +
1.122 +
1.123 +#define COL5650(r,g,b,a) ((r>>3) | ((g>>2)<<5) | ((b>>3)<<11))
1.124 +#define COL5551(r,g,b,a) ((r>>3) | ((g>>3)<<5) | ((b>>3)<<10) | (a>0?0x7000:0))
1.125 +#define COL4444(r,g,b,a) ((r>>4) | ((g>>4)<<4) | ((b>>4)<<8) | ((a>>4)<<12))
1.126 +#define COL8888(r,g,b,a) ((r) | ((g)<<8) | ((b)<<16) | ((a)<<24))
1.127 +
1.128 +
1.129 +typedef struct
1.130 +{
1.131 + void* frontbuffer ;
1.132 + void* backbuffer ;
1.133 + SDL_bool initialized ;
1.134 + SDL_bool displayListAvail ;
1.135 + unsigned int psm ;
1.136 + unsigned int bpp ;
1.137 +
1.138 + SDL_bool vsync;
1.139 + unsigned int currentColor;
1.140 + int currentBlendMode;
1.141 +
1.142 +} PSP_RenderData;
1.143 +
1.144 +
1.145 +typedef struct
1.146 +{
1.147 + void *data; /**< Image data. */
1.148 + unsigned int size; /**< Size of data in bytes. */
1.149 + unsigned int width; /**< Image width. */
1.150 + unsigned int height; /**< Image height. */
1.151 + unsigned int textureWidth; /**< Texture width (power of two). */
1.152 + unsigned int textureHeight; /**< Texture height (power of two). */
1.153 + unsigned int bits; /**< Image bits per pixel. */
1.154 + unsigned int format; /**< Image format - one of ::pgePixelFormat. */
1.155 + unsigned int pitch;
1.156 + SDL_bool swizzled; /**< Is image swizzled. */
1.157 +
1.158 +} PSP_TextureData;
1.159 +
1.160 +typedef struct
1.161 +{
1.162 + float x, y, z;
1.163 +} VertV;
1.164 +
1.165 +
1.166 +typedef struct
1.167 +{
1.168 + float u, v;
1.169 + float x, y, z;
1.170 +
1.171 +} VertTV;
1.172 +
1.173 +
1.174 +// Return next power of 2
1.175 +static int
1.176 +TextureNextPow2(unsigned int w)
1.177 +{
1.178 + if(w == 0)
1.179 + return 0;
1.180 +
1.181 + unsigned int n = 2;
1.182 +
1.183 + while(w > n)
1.184 + n <<= 1;
1.185 +
1.186 + return n;
1.187 +}
1.188 +
1.189 +
1.190 +static int
1.191 +GetScaleQuality(void)
1.192 +{
1.193 + const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
1.194 +
1.195 + if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
1.196 + return GU_NEAREST; // GU_NEAREST good for tile-map
1.197 + } else {
1.198 + return GU_LINEAR; // GU_LINEAR good for scaling
1.199 + }
1.200 +}
1.201 +
1.202 +static int
1.203 +PixelFormatToPSPFMT(Uint32 format)
1.204 +{
1.205 + switch (format) {
1.206 + case SDL_PIXELFORMAT_BGR565:
1.207 + return GU_PSM_5650;
1.208 + case SDL_PIXELFORMAT_ABGR1555:
1.209 + return GU_PSM_5551;
1.210 + case SDL_PIXELFORMAT_ABGR4444:
1.211 + return GU_PSM_4444;
1.212 + case SDL_PIXELFORMAT_ABGR8888:
1.213 + return GU_PSM_8888;
1.214 + default:
1.215 + return GU_PSM_8888;
1.216 + }
1.217 +}
1.218 +
1.219 +void
1.220 +StartDrawing(SDL_Renderer * renderer)
1.221 +{
1.222 + PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;
1.223 + if(data->displayListAvail)
1.224 + return;
1.225 +
1.226 + sceGuStart(GU_DIRECT, DisplayList);
1.227 + data->displayListAvail = SDL_TRUE;
1.228 +}
1.229 +
1.230 +
1.231 +int
1.232 +TextureSwizzle(PSP_TextureData *psp_texture)
1.233 +{
1.234 + if(psp_texture->swizzled)
1.235 + return 1;
1.236 +
1.237 + int bytewidth = psp_texture->textureWidth*(psp_texture->bits>>3);
1.238 + int height = psp_texture->size / bytewidth;
1.239 +
1.240 + int rowblocks = (bytewidth>>4);
1.241 + int rowblocksadd = (rowblocks-1)<<7;
1.242 + unsigned int blockaddress = 0;
1.243 + unsigned int *src = (unsigned int*) psp_texture->data;
1.244 +
1.245 + unsigned char *data = NULL;
1.246 + data = malloc(psp_texture->size);
1.247 +
1.248 + int j;
1.249 +
1.250 + for(j = 0; j < height; j++, blockaddress += 16)
1.251 + {
1.252 + unsigned int *block;
1.253 +
1.254 + block = (unsigned int*)&data[blockaddress];
1.255 +
1.256 + int i;
1.257 +
1.258 + for(i = 0; i < rowblocks; i++)
1.259 + {
1.260 + *block++ = *src++;
1.261 + *block++ = *src++;
1.262 + *block++ = *src++;
1.263 + *block++ = *src++;
1.264 + block += 28;
1.265 + }
1.266 +
1.267 + if((j & 0x7) == 0x7)
1.268 + blockaddress += rowblocksadd;
1.269 + }
1.270 +
1.271 + free(psp_texture->data);
1.272 + psp_texture->data = data;
1.273 + psp_texture->swizzled = SDL_TRUE;
1.274 +
1.275 + return 1;
1.276 +}
1.277 +int TextureUnswizzle(PSP_TextureData *psp_texture)
1.278 +{
1.279 + if(!psp_texture->swizzled)
1.280 + return 1;
1.281 +
1.282 + int blockx, blocky;
1.283 +
1.284 + int bytewidth = psp_texture->textureWidth*(psp_texture->bits>>3);
1.285 + int height = psp_texture->size / bytewidth;
1.286 +
1.287 + int widthblocks = bytewidth/16;
1.288 + int heightblocks = height/8;
1.289 +
1.290 + int dstpitch = (bytewidth - 16)/4;
1.291 + int dstrow = bytewidth * 8;
1.292 +
1.293 + unsigned int *src = (unsigned int*) psp_texture->data;
1.294 +
1.295 + unsigned char *data = NULL;
1.296 +
1.297 + data = malloc(psp_texture->size);
1.298 +
1.299 + if(!data)
1.300 + return 0;
1.301 +
1.302 + sceKernelDcacheWritebackAll();
1.303 +
1.304 + int j;
1.305 +
1.306 + unsigned char *ydst = (unsigned char *)data;
1.307 +
1.308 + for(blocky = 0; blocky < heightblocks; ++blocky)
1.309 + {
1.310 + unsigned char *xdst = ydst;
1.311 +
1.312 + for(blockx = 0; blockx < widthblocks; ++blockx)
1.313 + {
1.314 + unsigned int *block;
1.315 +
1.316 + block = (unsigned int*)xdst;
1.317 +
1.318 + for(j = 0; j < 8; ++j)
1.319 + {
1.320 + *(block++) = *(src++);
1.321 + *(block++) = *(src++);
1.322 + *(block++) = *(src++);
1.323 + *(block++) = *(src++);
1.324 + block += dstpitch;
1.325 + }
1.326 +
1.327 + xdst += 16;
1.328 + }
1.329 +
1.330 + ydst += dstrow;
1.331 + }
1.332 +
1.333 + free(psp_texture->data);
1.334 +
1.335 + psp_texture->data = data;
1.336 +
1.337 + psp_texture->swizzled = SDL_FALSE;
1.338 +
1.339 + return 1;
1.340 +}
1.341 +
1.342 +SDL_Renderer *
1.343 +PSP_CreateRenderer(SDL_Window * window, Uint32 flags)
1.344 +{
1.345 +
1.346 + SDL_Renderer *renderer;
1.347 + PSP_RenderData *data;
1.348 + int pixelformat;
1.349 + renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
1.350 + if (!renderer) {
1.351 + SDL_OutOfMemory();
1.352 + return NULL;
1.353 + }
1.354 +
1.355 + data = (PSP_RenderData *) SDL_calloc(1, sizeof(*data));
1.356 + if (!data) {
1.357 + PSP_DestroyRenderer(renderer);
1.358 + SDL_OutOfMemory();
1.359 + return NULL;
1.360 + }
1.361 +
1.362 +
1.363 + renderer->WindowEvent = PSP_WindowEvent;
1.364 + renderer->CreateTexture = PSP_CreateTexture;
1.365 + renderer->UpdateTexture = PSP_UpdateTexture;
1.366 + renderer->LockTexture = PSP_LockTexture;
1.367 + renderer->UnlockTexture = PSP_UnlockTexture;
1.368 + renderer->SetRenderTarget = PSP_SetRenderTarget;
1.369 + renderer->UpdateViewport = PSP_UpdateViewport;
1.370 + renderer->RenderClear = PSP_RenderClear;
1.371 + renderer->RenderDrawPoints = PSP_RenderDrawPoints;
1.372 + renderer->RenderDrawLines = PSP_RenderDrawLines;
1.373 + renderer->RenderFillRects = PSP_RenderFillRects;
1.374 + renderer->RenderCopy = PSP_RenderCopy;
1.375 + renderer->RenderReadPixels = PSP_RenderReadPixels;
1.376 + renderer->RenderCopyEx = PSP_RenderCopyEx;
1.377 + renderer->RenderPresent = PSP_RenderPresent;
1.378 + renderer->DestroyTexture = PSP_DestroyTexture;
1.379 + renderer->DestroyRenderer = PSP_DestroyRenderer;
1.380 + renderer->info = PSP_RenderDriver.info;
1.381 + renderer->info.flags = SDL_RENDERER_ACCELERATED;
1.382 + renderer->driverdata = data;
1.383 + renderer->window = window;
1.384 +
1.385 + if (data->initialized != SDL_FALSE)
1.386 + return 0;
1.387 + data->initialized = SDL_TRUE;
1.388 +
1.389 + if (flags & SDL_RENDERER_PRESENTVSYNC) {
1.390 + data->vsync = SDL_TRUE;
1.391 + } else {
1.392 + data->vsync = SDL_FALSE;
1.393 + }
1.394 +
1.395 + pixelformat=PixelFormatToPSPFMT(SDL_GetWindowPixelFormat(window));
1.396 + switch(pixelformat)
1.397 + {
1.398 + case GU_PSM_4444:
1.399 + case GU_PSM_5650:
1.400 + case GU_PSM_5551:
1.401 + data->frontbuffer = (unsigned int *)(PSP_FRAME_BUFFER_SIZE<<1);
1.402 + data->backbuffer = (unsigned int *)(0);
1.403 + data->bpp = 2;
1.404 + data->psm = pixelformat;
1.405 + break;
1.406 + default:
1.407 + data->frontbuffer = (unsigned int *)(PSP_FRAME_BUFFER_SIZE<<2);
1.408 + data->backbuffer = (unsigned int *)(0);
1.409 + data->bpp = 4;
1.410 + data->psm = GU_PSM_8888;
1.411 + break;
1.412 + }
1.413 +
1.414 + sceGuInit();
1.415 + // setup GU
1.416 + sceGuStart(GU_DIRECT, DisplayList);
1.417 + sceGuDrawBuffer(data->psm, data->frontbuffer, PSP_FRAME_BUFFER_WIDTH);
1.418 + sceGuDispBuffer(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT, data->backbuffer, PSP_FRAME_BUFFER_WIDTH);
1.419 +
1.420 +
1.421 + sceGuOffset(2048 - (PSP_SCREEN_WIDTH>>1), 2048 - (PSP_SCREEN_HEIGHT>>1));
1.422 + sceGuViewport(2048, 2048, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT);
1.423 +
1.424 + data->frontbuffer = vabsptr(data->frontbuffer);
1.425 + data->backbuffer = vabsptr(data->backbuffer);
1.426 +
1.427 + // Scissoring
1.428 + sceGuScissor(0, 0, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT);
1.429 + sceGuEnable(GU_SCISSOR_TEST);
1.430 +
1.431 + // Backface culling
1.432 + sceGuFrontFace(GU_CCW);
1.433 + sceGuEnable(GU_CULL_FACE);
1.434 +
1.435 + // Texturing
1.436 + sceGuEnable(GU_TEXTURE_2D);
1.437 + sceGuShadeModel(GU_SMOOTH);
1.438 + sceGuTexWrap(GU_REPEAT, GU_REPEAT);
1.439 +
1.440 + // Blending
1.441 + sceGuEnable(GU_BLEND);
1.442 + sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0);
1.443 +
1.444 + sceGuTexFilter(GU_LINEAR,GU_LINEAR);
1.445 +
1.446 + sceGuFinish();
1.447 + sceGuSync(0,0);
1.448 + sceDisplayWaitVblankStartCB();
1.449 + sceGuDisplay(GU_TRUE);
1.450 +
1.451 + return renderer;
1.452 +}
1.453 +
1.454 +static void
1.455 +PSP_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
1.456 +{
1.457 +
1.458 +}
1.459 +
1.460 +
1.461 +static int
1.462 +PSP_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1.463 +{
1.464 +// PSP_RenderData *renderdata = (PSP_RenderData *) renderer->driverdata;
1.465 + PSP_TextureData* psp_texture = (PSP_TextureData*) SDL_calloc(1, sizeof(*psp_texture));;
1.466 +
1.467 + if(!psp_texture)
1.468 + return -1;
1.469 +
1.470 + psp_texture->swizzled = SDL_FALSE;
1.471 + psp_texture->width = texture->w;
1.472 + psp_texture->height = texture->h;
1.473 + psp_texture->textureHeight = TextureNextPow2(texture->h);
1.474 + psp_texture->textureWidth = TextureNextPow2(texture->w);
1.475 + psp_texture->format = PixelFormatToPSPFMT(texture->format);
1.476 +
1.477 + switch(psp_texture->format)
1.478 + {
1.479 + case GU_PSM_5650:
1.480 + case GU_PSM_5551:
1.481 + case GU_PSM_4444:
1.482 + psp_texture->bits = 16;
1.483 + break;
1.484 +
1.485 + case GU_PSM_8888:
1.486 + psp_texture->bits = 32;
1.487 + break;
1.488 +
1.489 + default:
1.490 + return -1;
1.491 + }
1.492 +
1.493 + psp_texture->pitch = psp_texture->textureWidth * SDL_BYTESPERPIXEL(texture->format);
1.494 + psp_texture->size = psp_texture->textureHeight*psp_texture->pitch;
1.495 + psp_texture->data = SDL_calloc(1, psp_texture->size);
1.496 +
1.497 + if(!psp_texture->data)
1.498 + {
1.499 + SDL_OutOfMemory();
1.500 + SDL_free(psp_texture);
1.501 + return -1;
1.502 + }
1.503 + texture->driverdata = psp_texture;
1.504 +
1.505 + return 0;
1.506 +}
1.507 +
1.508 +
1.509 +void
1.510 +TextureActivate(SDL_Texture * texture)
1.511 +{
1.512 + PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
1.513 + int scaleMode = GetScaleQuality();
1.514 +
1.515 + // Swizzling is useless with small textures.
1.516 + if (texture->w >= 16 || texture->h >= 16)
1.517 + {
1.518 + TextureSwizzle(psp_texture);
1.519 + }
1.520 +
1.521 + sceGuEnable(GU_TEXTURE_2D);
1.522 + sceGuTexWrap(GU_REPEAT, GU_REPEAT);
1.523 + sceGuTexMode(psp_texture->format, 0, 0, psp_texture->swizzled);
1.524 + sceGuTexFilter(scaleMode, scaleMode); // GU_NEAREST good for tile-map
1.525 + // GU_LINEAR good for scaling
1.526 + sceGuTexImage(0, psp_texture->textureWidth, psp_texture->textureHeight, psp_texture->textureWidth, psp_texture->data);
1.527 + sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
1.528 +}
1.529 +
1.530 +
1.531 +static int
1.532 +PSP_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
1.533 + const SDL_Rect * rect, const void *pixels, int pitch)
1.534 +{
1.535 +// PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
1.536 + const Uint8 *src;
1.537 + Uint8 *dst;
1.538 + int row, length,dpitch;
1.539 + src = pixels;
1.540 +
1.541 + PSP_LockTexture(renderer, texture,rect,(void **)&dst, &dpitch);
1.542 + length = rect->w * SDL_BYTESPERPIXEL(texture->format);
1.543 + if (length == pitch && length == dpitch) {
1.544 + SDL_memcpy(dst, src, length*rect->h);
1.545 + } else {
1.546 + for (row = 0; row < rect->h; ++row) {
1.547 + SDL_memcpy(dst, src, length);
1.548 + src += pitch;
1.549 + dst += dpitch;
1.550 + }
1.551 + }
1.552 +
1.553 + sceKernelDcacheWritebackAll();
1.554 + return 0;
1.555 +}
1.556 +
1.557 +static int
1.558 +PSP_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
1.559 + const SDL_Rect * rect, void **pixels, int *pitch)
1.560 +{
1.561 + PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
1.562 +
1.563 + *pixels =
1.564 + (void *) ((Uint8 *) psp_texture->data + rect->y * psp_texture->pitch +
1.565 + rect->x * SDL_BYTESPERPIXEL(texture->format));
1.566 + *pitch = psp_texture->pitch;
1.567 + return 0;
1.568 +}
1.569 +
1.570 +static void
1.571 +PSP_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1.572 +{
1.573 + PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
1.574 + SDL_Rect rect;
1.575 +
1.576 + /* We do whole texture updates, at least for now */
1.577 + rect.x = 0;
1.578 + rect.y = 0;
1.579 + rect.w = texture->w;
1.580 + rect.h = texture->h;
1.581 + PSP_UpdateTexture(renderer, texture, &rect, psp_texture->data, psp_texture->pitch);
1.582 +}
1.583 +
1.584 +static int
1.585 +PSP_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
1.586 +{
1.587 +
1.588 + return 0;
1.589 +}
1.590 +
1.591 +static int
1.592 +PSP_UpdateViewport(SDL_Renderer * renderer)
1.593 +{
1.594 +
1.595 + return 0;
1.596 +}
1.597 +
1.598 +
1.599 +static void
1.600 +PSP_SetBlendMode(SDL_Renderer * renderer, int blendMode)
1.601 +{
1.602 + PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;
1.603 + if (blendMode != data-> currentBlendMode) {
1.604 + switch (blendMode) {
1.605 + case SDL_BLENDMODE_NONE:
1.606 + sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
1.607 + sceGuDisable(GU_BLEND);
1.608 + break;
1.609 + case SDL_BLENDMODE_BLEND:
1.610 + sceGuTexFunc(GU_TFX_MODULATE , GU_TCC_RGBA);
1.611 + sceGuEnable(GU_BLEND);
1.612 + sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
1.613 + break;
1.614 + case SDL_BLENDMODE_ADD:
1.615 + sceGuTexFunc(GU_TFX_MODULATE , GU_TCC_RGBA);
1.616 + sceGuEnable(GU_BLEND);
1.617 + sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_FIX, 0, 0x00FFFFFF );
1.618 + break;
1.619 + case SDL_BLENDMODE_MOD:
1.620 + sceGuTexFunc(GU_TFX_MODULATE , GU_TCC_RGBA);
1.621 + sceGuEnable(GU_BLEND);
1.622 + sceGuBlendFunc( GU_ADD, GU_FIX, GU_SRC_COLOR, 0, 0);
1.623 + break;
1.624 + }
1.625 + data->currentBlendMode = blendMode;
1.626 + }
1.627 +}
1.628 +
1.629 +
1.630 +
1.631 +static int
1.632 +PSP_RenderClear(SDL_Renderer * renderer)
1.633 +{
1.634 + //start list
1.635 + StartDrawing(renderer);
1.636 + int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r;
1.637 + sceGuClearColor(color);
1.638 + sceGuClearDepth(0);
1.639 + sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT|GU_FAST_CLEAR_BIT);
1.640 +
1.641 + return 0;
1.642 +}
1.643 +
1.644 +static int
1.645 +PSP_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
1.646 + int count)
1.647 +{
1.648 + int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r;
1.649 + int i;
1.650 + StartDrawing(renderer);
1.651 + VertV* vertices = (VertV*)sceGuGetMemory(count*sizeof(VertV));
1.652 +
1.653 + for (i = 0; i < count; ++i) {
1.654 + vertices[i].x = points[i].x;
1.655 + vertices[i].y = points[i].y;
1.656 + vertices[i].z = 0.0f;
1.657 + }
1.658 + sceGuDisable(GU_TEXTURE_2D);
1.659 + sceGuColor(color);
1.660 + sceGuShadeModel(GU_FLAT);
1.661 + sceGuDrawArray(GU_POINTS, GU_VERTEX_32BITF|GU_TRANSFORM_2D, count, 0, vertices);
1.662 + sceGuShadeModel(GU_SMOOTH);
1.663 + sceGuEnable(GU_TEXTURE_2D);
1.664 +
1.665 + return 0;
1.666 +}
1.667 +
1.668 +static int
1.669 +PSP_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
1.670 + int count)
1.671 +{
1.672 + int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r;
1.673 + int i;
1.674 + StartDrawing(renderer);
1.675 + VertV* vertices = (VertV*)sceGuGetMemory(count*sizeof(VertV));
1.676 +
1.677 + for (i = 0; i < count; ++i) {
1.678 + vertices[i].x = points[i].x;
1.679 + vertices[i].y = points[i].y;
1.680 + vertices[i].z = 0.0f;
1.681 + }
1.682 +
1.683 + sceGuDisable(GU_TEXTURE_2D);
1.684 + sceGuColor(color);
1.685 + sceGuShadeModel(GU_FLAT);
1.686 + sceGuDrawArray(GU_LINE_STRIP, GU_VERTEX_32BITF|GU_TRANSFORM_2D, count, 0, vertices);
1.687 + sceGuShadeModel(GU_SMOOTH);
1.688 + sceGuEnable(GU_TEXTURE_2D);
1.689 +
1.690 + return 0;
1.691 +}
1.692 +
1.693 +static int
1.694 +PSP_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects,
1.695 + int count)
1.696 +{
1.697 + int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r;
1.698 + int i;
1.699 + StartDrawing(renderer);
1.700 +
1.701 + for (i = 0; i < count; ++i) {
1.702 + const SDL_FRect *rect = &rects[i];
1.703 + VertV* vertices = (VertV*)sceGuGetMemory((sizeof(VertV)<<1));
1.704 + vertices[0].x = rect->x;
1.705 + vertices[0].y = rect->y;
1.706 + vertices[0].z = 0.0f;
1.707 +
1.708 + vertices[1].x = rect->x + rect->w;
1.709 + vertices[1].y = rect->y + rect->h;
1.710 + vertices[1].z = 0.0f;
1.711 +
1.712 + sceGuDisable(GU_TEXTURE_2D);
1.713 + sceGuColor(color);
1.714 + sceGuShadeModel(GU_FLAT);
1.715 + sceGuDrawArray(GU_SPRITES, GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices);
1.716 + sceGuShadeModel(GU_SMOOTH);
1.717 + sceGuEnable(GU_TEXTURE_2D);
1.718 + }
1.719 +
1.720 + return 0;
1.721 +}
1.722 +
1.723 +
1.724 +#define PI 3.14159265358979f
1.725 +
1.726 +#define radToDeg(x) ((x)*180.f/PI)
1.727 +#define degToRad(x) ((x)*PI/180.f)
1.728 +
1.729 +float MathAbs(float x)
1.730 +{
1.731 + float result;
1.732 +
1.733 + __asm__ volatile (
1.734 + "mtv %1, S000\n"
1.735 + "vabs.s S000, S000\n"
1.736 + "mfv %0, S000\n"
1.737 + : "=r"(result) : "r"(x));
1.738 +
1.739 + return result;
1.740 +}
1.741 +
1.742 +void MathSincos(float r, float *s, float *c)
1.743 +{
1.744 + __asm__ volatile (
1.745 + "mtv %2, S002\n"
1.746 + "vcst.s S003, VFPU_2_PI\n"
1.747 + "vmul.s S002, S002, S003\n"
1.748 + "vrot.p C000, S002, [s, c]\n"
1.749 + "mfv %0, S000\n"
1.750 + "mfv %1, S001\n"
1.751 + : "=r"(*s), "=r"(*c): "r"(r));
1.752 +}
1.753 +
1.754 +void Swap(float *a, float *b)
1.755 +{
1.756 + float n=*a;
1.757 + *a = *b;
1.758 + *b = n;
1.759 +}
1.760 +
1.761 +static int
1.762 +PSP_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
1.763 + const SDL_Rect * srcrect, const SDL_FRect * dstrect)
1.764 +{
1.765 + float x, y, width, height;
1.766 + float u0, v0, u1, v1;
1.767 + unsigned char alpha;
1.768 +
1.769 + x = dstrect->x;
1.770 + y = dstrect->y;
1.771 + width = dstrect->w;
1.772 + height = dstrect->h;
1.773 +
1.774 + u0 = srcrect->x;
1.775 + v0 = srcrect->y;
1.776 + u1 = srcrect->x + srcrect->w;
1.777 + v1 = srcrect->y + srcrect->h;
1.778 +
1.779 + alpha = texture->a;
1.780 +
1.781 + StartDrawing(renderer);
1.782 + TextureActivate(texture);
1.783 + PSP_SetBlendMode(renderer, renderer->blendMode);
1.784 +
1.785 + if(alpha != 255)
1.786 + {
1.787 + sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA);
1.788 + sceGuColor(GU_RGBA(255, 255, 255, alpha));
1.789 + }else{
1.790 + sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
1.791 + sceGuColor(0xFFFFFFFF);
1.792 + }
1.793 +
1.794 + if((MathAbs(u1) - MathAbs(u0)) < 64.0f)
1.795 + {
1.796 + VertTV* vertices = (VertTV*)sceGuGetMemory((sizeof(VertTV))<<1);
1.797 +
1.798 + vertices[0].u = u0;
1.799 + vertices[0].v = v0;
1.800 + vertices[0].x = x;
1.801 + vertices[0].y = y;
1.802 + vertices[0].z = 0;
1.803 +
1.804 + vertices[1].u = u1;
1.805 + vertices[1].v = v1;
1.806 + vertices[1].x = x + width;
1.807 + vertices[1].y = y + height;
1.808 + vertices[1].z = 0;
1.809 +
1.810 + sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices);
1.811 + }
1.812 + else
1.813 + {
1.814 + float start, end;
1.815 + float curU = u0;
1.816 + float curX = x;
1.817 + float endX = x + width;
1.818 + float slice = 64.0f;
1.819 + float ustep = (u1 - u0)/width * slice;
1.820 +
1.821 + if(ustep < 0.0f)
1.822 + ustep = -ustep;
1.823 +
1.824 + for(start = 0, end = width; start < end; start += slice)
1.825 + {
1.826 + VertTV* vertices = (VertTV*)sceGuGetMemory((sizeof(VertTV))<<1);
1.827 +
1.828 + float polyWidth = ((curX + slice) > endX) ? (endX - curX) : slice;
1.829 + float sourceWidth = ((curU + ustep) > u1) ? (u1 - curU) : ustep;
1.830 +
1.831 + vertices[0].u = curU;
1.832 + vertices[0].v = v0;
1.833 + vertices[0].x = curX;
1.834 + vertices[0].y = y;
1.835 + vertices[0].z = 0;
1.836 +
1.837 + curU += sourceWidth;
1.838 + curX += polyWidth;
1.839 +
1.840 + vertices[1].u = curU;
1.841 + vertices[1].v = v1;
1.842 + vertices[1].x = curX;
1.843 + vertices[1].y = (y + height);
1.844 + vertices[1].z = 0;
1.845 +
1.846 + sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices);
1.847 + }
1.848 + }
1.849 +
1.850 + if(alpha != 255)
1.851 + sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
1.852 + return 0;
1.853 +}
1.854 +
1.855 +static int
1.856 +PSP_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1.857 + Uint32 pixel_format, void * pixels, int pitch)
1.858 +
1.859 +{
1.860 + return 0;
1.861 +}
1.862 +
1.863 +
1.864 +static int
1.865 +PSP_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
1.866 + const SDL_Rect * srcrect, const SDL_FRect * dstrect,
1.867 + const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
1.868 +{
1.869 + float x, y, width, height;
1.870 + float u0, v0, u1, v1;
1.871 + unsigned char alpha;
1.872 + float centerx, centery;
1.873 +
1.874 + x = dstrect->x;
1.875 + y = dstrect->y;
1.876 + width = dstrect->w;
1.877 + height = dstrect->h;
1.878 +
1.879 + u0 = srcrect->x;
1.880 + v0 = srcrect->y;
1.881 + u1 = srcrect->x + srcrect->w;
1.882 + v1 = srcrect->y + srcrect->h;
1.883 +
1.884 + centerx = center->x;
1.885 + centery = center->y;
1.886 +
1.887 + alpha = texture->a;
1.888 +
1.889 + StartDrawing(renderer);
1.890 + TextureActivate(texture);
1.891 + PSP_SetBlendMode(renderer, renderer->blendMode);
1.892 +
1.893 + if(alpha != 255)
1.894 + {
1.895 + sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA);
1.896 + sceGuColor(GU_RGBA(255, 255, 255, alpha));
1.897 + }else{
1.898 + sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
1.899 + sceGuColor(0xFFFFFFFF);
1.900 + }
1.901 +
1.902 +// x += width * 0.5f;
1.903 +// y += height * 0.5f;
1.904 + x += centerx;
1.905 + y += centery;
1.906 +
1.907 + float c, s;
1.908 +
1.909 + MathSincos(degToRad(angle), &s, &c);
1.910 +
1.911 +// width *= 0.5f;
1.912 +// height *= 0.5f;
1.913 + width -= centerx;
1.914 + height -= centery;
1.915 +
1.916 +
1.917 + float cw = c*width;
1.918 + float sw = s*width;
1.919 + float ch = c*height;
1.920 + float sh = s*height;
1.921 +
1.922 + VertTV* vertices = (VertTV*)sceGuGetMemory(sizeof(VertTV)<<2);
1.923 +
1.924 + vertices[0].u = u0;
1.925 + vertices[0].v = v0;
1.926 + vertices[0].x = x - cw + sh;
1.927 + vertices[0].y = y - sw - ch;
1.928 + vertices[0].z = 0;
1.929 +
1.930 + vertices[1].u = u0;
1.931 + vertices[1].v = v1;
1.932 + vertices[1].x = x - cw - sh;
1.933 + vertices[1].y = y - sw + ch;
1.934 + vertices[1].z = 0;
1.935 +
1.936 + vertices[2].u = u1;
1.937 + vertices[2].v = v1;
1.938 + vertices[2].x = x + cw - sh;
1.939 + vertices[2].y = y + sw + ch;
1.940 + vertices[2].z = 0;
1.941 +
1.942 + vertices[3].u = u1;
1.943 + vertices[3].v = v0;
1.944 + vertices[3].x = x + cw + sh;
1.945 + vertices[3].y = y + sw - ch;
1.946 + vertices[3].z = 0;
1.947 +
1.948 + if (flip & SDL_FLIP_HORIZONTAL) {
1.949 + Swap(&vertices[0].v, &vertices[2].v);
1.950 + Swap(&vertices[1].v, &vertices[3].v);
1.951 + }
1.952 + if (flip & SDL_FLIP_VERTICAL) {
1.953 + Swap(&vertices[0].u, &vertices[2].u);
1.954 + Swap(&vertices[1].u, &vertices[3].u);
1.955 + }
1.956 +
1.957 + sceGuDrawArray(GU_TRIANGLE_FAN, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 4, 0, vertices);
1.958 +
1.959 + if(alpha != 255)
1.960 + sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
1.961 + return 0;
1.962 +}
1.963 +
1.964 +static void
1.965 +PSP_RenderPresent(SDL_Renderer * renderer)
1.966 +{
1.967 + PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;
1.968 + if(!data->displayListAvail)
1.969 + return;
1.970 +
1.971 + data->displayListAvail = SDL_FALSE;
1.972 + sceGuFinish();
1.973 + sceGuSync(0,0);
1.974 +
1.975 +// if(data->vsync)
1.976 + sceDisplayWaitVblankStart();
1.977 +
1.978 + data->backbuffer = data->frontbuffer;
1.979 + data->frontbuffer = vabsptr(sceGuSwapBuffers());
1.980 +
1.981 +}
1.982 +
1.983 +static void
1.984 +PSP_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1.985 +{
1.986 + PSP_RenderData *renderdata = (PSP_RenderData *) renderer->driverdata;
1.987 + PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
1.988 +
1.989 + if (renderdata == 0)
1.990 + return;
1.991 +
1.992 + if(psp_texture == 0)
1.993 + return;
1.994 +
1.995 + if(psp_texture->data != 0)
1.996 + {
1.997 + free(psp_texture->data);
1.998 + }
1.999 + free(texture);
1.1000 + texture->driverdata = NULL;
1.1001 +}
1.1002 +
1.1003 +static void
1.1004 +PSP_DestroyRenderer(SDL_Renderer * renderer)
1.1005 +{
1.1006 + PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;
1.1007 + if (data) {
1.1008 + if (!data->initialized)
1.1009 + return;
1.1010 +
1.1011 + StartDrawing(renderer);
1.1012 +
1.1013 + sceGuTerm();
1.1014 +// vfree(data->backbuffer);
1.1015 +// vfree(data->frontbuffer);
1.1016 +
1.1017 + data->initialized = SDL_FALSE;
1.1018 + data->displayListAvail = SDL_FALSE;
1.1019 + SDL_free(data);
1.1020 + }
1.1021 + SDL_free(renderer);
1.1022 +}
1.1023 +
1.1024 +#endif /* SDL_VIDEO_RENDER_PSP */
1.1025 +
1.1026 +/* vi: set ts=4 sw=4 expandtab: */
1.1027 +