diff options
author | Luc Verhaegen <libv@skynet.be> | 2005-10-04 06:26:04 +0000 |
---|---|---|
committer | Luc Verhaegen <libv@skynet.be> | 2005-10-04 06:26:04 +0000 |
commit | 4e33b3848da771678a68d826fbe1483f70dec15f (patch) | |
tree | 4e2beb9e884d2e3965cf39656275696e8004ff3e | |
parent | a65a7ef1b7d2674e249486b166a71577070fc80b (diff) |
[devel-swov_restructure_via_video] Sanitize ordering of via_video.c.
-rw-r--r-- | src/via_video.c | 2308 |
1 files changed, 1177 insertions, 1131 deletions
diff --git a/src/via_video.c b/src/via_video.c index 3fb8369..61d8d06 100644 --- a/src/via_video.c +++ b/src/via_video.c @@ -54,10 +54,45 @@ void viaInitVideo(ScreenPtr pScreen) {} #define VIA_MAX_XVIMAGE_X 1920 #define VIA_MAX_XVIMAGE_Y 1200 -#define XV_IMAGE 0 +#define ALIGN_TO(f, alignment) (((f) + ((alignment)-1)) & ~((alignment)-1)) + +#define XV_IMAGE 0 + +static XF86VideoEncodingRec DummyEncoding[1] = { + {XV_IMAGE, "XV_IMAGE", VIA_MAX_XVIMAGE_X, VIA_MAX_XVIMAGE_Y, {1, 1}}, +}; + +#define NUM_FORMATS_G 9 + +static XF86VideoFormatRec FormatsG[NUM_FORMATS_G] = +{ + { 8, TrueColor }, /* Dithered */ + { 8, PseudoColor }, /* Using .. */ + { 8, StaticColor }, + { 8, GrayScale }, + { 8, StaticGray }, /* .. TexelLUT */ + {16, TrueColor}, + {24, TrueColor}, + {16, DirectColor}, + {24, DirectColor} +}; + #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) +static Atom xvBrightness, xvContrast, xvColorKey, xvHue, xvSaturation, + xvAutoPaint, xvOpacity; -#define ALIGN_TO(f, alignment) (((f) + ((alignment)-1)) & ~((alignment)-1)) +#define NUM_ATTRIBUTES_G 7 + +static XF86AttributeRec AttributesG[NUM_ATTRIBUTES_G] = +{ + {XvSettable | XvGettable, 0, 0x00FFFFFF, "XV_COLORKEY"}, + {XvSettable | XvGettable, 0, 10000, "XV_BRIGHTNESS"}, + {XvSettable | XvGettable, 0, 20000, "XV_CONTRAST"}, + {XvSettable | XvGettable, 0, 20000, "XV_SATURATION"}, + {XvSettable | XvGettable, -180, 180, "XV_HUE"}, + {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}, + {XvSettable | XvGettable, 0, 0x0F, "XV_OPACITY"} +}; /* * I'm unable to set the ordering of packed YUV, so only YUY2 is possible. @@ -175,7 +210,7 @@ static XF86ImageRec ImagesG[NUM_IMAGES_G] = #ifdef HAVE_DEBUG /* * - * Dump Video registers for debugging purposes. + * Dump Video registers. * */ static void @@ -265,267 +300,6 @@ ViaSwovPrintRegs(struct ViaSwov *Swov) #endif /* HAVE_DEBUG */ /* - * Hardware level stuff. Actual Xv infrastructural stuff comes later. - */ - -/* - * Only needs to be altered when the Front buffer size changes. - */ -static void -ViaHQVFetch(struct ViaSwov *Swov, struct ViaXvPort *Port) -{ - CARD32 Fetch = Port->Width; - CARD32 Height = Port->Height; - - 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; - - if ((Port->Deinterlace & VIA_DEINT_BOB) && - !(Port->Deinterlace & VIA_DEINT_INTERLEAVE)) - Height <<= 1; - - Swov->HQV->SrcFetch = ((Fetch - 1) << 16) | (Height - 1); -} - -/* - * Only needs to be altered when the Back buffer size changes. - */ -static void -ViaSwovStride(struct ViaSwov *Swov, struct ViaXvPort *Port) -{ - switch (Port->FourCC) { - case FOURCC_YV12: - case FOURCC_I420: - /* planar YUV */ - Swov->HQV->SrcStride = ((Port->Width >> 1) << 16) | Port->Width; - 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; - 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__); - } -} - -/* - * - */ -static Bool -ViaSwovSurfaceCreate(ScrnInfoPtr pScrn, CARD32 FourCC, CARD16 Width, CARD16 Height) -{ - VIAPtr pVia = VIAPTR(pScrn); - struct ViaSwov *Swov = pVia->Swov; - struct ViaXvPort *Port = Swov->Port; - int FrontSize, BackSize; - - VIAFUNC(pScrn->scrnIndex); - ViaDebug(pScrn->scrnIndex, "%s: FourCC 0x%08X, Width %d, Height %d\n", - __FUNCTION__, FourCC, Width, Height); - - 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); - } else { /* YVU */ - Port->CrOffset = Width * Height; - Port->CbOffset = Port->CrOffset + (Width >> 1) * (Height >> 1); - } - - 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; - - FrontSize = Width * Height * 4; - BackSize = FrontSize; - break; - default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: unhandled FourCC: 0x%08X\n", - __FUNCTION__, FourCC); - return FALSE; - } - - Port->FourCC = FourCC; - Port->Width = Width; - Port->Height = Height; - - /* Front buffer, where the HQV sources its video. */ - Port->Front[0] = ViaMemAlloc(pScrn, FrontSize, 16); - if (!Port->Front[0]) - return FALSE; - - ViaHQVFetch(Swov, Port); - - /* Back Buffer: HQV destination and Video3 source. */ - 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, FrontSize, 16); - if (!Port->Front[1]) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s: Not enough memory available.\n", - __FUNCTION__); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s: Using only a single front buffer.\n", - __FUNCTION__); - - Swov->HQV->SrcAddressY = Port->Front[0]->Base; - if (Port->CrOffset) { - Swov->HQV->SrcAddressU = Port->Front[0]->Base + Port->CbOffset; - Swov->HQV->SrcAddressV = Port->Front[0]->Base + Port->CrOffset; - } - } - - /* This one may fail too. */ - if (Swov->ThreeHQVBuffer) { - Port->Back[2] = ViaMemAlloc(pScrn, BackSize, 16); - if (!Port->Back[2]) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s: Not enough memory available.\n", - __FUNCTION__); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s: Using only 2 back buffers.\n", - __FUNCTION__); - } - } - - Swov->HQV->DstAddress0 = Port->Back[0]->Base; - Swov->HQV->DstAddress1 = Port->Back[1]->Base; - if (Port->Back[2]) - Swov->HQV->DstAddress2 = Port->Back[2]->Base; - - ViaSwovStride(Swov, Port); - - return TRUE; -} - -/* - * - */ -static void -ViaSwovSurfaceDestroy(ScrnInfoPtr pScrn) -{ - struct ViaSwov *Swov = VIAPTR(pScrn)->Swov; - struct ViaXvPort *Port = Swov->Port; - - VIAFUNC(pScrn->scrnIndex); - - Port->FourCC = 0; - Port->Width = 0; - Port->Height = 0; - - if (Port->Front[0]) - ViaMemFree(pScrn, Port->Front[0]); - if (Port->Front[1]) - ViaMemFree(pScrn, Port->Front[1]); - if (Port->Back[0]) - ViaMemFree(pScrn, Port->Back[0]); - if (Port->Back[1]) - ViaMemFree(pScrn, Port->Back[1]); - if (Port->Back[2]) - ViaMemFree(pScrn, Port->Back[2]); - if (Port->Alpha[0]) - ViaMemFree(pScrn, Port->Alpha[0]); - if (Port->Alpha[1]) - ViaMemFree(pScrn, Port->Alpha[1]); - - Port->Front[0] = NULL; - Port->Front[1] = NULL; - Port->Back[0] = NULL; - Port->Back[1] = NULL; - Port->Back[2] = NULL; - Port->Alpha[0] = NULL; - Port->Alpha[1] = NULL; -} - -/* - * I've ditched all the FourCC stuff here. It's HQV->Video3 anyway. - * When not YV12 (amazingly), the FIFO was set set to - * (depth, prethreshold, threshhold) (1,0,0) when Width <= 8 - */ -static void -ViaSwovFIFO(VIAPtr pVia, struct ViaSwov *Swov) -{ - CARD8 depth, prethreshold, threshold; - - switch (pVia->Chipset) { - case VIA_CLE266: - if (CLE266_REV_IS_CX(pVia->ChipRev)) { - depth = 64; - prethreshold = 56; - threshold = 56; - Swov->Video->Video3Control |= V3_EXPIRE_NUM_F; - } else { /* CLE266Ax */ - depth = 32; - prethreshold = 16; - threshold = 8; - Swov->Video->Video3Control |= V3_EXPIRE_NUM; - } - break; - case VIA_KM400: - case VIA_K8M800: - depth = 32; - prethreshold = 29; - threshold = 29; - Swov->Video->Video3Control |= V3_EXPIRE_NUM_3205; - break; - default: - depth = 1; - prethreshold = 0; - threshold = 0; - break; - } - - Swov->Video->Video3AlphaFifo &= ~V3_FIFO_MASK; - Swov->Video->Video3AlphaFifo |= ((depth - 1) & 0xff) | ((threshold & 0xff) << 8); - - Swov->Video->Video3AlphaPreFifo &= ~V3_PREFIFO_MASK; - Swov->Video->Video3AlphaPreFifo |= (prethreshold & 0x7f); -} - -/* * Another bloody ugly mess. * * @@ -535,29 +309,32 @@ ViaSwovFIFO(VIAPtr pVia, struct ViaSwov *Swov) /* * This function uses quadratic mapping to adjust the midpoint of the scaling. */ -static float rangeEqualize(float inLow,float inHigh,float outLow,float outHigh,float outMid, - float inValue) +static float +rangeEqualize(float inLow,float inHigh,float outLow,float outHigh,float outMid, + float inValue) { - float - inRange = inHigh - inLow, - outRange = outHigh - outLow, - normIn = ((inValue - inLow) / inRange)*2.-1., - delta = outMid - outRange*0.5 - outLow; + float inRange = inHigh - inLow; + float outRange = outHigh - outLow; + float normIn = ((inValue - inLow) / inRange)*2.-1.; + float delta = outMid - outRange*0.5 - outLow; + return (inValue - inLow) * outRange / inRange + outLow + (1. - normIn*normIn)*delta; } -static unsigned vPackFloat(float val, float hiLimit, float loLimit, float mult, int shift, - Bool doSign) +static unsigned +vPackFloat(float val, float hiLimit, float loLimit, float mult, int shift, + Bool doSign) { unsigned packed,mask,sign; + val = (val > hiLimit) ? hiLimit : val; val = (val < loLimit) ? loLimit : val; sign = (val < 0) ? 1:0; val = (sign) ? -val : val; packed = ((unsigned)(val*mult + 1.)) >> 1; mask = (1 << shift) - 1; - return (((packed >= mask) ? mask : packed) | ((doSign) ? (sign << shift) : 0)); + return (((packed >= mask) ? mask : packed) | ((doSign) ? (sign << shift) : 0)); } /* @@ -687,6 +464,9 @@ VIASetColorSpace(VIAPtr pVia) pVia->Swov->Video->Video3ColorSpace2 = col2; } +/* + * + */ static void ViaSwovColorKey(ScrnInfoPtr pScrn, CARD32 Key) { @@ -704,6 +484,9 @@ ViaSwovColorKey(ScrnInfoPtr pScrn, CARD32 Key) } #ifdef UNUSED +/* + * + */ static void ViaSwovChromaKey(struct ViaSwov *Swov, CARD32 chromaLow, CARD32 chromaHigh) { @@ -721,323 +504,6 @@ ViaSwovChromaKey(struct ViaSwov *Swov, CARD32 chromaLow, CARD32 chromaHigh) } #endif /* UNUSED */ -static void -ViaHQVInit(struct ViaSwov *Swov) -{ - struct ViaXvPort *Port = Swov->Port; - - Swov->HQV->Control = HQV_SRC_SW; - /* not CLE266Ax could need |= HQV_ENABLE | HQV_SW_FLIP */ - - switch (Port->FourCC) { - case FOURCC_YV12: - case FOURCC_I420: - Swov->HQV->Control |= HQV_YUV420; - 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]) { - Swov->HQV->Control &= ~HQV_SW_FLIP; - Swov->HQV->Control |= HQV_TRIPLE_BUFF | HQV_FLIP_STATUS; - } - - /* For DCT450 test-BOB INTERLEAVE */ - if ((Port->Deinterlace & VIA_DEINT_BOB)) { - Swov->HQV->Control |= HQV_FIELD_2_FRAME | HQV_DEINTERLACE; - if ((Port->Deinterlace & VIA_DEINT_INTERLEAVE)) - Swov->HQV->Control |= HQV_FRAME_2_FIELD; - } - - Swov->HQV->Control |= HQV_ENABLE; -} - -static void -ViaHQVSwovIdle(struct ViaSwov *Swov) -{ - int i; - - for (i = 0; i < 10; i++) - if (!(Swov->Video->Compose & V3_COMMAND_FIRE) && - (Swov->HQV->Control & HQV_IDLE)) - break; - else - usleep(1); - - if (i) { - ViaDebug(Swov->scrnIndex, "%s: idle/fire wait: %d.\n", __FUNCTION__, i); - if (!(Swov->HQV->Control & HQV_IDLE)) - xf86DrvMsg(Swov->scrnIndex, X_WARNING, "%s: HQV not idle.\n", - __FUNCTION__); - if ((Swov->Video->Compose & V3_COMMAND_FIRE)) - xf86DrvMsg(Swov->scrnIndex, X_WARNING, "%s: Video3 still firing.\n", - __FUNCTION__); - } - -} - -/* - * Minify is done by the HQV entirely. - * Zoom is done by V3. - * - */ -static void -ViaSwovZoomH(struct ViaSwov *Swov, struct ViaXvPort *Port) -{ - unsigned long tmp; - - Swov->HQV->Minify &= 0xFFFF0000; - Swov->HQV->Filter &= 0xFFFF0000; - Swov->Video->Video3Zoom &= 0x0000FFFF; - Swov->Video->Video3Minify &= 0xF8FFFFFD; - - if (Port->Src_W == Port->Drw_W) { /* No zoom */ - Swov->HQV->Filter |= HQV_H_HIPASS_F1_DEFAULT; - } else if (Port->Src_W < Port->Drw_W) { /* Zoom in */ - - tmp = Port->Src_W * 0x800 / Port->Drw_W; - Swov->Video->Video3Zoom |= ((tmp & 0x7ff) << 16) | V3_X_ZOOM_ENABLE; - - Swov->Video->Video3Minify |= V3_X_INTERPOLY; - Swov->HQV->Filter |= HQV_H_HIPASS_F1_DEFAULT; - - } else { /* Zoom out */ - tmp = Port->Drw_W * 0x800 * 0x400 / Port->Src_W; - tmp = tmp / 0x400 + ((tmp & 0x3ff) ? 1 : 0); - - Swov->HQV->Minify |= (tmp & 0x7ff) | HQV_H_MINIFY_ENABLE; - - if (Port->Src_W > (4 * Port->Drw_W)) - Swov->HQV->Filter |= HQV_H_TAP8_12221; - else - Swov->HQV->Filter |= HQV_H_TAP4_121; - Swov->HQV->Minify |= HQV_HDEBLOCK_FILTER; - } -} - -/* - * - */ -static void -ViaSwovZoomV(struct ViaSwov *Swov, struct ViaXvPort *Port) -{ - unsigned long tmp; - short Src_H = Port->Src_H; - - if ((Port->Deinterlace & VIA_DEINT_BOB) && - !(Port->Deinterlace & VIA_DEINT_INTERLEAVE)) - Src_H <<= 1; - - Swov->HQV->Minify &= 0x0000FFFF; - Swov->HQV->Filter &= 0x0000FFFF; - Swov->Video->Video3Zoom &= 0xFFFF0000; - Swov->Video->Video3Minify &= 0xFFF8FFFA; - - /* Setup Y zoom factor */ - if (Src_H == Port->Drw_H) { /* No zoom */ - Swov->HQV->Filter |= HQV_V_TAP4_121; - } else if (Src_H < Port->Drw_H) { /* Zoom in */ - ScrnInfoPtr pScrn = xf86Screens[Swov->scrnIndex]; - - tmp = Src_H * 0x0400 / Port->Drw_H; - Swov->Video->Video3Zoom |= ((tmp & 0x3ff) | V3_Y_ZOOM_ENABLE); - - if ((VIAPTR(pScrn)->Chipset == VIA_CLE266) && (pScrn->currentMode->HDisplay > 1024)) - /* Temporary fix for 2D bandwidth problem. 2002/08/01*/ - Swov->Video->Video3Minify |= V3_YCBCR_INTERPOLY; - else - Swov->Video->Video3Minify |= V3_Y_INTERPOLY | V3_YCBCR_INTERPOLY; - - Swov->HQV->Filter |= HQV_V_TAP4_121; - Swov->HQV->Filter &= ~HQV_V_LOWPASS_4TAP; - } else { /* Zoom out */ - tmp = Port->Drw_H * 0x0800 * 0x400 / Src_H; - tmp = tmp / 0x400 + ((tmp & 0x3ff) ? 1 : 0); - Swov->HQV->Minify |= ((tmp & 0x7ff) << 16) | HQV_V_MINIFY_ENABLE; - - if (Src_H > (4 * Port->Drw_H)) - Swov->HQV->Filter |= HQV_V_TAP8_12221; - else - Swov->HQV->Filter |= HQV_V_TAP4_121; - Swov->HQV->Minify |= HQV_VDEBLOCK_FILTER; - } -} - -/* - * Returns FALSE when the overlay is not currently visible. - */ -static Bool -ViaSwovVisibleH(ScrnInfoPtr pScrn, struct ViaXvPort *Port) -{ - struct ViaSwov *Swov = VIAPTR(pScrn)->Swov; - short limit; - long temp; - CARD32 Fetch; - short Src_X, Src_W, Dst_X, Dst_W; - - /* Horizontal */ - if (pScrn->currentMode->HDisplay < 2047) - limit = pScrn->currentMode->HDisplay; - else - limit = 2047; - - if (((Port->Drw_X + Port->Drw_W) < pScrn->frameX0) || - (Port->Drw_X > (limit + pScrn->frameX0))) - return FALSE; - - Src_X = Port->Src_X; - Dst_W = Port->Drw_W; - - if (Port->Drw_X < pScrn->frameX0) { - temp = (pScrn->frameX0 - Port->Drw_X) * Port->Src_W; - temp += Port->Drw_W >> 1; - Src_X += temp / Port->Drw_W; - - Dst_W -= pScrn->frameX0 - Port->Drw_X; - Dst_X = 0; - } else - Dst_X = Port->Drw_X - pScrn->frameX0; - - if ((Dst_X + Dst_W) > limit) - Dst_W = limit - Dst_X; - - if (Dst_W != Port->Drw_W) { - temp = Dst_W * Port->Src_W; - temp += Port->Drw_W >> 1; - Src_W = temp / Port->Drw_W; - } else - Src_W = Port->Src_W; - - /* set up window */ - Swov->Video->Video3WindowEnd &= 0x0000FFFF; - Swov->Video->Video3WindowEnd |= (Dst_X + Dst_W - 1) << 16; - - Swov->Video->Video3WindowStart &= 0x0000FFFF; - Swov->Video->Video3WindowStart |= Dst_X << 16; - - /* set up Fetch */ - 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) - Fetch = 4; - - Swov->Video->Video3AlphaFetch &= ~V3_FETCH_COUNT; - Swov->Video->Video3AlphaFetch |= Fetch << 20; - - Swov->Video->Video3SrcWidth = Src_W - 1; - - /* for startAddress offset */ - Port->Offset_X = Src_X; - - /* for alpha */ - Port->Win_X = Dst_X; - Port->Win_W = Dst_W; - - return TRUE; -} - -/* - * - */ -static Bool -ViaSwovVisibleV(ScrnInfoPtr pScrn, struct ViaXvPort *Port) -{ - struct ViaSwov *Swov = VIAPTR(pScrn)->Swov; - short limit; - long temp; - short Src_Y, Dst_Y, Dst_H; - - if (pScrn->currentMode->VDisplay < 2047) - limit = pScrn->currentMode->VDisplay; - else - limit = 2047; - - if (((Port->Drw_Y + Port->Drw_H) < pScrn->frameY0) || - (Port->Drw_Y > (limit + pScrn->frameY0))) - return FALSE; - - Src_Y = Port->Src_Y; - Dst_H = Port->Drw_H; - - if (Port->Drw_Y < pScrn->frameY0) { - /* Round down. */ - temp = (pScrn->frameY0 - Port->Drw_Y) * Port->Src_H; - Src_Y += temp / Port->Drw_H; - - Dst_H -= pScrn->frameY0 - Port->Drw_Y; - Dst_Y = 0; - } else - Dst_Y = Port->Drw_Y - pScrn->frameY0; - - if ((Dst_Y + Dst_H) > limit) - Dst_H = limit - Dst_Y; - - /* set up window */ - Swov->Video->Video3WindowEnd &= 0xFFFF0000; - Swov->Video->Video3WindowEnd |= Dst_Y + Dst_H - 1; - - Swov->Video->Video3WindowStart &= 0xFFFF0000; - Swov->Video->Video3WindowStart |= Dst_Y; - - /* for startAddress offset */ - Port->Offset_Y = Src_Y; - - /* for alpha */ - Port->Win_Y = Dst_Y; - Port->Win_H = Dst_H; - - return TRUE; -} - -/* - * - */ -static void -ViaSwovStartAddress(struct ViaSwov *Swov, struct ViaXvPort *Port) -{ - unsigned long Offset; - - Offset = Port->Offset_Y * Port->Width + Port->Offset_X; - - 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; - if (Port->Back[2]) - Swov->Video->Video3Address2 = Port->Back[2]->Base + Offset; -} - /* * Eyecandy: alpha blended overlay. * @@ -1053,6 +519,9 @@ ViaSwovStartAddress(struct ViaSwov *Swov, struct ViaXvPort *Port) */ #define VIA_ALPHAADDRESS_ALIGN 16 +/* + * + */ static void ViaSwovAlphaFillRectangle(struct ViaXvPort *Port, CARD8 *Base, BoxRec Box) { @@ -1075,6 +544,9 @@ ViaSwovAlphaFillRectangle(struct ViaXvPort *Port, CARD8 *Base, BoxRec Box) (Box.x2 - Box.x1) / 2); } +/* + * + */ static void ViaSwovAlphaFill(ScrnInfoPtr pScrn, struct ViaMem *Mem) { @@ -1239,11 +711,11 @@ ViaSwovAlphaEnable(ScrnInfoPtr pScrn) struct ViaXvPort *Port = Swov->Port; ViaSwovAlphaSize(pScrn, Port->Drw_W, Port->Drw_H); - + if (ViaSwovAlphaSurface(pScrn)) { /* enable alpha */ Swov->Video->AlphaControl = 0x0000F001; - + /* disable colorkey */ Swov->Video->Compose &= ~0x0F; Swov->Video->Compose |= V3_COMMAND_FIRE; @@ -1253,6 +725,9 @@ ViaSwovAlphaEnable(ScrnInfoPtr pScrn) } } +/* + * + */ static void ViaSwovAlphaDisable(ScrnInfoPtr pScrn) { @@ -1262,11 +737,11 @@ ViaSwovAlphaDisable(ScrnInfoPtr pScrn) if (Port->Alpha[0]) ViaMemFree(pScrn, Port->Alpha[0]); Port->Alpha[0] = NULL; - + if (Port->Alpha[1]) ViaMemFree(pScrn, Port->Alpha[1]); Port->Alpha[1] = NULL; - + Swov->Video->Video3AlphaFifo &= 0x0000FFFF; Swov->Video->Video3AlphaPreFifo &= 0x8000007F; @@ -1288,6 +763,9 @@ ViaSwovAlphaDisable(ScrnInfoPtr pScrn) xf86XVFillKeyHelper(pScrn->pScreen, Port->ColorKey, &Port->clip); } +/* + * + */ static void ViaSwovAlphaSet(ScrnInfoPtr pScrn, INT32 value) { @@ -1308,226 +786,100 @@ ViaSwovAlphaSet(ScrnInfoPtr pScrn, INT32 value) } } -static void -ViaSwovCopy(VIAPtr pVia, struct ViaMem *Mem, unsigned char *buf) -{ -#if 0 - xf86memcpy(pVia->FBBase + Mem->Base, buf, Mem->Size); -#else - { - CARD32 *Dst = (CARD32 *) (pVia->FBBase + Mem->Base); - CARD32 *End = (CARD32 *) (pVia->FBBase + Mem->Base + Mem->Size); - CARD32 *Src = (CARD32 *) buf; - - while (Dst < End) { - *Dst = *Src; - Dst++; - Src++; - } - } -#endif -} - /* * */ -static void -ViaHQVFlip(VIAPtr pVia, unsigned char* buf) +static int +viaSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value, pointer data) { - struct ViaSwov *Swov = pVia->Swov; - struct ViaXvPort *Port = Swov->Port; - int i; - - for (i = 0; i < 15; i++) - if (!(Swov->HQV->Control & HQV_SW_FLIP)) - break; - else - usleep(1); + VIAPtr pVia = VIAPTR(pScrn); + struct ViaXvPort *Port = (struct ViaXvPort *) data; - if (i) { - ViaDebug(Swov->scrnIndex, "%s: flip wait: %d.\n", __FUNCTION__, i); - if ((Swov->HQV->Control & HQV_SW_FLIP)) - xf86DrvMsg(Swov->scrnIndex, X_WARNING, "%s: HQV is still flipping.\n", - __FUNCTION__); - } + if (attribute == xvColorKey) { + Port->ColorKey = value; - if (!Port->Front[1]) /* single buffering */ - ViaSwovCopy(pVia, Port->Front[0], buf); - else { /* We only need to set the address */ - Swov->HQV->SrcAddressY = Port->Front[0]->Base; - if (Port->CrOffset) { - Swov->HQV->SrcAddressU = Port->Front[0]->Base + Port->CbOffset; - Swov->HQV->SrcAddressV = Port->Front[0]->Base + Port->CrOffset; + if (!Port->Opacity) { + ViaSwovColorKey(pScrn, value); + REGION_EMPTY(pScrn->pScreen, &Port->clip); } - } - - Swov->HQV->Control |= HQV_SW_FLIP | HQV_FLIP_STATUS; + return Success; + } else if (attribute == xvAutoPaint) { + if (value) + Port->autoPaint = TRUE; + else + Port->autoPaint = FALSE; + return Success; + } else if (attribute == xvBrightness) { + Port->brightness = value; + VIASetColorSpace(pVia); + return Success; + } else if (attribute == xvContrast) { + Port->contrast = value; + VIASetColorSpace(pVia); + return Success; + } else if (attribute == xvSaturation) { + Port->saturation = value; + VIASetColorSpace(pVia); + return Success; + } else if (attribute == xvHue) { + Port->hue = value; + VIASetColorSpace(pVia); + return Success; + } else if (attribute == xvOpacity) { + if ((value < 0) || (value > 15)) + return BadValue; - /* Before we fire V3 for the first time, wait. */ - if (!Swov->Active) { - for (i = 0; i < 15; i++) - if ((Swov->HQV->Control & HQV_FLIP_STATUS)) - break; - else - usleep(1); - if (i) { - ViaDebug(Swov->scrnIndex, "%s: status wait: %d.\n", __FUNCTION__, i); - if (!(Swov->HQV->Control & HQV_FLIP_STATUS)) - xf86DrvMsg(Swov->scrnIndex, X_WARNING, "%s: Unable to initialise" - " the HQV. (Status still not set)\n", __FUNCTION__); - } + if (pVia->Swov->Active) + ViaSwovAlphaSet(pScrn, value); + else + Port->Opacity = value; + return Success; } -} - -/* - * - */ -static void -ViaSwovStop(ScrnInfoPtr pScrn) -{ - struct ViaSwov *Swov = VIAPTR(pScrn)->Swov; - vgaHWPtr hwp = VGAHWPTR(pScrn); - - VIAFUNC(pScrn->scrnIndex); - - if (Swov->HQVDisablePatch) - ViaSeqMask(hwp, 0x2E, 0x00, 0x10); - - Swov->Video->Video3AlphaFifo = ALPHA_FIFO_THRESHOLD4 | ALPHA_FIFO_DEPTH8 - | 0x00002431; /* threshold 24, depth 32 */ - - Swov->HQV->Control &= ~HQV_ENABLE; - - if (Swov->HQVDisablePatch) - ViaSeqMask(hwp, 0x2E, 0x10, 0x10); - /* disable alpha too */ - Swov->Video->AlphaControl = 0x001FF000; - - Swov->Active = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: Unhandled attribute.\n", + __FUNCTION__); + return BadMatch; } /* * */ -static void -ViaSwovInit(VIAPtr pVia) +static int +viaGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value, pointer data) { - struct ViaSwov *Swov = pVia->Swov; - - VIAFUNC(pVia->scrnIndex); - - Swov->scrnIndex = pVia->scrnIndex; - - Swov->Allowed = FALSE; - Swov->Active = FALSE; - - Swov->Adaptor = NULL; - Swov->Adaptors = NULL; - - /* Set up memory Map */ - Swov->Video = (struct ViaVideoRegs *) (pVia->MapBase + 0x200); - Swov->HQV = (struct ViaHQVRegs *) (pVia->MapBase + 0x3D0); - -#ifdef HAVE_DEBUG - if (pVia->PrintSwovRegs) - ViaSwovPrintRegs(Swov); -#endif - - /* make sure that nothing is active -- we might have an unclean state */ - Swov->Video->Video1Control &= ~0x00000001; - Swov->Video->Video3Control &= ~0x00000001; - Swov->HQV->Control &= ~0x08000000; - Swov->Video->AlphaControl = 0x001FF000; + struct ViaXvPort *Port = (struct ViaXvPort *) data; - /* old HWDiff stuff */ - switch(pVia->Chipset) { - case VIA_CLE266: - if (CLE266_REV_IS_AX(pVia->ChipRev)) { - Swov->ThreeHQVBuffer = FALSE; - Swov->HQVFetchByteUnit = TRUE; - Swov->HQVDisablePatch = FALSE; - } else { - Swov->ThreeHQVBuffer = TRUE; - Swov->HQVFetchByteUnit = FALSE; - Swov->HQVDisablePatch = TRUE; - } - break; - case VIA_KM400: - Swov->ThreeHQVBuffer = TRUE; - Swov->HQVFetchByteUnit = FALSE; - Swov->HQVDisablePatch = TRUE; - break; - case VIA_K8M800: - Swov->ThreeHQVBuffer = TRUE; - Swov->HQVFetchByteUnit = FALSE; - Swov->HQVDisablePatch = TRUE; - break; - case VIA_PM800: - Swov->ThreeHQVBuffer = TRUE; - Swov->HQVFetchByteUnit = FALSE; - Swov->HQVDisablePatch = FALSE; - break; - default: - xf86DrvMsg(pVia->scrnIndex, X_ERROR, "%s: Unhandled ChipSet.\n", - __FUNCTION__); + if (attribute == xvColorKey) { + *value =(INT32) Port->ColorKey; + return Success; + } else if (attribute == xvAutoPaint) { + if (Port->autoPaint) + *value = 1; + else + *value = 0; + return Success; + } else if (attribute == xvBrightness) { + *value = Port->brightness; + return Success; + } else if (attribute == xvContrast) { + *value = Port->contrast; + return Success; + } else if (attribute == xvSaturation) { + *value = Port->saturation; + return Success; + } else if (attribute == xvHue) { + *value = Port->hue; + return Success; + } else if (attribute == xvOpacity) { + *value = Port->Opacity; + return Success; } -} - -/* - * F U N C T I O N D E C L A R A T I O N - */ -static void viaStopVideo(ScrnInfoPtr, pointer, Bool); -static void viaQueryBestSize(ScrnInfoPtr, Bool, - short, short, short, short, unsigned int *, unsigned int *, pointer); -static int viaQueryImageAttributes(ScrnInfoPtr, - int, unsigned short *, unsigned short *, int *, int *); -static int viaGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); -static int viaSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); -static int viaPutImage(ScrnInfoPtr, short, short, short, short, short, short, - short, short,int, unsigned char*, short, short, Bool, - RegionPtr, pointer); -static int ViaSwovReputImage(ScrnInfoPtr pScrn, short drw_x, short drw_y, - RegionPtr clipBoxes, pointer data); - -static Atom xvBrightness, xvContrast, xvColorKey, xvHue, xvSaturation, - xvAutoPaint, xvOpacity; - -/* - * S T R U C T S - */ -/* client libraries expect an encoding */ -static XF86VideoEncodingRec DummyEncoding[1] = { - {XV_IMAGE, "XV_IMAGE", VIA_MAX_XVIMAGE_X, VIA_MAX_XVIMAGE_Y, {1, 1}}, -}; - -#define NUM_FORMATS_G 9 - -static XF86VideoFormatRec FormatsG[NUM_FORMATS_G] = -{ - { 8, TrueColor }, /* Dithered */ - { 8, PseudoColor }, /* Using .. */ - { 8, StaticColor }, - { 8, GrayScale }, - { 8, StaticGray }, /* .. TexelLUT */ - {16, TrueColor}, - {24, TrueColor}, - {16, DirectColor}, - {24, DirectColor} -}; - -#define NUM_ATTRIBUTES_G 7 -static XF86AttributeRec AttributesG[NUM_ATTRIBUTES_G] = -{ - {XvSettable | XvGettable, 0, 0x00FFFFFF, "XV_COLORKEY"}, - {XvSettable | XvGettable, 0, 10000, "XV_BRIGHTNESS"}, - {XvSettable | XvGettable, 0, 20000, "XV_CONTRAST"}, - {XvSettable | XvGettable, 0, 20000, "XV_SATURATION"}, - {XvSettable | XvGettable, -180, 180, "XV_HUE"}, - {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}, - {XvSettable | XvGettable, 0, 0x0F, "XV_OPACITY"} -}; + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: Unhandled attribute.\n", + __FUNCTION__); + *value = 0; + return BadMatch; +} /* * BLOODY MESS! @@ -1543,7 +895,10 @@ static XF86AttributeRec AttributesG[NUM_ATTRIBUTES_G] = #define VIDEO_BPP 2 -static Bool +/* + * + */ +static Bool ViaSwovBandwidth(ScrnInfoPtr pScrn) { VIAPtr pVia = VIAPTR(pScrn); @@ -1602,7 +957,7 @@ ViaSwovBandwidth(ScrnInfoPtr pScrn) memEfficiency = (float)SINGLE_3205_133; break; } - + width = mode->HDisplay; height = mode->VDisplay; refresh = mode->VRefresh; @@ -1630,108 +985,216 @@ ViaSwovBandwidth(ScrnInfoPtr pScrn) needBandWidth = (float)(((pScrn->bitsPerPixel >> 3) + VIDEO_BPP)*dClock); totalBandWidth = (float)(mClock*16.*memEfficiency); - + if (needBandWidth < totalBandWidth) return TRUE; } return FALSE; } +/* + * Only needs to be altered when the Front buffer size changes. + */ static void -ViaVideoReset(struct ViaSwov *Swov) +ViaHQVFetch(struct ViaSwov *Swov, struct ViaXvPort *Port) { - VIAFUNC(Swov->scrnIndex); + CARD32 Fetch = Port->Width; + CARD32 Height = Port->Height; + + 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__); + } - Swov->Video->Video1Control = 0; - Swov->Video->Video3Control = 0; - Swov->Video->Compose = 0x80000000; - Swov->Video->Compose = 0x40000000; - Swov->Video->ColorKey = 0x821; - Swov->Video->ColorKeySecond = 0x00000000; - Swov->Video->Video3ColorKey = 0x00000000; - Swov->Video->AlphaControl = 0x001FF000; -} + if (Swov->HQVFetchByteUnit) /* CLE266A */ + Fetch >>= 3; -void -ViaVideoSave(struct ViaSwov *Swov) -{ - VIAFUNC(Swov->scrnIndex); + if ((Port->Deinterlace & VIA_DEINT_BOB) && + !(Port->Deinterlace & VIA_DEINT_INTERLEAVE)) + Height <<= 1; - Swov->Video1Control = Swov->Video->Video1Control; - Swov->Video3Control = Swov->Video->Video3Control; - Swov->Video->Video1Control = 0; - Swov->Video->Video3Control = 0; - Swov->Video->Compose = 0x80000000; - Swov->Video->Compose = 0x40000000; + Swov->HQV->SrcFetch = ((Fetch - 1) << 16) | (Height - 1); } -void -ViaVideoRestore(struct ViaSwov *Swov) +/* + * Only needs to be altered when the Back buffer size changes. + */ +static void +ViaSwovStride(struct ViaSwov *Swov, struct ViaXvPort *Port) { - VIAFUNC(Swov->scrnIndex); - - Swov->Video->Video1Control = Swov->Video1Control; - Swov->Video->Video3Control = Swov->Video3Control; - Swov->Video->Compose = 0x80000000; - Swov->Video->Compose = 0x40000000; + switch (Port->FourCC) { + case FOURCC_YV12: + case FOURCC_I420: + /* planar YUV */ + Swov->HQV->SrcStride = ((Port->Width >> 1) << 16) | Port->Width; + 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; + 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__); + } } -void -ViaVideoExit(ScrnInfoPtr pScrn) +/* + * + */ +static Bool +ViaSwovSurfaceCreate(ScrnInfoPtr pScrn, CARD32 FourCC, CARD16 Width, CARD16 Height) { - struct ViaSwov *Swov = VIAPTR(pScrn)->Swov; + VIAPtr pVia = VIAPTR(pScrn); + struct ViaSwov *Swov = pVia->Swov; + struct ViaXvPort *Port = Swov->Port; + int FrontSize, BackSize; - VIAFUNC(Swov->scrnIndex); + VIAFUNC(pScrn->scrnIndex); + ViaDebug(pScrn->scrnIndex, "%s: FourCC 0x%08X, Width %d, Height %d\n", + __FUNCTION__, FourCC, Width, Height); - if (Swov->Active) - ViaSwovStop(pScrn); + 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); + } else { /* YVU */ + Port->CrOffset = Width * Height; + Port->CbOffset = Port->CrOffset + (Width >> 1) * (Height >> 1); + } - if (Swov->Port->Front[0]) - ViaSwovSurfaceDestroy(pScrn); + 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; - Swov->Video->Video1Control = 0; - Swov->Video->Video3Control = 0; - Swov->Video->Compose = 0x80000000; - Swov->Video->Compose = 0x40000000; - Swov->Video->AlphaControl = 0x001FF000; + FrontSize = Width * Height * 2; + BackSize = FrontSize; + break; + case FOURCC_RV32: + Port->CrOffset = 0; + Port->CbOffset = 0; - /* Free all adapter info allocated in viaInitVideo. */ - if (Swov->Adaptor) { - if (Swov->Adaptor->pPortPrivates) { - if (Swov->Adaptor->pPortPrivates->ptr) - xfree(Swov->Adaptor->pPortPrivates->ptr); - xfree(Swov->Adaptor->pPortPrivates); + FrontSize = Width * Height * 4; + BackSize = FrontSize; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: unhandled FourCC: 0x%08X\n", + __FUNCTION__, FourCC); + return FALSE; + } + + Port->FourCC = FourCC; + Port->Width = Width; + Port->Height = Height; + + /* Front buffer, where the HQV sources its video. */ + Port->Front[0] = ViaMemAlloc(pScrn, FrontSize, 16); + if (!Port->Front[0]) + return FALSE; + + ViaHQVFetch(Swov, Port); + + /* Back Buffer: HQV destination and Video3 source. */ + 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, FrontSize, 16); + if (!Port->Front[1]) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s: Not enough memory available.\n", + __FUNCTION__); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s: Using only a single front buffer.\n", + __FUNCTION__); + + Swov->HQV->SrcAddressY = Port->Front[0]->Base; + if (Port->CrOffset) { + Swov->HQV->SrcAddressU = Port->Front[0]->Base + Port->CbOffset; + Swov->HQV->SrcAddressV = Port->Front[0]->Base + Port->CrOffset; } - xfree(Swov->Adaptor); } - if (Swov->Adaptors) - xfree(Swov->Adaptors); + /* This one may fail too. */ + if (Swov->ThreeHQVBuffer) { + Port->Back[2] = ViaMemAlloc(pScrn, BackSize, 16); + if (!Port->Back[2]) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s: Not enough memory available.\n", + __FUNCTION__); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s: Using only 2 back buffers.\n", + __FUNCTION__); + } + } + + Swov->HQV->DstAddress0 = Port->Back[0]->Base; + Swov->HQV->DstAddress1 = Port->Back[1]->Base; + if (Port->Back[2]) + Swov->HQV->DstAddress2 = Port->Back[2]->Base; + + ViaSwovStride(Swov, Port); + + return TRUE; } -static struct ViaXvPort * -ViaXvPortInit(ScreenPtr pScreen) +/* + * + */ +static void +ViaSwovSurfaceDestroy(ScrnInfoPtr pScrn) { - struct ViaXvPort *Port = xnfcalloc(1, sizeof(struct ViaXvPort)); - - Port->ColorKey = 0x821; - Port->autoPaint = TRUE; - Port->brightness = 5000.; - Port->saturation = 10000; - Port->contrast = 10000; - Port->hue = 0; - Port->Opacity = 0; + struct ViaSwov *Swov = VIAPTR(pScrn)->Swov; + struct ViaXvPort *Port = Swov->Port; -#ifdef X_USE_REGION_NULL - REGION_NULL(pScreen, &Port->clip); -#else - REGION_INIT(pScreen, &Port->clip, NullBox, 1); -#endif + VIAFUNC(pScrn->scrnIndex); - /* init ViaMem pointers */ + Port->FourCC = 0; Port->Width = 0; Port->Height = 0; + if (Port->Front[0]) + ViaMemFree(pScrn, Port->Front[0]); + if (Port->Front[1]) + ViaMemFree(pScrn, Port->Front[1]); + if (Port->Back[0]) + ViaMemFree(pScrn, Port->Back[0]); + if (Port->Back[1]) + ViaMemFree(pScrn, Port->Back[1]); + if (Port->Back[2]) + ViaMemFree(pScrn, Port->Back[2]); + if (Port->Alpha[0]) + ViaMemFree(pScrn, Port->Alpha[0]); + if (Port->Alpha[1]) + ViaMemFree(pScrn, Port->Alpha[1]); + Port->Front[0] = NULL; Port->Front[1] = NULL; Port->Back[0] = NULL; @@ -1739,263 +1202,407 @@ ViaXvPortInit(ScreenPtr pScreen) Port->Back[2] = NULL; Port->Alpha[0] = NULL; Port->Alpha[1] = NULL; +} - /* attribute? */ - Port->Deinterlace = VIA_DEINT_INTERLEAVE; +/* + * I've ditched all the FourCC stuff here. It's HQV->Video3 anyway. + * When not YV12 (amazingly), the FIFO was set set to + * (depth, prethreshold, threshhold) (1,0,0) when Width <= 8 + */ +static void +ViaSwovFIFO(VIAPtr pVia, struct ViaSwov *Swov) +{ + CARD8 depth, prethreshold, threshold; - Port->Src_X = 0; - Port->Src_Y = 0; - Port->Src_W = 0; - Port->Src_H = 0; + switch (pVia->Chipset) { + case VIA_CLE266: + if (CLE266_REV_IS_CX(pVia->ChipRev)) { + depth = 64; + prethreshold = 56; + threshold = 56; + Swov->Video->Video3Control |= V3_EXPIRE_NUM_F; + } else { /* CLE266Ax */ + depth = 32; + prethreshold = 16; + threshold = 8; + Swov->Video->Video3Control |= V3_EXPIRE_NUM; + } + break; + case VIA_KM400: + case VIA_K8M800: + depth = 32; + prethreshold = 29; + threshold = 29; + Swov->Video->Video3Control |= V3_EXPIRE_NUM_3205; + break; + default: + depth = 1; + prethreshold = 0; + threshold = 0; + break; + } - Port->Drw_X = 0; - Port->Drw_Y = 0; - Port->Drw_W = 0; - Port->Drw_H = 0; + Swov->Video->Video3AlphaFifo &= ~V3_FIFO_MASK; + Swov->Video->Video3AlphaFifo |= ((depth - 1) & 0xff) | ((threshold & 0xff) << 8); - return Port; + Swov->Video->Video3AlphaPreFifo &= ~V3_PREFIFO_MASK; + Swov->Video->Video3AlphaPreFifo |= (prethreshold & 0x7f); } -static XF86VideoAdaptorPtr -ViaXvAdaptorInit(ScrnInfoPtr pScrn) +/* + * + */ +static void +ViaHQVInit(struct ViaSwov *Swov) { - XF86VideoAdaptorPtr Adaptor; + struct ViaXvPort *Port = Swov->Port; - VIAFUNC(pScrn->scrnIndex); + Swov->HQV->Control = HQV_SRC_SW; + /* not CLE266Ax could need |= HQV_ENABLE | HQV_SW_FLIP */ - Adaptor = xf86XVAllocateVideoAdaptorRec(pScrn); - - Adaptor->type = XvInputMask | XvWindowMask | XvImageMask | - XvVideoMask | XvStillMask; - Adaptor->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; - - Adaptor->name = "XV_SWOV"; - Adaptor->nEncodings = 1; - Adaptor->pEncodings = DummyEncoding; - Adaptor->nFormats = sizeof(FormatsG) / sizeof(FormatsG[0]); - Adaptor->pFormats = FormatsG; - - Adaptor->nPorts = 1; - Adaptor->pPortPrivates = (DevUnion *)xnfcalloc(1, sizeof(DevUnion)); - Adaptor->pPortPrivates->ptr = VIAPTR(pScrn)->Swov->Port; - Adaptor->nAttributes = NUM_ATTRIBUTES_G; - Adaptor->pAttributes = AttributesG; + switch (Port->FourCC) { + case FOURCC_YV12: + case FOURCC_I420: + Swov->HQV->Control |= HQV_YUV420; + 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__); + } - Adaptor->nImages = NUM_IMAGES_G; - Adaptor->pImages = ImagesG; - Adaptor->PutVideo = NULL; - Adaptor->StopVideo = viaStopVideo; - Adaptor->QueryBestSize = viaQueryBestSize; - Adaptor->GetPortAttribute = viaGetPortAttribute; - Adaptor->SetPortAttribute = viaSetPortAttribute; - Adaptor->PutImage = viaPutImage; - Adaptor->ReputImage = ViaSwovReputImage; - Adaptor->QueryImageAttributes = viaQueryImageAttributes; - - return Adaptor; + /* why this flip stuff? -- Luc */ + if (Port->Back[2]) { + Swov->HQV->Control &= ~HQV_SW_FLIP; + Swov->HQV->Control |= HQV_TRIPLE_BUFF | HQV_FLIP_STATUS; + } + + /* For DCT450 test-BOB INTERLEAVE */ + if ((Port->Deinterlace & VIA_DEINT_BOB)) { + Swov->HQV->Control |= HQV_FIELD_2_FRAME | HQV_DEINTERLACE; + if ((Port->Deinterlace & VIA_DEINT_INTERLEAVE)) + Swov->HQV->Control |= HQV_FRAME_2_FIELD; + } + + Swov->HQV->Control |= HQV_ENABLE; } -void -ViaVideoInit(ScrnInfoPtr pScrn, ScreenPtr pScreen) +/* + * + */ +static void +ViaVideo3Init(struct ViaSwov *Swov) { - VIAPtr pVia = VIAPTR(pScrn); - struct ViaSwov *Swov; - XF86VideoAdaptorPtr adaptor[1], *adaptors[1]; - int num_adaptors; + struct ViaXvPort *Port = Swov->Port; - VIAFUNC(pScrn->scrnIndex); + Swov->Video->Compose = V_COMMAND_LOAD_VBI | ALWAYS_SELECT_VIDEO; + Swov->Video->Video3Control = V3_COLORSPACE_SIGN | V3_YUV422| V3_SWAP_HW_HQV; - num_adaptors = xf86XVListGenericAdaptors(pScrn, adaptors); + 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__); + } +} - xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); - xvContrast = MAKE_ATOM("XV_CONTRAST"); - xvColorKey = MAKE_ATOM("XV_COLORKEY"); - xvHue = MAKE_ATOM("XV_HUE"); - xvSaturation = MAKE_ATOM("XV_SATURATION"); - xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); - xvOpacity = MAKE_ATOM("XV_OPACITY"); +/* + * + */ +static void +ViaHQVSwovIdle(struct ViaSwov *Swov) +{ + int i; - ViaSwovInit(pVia); - Swov = pVia->Swov; + for (i = 0; i < 10; i++) + if (!(Swov->Video->Compose & V3_COMMAND_FIRE) && + (Swov->HQV->Control & HQV_IDLE)) + break; + else + usleep(1); - Swov->Port = ViaXvPortInit(pScreen); + if (i) { + ViaDebug(Swov->scrnIndex, "%s: idle/fire wait: %d.\n", __FUNCTION__, i); + if (!(Swov->HQV->Control & HQV_IDLE)) + xf86DrvMsg(Swov->scrnIndex, X_WARNING, "%s: HQV not idle.\n", + __FUNCTION__); + if ((Swov->Video->Compose & V3_COMMAND_FIRE)) + xf86DrvMsg(Swov->scrnIndex, X_WARNING, "%s: Video3 still firing.\n", + __FUNCTION__); + } - Swov->Adaptor = ViaXvAdaptorInit(pScrn); - ViaVideoReset(Swov); +} - Swov->Adaptors = xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); +/* + * Minify is done by the HQV entirely. + * Zoom is done by V3. + * + */ +static void +ViaSwovZoomH(struct ViaSwov *Swov, struct ViaXvPort *Port) +{ + unsigned long tmp; - if (num_adaptors) - memcpy(Swov->Adaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); + Swov->HQV->Minify &= 0xFFFF0000; + Swov->HQV->Filter &= 0xFFFF0000; + Swov->Video->Video3Zoom &= 0x0000FFFF; + Swov->Video->Video3Minify &= 0xF8FFFFFD; - adaptor[0] = pVia->Swov->Adaptor; - memcpy(Swov->Adaptors + num_adaptors, adaptor, sizeof(XF86VideoAdaptorPtr)); + if (Port->Src_W == Port->Drw_W) { /* No zoom */ + Swov->HQV->Filter |= HQV_H_HIPASS_F1_DEFAULT; + } else if (Port->Src_W < Port->Drw_W) { /* Zoom in */ - xf86XVScreenInit(pScreen, Swov->Adaptors, num_adaptors + 1); - VIASetColorSpace(pVia); + tmp = Port->Src_W * 0x800 / Port->Drw_W; + Swov->Video->Video3Zoom |= ((tmp & 0x7ff) << 16) | V3_X_ZOOM_ENABLE; + + Swov->Video->Video3Minify |= V3_X_INTERPOLY; + Swov->HQV->Filter |= HQV_H_HIPASS_F1_DEFAULT; + + } else { /* Zoom out */ + tmp = Port->Drw_W * 0x800 * 0x400 / Port->Src_W; + tmp = tmp / 0x400 + ((tmp & 0x3ff) ? 1 : 0); + + Swov->HQV->Minify |= (tmp & 0x7ff) | HQV_H_MINIFY_ENABLE; + + if (Port->Src_W > (4 * Port->Drw_W)) + Swov->HQV->Filter |= HQV_H_TAP8_12221; + else + Swov->HQV->Filter |= HQV_H_TAP4_121; + Swov->HQV->Minify |= HQV_HDEBLOCK_FILTER; + } } -static void -viaStopVideo(ScrnInfoPtr pScrn, pointer data, Bool exit) +/* + * + */ +static void +ViaSwovZoomV(struct ViaSwov *Swov, struct ViaXvPort *Port) { - struct ViaSwov *Swov = VIAPTR(pScrn)->Swov; - struct ViaXvPort *Port = (struct ViaXvPort *)data; + unsigned long tmp; + short Src_H = Port->Src_H; - VIAFUNC(pScrn->scrnIndex); + if ((Port->Deinterlace & VIA_DEINT_BOB) && + !(Port->Deinterlace & VIA_DEINT_INTERLEAVE)) + Src_H <<= 1; - if (!Port->Opacity) - REGION_EMPTY(pScrn->pScreen, &Port->clip); + Swov->HQV->Minify &= 0x0000FFFF; + Swov->HQV->Filter &= 0x0000FFFF; + Swov->Video->Video3Zoom &= 0xFFFF0000; + Swov->Video->Video3Minify &= 0xFFF8FFFA; - /* Hide overlay */ - Swov->Video->Video3Control &= ~V3_ENABLE; - Swov->Video->Compose |= V3_COMMAND_FIRE; + /* Setup Y zoom factor */ + if (Src_H == Port->Drw_H) { /* No zoom */ + Swov->HQV->Filter |= HQV_V_TAP4_121; + } else if (Src_H < Port->Drw_H) { /* Zoom in */ + ScrnInfoPtr pScrn = xf86Screens[Swov->scrnIndex]; - if (exit) { - ViaDebug(pScrn->scrnIndex, "%s: Exiting!\n", __FUNCTION__); + tmp = Src_H * 0x0400 / Port->Drw_H; + Swov->Video->Video3Zoom |= ((tmp & 0x3ff) | V3_Y_ZOOM_ENABLE); - ViaSwovStop(pScrn); - ViaSwovSurfaceDestroy(pScrn); + if ((VIAPTR(pScrn)->Chipset == VIA_CLE266) && (pScrn->currentMode->HDisplay > 1024)) + /* Temporary fix for 2D bandwidth problem. 2002/08/01*/ + Swov->Video->Video3Minify |= V3_YCBCR_INTERPOLY; + else + Swov->Video->Video3Minify |= V3_Y_INTERPOLY | V3_YCBCR_INTERPOLY; - Port->Drw_X = 0; - Port->Drw_Y = 0; - Port->Drw_W = 0; - Port->Drw_H = 0; - } + Swov->HQV->Filter |= HQV_V_TAP4_121; + Swov->HQV->Filter &= ~HQV_V_LOWPASS_4TAP; + } else { /* Zoom out */ + tmp = Port->Drw_H * 0x0800 * 0x400 / Src_H; + tmp = tmp / 0x400 + ((tmp & 0x3ff) ? 1 : 0); + Swov->HQV->Minify |= ((tmp & 0x7ff) << 16) | HQV_V_MINIFY_ENABLE; + + if (Src_H > (4 * Port->Drw_H)) + Swov->HQV->Filter |= HQV_V_TAP8_12221; + else + Swov->HQV->Filter |= HQV_V_TAP4_121; + Swov->HQV->Minify |= HQV_VDEBLOCK_FILTER; + } } -static int -viaSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value, pointer data) +/* + * Returns FALSE when the overlay is not currently visible. + */ +static Bool +ViaSwovVisibleH(ScrnInfoPtr pScrn, struct ViaXvPort *Port) { - VIAPtr pVia = VIAPTR(pScrn); - struct ViaXvPort *Port = (struct ViaXvPort *) data; + struct ViaSwov *Swov = VIAPTR(pScrn)->Swov; + short limit; + long temp; + CARD32 Fetch; + short Src_X, Src_W, Dst_X, Dst_W; - if (attribute == xvColorKey) { - Port->ColorKey = value; + /* Horizontal */ + if (pScrn->currentMode->HDisplay < 2047) + limit = pScrn->currentMode->HDisplay; + else + limit = 2047; - if (!Port->Opacity) { - ViaSwovColorKey(pScrn, value); - REGION_EMPTY(pScrn->pScreen, &Port->clip); - } - return Success; - } else if (attribute == xvAutoPaint) { - if (value) - Port->autoPaint = TRUE; - else - Port->autoPaint = FALSE; - return Success; - } else if (attribute == xvBrightness) { - Port->brightness = value; - VIASetColorSpace(pVia); - return Success; - } else if (attribute == xvContrast) { - Port->contrast = value; - VIASetColorSpace(pVia); - return Success; - } else if (attribute == xvSaturation) { - Port->saturation = value; - VIASetColorSpace(pVia); - return Success; - } else if (attribute == xvHue) { - Port->hue = value; - VIASetColorSpace(pVia); - return Success; - } else if (attribute == xvOpacity) { - if ((value < 0) || (value > 15)) - return BadValue; + if (((Port->Drw_X + Port->Drw_W) < pScrn->frameX0) || + (Port->Drw_X > (limit + pScrn->frameX0))) + return FALSE; - if (pVia->Swov->Active) - ViaSwovAlphaSet(pScrn, value); - else - Port->Opacity = value; - return Success; - } + Src_X = Port->Src_X; + Dst_W = Port->Drw_W; - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: Unhandled attribute.\n", - __FUNCTION__); - return BadMatch; -} + if (Port->Drw_X < pScrn->frameX0) { + temp = (pScrn->frameX0 - Port->Drw_X) * Port->Src_W; + temp += Port->Drw_W >> 1; + Src_X += temp / Port->Drw_W; -static int -viaGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value, pointer data) -{ - struct ViaXvPort *Port = (struct ViaXvPort *) data; + Dst_W -= pScrn->frameX0 - Port->Drw_X; + Dst_X = 0; + } else + Dst_X = Port->Drw_X - pScrn->frameX0; - if (attribute == xvColorKey) { - *value =(INT32) Port->ColorKey; - return Success; - } else if (attribute == xvAutoPaint) { - if (Port->autoPaint) - *value = 1; + if ((Dst_X + Dst_W) > limit) + Dst_W = limit - Dst_X; + + if (Dst_W != Port->Drw_W) { + temp = Dst_W * Port->Src_W; + temp += Port->Drw_W >> 1; + Src_W = temp / Port->Drw_W; + } else + Src_W = Port->Src_W; + + /* set up window */ + Swov->Video->Video3WindowEnd &= 0x0000FFFF; + Swov->Video->Video3WindowEnd |= (Dst_X + Dst_W - 1) << 16; + + Swov->Video->Video3WindowStart &= 0x0000FFFF; + Swov->Video->Video3WindowStart |= Dst_X << 16; + + /* set up Fetch */ + if (Port->FourCC == FOURCC_RV32) { + if (Dst_W >= Src_W) + Fetch = (ALIGN_TO(Src_W << 2, 16) >> 4) + 1; else - *value = 0; - return Success; - } else if (attribute == xvBrightness) { - *value = Port->brightness; - return Success; - } else if (attribute == xvContrast) { - *value = Port->contrast; - return Success; - } else if (attribute == xvSaturation) { - *value = Port->saturation; - return Success; - } else if (attribute == xvHue) { - *value = Port->hue; - return Success; - } else if (attribute == xvOpacity) { - *value = Port->Opacity; - return Success; + 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; } - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: Unhandled attribute.\n", - __FUNCTION__); - *value = 0; - return BadMatch; -} + /* Fix planar mode problem. */ + if (Fetch < 4) + Fetch = 4; -static void -viaQueryBestSize(ScrnInfoPtr pScrn, Bool motion, short vid_w, short vid_h, - short drw_w, short drw_h, unsigned int *p_w, unsigned int *p_h, - pointer data) -{ - *p_w = drw_w; - *p_h = drw_h; - - if (*p_w > 2048 ) - *p_w = 2048; + Swov->Video->Video3AlphaFetch &= ~V3_FETCH_COUNT; + Swov->Video->Video3AlphaFetch |= Fetch << 20; + + Swov->Video->Video3SrcWidth = Src_W - 1; + + /* for startAddress offset */ + Port->Offset_X = Src_X; + + /* for alpha */ + Port->Win_X = Dst_X; + Port->Win_W = Dst_W; + + return TRUE; } -/* Newer X versions have this built in, but debian xfree86-4.3.0 doesn't. */ -#ifndef REGION_EQUAL +/* + * + */ static Bool -RegionsEqual(ScreenPtr pScreen, RegionPtr A, RegionPtr B) +ViaSwovVisibleV(ScrnInfoPtr pScrn, struct ViaXvPort *Port) { - int *dataA, *dataB; - int num; + struct ViaSwov *Swov = VIAPTR(pScrn)->Swov; + short limit; + long temp; + short Src_Y, Dst_Y, Dst_H; - num = REGION_NUM_RECTS(A); - if(num != REGION_NUM_RECTS(B)) - return FALSE; + if (pScrn->currentMode->VDisplay < 2047) + limit = pScrn->currentMode->VDisplay; + else + limit = 2047; - if((A->extents.x1 != B->extents.x1) || - (A->extents.x2 != B->extents.x2) || - (A->extents.y1 != B->extents.y1) || - (A->extents.y2 != B->extents.y2)) + if (((Port->Drw_Y + Port->Drw_H) < pScrn->frameY0) || + (Port->Drw_Y > (limit + pScrn->frameY0))) return FALSE; - dataA = (int*)REGION_RECTS(A); - dataB = (int*)REGION_RECTS(B); + Src_Y = Port->Src_Y; + Dst_H = Port->Drw_H; + + if (Port->Drw_Y < pScrn->frameY0) { + /* Round down. */ + temp = (pScrn->frameY0 - Port->Drw_Y) * Port->Src_H; + Src_Y += temp / Port->Drw_H; + + Dst_H -= pScrn->frameY0 - Port->Drw_Y; + Dst_Y = 0; + } else + Dst_Y = Port->Drw_Y - pScrn->frameY0; + + if ((Dst_Y + Dst_H) > limit) + Dst_H = limit - Dst_Y; + + /* set up window */ + Swov->Video->Video3WindowEnd &= 0xFFFF0000; + Swov->Video->Video3WindowEnd |= Dst_Y + Dst_H - 1; + + Swov->Video->Video3WindowStart &= 0xFFFF0000; + Swov->Video->Video3WindowStart |= Dst_Y; + + /* for startAddress offset */ + Port->Offset_Y = Src_Y; + + /* for alpha */ + Port->Win_Y = Dst_Y; + Port->Win_H = Dst_H; - while(num--) { - if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])) - return FALSE; - dataA += 2; - dataB += 2; - } - return TRUE; } -#define REGION_EQUAL(_pScreen, _pReg1, _pReg2) RegionsEqual((_pScreen), (_pReg1), (_pReg2)) -#endif /* !REGION_EQUAL */ + +/* + * + */ +static void +ViaSwovStartAddress(struct ViaSwov *Swov, struct ViaXvPort *Port) +{ + unsigned long Offset; + + Offset = Port->Offset_Y * Port->Width + Port->Offset_X; + + 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; + if (Port->Back[2]) + Swov->Video->Video3Address2 = Port->Back[2]->Base + Offset; +} /* * @@ -2049,33 +1656,113 @@ ViaSwovWindow(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, return FALSE; } - + +/* + * Newer X versions have this built in, but debian xfree86-4.3.0 doesn't. + */ +#ifndef REGION_EQUAL +static Bool +RegionsEqual(ScreenPtr pScreen, RegionPtr A, RegionPtr B) +{ + int *dataA, *dataB; + int num; + + num = REGION_NUM_RECTS(A); + if(num != REGION_NUM_RECTS(B)) + return FALSE; + + if((A->extents.x1 != B->extents.x1) || + (A->extents.x2 != B->extents.x2) || + (A->extents.y1 != B->extents.y1) || + (A->extents.y2 != B->extents.y2)) + return FALSE; + + dataA = (int*)REGION_RECTS(A); + dataB = (int*)REGION_RECTS(B); + + while(num--) { + if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])) + return FALSE; + dataA += 2; + dataB += 2; + } + + return TRUE; +} +#define REGION_EQUAL(_pScreen, _pReg1, _pReg2) RegionsEqual((_pScreen), (_pReg1), (_pReg2)) +#endif /* !REGION_EQUAL */ + +/* + * + */ static void -ViaVideo3Init(struct ViaSwov *Swov) +ViaSwovCopy(VIAPtr pVia, struct ViaMem *Mem, unsigned char *buf) { +#if 0 + xf86memcpy(pVia->FBBase + Mem->Base, buf, Mem->Size); +#else + { + CARD32 *Dst = (CARD32 *) (pVia->FBBase + Mem->Base); + CARD32 *End = (CARD32 *) (pVia->FBBase + Mem->Base + Mem->Size); + CARD32 *Src = (CARD32 *) buf; + + while (Dst < End) { + *Dst = *Src; + Dst++; + Src++; + } + } +#endif +} + +/* + * + */ +static void +ViaHQVFlip(VIAPtr pVia, unsigned char* buf) +{ + struct ViaSwov *Swov = pVia->Swov; struct ViaXvPort *Port = Swov->Port; + int i; - Swov->Video->Compose = V_COMMAND_LOAD_VBI | ALWAYS_SELECT_VIDEO; - Swov->Video->Video3Control = V3_COLORSPACE_SIGN | V3_YUV422| V3_SWAP_HW_HQV; + for (i = 0; i < 15; i++) + if (!(Swov->HQV->Control & HQV_SW_FLIP)) + break; + else + usleep(1); - 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__); + if (i) { + ViaDebug(Swov->scrnIndex, "%s: flip wait: %d.\n", __FUNCTION__, i); + if ((Swov->HQV->Control & HQV_SW_FLIP)) + xf86DrvMsg(Swov->scrnIndex, X_WARNING, "%s: HQV is still flipping.\n", + __FUNCTION__); + } + + if (!Port->Front[1]) /* single buffering */ + ViaSwovCopy(pVia, Port->Front[0], buf); + else { /* We only need to set the address */ + Swov->HQV->SrcAddressY = Port->Front[0]->Base; + if (Port->CrOffset) { + Swov->HQV->SrcAddressU = Port->Front[0]->Base + Port->CbOffset; + Swov->HQV->SrcAddressV = Port->Front[0]->Base + Port->CrOffset; + } + } + + Swov->HQV->Control |= HQV_SW_FLIP | HQV_FLIP_STATUS; + + /* Before we fire V3 for the first time, wait. */ + if (!Swov->Active) { + for (i = 0; i < 15; i++) + if ((Swov->HQV->Control & HQV_FLIP_STATUS)) + break; + else + usleep(1); + if (i) { + ViaDebug(Swov->scrnIndex, "%s: status wait: %d.\n", __FUNCTION__, i); + if (!(Swov->HQV->Control & HQV_FLIP_STATUS)) + xf86DrvMsg(Swov->scrnIndex, X_WARNING, "%s: Unable to initialise" + " the HQV. (Status still not set)\n", __FUNCTION__); + } } } @@ -2195,6 +1882,75 @@ viaPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, } /* + * This doesn't fix the case where the overlay window was not + * in the visible frame when switching away. That one requires + * some DIX poking. + */ +static int +ViaSwovReputImage(ScrnInfoPtr pScrn, short drw_x, short drw_y, + RegionPtr clipBoxes, pointer data) +{ + struct ViaSwov *Swov = VIAPTR(pScrn)->Swov; + struct ViaXvPort *Port = Swov->Port; + Bool HVisible = TRUE, VVisible = TRUE; + + if (!Swov->Active) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s: Overlay not active.\n", + __FUNCTION__); + return BadAccess; + } + + /* redraw colorkey when needed -- does this ever get hit here? */ + if (!REGION_EQUAL(pScrn->pScreen, &Port->clip, clipBoxes)) { + REGION_COPY(pScrn->pScreen, &Port->clip, clipBoxes); + if (Port->autoPaint && !Port->Opacity) + xf86XVFillKeyHelper(pScrn->pScreen, Port->ColorKey, clipBoxes); + } + + /* FrameAdjust is usually in only a single direction */ + if ((pScrn->frameX0 != Swov->frameX0) || (drw_x != Port->Drw_X)) { + Port->Drw_X = drw_x; + HVisible = ViaSwovVisibleH(pScrn, Swov->Port); + } + + if ((pScrn->frameY0 != Swov->frameY0) || (drw_y != Port->Drw_Y)) { + Port->Drw_Y = drw_y; + VVisible = ViaSwovVisibleV(pScrn, Swov->Port); + } + + if (HVisible && VVisible) { + ViaSwovStartAddress(Swov, Swov->Port); + Swov->Video->Video3Control |= V3_ENABLE; + } else + Swov->Video->Video3Control &= ~V3_ENABLE; + + if (Port->Opacity) + ViaSwovAlphaPosition(pScrn); + + Swov->Video->Compose |= V3_COMMAND_FIRE; + + Swov->frameX0 = pScrn->frameX0; + Swov->frameY0 = pScrn->frameY0; + + return Success; +} + +/* + * + */ +static void +viaQueryBestSize(ScrnInfoPtr pScrn, Bool motion, short vid_w, short vid_h, + short drw_w, short drw_h, unsigned int *p_w, unsigned int *p_h, + pointer data) +{ + *p_w = drw_w; + *p_h = drw_h; + + if (*p_w > 2048 ) + *p_w = 2048; +} + +/* * */ static int @@ -2202,15 +1958,15 @@ viaQueryImageAttributes(ScrnInfoPtr pScrn, int FourCC, CARD16 *Width, CARD16 *Height, int *pitches, int *offsets) { int Size; - + if (!Width || !Height) return 0; - + if (*Width > VIA_MAX_XVIMAGE_X) *Width = VIA_MAX_XVIMAGE_X; if (*Height > VIA_MAX_XVIMAGE_Y) *Height = VIA_MAX_XVIMAGE_Y; - + switch (FourCC) { case FOURCC_YV12: /* YUV420 */ case FOURCC_I420: @@ -2266,63 +2022,353 @@ viaQueryImageAttributes(ScrnInfoPtr pScrn, int FourCC, CARD16 *Width, *Height = 0; return 0; } - + return Size; } +/* + * + */ +static void +ViaVideoReset(struct ViaSwov *Swov) +{ + VIAFUNC(Swov->scrnIndex); + + Swov->Video->Video1Control = 0; + Swov->Video->Video3Control = 0; + Swov->Video->Compose = 0x80000000; + Swov->Video->Compose = 0x40000000; + Swov->Video->ColorKey = 0x821; + Swov->Video->ColorKeySecond = 0x00000000; + Swov->Video->Video3ColorKey = 0x00000000; + Swov->Video->AlphaControl = 0x001FF000; +} + +/* + * + */ +void +ViaVideoSave(struct ViaSwov *Swov) +{ + VIAFUNC(Swov->scrnIndex); + + Swov->Video1Control = Swov->Video->Video1Control; + Swov->Video3Control = Swov->Video->Video3Control; + Swov->Video->Video1Control = 0; + Swov->Video->Video3Control = 0; + Swov->Video->Compose = 0x80000000; + Swov->Video->Compose = 0x40000000; +} /* - * This doesn't fix the case where the overlay window was not - * in the visible frame when switching away. That one requires - * some DIX poking. + * */ -static int -ViaSwovReputImage(ScrnInfoPtr pScrn, short drw_x, short drw_y, - RegionPtr clipBoxes, pointer data) +void +ViaVideoRestore(struct ViaSwov *Swov) +{ + VIAFUNC(Swov->scrnIndex); + + Swov->Video->Video1Control = Swov->Video1Control; + Swov->Video->Video3Control = Swov->Video3Control; + Swov->Video->Compose = 0x80000000; + Swov->Video->Compose = 0x40000000; +} + +/* + * + */ +static void +ViaSwovStop(ScrnInfoPtr pScrn) { struct ViaSwov *Swov = VIAPTR(pScrn)->Swov; - struct ViaXvPort *Port = Swov->Port; - Bool HVisible = TRUE, VVisible = TRUE; + vgaHWPtr hwp = VGAHWPTR(pScrn); - if (!Swov->Active) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s: Overlay not active.\n", - __FUNCTION__); - return BadAccess; - } + VIAFUNC(pScrn->scrnIndex); - /* redraw colorkey when needed -- does this ever get hit here? */ - if (!REGION_EQUAL(pScrn->pScreen, &Port->clip, clipBoxes)) { - REGION_COPY(pScrn->pScreen, &Port->clip, clipBoxes); - if (Port->autoPaint && !Port->Opacity) - xf86XVFillKeyHelper(pScrn->pScreen, Port->ColorKey, clipBoxes); - } + if (Swov->HQVDisablePatch) + ViaSeqMask(hwp, 0x2E, 0x00, 0x10); - /* FrameAdjust is usually in only a single direction */ - if ((pScrn->frameX0 != Swov->frameX0) || (drw_x != Port->Drw_X)) { - Port->Drw_X = drw_x; - HVisible = ViaSwovVisibleH(pScrn, Swov->Port); - } + Swov->Video->Video3AlphaFifo = ALPHA_FIFO_THRESHOLD4 | ALPHA_FIFO_DEPTH8 + | 0x00002431; /* threshold 24, depth 32 */ - if ((pScrn->frameY0 != Swov->frameY0) || (drw_y != Port->Drw_Y)) { - Port->Drw_Y = drw_y; - VVisible = ViaSwovVisibleV(pScrn, Swov->Port); + Swov->HQV->Control &= ~HQV_ENABLE; + + if (Swov->HQVDisablePatch) + ViaSeqMask(hwp, 0x2E, 0x10, 0x10); + + /* disable alpha too */ + Swov->Video->AlphaControl = 0x001FF000; + + Swov->Active = FALSE; +} + +/* + * + */ +void +ViaVideoExit(ScrnInfoPtr pScrn) +{ + struct ViaSwov *Swov = VIAPTR(pScrn)->Swov; + + VIAFUNC(Swov->scrnIndex); + + if (Swov->Active) + ViaSwovStop(pScrn); + + if (Swov->Port->Front[0]) + ViaSwovSurfaceDestroy(pScrn); + + Swov->Video->Video1Control = 0; + Swov->Video->Video3Control = 0; + Swov->Video->Compose = 0x80000000; + Swov->Video->Compose = 0x40000000; + Swov->Video->AlphaControl = 0x001FF000; + + /* Free all adapter info allocated in viaInitVideo. */ + if (Swov->Adaptor) { + if (Swov->Adaptor->pPortPrivates) { + if (Swov->Adaptor->pPortPrivates->ptr) + xfree(Swov->Adaptor->pPortPrivates->ptr); + xfree(Swov->Adaptor->pPortPrivates); + } + xfree(Swov->Adaptor); } - if (HVisible && VVisible) { - ViaSwovStartAddress(Swov, Swov->Port); - Swov->Video->Video3Control |= V3_ENABLE; - } else - Swov->Video->Video3Control &= ~V3_ENABLE; + if (Swov->Adaptors) + xfree(Swov->Adaptors); +} - if (Port->Opacity) - ViaSwovAlphaPosition(pScrn); +/* + * + */ +static void +viaStopVideo(ScrnInfoPtr pScrn, pointer data, Bool exit) +{ + struct ViaSwov *Swov = VIAPTR(pScrn)->Swov; + struct ViaXvPort *Port = (struct ViaXvPort *)data; + + VIAFUNC(pScrn->scrnIndex); + if (!Port->Opacity) + REGION_EMPTY(pScrn->pScreen, &Port->clip); + + /* Hide overlay */ + Swov->Video->Video3Control &= ~V3_ENABLE; Swov->Video->Compose |= V3_COMMAND_FIRE; - Swov->frameX0 = pScrn->frameX0; - Swov->frameY0 = pScrn->frameY0; + if (exit) { + ViaDebug(pScrn->scrnIndex, "%s: Exiting!\n", __FUNCTION__); - return Success; + ViaSwovStop(pScrn); + ViaSwovSurfaceDestroy(pScrn); + + Port->Drw_X = 0; + Port->Drw_Y = 0; + Port->Drw_W = 0; + Port->Drw_H = 0; + } +} + +/* + * + */ +static void +ViaSwovInit(VIAPtr pVia) +{ + struct ViaSwov *Swov = pVia->Swov; + + VIAFUNC(pVia->scrnIndex); + + Swov->scrnIndex = pVia->scrnIndex; + + Swov->Allowed = FALSE; + Swov->Active = FALSE; + + Swov->Adaptor = NULL; + Swov->Adaptors = NULL; + + /* Set up memory Map */ + Swov->Video = (struct ViaVideoRegs *) (pVia->MapBase + 0x200); + Swov->HQV = (struct ViaHQVRegs *) (pVia->MapBase + 0x3D0); + +#ifdef HAVE_DEBUG + if (pVia->PrintSwovRegs) + ViaSwovPrintRegs(Swov); +#endif + + /* make sure that nothing is active -- we might have an unclean state */ + Swov->Video->Video1Control &= ~0x00000001; + Swov->Video->Video3Control &= ~0x00000001; + Swov->HQV->Control &= ~0x08000000; + Swov->Video->AlphaControl = 0x001FF000; + + /* old HWDiff stuff */ + switch(pVia->Chipset) { + case VIA_CLE266: + if (CLE266_REV_IS_AX(pVia->ChipRev)) { + Swov->ThreeHQVBuffer = FALSE; + Swov->HQVFetchByteUnit = TRUE; + Swov->HQVDisablePatch = FALSE; + } else { + Swov->ThreeHQVBuffer = TRUE; + Swov->HQVFetchByteUnit = FALSE; + Swov->HQVDisablePatch = TRUE; + } + break; + case VIA_KM400: + Swov->ThreeHQVBuffer = TRUE; + Swov->HQVFetchByteUnit = FALSE; + Swov->HQVDisablePatch = TRUE; + break; + case VIA_K8M800: + Swov->ThreeHQVBuffer = TRUE; + Swov->HQVFetchByteUnit = FALSE; + Swov->HQVDisablePatch = TRUE; + break; + case VIA_PM800: + Swov->ThreeHQVBuffer = TRUE; + Swov->HQVFetchByteUnit = FALSE; + Swov->HQVDisablePatch = FALSE; + break; + default: + xf86DrvMsg(pVia->scrnIndex, X_ERROR, "%s: Unhandled ChipSet.\n", + __FUNCTION__); + } +} + +/* + * + */ +static struct ViaXvPort * +ViaXvPortInit(ScreenPtr pScreen) +{ + struct ViaXvPort *Port = xnfcalloc(1, sizeof(struct ViaXvPort)); + + Port->ColorKey = 0x821; + Port->autoPaint = TRUE; + Port->brightness = 5000.; + Port->saturation = 10000; + Port->contrast = 10000; + Port->hue = 0; + Port->Opacity = 0; + +#ifdef X_USE_REGION_NULL + REGION_NULL(pScreen, &Port->clip); +#else + REGION_INIT(pScreen, &Port->clip, NullBox, 1); +#endif + + /* init ViaMem pointers */ + Port->Width = 0; + Port->Height = 0; + + Port->Front[0] = NULL; + Port->Front[1] = NULL; + Port->Back[0] = NULL; + Port->Back[1] = NULL; + Port->Back[2] = NULL; + Port->Alpha[0] = NULL; + Port->Alpha[1] = NULL; + + /* attribute? */ + Port->Deinterlace = VIA_DEINT_INTERLEAVE; + + Port->Src_X = 0; + Port->Src_Y = 0; + Port->Src_W = 0; + Port->Src_H = 0; + + Port->Drw_X = 0; + Port->Drw_Y = 0; + Port->Drw_W = 0; + Port->Drw_H = 0; + + return Port; +} + +/* + * + */ +static XF86VideoAdaptorPtr +ViaXvAdaptorInit(ScrnInfoPtr pScrn) +{ + XF86VideoAdaptorPtr Adaptor; + + VIAFUNC(pScrn->scrnIndex); + + Adaptor = xf86XVAllocateVideoAdaptorRec(pScrn); + + Adaptor->type = XvInputMask | XvWindowMask | XvImageMask | + XvVideoMask | XvStillMask; + Adaptor->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + + Adaptor->name = "XV_SWOV"; + Adaptor->nEncodings = 1; + Adaptor->pEncodings = DummyEncoding; + Adaptor->nFormats = sizeof(FormatsG) / sizeof(FormatsG[0]); + Adaptor->pFormats = FormatsG; + + Adaptor->nPorts = 1; + Adaptor->pPortPrivates = (DevUnion *)xnfcalloc(1, sizeof(DevUnion)); + Adaptor->pPortPrivates->ptr = VIAPTR(pScrn)->Swov->Port; + Adaptor->nAttributes = NUM_ATTRIBUTES_G; + Adaptor->pAttributes = AttributesG; + + Adaptor->nImages = NUM_IMAGES_G; + Adaptor->pImages = ImagesG; + Adaptor->PutVideo = NULL; + Adaptor->StopVideo = viaStopVideo; + Adaptor->QueryBestSize = viaQueryBestSize; + Adaptor->GetPortAttribute = viaGetPortAttribute; + Adaptor->SetPortAttribute = viaSetPortAttribute; + Adaptor->PutImage = viaPutImage; + Adaptor->ReputImage = ViaSwovReputImage; + Adaptor->QueryImageAttributes = viaQueryImageAttributes; + + return Adaptor; +} + +/* + * + */ +void +ViaVideoInit(ScrnInfoPtr pScrn, ScreenPtr pScreen) +{ + VIAPtr pVia = VIAPTR(pScrn); + struct ViaSwov *Swov; + XF86VideoAdaptorPtr adaptor[1], *adaptors[1]; + int num_adaptors; + + VIAFUNC(pScrn->scrnIndex); + + num_adaptors = xf86XVListGenericAdaptors(pScrn, adaptors); + + xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); + xvContrast = MAKE_ATOM("XV_CONTRAST"); + xvColorKey = MAKE_ATOM("XV_COLORKEY"); + xvHue = MAKE_ATOM("XV_HUE"); + xvSaturation = MAKE_ATOM("XV_SATURATION"); + xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); + xvOpacity = MAKE_ATOM("XV_OPACITY"); + + ViaSwovInit(pVia); + Swov = pVia->Swov; + + Swov->Port = ViaXvPortInit(pScreen); + + Swov->Adaptor = ViaXvAdaptorInit(pScrn); + ViaVideoReset(Swov); + + Swov->Adaptors = xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); + + if (num_adaptors) + memcpy(Swov->Adaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); + + adaptor[0] = pVia->Swov->Adaptor; + memcpy(Swov->Adaptors + num_adaptors, adaptor, sizeof(XF86VideoAdaptorPtr)); + + xf86XVScreenInit(pScreen, Swov->Adaptors, num_adaptors + 1); + VIASetColorSpace(pVia); } #endif /* !XvExtension */ |