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