117a48c7cSmrg
217a48c7cSmrg#ifdef HAVE_CONFIG_H
317a48c7cSmrg#include "config.h"
417a48c7cSmrg#endif
517a48c7cSmrg
617a48c7cSmrg#if PSZ != 24
717a48c7cSmrg#include "dixstruct.h"
817a48c7cSmrg#include "fourcc.h"
917a48c7cSmrg
1017a48c7cSmrg/*
1117a48c7cSmrg * Ported from mga_video.c by Loïc Grenié
1217a48c7cSmrg */
1317a48c7cSmrg
1417a48c7cSmrg#ifndef OFF_DELAY
1517a48c7cSmrg#define OFF_DELAY	200
1617a48c7cSmrg#endif
1717a48c7cSmrg
1817a48c7cSmrgstatic XF86VideoAdaptorPtr A(SetupImageVideo)(ScreenPtr);
1917a48c7cSmrg
2017a48c7cSmrgstatic void	A(StopVideo)(ScrnInfoPtr, pointer, Bool);
2117a48c7cSmrgstatic int	A(SetPortAttribute)(ScrnInfoPtr, Atom, INT32, pointer);
2217a48c7cSmrgstatic int	ApmGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
2317a48c7cSmrgstatic void	ApmQueryBestSize(ScrnInfoPtr, Bool, short, short, short,
2417a48c7cSmrg				    short, unsigned int *, unsigned int *,
2517a48c7cSmrg				    pointer);
2617a48c7cSmrgstatic int	ApmQueryImageAttributes(ScrnInfoPtr, int,
2717a48c7cSmrg					    unsigned short *, unsigned short *,
2817a48c7cSmrg					    int *, int *);
295c69f917Smrg#ifndef XV_NEW_REPUT
3017a48c7cSmrgstatic int	A(ReputImage)(ScrnInfoPtr, short, short, RegionPtr, pointer,
3117a48c7cSmrg				DrawablePtr);
325c69f917Smrg#endif
3317a48c7cSmrgstatic int	A(PutImage)(ScrnInfoPtr, short, short, short, short, short,
3417a48c7cSmrg				short, short, short, int, unsigned char*,
3517a48c7cSmrg				short, short, Bool, RegionPtr, pointer,
3617a48c7cSmrg				DrawablePtr);
3717a48c7cSmrg
3817a48c7cSmrgstatic void	A(ResetVideo)(ScrnInfoPtr);
3917a48c7cSmrgstatic void	A(XvMoveCB)(FBAreaPtr, FBAreaPtr);
4017a48c7cSmrgstatic void	A(XvRemoveCB)(FBAreaPtr);
4117a48c7cSmrg
4217a48c7cSmrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
4317a48c7cSmrg
4417a48c7cSmrgvoid A(InitVideo)(ScreenPtr pScreen)
4517a48c7cSmrg{
465c69f917Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
4717a48c7cSmrg    XF86VideoAdaptorPtr *adaptors, *newAdaptors;
4817a48c7cSmrg    XF86VideoAdaptorPtr newAdaptor;
4917a48c7cSmrg    APMDECL(pScrn);
5017a48c7cSmrg    int num_adaptors;
5117a48c7cSmrg    Bool freeAdaptors = FALSE;
5217a48c7cSmrg
5317a48c7cSmrg    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
5417a48c7cSmrg
5517a48c7cSmrg    if (pApm->Chipset >= AT24) {
5617a48c7cSmrg	if ((newAdaptor = A(SetupImageVideo)(pScreen))) {
5717a48c7cSmrg
585c69f917Smrg	   newAdaptors = malloc((num_adaptors + 1) *
5917a48c7cSmrg				   sizeof(XF86VideoAdaptorPtr*));
6017a48c7cSmrg	   if(newAdaptors) {
6117a48c7cSmrg		if(num_adaptors)
6217a48c7cSmrg		    memcpy(newAdaptors, adaptors, num_adaptors *
6317a48c7cSmrg					sizeof(XF86VideoAdaptorPtr));
6417a48c7cSmrg		newAdaptors[num_adaptors] = newAdaptor;
6517a48c7cSmrg		adaptors = newAdaptors;
6617a48c7cSmrg		num_adaptors++;
6717a48c7cSmrg		freeAdaptors = TRUE;
6817a48c7cSmrg	   }
6917a48c7cSmrg	}
7017a48c7cSmrg    }
7117a48c7cSmrg
7217a48c7cSmrg    if(num_adaptors)
7317a48c7cSmrg        xf86XVScreenInit(pScreen, adaptors, num_adaptors);
7417a48c7cSmrg
755c69f917Smrg    free(adaptors);
7617a48c7cSmrg}
7717a48c7cSmrg
7817a48c7cSmrg#ifndef APM_VIDEO_DEFINES
7917a48c7cSmrg#define APM_VIDEO_DEFINES
8017a48c7cSmrg
8117a48c7cSmrgstatic Atom xvBrightness, xvContrast;
8217a48c7cSmrg
8317a48c7cSmrg/* client libraries expect an encoding */
8417a48c7cSmrgstatic XF86VideoEncodingRec DummyEncoding[1] =
8517a48c7cSmrg{
8617a48c7cSmrg    {
8717a48c7cSmrg	0,
8817a48c7cSmrg	"XV_IMAGE",
8917a48c7cSmrg	1024, 1024,
9017a48c7cSmrg	{1, 1}
9117a48c7cSmrg    }
9217a48c7cSmrg};
9317a48c7cSmrg
9417a48c7cSmrg#define NUM_FORMATS 24
9517a48c7cSmrg
9617a48c7cSmrgstatic XF86VideoFormatRec Formats[NUM_FORMATS] =
9717a48c7cSmrg{
9817a48c7cSmrg    { 8, PseudoColor},
9917a48c7cSmrg    {15, PseudoColor},
10017a48c7cSmrg    {16, PseudoColor},
10117a48c7cSmrg    {24, PseudoColor},
10217a48c7cSmrg    {32, PseudoColor},
10317a48c7cSmrg    { 8, DirectColor},
10417a48c7cSmrg    {15, DirectColor},
10517a48c7cSmrg    {16, DirectColor},
10617a48c7cSmrg    {24, DirectColor},
10717a48c7cSmrg    {32, DirectColor},
10817a48c7cSmrg    { 8,   TrueColor},
10917a48c7cSmrg    {15,   TrueColor},
11017a48c7cSmrg    {16,   TrueColor},
11117a48c7cSmrg    {24,   TrueColor},
11217a48c7cSmrg    {32,   TrueColor}
11317a48c7cSmrg};
11417a48c7cSmrg
11517a48c7cSmrg#define NUM_ATTRIBUTES 2
11617a48c7cSmrg
11717a48c7cSmrgstatic XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
11817a48c7cSmrg{
11917a48c7cSmrg    {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
12017a48c7cSmrg    {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}
12117a48c7cSmrg};
12217a48c7cSmrg
12317a48c7cSmrg#define NUM_IMAGES 9
12417a48c7cSmrgtypedef char c8;
12517a48c7cSmrg
12617a48c7cSmrgstatic XF86ImageRec Images[NUM_IMAGES] =
12717a48c7cSmrg{
12817a48c7cSmrg   {
12917a48c7cSmrg	0x35315652,
13017a48c7cSmrg        XvRGB,
13117a48c7cSmrg	LSBFirst,
13217a48c7cSmrg	{'R','V','1','5',
13317a48c7cSmrg	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
13417a48c7cSmrg	16,
13517a48c7cSmrg	XvPacked,
13617a48c7cSmrg	1,
13717a48c7cSmrg	15, 0x001F, 0x03E0, 0x7C00,
13817a48c7cSmrg	0, 0, 0,
13917a48c7cSmrg	0, 0, 0,
14017a48c7cSmrg	0, 0, 0,
14117a48c7cSmrg	{'R','V','B',0,
14217a48c7cSmrg	  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},
14317a48c7cSmrg	XvTopToBottom
14417a48c7cSmrg   },
14517a48c7cSmrg   {
14617a48c7cSmrg	0x36315652,
14717a48c7cSmrg        XvRGB,
14817a48c7cSmrg	LSBFirst,
14917a48c7cSmrg	{'R','V','1','6',
15017a48c7cSmrg	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
15117a48c7cSmrg	16,
15217a48c7cSmrg	XvPacked,
15317a48c7cSmrg	1,
15417a48c7cSmrg	16, 0x001F, 0x07E0, 0xF800,
15517a48c7cSmrg	0, 0, 0,
15617a48c7cSmrg	0, 0, 0,
15717a48c7cSmrg	0, 0, 0,
15817a48c7cSmrg	{'R','V','B',0,
15917a48c7cSmrg	  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},
16017a48c7cSmrg	XvTopToBottom
16117a48c7cSmrg   },
16217a48c7cSmrg   {
16317a48c7cSmrg	0x32335652,
16417a48c7cSmrg        XvRGB,
16517a48c7cSmrg	LSBFirst,
16617a48c7cSmrg	{'R','V','3','2',
16717a48c7cSmrg	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
16817a48c7cSmrg	32,
16917a48c7cSmrg	XvPacked,
17017a48c7cSmrg	1,
17117a48c7cSmrg	24, 0x0000FF, 0x00FF00, 0xFF0000,
17217a48c7cSmrg	0, 0, 0,
17317a48c7cSmrg	0, 0, 0,
17417a48c7cSmrg	0, 0, 0,
17517a48c7cSmrg	{'R','V','B',0,
17617a48c7cSmrg	  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},
17717a48c7cSmrg	XvTopToBottom
17817a48c7cSmrg   },
17917a48c7cSmrg   XVIMAGE_YUY2,
18017a48c7cSmrg   {
18117a48c7cSmrg	0x59595959,
18217a48c7cSmrg        XvYUV,
18317a48c7cSmrg	LSBFirst,
18417a48c7cSmrg	{0x00,0x00,0x00,0x00,
18517a48c7cSmrg	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
18617a48c7cSmrg	8,
18717a48c7cSmrg	XvPacked,
18817a48c7cSmrg	1,
18917a48c7cSmrg	0, 0, 0, 0,
19017a48c7cSmrg	8, 0, 0,
19117a48c7cSmrg	1, 1, 1,
19217a48c7cSmrg	1, 1, 1,
19317a48c7cSmrg	{'Y','Y','Y','Y',
19417a48c7cSmrg	  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},
19517a48c7cSmrg	XvTopToBottom
19617a48c7cSmrg   },
19717a48c7cSmrg   {
19817a48c7cSmrg	0x32315659,
19917a48c7cSmrg        XvYUV,
20017a48c7cSmrg	LSBFirst,
20117a48c7cSmrg	{'Y','V','1','2',
20217a48c7cSmrg	  0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71},
20317a48c7cSmrg	12,
20417a48c7cSmrg	XvPlanar,
20517a48c7cSmrg	3,
20617a48c7cSmrg	0, 0, 0, 0 ,
20717a48c7cSmrg	8, 8, 8,
20817a48c7cSmrg	1, 2, 2,
20917a48c7cSmrg	1, 2, 2,
21017a48c7cSmrg	{'Y','V','U',
21117a48c7cSmrg	  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},
21217a48c7cSmrg	XvTopToBottom
21317a48c7cSmrg   },
21417a48c7cSmrg   {
21517a48c7cSmrg	0x59565955,
21617a48c7cSmrg        XvYUV,
21717a48c7cSmrg	LSBFirst,
21817a48c7cSmrg	{'U','Y','V','Y',
21917a48c7cSmrg	  0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71},
22017a48c7cSmrg	16,
22117a48c7cSmrg	XvPlanar,
22217a48c7cSmrg	1,
22317a48c7cSmrg	0, 0, 0, 0,
22417a48c7cSmrg	8, 8, 8,
22517a48c7cSmrg	1, 2, 2,
22617a48c7cSmrg	1, 1, 1,
22717a48c7cSmrg	{'U','Y','V','Y',
22817a48c7cSmrg	  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},
22917a48c7cSmrg	XvTopToBottom
23017a48c7cSmrg   },
23117a48c7cSmrg   {
23217a48c7cSmrg	0x55595659,
23317a48c7cSmrg        XvYUV,
23417a48c7cSmrg	LSBFirst,
23517a48c7cSmrg	{'Y','V','Y','U',
23617a48c7cSmrg	  0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71},
23717a48c7cSmrg	16,
23817a48c7cSmrg	XvPlanar,
23917a48c7cSmrg	1,
24017a48c7cSmrg	0, 0, 0, 0,
24117a48c7cSmrg	8, 8, 8,
24217a48c7cSmrg	1, 2, 2,
24317a48c7cSmrg	1, 1, 1,
24417a48c7cSmrg	{'Y','V','Y','U',
24517a48c7cSmrg	  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},
24617a48c7cSmrg	XvTopToBottom
24717a48c7cSmrg   },
24817a48c7cSmrg   {
24917a48c7cSmrg	0x59555956,
25017a48c7cSmrg        XvYUV,
25117a48c7cSmrg	LSBFirst,
25217a48c7cSmrg	{'V','Y','U','Y',
25317a48c7cSmrg	  0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71},
25417a48c7cSmrg	16,
25517a48c7cSmrg	XvPlanar,
25617a48c7cSmrg	1,
25717a48c7cSmrg	0, 0, 0, 0,
25817a48c7cSmrg	8, 8, 8,
25917a48c7cSmrg	1, 2, 2,
26017a48c7cSmrg	1, 1, 1,
26117a48c7cSmrg	{'V','Y','U','Y',
26217a48c7cSmrg	  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},
26317a48c7cSmrg	XvTopToBottom
26417a48c7cSmrg   }
26517a48c7cSmrg};
26617a48c7cSmrg
26717a48c7cSmrgtypedef struct {
26817a48c7cSmrg   Bool		on;
26917a48c7cSmrg   unsigned char	brightness;
27017a48c7cSmrg   unsigned char	contrast;
27117a48c7cSmrg   unsigned short	reg, val;
27217a48c7cSmrg   ApmPtr	pApm;
27317a48c7cSmrg   int		x1, x10, y1, drw_x, drw_y, Bpp, Bps;
27417a48c7cSmrg   FBAreaPtr	area;
27517a48c7cSmrg   RegionRec	clip;
27617a48c7cSmrg   int		xnum, xden, ynum, yden;
27717a48c7cSmrg   CARD32	scalex, scaley;
27817a48c7cSmrg   CARD32	data;
27917a48c7cSmrg} ApmPortPrivRec, *ApmPortPrivPtr;
28017a48c7cSmrg#endif
28117a48c7cSmrg
28217a48c7cSmrg
28317a48c7cSmrgstatic void
28417a48c7cSmrgA(ResetVideo)(ScrnInfoPtr pScrn)
28517a48c7cSmrg{
28617a48c7cSmrg    APMDECL(pScrn);
28717a48c7cSmrg
28817a48c7cSmrg    A(WaitForFifo)(pApm, 2);
28917a48c7cSmrg    ((ApmPortPrivPtr)pApm->adaptor->pPortPrivates[0].ptr)->on = 0;
29017a48c7cSmrg    ((ApmPortPrivPtr)pApm->adaptor->pPortPrivates[1].ptr)->on = 0;
29117a48c7cSmrg    WRXW(0x82, 0);
29217a48c7cSmrg    WRXW(0x92, 0);
29317a48c7cSmrg}
29417a48c7cSmrg
29517a48c7cSmrg
29617a48c7cSmrgstatic XF86VideoAdaptorPtr
29717a48c7cSmrgA(SetupImageVideo)(ScreenPtr pScreen)
29817a48c7cSmrg{
2995c69f917Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
30017a48c7cSmrg    APMDECL(pScrn);
30117a48c7cSmrg    XF86VideoAdaptorPtr adapt;
30217a48c7cSmrg    ApmPortPrivPtr pPriv;
30317a48c7cSmrg
3045c69f917Smrg    if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
3055c69f917Smrg			   2 * sizeof(ApmPortPrivRec) +
3065c69f917Smrg			   2 * sizeof(DevUnion))))
30717a48c7cSmrg	return NULL;
30817a48c7cSmrg
30917a48c7cSmrg    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
31017a48c7cSmrg    adapt->flags = VIDEO_OVERLAID_IMAGES;
31117a48c7cSmrg    adapt->name = "Alliance Pro Motion video engine";
31217a48c7cSmrg    adapt->nEncodings = 1;
31317a48c7cSmrg    adapt->pEncodings = DummyEncoding;
31417a48c7cSmrg    adapt->nFormats = NUM_FORMATS;
31517a48c7cSmrg    adapt->pFormats = Formats;
31617a48c7cSmrg    adapt->nPorts = 2;
31717a48c7cSmrg    adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
31817a48c7cSmrg    pPriv = (ApmPortPrivPtr)(&adapt->pPortPrivates[2]);
31917a48c7cSmrg    pPriv->pApm = pApm;
32017a48c7cSmrg    pPriv[1].pApm = pApm;
32117a48c7cSmrg    pPriv->reg = 0x82;
32217a48c7cSmrg    pPriv[1].reg = 0x92;
32317a48c7cSmrg    adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
32417a48c7cSmrg    adapt->pPortPrivates[1].ptr = (pointer)(pPriv + 1);
32517a48c7cSmrg    adapt->nAttributes = NUM_ATTRIBUTES;
32617a48c7cSmrg    adapt->pAttributes = Attributes;
32717a48c7cSmrg    adapt->nImages = NUM_IMAGES;
32817a48c7cSmrg    adapt->pImages = Images;
32917a48c7cSmrg    adapt->PutVideo = NULL;
33017a48c7cSmrg    adapt->PutStill = NULL;
33117a48c7cSmrg    adapt->GetVideo = NULL;
33217a48c7cSmrg    adapt->GetStill = NULL;
33317a48c7cSmrg    adapt->StopVideo = A(StopVideo);
33417a48c7cSmrg    adapt->SetPortAttribute = A(SetPortAttribute);
33517a48c7cSmrg    adapt->GetPortAttribute = ApmGetPortAttribute;
33617a48c7cSmrg    adapt->QueryBestSize = ApmQueryBestSize;
33717a48c7cSmrg    adapt->PutImage = A(PutImage);
3385c69f917Smrg#ifndef XV_NEW_REPUT
3395c69f917Smrg    adapt->ReputImage = A(ReputImage);
3405c69f917Smrg#endif
34117a48c7cSmrg    adapt->QueryImageAttributes = ApmQueryImageAttributes;
34217a48c7cSmrg
34317a48c7cSmrg    pPriv->brightness = 0;
34417a48c7cSmrg    pPriv->contrast = 128;
34517a48c7cSmrg    pPriv[1].brightness = 0;
34617a48c7cSmrg    pPriv[1].contrast = 128;
34717a48c7cSmrg
34817a48c7cSmrg    /* gotta uninit this someplace */
34917a48c7cSmrg    REGION_NULL(pScreen, &pPriv->clip);
35017a48c7cSmrg    REGION_NULL(pScreen, &(pPriv + 1)->clip);
35117a48c7cSmrg
35217a48c7cSmrg    pApm->adaptor = adapt;
35317a48c7cSmrg
35417a48c7cSmrg    xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
35517a48c7cSmrg    xvContrast   = MAKE_ATOM("XV_CONTRAST");
35617a48c7cSmrg
35717a48c7cSmrg    A(ResetVideo)(pScrn);
35817a48c7cSmrg
35917a48c7cSmrg    return adapt;
36017a48c7cSmrg}
36117a48c7cSmrg
36217a48c7cSmrg/* ApmClipVideo -
36317a48c7cSmrg
36417a48c7cSmrg   Takes the dst box in standard X BoxRec form (top and left
36517a48c7cSmrg   edges inclusive, bottom and right exclusive).  The new dst
36617a48c7cSmrg   box is returned.  The source boundaries are given (x1, y1
36717a48c7cSmrg   inclusive, x2, y2 exclusive) and returned are the new source
36817a48c7cSmrg   boundaries in 16.16 fixed point.
36917a48c7cSmrg
37017a48c7cSmrg  extents is the extents of the clip region
37117a48c7cSmrg*/
37217a48c7cSmrg
37317a48c7cSmrgstatic void
37417a48c7cSmrgApmClipVideo(BoxPtr dst, INT32 *x1, INT32 *x2, INT32 *y1, INT32 *y2,
37517a48c7cSmrg	      BoxPtr extents, INT32 width, INT32 height,
37617a48c7cSmrg	      CARD32 *scalex, CARD32 *scaley, INT32 mask)
37717a48c7cSmrg{
37817a48c7cSmrg    INT32 vscale, hscale;
37917a48c7cSmrg    int diff;
38017a48c7cSmrg
38117a48c7cSmrg    if (dst->x2 - dst->x1 < *x2 - *x1)
38217a48c7cSmrg	dst->x2 = dst->x1 + *x2 - *x1;
38317a48c7cSmrg
38417a48c7cSmrg    if (dst->y2 - dst->y1 < *y2 - *y1)
38517a48c7cSmrg	dst->y2 = dst->y1 + *y2 - *y1;
38617a48c7cSmrg
38717a48c7cSmrg    *x1 <<= 12; *x2 <<= 16;
38817a48c7cSmrg    *y1 <<= 12; *y2 <<= 16;
38917a48c7cSmrg
39017a48c7cSmrg    hscale = (*x2 - *x1) / (dst->x2 - dst->x1);
39117a48c7cSmrg    vscale = (*y2 - *y1) / (dst->y2 - dst->y1);
39217a48c7cSmrg
39317a48c7cSmrg    diff = extents->x1 - dst->x1;
39417a48c7cSmrg    if(diff > 0) {
39517a48c7cSmrg	dst->x1 = extents->x1;
39617a48c7cSmrg	*x1 += diff * hscale;
39717a48c7cSmrg    }
39817a48c7cSmrg    diff = dst->x2 - extents->x2;
39917a48c7cSmrg    if(diff > 0) {
40017a48c7cSmrg	dst->x2 = extents->x2;
40117a48c7cSmrg	*x2 -= diff * hscale;
40217a48c7cSmrg    }
40317a48c7cSmrg    diff = extents->y1 - dst->y1;
40417a48c7cSmrg    if(diff > 0) {
40517a48c7cSmrg	dst->y1 = extents->y1;
40617a48c7cSmrg	*y1 += diff * vscale;
40717a48c7cSmrg    }
40817a48c7cSmrg    diff = dst->y2 - extents->y2;
40917a48c7cSmrg    if(diff > 0) {
41017a48c7cSmrg	dst->y2 = extents->y2;
41117a48c7cSmrg	*y2 -= diff * vscale;
41217a48c7cSmrg    }
41317a48c7cSmrg
41417a48c7cSmrg    if (*x2 - *x1 == 0x10000 * (dst->x2 - dst->x1))	/* Shrinking */
41517a48c7cSmrg	*scalex = 0;
41617a48c7cSmrg    else
41717a48c7cSmrg	*scalex = ((*x2 - *x1) / (dst->x2 - dst->x1)) >> 4;
41817a48c7cSmrg    if (*y2 - *y1 == 0x10000 * (dst->y2 - dst->y1))	/* Shrinking */
41917a48c7cSmrg	*scaley = 0;
42017a48c7cSmrg    else
42117a48c7cSmrg	*scaley = ((*y2 - *y1) / (dst->y2 - dst->y1)) >> 4;
42217a48c7cSmrg}
42317a48c7cSmrg
42417a48c7cSmrgstatic void
42517a48c7cSmrgA(StopVideo)(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
42617a48c7cSmrg{
42717a48c7cSmrg    ApmPortPrivPtr pPriv = (ApmPortPrivPtr)data;
42817a48c7cSmrg    APMDECL(pScrn);
42917a48c7cSmrg
43017a48c7cSmrg    REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
43117a48c7cSmrg
43217a48c7cSmrg    pPriv->on = 0;
43317a48c7cSmrg    A(WaitForFifo)(pApm, 1);
43417a48c7cSmrg    WRXB(pPriv->reg, 0);
43517a48c7cSmrg}
43617a48c7cSmrg
43717a48c7cSmrgstatic int
43817a48c7cSmrgA(SetPortAttribute)(ScrnInfoPtr pScrn, Atom attribute, INT32 value,
43917a48c7cSmrg		      pointer data)
44017a48c7cSmrg{
44117a48c7cSmrg  ApmPortPrivPtr pPriv = (ApmPortPrivPtr)data;
44217a48c7cSmrg  /*APMDECL(pScrn);*/
44317a48c7cSmrg
44417a48c7cSmrg  if(attribute == xvBrightness) {
44517a48c7cSmrg	if((value < -128) || (value > 127))
44617a48c7cSmrg	   return BadValue;
44717a48c7cSmrg	pPriv->brightness = value;
44817a48c7cSmrg	/* TODO : enable */
44917a48c7cSmrg  } else if(attribute == xvContrast) {
45017a48c7cSmrg	if((value < 0) || (value > 255))
45117a48c7cSmrg	   return BadValue;
45217a48c7cSmrg	pPriv->contrast = value;
45317a48c7cSmrg	/* TODO : enable */
45417a48c7cSmrg  }
45517a48c7cSmrg
45617a48c7cSmrg  return Success;
45717a48c7cSmrg}
45817a48c7cSmrg
45917a48c7cSmrgstatic int
46017a48c7cSmrgApmGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value,
46117a48c7cSmrg		      pointer data)
46217a48c7cSmrg{
46317a48c7cSmrg  ApmPortPrivPtr pPriv = (ApmPortPrivPtr)data;
46417a48c7cSmrg
46517a48c7cSmrg  if(attribute == xvBrightness) {
46617a48c7cSmrg	*value = pPriv->brightness;
46717a48c7cSmrg  } else
46817a48c7cSmrg  if(attribute == xvContrast) {
46917a48c7cSmrg	*value = pPriv->contrast;
47017a48c7cSmrg  }
47117a48c7cSmrg
47217a48c7cSmrg  return Success;
47317a48c7cSmrg}
47417a48c7cSmrg
47517a48c7cSmrgstatic void
47617a48c7cSmrgApmQueryBestSize(ScrnInfoPtr pScrn, Bool motion, short vid_w, short vid_h,
47717a48c7cSmrg		  short drw_w, short drw_h,
47817a48c7cSmrg		  unsigned int *p_w, unsigned int *p_h, pointer data)
47917a48c7cSmrg{
48017a48c7cSmrg    APMDECL(pScrn);
48117a48c7cSmrg    unsigned short	round = ~pApm->CurrentLayout.mask32;
48217a48c7cSmrg
48317a48c7cSmrg    *p_w = drw_w & round;
48417a48c7cSmrg    *p_h = drw_h & round;
48517a48c7cSmrg}
48617a48c7cSmrg
48717a48c7cSmrgstatic void A(XvMoveCB)(FBAreaPtr area1, FBAreaPtr area2)
48817a48c7cSmrg{
48917a48c7cSmrg    ApmPortPrivPtr	pPriv = (ApmPortPrivPtr)area1->devPrivate.ptr;
49017a48c7cSmrg    ApmPtr		pApm = pPriv->pApm;
49117a48c7cSmrg
49217a48c7cSmrg    pPriv->on = 0;
49317a48c7cSmrg    A(WaitForFifo)(pApm, 1);
49417a48c7cSmrg    WRXB(pPriv->reg, 0);	/* Stop video for this port */
49517a48c7cSmrg    pPriv->area = area2;
49617a48c7cSmrg}
49717a48c7cSmrg
49817a48c7cSmrgstatic void A(XvRemoveCB)(FBAreaPtr area)
49917a48c7cSmrg{
50017a48c7cSmrg    ApmPortPrivPtr	pPriv = (ApmPortPrivPtr)area->devPrivate.ptr;
50117a48c7cSmrg    ApmPtr		pApm = pPriv->pApm;
50217a48c7cSmrg
50317a48c7cSmrg    pPriv->on = 0;
50417a48c7cSmrg    A(WaitForFifo)(pApm, 1);
50517a48c7cSmrg    WRXB(pPriv->reg, 0);	/* Stop video for this port */
50617a48c7cSmrg    pPriv->area = NULL;
50717a48c7cSmrg}
50817a48c7cSmrg
50917a48c7cSmrgstatic int
51017a48c7cSmrgA(ReputImage)(ScrnInfoPtr pScrn, short drw_x, short drw_y,
51117a48c7cSmrg		RegionPtr clipBoxes, pointer pdata, DrawablePtr pDraw)
51217a48c7cSmrg{
51317a48c7cSmrg    ScreenPtr		pScreen = pScrn->pScreen;
51417a48c7cSmrg    APMDECL(pScrn);
51517a48c7cSmrg    ApmPortPrivPtr	pPriv = pdata, pPriv0, pPriv1;
51617a48c7cSmrg    register int	fx, fy;
51717a48c7cSmrg    CARD32	mask;
51817a48c7cSmrg    RegionRec	Union;
51917a48c7cSmrg    RegionPtr	reg0;
52017a48c7cSmrg    int		nrects, CurrY, tile;
52117a48c7cSmrg    int		X1, X2, Y1, y2, xmax, ymax;
52217a48c7cSmrg    BoxPtr	rects;
52317a48c7cSmrg    Bool	didit = 0;
52417a48c7cSmrg
52517a48c7cSmrg    mask = pApm->CurrentLayout.mask32;
52617a48c7cSmrg    fx = pScrn->frameX0 & ~mask;
52717a48c7cSmrg    fy = pScrn->frameY0 + 1;
52817a48c7cSmrg    REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
52917a48c7cSmrg    pPriv->x1 += drw_x - pPriv->drw_x;
53017a48c7cSmrg    pPriv->x10 = ((pPriv->x1 + mask) & ~mask) - fx;
53117a48c7cSmrg    pPriv->y1 += drw_y - pPriv->drw_y;
53217a48c7cSmrg    pPriv->drw_x = drw_x;
53317a48c7cSmrg    pPriv->drw_y = drw_y;
53417a48c7cSmrg    A(WaitForFifo)(pApm, 2);
53517a48c7cSmrg    WRXW(pPriv->reg + 0x06, 0xFFF - ((pPriv->scalex * pPriv->x10) & 0xFFF));
53617a48c7cSmrg    WRXW(pPriv->reg + 0x0A, 0xFFF - ((pPriv->scaley * pPriv->y1) & 0xFFF));
53717a48c7cSmrg    pPriv0 = (ApmPortPrivPtr)pApm->adaptor->pPortPrivates[0].ptr;
53817a48c7cSmrg    pPriv1 = (ApmPortPrivPtr)pApm->adaptor->pPortPrivates[1].ptr;
53917a48c7cSmrg    reg0 = &pPriv0->clip;
54017a48c7cSmrg    bzero(&Union, sizeof Union);
54117a48c7cSmrg    REGION_EMPTY(pScreen, &Union);
54217a48c7cSmrg    REGION_NULL(pScreen, &Union);
54317a48c7cSmrg    REGION_UNION(pScreen, &Union, reg0, &pPriv1->clip);
54417a48c7cSmrg    nrects = REGION_NUM_RECTS(&Union);
54517a48c7cSmrg    rects = REGION_RECTS(&Union);
54617a48c7cSmrg    tile = 0x200;
54717a48c7cSmrg    xmax = pScrn->frameX1 - pScrn->frameX0 + 1;
54817a48c7cSmrg    ymax = pScrn->frameY1 - pScrn->frameY0;
54917a48c7cSmrg    CurrY = -1;
55017a48c7cSmrg    goto BEGIN_LOOP_1;
55117a48c7cSmrg    do {
55217a48c7cSmrg	rects++;
55317a48c7cSmrgBEGIN_LOOP_1:
55417a48c7cSmrg	X1 = ((rects->x1 + mask) & ~mask) - fx;
55517a48c7cSmrg	if (X1 < 0)
55617a48c7cSmrg	    X1 = 0;
55717a48c7cSmrg	X2 = (rects->x2 & ~mask) - fx;
55817a48c7cSmrg	if (X2 > xmax)
55917a48c7cSmrg	    X2 = xmax;
56017a48c7cSmrg	y2 = rects->y2 - fy;
56117a48c7cSmrg    } while ((X2 <= X1 || y2 < -1) && --nrects > 0);
56217a48c7cSmrg    Y1 = rects->y1 - fy;
56317a48c7cSmrg
56417a48c7cSmrg    while (!(STATUS() & 0x800));
56517a48c7cSmrg    while (STATUS() & 0x800);
56617a48c7cSmrg    while (nrects-- > 0) {
56717a48c7cSmrg	CARD32	reg, data;
56817a48c7cSmrg	int	x1, x2, y1;
56917a48c7cSmrg
57017a48c7cSmrg	x1 = X1;
57117a48c7cSmrg	x2 = X2;
57217a48c7cSmrg	y1 = Y1;
57317a48c7cSmrg	if (y1 < -1) y1 = -1;
57417a48c7cSmrg	if (y1 > ymax)
57517a48c7cSmrg	    break;
57617a48c7cSmrg	didit = 1;
57717a48c7cSmrg	if (y1 > CurrY) {
57817a48c7cSmrg	    A(WaitForFifo)(pApm, 3);
57917a48c7cSmrg	    WRXL(tile + 0x00, 0xFFF0011);
58017a48c7cSmrg	    WRXL(tile + 0x04, y1 << 16);
58117a48c7cSmrg	    WRXL(tile + 0x08, 0);
58217a48c7cSmrg	    tile += 16;
58317a48c7cSmrg	}
58417a48c7cSmrg	if (RECT_IN_REGION(pScreen, reg0, rects)) {
58517a48c7cSmrg	    pPriv = pPriv0;
58617a48c7cSmrg	    reg = (x1 << 16) | 1;
58717a48c7cSmrg	}
58817a48c7cSmrg	else {
58917a48c7cSmrg	    pPriv = pPriv1;
59017a48c7cSmrg	    reg = (x1 << 16) | 2;
59117a48c7cSmrg	}
59217a48c7cSmrg	CurrY = y2;
59317a48c7cSmrg	if (nrects <= 0)
59417a48c7cSmrg	    goto BEGIN_LOOP_2;
59517a48c7cSmrg	do {
59617a48c7cSmrg	    rects++;
59717a48c7cSmrgBEGIN_LOOP_2:
59817a48c7cSmrg	    X1 = ((rects->x1 + mask) & ~mask) - fx;
59917a48c7cSmrg	    if (X1 < 0)
60017a48c7cSmrg		X1 = 0;
60117a48c7cSmrg	    X2 = (rects->x2 & ~mask) - fx;
60217a48c7cSmrg	    if (X2 > xmax)
60317a48c7cSmrg		X2 = xmax;
60417a48c7cSmrg	} while (X2 <= X1 && --nrects > 0);
60517a48c7cSmrg	Y1 = rects->y1 - fy;
60617a48c7cSmrg	y2 = rects->y2 - fy;
60717a48c7cSmrg	data = pPriv->data + (((x1 - pPriv->x10)
60817a48c7cSmrg				* pPriv->xden) / pPriv->xnum) * pPriv->Bpp +
60917a48c7cSmrg	    (((y1 - pPriv->y1 + fy) * pPriv->yden) / pPriv->ynum) * pPriv->Bps;
61017a48c7cSmrg	A(WaitForFifo)(pApm, 4);
61117a48c7cSmrg	if (!nrects || tile == 0x2B0 || y1 < Y1) {
61217a48c7cSmrg	    WRXL(tile   , 0x10 | reg);
61317a48c7cSmrg	}
61417a48c7cSmrg	else {
61517a48c7cSmrg	    WRXL(tile   , reg);
61617a48c7cSmrg	}
61717a48c7cSmrg	WRXL(tile + 0x04, x2 | (CurrY << 16));
61817a48c7cSmrg	WRXL(tile + 0x08, (((x2-x1)*pPriv->xden+pPriv->xnum-1) / pPriv->xnum) |
61917a48c7cSmrg				(data << 16));
62017a48c7cSmrg	WRXB(tile + 0x0C, data >> 16);
62117a48c7cSmrg	tile += 16;
62217a48c7cSmrg	if (tile == 0x2C0) {
62317a48c7cSmrg	    tile = 0x200;
62417a48c7cSmrg	    break;
62517a48c7cSmrg	}
62617a48c7cSmrg    }
62717a48c7cSmrg    REGION_UNINIT(pScreen, &Union);
62817a48c7cSmrg
62917a48c7cSmrg    if (didit) {
63017a48c7cSmrg	A(WaitForFifo)(pApm, 1);
63117a48c7cSmrg	WRXW(0x8E, tile - 0x200);
63217a48c7cSmrg    }
63317a48c7cSmrg
63417a48c7cSmrg    if (didit ^ ((pPriv0->val | pPriv1->val) & 1)) {
63517a48c7cSmrg	if (didit) {
63617a48c7cSmrg	    pPriv0->val |= 1;
63717a48c7cSmrg	    pPriv1->val |= 1;
63817a48c7cSmrg	}
63917a48c7cSmrg	else {
64017a48c7cSmrg	    pPriv0->val &= 0xFFFE;
64117a48c7cSmrg	    pPriv1->val &= 0xFFFE;
64217a48c7cSmrg	}
64317a48c7cSmrg	if (pPriv0->on) {
64417a48c7cSmrg	    A(WaitForFifo)(pApm, 1);
64517a48c7cSmrg	    WRXW(0x82, pPriv0->val);
64617a48c7cSmrg	}
64717a48c7cSmrg	if (pPriv1->on) {
64817a48c7cSmrg	    A(WaitForFifo)(pApm, 1);
64917a48c7cSmrg	    WRXW(0x92, pPriv1->val);
65017a48c7cSmrg	}
65117a48c7cSmrg    }
65217a48c7cSmrg
65317a48c7cSmrg    return Success;
65417a48c7cSmrg}
65517a48c7cSmrg
65617a48c7cSmrgstatic int
65717a48c7cSmrgA(PutImage)(ScrnInfoPtr pScrn, short src_x, short src_y,
65817a48c7cSmrg	      short drw_x, short drw_y, short src_w, short src_h,
65917a48c7cSmrg	      short drw_w, short drw_h, int id, unsigned char* buf,
66017a48c7cSmrg	      short width, short height, Bool sync, RegionPtr clipBoxes,
66117a48c7cSmrg	      pointer data, DrawablePtr pDraw)
66217a48c7cSmrg{
66317a48c7cSmrg    ApmPortPrivPtr	pPriv = (ApmPortPrivPtr)data;
66417a48c7cSmrg    ScreenPtr	pScreen = pScrn->pScreen;
66517a48c7cSmrg    APMDECL(pScrn);
66617a48c7cSmrg    INT32	x1, x2, y1, y2;
66717a48c7cSmrg    unsigned char	*dst_start;
66817a48c7cSmrg    int		pitch, Bpp, new_h, offset = 0, offset2 = 0, offset3 = 0;
66917a48c7cSmrg    CARD32	mask;
67017a48c7cSmrg    FBAreaPtr	area;
67117a48c7cSmrg    int		srcPitch, dstPitch, srcPitch2 = 0;
67217a48c7cSmrg    int		top, left, npixels, nlines;
67317a48c7cSmrg    BoxRec	dstBox;
67417a48c7cSmrg    CARD32	scalex, scaley, scale;
67517a48c7cSmrg    CARD32	tmp;
67617a48c7cSmrg    Bool	offscreen;
67717a48c7cSmrg
67817a48c7cSmrg    offscreen = (buf < (unsigned char *)pApm->FbBase ||
67917a48c7cSmrg		    buf > (unsigned char *)pApm->FbBase + 0x400000);
68017a48c7cSmrg
68117a48c7cSmrg    if(drw_w > 16384) drw_w = 16384;
68217a48c7cSmrg
68317a48c7cSmrg    /* Clip */
68417a48c7cSmrg    x1 = src_x;
68517a48c7cSmrg    x2 = src_x + src_w;
68617a48c7cSmrg    y1 = src_y;
68717a48c7cSmrg    y2 = src_y + src_h;
68817a48c7cSmrg
68917a48c7cSmrg    dstBox.x1 = drw_x;
69017a48c7cSmrg    dstBox.x2 = drw_x + drw_w;
69117a48c7cSmrg    dstBox.y1 = drw_y;
69217a48c7cSmrg    dstBox.y2 = drw_y + drw_h;
69317a48c7cSmrg
69417a48c7cSmrg    mask = pApm->CurrentLayout.mask32;
69517a48c7cSmrg
69617a48c7cSmrg    ApmClipVideo(&dstBox, &x1, &x2, &y1, &y2,
69717a48c7cSmrg		REGION_EXTENTS(pScreen, clipBoxes), width, height,
69817a48c7cSmrg		&scalex, &scaley, mask);
69917a48c7cSmrg
70017a48c7cSmrg    pPriv->drw_x = drw_x;
70117a48c7cSmrg    pPriv->drw_y = drw_y;
70217a48c7cSmrg    pPriv->xnum = drw_w;
70317a48c7cSmrg    if (scalex)
70417a48c7cSmrg	pPriv->xden = src_w;
70517a48c7cSmrg    else
70617a48c7cSmrg	pPriv->xden = drw_w;	/* If image is larger than window */
70717a48c7cSmrg    pPriv->ynum = drw_h;
70817a48c7cSmrg    if (scaley)
70917a48c7cSmrg	pPriv->yden = src_h;
71017a48c7cSmrg    else
71117a48c7cSmrg	pPriv->yden = drw_h;
71217a48c7cSmrg    if((x1 - x2 >= 0xFFFF) || (y1 - y2 >= 0xFFFF))
71317a48c7cSmrg     return Success;
71417a48c7cSmrg
71517a48c7cSmrg    Bpp = pScrn->bitsPerPixel >> 3;
71617a48c7cSmrg    pitch = Bpp * pScrn->displayWidth;
71717a48c7cSmrg
71817a48c7cSmrg    switch(id) {
71917a48c7cSmrg    case 0x32315659:
72017a48c7cSmrg	dstPitch = ((width << 1) + 3) & ~3;
72117a48c7cSmrg	srcPitch = (width + 3) & ~3;
72217a48c7cSmrg	offset2 = srcPitch * height;
72317a48c7cSmrg	srcPitch2 = ((width >> 1) + 3) & ~3;
72417a48c7cSmrg	offset = srcPitch2 * (height >> 1);
72517a48c7cSmrg	offset3 = offset + offset2;
72617a48c7cSmrg	new_h = (2 * offset2 + pitch - 1) / pitch;
72717a48c7cSmrg	break;
72817a48c7cSmrg    case 0x59595959:
72917a48c7cSmrg	srcPitch = width;
73017a48c7cSmrg	dstPitch = (srcPitch + 3) & ~3;
73117a48c7cSmrg	offset = dstPitch * height;
73217a48c7cSmrg	new_h = (offset + pitch - 1) / pitch;
73317a48c7cSmrg	break;
73417a48c7cSmrg    case 0x32335652:
73517a48c7cSmrg	srcPitch = (width << 2);
73617a48c7cSmrg	dstPitch = (srcPitch + 3) & ~3;
73717a48c7cSmrg	offset = dstPitch * height;
73817a48c7cSmrg	new_h = (offset + pitch - 1) / pitch;
73917a48c7cSmrg	break;
74017a48c7cSmrg    default:
74117a48c7cSmrg	if (pApm->PutImageStride)
74217a48c7cSmrg	    srcPitch = pApm->PutImageStride;
74317a48c7cSmrg	else
74417a48c7cSmrg	    srcPitch = (width << 1);
74517a48c7cSmrg	dstPitch = (srcPitch + 3) & ~3;
74617a48c7cSmrg	offset = dstPitch * height;
74717a48c7cSmrg	new_h = (offset + pitch - 1) / pitch;
74817a48c7cSmrg	break;
74917a48c7cSmrg    }
75017a48c7cSmrg
75117a48c7cSmrg    area = pPriv->area;
75217a48c7cSmrg
75317a48c7cSmrg    /* Allocate offscreen memory */
75417a48c7cSmrg    if (offscreen && (!area || ((area->box.y2 - area->box.y1) < new_h))) {
75517a48c7cSmrg	Bool nukeMem = FALSE;
75617a48c7cSmrg	int max_w, max_h;
75717a48c7cSmrg
75817a48c7cSmrg	xf86QueryLargestOffscreenArea(pScreen, &max_w, &max_h, 0,
75917a48c7cSmrg			  FAVOR_WIDTH_THEN_AREA, PRIORITY_LOW);
76017a48c7cSmrg	if (max_w == pScrn->displayWidth && max_h >= new_h) {
76117a48c7cSmrg	    area = xf86AllocateOffscreenArea(pScreen,
76217a48c7cSmrg					pScrn->displayWidth, new_h,
76317a48c7cSmrg					4, A(XvMoveCB), A(XvRemoveCB), pPriv);
76417a48c7cSmrg	    if (area) {
76517a48c7cSmrg		if (pPriv->area)
76617a48c7cSmrg		    xf86FreeOffscreenArea(pPriv->area);
76717a48c7cSmrg	    }
76817a48c7cSmrg	    else
76917a48c7cSmrg		area = pPriv->area;	/* Should not happen */
77017a48c7cSmrg	}
77117a48c7cSmrg	if(!area) {
77217a48c7cSmrg	    if(!(area = xf86AllocateOffscreenArea(pScreen,
77317a48c7cSmrg					pScrn->displayWidth, new_h, 4,
77417a48c7cSmrg					A(XvMoveCB), A(XvRemoveCB), pPriv)))
77517a48c7cSmrg	    {
77617a48c7cSmrg	       nukeMem = TRUE;
77717a48c7cSmrg	    }
77817a48c7cSmrg	} else {
77917a48c7cSmrg	    if(!xf86ResizeOffscreenArea(area, pScrn->displayWidth, new_h)) {
78017a48c7cSmrg	       xf86FreeOffscreenArea(area);
78117a48c7cSmrg	       pPriv->area = area = NULL;
78217a48c7cSmrg	       nukeMem = TRUE;
78317a48c7cSmrg	    }
78417a48c7cSmrg	}
78517a48c7cSmrg	if(nukeMem) {
78617a48c7cSmrg	    xf86QueryLargestOffscreenArea(pScreen, &max_w, &max_h, 0,
78717a48c7cSmrg			    FAVOR_WIDTH_THEN_AREA, PRIORITY_EXTREME);
78817a48c7cSmrg
78917a48c7cSmrg	    if((max_w < pScrn->displayWidth) || (max_h < new_h))
79017a48c7cSmrg		return BadAlloc;
79117a48c7cSmrg
79217a48c7cSmrg	    xf86PurgeUnlockedOffscreenAreas(pScreen);
79317a48c7cSmrg
79417a48c7cSmrg	    area = xf86AllocateOffscreenArea(pScreen,
79517a48c7cSmrg					pScrn->displayWidth, new_h, 4,
79617a48c7cSmrg					A(XvMoveCB), A(XvRemoveCB), pPriv);
79717a48c7cSmrg	}
79817a48c7cSmrg
79917a48c7cSmrg	pPriv->area = area;
80017a48c7cSmrg    }
80117a48c7cSmrg
80217a48c7cSmrg    /* copy data */
80317a48c7cSmrg    pPriv->x1 = dstBox.x1 /*drw_x*/;
80417a48c7cSmrg    pPriv->y1 = dstBox.y1 /*drw_y*/;
80517a48c7cSmrg    top = y1 >> 16;
80617a48c7cSmrg    left = (x1 >> 16) & ~1;
80717a48c7cSmrg    npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
80817a48c7cSmrg
80917a48c7cSmrg    switch(id) {
81017a48c7cSmrg    case 0x59595959:
81117a48c7cSmrg	pPriv->Bpp = 1;
81217a48c7cSmrg	break;
81317a48c7cSmrg    default:
81417a48c7cSmrg	pPriv->Bpp = 2;
81517a48c7cSmrg	left <<= 1;
81617a48c7cSmrg	break;
81717a48c7cSmrg    case 0x32335652:
81817a48c7cSmrg	pPriv->Bpp = 4;
81917a48c7cSmrg	left <<= 2;
82017a48c7cSmrg	break;
82117a48c7cSmrg    }
82217a48c7cSmrg    pPriv->Bps = pPriv->Bpp * pPriv->xden;
82317a48c7cSmrg    if (offscreen) {
82417a48c7cSmrg	offset = (area->box.y1 * pitch) + (top * dstPitch);
82517a48c7cSmrg	dst_start = ((unsigned char *)pApm->FbBase) +
82617a48c7cSmrg						(pPriv->data = offset + left);
82717a48c7cSmrg	switch(id) {
82817a48c7cSmrg	case 0x32315659:
82917a48c7cSmrg	    top &= ~1;
83017a48c7cSmrg	    tmp = ((top >> 1) * srcPitch2) + (left >> 2);
83117a48c7cSmrg	    offset2 += tmp;
83217a48c7cSmrg	    offset3 += tmp;
83317a48c7cSmrg	    nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
83417a48c7cSmrg	    xf86XVCopyYUV12ToPacked(buf + (top * srcPitch) + (left >> 1),
83517a48c7cSmrg				    buf + offset2, buf + offset3, dst_start,
83617a48c7cSmrg				    srcPitch, srcPitch2, dstPitch,
83717a48c7cSmrg				    nlines, npixels);
83817a48c7cSmrg	    break;
83917a48c7cSmrg	default:
84017a48c7cSmrg	    if (id == 0x32335652)
84117a48c7cSmrg		npixels <<= 1;
84217a48c7cSmrg	    else if (id == 0x59595959)
84317a48c7cSmrg		npixels >>= 1;
84417a48c7cSmrg	    buf += (top * srcPitch) + left;
84517a48c7cSmrg	    nlines = ((y2 + 0xffff) >> 16) - top;
84617a48c7cSmrg	    if (offscreen)
84717a48c7cSmrg		xf86XVCopyPacked(buf, dst_start, srcPitch, dstPitch,
84817a48c7cSmrg				 nlines, npixels);
84917a48c7cSmrg	    break;
85017a48c7cSmrg	}
85117a48c7cSmrg    }
85217a48c7cSmrg    else
85317a48c7cSmrg	pPriv->data = buf - (unsigned char *)pApm->FbBase;
85417a48c7cSmrg    pPriv->on = 1;
85517a48c7cSmrg    A(WaitForFifo)(pApm, 3);
85617a48c7cSmrg    WRXW(pPriv->reg + 0x02, dstPitch >> 2);
85717a48c7cSmrg    WRXW(pPriv->reg + 0x04, scalex);
85817a48c7cSmrg    WRXW(pPriv->reg + 0x08, scaley);
85917a48c7cSmrg    pPriv->scalex = scalex;
86017a48c7cSmrg    pPriv->scaley = scaley;
86117a48c7cSmrg    if (scalex && scaley)
86217a48c7cSmrg	scale = 0x0E00;
86317a48c7cSmrg    else if (scalex)
86417a48c7cSmrg	scale = 0x0600;
86517a48c7cSmrg    else if (scaley)
86617a48c7cSmrg	scale = 0x0A00;
86717a48c7cSmrg    else
86817a48c7cSmrg	scale = 0;
86917a48c7cSmrg    switch(id) {
87017a48c7cSmrg    case 0x59595959:
87117a48c7cSmrg	pPriv->val = 0x017B | scale;
87217a48c7cSmrg	break;
87317a48c7cSmrg    case 0x32335652:
87417a48c7cSmrg	pPriv->val = 0x002F | (scale & 0xF7FF);/*Smoothing filter doesn't work*/
87517a48c7cSmrg	break;
87617a48c7cSmrg    case 0x36315652:
87717a48c7cSmrg	pPriv->val = 0x002B | (scale & 0xF7FF);
87817a48c7cSmrg	break;
87917a48c7cSmrg    case 0x35315652:
88017a48c7cSmrg	pPriv->val = 0x0029 | (scale & 0xF7FF);
88117a48c7cSmrg	break;
88217a48c7cSmrg    case 0x59555956:
88317a48c7cSmrg	pPriv->val = 0x013B | scale;
88417a48c7cSmrg	break;
88517a48c7cSmrg    case 0x55595659:
88617a48c7cSmrg	pPriv->val = 0x014B | scale;
88717a48c7cSmrg	break;
88817a48c7cSmrg    case 0x32315659:
88917a48c7cSmrg    case 0x59565955:
89017a48c7cSmrg    default:
89117a48c7cSmrg	pPriv->val = 0x016B | scale;
89217a48c7cSmrg	break;
89317a48c7cSmrg    }
89417a48c7cSmrg
89517a48c7cSmrg    (void) A(ReputImage)(pScrn, drw_x, drw_y, clipBoxes, data, pDraw);
89617a48c7cSmrg
89717a48c7cSmrg    A(WaitForFifo)(pApm, 1);
89817a48c7cSmrg    WRXW(pPriv->reg, pPriv->val);
89917a48c7cSmrg
90017a48c7cSmrg    return Success;
90117a48c7cSmrg}
90217a48c7cSmrg
90317a48c7cSmrgstatic int
90417a48c7cSmrgApmQueryImageAttributes(ScrnInfoPtr pScrn, int id,
90517a48c7cSmrg			  unsigned short *w, unsigned short *h,
90617a48c7cSmrg			  int *pitches, int *offsets)
90717a48c7cSmrg{
90817a48c7cSmrg    int size, tmp;
90917a48c7cSmrg
91017a48c7cSmrg    if(*w > 1024) *w = 1024;
91117a48c7cSmrg    if(*h > 1024) *h = 1024;
91217a48c7cSmrg
91317a48c7cSmrg    *w = (*w + 1) & ~1;
91417a48c7cSmrg    if(offsets) offsets[0] = 0;
91517a48c7cSmrg
91617a48c7cSmrg    switch(id) {
91717a48c7cSmrg    case 0x32315659:
91817a48c7cSmrg	*h = (*h + 1) & ~1;
91917a48c7cSmrg	size = (*w + 3) & ~3;
92017a48c7cSmrg	if(pitches) pitches[0] = size;
92117a48c7cSmrg	size *= *h;
92217a48c7cSmrg	if(offsets) offsets[1] = size;
92317a48c7cSmrg	tmp = ((*w >> 1) + 3) & ~3;
92417a48c7cSmrg	if(pitches) pitches[1] = pitches[2] = tmp;
92517a48c7cSmrg	tmp *= (*h >> 1);
92617a48c7cSmrg	size += tmp;
92717a48c7cSmrg	if(offsets) offsets[2] = size;
92817a48c7cSmrg	size += tmp;
92917a48c7cSmrg	break;
93017a48c7cSmrg    case 0x59565955:
93117a48c7cSmrg    case 0x55595659:
93217a48c7cSmrg    case 0x59555956:
93317a48c7cSmrg    case 0x32595559:
93417a48c7cSmrg	size = *w << 1;
93517a48c7cSmrg	goto common;
93617a48c7cSmrg    case 0x59595959:
93717a48c7cSmrg    default:
93817a48c7cSmrg	size = *w;
93917a48c7cSmrgcommon:
94017a48c7cSmrg	if (pitches)
94117a48c7cSmrg	    pitches[0] = size;
94217a48c7cSmrg	size *= *h;
94317a48c7cSmrg	break;
94417a48c7cSmrg    }
94517a48c7cSmrg
94617a48c7cSmrg    return size;
94717a48c7cSmrg}
9485c69f917Smrg
94917a48c7cSmrg#endif
950