diff options
author | Luc Verhaegen <libv@skynet.be> | 2005-10-04 05:03:40 +0000 |
---|---|---|
committer | Luc Verhaegen <libv@skynet.be> | 2005-10-04 05:03:40 +0000 |
commit | a65a7ef1b7d2674e249486b166a71577070fc80b (patch) | |
tree | 636858e5010fbb39ef643396df8151bd8d71a7a6 | |
parent | 4b1eb56e8b1ed4518bc7f295a569e7c3c34a869d (diff) |
[devel-swov_fourcc_rgb]
- Add RV15, RV16 and RV32.
- Check alignment for all fourccs.
- Move ImageRec definitions to the start of via_video.c.
-rw-r--r-- | src/via_video.c | 333 |
1 files changed, 263 insertions, 70 deletions
diff --git a/src/via_video.c b/src/via_video.c index a5037d9..3fb8369 100644 --- a/src/via_video.c +++ b/src/via_video.c @@ -59,9 +59,118 @@ void viaInitVideo(ScreenPtr pScreen) {} #define ALIGN_TO(f, alignment) (((f) + ((alignment)-1)) & ~((alignment)-1)) -/* some HW dependant Pitch alignment */ -#define VIA_PITCH_ALIGN_YUV420 32 -#define VIA_PITCH_ALIGN_YUV422 32 +/* + * I'm unable to set the ordering of packed YUV, so only YUY2 is possible. + * A conversion routine could be implemented, but it is more efficient + * to let the client ignore/convert it. -- Luc. + */ + +/* + * VIA seems to have it's RGB components reversed. RGBA tends to mean that + * A is the high byte and R the low. Sadly, VIA is not alone in this, and + * there is no consensus between devices here either. + * + * This severely reduces the chances of any inclusion in fourcc.h. But in + * case this does happen, ignore it and define our own. -- Luc. + */ + +/* + * RGB 555 + */ +#ifndef FOURCC_RV15 +#define FOURCC_RV15 0x35315652 +#endif + +#ifdef XVIMAGE_RV15 +#undef XVIMAGE_RV15 +#endif + +#define XVIMAGE_RV15 \ + { \ + FOURCC_RV15, \ + XvRGB, \ + LSBFirst, \ + {'R','V','1','5'}, \ + 16, \ + XvPacked, \ + 1, \ + 15, \ + 0x7C00, 0x03E0, 0x001F, \ + 0, 0, 0, \ + 0, 0, 0, \ + 0, 0, 0, \ + {'R','V','B' }, \ + XvTopToBottom \ + } + +/* + * RGB 565 + */ +#ifndef FOURCC_RV16 +#define FOURCC_RV16 0x36315652 +#endif + +#ifdef XVIMAGE_RV16 +#undef XVIMAGE_RV16 +#endif + +#define XVIMAGE_RV16 \ + { \ + FOURCC_RV16, \ + XvRGB, \ + LSBFirst, \ + {'R','V','1','6' }, \ + 16, \ + XvPacked, \ + 1, \ + 16, \ + 0xF800, 0x07E0, 0x001F, \ + 0, 0, 0, \ + 0, 0, 0, \ + 0, 0, 0, \ + {'R','V','B' }, \ + XvTopToBottom \ + } + +/* + * RGB 888 + */ +#ifndef FOURCC_RV32 +#define FOURCC_RV32 0x32335652 +#endif + +#ifdef XVIMAGE_RV32 +#undef XVIMAGE_RV32 +#endif + +#define XVIMAGE_RV32 \ + { \ + FOURCC_RV32, \ + XvRGB, \ + LSBFirst, \ + { 'R', 'V' ,'3', '2' }, \ + 32, \ + XvPacked, \ + 1, \ + 24, \ + 0xFF0000, 0x00FF00, 0x0000FF, \ + 0, 0, 0, \ + 0, 0, 0, \ + 0, 0, 0, \ + { 'R', 'V', 'B' }, \ + XvTopToBottom \ + } + +#define NUM_IMAGES_G 6 +static XF86ImageRec ImagesG[NUM_IMAGES_G] = +{ + XVIMAGE_YUY2, + XVIMAGE_YV12, + XVIMAGE_I420, + XVIMAGE_RV15, + XVIMAGE_RV16, + XVIMAGE_RV32 +}; #ifdef HAVE_DEBUG /* @@ -160,7 +269,7 @@ ViaSwovPrintRegs(struct ViaSwov *Swov) */ /* - * Only needs to be altered when HQV front buffer size changes. + * Only needs to be altered when the Front buffer size changes. */ static void ViaHQVFetch(struct ViaSwov *Swov, struct ViaXvPort *Port) @@ -168,9 +277,24 @@ ViaHQVFetch(struct ViaSwov *Swov, struct ViaXvPort *Port) CARD32 Fetch = Port->Width; CARD32 Height = Port->Height; - if (Port->FourCC == FOURCC_YUY2) - Fetch <<= 1; - + switch (Port->FourCC) { + case FOURCC_YV12: + case FOURCC_I420: + /* Fetch is ok */ + break; + case FOURCC_YUY2: + case FOURCC_RV15: + case FOURCC_RV16: + Fetch *= 2; + break; + case FOURCC_RV32: + Fetch *= 4; + break; + default: + xf86DrvMsg(Swov->scrnIndex, X_ERROR, "%s: Unhandled FourCC.\n", + __FUNCTION__); + } + if (Swov->HQVFetchByteUnit) /* CLE266A */ Fetch >>= 3; @@ -182,18 +306,35 @@ ViaHQVFetch(struct ViaSwov *Swov, struct ViaXvPort *Port) } /* - * Only needs to be altered when the second buffer size changes. + * Only needs to be altered when the Back buffer size changes. */ static void ViaSwovStride(struct ViaSwov *Swov, struct ViaXvPort *Port) { - if ((Port->FourCC == FOURCC_YV12) || (Port->FourCC == FOURCC_I420)) + switch (Port->FourCC) { + case FOURCC_YV12: + case FOURCC_I420: + /* planar YUV */ Swov->HQV->SrcStride = ((Port->Width >> 1) << 16) | Port->Width; - else if (Port->FourCC == FOURCC_YUY2) + Swov->HQV->DstStride = Port->Width << 1; + Swov->Video->Video3Stride = Port->Width << 1; + break; + case FOURCC_YUY2: + case FOURCC_RV15: + case FOURCC_RV16: Swov->HQV->SrcStride = Port->Width << 1; - - Swov->HQV->DstStride = Port->Width << 1; - Swov->Video->Video3Stride = Port->Width << 1; + Swov->HQV->DstStride = Port->Width << 1; + Swov->Video->Video3Stride = Port->Width << 1; + break; + case FOURCC_RV32: + Swov->HQV->SrcStride = Port->Width << 2; + Swov->HQV->DstStride = Port->Width << 2; + Swov->Video->Video3Stride = Port->Width << 2; + break; + default: + xf86DrvMsg(Swov->scrnIndex, X_ERROR, "%s: Unhandled FourCC.\n", + __FUNCTION__); + } } /* @@ -205,19 +346,15 @@ ViaSwovSurfaceCreate(ScrnInfoPtr pScrn, CARD32 FourCC, CARD16 Width, CARD16 Heig VIAPtr pVia = VIAPTR(pScrn); struct ViaSwov *Swov = pVia->Swov; struct ViaXvPort *Port = Swov->Port; - int size; + int FrontSize, BackSize; VIAFUNC(pScrn->scrnIndex); ViaDebug(pScrn->scrnIndex, "%s: FourCC 0x%08X, Width %d, Height %d\n", __FUNCTION__, FourCC, Width, Height); - if ((FourCC == FOURCC_YV12) || (FourCC == FOURCC_I420)) { - if (Width != ALIGN_TO(Width, VIA_PITCH_ALIGN_YUV420)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: wrong Xv image width for" - " YUV420.\n", __FUNCTION__); - return FALSE; - } - + switch (FourCC) { + case FOURCC_YV12: + case FOURCC_I420: if (FourCC == FOURCC_I420) { /* YUV */ Port->CbOffset = Width * Height; Port->CrOffset = Port->CbOffset + (Width >> 1) * (Height >> 1); @@ -226,19 +363,26 @@ ViaSwovSurfaceCreate(ScrnInfoPtr pScrn, CARD32 FourCC, CARD16 Width, CARD16 Heig Port->CbOffset = Port->CrOffset + (Width >> 1) * (Height >> 1); } - size = (Width * Height * 3) >> 1; - } else if (FourCC == FOURCC_YUY2) { - if (Width != ALIGN_TO(Width, VIA_PITCH_ALIGN_YUV422)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: wrong Xv image width for" - " YUV422.\n", __FUNCTION__); - return FALSE; - } + FrontSize = (Width * Height * 3) >> 1; + BackSize = Width * Height * 2; + break; + case FOURCC_YUY2: + case FOURCC_RV15: + case FOURCC_RV16: + Port->CrOffset = 0; + Port->CbOffset = 0; + FrontSize = Width * Height * 2; + BackSize = FrontSize; + break; + case FOURCC_RV32: Port->CrOffset = 0; Port->CbOffset = 0; - size = Width * Height * 2; - } else { + FrontSize = Width * Height * 4; + BackSize = FrontSize; + break; + default: xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: unhandled FourCC: 0x%08X\n", __FUNCTION__, FourCC); return FALSE; @@ -249,22 +393,20 @@ ViaSwovSurfaceCreate(ScrnInfoPtr pScrn, CARD32 FourCC, CARD16 Width, CARD16 Heig Port->Height = Height; /* Front buffer, where the HQV sources its video. */ - Port->Front[0] = ViaMemAlloc(pScrn, size, 16); + Port->Front[0] = ViaMemAlloc(pScrn, FrontSize, 16); if (!Port->Front[0]) return FALSE; ViaHQVFetch(Swov, Port); /* Back Buffer: HQV destination and Video3 source. */ - size = 2 * Width * Height; - - Port->Back[0] = ViaMemAlloc(pScrn, size, 16); - Port->Back[1] = ViaMemAlloc(pScrn, size, 16); + Port->Back[0] = ViaMemAlloc(pScrn, BackSize, 16); + Port->Back[1] = ViaMemAlloc(pScrn, BackSize, 16); if (!Port->Back[0] || !Port->Back[1]) return FALSE; /* This one may fail. */ - Port->Front[1] = ViaMemAlloc(pScrn, Port->Front[0]->Size, 16); + Port->Front[1] = ViaMemAlloc(pScrn, FrontSize, 16); if (!Port->Front[1]) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s: Not enough memory available.\n", __FUNCTION__); @@ -280,7 +422,7 @@ ViaSwovSurfaceCreate(ScrnInfoPtr pScrn, CARD32 FourCC, CARD16 Width, CARD16 Heig /* This one may fail too. */ if (Swov->ThreeHQVBuffer) { - Port->Back[2] = ViaMemAlloc(pScrn, Port->Back[0]->Size, 16); + Port->Back[2] = ViaMemAlloc(pScrn, BackSize, 16); if (!Port->Back[2]) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s: Not enough memory available.\n", __FUNCTION__); @@ -586,11 +728,28 @@ ViaHQVInit(struct ViaSwov *Swov) Swov->HQV->Control = HQV_SRC_SW; /* not CLE266Ax could need |= HQV_ENABLE | HQV_SW_FLIP */ - - if ((Port->FourCC == FOURCC_YV12) || (Port->FourCC == FOURCC_I420)) + + switch (Port->FourCC) { + case FOURCC_YV12: + case FOURCC_I420: Swov->HQV->Control |= HQV_YUV420; - else + break; + case FOURCC_YUY2: Swov->HQV->Control |= HQV_YUV422; + break; + case FOURCC_RV15: + Swov->HQV->Control |= HQV_RGB15; + break; + case FOURCC_RV16: + Swov->HQV->Control |= HQV_RGB16; + break; + case FOURCC_RV32: + Swov->HQV->Control |= HQV_RGB32; + break; + default: + xf86DrvMsg(Swov->scrnIndex, X_ERROR, "%s: Unhandled FourCC.\n", + __FUNCTION__); + } /* why this flip stuff? -- Luc */ if (Port->Back[2]) { @@ -772,10 +931,17 @@ ViaSwovVisibleH(ScrnInfoPtr pScrn, struct ViaXvPort *Port) Swov->Video->Video3WindowStart |= Dst_X << 16; /* set up Fetch */ - if (Dst_W >= Src_W) - Fetch = (ALIGN_TO(Src_W << 1, 16) >> 4) + 1; - else - Fetch = (ALIGN_TO(Dst_W << 1, 16) >> 4) + 1; + if (Port->FourCC == FOURCC_RV32) { + if (Dst_W >= Src_W) + Fetch = (ALIGN_TO(Src_W << 2, 16) >> 4) + 1; + else + Fetch = (ALIGN_TO(Dst_W << 2, 16) >> 4) + 1; + } else { + if (Dst_W >= Src_W) + Fetch = (ALIGN_TO(Src_W << 1, 16) >> 4) + 1; + else + Fetch = (ALIGN_TO(Dst_W << 1, 16) >> 4) + 1; + } /* Fix planar mode problem. */ if (Fetch < 4) @@ -850,7 +1016,7 @@ ViaSwovVisibleV(ScrnInfoPtr pScrn, struct ViaXvPort *Port) } /* - * Video3 always takes in YUV422 from the HQV. + * */ static void ViaSwovStartAddress(struct ViaSwov *Swov, struct ViaXvPort *Port) @@ -858,8 +1024,13 @@ ViaSwovStartAddress(struct ViaSwov *Swov, struct ViaXvPort *Port) unsigned long Offset; Offset = Port->Offset_Y * Port->Width + Port->Offset_X; - Offset <<= 1; - Offset &= ~0x03; + + if (Port->FourCC == FOURCC_RV32) + Offset <<= 2; + else + Offset <<= 1; + + /* Warning: hardware rounds down to the nearest 16bytes */ Swov->Video->Video3Address0 = Port->Back[0]->Base + Offset; Swov->Video->Video3Address1 = Port->Back[1]->Base + Offset; @@ -1359,19 +1530,6 @@ static XF86AttributeRec AttributesG[NUM_ATTRIBUTES_G] = }; /* - * I'm unable to set the ordering of packed YUV, so only YUY2 is possible. - * A conversion routine could be implemented, but it is more efficient - * to let the client ignore/convert it. -- Luc. - */ -#define NUM_IMAGES_G 3 -static XF86ImageRec ImagesG[NUM_IMAGES_G] = -{ - XVIMAGE_YUY2, - XVIMAGE_YV12, - XVIMAGE_I420 -}; - -/* * BLOODY MESS! * * The whole bandwidth mess, both for primary and secondary, and for Xv and @@ -1892,6 +2050,34 @@ ViaSwovWindow(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, return FALSE; } +static void +ViaVideo3Init(struct ViaSwov *Swov) +{ + struct ViaXvPort *Port = Swov->Port; + + Swov->Video->Compose = V_COMMAND_LOAD_VBI | ALWAYS_SELECT_VIDEO; + Swov->Video->Video3Control = V3_COLORSPACE_SIGN | V3_YUV422| V3_SWAP_HW_HQV; + + switch (Port->FourCC) { + case FOURCC_YV12: + case FOURCC_I420: + case FOURCC_YUY2: + Swov->Video->Video3Control |= V3_YUV422; + break; + case FOURCC_RV15: + Swov->Video->Video3Control |= V3_RGB15; + break; + case FOURCC_RV16: + Swov->Video->Video3Control |= V3_RGB16; + break; + case FOURCC_RV32: + Swov->Video->Video3Control |= V3_RGB32; + break; + default: + xf86DrvMsg(Swov->scrnIndex, X_ERROR, "%s: Unhandled FourCC.\n", + __FUNCTION__); + } +} /* * We should clean up on exit - some things in here depend on @@ -1930,10 +2116,9 @@ viaPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, ViaSwovCopy(pVia, Port->Front[0], buf); ViaHQVInit(Swov); + ViaVideo3Init(Swov); Video3Touched = TRUE; - Swov->Video->Compose = V_COMMAND_LOAD_VBI | ALWAYS_SELECT_VIDEO; - Swov->Video->Video3Control = V3_COLORSPACE_SIGN | V3_YUV422 | V3_SWAP_HW_HQV; #ifdef UNUSED ViaSwovChromaKey(Swov, 0, 0); @@ -2029,12 +2214,9 @@ viaQueryImageAttributes(ScrnInfoPtr pScrn, int FourCC, CARD16 *Width, switch (FourCC) { case FOURCC_YV12: /* YUV420 */ case FOURCC_I420: - *Width = ALIGN_TO(*Width, 2); + *Width = ALIGN_TO(*Width, 32); *Height = ALIGN_TO(*Height, 2); - /* impose HW limitations */ - *Width = ALIGN_TO(*Width, VIA_PITCH_ALIGN_YUV420); - Size = 3 * (*Width) * (*Height); Size /= 2; @@ -2052,10 +2234,9 @@ viaQueryImageAttributes(ScrnInfoPtr pScrn, int FourCC, CARD16 *Width, break; case FOURCC_YUY2: /* YUV422 */ - *Width = ALIGN_TO(*Width, 2); - - /* impose HW limitations */ - *Width = ALIGN_TO(*Width, VIA_PITCH_ALIGN_YUV422); + case FOURCC_RV15: /* RGB555 */ + case FOURCC_RV16: /* RGB565 */ + *Width = ALIGN_TO(*Width, 8); Size = (*Width << 1) * (*Height); @@ -2066,6 +2247,18 @@ viaQueryImageAttributes(ScrnInfoPtr pScrn, int FourCC, CARD16 *Width, offsets[0] = 0; break; + case FOURCC_RV32: /* RGB888 */ + *Width = ALIGN_TO(*Width, 4); + + Size = (*Width << 2) * (*Height); + + if (pitches) + pitches[0] = *Width << 2; + + if (offsets) + offsets[0] = 0; + + break; default: xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: Unhandled FourCC: 0x%08X.\n", __FUNCTION__, FourCC); |