diff options
Diffstat (limited to 'src/apm_video.c')
-rw-r--r-- | src/apm_video.c | 986 |
1 files changed, 986 insertions, 0 deletions
diff --git a/src/apm_video.c b/src/apm_video.c new file mode 100644 index 0000000..4f57808 --- /dev/null +++ b/src/apm_video.c @@ -0,0 +1,986 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm_video.c,v 1.9 2001/06/15 21:22:45 dawes Exp $ */ + +#if PSZ != 24 +#include "dixstruct.h" + +/* + * Ported from mga_video.c by Loïc Grenié + */ + +#ifndef XvExtension +void A(InitVideo)(ScreenPtr pScreen) {} +void A(ResetVideo)(ScrnInfoPtr pScrn) {} +#else + +#ifndef OFF_DELAY +#define OFF_DELAY 200 +#endif + +static XF86VideoAdaptorPtr A(SetupImageVideo)(ScreenPtr); + +static void A(StopVideo)(ScrnInfoPtr, pointer, Bool); +static int A(SetPortAttribute)(ScrnInfoPtr, Atom, INT32, pointer); +#ifndef IOP_ACCESS +static int ApmGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); +static void ApmQueryBestSize(ScrnInfoPtr, Bool, short, short, short, + short, unsigned int *, unsigned int *, + pointer); +static int ApmQueryImageAttributes(ScrnInfoPtr, int, + unsigned short *, unsigned short *, + int *, int *); +#endif +static int A(ReputImage)(ScrnInfoPtr, short, short, RegionPtr, pointer); +static int A(PutImage)(ScrnInfoPtr, short, short, short, short, short, + short, short, short, int, unsigned char*, + short, short, Bool, RegionPtr, pointer); + +static void A(ResetVideo)(ScrnInfoPtr); +static void A(XvMoveCB)(FBAreaPtr, FBAreaPtr); +static void A(XvRemoveCB)(FBAreaPtr); + +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +void A(InitVideo)(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XF86VideoAdaptorPtr *adaptors, *newAdaptors; + XF86VideoAdaptorPtr newAdaptor; + APMDECL(pScrn); + int num_adaptors; + Bool freeAdaptors = FALSE; + + num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); + + if (pApm->Chipset >= AT24) { + if ((newAdaptor = A(SetupImageVideo)(pScreen))) { + + newAdaptors = xalloc((num_adaptors + 1) * + sizeof(XF86VideoAdaptorPtr*)); + if(newAdaptors) { + if(num_adaptors) + memcpy(newAdaptors, adaptors, num_adaptors * + sizeof(XF86VideoAdaptorPtr)); + newAdaptors[num_adaptors] = newAdaptor; + adaptors = newAdaptors; + num_adaptors++; + freeAdaptors = TRUE; + } + } + } + + if(num_adaptors) + xf86XVScreenInit(pScreen, adaptors, num_adaptors); + + if(freeAdaptors) + xfree(adaptors); +} + +#ifndef APM_VIDEO_DEFINES +#define APM_VIDEO_DEFINES + +static Atom xvBrightness, xvContrast; + +/* client libraries expect an encoding */ +static XF86VideoEncodingRec DummyEncoding[1] = +{ + { + 0, + "XV_IMAGE", + 1024, 1024, + {1, 1} + } +}; + +#define NUM_FORMATS 24 + +static XF86VideoFormatRec Formats[NUM_FORMATS] = +{ + { 8, PseudoColor}, + {15, PseudoColor}, + {16, PseudoColor}, + {24, PseudoColor}, + {32, PseudoColor}, + { 8, DirectColor}, + {15, DirectColor}, + {16, DirectColor}, + {24, DirectColor}, + {32, DirectColor}, + { 8, TrueColor}, + {15, TrueColor}, + {16, TrueColor}, + {24, TrueColor}, + {32, TrueColor} +}; + +#define NUM_ATTRIBUTES 2 + +static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = +{ + {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, + {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"} +}; + +#define NUM_IMAGES 8 +typedef char c8; + +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, 0x001F, 0x03E0, 0x7C00, + 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, 0x001F, 0x07E0, 0xF800, + 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 + }, + { + 0x32335652, + XvRGB, + LSBFirst, + {'R','V','3','2', + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + 32, + XvPacked, + 1, + 24, 0x0000FF, 0x00FF00, 0xFF0000, + 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 + }, + { + 0x59595959, + XvYUV, + LSBFirst, + {0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + 8, + XvPacked, + 1, + 0, 0, 0, 0, + 8, 0, 0, + 1, 1, 1, + 1, 1, 1, + {'Y','Y','Y','Y', + 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 + }, + { + 0x32315659, + XvYUV, + LSBFirst, + {'Y','V','1','2', + 0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71}, + 12, + XvPlanar, + 3, + 0, 0, 0, 0 , + 8, 8, 8, + 1, 2, 2, + 1, 2, 2, + {'Y','V','U', + 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 + }, + { + 0x59565955, + XvYUV, + LSBFirst, + {'U','Y','V','Y', + 0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71}, + 16, + XvPlanar, + 1, + 0, 0, 0, 0, + 8, 8, 8, + 1, 2, 2, + 1, 1, 1, + {'U','Y','V','Y', + 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 + }, + { + 0x55595659, + XvYUV, + LSBFirst, + {'Y','V','Y','U', + 0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71}, + 16, + XvPlanar, + 1, + 0, 0, 0, 0, + 8, 8, 8, + 1, 2, 2, + 1, 1, 1, + {'Y','V','Y','U', + 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 + }, + { + 0x59555956, + XvYUV, + LSBFirst, + {'V','Y','U','Y', + 0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71}, + 16, + XvPlanar, + 1, + 0, 0, 0, 0, + 8, 8, 8, + 1, 2, 2, + 1, 1, 1, + {'V','Y','U','Y', + 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 + } +}; + +typedef struct { + Bool on; + unsigned char brightness; + unsigned char contrast; + unsigned short reg, val; + ApmPtr pApm; + int x1, x10, y1, drw_x, drw_y, Bpp, Bps; + FBAreaPtr area; + RegionRec clip; + int xnum, xden, ynum, yden; + CARD32 scalex, scaley; + CARD32 data; +} ApmPortPrivRec, *ApmPortPrivPtr; +#endif + + +static void +A(ResetVideo)(ScrnInfoPtr pScrn) +{ + APMDECL(pScrn); + + A(WaitForFifo)(pApm, 2); + ((ApmPortPrivPtr)pApm->adaptor->pPortPrivates[0].ptr)->on = 0; + ((ApmPortPrivPtr)pApm->adaptor->pPortPrivates[1].ptr)->on = 0; + WRXW(0x82, 0); + WRXW(0x92, 0); +} + + +static XF86VideoAdaptorPtr +A(SetupImageVideo)(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + APMDECL(pScrn); + XF86VideoAdaptorPtr adapt; + ApmPortPrivPtr pPriv; + + if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + + 2 * sizeof(ApmPortPrivRec) + + 2 * sizeof(DevUnion)))) + return NULL; + + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = VIDEO_OVERLAID_IMAGES; + adapt->name = "Alliance Pro Motion video engine"; + adapt->nEncodings = 1; + adapt->pEncodings = DummyEncoding; + adapt->nFormats = NUM_FORMATS; + adapt->pFormats = Formats; + adapt->nPorts = 2; + adapt->pPortPrivates = (DevUnion*)(&adapt[1]); + pPriv = (ApmPortPrivPtr)(&adapt->pPortPrivates[2]); + pPriv->pApm = pApm; + pPriv[1].pApm = pApm; + pPriv->reg = 0x82; + pPriv[1].reg = 0x92; + adapt->pPortPrivates[0].ptr = (pointer)(pPriv); + adapt->pPortPrivates[1].ptr = (pointer)(pPriv + 1); + adapt->nAttributes = NUM_ATTRIBUTES; + adapt->pAttributes = Attributes; + adapt->nImages = NUM_IMAGES; + adapt->pImages = Images; + adapt->PutVideo = NULL; + adapt->PutStill = NULL; + adapt->GetVideo = NULL; + adapt->GetStill = NULL; + adapt->StopVideo = A(StopVideo); + adapt->SetPortAttribute = A(SetPortAttribute); + adapt->GetPortAttribute = ApmGetPortAttribute; + adapt->QueryBestSize = ApmQueryBestSize; + adapt->PutImage = A(PutImage); + adapt->ReputImage = A(ReputImage); + adapt->QueryImageAttributes = ApmQueryImageAttributes; + + pPriv->brightness = 0; + pPriv->contrast = 128; + pPriv[1].brightness = 0; + pPriv[1].contrast = 128; + + /* gotta uninit this someplace */ + REGION_INIT(pScreen, &pPriv->clip, NullBox, 0); + REGION_INIT(pScreen, &(pPriv + 1)->clip, NullBox, 0); + + pApm->adaptor = adapt; + + xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); + xvContrast = MAKE_ATOM("XV_CONTRAST"); + + A(ResetVideo)(pScrn); + + return adapt; +} + +#ifndef IOP_ACCESS +/* ApmClipVideo - + + 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. + + extents is the extents of the clip region +*/ + +static void +ApmClipVideo(BoxPtr dst, INT32 *x1, INT32 *x2, INT32 *y1, INT32 *y2, + BoxPtr extents, INT32 width, INT32 height, + CARD32 *scalex, CARD32 *scaley, INT32 mask) +{ + INT32 vscale, hscale; + int diff; + + if (dst->x2 - dst->x1 < *x2 - *x1) + dst->x2 = dst->x1 + *x2 - *x1; + + if (dst->y2 - dst->y1 < *y2 - *y1) + dst->y2 = dst->y1 + *y2 - *y1; + + *x1 <<= 12; *x2 <<= 16; + *y1 <<= 12; *y2 <<= 16; + + hscale = (*x2 - *x1) / (dst->x2 - dst->x1); + vscale = (*y2 - *y1) / (dst->y2 - dst->y1); + + 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 (*x2 - *x1 == 0x10000 * (dst->x2 - dst->x1)) /* Shrinking */ + *scalex = 0; + else + *scalex = ((*x2 - *x1) / (dst->x2 - dst->x1)) >> 4; + if (*y2 - *y1 == 0x10000 * (dst->y2 - dst->y1)) /* Shrinking */ + *scaley = 0; + else + *scaley = ((*y2 - *y1) / (dst->y2 - dst->y1)) >> 4; +} +#endif + +static void +A(StopVideo)(ScrnInfoPtr pScrn, pointer data, Bool shutdown) +{ + ApmPortPrivPtr pPriv = (ApmPortPrivPtr)data; + APMDECL(pScrn); + + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); + + pPriv->on = 0; + A(WaitForFifo)(pApm, 1); + WRXB(pPriv->reg, 0); +} + +static int +A(SetPortAttribute)(ScrnInfoPtr pScrn, Atom attribute, INT32 value, + pointer data) +{ + ApmPortPrivPtr pPriv = (ApmPortPrivPtr)data; + /*APMDECL(pScrn);*/ + + if(attribute == xvBrightness) { + if((value < -128) || (value > 127)) + return BadValue; + pPriv->brightness = value; + /* TODO : enable */ + } else if(attribute == xvContrast) { + if((value < 0) || (value > 255)) + return BadValue; + pPriv->contrast = value; + /* TODO : enable */ + } + + return Success; +} + +#ifndef IOP_ACCESS +static int +ApmGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value, + pointer data) +{ + ApmPortPrivPtr pPriv = (ApmPortPrivPtr)data; + + if(attribute == xvBrightness) { + *value = pPriv->brightness; + } else + if(attribute == xvContrast) { + *value = pPriv->contrast; + } + + return Success; +} + +static void +ApmQueryBestSize(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) +{ + APMDECL(pScrn); + unsigned short round = ~pApm->CurrentLayout.mask32; + + *p_w = drw_w & round; + *p_h = drw_h & round; +} + +static void +ApmCopyData(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 +ApmCopyMungedData(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) | + (src2[i] << 8) | (src3[i] << 24); + } + dst += dstPitch; + src1 += srcPitch; + if(j & 1) { + src2 += srcPitch2; + src3 += srcPitch2; + } + } +} +#endif + +static void A(XvMoveCB)(FBAreaPtr area1, FBAreaPtr area2) +{ + ApmPortPrivPtr pPriv = (ApmPortPrivPtr)area1->devPrivate.ptr; + ApmPtr pApm = pPriv->pApm; + + pPriv->on = 0; + A(WaitForFifo)(pApm, 1); + WRXB(pPriv->reg, 0); /* Stop video for this port */ + pPriv->area = area2; +} + +static void A(XvRemoveCB)(FBAreaPtr area) +{ + ApmPortPrivPtr pPriv = (ApmPortPrivPtr)area->devPrivate.ptr; + ApmPtr pApm = pPriv->pApm; + + pPriv->on = 0; + A(WaitForFifo)(pApm, 1); + WRXB(pPriv->reg, 0); /* Stop video for this port */ + pPriv->area = NULL; +} + +static int +A(ReputImage)(ScrnInfoPtr pScrn, short drw_x, short drw_y, + RegionPtr clipBoxes, pointer pdata) +{ + APMDECL(pScrn); + ApmPortPrivPtr pPriv = pdata, pPriv0, pPriv1; + register int fx, fy; + CARD32 mask; + RegionRec Union; + RegionPtr reg0; + int nrects, CurrY, tile; + int X1, X2, Y1, y2, xmax, ymax; + BoxPtr rects; + Bool didit = 0; + + mask = pApm->CurrentLayout.mask32; + fx = pScrn->frameX0 & ~mask; + fy = pScrn->frameY0 + 1; + REGION_COPY(pScreen, &pPriv->clip, clipBoxes); + pPriv->x1 += drw_x - pPriv->drw_x; + pPriv->x10 = ((pPriv->x1 + mask) & ~mask) - fx; + pPriv->y1 += drw_y - pPriv->drw_y; + pPriv->drw_x = drw_x; + pPriv->drw_y = drw_y; + A(WaitForFifo)(pApm, 2); + WRXW(pPriv->reg + 0x06, 0xFFF - ((pPriv->scalex * pPriv->x10) & 0xFFF)); + WRXW(pPriv->reg + 0x0A, 0xFFF - ((pPriv->scaley * pPriv->y1) & 0xFFF)); + pPriv0 = (ApmPortPrivPtr)pApm->adaptor->pPortPrivates[0].ptr; + pPriv1 = (ApmPortPrivPtr)pApm->adaptor->pPortPrivates[1].ptr; + reg0 = &pPriv0->clip; + bzero(&Union, sizeof Union); + REGION_EMPTY(pScreen, &Union); + REGION_INIT(pScreen, &Union, NullBox, 0); + REGION_UNION(pScreen, &Union, reg0, &pPriv1->clip); + nrects = REGION_NUM_RECTS(&Union); + rects = REGION_RECTS(&Union); + tile = 0x200; + xmax = pScrn->frameX1 - pScrn->frameX0 + 1; + ymax = pScrn->frameY1 - pScrn->frameY0; + CurrY = -1; + goto BEGIN_LOOP_1; + do { + rects++; +BEGIN_LOOP_1: + X1 = ((rects->x1 + mask) & ~mask) - fx; + if (X1 < 0) + X1 = 0; + X2 = (rects->x2 & ~mask) - fx; + if (X2 > xmax) + X2 = xmax; + y2 = rects->y2 - fy; + } while ((X2 <= X1 || y2 < -1) && --nrects > 0); + Y1 = rects->y1 - fy; + + while (!(STATUS() & 0x800)); + while (STATUS() & 0x800); + while (nrects-- > 0) { + CARD32 reg, data; + int x1, x2, y1; + + x1 = X1; + x2 = X2; + y1 = Y1; + if (y1 < -1) y1 = -1; + if (y1 > ymax) + break; + didit = 1; + if (y1 > CurrY) { + A(WaitForFifo)(pApm, 3); + WRXL(tile + 0x00, 0xFFF0011); + WRXL(tile + 0x04, y1 << 16); + WRXL(tile + 0x08, 0); + tile += 16; + } + if (RECT_IN_REGION(pScreen, reg0, rects)) { + pPriv = pPriv0; + reg = (x1 << 16) | 1; + } + else { + pPriv = pPriv1; + reg = (x1 << 16) | 2; + } + CurrY = y2; + if (nrects <= 0) + goto BEGIN_LOOP_2; + do { + rects++; +BEGIN_LOOP_2: + X1 = ((rects->x1 + mask) & ~mask) - fx; + if (X1 < 0) + X1 = 0; + X2 = (rects->x2 & ~mask) - fx; + if (X2 > xmax) + X2 = xmax; + } while (X2 <= X1 && --nrects > 0); + Y1 = rects->y1 - fy; + y2 = rects->y2 - fy; + data = pPriv->data + (((x1 - pPriv->x10) + * pPriv->xden) / pPriv->xnum) * pPriv->Bpp + + (((y1 - pPriv->y1 + fy) * pPriv->yden) / pPriv->ynum) * pPriv->Bps; + A(WaitForFifo)(pApm, 4); + if (!nrects || tile == 0x2B0 || y1 < Y1) { + WRXL(tile , 0x10 | reg); + } + else { + WRXL(tile , reg); + } + WRXL(tile + 0x04, x2 | (CurrY << 16)); + WRXL(tile + 0x08, (((x2-x1)*pPriv->xden+pPriv->xnum-1) / pPriv->xnum) | + (data << 16)); + WRXB(tile + 0x0C, data >> 16); + tile += 16; + if (tile == 0x2C0) { + tile = 0x200; + break; + } + } + REGION_UNINIT(pScreen, &Union); + + if (didit) { + A(WaitForFifo)(pApm, 1); + WRXW(0x8E, tile - 0x200); + } + + if (didit ^ ((pPriv0->val | pPriv1->val) & 1)) { + if (didit) { + pPriv0->val |= 1; + pPriv1->val |= 1; + } + else { + pPriv0->val &= 0xFFFE; + pPriv1->val &= 0xFFFE; + } + if (pPriv0->on) { + A(WaitForFifo)(pApm, 1); + WRXW(0x82, pPriv0->val); + } + if (pPriv1->on) { + A(WaitForFifo)(pApm, 1); + WRXW(0x92, pPriv1->val); + } + } + + return Success; +} + +static int +A(PutImage)(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) +{ + ApmPortPrivPtr pPriv = (ApmPortPrivPtr)data; + ScreenPtr pScreen = pScrn->pScreen; + APMDECL(pScrn); + INT32 x1, x2, y1, y2; + unsigned char *dst_start; + int pitch, Bpp, new_h, offset = 0, offset2 = 0, offset3 = 0; + CARD32 mask; + FBAreaPtr area; + int srcPitch, dstPitch, srcPitch2 = 0; + int top, left, npixels, nlines; + BoxRec dstBox; + CARD32 scalex, scaley, scale; + CARD32 tmp; + Bool offscreen; + + offscreen = (buf < (unsigned char *)pApm->FbBase || + buf > (unsigned char *)pApm->FbBase + 0x400000); + + 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; + + mask = pApm->CurrentLayout.mask32; + + ApmClipVideo(&dstBox, &x1, &x2, &y1, &y2, + REGION_EXTENTS(pScreen, clipBoxes), width, height, + &scalex, &scaley, mask); + + pPriv->drw_x = drw_x; + pPriv->drw_y = drw_y; + pPriv->xnum = drw_w; + if (scalex) + pPriv->xden = src_w; + else + pPriv->xden = drw_w; /* If image is larger than window */ + pPriv->ynum = drw_h; + if (scaley) + pPriv->yden = src_h; + else + pPriv->yden = drw_h; + if((x1 - x2 >= 0xFFFF) || (y1 - y2 >= 0xFFFF)) + return Success; + + Bpp = pScrn->bitsPerPixel >> 3; + pitch = Bpp * pScrn->displayWidth; + + switch(id) { + case 0x32315659: + dstPitch = ((width << 1) + 3) & ~3; + srcPitch = (width + 3) & ~3; + offset2 = srcPitch * height; + srcPitch2 = ((width >> 1) + 3) & ~3; + offset = srcPitch2 * (height >> 1); + offset3 = offset + offset2; + new_h = (2 * offset2 + pitch - 1) / pitch; + break; + case 0x59595959: + srcPitch = width; + dstPitch = (srcPitch + 3) & ~3; + offset = dstPitch * height; + new_h = (offset + pitch - 1) / pitch; + break; + case 0x32335652: + srcPitch = (width << 2); + dstPitch = (srcPitch + 3) & ~3; + offset = dstPitch * height; + new_h = (offset + pitch - 1) / pitch; + break; + default: + if (pApm->PutImageStride) + srcPitch = pApm->PutImageStride; + else + srcPitch = (width << 1); + dstPitch = (srcPitch + 3) & ~3; + offset = dstPitch * height; + new_h = (offset + pitch - 1) / pitch; + break; + } + + area = pPriv->area; + + /* Allocate offscreen memory */ + if (offscreen && (!area || ((area->box.y2 - area->box.y1) < new_h))) { + Bool nukeMem = FALSE; + int max_w, max_h; + + xf86QueryLargestOffscreenArea(pScreen, &max_w, &max_h, 0, + FAVOR_WIDTH_THEN_AREA, PRIORITY_LOW); + if (max_w == pScrn->displayWidth && max_h >= new_h) { + area = xf86AllocateOffscreenArea(pScreen, + pScrn->displayWidth, new_h, + 4, A(XvMoveCB), A(XvRemoveCB), pPriv); + if (area) { + if (pPriv->area) + xf86FreeOffscreenArea(pPriv->area); + } + else + area = pPriv->area; /* Should not happen */ + } + if(!area) { + if(!(area = xf86AllocateOffscreenArea(pScreen, + pScrn->displayWidth, new_h, 4, + A(XvMoveCB), A(XvRemoveCB), pPriv))) + { + nukeMem = TRUE; + } + } else { + if(!xf86ResizeOffscreenArea(area, pScrn->displayWidth, new_h)) { + xf86FreeOffscreenArea(area); + pPriv->area = area = NULL; + nukeMem = TRUE; + } + } + if(nukeMem) { + xf86QueryLargestOffscreenArea(pScreen, &max_w, &max_h, 0, + FAVOR_WIDTH_THEN_AREA, PRIORITY_EXTREME); + + if((max_w < pScrn->displayWidth) || (max_h < new_h)) + return BadAlloc; + + xf86PurgeUnlockedOffscreenAreas(pScreen); + + area = xf86AllocateOffscreenArea(pScreen, + pScrn->displayWidth, new_h, 4, + A(XvMoveCB), A(XvRemoveCB), pPriv); + } + + pPriv->area = area; + } + + /* copy data */ + pPriv->x1 = dstBox.x1 /*drw_x*/; + pPriv->y1 = dstBox.y1 /*drw_y*/; + top = y1 >> 16; + left = (x1 >> 16) & ~1; + npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; + + switch(id) { + case 0x59595959: + pPriv->Bpp = 1; + break; + default: + pPriv->Bpp = 2; + left <<= 1; + break; + case 0x32335652: + pPriv->Bpp = 4; + left <<= 2; + break; + } + pPriv->Bps = pPriv->Bpp * pPriv->xden; + if (offscreen) { + offset = (area->box.y1 * pitch) + (top * dstPitch); + dst_start = ((unsigned char *)pApm->FbBase) + + (pPriv->data = offset + left); + switch(id) { + case 0x32315659: + top &= ~1; + tmp = ((top >> 1) * srcPitch2) + (left >> 2); + offset2 += tmp; + offset3 += tmp; + nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; + ApmCopyMungedData(buf + (top * srcPitch) + (left >> 1), + buf + offset2, buf + offset3, dst_start, + srcPitch, srcPitch2, dstPitch, nlines, npixels); + break; + default: + if (id == 0x32335652) + npixels <<= 1; + else if (id == 0x59595959) + npixels >>= 1; + buf += (top * srcPitch) + left; + nlines = ((y2 + 0xffff) >> 16) - top; + if (offscreen) + ApmCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels); + break; + } + } + else + pPriv->data = buf - (unsigned char *)pApm->FbBase; + pPriv->on = 1; + A(WaitForFifo)(pApm, 3); + WRXW(pPriv->reg + 0x02, dstPitch >> 2); + WRXW(pPriv->reg + 0x04, scalex); + WRXW(pPriv->reg + 0x08, scaley); + pPriv->scalex = scalex; + pPriv->scaley = scaley; + if (scalex && scaley) + scale = 0x0E00; + else if (scalex) + scale = 0x0600; + else if (scaley) + scale = 0x0A00; + else + scale = 0; + switch(id) { + case 0x59595959: + pPriv->val = 0x017B | scale; + break; + case 0x32335652: + pPriv->val = 0x002F | (scale & 0xF7FF);/*Smoothing filter doesn't work*/ + break; + case 0x36315652: + pPriv->val = 0x002B | (scale & 0xF7FF); + break; + case 0x35315652: + pPriv->val = 0x0029 | (scale & 0xF7FF); + break; + case 0x59555956: + pPriv->val = 0x013B | scale; + break; + case 0x55595659: + pPriv->val = 0x014B | scale; + break; + case 0x32315659: + case 0x59565955: + default: + pPriv->val = 0x016B | scale; + break; + } + + (void) A(ReputImage)(pScrn, drw_x, drw_y, clipBoxes, data); + + A(WaitForFifo)(pApm, 1); + WRXW(pPriv->reg, pPriv->val); + + return Success; +} + +#ifndef IOP_ACCESS +static int +ApmQueryImageAttributes(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 0x32315659: + *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; + case 0x59565955: + case 0x55595659: + case 0x59555956: + size = *w << 1; + goto common; + case 0x59595959: + default: + size = *w; +common: + if (pitches) + pitches[0] = size; + size *= *h; + break; + } + + return size; +} +#endif +#endif +#endif + |