src/render/psp/SDL_render_psp.c
changeset 7009 161b7b6a5303
child 7037 3fedf1f25b94
equal deleted inserted replaced
7008:e0f05e041a72 7009:161b7b6a5303
       
     1 /*
       
     2   Simple DirectMedia Layer
       
     3   Copyright (C) 1997-2013 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_config.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 
       
    46 extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
       
    47 
       
    48 
       
    49 static SDL_Renderer *PSP_CreateRenderer(SDL_Window * window, Uint32 flags);
       
    50 static void PSP_WindowEvent(SDL_Renderer * renderer,
       
    51                              const SDL_WindowEvent *event);
       
    52 static int PSP_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
       
    53 static int PSP_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
       
    54                               const SDL_Rect * rect, const void *pixels,
       
    55                               int pitch);
       
    56 static int PSP_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
       
    57                             const SDL_Rect * rect, void **pixels, int *pitch);
       
    58 static void PSP_UnlockTexture(SDL_Renderer * renderer,
       
    59                                SDL_Texture * texture);
       
    60 static int PSP_SetRenderTarget(SDL_Renderer * renderer,
       
    61                                  SDL_Texture * texture);
       
    62 static int PSP_UpdateViewport(SDL_Renderer * renderer);
       
    63 static int PSP_RenderClear(SDL_Renderer * renderer);
       
    64 static int PSP_RenderDrawPoints(SDL_Renderer * renderer,
       
    65                                  const SDL_FPoint * points, int count);
       
    66 static int PSP_RenderDrawLines(SDL_Renderer * renderer,
       
    67                                 const SDL_FPoint * points, int count);
       
    68 static int PSP_RenderFillRects(SDL_Renderer * renderer,
       
    69                                 const SDL_FRect * rects, int count);
       
    70 static int PSP_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
       
    71                            const SDL_Rect * srcrect,
       
    72                            const SDL_FRect * dstrect);
       
    73 static int PSP_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
       
    74                     Uint32 pixel_format, void * pixels, int pitch);
       
    75 static 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);
       
    78 static void PSP_RenderPresent(SDL_Renderer * renderer);
       
    79 static void PSP_DestroyTexture(SDL_Renderer * renderer,
       
    80                                 SDL_Texture * texture);
       
    81 static void PSP_DestroyRenderer(SDL_Renderer * renderer);
       
    82 
       
    83 /*
       
    84 SDL_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 */
       
    95 SDL_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 
       
   117 static 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 
       
   126 typedef 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 
       
   142 typedef 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 
       
   157 typedef struct
       
   158 {	
       
   159 	float	x, y, z;
       
   160 } VertV;
       
   161 
       
   162 
       
   163 typedef struct
       
   164 {
       
   165 	float	u, v;
       
   166 	float	x, y, z;
       
   167 	
       
   168 } VertTV;
       
   169 
       
   170 
       
   171 // Return next power of 2
       
   172 static int 
       
   173 TextureNextPow2(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 
       
   187 static int
       
   188 GetScaleQuality(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 
       
   199 static int
       
   200 PixelFormatToPSPFMT(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 
       
   216 void 
       
   217 StartDrawing(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 
       
   228 int 
       
   229 TextureSwizzle(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 }
       
   274 int 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 
       
   339 SDL_Renderer *
       
   340 PSP_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;
       
   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 
       
   451 static void
       
   452 PSP_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
       
   453 {
       
   454 
       
   455 }
       
   456 
       
   457 
       
   458 static int
       
   459 PSP_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_OutOfMemory();
       
   497 		SDL_free(psp_texture);
       
   498 		return -1;
       
   499 	}
       
   500     texture->driverdata = psp_texture;
       
   501     
       
   502     return 0;
       
   503 }
       
   504 
       
   505 
       
   506 void 
       
   507 TextureActivate(SDL_Texture * texture)
       
   508 {		
       
   509 	PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
       
   510 	int scaleMode = GetScaleQuality();
       
   511 	
       
   512 	// Swizzling is useless with small textures.
       
   513     if (texture->w >= 16 || texture->h >= 16)
       
   514     {
       
   515 		TextureSwizzle(psp_texture);	
       
   516     }
       
   517     
       
   518 	sceGuEnable(GU_TEXTURE_2D);
       
   519 	sceGuTexWrap(GU_REPEAT, GU_REPEAT);
       
   520 	sceGuTexMode(psp_texture->format, 0, 0, psp_texture->swizzled);
       
   521 	sceGuTexFilter(scaleMode, scaleMode); // GU_NEAREST good for tile-map
       
   522 										  // GU_LINEAR good for scaling	
       
   523 	sceGuTexImage(0, psp_texture->textureWidth, psp_texture->textureHeight, psp_texture->textureWidth, psp_texture->data);
       
   524 	sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
       
   525 }
       
   526 
       
   527 
       
   528 static int
       
   529 PSP_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
       
   530                    const SDL_Rect * rect, const void *pixels, int pitch)
       
   531 {
       
   532 //	PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
       
   533     const Uint8 *src;
       
   534     Uint8 *dst;
       
   535     int row, length,dpitch;
       
   536     src = pixels;
       
   537     
       
   538     PSP_LockTexture(renderer, texture,rect,(void **)&dst, &dpitch);
       
   539     length = rect->w * SDL_BYTESPERPIXEL(texture->format);
       
   540     if (length == pitch && length == dpitch) {
       
   541         SDL_memcpy(dst, src, length*rect->h);
       
   542     } else {
       
   543         for (row = 0; row < rect->h; ++row) {
       
   544             SDL_memcpy(dst, src, length);
       
   545             src += pitch;
       
   546             dst += dpitch;
       
   547         }
       
   548     }
       
   549     
       
   550 	sceKernelDcacheWritebackAll();
       
   551     return 0;
       
   552 }
       
   553 
       
   554 static int
       
   555 PSP_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
       
   556                  const SDL_Rect * rect, void **pixels, int *pitch)
       
   557 {
       
   558 	PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
       
   559 
       
   560     *pixels =
       
   561         (void *) ((Uint8 *) psp_texture->data + rect->y * psp_texture->pitch +
       
   562                   rect->x * SDL_BYTESPERPIXEL(texture->format));
       
   563     *pitch = psp_texture->pitch;
       
   564     return 0;
       
   565 }
       
   566 
       
   567 static void
       
   568 PSP_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
       
   569 {
       
   570 	PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
       
   571     SDL_Rect rect;
       
   572 
       
   573     /* We do whole texture updates, at least for now */
       
   574     rect.x = 0;
       
   575     rect.y = 0;
       
   576     rect.w = texture->w;
       
   577     rect.h = texture->h;
       
   578     PSP_UpdateTexture(renderer, texture, &rect, psp_texture->data, psp_texture->pitch);
       
   579 }
       
   580 
       
   581 static int
       
   582 PSP_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
       
   583 {
       
   584 
       
   585     return 0;
       
   586 }
       
   587 
       
   588 static int
       
   589 PSP_UpdateViewport(SDL_Renderer * renderer)
       
   590 {
       
   591 
       
   592     return 0;
       
   593 }
       
   594 
       
   595 
       
   596 static void
       
   597 PSP_SetBlendMode(SDL_Renderer * renderer, int blendMode)
       
   598 {
       
   599 	PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;				
       
   600     if (blendMode != data-> currentBlendMode) {
       
   601         switch (blendMode) {
       
   602         case SDL_BLENDMODE_NONE:
       
   603         		sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);        
       
   604 				sceGuDisable(GU_BLEND);
       
   605             break;
       
   606         case SDL_BLENDMODE_BLEND:
       
   607         		sceGuTexFunc(GU_TFX_MODULATE , GU_TCC_RGBA);
       
   608 				sceGuEnable(GU_BLEND);
       
   609 				sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
       
   610             break;
       
   611         case SDL_BLENDMODE_ADD:
       
   612         		sceGuTexFunc(GU_TFX_MODULATE , GU_TCC_RGBA);
       
   613 				sceGuEnable(GU_BLEND);
       
   614 				sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_FIX, 0, 0x00FFFFFF );
       
   615             break;
       
   616         case SDL_BLENDMODE_MOD:
       
   617         		sceGuTexFunc(GU_TFX_MODULATE , GU_TCC_RGBA);
       
   618 				sceGuEnable(GU_BLEND);
       
   619 				sceGuBlendFunc( GU_ADD, GU_FIX, GU_SRC_COLOR, 0, 0);
       
   620             break;
       
   621         }
       
   622         data->currentBlendMode = blendMode;
       
   623     }
       
   624 }
       
   625 
       
   626 
       
   627 
       
   628 static int
       
   629 PSP_RenderClear(SDL_Renderer * renderer)
       
   630 {					
       
   631 		//start list
       
   632 	StartDrawing(renderer);
       
   633 	int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r;		
       
   634 	sceGuClearColor(color);
       
   635 	sceGuClearDepth(0);
       
   636 	sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT|GU_FAST_CLEAR_BIT);
       
   637 
       
   638     return 0;
       
   639 }
       
   640 
       
   641 static int
       
   642 PSP_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
       
   643                       int count)
       
   644 {
       
   645 	int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r;
       
   646 	int i;
       
   647 	StartDrawing(renderer);		
       
   648 	VertV* vertices = (VertV*)sceGuGetMemory(count*sizeof(VertV)); 
       
   649 	
       
   650  	for (i = 0; i < count; ++i) {
       
   651 			vertices[i].x = points[i].x;
       
   652 			vertices[i].y = points[i].y;
       
   653 			vertices[i].z = 0.0f;
       
   654 	}
       
   655 	sceGuDisable(GU_TEXTURE_2D);
       
   656 	sceGuColor(color);		
       
   657 	sceGuShadeModel(GU_FLAT);
       
   658 	sceGuDrawArray(GU_POINTS, GU_VERTEX_32BITF|GU_TRANSFORM_2D, count, 0, vertices);
       
   659 	sceGuShadeModel(GU_SMOOTH);
       
   660 	sceGuEnable(GU_TEXTURE_2D);			
       
   661 
       
   662     return 0;
       
   663 }
       
   664 
       
   665 static int
       
   666 PSP_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
       
   667                      int count)
       
   668 {
       
   669 	int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r;
       
   670 	int i;
       
   671 	StartDrawing(renderer);
       
   672 	VertV* vertices = (VertV*)sceGuGetMemory(count*sizeof(VertV)); 
       
   673 	
       
   674 	for (i = 0; i < count; ++i) {
       
   675 			vertices[i].x = points[i].x;
       
   676 			vertices[i].y = points[i].y;
       
   677 			vertices[i].z = 0.0f;
       
   678 	}
       
   679 
       
   680 	sceGuDisable(GU_TEXTURE_2D);
       
   681 	sceGuColor(color);
       
   682 	sceGuShadeModel(GU_FLAT);
       
   683 	sceGuDrawArray(GU_LINE_STRIP, GU_VERTEX_32BITF|GU_TRANSFORM_2D, count, 0, vertices);
       
   684 	sceGuShadeModel(GU_SMOOTH);
       
   685 	sceGuEnable(GU_TEXTURE_2D);
       
   686 	 
       
   687     return 0;
       
   688 }
       
   689 
       
   690 static int
       
   691 PSP_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects,
       
   692                      int count)
       
   693 {
       
   694 	int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r;
       
   695 	int i;	
       
   696 	StartDrawing(renderer);
       
   697 	
       
   698 	for (i = 0; i < count; ++i) {
       
   699     	const SDL_FRect *rect = &rects[i];
       
   700 		VertV* vertices = (VertV*)sceGuGetMemory((sizeof(VertV)<<1));
       
   701 		vertices[0].x = rect->x;
       
   702 		vertices[0].y = rect->y;
       
   703 		vertices[0].z = 0.0f;
       
   704 
       
   705 		vertices[1].x = rect->x + rect->w;
       
   706 		vertices[1].y = rect->y + rect->h;
       
   707 		vertices[1].z = 0.0f;
       
   708 		
       
   709 		sceGuDisable(GU_TEXTURE_2D);
       
   710 		sceGuColor(color);			
       
   711 		sceGuShadeModel(GU_FLAT);
       
   712 		sceGuDrawArray(GU_SPRITES, GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices);
       
   713 		sceGuShadeModel(GU_SMOOTH);
       
   714 		sceGuEnable(GU_TEXTURE_2D);
       
   715     }
       
   716 		
       
   717     return 0;
       
   718 }
       
   719 
       
   720 
       
   721 #define PI   3.14159265358979f
       
   722 
       
   723 #define radToDeg(x) ((x)*180.f/PI)
       
   724 #define degToRad(x) ((x)*PI/180.f)
       
   725 
       
   726 float MathAbs(float x)
       
   727 {
       
   728 	float result;
       
   729 
       
   730 	__asm__ volatile (
       
   731 		"mtv      %1, S000\n"
       
   732 		"vabs.s   S000, S000\n"
       
   733 		"mfv      %0, S000\n"
       
   734 	: "=r"(result) : "r"(x));
       
   735 
       
   736 	return result;
       
   737 }
       
   738 
       
   739 void MathSincos(float r, float *s, float *c)
       
   740 {
       
   741 	__asm__ volatile (
       
   742 		"mtv      %2, S002\n"
       
   743 		"vcst.s   S003, VFPU_2_PI\n"
       
   744 		"vmul.s   S002, S002, S003\n"
       
   745 		"vrot.p   C000, S002, [s, c]\n"
       
   746 		"mfv      %0, S000\n"
       
   747 		"mfv      %1, S001\n"
       
   748 	: "=r"(*s), "=r"(*c): "r"(r));
       
   749 }
       
   750 
       
   751 void Swap(float *a, float *b)
       
   752 {
       
   753 	float n=*a;
       
   754 	*a = *b;
       
   755 	*b = n;
       
   756 }
       
   757 
       
   758 static int
       
   759 PSP_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
       
   760                 const SDL_Rect * srcrect, const SDL_FRect * dstrect)
       
   761 {
       
   762 	float x, y, width, height;
       
   763 	float u0, v0, u1, v1;
       
   764 	unsigned char alpha;
       
   765 	
       
   766 	x = dstrect->x;
       
   767 	y = dstrect->y;
       
   768 	width = dstrect->w;
       
   769 	height = dstrect->h;
       
   770 
       
   771 	u0 = srcrect->x;
       
   772 	v0 = srcrect->y;
       
   773 	u1 = srcrect->x + srcrect->w;
       
   774 	v1 = srcrect->y + srcrect->h;
       
   775 	
       
   776 	alpha = texture->a;
       
   777 	
       
   778 	StartDrawing(renderer);
       
   779 	TextureActivate(texture);
       
   780 	PSP_SetBlendMode(renderer, renderer->blendMode);
       
   781 	
       
   782 	if(alpha != 255)
       
   783 	{
       
   784 		sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA);
       
   785 		sceGuColor(GU_RGBA(255, 255, 255, alpha));
       
   786 	}else{
       
   787 		sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
       
   788 		sceGuColor(0xFFFFFFFF);
       
   789 	}
       
   790 		
       
   791 	if((MathAbs(u1) - MathAbs(u0)) < 64.0f)
       
   792 	{
       
   793 		VertTV* vertices = (VertTV*)sceGuGetMemory((sizeof(VertTV))<<1);
       
   794 
       
   795 		vertices[0].u = u0;
       
   796 		vertices[0].v = v0;
       
   797 		vertices[0].x = x;
       
   798 		vertices[0].y = y; 
       
   799 		vertices[0].z = 0;
       
   800 
       
   801 		vertices[1].u = u1;
       
   802 		vertices[1].v = v1;
       
   803 		vertices[1].x = x + width;
       
   804 		vertices[1].y = y + height;
       
   805 		vertices[1].z = 0;
       
   806 
       
   807 		sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices);
       
   808 	}
       
   809 	else
       
   810 	{
       
   811 		float start, end;
       
   812 		float curU = u0;
       
   813 		float curX = x;
       
   814 		float endX = x + width;
       
   815 		float slice = 64.0f;
       
   816 		float ustep = (u1 - u0)/width * slice;
       
   817 	
       
   818 		if(ustep < 0.0f)
       
   819 			ustep = -ustep;
       
   820 
       
   821 		for(start = 0, end = width; start < end; start += slice)
       
   822 		{
       
   823 			VertTV* vertices = (VertTV*)sceGuGetMemory((sizeof(VertTV))<<1);
       
   824 
       
   825 			float polyWidth = ((curX + slice) > endX) ? (endX - curX) : slice;
       
   826 			float sourceWidth = ((curU + ustep) > u1) ? (u1 - curU) : ustep;
       
   827 
       
   828 			vertices[0].u = curU;
       
   829 			vertices[0].v = v0;
       
   830 			vertices[0].x = curX;
       
   831 			vertices[0].y = y; 
       
   832 			vertices[0].z = 0;
       
   833 
       
   834 			curU += sourceWidth;
       
   835 			curX += polyWidth;
       
   836 
       
   837 			vertices[1].u = curU;
       
   838 			vertices[1].v = v1;
       
   839 			vertices[1].x = curX;
       
   840 			vertices[1].y = (y + height);
       
   841 			vertices[1].z = 0;
       
   842 
       
   843 			sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices);
       
   844 		}
       
   845 	}
       
   846 	
       
   847 	if(alpha != 255)
       
   848 		sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
       
   849     return 0;
       
   850 }
       
   851 
       
   852 static int
       
   853 PSP_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
       
   854                     Uint32 pixel_format, void * pixels, int pitch)
       
   855 
       
   856 {
       
   857 		return 0;
       
   858 }
       
   859 
       
   860 
       
   861 static int
       
   862 PSP_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
       
   863                 const SDL_Rect * srcrect, const SDL_FRect * dstrect,
       
   864                 const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
       
   865 {
       
   866 	float x, y, width, height;
       
   867 	float u0, v0, u1, v1;
       
   868 	unsigned char alpha;
       
   869 	float centerx, centery;
       
   870 	
       
   871 	x = dstrect->x;
       
   872 	y = dstrect->y;
       
   873 	width = dstrect->w;
       
   874 	height = dstrect->h;
       
   875 
       
   876 	u0 = srcrect->x;
       
   877 	v0 = srcrect->y;
       
   878 	u1 = srcrect->x + srcrect->w;
       
   879 	v1 = srcrect->y + srcrect->h;
       
   880 	
       
   881     centerx = center->x;
       
   882     centery = center->y;
       
   883 		
       
   884 	alpha = texture->a;
       
   885 	
       
   886 	StartDrawing(renderer);
       
   887 	TextureActivate(texture);
       
   888 	PSP_SetBlendMode(renderer, renderer->blendMode);
       
   889 	
       
   890 	if(alpha != 255)
       
   891 	{
       
   892 		sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA);
       
   893 		sceGuColor(GU_RGBA(255, 255, 255, alpha));
       
   894 	}else{
       
   895 		sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
       
   896 		sceGuColor(0xFFFFFFFF);
       
   897 	}
       
   898 
       
   899 //		x += width * 0.5f;
       
   900 //		y += height * 0.5f;
       
   901 	x += centerx;
       
   902 	y += centery;		
       
   903 	
       
   904 	float c, s;
       
   905 	
       
   906 	MathSincos(degToRad(angle), &s, &c);
       
   907 	
       
   908 //		width *= 0.5f;
       
   909 //		height *= 0.5f;
       
   910 	width  -= centerx;
       
   911 	height -= centery;		
       
   912 	
       
   913 	
       
   914 	float cw = c*width;
       
   915 	float sw = s*width;
       
   916 	float ch = c*height;
       
   917 	float sh = s*height;
       
   918 
       
   919 	VertTV* vertices = (VertTV*)sceGuGetMemory(sizeof(VertTV)<<2);
       
   920 
       
   921 	vertices[0].u = u0;
       
   922 	vertices[0].v = v0;
       
   923 	vertices[0].x = x - cw + sh;
       
   924 	vertices[0].y = y - sw - ch;
       
   925 	vertices[0].z = 0;
       
   926 			
       
   927 	vertices[1].u = u0;
       
   928 	vertices[1].v = v1;
       
   929 	vertices[1].x = x - cw - sh;
       
   930 	vertices[1].y = y - sw + ch;
       
   931 	vertices[1].z = 0;
       
   932 	
       
   933 	vertices[2].u = u1;
       
   934 	vertices[2].v = v1;
       
   935 	vertices[2].x = x + cw - sh;
       
   936 	vertices[2].y = y + sw + ch;
       
   937 	vertices[2].z = 0;
       
   938 	
       
   939 	vertices[3].u = u1;
       
   940 	vertices[3].v = v0;
       
   941 	vertices[3].x = x + cw + sh;
       
   942 	vertices[3].y = y + sw - ch;
       
   943 	vertices[3].z = 0;
       
   944 	
       
   945 	if (flip & SDL_FLIP_HORIZONTAL) {
       
   946 				Swap(&vertices[0].v, &vertices[2].v);
       
   947 				Swap(&vertices[1].v, &vertices[3].v);
       
   948 	}
       
   949 	if (flip & SDL_FLIP_VERTICAL) {
       
   950 				Swap(&vertices[0].u, &vertices[2].u);
       
   951 				Swap(&vertices[1].u, &vertices[3].u);
       
   952 	}  	
       
   953 
       
   954 	sceGuDrawArray(GU_TRIANGLE_FAN, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 4, 0, vertices);
       
   955 			
       
   956 	if(alpha != 255)
       
   957 		sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
       
   958     return 0;
       
   959 }
       
   960 
       
   961 static void
       
   962 PSP_RenderPresent(SDL_Renderer * renderer)
       
   963 {
       
   964     PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;
       
   965 	if(!data->displayListAvail)
       
   966 		return;
       
   967 	
       
   968 	data->displayListAvail = SDL_FALSE;
       
   969 	sceGuFinish();
       
   970 	sceGuSync(0,0);
       
   971 	
       
   972 //	if(data->vsync)
       
   973 		sceDisplayWaitVblankStart();
       
   974 			
       
   975     data->backbuffer = data->frontbuffer;
       
   976     data->frontbuffer = vabsptr(sceGuSwapBuffers());
       
   977 		
       
   978 }
       
   979 
       
   980 static void
       
   981 PSP_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
       
   982 {
       
   983 	PSP_RenderData *renderdata = (PSP_RenderData *) renderer->driverdata;
       
   984 	PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
       
   985 	
       
   986 	if (renderdata == 0)
       
   987 		return;
       
   988 
       
   989 	if(psp_texture == 0)
       
   990 		return;
       
   991 
       
   992 	if(psp_texture->data != 0)
       
   993 	{
       
   994 		free(psp_texture->data);
       
   995 	}
       
   996 	free(texture);
       
   997 	texture->driverdata = NULL;
       
   998 }
       
   999 
       
  1000 static void
       
  1001 PSP_DestroyRenderer(SDL_Renderer * renderer)
       
  1002 {
       
  1003     PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;
       
  1004     if (data) {
       
  1005 		if (!data->initialized)
       
  1006 			return;
       
  1007 
       
  1008 		StartDrawing(renderer);
       
  1009 		
       
  1010 		sceGuTerm();
       
  1011 //		vfree(data->backbuffer);
       
  1012 //		vfree(data->frontbuffer);
       
  1013 		
       
  1014 		data->initialized = SDL_FALSE;
       
  1015 		data->displayListAvail = SDL_FALSE;
       
  1016         SDL_free(data);
       
  1017     }
       
  1018     SDL_free(renderer);
       
  1019 }
       
  1020 
       
  1021 #endif /* SDL_VIDEO_RENDER_PSP */
       
  1022 
       
  1023 /* vi: set ts=4 sw=4 expandtab: */
       
  1024