diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:55 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:55 +0000 |
commit | 0a3d86ee8123b4ba2c54abbae6675b4bc010f428 (patch) | |
tree | 59f077b15f77e3ad91fda89bb238dc9eba92a61a /src/ct_video.c | |
parent | 607c7f48bd004450fda196cd1e8029210cfba0c2 (diff) |
Initial revisionXORG-STABLE
Diffstat (limited to 'src/ct_video.c')
-rw-r--r-- | src/ct_video.c | 1163 |
1 files changed, 1163 insertions, 0 deletions
diff --git a/src/ct_video.c b/src/ct_video.c new file mode 100644 index 0000000..f5a824e --- /dev/null +++ b/src/ct_video.c @@ -0,0 +1,1163 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/ct_video.c,v 1.12 2002/11/25 14:04:58 eich Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "xf86_ansic.h" +#include "compiler.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "xf86fbman.h" +#include "regionstr.h" + +#include "ct_driver.h" +#include "Xv.h" +#include "xaa.h" +#include "xaalocal.h" +#include "dixstruct.h" +#include "fourcc.h" + +#define OFF_DELAY 200 /* milliseconds */ +#define FREE_DELAY 60000 + +#define OFF_TIMER 0x01 +#define FREE_TIMER 0x02 +#define CLIENT_VIDEO_ON 0x04 + +#define TIMER_MASK (OFF_TIMER | FREE_TIMER) + +#ifndef XvExtension +void CHIPSInitVideo(ScreenPtr pScreen) {} +void CHIPSResetVideo(ScrnInfoPtr pScrn) {} +#else + +static XF86VideoAdaptorPtr CHIPSSetupImageVideo(ScreenPtr); +static void CHIPSInitOffscreenImages(ScreenPtr); +static void CHIPSStopVideo(ScrnInfoPtr, pointer, Bool); +static int CHIPSSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); +static int CHIPSGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); +static void CHIPSQueryBestSize(ScrnInfoPtr, Bool, + short, short, short, short, unsigned int *, unsigned int *, pointer); +static int CHIPSPutImage( ScrnInfoPtr, + short, short, short, short, short, short, short, short, + int, unsigned char*, short, short, Bool, RegionPtr, pointer); +static int CHIPSQueryImageAttributes(ScrnInfoPtr, + int, unsigned short *, unsigned short *, int *, int *); +static void CHIPSVideoTimerCallback(ScrnInfoPtr pScrn, Time time); + + +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +static Atom xvColorKey; + +void +CHIPSInitVideo(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; + XF86VideoAdaptorPtr newAdaptor = NULL; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + int num_adaptors; + + if (!(cPtr->Flags & ChipsOverlay8plus16) && + (cPtr->Flags & ChipsVideoSupport)) { + newAdaptor = CHIPSSetupImageVideo(pScreen); + CHIPSInitOffscreenImages(pScreen); + } + + num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); + + if(newAdaptor) { + if(!num_adaptors) { + num_adaptors = 1; + adaptors = &newAdaptor; + } else { + newAdaptors = /* need to free this someplace */ + xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); + if(newAdaptors) { + memcpy(newAdaptors, adaptors, num_adaptors * + sizeof(XF86VideoAdaptorPtr)); + newAdaptors[num_adaptors] = newAdaptor; + adaptors = newAdaptors; + num_adaptors++; + } + } + } + + if(num_adaptors) + xf86XVScreenInit(pScreen, adaptors, num_adaptors); + + if(newAdaptors) + xfree(newAdaptors); +} + +/* client libraries expect an encoding */ +static +XF86VideoEncodingRec DummyEncoding[1] = +{ + { + 0, + "XV_IMAGE", + 1024, 1024, + {1, 1} + } +}; + +#define NUM_FORMATS 4 + +static XF86VideoFormatRec Formats[NUM_FORMATS] = +{ + {8, PseudoColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor} +}; + +#define NUM_ATTRIBUTES 1 + +static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = +{ + {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"} +}; + +#define NUM_IMAGES 4 + +static XF86ImageRec Images[NUM_IMAGES] = +{ + { + 0x35315652, + XvRGB, + LSBFirst, + {'R','V','1','5', + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + 16, + XvPacked, + 1, + 15, 0x7C00, 0x03E0, 0x001F, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + {'R','V','B',0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + XvTopToBottom + }, + { + 0x36315652, + XvRGB, + LSBFirst, + {'R','V','1','6', + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + 16, + XvPacked, + 1, + 16, 0xF800, 0x07E0, 0x001F, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + {'R','V','B',0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + XvTopToBottom + }, + XVIMAGE_YV12, + XVIMAGE_YUY2 +}; + +typedef struct { + FBLinearPtr linear; + RegionRec clip; + CARD32 colorKey; + CARD32 videoStatus; + Time offTime; + Time freeTime; + Bool doubleBuffer; + Bool manualDoubleBuffer; + int currentBuffer; +} CHIPSPortPrivRec, *CHIPSPortPrivPtr; + + +#define GET_PORT_PRIVATE(pScrn) \ + (CHIPSPortPrivPtr)((CHIPSPTR(pScrn))->adaptor->pPortPrivates[0].ptr) + +void +CHIPSResetVideo(ScrnInfoPtr pScrn) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSPortPrivPtr pPriv = cPtr->adaptor->pPortPrivates[0].ptr; + unsigned char mr3c; + int red, green, blue; + + if (cPtr->Flags & ChipsAccelSupport) + CHIPSHiQVSync(pScrn); + + mr3c = cPtr->readMR(cPtr, 0x3C); + cPtr->writeMR(cPtr, 0x3C, (mr3c | 0x6)); + switch (pScrn->depth) { + case 8: + cPtr->writeMR(cPtr, 0x3D, 0x00); + cPtr->writeMR(cPtr, 0x3E, 0x00); + cPtr->writeMR(cPtr, 0x3F, (pPriv->colorKey & 0xFF)); + cPtr->writeMR(cPtr, 0x40, 0xFF); + cPtr->writeMR(cPtr, 0x41, 0xFF); + cPtr->writeMR(cPtr, 0x42, 0x00); + break; + default: + red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; + green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; + blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; + switch (pScrn->depth) { + case 15: + cPtr->writeMR(cPtr, 0x3D, (red << 3)); + cPtr->writeMR(cPtr, 0x3E, (green << 3)); + cPtr->writeMR(cPtr, 0x3F, (blue << 3)); + cPtr->writeMR(cPtr, 0x40, 0x07); + cPtr->writeMR(cPtr, 0x41, 0x07); + cPtr->writeMR(cPtr, 0x42, 0x07); + break; + case 16: + cPtr->writeMR(cPtr, 0x3D, (red << 3)); + cPtr->writeMR(cPtr, 0x3E, (green << 2)); + cPtr->writeMR(cPtr, 0x3F, (blue << 3)); + cPtr->writeMR(cPtr, 0x40, 0x07); + cPtr->writeMR(cPtr, 0x41, 0x03); + cPtr->writeMR(cPtr, 0x42, 0x07); + break; + case 24: + cPtr->writeMR(cPtr, 0x3D, red); + cPtr->writeMR(cPtr, 0x3E, green); + cPtr->writeMR(cPtr, 0x3F, blue); + cPtr->writeMR(cPtr, 0x40, 0x00); + cPtr->writeMR(cPtr, 0x41, 0x00); + cPtr->writeMR(cPtr, 0x42, 0x00); + break; + } + } +} + + +static XF86VideoAdaptorPtr +CHIPSSetupImageVideo(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + XF86VideoAdaptorPtr adapt; + CHIPSPortPrivPtr pPriv; + + if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + + sizeof(CHIPSPortPrivRec) + + sizeof(DevUnion)))) + return NULL; + + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + adapt->name = "Chips and Technologies Backend Scaler"; + adapt->nEncodings = 1; + adapt->pEncodings = DummyEncoding; + adapt->nFormats = NUM_FORMATS; + adapt->pFormats = Formats; + adapt->nPorts = 1; + adapt->pPortPrivates = (DevUnion*)(&adapt[1]); + pPriv = (CHIPSPortPrivPtr)(&adapt->pPortPrivates[1]); + adapt->pPortPrivates[0].ptr = (pointer)(pPriv); + adapt->pAttributes = Attributes; + adapt->nImages = NUM_IMAGES; + adapt->nAttributes = NUM_ATTRIBUTES; + adapt->pImages = Images; + adapt->PutVideo = NULL; + adapt->PutStill = NULL; + adapt->GetVideo = NULL; + adapt->GetStill = NULL; + adapt->StopVideo = CHIPSStopVideo; + adapt->SetPortAttribute = CHIPSSetPortAttribute; + adapt->GetPortAttribute = CHIPSGetPortAttribute; + adapt->QueryBestSize = CHIPSQueryBestSize; + adapt->PutImage = CHIPSPutImage; + adapt->QueryImageAttributes = CHIPSQueryImageAttributes; + + pPriv->colorKey = cPtr->videoKey; + pPriv->videoStatus = 0; + pPriv->doubleBuffer = TRUE; + pPriv->manualDoubleBuffer = FALSE; + pPriv->currentBuffer = 0; + + /* gotta uninit this someplace */ + REGION_INIT(pScreen, &pPriv->clip, NullBox, 0); + + cPtr->adaptor = adapt; + + xvColorKey = MAKE_ATOM("XV_COLORKEY"); + + CHIPSResetVideo(pScrn); + + return adapt; +} + + +static Bool +RegionsEqual(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; +} + + +/* CHIPSClipVideo - + + Takes the dst box in standard X BoxRec form (top and left + edges inclusive, bottom and right exclusive). The new dst + box is returned. The source boundaries are given (x1, y1 + inclusive, x2, y2 exclusive) and returned are the new source + boundaries in 16.16 fixed point. +*/ + +static Bool +CHIPSClipVideo( + BoxPtr dst, + INT32 *x1, + INT32 *x2, + INT32 *y1, + INT32 *y2, + RegionPtr reg, + INT32 width, + INT32 height +){ + INT32 vscale, hscale, delta; + BoxPtr extents = REGION_EXTENTS(DummyScreen, reg); + int diff; + + hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1); + vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1); + + *x1 <<= 16; *x2 <<= 16; + *y1 <<= 16; *y2 <<= 16; + + diff = extents->x1 - dst->x1; + if(diff > 0) { + dst->x1 = extents->x1; + *x1 += diff * hscale; + } + diff = dst->x2 - extents->x2; + if(diff > 0) { + dst->x2 = extents->x2; + *x2 -= diff * hscale; + } + diff = extents->y1 - dst->y1; + if(diff > 0) { + dst->y1 = extents->y1; + *y1 += diff * vscale; + } + diff = dst->y2 - extents->y2; + if(diff > 0) { + dst->y2 = extents->y2; + *y2 -= diff * vscale; + } + + if(*x1 < 0) { + diff = (- *x1 + hscale - 1)/ hscale; + dst->x1 += diff; + *x1 += diff * hscale; + } + delta = *x2 - (width << 16); + if(delta > 0) { + diff = (delta + hscale - 1)/ hscale; + dst->x2 -= diff; + *x2 -= diff * hscale; + } + if(*x1 >= *x2) return FALSE; + + if(*y1 < 0) { + diff = (- *y1 + vscale - 1)/ vscale; + dst->y1 += diff; + *y1 += diff * vscale; + } + delta = *y2 - (height << 16); + if(delta > 0) { + diff = (delta + vscale - 1)/ vscale; + dst->y2 -= diff; + *y2 -= diff * vscale; + } + if(*y1 >= *y2) return FALSE; + + if((dst->x1 != extents->x1) || (dst->x2 != extents->x2) || + (dst->y1 != extents->y1) || (dst->y2 != extents->y2)) + { + RegionRec clipReg; + REGION_INIT(DummyScreen, &clipReg, dst, 1); + REGION_INTERSECT(DummyScreen, reg, reg, &clipReg); + REGION_UNINIT(DummyScreen, &clipReg); + } + return TRUE; +} + +static void +CHIPSStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shadow) +{ + CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + unsigned char mr3c, tmp; + + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); + if (cPtr->Flags & ChipsAccelSupport) + CHIPSHiQVSync(pScrn); + if(shadow) { + if(pPriv->videoStatus & CLIENT_VIDEO_ON) { + mr3c = cPtr->readMR(cPtr, 0x3C); + cPtr->writeMR(cPtr, 0x3C, (mr3c & 0xFE)); + tmp = cPtr->readXR(cPtr, 0xD0); + cPtr->writeXR(cPtr, 0xD0, (tmp & 0xf)); + } + if(pPriv->linear) { + xf86FreeOffscreenLinear(pPriv->linear); + pPriv->linear = NULL; + } + pPriv->videoStatus = 0; + } else { + if(pPriv->videoStatus & CLIENT_VIDEO_ON) { + pPriv->videoStatus |= OFF_TIMER; + pPriv->offTime = currentTime.milliseconds + OFF_DELAY; + cPtr->VideoTimerCallback = CHIPSVideoTimerCallback; + } + } +} + +static int +CHIPSSetPortAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 value, + pointer data +){ + CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + if (cPtr->Flags & ChipsAccelSupport) + CHIPSHiQVSync(pScrn); + if(attribute == xvColorKey) { + int red, green, blue; + pPriv->colorKey = value; + switch (pScrn->depth) { + case 8: + cPtr->writeMR(cPtr, 0x3D, 0x00); + cPtr->writeMR(cPtr, 0x3E, 0x00); + cPtr->writeMR(cPtr, 0x3F, (pPriv->colorKey & 0xFF)); + break; + default: + red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; + green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; + blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; + switch (pScrn->depth) { + case 15: + cPtr->writeMR(cPtr, 0x3D, (red << 3)); + cPtr->writeMR(cPtr, 0x3E, (green << 3)); + cPtr->writeMR(cPtr, 0x3F, (blue << 3)); + break; + case 16: + cPtr->writeMR(cPtr, 0x3D, (red << 3)); + cPtr->writeMR(cPtr, 0x3E, (green << 2)); + cPtr->writeMR(cPtr, 0x3F, (blue << 3)); + break; + case 24: + cPtr->writeMR(cPtr, 0x3D, red); + cPtr->writeMR(cPtr, 0x3E, green); + cPtr->writeMR(cPtr, 0x3F, blue); + break; + } + } + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); + } else return BadMatch; + + return Success; +} + +static int +CHIPSGetPortAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 *value, + pointer data +){ + CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data; + + if(attribute == xvColorKey) { + *value = pPriv->colorKey; + } else return BadMatch; + + return Success; +} + +static void +CHIPSQueryBestSize( + 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 > 16384) *p_w = 16384; +} + + +static void +CHIPSCopyData( + unsigned char *src, + unsigned char *dst, + int srcPitch, + int dstPitch, + int h, + int w +){ + w <<= 1; + while(h--) { + memcpy(dst, src, w); + src += srcPitch; + dst += dstPitch; + } +} + +static void +CHIPSCopyMungedData( + unsigned char *src1, + unsigned char *src2, + unsigned char *src3, + unsigned char *dst1, + int srcPitch, + int srcPitch2, + int dstPitch, + int h, + int w +){ + CARD32 *dst = (CARD32*)dst1; + int i, j; + + dstPitch >>= 2; + w >>= 1; + + for(j = 0; j < h; j++) { + for(i = 0; i < w; i++) { + dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) | + (src3[i] << 8) | (src2[i] << 24); + } + dst += dstPitch; + src1 += srcPitch; + if(j & 1) { + src2 += srcPitch2; + src3 += srcPitch2; + } + } +} + +static FBLinearPtr +CHIPSAllocateMemory( + ScrnInfoPtr pScrn, + FBLinearPtr linear, + int size +){ + ScreenPtr pScreen; + FBLinearPtr new_linear; + + if(linear) { + if(linear->size >= size) + return linear; + + if(xf86ResizeOffscreenLinear(linear, size)) + return linear; + + xf86FreeOffscreenLinear(linear); + } + + pScreen = screenInfo.screens[pScrn->scrnIndex]; + + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, + NULL, NULL, NULL); + + if(!new_linear) { + int max_size; + + xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, + PRIORITY_EXTREME); + + if(max_size < size) + return NULL; + + xf86PurgeUnlockedOffscreenAreas(pScreen); + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, + NULL, NULL, NULL); + } + + return new_linear; +} + +static int +CHIPSSetCurrentPlaybackBuffer(CHIPSPtr cPtr, int n) +{ + + CARD8 mr20; + mr20 = cPtr->readMR(cPtr, 0x20); + mr20 &= ~0x1B; + if (!n) mr20 |= 0x10; + cPtr->writeMR(cPtr, 0x22, mr20); + return n; +} + +static int +CHIPSWaitGetNextFrame(CHIPSPtr cPtr) +{ + volatile CARD8 mr20; + volatile CARD8 mr21; + + mr20 = cPtr->readMR(cPtr, 0x20); + while (1) { + mr21 = cPtr->readMR(cPtr, 0x21); + if (!(mr20 & (1 << 5)) || !(mr21 & 1)) + break; + } + mr20 &= ~0x4; + mr20 = cPtr->readMR(cPtr, 0x20); + return (mr21 & 2)? 0 : 1; +} + +static void +CHIPSDisplayVideo( + ScrnInfoPtr pScrn, + int id, + int offset, + short width, short height, + int pitch, + int x1, int y1, int x2, int y2, + BoxPtr dstBox, + short src_w, short src_h, + short drw_w, short drw_h, + Bool triggerBufSwitch +){ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); + DisplayModePtr mode = pScrn->currentMode; + unsigned char tmp, m1f, m1e; + int buffer = pPriv->currentBuffer; + + if (cPtr->Flags & ChipsAccelSupport) + CHIPSHiQVSync(pScrn); + + tmp = cPtr->readXR(cPtr, 0xD0); + cPtr->writeXR(cPtr, 0xD0, (tmp | 0x10)); + + m1e = cPtr->readMR(cPtr, 0x1E); + m1e &= 0xE0; /* Set Zoom and Direction */ + if ((!(cPtr->PanelType & ChipsLCD)) && (mode->Flags & V_INTERLACE)) + m1e |= 0x10; + + m1f = cPtr->readMR(cPtr, 0x1F); + m1f = (m1f & 0x14); /* Mask reserved bits, unset interpolation */ + switch(id) { + case 0x35315652: /* RGB15 */ + m1f |= 0x09; + break; + case 0x36315652: /* RGB16 */ + m1f |= 0x08; + break; + case FOURCC_YV12: /* YV12 */ + /* m1f |= 0x03 */ + m1f |= 0x00; + break; + case FOURCC_YUY2: /* YUY2 */ + default: + m1f |= 0x00; /* Do nothing here */ + break; + } + + offset += (x1 >> 15) & ~0x01; + /* Setup Pointer 1 */ + if (!buffer || pPriv->manualDoubleBuffer || !pPriv->doubleBuffer) { + cPtr->writeMR(cPtr, 0x22, (offset & 0xF8)); + cPtr->writeMR(cPtr, 0x23, ((offset >> 8) & 0xFF)); + cPtr->writeMR(cPtr, 0x24, ((offset >> 16) & 0xFF)); + } + /* Setup Pointer 2 */ + if ((buffer && !pPriv->manualDoubleBuffer) || !pPriv->doubleBuffer) { + cPtr->writeMR(cPtr, 0x25, (offset & 0xF8)); + cPtr->writeMR(cPtr, 0x26, ((offset >> 8) & 0xFF)); + cPtr->writeMR(cPtr, 0x27, ((offset >> 16) & 0xFF)); + } + + + tmp = cPtr->readMR(cPtr, 0x04); + if (pPriv->doubleBuffer && !pPriv->manualDoubleBuffer && triggerBufSwitch) + tmp |= 0x18; + cPtr->writeMR(cPtr, 0x04, tmp); + + tmp = cPtr->readMR(cPtr, 0x20); + tmp &= 0xC3; + if (pPriv->doubleBuffer && !pPriv->manualDoubleBuffer && triggerBufSwitch) + tmp |= ((1 << 2 | 1 << 5) | ((buffer) ? (1 << 4) : 0)); + cPtr->writeMR(cPtr, 0x20, tmp); + + cPtr->writeMR(cPtr, 0x28, ((width >> 2) - 1)); /* Width */ + cPtr->writeMR(cPtr, 0x34, ((width >> 2) - 1)); + + /* Left Edge of Overlay */ + cPtr->writeMR(cPtr, 0x2A, ((cPtr->OverlaySkewX + dstBox->x1) & 0xFF)); + tmp = cPtr->readMR(cPtr, 0x2B); + tmp = (tmp & 0xF8) + (((cPtr->OverlaySkewX + dstBox->x1) >> 8) & 0x07); + cPtr->writeMR(cPtr, 0x2B, tmp); + /* Right Edge of Overlay */ + cPtr->writeMR(cPtr, 0x2C, ((cPtr->OverlaySkewX + dstBox->x2 -1) + & 0xFF)); + tmp = cPtr->readMR(cPtr, 0x2D); + tmp = (tmp & 0xF8) + (((cPtr->OverlaySkewX + dstBox->x2 - 1) >> 8) & 0x07); + cPtr->writeMR(cPtr, 0x2D, tmp); + /* Top Edge of Overlay */ + cPtr->writeMR(cPtr, 0x2E, ((cPtr->OverlaySkewY + dstBox->y1) & 0xFF)); + tmp = cPtr->readMR(cPtr, 0x2F); + tmp = (tmp & 0xF8) + (((cPtr->OverlaySkewY + dstBox->y1) >> 8) & 0x07); + cPtr->writeMR(cPtr, 0x2F, tmp); + /* Bottom Edge of Overlay*/ + cPtr->writeMR(cPtr, 0x30, ((cPtr->OverlaySkewY + dstBox->y2 - 1) & 0xFF)); + tmp = cPtr->readMR(cPtr, 0x31); + tmp = (tmp & 0xF8) + (((cPtr->OverlaySkewY + dstBox->y2 - 1) >> 8) & 0x07); + cPtr->writeMR(cPtr, 0x31, tmp); + + /* Horizontal Zoom */ + if (drw_w > src_w) { + m1f = m1f | 0x20; /* set H-interpolation */ + m1e = m1e | 0x04; + tmp = cPtr->VideoZoomMax * src_w / drw_w; + cPtr->writeMR(cPtr, 0x32, tmp); + } + + /* Vertical Zoom */ + if (drw_h > src_h) { + m1f = m1f | 0x80; + m1e = m1e | 0x08; /* set V-interpolation */ + tmp = cPtr->VideoZoomMax * src_h / drw_h ; + cPtr->writeMR(cPtr, 0x33, tmp); + } + cPtr->writeMR(cPtr, 0x1F, m1f); + cPtr->writeMR(cPtr, 0x1E, m1e); + + tmp = cPtr->readMR(cPtr, 0x3C); + cPtr->writeMR(cPtr, 0x3C, (tmp | 0x7)); + if (cPtr->Flags & ChipsAccelSupport) + CHIPSHiQVSync(pScrn); +} + +static int +CHIPSPutImage( + ScrnInfoPtr pScrn, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + int id, unsigned char* buf, + short width, short height, + Bool sync, + RegionPtr clipBoxes, pointer data +){ + CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + INT32 x1, x2, y1, y2; + unsigned char *dst_start; + int pitch, new_size, offset, offset2 = 0, offset3 = 0; + int srcPitch, srcPitch2 = 0, dstPitch; + int top, left, npixels, nlines, bpp; + BoxRec dstBox; + CARD32 tmp; + + if(drw_w > 16384) drw_w = 16384; + + /* Clip */ + x1 = src_x; + x2 = src_x + src_w; + y1 = src_y; + y2 = src_y + src_h; + + dstBox.x1 = drw_x; + dstBox.x2 = drw_x + drw_w; + dstBox.y1 = drw_y; + dstBox.y2 = drw_y + drw_h; + + if (!CHIPSClipVideo(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height)) + return Success; + + dstBox.x1 -= pScrn->frameX0 & cPtr->viewportMask; + dstBox.x2 -= pScrn->frameX0 & cPtr->viewportMask; + dstBox.y1 -= pScrn->frameY0; + dstBox.y2 -= pScrn->frameY0; + + bpp = pScrn->bitsPerPixel >> 3; + pitch = bpp * pScrn->displayWidth; + + dstPitch = ((width << 1) + 15) & ~15; + new_size = ((dstPitch * height) + bpp - 1) / bpp; + if (pPriv->doubleBuffer) + new_size <<= 1; + + switch(id) { + case FOURCC_YV12: /* YV12 */ + srcPitch = (width + 3) & ~3; + offset2 = srcPitch * height; + srcPitch2 = ((width >> 1) + 3) & ~3; + offset3 = (srcPitch2 * (height >> 1)) + offset2; + break; + default: /* RGB15, RGB16, YUY2 */ + srcPitch = (width << 1); + break; + } + + if(!(pPriv->linear = CHIPSAllocateMemory(pScrn, pPriv->linear, new_size))) { + if (pPriv->doubleBuffer && + (pPriv->linear = CHIPSAllocateMemory(pScrn, pPriv->linear, + new_size >> 1))) { + new_size >>= 1; + pPriv->doubleBuffer = FALSE; + } else + return BadAlloc; + } + + /* copy data */ + top = y1 >> 16; + left = (x1 >> 16) & ~1; + npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; + left <<= 1; + + offset = pPriv->linear->offset * bpp; + if (!pPriv->manualDoubleBuffer) + pPriv->currentBuffer = CHIPSWaitGetNextFrame(cPtr); + if(pPriv->doubleBuffer && pPriv->currentBuffer) + offset += (new_size * bpp) >> 1; + + dst_start = cPtr->FbBase + offset + left + (top * dstPitch); + + switch(id) { + case FOURCC_YV12: /* YV12 */ + top &= ~1; + tmp = ((top >> 1) * srcPitch2) + (left >> 2); + offset2 += tmp; + offset3 += tmp; + nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; + CHIPSCopyMungedData(buf + (top * srcPitch) + (left >> 1), + buf + offset2, buf + offset3, dst_start, + srcPitch, srcPitch2, dstPitch, nlines, npixels); + break; + default: /* RGB15, RGB16, YUY2 */ + buf += (top * srcPitch) + left; + nlines = ((y2 + 0xffff) >> 16) - top; + CHIPSCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels); + break; + } + + /* update cliplist */ + if(!RegionsEqual(&pPriv->clip, clipBoxes)) { + REGION_COPY(pScreen, &pPriv->clip, clipBoxes); + xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); + } + + offset += top * dstPitch; + CHIPSDisplayVideo(pScrn, id, offset, width, height, dstPitch, + x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h, TRUE); + + pPriv->videoStatus = CLIENT_VIDEO_ON; + + if (pPriv->manualDoubleBuffer) + pPriv->currentBuffer ^= 1; + + return Success; +} + +static int +CHIPSQueryImageAttributes( + ScrnInfoPtr pScrn, + int id, + unsigned short *w, unsigned short *h, + int *pitches, int *offsets +){ + int size, tmp; + + if(*w > 1024) *w = 1024; + if(*h > 1024) *h = 1024; + + *w = (*w + 1) & ~1; + if(offsets) offsets[0] = 0; + + switch(id) { + case FOURCC_YV12: /* YV12 */ + *h = (*h + 1) & ~1; + size = (*w + 3) & ~3; + if(pitches) pitches[0] = size; + size *= *h; + if(offsets) offsets[1] = size; + tmp = ((*w >> 1) + 3) & ~3; + if(pitches) pitches[1] = pitches[2] = tmp; + tmp *= (*h >> 1); + size += tmp; + if(offsets) offsets[2] = size; + size += tmp; + break; + default: /* RGB15, RGB16, YUY2 */ + size = *w << 1; + if(pitches) pitches[0] = size; + size *= *h; + break; + } + + return size; +} + + +static void +CHIPSVideoTimerCallback(ScrnInfoPtr pScrn, Time time) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); + unsigned char mr3c; + + if(pPriv->videoStatus & TIMER_MASK) { + if(pPriv->videoStatus & OFF_TIMER) { + if(pPriv->offTime < time) { + if (cPtr->Flags & ChipsAccelSupport) + CHIPSHiQVSync(pScrn); + mr3c = cPtr->readMR(cPtr, 0x3C); + cPtr->writeMR(cPtr, 0x3C, (mr3c & 0xFE)); + pPriv->videoStatus = FREE_TIMER; + pPriv->freeTime = currentTime.milliseconds + FREE_DELAY; + } + } else { /* FREE_TIMER */ + if(pPriv->freeTime < time) { + if(pPriv->linear) { + xf86FreeOffscreenLinear(pPriv->linear); + pPriv->linear = NULL; + } + pPriv->videoStatus = 0; + cPtr->VideoTimerCallback = NULL; + } + } + } else /* shouldn't get here */ + cPtr->VideoTimerCallback = NULL; +} + + +/****************** Offscreen stuff ***************/ + +typedef struct { + FBLinearPtr linear; + Bool isOn; +} OffscreenPrivRec, * OffscreenPrivPtr; + +static int +CHIPSAllocateSurface( + ScrnInfoPtr pScrn, + int id, + unsigned short w, + unsigned short h, + XF86SurfacePtr surface +){ + FBLinearPtr linear; + int pitch, fbpitch, size, bpp; + OffscreenPrivPtr pPriv; + + if((w > 1024) || (h > 1024)) + return BadAlloc; + + w = (w + 1) & ~1; + pitch = ((w << 1) + 15) & ~15; + bpp = pScrn->bitsPerPixel >> 3; + fbpitch = bpp * pScrn->displayWidth; + size = ((pitch * h) + bpp - 1) / bpp; + + if(!(linear = CHIPSAllocateMemory(pScrn, NULL, size))) + return BadAlloc; + + surface->width = w; + surface->height = h; + + if(!(surface->pitches = xalloc(sizeof(int)))) { + xf86FreeOffscreenLinear(linear); + return BadAlloc; + } + if(!(surface->offsets = xalloc(sizeof(int)))) { + xfree(surface->pitches); + xf86FreeOffscreenLinear(linear); + return BadAlloc; + } + if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) { + xfree(surface->pitches); + xfree(surface->offsets); + xf86FreeOffscreenLinear(linear); + return BadAlloc; + } + + pPriv->linear = linear; + pPriv->isOn = FALSE; + + surface->pScrn = pScrn; + surface->id = id; + surface->pitches[0] = pitch; + surface->offsets[0] = linear->offset * bpp; + surface->devPrivate.ptr = (pointer)pPriv; + + return Success; +} + +static int +CHIPSStopSurface( + XF86SurfacePtr surface +){ + OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; + + if(pPriv->isOn) { + CHIPSPtr cPtr = CHIPSPTR(surface->pScrn); + unsigned char mr3c, tmp; + tmp = cPtr->readXR(cPtr, 0xD0); + cPtr->writeXR(cPtr, 0xD0, (tmp & 0xf)); + mr3c = cPtr->readMR(cPtr, 0x3C); + cPtr->writeMR(cPtr, 0x3C, (mr3c & 0xFE)); + pPriv->isOn = FALSE; + } + + return Success; +} + + +static int +CHIPSFreeSurface( + XF86SurfacePtr surface +){ + OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; + + if(pPriv->isOn) + CHIPSStopSurface(surface); + xf86FreeOffscreenLinear(pPriv->linear); + xfree(surface->pitches); + xfree(surface->offsets); + xfree(surface->devPrivate.ptr); + + return Success; +} + +static int +CHIPSGetSurfaceAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 *value +){ + return CHIPSGetPortAttribute(pScrn, attribute, value, + (pointer)(GET_PORT_PRIVATE(pScrn))); +} + +static int +CHIPSSetSurfaceAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 value +){ + return CHIPSSetPortAttribute(pScrn, attribute, value, + (pointer)(GET_PORT_PRIVATE(pScrn))); +} + + +static int +CHIPSDisplaySurface( + XF86SurfacePtr surface, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + RegionPtr clipBoxes +){ + OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; + ScrnInfoPtr pScrn = surface->pScrn; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSPortPrivPtr portPriv = GET_PORT_PRIVATE(pScrn); + INT32 x1, y1, x2, y2; + BoxRec dstBox; + + x1 = src_x; + x2 = src_x + src_w; + y1 = src_y; + y2 = src_y + src_h; + + dstBox.x1 = drw_x; + dstBox.x2 = drw_x + drw_w; + dstBox.y1 = drw_y; + dstBox.y2 = drw_y + drw_h; + + if(!CHIPSClipVideo(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, + surface->width, surface->height)) + return Success; + + dstBox.x1 -= pScrn->frameX0; + dstBox.x2 -= pScrn->frameX0; + dstBox.y1 -= pScrn->frameY0; + dstBox.y2 -= pScrn->frameY0; + + if (portPriv->doubleBuffer) + portPriv->currentBuffer = CHIPSSetCurrentPlaybackBuffer(cPtr,0); + else + portPriv->currentBuffer = 0; + + CHIPSDisplayVideo(pScrn, surface->id, surface->offsets[0], + surface->width, surface->height, surface->pitches[0], + x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h, FALSE); + xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes); + + pPriv->isOn = TRUE; + if(portPriv->videoStatus & CLIENT_VIDEO_ON) { + REGION_EMPTY(pScrn->pScreen, &portPriv->clip); + UpdateCurrentTime(); + portPriv->videoStatus = FREE_TIMER; + portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; + cPtr->VideoTimerCallback = CHIPSVideoTimerCallback; + } + + return Success; +} + + +static void +CHIPSInitOffscreenImages(ScreenPtr pScreen) +{ + XF86OffscreenImagePtr offscreenImages; + + /* need to free this someplace */ + if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) + return; + + offscreenImages[0].image = &Images[0]; + offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | + VIDEO_CLIP_TO_VIEWPORT; + offscreenImages[0].alloc_surface = CHIPSAllocateSurface; + offscreenImages[0].free_surface = CHIPSFreeSurface; + offscreenImages[0].display = CHIPSDisplaySurface; + offscreenImages[0].stop = CHIPSStopSurface; + offscreenImages[0].setAttribute = CHIPSSetSurfaceAttribute; + offscreenImages[0].getAttribute = CHIPSGetSurfaceAttribute; + offscreenImages[0].max_width = 1024; + offscreenImages[0].max_height = 1024; + offscreenImages[0].num_attributes = NUM_ATTRIBUTES; + offscreenImages[0].attributes = Attributes; + + xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); +} + +#endif /* !XvExtension */ |