diff options
-rw-r--r-- | src/smi_video.c | 392 |
1 files changed, 271 insertions, 121 deletions
diff --git a/src/smi_video.c b/src/smi_video.c index 79fb087..3918b03 100644 --- a/src/smi_video.c +++ b/src/smi_video.c @@ -41,7 +41,8 @@ Author of changes: Corvin Zahn <zahn@zac.de> Date: 2.11.2001 */ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/smi_video.c,v 1.11 2003/04/23 21:51:44 tsi Exp $ */ +/* $XdotOrg: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/smi_video.c,v 1.2 2004/04/23 19:45:06 eich Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/siliconmotion/smi_video.c,v 1.13 2003/11/10 18:22:26 tsi Exp $ */ #include "smi.h" #include "smi_video.h" @@ -119,6 +120,9 @@ static Bool SMI_ClipVideo(ScrnInfoPtr pScrn, BoxPtr dst, static void SMI_DisplayVideo(ScrnInfoPtr pScrn, int id, int offset, short width, short height, int pitch, int x1, int y1, int x2, int y2, BoxPtr dstBox, short vid_w, short vid_h, short drw_w, short drw_h); +static void SMI_DisplayVideo0730(ScrnInfoPtr pScrn, int id, int offset, + short width, short height, int pitch, int x1, int y1, int x2, int y2, + BoxPtr dstBox, short vid_w, short vid_h, short drw_w, short drw_h); static void SMI_BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadMask); #if 0 @@ -130,11 +134,6 @@ static void SMI_WaitForSync(ScrnInfoPtr pScrn); static void SMI_InitOffscreenImages(ScreenPtr pScreen); static FBAreaPtr SMI_AllocateMemory(ScrnInfoPtr pScrn, FBAreaPtr area, int numLines); -static void SMI_CopyData(unsigned char *src, unsigned char *dst, int srcPitch, - int dstPitch, int height, int width); -static void SMI_CopyYV12Data(unsigned char *src1, unsigned char *src2, - unsigned char *src3, unsigned char *dst, int srcPitch1, int srcPitch2, - int dstPitch, int height, int width); static int SMI_AllocSurface(ScrnInfoPtr pScrn, int id, unsigned short width, unsigned short height, @@ -151,7 +150,11 @@ static int SMI_SetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attr, INT32 value); static int SetAttr(ScrnInfoPtr pScrn, int i, int value); static int SetAttrSAA7110(ScrnInfoPtr pScrn, int i, int value); static int SetAttrSAA7111(ScrnInfoPtr pScrn, int i, int value); +static void SetKeyReg(SMIPtr pSmi, int reg, int value); +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,0,0) +static Bool RegionsEqual(RegionPtr A, RegionPtr B); +#endif /** * Atoms */ @@ -176,7 +179,7 @@ static Atom xvInterlaced; #define N_SVIDEO_CHANNELS 2 #define N_VIDEO_INPUTS 2 -typedef enum _VideoInput { COMPOSITE, SVIDEO } VideoInput; +typedef enum _VideoInput { VID_COMPOSITE, VID_SVIDEO } VideoInput; /**************************************************************************/ @@ -457,6 +460,55 @@ static I2CByte SAA7111InitData[] = /**************************************************************************/ +/* To allow this ddx to work on 4_3_0 and above, we need to include this */ +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,0,0) +static Bool +RegionsEqual( + RegionPtr A, + RegionPtr B +) +{ + int *dataA, *dataB; + int num; + + ENTER_PROC("RegionsEqual"); + + num = REGION_NUM_RECTS(A); + if (num != REGION_NUM_RECTS(B)) + { + LEAVE_PROC("RegionsEqual"); + return(FALSE); + } + + if ( (A->extents.x1 != B->extents.x1) + || (A->extents.y1 != B->extents.y1) + || (A->extents.x2 != B->extents.x2) + || (A->extents.y2 != B->extents.y2) + ) + { + LEAVE_PROC("RegionsEqual"); + 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; + } + + LEAVE_PROC("RegionsEqual"); + return(TRUE); +} +#endif + + /** * generates XF86VideoEncoding[i] with video norm norm, video input format * input and video input channel channel @@ -528,18 +580,18 @@ SMI_BuildEncodings(SMI_PortPtr p) p->nenc = 0; for (ch = 0; ch < N_COMPOSITE_CHANNELS; ch++) { for (n = 0; n < N_VIDEO_NORMS; n++) { - SMI_AddEncoding(p->enc, p->nenc, n, COMPOSITE, ch); + SMI_AddEncoding(p->enc, p->nenc, n, VID_COMPOSITE, ch); p->norm[p->nenc] = n; - p->input[p->nenc] = COMPOSITE; + p->input[p->nenc] = VID_COMPOSITE; p->channel[p->nenc] = ch; p->nenc++; } } for (ch = 0; ch < N_SVIDEO_CHANNELS; ch++) { for (n = 0; n < N_VIDEO_NORMS; n++) { - SMI_AddEncoding(p->enc, p->nenc, n, SVIDEO, ch); + SMI_AddEncoding(p->enc, p->nenc, n, VID_SVIDEO, ch); p->norm[p->nenc] = n; - p->input[p->nenc] = SVIDEO; + p->input[p->nenc] = VID_SVIDEO; p->channel[p->nenc] = ch; p->nenc++; } @@ -660,7 +712,7 @@ SetAttr(ScrnInfoPtr pScrn, int i, int value) if (i == XV_BRIGHTNESS) { int my_value = (value <= 128? value + 128 : value - 128); - WRITE_VPR(pSmi, 0x5C, 0xEDEDED | (my_value << 24)); + SetKeyReg(pSmi, 0x5C, 0xEDEDED | (my_value << 24)); } else if (pPort->I2CDev.SlaveAddr == SAA7110) { return SetAttrSAA7110(pScrn, i, value); } @@ -715,7 +767,7 @@ SetAttrSAA7111(ScrnInfoPtr pScrn, int i, int value) return XvBadAlloc; } /* set video input format and channel */ - if (input == COMPOSITE) { + if (input == VID_COMPOSITE) { if (!xf86I2CWriteVec(&(pPort->I2CDev), SAA7111CompositeChannelSelect[channel], ENTRIES(SAA7111CompositeChannelSelect[channel]) / 2)) { @@ -850,7 +902,10 @@ SMI_SetupVideo( ptrAdaptor->pImages = SMI_VideoImages; #if SMI_USE_CAPTURE - ptrAdaptor->PutVideo = SMI_PutVideo; + if (pSmi->Chipset == SMI_COUGAR3DR) + ptrAdaptor->PutVideo = NULL; + else + ptrAdaptor->PutVideo = SMI_PutVideo; ptrAdaptor->PutStill = NULL; ptrAdaptor->GetVideo = NULL; ptrAdaptor->GetStill = NULL; @@ -906,7 +961,11 @@ SMI_SetupVideo( } else smiPortPtr->I2CDev.SlaveAddr = 0; +#if defined(REGION_NULL) + REGION_NULL(pScreen, &smiPortPtr->clip); +#else REGION_INIT(pScreen, &smiPortPtr->clip, NullBox, 0); +#endif pSmi->ptrAdaptor = ptrAdaptor; pSmi->BlockHandler = pScreen->BlockHandler; @@ -943,26 +1002,26 @@ SMI_ResetVideo( switch (pScrn->depth) { case 8: - WRITE_VPR(pSmi, 0x04, pPort->Attribute[XV_COLORKEY] & 0x00FF); - WRITE_VPR(pSmi, 0x08, 0); + SetKeyReg(pSmi, FPR04, pPort->Attribute[XV_COLORKEY] & 0x00FF); + SetKeyReg(pSmi, FPR08, 0); break; case 15: case 16: - WRITE_VPR(pSmi, 0x04, pPort->Attribute[XV_COLORKEY] & 0xFFFF); - WRITE_VPR(pSmi, 0x08, 0); + SetKeyReg(pSmi, FPR04, pPort->Attribute[XV_COLORKEY] & 0xFFFF); + SetKeyReg(pSmi, FPR08, 0); break; default: r = (pPort->Attribute[XV_COLORKEY] & pScrn->mask.red) >> pScrn->offset.red; g = (pPort->Attribute[XV_COLORKEY] & pScrn->mask.green) >> pScrn->offset.green; b = (pPort->Attribute[XV_COLORKEY] & pScrn->mask.blue) >> pScrn->offset.blue; - WRITE_VPR(pSmi, 0x04, ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)); - WRITE_VPR(pSmi, 0x08, 0); + SetKeyReg(pSmi, FPR04, ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)); + SetKeyReg(pSmi, FPR08, 0); break; } - WRITE_VPR(pSmi, 0x5C, 0xEDEDED | (pPort->Attribute[XV_BRIGHTNESS] << 24)); + SetKeyReg(pSmi, FPR5C, 0xEDEDED | (pPort->Attribute[XV_BRIGHTNESS] << 24)); LEAVE_PROC("SMI_ResetVideo"); } @@ -1234,7 +1293,11 @@ SMI_PutVideo( vid_address = (pPort->area->box.y1 * fbPitch); DEBUG((VERBLEV, "test RegionsEqual\n")); +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,0,0) + if (!RegionsEqual(&pPort->clip, clipBoxes)) +#else if (!REGION_EQUAL(pScrn->pScreen, &pPort->clip, clipBoxes)) +#endif { DEBUG((VERBLEV, "RegionCopy\n")); REGION_COPY(pScrn->pScreen, &pPort->clip, clipBoxes); @@ -1335,11 +1398,21 @@ SMI_StopVideo( { if (pPort->videoStatus & CLIENT_VIDEO_ON) { - WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x01000008); + if (pSmi->Chipset == SMI_COUGAR3DR) + { + WRITE_FPR(pSmi, FPR00, READ_FPR(pSmi, 0x00) & ~(FPR00_VWIENABLE)); + } + else + { + WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x01000008); + } #if SMI_USE_CAPTURE - WRITE_CPR(pSmi, 0x00, READ_CPR(pSmi, 0x00) & ~0x00000001); - WRITE_VPR(pSmi, 0x54, READ_VPR(pSmi, 0x54) & ~0x00F00000); -/* #864 OUT_SEQ(pSmi, 0x21, IN_SEQ(pSmi, 0x21) | 0x04); */ + if (pSmi->Chipset != SMI_COUGAR3DR) + { + WRITE_CPR(pSmi, 0x00, READ_CPR(pSmi, 0x00) & ~0x00000001); + WRITE_VPR(pSmi, 0x54, READ_VPR(pSmi, 0x54) & ~0x00F00000); + } + /* #864 OUT_SEQ(pSmi, 0x21, IN_SEQ(pSmi, 0x21) | 0x04); */ #endif } if (pPort->area != NULL) @@ -1384,19 +1457,19 @@ SMI_SetPortAttribute( switch (pScrn->depth) { case 8: - WRITE_VPR(pSmi, 0x04, value & 0x00FF); + SetKeyReg(pSmi, FPR04, value & 0x00FF); break; case 15: case 16: - WRITE_VPR(pSmi, 0x04, value & 0xFFFF); + SetKeyReg(pSmi, FPR04, value & 0xFFFF); break; default: r = (value & pScrn->mask.red) >> pScrn->offset.red; g = (value & pScrn->mask.green) >> pScrn->offset.green; b = (value & pScrn->mask.blue) >> pScrn->offset.blue; - WRITE_VPR(pSmi, 0x04, + SetKeyReg(pSmi, FPR04, ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)); break; } @@ -1613,37 +1686,49 @@ SMI_PutImage( offset = (pPort->area->box.y1 * fbPitch) + (top * dstPitch); dstStart = pSmi->FBBase + offset + left; - switch (id) - { - case FOURCC_YV12: - case FOURCC_I420: - top &= ~1; - tmp = ((top >> 1) * srcPitch2) + (left >> 2); - offset2 += tmp; - offset3 += tmp; - nLines = ((((y2 + 0xFFFF) >> 16) + 1) & ~1) - top; - SMI_CopyYV12Data(buf + (top * srcPitch) + (left >> 1), - buf + offset2, buf + offset3, dstStart, srcPitch, srcPitch2, - dstPitch, nLines, nPixels); - break; - - default: - buf += (top * srcPitch) + left; - nLines = ((y2 + 0xFFFF) >> 16) - top; - SMI_CopyData(buf, dstStart, srcPitch, dstPitch, nLines, - nPixels * bpp); - break; - } + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + top &= ~1; + tmp = ((top >> 1) * srcPitch2) + (left >> 2); + offset2 += tmp; + offset3 += tmp; + if(id == FOURCC_I420) { + tmp = offset2; + offset2 = offset3; + offset3 = tmp; + } + nLines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; + xf86XVCopyYUV12ToPacked(buf + (top * srcPitch) + (left >> 1), + buf + offset2, buf + offset3, dstStart, + srcPitch, srcPitch2, dstPitch, nLines, nPixels); + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + buf += (top * srcPitch) + left; + nLines = ((y2 + 0xffff) >> 16) - top; + xf86XVCopyPacked(buf, dstStart, srcPitch, dstPitch, nLines, nPixels); + break; + } +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,0,0) + if (!RegionsEqual(&pPort->clip, clipBoxes)) +#else if (!REGION_EQUAL(pScrn->pScreen, &pPort->clip, clipBoxes)) +#endif { REGION_COPY(pScrn->pScreen, &pPort->clip, clipBoxes); xf86XVFillKeyHelper(pScrn->pScreen, pPort->Attribute[XV_COLORKEY], clipBoxes); } - SMI_DisplayVideo(pScrn, id, offset, width, height, dstPitch, x1, y1, x2, y2, - &dstBox, src_w, src_h, drw_w, drw_h); + if (pSmi->Chipset != SMI_COUGAR3DR) + SMI_DisplayVideo(pScrn, id, offset, width, height, dstPitch, x1, y1, x2, y2, + &dstBox, src_w, src_h, drw_w, drw_h); + else + SMI_DisplayVideo0730(pScrn, id, offset, width, height, dstPitch, x1, y1, x2, y2, + &dstBox, src_w, src_h, drw_w, drw_h); pPort->videoStatus = CLIENT_VIDEO_ON; LEAVE_PROC("SMI_PutImage"); @@ -1781,8 +1866,9 @@ SMI_ClipVideo( INT32 height ) { + ScreenPtr pScreen = pScrn->pScreen; INT32 vscale, hscale; - BoxPtr extents = REGION_EXTENTS(pScrn, reg); + BoxPtr extents = REGION_EXTENTS(pScreen, reg); int diff; ENTER_PROC("SMI_ClipVideo"); @@ -1877,9 +1963,9 @@ SMI_ClipVideo( ) { RegionRec clipReg; - REGION_INIT(pScrn, &clipReg, dst, 1); - REGION_INTERSECT(pScrn, reg, reg, &clipReg); - REGION_UNINIT(pScrn, &clipReg); + REGION_INIT(pScreen, &clipReg, dst, 1); + REGION_INTERSECT(pScreen, reg, reg, &clipReg); + REGION_UNINIT(pScreen, &clipReg); } DEBUG((VERBLEV, "ClipVideo(%d): x1=%d y1=%d x2=%d y2=%d\n", __LINE__, *x1 >> 16, *y1 >> 16, *x2 >> 16, *y2 >> 16)); @@ -1973,6 +2059,90 @@ SMI_DisplayVideo( } static void +SMI_DisplayVideo0730( + ScrnInfoPtr pScrn, + int id, + int offset, + short width, + short height, + int pitch, + int x1, + int y1, + int x2, + int y2, + BoxPtr dstBox, + short vid_w, + short vid_h, + short drw_w, + short drw_h +) +{ + SMIPtr pSmi = SMIPTR(pScrn); + CARD32 fpr00; + int hstretch, vstretch; + + ENTER_PROC("SMI_DisplayVideo0730"); + + fpr00 = READ_FPR(pSmi, 0x00) & ~(FPR00_MASKBITS); + + switch (id) + { + case FOURCC_YV12: + case FOURCC_I420: + case FOURCC_YUY2: + fpr00 |= FPR00_FMT_YUV422; + break; + + case FOURCC_RV15: + fpr00 |= FPR00_FMT_15P; + break; + + case FOURCC_RV16: + fpr00 |= FPR00_FMT_16P; + break; + + case FOURCC_RV24: + fpr00 |= FPR00_FMT_24P; + break; + + case FOURCC_RV32: + fpr00 |= FPR00_FMT_32P; + break; + } + + /* the formulas for calculating the stretch values do not match the + documentation, but they're the same as the ddraw driver and they work */ + if (drw_w > vid_w) + { + hstretch = (8192 * vid_w / drw_w); + } + else + { + hstretch = 0; + } + + if (drw_h > vid_h) + { + vstretch = (8192 * vid_h / drw_h); + } + else + { + vstretch = 0; + } + + + WRITE_FPR(pSmi, FPR00, fpr00 | FPR00_VWIENABLE | FPR00_VWIKEYENABLE); + WRITE_FPR(pSmi, FPR14, (dstBox->x1) | (dstBox->y1 << 16)); + WRITE_FPR(pSmi, FPR18, (dstBox->x2) | (dstBox->y2 << 16)); + WRITE_FPR(pSmi, FPR1C, offset >> 3); + WRITE_FPR(pSmi, FPR20, (pitch >> 3) | ((pitch >> 3) << 16)); + WRITE_FPR(pSmi, FPR24, (hstretch & 0xFF00) | ((vstretch & 0xFF00)>>8)); + WRITE_FPR(pSmi, FPR68, ((hstretch & 0x00FF)<<8) | (vstretch & 0x00FF)); + + LEAVE_PROC("SMI_DisplayVideo0730"); +} + +static void SMI_BlockHandler( int i, pointer blockData, @@ -1996,7 +2166,14 @@ SMI_BlockHandler( { if (pPort->offTime < currentTime.milliseconds) { - WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x00000008); + if (pSmi->Chipset == SMI_COUGAR3DR) + { + WRITE_FPR(pSmi, FPR00, READ_FPR(pSmi, 0x00) & ~(FPR00_VWIENABLE)); + } + else + { + WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x00000008); + } pPort->videoStatus = FREE_TIMER; pPort->freeTime = currentTime.milliseconds + FREE_DELAY; } @@ -2172,65 +2349,6 @@ SMI_AllocateMemory( return(area); } -static void -SMI_CopyData( - unsigned char *src, - unsigned char *dst, - int srcPitch, - int dstPitch, - int height, - int width -) -{ - ENTER_PROC("SMI_CopyData"); - - while (height-- > 0) - { - memcpy(dst, src, width); - src += srcPitch; - dst += dstPitch; - } - - LEAVE_PROC("SMI_CopyData"); -} - -static void -SMI_CopyYV12Data( - unsigned char *src1, - unsigned char *src2, - unsigned char *src3, - unsigned char *dst, - int srcPitch1, - int srcPitch2, - int dstPitch, - int height, - int width -) -{ - CARD32 *pDst = (CARD32 *) dst; - int i, j; - - ENTER_PROC("SMI_CopyYV12Data"); - - for (j = 0; j < height; j++) - { - for (i =0; i < width; i++) - { - pDst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) | - (src3[i] << 8) | (src2[i] << 24); - } - pDst += dstPitch >> 2; - src1 += srcPitch1; - if (j & 1) - { - src2 += srcPitch2; - src3 += srcPitch2; - } - } - - LEAVE_PROC("SMI_CopyYV12Data"); -} - static int SMI_AllocSurface( ScrnInfoPtr pScrn, @@ -2407,15 +2525,25 @@ SMI_DisplaySurface( xf86XVFillKeyHelper(surface->pScrn->pScreen, pPort->Attribute[XV_COLORKEY], clipBoxes); - SMI_ResetVideo(surface->pScrn); - SMI_DisplayVideo(surface->pScrn, surface->id, surface->offsets[0], - surface->width, surface->height, surface->pitches[0], x1, y1, x2, - y2, &dstBox, vid_w, vid_h, drw_w, drw_h); + if (pSmi->Chipset != SMI_COUGAR3DR) + { + SMI_ResetVideo(surface->pScrn); + SMI_DisplayVideo(surface->pScrn, surface->id, surface->offsets[0], + surface->width, surface->height, surface->pitches[0], x1, y1, x2, + y2, &dstBox, vid_w, vid_h, drw_w, drw_h); + } + else + { + SMI_ResetVideo(surface->pScrn); + SMI_DisplayVideo0730(surface->pScrn, surface->id, surface->offsets[0], + surface->width, surface->height, surface->pitches[0], x1, y1, x2, + y2, &dstBox, vid_w, vid_h, drw_w, drw_h); + } ptrOffscreen->isOn = TRUE; if (pPort->videoStatus & CLIENT_VIDEO_ON) { - REGION_EMPTY(pScrn->pScreen, &pPort->clip); + REGION_EMPTY(surface->pScrn->pScreen, &pPort->clip); UpdateCurrentTime(); pPort->videoStatus = FREE_TIMER; pPort->freeTime = currentTime.milliseconds + FREE_DELAY; @@ -2437,7 +2565,15 @@ SMI_StopSurface( if (ptrOffscreen->isOn) { SMIPtr pSmi = SMIPTR(surface->pScrn); - WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x00000008); + if (pSmi->Chipset == SMI_COUGAR3DR) + { + WRITE_FPR(pSmi, FPR00, READ_FPR(pSmi, 0x00) & ~(FPR00_VWIENABLE)); + } + else + { + WRITE_VPR(pSmi, 0x00, READ_VPR(pSmi, 0x00) & ~0x00000008); + } + ptrOffscreen->isOn = FALSE; } @@ -2470,6 +2606,20 @@ SMI_SetSurfaceAttribute( return(SMI_SetPortAttribute(pScrn, attr, value, (pointer) pSmi->ptrAdaptor->pPortPrivates[0].ptr)); } + +static void +SetKeyReg(SMIPtr pSmi, int reg, int value) +{ + if (pSmi->Chipset == SMI_COUGAR3DR) + { + WRITE_FPR(pSmi, reg, value); + } + else + { + WRITE_VPR(pSmi, reg, value); + } +} + #else /* SMI_USE_VIDEO */ void SMI_InitVideo(ScreenPtr pScreen) {} #endif |