src/render/psp/SDL_render_psp.c
changeset 7009 161b7b6a5303
child 7037 3fedf1f25b94
     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 +