|
From: <lit...@us...> - 2009-01-26 15:34:21
|
Revision: 352
http://open2x.svn.sourceforge.net/open2x/?rev=352&view=rev
Author: lithosphere
Date: 2009-01-26 15:34:18 +0000 (Mon, 26 Jan 2009)
Log Message:
-----------
Add support for other YUV surfaces (untested)
Modified Paths:
--------------
trunk/libs-new/sdl/sdl/SDL-1.2.11/src/video/gp2x/SDL_gp2xyuv.c
Modified: trunk/libs-new/sdl/sdl/SDL-1.2.11/src/video/gp2x/SDL_gp2xyuv.c
===================================================================
--- trunk/libs-new/sdl/sdl/SDL-1.2.11/src/video/gp2x/SDL_gp2xyuv.c 2009-01-25 10:08:59 UTC (rev 351)
+++ trunk/libs-new/sdl/sdl/SDL-1.2.11/src/video/gp2x/SDL_gp2xyuv.c 2009-01-26 15:34:18 UTC (rev 352)
@@ -47,18 +47,28 @@
struct private_yuvhwdata
{
- Uint8 *YUVBuf[2]; // we will have two buffers, a front and back (double buffered)
- unsigned int GP2XAddr[2]; // the yuv buffer address from the gp2x's perspective
+ Uint8 *YUVBuf[2][3]; // we will have two buffers, a front and back (double buffered)
+ unsigned int GP2XAddr[2][3]; // the yuv buffer address from the gp2x's perspective
unsigned int uBackBuf; // which buffer is currently the back buffer (0 or 1)
unsigned int uBufSize; // how big the YUVBuf buffers are (in bytes)
+ unsigned int uYsize; // how big the Y plane is (in bytes) (not used for YUY2)
+ unsigned int uUsize; // how big the U plane is (in bytes) (not used for YUY2)
SDL_Rect rctLast; // the last rectangle we used for displaying (so we know when to rescale/change coordinates)
Uint16 u16PixelWidth; // value stored for MLC_VLA_TP_PXW register
/* These are just so we don't have to allocate them separately */
Uint16 pitches[3];
Uint8 *planes[3];
+
+ Uint32 format;
};
+#define FDC_CNTL (0x1838 >> 1)
+#define FDC_FRAME_SIZE (0x183A >> 1)
+#define FDC_LUMA_OFFSET (0x183C >> 1)
+#define FDC_CB_OFFSET (0x183E >> 1)
+#define FDC_CR_OFFSET (0x1840 >> 1)
+
// These are the registers (currently) modified by this code;
// They are in this array so we can restore them to their previous state after the overlay is destroyed.
const unsigned int g_pTouchedRegs[] =
@@ -80,7 +90,12 @@
0x28A4 >> 1,
0x28A6 >> 1,
0x28C0 >> 1,
- 0x28C2 >> 1
+ 0x28C2 >> 1,
+ FDC_CNTL,
+ FDC_FRAME_SIZE,
+ FDC_LUMA_OFFSET,
+ FDC_CB_OFFSET,
+ FDC_CR_OFFSET
};
const unsigned int TOUCHEDREGS_COUNT = sizeof(g_pTouchedRegs) / sizeof(unsigned int);
@@ -120,7 +135,10 @@
SDL_PrivateVideoData *data = this->hidden;
unsigned short volatile *p16GP2XRegs = data->io;
- hwdata->uBufSize = width * height * 2; // YUY2 is (2 * width) bytes per line
+ if(format == SDL_YUY2_OVERLAY)
+ hwdata->uBufSize = width * height * 2; // YUY2 is (2 * width) bytes per line
+ else if(format == SDL_YV12_OVERLAY || format == SDL_IYUV_OVERLAY)
+ hwdata->uBufSize = width * height * 3 / 2; // u v 2x2 subsampled -> width * 1.5 bytes per line
// initialize to values that will never be used so that we force a rescale the first time GP2X_DisplayYUVOverlay is called
hwdata->rctLast.h = hwdata->rctLast.w = 0;
@@ -128,29 +146,56 @@
hwdata->uBackBuf = 0; // arbitrary starting point (can be 0 or 1)
- // We're using GP2X_UPPER_MEM_START because that's where vmem is mapped in SDL_gp2xvideo.c
- hwdata->GP2XAddr[0] = GP2X_UPPER_MEM_START; // this is where vmem is mapped from the gp2x's pov
- hwdata->GP2XAddr[1] = GP2X_UPPER_MEM_START + hwdata->uBufSize;
+ if(format == SDL_YUY2_OVERLAY)
+ {
+ // We're using GP2X_UPPER_MEM_START because that's where vmem is mapped in SDL_gp2xvideo.c
+ hwdata->GP2XAddr[0][0] = GP2X_UPPER_MEM_START; // this is where vmem is mapped from the gp2x's pov
+ hwdata->GP2XAddr[1][0] = GP2X_UPPER_MEM_START + hwdata->uBufSize;
- //map memory for our cursor + 4 YUV regions (double buffered each one)
- hwdata->YUVBuf[0] = (Uint8 *) data->vmem;
- hwdata->YUVBuf[1] = ((Uint8 *) data->vmem) + hwdata->uBufSize;
+ //map memory for our cursor + 4 YUV regions (double buffered each one)
+ hwdata->YUVBuf[0][0] = (Uint8 *) data->vmem;
+ hwdata->YUVBuf[1][0] = ((Uint8 *) data->vmem) + hwdata->uBufSize;
+ }
+ else if(format == SDL_YV12_OVERLAY || format == SDL_IYUV_OVERLAY)
+ {
+ // PhyAddr = (ScreenOffset << 24) | (YOffset << 20) | (XOffset * 0x2000)
+ // GP2X_UPPER_MEM_START == 0x0200 << 24
+ hwdata->GP2XAddr[0][0] = 0x0240; // this is from the gp2x's pov
+ hwdata->GP2XAddr[0][1] = 0x0244;
+ hwdata->GP2XAddr[0][2] = 0x0246;
+ hwdata->GP2XAddr[1][0] = 0x0260;
+ hwdata->GP2XAddr[1][1] = 0x0264;
+ hwdata->GP2XAddr[1][2] = 0x0266;
+
+ //map memory for our cursor + 4 YUV regions (double buffered each one)
+ hwdata->YUVBuf[0][0] = (Uint8 *) data->vmem + (0x4 << 20);
+ hwdata->YUVBuf[0][1] = (Uint8 *) data->vmem + (0x4 << 20) + 0x4 * 0x2000;
+ hwdata->YUVBuf[0][2] = (Uint8 *) data->vmem + (0x4 << 20) + 0x6 * 0x2000;
+ hwdata->YUVBuf[1][0] = (Uint8 *) data->vmem + (0x6 << 20);
+ hwdata->YUVBuf[1][1] = (Uint8 *) data->vmem + (0x6 << 20) + 0x4 * 0x2000;
+ hwdata->YUVBuf[1][2] = (Uint8 *) data->vmem + (0x6 << 20) + 0x6 * 0x2000;
+ }
+
+ hwdata->format = format;
+
// tests have shown that this value should be the width of the overlay, not the width of the display (ie not always 320)
hwdata->u16PixelWidth = width;
+ if(format != SDL_YUY2_OVERLAY)
+ p16GP2XRegs[FDC_CNTL] = 1<<11 + // Write mode: mem -> scaler/display
+ ((format == SDL_YV12_OVERLAY || format == SDL_IYUV_OVERLAY) ? 1 : 0) << 1;
+
// Set MLC_VLA_TP_PXW
p16GP2XRegs[0x2892>>1] = hwdata->u16PixelWidth;
- // MLC_YUV_CNTL: set YUV source to external memory for regions A and B, turn off "stepping"
- p16GP2XRegs[0x2884>>1]=0;
+ // MLC_YUV_CNTL: set YUV source to external memory for regions A and B, turn off "stepping" when YUY2
+ // otherwise get it from the fdc
+ p16GP2XRegs[0x2884>>1] = format == SDL_YUY2_OVERLAY ? 0 : 1;
- // disable all RGB Windows, and YUV region B
- p16GP2XRegs[MLC_OVLAY_CNTR] &= ~(DISP_STL5EN|DISP_STL4EN|DISP_STL3EN|DISP_STL2EN|DISP_STL1EN|DISP_VLBON);
+ // disable all RGB Windows, and YUV region A & B
+ p16GP2XRegs[MLC_OVLAY_CNTR] &= ~(DISP_STL5EN|DISP_STL4EN|DISP_STL3EN|DISP_STL2EN|DISP_STL1EN|DISP_VLAON|DISP_VLBON);
- // enable YUV region A
- p16GP2XRegs[MLC_OVLAY_CNTR] |= DISP_VLAON;
-
// disable bottom regions for A & B, and turn off all mirroring
p16GP2XRegs[0x2882>>1] &= 0xFC00;
@@ -167,11 +212,19 @@
SDL_Overlay *overlay = NULL;
struct private_yuvhwdata *hwdata;
- // we ONLY support YUY2 because that is the native gp2x YUV format
- if (format != SDL_YUY2_OVERLAY)
- {
- printf("SDL_GP2X: Unsupported YUV format for hardware acceleration. Falling back to software.\n");
- return NULL;
+ switch(format){
+ // we support YUY2 because that is the native gp2x YUV format
+ case SDL_YUY2_OVERLAY:
+ // other planar formats need the extra frame dimension converter
+ case SDL_YV12_OVERLAY:
+ case SDL_IYUV_OVERLAY: // == I420 ?
+ break;
+
+ default:
+ // SDL_UYVY_OVERLAY: // 2x2 subsampled packed
+ // SDL_YVYU_OVERLAY: // 2x2 subsampled packed
+ printf("SDL_GP2X: Unsupported YUV format for hardware acceleration. Falling back to software.\n");
+ return NULL;
}
/* Create the overlay structure */
@@ -225,16 +278,30 @@
/* Set up the plane pointers */
overlay->pitches = hwdata->pitches;
overlay->pixels = hwdata->planes;
- overlay->planes = 1; // since we only support YUY2, there is always only 1 plane
- // the pitch will always be the overlay width * 2, because we only support YUY2
- overlay->pitches[0] = overlay->w * 2;
+ if(format == SDL_YUY2_OVERLAY)
+ {
+ overlay->planes = 1;
+ // the pitch will be the overlay width * 2
+ overlay->pitches[0] = overlay->w * 2;
+ }
+ else if(format == SDL_YV12_OVERLAY || format == SDL_IYUV_OVERLAY)
+ {
+ overlay->planes = 3;
+
+ overlay->pitches[0] = overlay->w * 1;
+ overlay->pitches[1] = overlay->w / 4;
+ overlay->pitches[2] = overlay->w / 4;
+ }
+
// start on the correct back buffer
- overlay->pixels[0] = hwdata->YUVBuf[hwdata->uBackBuf];
+ overlay->pixels[0] = hwdata->YUVBuf[hwdata->uBackBuf][0];
+ overlay->pixels[1] = hwdata->YUVBuf[hwdata->uBackBuf][1];
+ overlay->pixels[1] = hwdata->YUVBuf[hwdata->uBackBuf][2];
/* We're all done.. */
- printf("SDL_GP2X: Created YUY2 overlay\n");
+ printf("SDL_GP2X: Created YUV overlay\n");
return(overlay);
}
@@ -250,7 +317,7 @@
int GP2X_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect)
{
struct private_yuvhwdata *hwdata = overlay->hwdata;
- unsigned int uAddress = (unsigned int) hwdata->GP2XAddr[hwdata->uBackBuf];
+ unsigned int *uAddress = (unsigned int*) hwdata->GP2XAddr[hwdata->uBackBuf];
SDL_PrivateVideoData *data = this->hidden;
unsigned short volatile *p16GP2XRegs = data->io;
@@ -290,6 +357,12 @@
if (s16Right > 319) s16Right = 319;
if (s16Bottom > 239) s16Bottom = 239;
+ if(hwdata->format != SDL_YUY2_OVERLAY){
+ // Set frame size for FDC
+ p16GP2XRegs[FDC_FRAME_SIZE] = (overlay->w / 16 - 1) + // width / 16 - 1
+ (overlay->h / 16 - 1) << 8; // height / 16 - 1
+ }
+
// now that we've done all the calculations we can before changing registers, wait for vblank
GP2X_WaitVBlank(data);
@@ -324,22 +397,33 @@
// NOW FLIP THE ACTUAL BUFFER
- // NOTE : I am flipping the odd and even fields here because that's how rlyeh did it, but I am not sure
- // whether both of these need to be flipped.
+ if(hwdata->format == SDL_YUY2_OVERLAY){
+ // NOTE : I am flipping the odd and even fields here because that's how rlyeh did it, but I am not sure
+ // whether both of these need to be flipped.
- // region A, odd fields
- p16GP2XRegs[0x28A0>>1] = (uAddress & 0xFFFF);
- p16GP2XRegs[0x28A2>>1] = (uAddress >> 16);
+ // region A, odd fields
+ p16GP2XRegs[0x28A0>>1] = (uAddress[0] & 0xFFFF);
+ p16GP2XRegs[0x28A2>>1] = (uAddress[0] >> 16);
- // region A, even fields
- p16GP2XRegs[0x28A4>>1] = (uAddress & 0xFFFF);
- p16GP2XRegs[0x28A6>>1] = (uAddress >> 16);
+ // region A, even fields
+ p16GP2XRegs[0x28A4>>1] = (uAddress[0] & 0xFFFF);
+ p16GP2XRegs[0x28A6>>1] = (uAddress[0] >> 16);
+ }else{
+ p16GP2XRegs[FDC_LUMA_OFFSET] = uAddress[0];
+ p16GP2XRegs[FDC_CB_OFFSET] = uAddress[1];
+ p16GP2XRegs[FDC_CR_OFFSET] = uAddress[2];
+
+ p16GP2XRegs[FDC_CNTL] |= 1; // START FDC
+ }
+
// change back buffer to the other buffer (can be 0 or 1, so XOR works nicely)
hwdata->uBackBuf ^= 1;
// update the pixel pointer to new back buffer
- overlay->pixels[0] = hwdata->YUVBuf[hwdata->uBackBuf];
+ overlay->pixels[0] = hwdata->YUVBuf[hwdata->uBackBuf][0];
+ overlay->pixels[1] = hwdata->YUVBuf[hwdata->uBackBuf][1];
+ overlay->pixels[2] = hwdata->YUVBuf[hwdata->uBackBuf][2];
return(0);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|