diff options
author | Paulo Cesar Pereira de Andrade <pcpa@mandriva.com.br> | 2008-11-04 15:57:12 -0200 |
---|---|---|
committer | Paulo Cesar Pereira de Andrade <pcpa@mandriva.com.br> | 2008-11-04 15:57:12 -0200 |
commit | 1d7b9547e1d37601f14410857c22f256e5c74f14 (patch) | |
tree | 435e5494c22952c20843eb6282ccf0f67df18fc3 /src/smi_video.c | |
parent | 93308d067c93126dd0aba9b718d9e0ba28dde9f4 (diff) |
Add CSCVideo option to smi 501/502.
This code is an adaptation of SMI sample implementation.
CSCVideo is an alternate way to render video, that should reduce memory
bandwidth usage, and uses the color space conversion hardware to render
video directly to the framebuffer memory.
When using randr dual head mode, currently only XAA is supported. As it
has a fixed format framebuffer (when using the Virtual xorg.conf option).
This patch also ensures that pScrn->displayWidth, pScrn->virtualX and
pScrn->virtualY are only changed by the driver when using EXA.
Diffstat (limited to 'src/smi_video.c')
-rw-r--r-- | src/smi_video.c | 382 |
1 files changed, 325 insertions, 57 deletions
diff --git a/src/smi_video.c b/src/smi_video.c index 89b41ca..d340f93 100644 --- a/src/smi_video.c +++ b/src/smi_video.c @@ -1,8 +1,8 @@ -/* Header: //Mercury/Projects/archives/XFree86/4.0/smi_video.c.-arc 1.14 30 Nov 2000 16:51:40 Frido $ */ /* Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved. -Copyright (C) 2000 Silicon Motion, Inc. All Rights Reserved. +Copyright (C) 2000,2008 Silicon Motion, Inc. All Rights Reserved. Copyright (C) 2001 Corvin Zahn. All Rights Reserved. +Copyright (C) 2008 Mandriva Linux. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -27,18 +27,25 @@ sale, use or other dealings in this Software without prior written authorization from the XFree86 Project and silicon Motion. */ + /* -this is a heavy modified version of the V1.2.2 original siliconmotion driver. -- SAA7111 support -- supports attributes: XV_ENCODING, XV_BRIGHTNESS, XV_CONTRAST, - XV_SATURATION, XV_HUE, XV_COLORKEY, XV_INTERLACED - XV_CAPTURE_BRIGHTNESS can be used to set brightness in the capture device -- bug fixes -- tries not to use acceleration functions -- interlaced video for double vertical resolution - -Author of changes: Corvin Zahn <zahn@zac.de> -Date: 2.11.2001 + Corvin Zahn <zahn@zac.de> Date: 2.11.2001 + - SAA7111 support + - supports attributes: XV_ENCODING, XV_BRIGHTNESS, XV_CONTRAST, + XV_SATURATION, XV_HUE, XV_COLORKEY, XV_INTERLACED + XV_CAPTURE_BRIGHTNESS can be used to set brightness in the capture device + - bug fixes + - tries not to use acceleration functions + - interlaced video for double vertical resolution + XV_INTERLACED = 0: only one field of an interlaced video signal is + displayed: + -> half vertical resolution, but no comb like artifacts + from moving vertical edges + XV_INTERLACED = 1: both fields of an interlaced video signal are + displayed: + -> full vertical resolution, but comb like artifacts from + moving vertical edges + The default value can be set with the driver option Interlaced */ @@ -51,22 +58,6 @@ Date: 2.11.2001 #include "xf86Crtc.h" -/* - -new attribute: - -XV_INTERLACED = 0: only one field of an interlaced video signal is displayed: - -> half vertical resolution, but no comb like artifacts from - moving vertical edges -XV_INTERLACED = 1: both fields of an interlaced video signal are displayed: - -> full vertical resolution, but comb like artifacts from - moving vertical edges - -The default value can be set with the driver option Interlaced - -*/ - - #undef MIN #undef ABS #undef CLAMP @@ -118,6 +109,13 @@ static int SMI_QueryImageAttributes(ScrnInfoPtr pScrn, 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_CSC_Start(SMIPtr pSmi, CARD32 CSC_Control); +static void SMI_DisplayVideo0501_CSC(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, + RegionPtr clipboxes); static void SMI_DisplayVideo0501(ScrnInfoPtr pScrn, int id, int offset, short width, short height, int pitch, int x1, int y1, int x2, int y2, @@ -135,8 +133,15 @@ static void SMI_InitOffscreenImages(ScreenPtr pScreen); static void SMI_VideoSave(ScreenPtr pScreen, ExaOffscreenArea *area); static CARD32 SMI_AllocateMemory(ScrnInfoPtr pScrn, void **mem_struct, int size); static void SMI_FreeMemory(ScrnInfoPtr pScrn, void *mem_struct); - +static void CopyYV12ToVideoMem(unsigned char *src1, unsigned char *src2, + unsigned char *src3, unsigned char *dst, + int src1Pitch, int src23Pitch, 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, XF86SurfacePtr surface); @@ -1147,10 +1152,7 @@ SMI_PutVideo( if (pSmi->ByteSwap) cpr00 |= 0x00004000; - fbPitch = pSmi->Stride; - if (pSmi->Bpp != 3) { - fbPitch *= pSmi->Bpp; - } + fbPitch = (pScrn->displayWidth * pSmi->Bpp + 15) & ~15; if (vid_w <= drw_w) { xscale = (256 * vid_w / drw_w) & 0xFF; @@ -1483,8 +1485,8 @@ SMI_PutImage( short src_h, short drw_w, short drw_h, - int id, - unsigned char *buf, + int id, + unsigned char *buf, short width, short height, Bool sync, @@ -1517,15 +1519,23 @@ SMI_PutImage( dstBox.x2 = drw_x + drw_w; dstBox.y2 = drw_y + drw_h; - if(!xf86_crtc_clip_video_helper(pScrn, &crtc, NULL, &dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height)) - RETURN(Success); - - /* Transform dstBox to the CRTC coordinates */ - dstBox.x1 -= crtc->x; - dstBox.y1 -= crtc->y; - dstBox.x2 -= crtc->x; - dstBox.y2 -= crtc->y; - + if (pSmi->CSCVideo) { + if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, + width, height)) + RETURN(Success); + } + else { + if (!xf86_crtc_clip_video_helper(pScrn, &crtc, NULL, &dstBox, + &x1, &x2, &y1, &y2, clipBoxes, + width, height)) + RETURN(Success); + + /* Transform dstBox to the CRTC coordinates */ + dstBox.x1 -= crtc->x; + dstBox.y1 -= crtc->y; + dstBox.x2 -= crtc->x; + dstBox.y2 -= crtc->y; + } switch (id) { case FOURCC_YV12: @@ -1533,14 +1543,20 @@ SMI_PutImage( offset2 = srcPitch * height; srcPitch2 = ((width >> 1) + 3) & ~3; offset3 = offset2 + (srcPitch2 * (height >> 1)); - dstPitch = ((width << 1) + 15) & ~15; + if (pSmi->CSCVideo) + dstPitch = (((width >> 1) + 15) & ~15) << 1; + else + dstPitch = ((width << 1) + 15) & ~15; break; case FOURCC_I420: srcPitch = (width + 3) & ~3; offset3 = srcPitch * height; srcPitch2 = ((width >> 1) + 3) & ~3; offset2 = offset3 + (srcPitch2 * (height >> 1)); - dstPitch = ((width << 1) + 15) & ~15; + if (pSmi->CSCVideo) + dstPitch = (((width >> 1) + 15) & ~15) << 1; + else + dstPitch = ((width << 1) + 15) & ~15; break; case FOURCC_RV24: bpp = 3; @@ -1582,10 +1598,25 @@ SMI_PutImage( tmp = ((top >> 1) * srcPitch2) + (left >> 2); offset2 += tmp; 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); + + if (id == FOURCC_I420) { + tmp = offset2; + offset2 = offset3; + offset3 = tmp; + } + + if (pSmi->CSCVideo) + CopyYV12ToVideoMem(buf, + buf + offset2, buf + offset3, + dstStart, srcPitch, srcPitch2, dstPitch, + height, width); + else { + 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: @@ -1599,17 +1630,24 @@ SMI_PutImage( if (IS_MSOC(pSmi) || !REGION_EQUAL(pScrn->pScreen, &pPort->clip, clipBoxes)) { REGION_COPY(pScrn->pScreen, &pPort->clip, clipBoxes); - xf86XVFillKeyHelper(pScrn->pScreen, pPort->Attribute[XV_COLORKEY], - clipBoxes); + if (!pSmi->CSCVideo) + xf86XVFillKeyHelper(pScrn->pScreen, pPort->Attribute[XV_COLORKEY], + clipBoxes); } if (pSmi->Chipset == SMI_COUGAR3DR) SMI_DisplayVideo0730(pScrn, id, offset, width, height, dstPitch, x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); - else if (IS_MSOC(pSmi)) - SMI_DisplayVideo0501(pScrn, id, offset, width, height, dstPitch, - x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, - drw_h); + else if (IS_MSOC(pSmi)) { + if (pSmi->CSCVideo) + SMI_DisplayVideo0501_CSC(pScrn, id, offset, width, height, dstPitch, + x1, y1, x2, y2, &dstBox, + src_w, src_h, drw_w, drw_h, clipBoxes); + else + SMI_DisplayVideo0501(pScrn, id, offset, width, height, dstPitch, + x1, y1, x2, y2, &dstBox, src_w, src_h, + drw_w, drw_h); + } else{ if(!pSmi->Dualhead || crtc == crtcConf->crtc[1]) SMI_DisplayVideo(pScrn, id, offset, width, height, dstPitch, x1, y1, x2, y2, @@ -1779,6 +1817,176 @@ SMI_DisplayVideo( } static void +SMI_CSC_Start(SMIPtr pSmi, CARD32 CSC_Control) +{ + CARD32 CSC_Control_Old; + + while (1) { + CSC_Control_Old = READ_DPR(pSmi, 0xFC); + if (CSC_Control_Old & 0x80000000) + continue; + else { + CSC_Control |= 1 << 31; + WRITE_DPR(pSmi, 0xFC, CSC_Control); + break; + } + } + /* CSC stop */ + while (1) { + CSC_Control_Old = READ_DPR(pSmi, 0xFC); + if (!(CSC_Control_Old & 0x80000000)) + break; + } +} + +static void +SMI_DisplayVideo0501_CSC(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, + RegionPtr clipboxes) +{ + CARD32 ScaleXn, ScaleXd, ScaleYn, ScaleYd; + CARD32 SrcTn, SrcTd, SrcLn, SrcLd; + CARD32 SrcRn, SrcRd, SrcBn, SrcBd; + CARD32 SrcDimX, SrcDimY, DestDimX, DestDimY; + CARD32 SrcFormat, DstFormat, HFilter, VFilter, byOrder; + CARD32 SrcYBase, SrcUBase, SrcVBase, SrcYPitch, SrcUVPitch; + CARD32 DestPitch, DestHeight, DestWidth, DestBpp; + CARD32 SrcBpp = 0, SrcLnAdd = 0; + SMIPtr pSmi = SMIPTR(pScrn); + BoxPtr pbox = REGION_RECTS(clipboxes); + int i, nbox = REGION_NUM_RECTS(clipboxes); + xRectangle rect; + CARD32 CSC_Control; + + ENTER(); + + if (!pScrn->vtSema) + return; + + SrcYBase = offset; + SrcYPitch = pitch; + + DestPitch = (pScrn->displayWidth * pSmi->Bpp + 15) & ~15; + DestBpp = pSmi->Bpp; + + byOrder = 0; + + ScaleXn = (vid_w - 1) / (drw_w - 1); + ScaleXd = ((vid_w - 1) << 13) / (drw_w - 1) - (ScaleXn << 13); + + ScaleYn = (vid_h - 1) / (drw_h - 1); + ScaleYd = ((vid_h - 1) << 13) / (drw_h - 1) - (ScaleYn << 13); + + for (i = 0; i < nbox; i++, pbox++) { + rect.x = pbox->x1; + rect.y = pbox->y1; + rect.width = pbox->x2 - pbox->x1; + rect.height = pbox->y2 - pbox->y1; + + DestHeight = rect.height; + DestWidth = rect.width; + + switch (id) { + case FOURCC_YV12: + SrcFormat = 2; + byOrder = 0; + SrcLnAdd = 0; + + SrcYPitch = pitch; + SrcUVPitch = SrcYPitch / 2; + + SrcVBase = SrcYBase + SrcYPitch * height; + SrcUBase = SrcVBase + SrcUVPitch * height / 2; + break; + + case FOURCC_I420: + SrcFormat = 2; + byOrder = 0; + SrcLnAdd = 0; + + SrcYPitch = pitch; + SrcUVPitch = SrcYPitch / 2; + + SrcUBase = SrcYBase + SrcYPitch * height; + SrcVBase = SrcUBase + SrcUVPitch * height / 2; + break; + + case FOURCC_YUY2: + case FOURCC_RV16: + case FOURCC_RV32: + SrcUBase = SrcVBase = SrcYBase; + SrcUVPitch = SrcYPitch; + SrcFormat = 0; + byOrder = 0; + SrcBpp = 16 / 8; + SrcLnAdd = 0; + break; + } + + switch (DestBpp) { + case 2: + DstFormat = 0; + break; + case 4: + DstFormat = 1; + break; + default: + return; + } + + HFilter = 1; + VFilter = 1; + + SrcLn = (rect.x - dstBox->x1) * (vid_w - 1) / (drw_w - 1); + SrcLd = ((rect.x - dstBox->x1) << 13) * 1.0 * + (vid_w - 1) / (drw_w - 1) - (SrcLn << 13); + + SrcRn = (rect.x + rect.width - dstBox->x1) * + (vid_w - 1) / (drw_w-1); + SrcRd = ((rect.x + rect.width - dstBox->x1) << 13) * 1.0 * + (vid_w - 1) / (drw_w - 1) - (SrcRn << 13); + + SrcTn = (rect.y - dstBox->y1) * (vid_h - 1) / (drw_h - 1); + SrcTd = ((rect.y - dstBox->y1) << 13) * 1.0 * + (vid_h-1) / (drw_h - 1) - (SrcTn << 13); + + SrcBn = (rect.y + rect.height - dstBox->y1) * + (vid_h - 1) / (drw_h - 1); + SrcBd = ((rect.y + rect.height - dstBox->y1) << 13) * 1.0 * + (vid_h - 1) / (drw_h - 1) - (SrcBn << 13); + + SrcDimX = (SrcRd == 0) ? (SrcRn - SrcLn + 1) : (SrcRn - SrcLn + 2); + SrcDimY = (SrcBd == 0) ? (SrcBn - SrcTn + 1) : (SrcBn - SrcTn + 2); + + DestDimX = rect.width; + DestDimY = rect.height; + + WRITE_DPR(pSmi, 0xCC, 0x0); + WRITE_DPR(pSmi, 0xD0, (SrcLn + SrcLnAdd << 16) | SrcLd); + WRITE_DPR(pSmi, 0xD4, SrcTn << 16 | SrcTd); + WRITE_DPR(pSmi, 0xE0, SrcDimX << 16 | SrcDimY); + WRITE_DPR(pSmi, 0xE4, (SrcYPitch >> 4) << 16 | (SrcUVPitch >> 4)); + WRITE_DPR(pSmi, 0xE8, (rect.x) << 16 | rect.y); + WRITE_DPR(pSmi, 0xEC, DestDimX << 16 | DestDimY); + WRITE_DPR(pSmi, 0xF0, (DestPitch >> 4) << 16 | DestHeight); + WRITE_DPR(pSmi, 0xF4, (ScaleXn << 13 | ScaleXd) << 16 | + (ScaleYn << 13 | ScaleYd)); + WRITE_DPR(pSmi, 0xC8, SrcYBase); + WRITE_DPR(pSmi, 0xD8, SrcUBase); + WRITE_DPR(pSmi, 0xDC, SrcVBase); + WRITE_DPR(pSmi, 0xF8, 0); + + CSC_Control = (1 << 31 | SrcFormat << 28 | DstFormat << 26 | + HFilter << 25 | VFilter << 24 | byOrder << 23); + SMI_CSC_Start(pSmi, CSC_Control); + } + + LEAVE(); +} + +static void SMI_DisplayVideo0501(ScrnInfoPtr pScrn, int id, int offset, @@ -2164,6 +2372,66 @@ SMI_FreeMemory( LEAVE(); } +static void +CopyYV12ToVideoMem(unsigned char *src1, unsigned char *src2, + unsigned char *src3, unsigned char *dst, + int src1Pitch, int src23Pitch, int dstPitch, + int height, int width) +{ + int j = height; + + ENTER(); + + /* copy 1 data */ + while (j -- > 0) { + memcpy(dst, src1, width); + src1 += src1Pitch; + dst += dstPitch; + } + /* copy 2 data */ + j = height / 2; + while (j -- > 0) { + memcpy(dst, src2, width / 2); + src2 += src23Pitch; + dst += dstPitch / 2; + } + /* copy 3 data */ + j = height / 2; + while (j -- > 0) { + memcpy(dst, src3, width / 2); + src3 += src23Pitch; + dst += dstPitch / 2; + } + + LEAVE(); +} + +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(); + + 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(); +} + static int SMI_AllocSurface( ScrnInfoPtr pScrn, |