UpdateRect support and 32 bpp support (thanks brijohn!)

slight performance decrease on FlipHWSurface :(
This commit is contained in:
dborth 2009-07-23 06:25:50 +00:00
parent c992e47e46
commit 379044f0e1

View file

@ -26,6 +26,8 @@
// SDL internal includes.
#include "../SDL_sysvideo.h"
#include "../SDL_pixels_c.h"
#include "SDL_timer.h"
#include "SDL_thread.h"
// SDL Wii specifics.
#include <gccore.h>
@ -37,6 +39,8 @@
#include "SDL_wiievents_c.h"
static const char WIIVID_DRIVER_NAME[] = "wii";
static SDL_Thread * videothread;
static SDL_mutex * videomutex;
/*** SDL ***/
static SDL_Rect mode_320;
@ -58,7 +62,6 @@ static unsigned int *xfb[2] = { NULL, NULL }; // Double buffered
static int whichfb = 0; // Switch
static GXRModeObj* vmode = 0;
static unsigned char texturemem[TEXTUREMEM_SIZE] __attribute__((aligned(32))); // GX texture
static unsigned char textureconvert[TEXTUREMEM_SIZE] __attribute__((aligned(32))); // 565 mem
/*** GX ***/
#define DEFAULT_FIFO_SIZE 256 * 1024
@ -102,7 +105,7 @@ static camera cam = {
* Scaler Support Functions
***************************************************************************/
static void
draw_init (SDL_Surface *current)
draw_init (SDL_Surface *current, int bpp)
{
GX_ClearVtxDesc ();
GX_SetVtxDesc (GX_VA_POS, GX_INDEX8);
@ -130,10 +133,10 @@ draw_init (SDL_Surface *current)
GX_InvVtxCache (); // update vertex cache
// initialize the texture obj we are going to use
GX_InitTexObj (&texobj, texturemem, current->w, current->h, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE);
// force texture filtering OFF
//GX_InitTexObjLOD(&texobj,GX_NEAR,GX_NEAR_MIP_NEAR,2.5,9.0,0.0,GX_FALSE,GX_FALSE,GX_ANISO_1); // original/unfiltered video mode: force texture filtering OFF
if (bpp == 8 || bpp == 16)
GX_InitTexObj (&texobj, texturemem, current->w, current->h, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE);
else
GX_InitTexObj (&texobj, texturemem, current->w, current->h, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
GX_LoadTexObj (&texobj, GX_TEXMAP0); // load texture object so its ready to use
}
@ -165,6 +168,41 @@ draw_square (Mtx v)
GX_End ();
}
static int quit_flip_thread = 0;
int flip_thread(void * arg)
{
while(1)
{
if (quit_flip_thread)
break;
whichfb ^= 1;
SDL_mutexP(videomutex);
// clear texture objects
GX_InvVtxCache();
GX_InvalidateTexAll();
// load texture into GX
DCFlushRange(texturemem, TEXTUREMEM_SIZE);
GX_SetNumChans(1);
GX_LoadTexObj(&texobj, GX_TEXMAP0);
draw_square(view); // render textured quad
GX_CopyDisp(xfb[whichfb], GX_TRUE);
GX_DrawDone ();
SDL_mutexV(videomutex);
VIDEO_SetNextFramebuffer(xfb[whichfb]);
VIDEO_Flush();
VIDEO_WaitVSync();
}
return 0;
}
void
WII_InitVideoSystem()
{
@ -299,9 +337,9 @@ SDL_Surface *WII_SetVideoMode(_THIS, SDL_Surface *current,
return NULL;
}
if(bpp != 8 && bpp != 16 && bpp != 24)
if(bpp != 8 && bpp != 16 && bpp != 24 && bpp != 32)
{
SDL_SetError("Resolution (%d bpp) is unsupported (8/16/24 bpp only).",
SDL_SetError("Resolution (%d bpp) is unsupported (8/16/24/32 bpp only).",
bpp);
return NULL;
}
@ -337,7 +375,7 @@ SDL_Surface *WII_SetVideoMode(_THIS, SDL_Surface *current,
SDL_memset(this->hidden->buffer, 0, width * height * bytes_per_pixel);
// Set up the new mode framebuffer
current->flags = SDL_DOUBLEBUF | (flags & SDL_FULLSCREEN) | (flags & SDL_HWPALETTE);
current->flags = (flags & SDL_DOUBLEBUF) | (flags & SDL_FULLSCREEN) | (flags & SDL_HWPALETTE);
current->w = width;
current->h = height;
current->pitch = current->w * bytes_per_pixel;
@ -348,8 +386,8 @@ SDL_Surface *WII_SetVideoMode(_THIS, SDL_Surface *current,
this->hidden->height = current->h;
this->hidden->pitch = current->pitch;
draw_init(current);
draw_init(current, bpp);
videothread = SDL_CreateThread(flip_thread, NULL);
/* We're done */
return(current);
}
@ -375,215 +413,134 @@ static void WII_UnlockHWSurface(_THIS, SDL_Surface *surface)
return;
}
static void flipHWSurface_8_16(_THIS, SDL_Surface *surface)
static inline void Set_RGBAPixel(_THIS, int x, int y, u32 color) {
u8 *truc = (u8*)texturemem;
int width = this->hidden->width;
u32 offset;
offset = (((y >> 2)<<4)*width) + ((x >> 2)<<6) + (((y%4 << 2) + x%4 ) <<1);
*(truc+offset)=color & 0xFF;
*(truc+offset+1)=(color>>24) & 0xFF;
*(truc+offset+32)=(color>>16) & 0xFF;
*(truc+offset+33)=(color>>8) & 0xFF;
}
static inline void Set_RGB565Pixel(_THIS, int x, int y, u16 color) {
u8 *truc = (u8*)texturemem;
int width = this->hidden->width;
u32 offset;
offset = (((y >> 2)<<3)*width) + ((x >> 2)<<5) + (((y%4 << 2) + x%4 ) <<1);
*(truc+offset)=(color>> 8) & 0xFF;
*(truc+offset+1)=color & 0xFF;
}
static void UpdateRect_8(_THIS, SDL_Rect *rect)
{
int new_pitch = this->hidden->width * 2;
long long int *dst = (long long int *) texturemem;
long long int *src1 = (long long int *) textureconvert;
long long int *src2 = (long long int *) (textureconvert + new_pitch);
long long int *src3 = (long long int *) (textureconvert + (new_pitch * 2));
long long int *src4 = (long long int *) (textureconvert + (new_pitch * 3));
int rowpitch = (new_pitch >> 3) * 3;
int rowadjust = (new_pitch % 8) * 4;
u8 *src;
u8 *ptr;
u16 color;
int i, j;
Uint16 *palette = this->hidden->palette;
char *ra = NULL;
int h, w;
// crude convert
Uint16 * ptr_cv = (Uint16 *) textureconvert;
Uint8 *ptr = (Uint8 *)this->hidden->buffer;
for (h = 0; h < this->hidden->height; h++)
{
for (w = 0; w < this->hidden->width; w++)
{
Uint16 v = palette[*ptr];
*ptr_cv++ = v;
ptr++;
}
}
// same as 16bit
for (h = 0; h < this->hidden->height; h += 4)
{
for (w = 0; w < (this->hidden->width >> 2); w++)
{
*dst++ = *src1++;
*dst++ = *src2++;
*dst++ = *src3++;
*dst++ = *src4++;
}
src1 += rowpitch;
src2 += rowpitch;
src3 += rowpitch;
src4 += rowpitch;
if ( rowadjust )
{
ra = (char *)src1;
src1 = (long long int *)(ra + rowadjust);
ra = (char *)src2;
src2 = (long long int *)(ra + rowadjust);
ra = (char *)src3;
src3 = (long long int *)(ra + rowadjust);
ra = (char *)src4;
src4 = (long long int *)(ra + rowadjust);
for(i = 0; i < rect->h; i++) {
src = (this->hidden->buffer + (this->hidden->width*(i+rect->y)) + (rect->x));
for (j = 0; j < rect->w; j++) {
ptr = src + j;
color = palette[*ptr];
Set_RGB565Pixel(this, rect->x + j, rect->y + i, color);
}
}
}
static void flipHWSurface_16_16(_THIS, SDL_Surface *surface)
static void UpdateRect_16(_THIS, SDL_Rect *rect)
{
int h, w;
long long int *dst = (long long int *) texturemem;
long long int *src1 = (long long int *) this->hidden->buffer;
long long int *src2 = (long long int *) (this->hidden->buffer + this->hidden->pitch);
long long int *src3 = (long long int *) (this->hidden->buffer + (this->hidden->pitch * 2));
long long int *src4 = (long long int *) (this->hidden->buffer + (this->hidden->pitch * 3));
int rowpitch = (this->hidden->pitch >> 3) * 3;
int rowadjust = (this->hidden->pitch % 8) * 4;
char *ra = NULL;
for (h = 0; h < this->hidden->height; h += 4)
{
for (w = 0; w < this->hidden->width; w += 4)
{
*dst++ = *src1++;
*dst++ = *src2++;
*dst++ = *src3++;
*dst++ = *src4++;
}
src1 += rowpitch;
src2 += rowpitch;
src3 += rowpitch;
src4 += rowpitch;
if ( rowadjust )
{
ra = (char *)src1;
src1 = (long long int *)(ra + rowadjust);
ra = (char *)src2;
src2 = (long long int *)(ra + rowadjust);
ra = (char *)src3;
src3 = (long long int *)(ra + rowadjust);
ra = (char *)src4;
src4 = (long long int *)(ra + rowadjust);
u8 *src;
u8 *ptr;
u16 color;
int i, j;
for(i = 0; i < rect->h; i++) {
src = (this->hidden->buffer + (this->hidden->width*2*(i+rect->y)) + (rect->x*2));
for (j = 0; j < rect->w; j++) {
ptr = src + (j*2);
color = (ptr[0] << 8) | ptr[1];
Set_RGB565Pixel(this, rect->x + j, rect->y + i, color);
}
}
}
static void flipHWSurface_24_16(_THIS, SDL_Surface *surface)
static void UpdateRect_24(_THIS, SDL_Rect *rect)
{
int new_pitch = this->hidden->width * 2;
long long int *dst = (long long int *) texturemem;
long long int *src1 = (long long int *) textureconvert;
long long int *src2 = (long long int *) (textureconvert + new_pitch);
long long int *src3 = (long long int *) (textureconvert + (new_pitch * 2));
long long int *src4 = (long long int *) (textureconvert + (new_pitch * 3));
int rowpitch = (new_pitch >> 3) * 3;
int rowadjust = (new_pitch % 8) * 4;
char *ra = NULL;
int h, w;
Uint8 r,g,b;
// crude convert
Uint16 * ptr_cv = (Uint16 *) textureconvert;
Uint8 *ptr = (Uint8 *)this->hidden->buffer;
for (h = 0; h < this->hidden->height; h++)
{
for (w = 0; w < this->hidden->width; w++)
{
r = *ptr++;
g = *ptr++;
b = *ptr++;
*ptr_cv++ = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
}
}
// same as 16bit
for (h = 0; h < this->hidden->height; h += 4)
{
for (w = 0; w < (this->hidden->width >> 2); w++)
{
*dst++ = *src1++;
*dst++ = *src2++;
*dst++ = *src3++;
*dst++ = *src4++;
}
src1 += rowpitch;
src2 += rowpitch;
src3 += rowpitch;
src4 += rowpitch;
if ( rowadjust )
{
ra = (char *)src1;
src1 = (long long int *)(ra + rowadjust);
ra = (char *)src2;
src2 = (long long int *)(ra + rowadjust);
ra = (char *)src3;
src3 = (long long int *)(ra + rowadjust);
ra = (char *)src4;
src4 = (long long int *)(ra + rowadjust);
u8 *src;
u8 *ptr;
u32 color;
int i, j;
for(i = 0; i < rect->h; i++) {
src = (this->hidden->buffer + (this->hidden->width*3*(i+rect->y)) + (rect->x*3));
for (j = 0; j < rect->w; j++) {
ptr = src + (j*3);
color = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | 0xff;
Set_RGBAPixel(this, rect->x + j, rect->y + i, color);
}
}
}
// TO DO
static void flipHWSurface_32_16(_THIS, SDL_Surface *surface)
static void UpdateRect_32(_THIS, SDL_Rect *rect)
{
u8 *src;
u8 *ptr;
u32 color;
int i, j;
for(i = 0; i < rect->h; i++) {
src = (this->hidden->buffer + (this->hidden->width*4*(i+rect->y)) + (rect->x*4));
for (j = 0; j < rect->w; j++) {
ptr = src + (j*4);
color = (ptr[1] << 24) | (ptr[2] << 16) | (ptr[3] << 8) | ptr[0];
Set_RGBAPixel(this, rect->x + j, rect->y + i, color);
}
}
}
static int WII_FlipHWSurface(_THIS, SDL_Surface *surface)
static void WII_UpdateRect(_THIS, SDL_Rect *rect)
{
whichfb ^= 1;
// clear texture objects
GX_InvVtxCache();
GX_InvalidateTexAll();
switch(surface->format->BytesPerPixel)
{
const SDL_Surface* const screen = this->screen;
SDL_mutexP(videomutex);
switch(screen->format->BytesPerPixel) {
case 1:
flipHWSurface_8_16(this, surface); break;
UpdateRect_8(this, rect);
break;
case 2:
flipHWSurface_16_16(this, surface); break;
UpdateRect_16(this, rect);
break;
case 3:
flipHWSurface_24_16(this, surface); break;
UpdateRect_24(this, rect);
break;
case 4:
flipHWSurface_32_16(this, surface); break;
UpdateRect_32(this, rect);
break;
default:
return -1;
fprintf(stderr, "Invalid BPP %d\n", screen->format->BytesPerPixel);
break;
}
// load texture into GX
DCFlushRange(texturemem, TEXTUREMEM_SIZE);
GX_SetNumChans(1);
GX_LoadTexObj(&texobj, GX_TEXMAP0);
draw_square(view); // render textured quad
GX_CopyDisp(xfb[whichfb], GX_TRUE);
GX_DrawDone ();
VIDEO_SetNextFramebuffer(xfb[whichfb]);
VIDEO_Flush();
return(1);
SDL_mutexV(videomutex);
}
static void WII_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
{
int i;
for (i = 0; i < numrects; i++)
{
WII_UpdateRect(this, &rects[i]);
}
}
static int WII_FlipHWSurface(_THIS, SDL_Surface *surface)
{
SDL_Rect screen_rect = {0, 0, surface->w, surface->h};
WII_UpdateRect(this, &screen_rect);
return 1;
}
int WII_SetColors(_THIS, int first_color, int color_count, SDL_Color *colors)
@ -608,6 +565,8 @@ int WII_SetColors(_THIS, int first_color, int color_count, SDL_Color *colors)
void WII_VideoQuit(_THIS)
{
quit_flip_thread = 1;
SDL_WaitThread(videothread, NULL);
GX_AbortFrame();
GX_Flush();
@ -641,6 +600,8 @@ static SDL_VideoDevice *WII_CreateDevice(int devindex)
}
SDL_memset(device->hidden, 0, (sizeof *device->hidden));
videomutex = SDL_CreateMutex();
/* Set the function pointers */
device->VideoInit = WII_VideoInit;
device->ListModes = WII_ListModes;