105b261ecSmrg/*
205b261ecSmrg * XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com)
305b261ecSmrg */
405b261ecSmrg/*
505b261ecSmrg * Copyright (c) 1998-2003 by The XFree86 Project, Inc.
605b261ecSmrg *
705b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a
805b261ecSmrg * copy of this software and associated documentation files (the "Software"),
905b261ecSmrg * to deal in the Software without restriction, including without limitation
1005b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1105b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the
1205b261ecSmrg * Software is furnished to do so, subject to the following conditions:
1305b261ecSmrg *
1405b261ecSmrg * The above copyright notice and this permission notice shall be included in
1505b261ecSmrg * all copies or substantial portions of the Software.
1605b261ecSmrg *
1705b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1805b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1905b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2005b261ecSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
2105b261ecSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2205b261ecSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2305b261ecSmrg * OTHER DEALINGS IN THE SOFTWARE.
2405b261ecSmrg *
2505b261ecSmrg * Except as contained in this notice, the name of the copyright holder(s)
2605b261ecSmrg * and author(s) shall not be used in advertising or otherwise to promote
2705b261ecSmrg * the sale, use or other dealings in this Software without prior written
2805b261ecSmrg * authorization from the copyright holder(s) and author(s).
2905b261ecSmrg */
3005b261ecSmrg
3105b261ecSmrg#ifdef HAVE_XORG_CONFIG_H
3205b261ecSmrg#include <xorg-config.h>
3305b261ecSmrg#endif
3405b261ecSmrg
3505b261ecSmrg#include "misc.h"
3605b261ecSmrg#include "xf86.h"
3705b261ecSmrg#include "xf86_OSproc.h"
3805b261ecSmrg
3905b261ecSmrg#include <X11/X.h>
4005b261ecSmrg#include <X11/Xproto.h>
4105b261ecSmrg#include "scrnintstr.h"
4205b261ecSmrg#include "regionstr.h"
4305b261ecSmrg#include "windowstr.h"
4405b261ecSmrg#include "pixmapstr.h"
4505b261ecSmrg#include "mivalidate.h"
4605b261ecSmrg#include "validate.h"
4705b261ecSmrg#include "resource.h"
4805b261ecSmrg#include "gcstruct.h"
4905b261ecSmrg#include "dixstruct.h"
5005b261ecSmrg
5105b261ecSmrg#include <X11/extensions/Xv.h>
5205b261ecSmrg#include <X11/extensions/Xvproto.h>
5305b261ecSmrg#include "xvdix.h"
5405b261ecSmrg
5505b261ecSmrg#include "xf86xvpriv.h"
5605b261ecSmrg
5705b261ecSmrg/* XvAdaptorRec fields */
5805b261ecSmrg
5935c4bbdfSmrgstatic int xf86XVPutVideo(DrawablePtr, XvPortPtr, GCPtr,
6035c4bbdfSmrg                          INT16, INT16, CARD16, CARD16,
6135c4bbdfSmrg                          INT16, INT16, CARD16, CARD16);
6235c4bbdfSmrgstatic int xf86XVPutStill(DrawablePtr, XvPortPtr, GCPtr,
6335c4bbdfSmrg                          INT16, INT16, CARD16, CARD16,
6435c4bbdfSmrg                          INT16, INT16, CARD16, CARD16);
6535c4bbdfSmrgstatic int xf86XVGetVideo(DrawablePtr, XvPortPtr, GCPtr,
6635c4bbdfSmrg                          INT16, INT16, CARD16, CARD16,
6735c4bbdfSmrg                          INT16, INT16, CARD16, CARD16);
6835c4bbdfSmrgstatic int xf86XVGetStill(DrawablePtr, XvPortPtr, GCPtr,
6935c4bbdfSmrg                          INT16, INT16, CARD16, CARD16,
7035c4bbdfSmrg                          INT16, INT16, CARD16, CARD16);
7135c4bbdfSmrgstatic int xf86XVStopVideo(XvPortPtr, DrawablePtr);
7235c4bbdfSmrgstatic int xf86XVSetPortAttribute(XvPortPtr, Atom, INT32);
7335c4bbdfSmrgstatic int xf86XVGetPortAttribute(XvPortPtr, Atom, INT32 *);
7435c4bbdfSmrgstatic int xf86XVQueryBestSize(XvPortPtr, CARD8,
7535c4bbdfSmrg                               CARD16, CARD16, CARD16, CARD16,
7635c4bbdfSmrg                               unsigned int *, unsigned int *);
7735c4bbdfSmrgstatic int xf86XVPutImage(DrawablePtr, XvPortPtr, GCPtr,
7835c4bbdfSmrg                          INT16, INT16, CARD16, CARD16,
7935c4bbdfSmrg                          INT16, INT16, CARD16, CARD16,
8035c4bbdfSmrg                          XvImagePtr, unsigned char *, Bool, CARD16, CARD16);
8135c4bbdfSmrgstatic int xf86XVQueryImageAttributes(XvPortPtr, XvImagePtr,
8235c4bbdfSmrg                                      CARD16 *, CARD16 *, int *, int *);
8305b261ecSmrg
8405b261ecSmrg/* ScreenRec fields */
8505b261ecSmrg
8605b261ecSmrgstatic Bool xf86XVDestroyWindow(WindowPtr pWin);
8735c4bbdfSmrgstatic void xf86XVWindowExposures(WindowPtr pWin, RegionPtr r1);
8835c4bbdfSmrgstatic void xf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin,
8935c4bbdfSmrg                                   VTKind kind);
9005b261ecSmrgstatic void xf86XVClipNotify(WindowPtr pWin, int dx, int dy);
9135c4bbdfSmrgstatic Bool xf86XVCloseScreen(ScreenPtr);
9205b261ecSmrg
939ace9065Smrg#define PostValidateTreeUndefined ((PostValidateTreeProcPtr)-1)
949ace9065Smrg
9505b261ecSmrg/* ScrnInfoRec functions */
9605b261ecSmrg
9735c4bbdfSmrgstatic Bool xf86XVEnterVT(ScrnInfoPtr);
9835c4bbdfSmrgstatic void xf86XVLeaveVT(ScrnInfoPtr);
9935c4bbdfSmrgstatic void xf86XVAdjustFrame(ScrnInfoPtr, int x, int y);
1009ace9065Smrgstatic void xf86XVModeSet(ScrnInfoPtr pScrn);
10105b261ecSmrg
10205b261ecSmrg/* misc */
10305b261ecSmrg
10435c4bbdfSmrgstatic Bool xf86XVInitAdaptors(ScreenPtr, XF86VideoAdaptorPtr *, int);
10505b261ecSmrg
1066747b715Smrgstatic DevPrivateKeyRec XF86XVWindowKeyRec;
10735c4bbdfSmrg
1086747b715Smrg#define XF86XVWindowKey (&XF86XVWindowKeyRec)
1096747b715Smrg
11035c4bbdfSmrg/* dixmain.c XvScreenPtr screen private */
1116747b715SmrgDevPrivateKey XF86XvScreenKey;
11235c4bbdfSmrg/** xf86xv.c XF86XVScreenPtr screen private */
11335c4bbdfSmrgstatic DevPrivateKeyRec XF86XVScreenPrivateKey;
1146747b715Smrg
11505b261ecSmrgstatic unsigned long PortResource = 0;
11605b261ecSmrg
11705b261ecSmrg#define GET_XV_SCREEN(pScreen) \
1184642e01fSmrg    ((XvScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, XF86XvScreenKey))
11905b261ecSmrg
12005b261ecSmrg#define GET_XF86XV_SCREEN(pScreen) \
12135c4bbdfSmrg    ((XF86XVScreenPtr)(dixGetPrivate(&pScreen->devPrivates, &XF86XVScreenPrivateKey)))
12205b261ecSmrg
12305b261ecSmrg#define GET_XF86XV_WINDOW(pWin) \
1244642e01fSmrg    ((XF86XVWindowPtr)dixLookupPrivate(&(pWin)->devPrivates, XF86XVWindowKey))
12505b261ecSmrg
12605b261ecSmrgstatic xf86XVInitGenericAdaptorPtr *GenDrivers = NULL;
12705b261ecSmrgstatic int NumGenDrivers = 0;
12805b261ecSmrg
1296747b715Smrgint
13035c4bbdfSmrgxf86XVRegisterGenericAdaptorDriver(xf86XVInitGenericAdaptorPtr InitFunc)
13135c4bbdfSmrg{
13235c4bbdfSmrg    xf86XVInitGenericAdaptorPtr *newdrivers;
13305b261ecSmrg
13435c4bbdfSmrg    newdrivers = reallocarray(GenDrivers, 1 + NumGenDrivers,
13535c4bbdfSmrg                              sizeof(xf86XVInitGenericAdaptorPtr));
13635c4bbdfSmrg    if (!newdrivers)
13735c4bbdfSmrg        return 0;
13835c4bbdfSmrg    GenDrivers = newdrivers;
13905b261ecSmrg
14035c4bbdfSmrg    GenDrivers[NumGenDrivers++] = InitFunc;
14105b261ecSmrg
14235c4bbdfSmrg    return 1;
14305b261ecSmrg}
14405b261ecSmrg
1456747b715Smrgint
14635c4bbdfSmrgxf86XVListGenericAdaptors(ScrnInfoPtr pScrn, XF86VideoAdaptorPtr ** adaptors)
14735c4bbdfSmrg{
14835c4bbdfSmrg    int i, j, n, num;
14935c4bbdfSmrg    XF86VideoAdaptorPtr *DrivAdap, *new;
15005b261ecSmrg
15105b261ecSmrg    num = 0;
15205b261ecSmrg    *adaptors = NULL;
15305b261ecSmrg    /*
15405b261ecSmrg     * The v4l driver registers itself first, but can use surfaces registered
15505b261ecSmrg     * by other drivers.  So, call the v4l driver last.
15605b261ecSmrg     */
15735c4bbdfSmrg    for (i = NumGenDrivers; --i >= 0;) {
15835c4bbdfSmrg        DrivAdap = NULL;
15935c4bbdfSmrg        n = (*GenDrivers[i]) (pScrn, &DrivAdap);
16035c4bbdfSmrg        if (0 == n)
16135c4bbdfSmrg            continue;
16235c4bbdfSmrg        new = reallocarray(*adaptors, num + n, sizeof(XF86VideoAdaptorPtr));
16335c4bbdfSmrg        if (NULL == new)
16435c4bbdfSmrg            continue;
16535c4bbdfSmrg        *adaptors = new;
16635c4bbdfSmrg        for (j = 0; j < n; j++, num++)
16735c4bbdfSmrg            (*adaptors)[num] = DrivAdap[j];
16805b261ecSmrg    }
16905b261ecSmrg    return num;
17005b261ecSmrg}
17105b261ecSmrg
17205b261ecSmrg/****************  Offscreen surface stuff *******************/
17305b261ecSmrg
17405b261ecSmrgtypedef struct {
17535c4bbdfSmrg    XF86OffscreenImagePtr images;
17635c4bbdfSmrg    int num;
17705b261ecSmrg} OffscreenImageRec;
17805b261ecSmrg
1796747b715Smrgstatic DevPrivateKeyRec OffscreenPrivateKeyRec;
18035c4bbdfSmrg
1816747b715Smrg#define OffscreenPrivateKey (&OffscreenPrivateKeyRec)
1826747b715Smrg#define GetOffscreenImage(pScreen) ((OffscreenImageRec *) dixLookupPrivate(&(pScreen)->devPrivates, OffscreenPrivateKey))
18305b261ecSmrg
1846747b715SmrgBool
18535c4bbdfSmrgxf86XVRegisterOffscreenImages(ScreenPtr pScreen,
18635c4bbdfSmrg                              XF86OffscreenImagePtr images, int num)
18735c4bbdfSmrg{
1886747b715Smrg    OffscreenImageRec *OffscreenImage;
18935c4bbdfSmrg
1906747b715Smrg    /* This function may be called before xf86XVScreenInit, so there's
1916747b715Smrg     * no better place than this to call dixRegisterPrivateKey to ensure we
1926747b715Smrg     * have space reserved. After the first call it is a no-op. */
19335c4bbdfSmrg    if (!dixRegisterPrivateKey
19435c4bbdfSmrg        (OffscreenPrivateKey, PRIVATE_SCREEN, sizeof(OffscreenImageRec)) ||
19535c4bbdfSmrg        !(OffscreenImage = GetOffscreenImage(pScreen)))
1966747b715Smrg        /* Every X.org driver assumes this function always succeeds, so
1976747b715Smrg         * just die on allocation failure. */
19835c4bbdfSmrg        FatalError
19935c4bbdfSmrg            ("Could not allocate private storage for XV offscreen images.\n");
2006747b715Smrg
2016747b715Smrg    OffscreenImage->num = num;
2026747b715Smrg    OffscreenImage->images = images;
20305b261ecSmrg    return TRUE;
20405b261ecSmrg}
20505b261ecSmrg
2066747b715SmrgXF86OffscreenImagePtr
20735c4bbdfSmrgxf86XVQueryOffscreenImages(ScreenPtr pScreen, int *num)
20835c4bbdfSmrg{
2096747b715Smrg    OffscreenImageRec *OffscreenImage = GetOffscreenImage(pScreen);
21035c4bbdfSmrg
2116747b715Smrg    *num = OffscreenImage->num;
2126747b715Smrg    return OffscreenImage->images;
21305b261ecSmrg}
21405b261ecSmrg
2156747b715SmrgXF86VideoAdaptorPtr
21605b261ecSmrgxf86XVAllocateVideoAdaptorRec(ScrnInfoPtr pScrn)
21705b261ecSmrg{
2186747b715Smrg    return calloc(1, sizeof(XF86VideoAdaptorRec));
21905b261ecSmrg}
22005b261ecSmrg
2216747b715Smrgvoid
22205b261ecSmrgxf86XVFreeVideoAdaptorRec(XF86VideoAdaptorPtr ptr)
22305b261ecSmrg{
2246747b715Smrg    free(ptr);
22505b261ecSmrg}
22605b261ecSmrg
2276747b715SmrgBool
22835c4bbdfSmrgxf86XVScreenInit(ScreenPtr pScreen, XF86VideoAdaptorPtr * adaptors, int num)
22935c4bbdfSmrg{
23035c4bbdfSmrg    ScrnInfoPtr pScrn;
23135c4bbdfSmrg    XF86XVScreenPtr ScreenPriv;
2326747b715Smrg
23335c4bbdfSmrg    if (num <= 0 || noXvExtension)
23435c4bbdfSmrg        return FALSE;
23505b261ecSmrg
23635c4bbdfSmrg    if (Success != XvScreenInit(pScreen))
23735c4bbdfSmrg        return FALSE;
23805b261ecSmrg
23935c4bbdfSmrg    if (!dixRegisterPrivateKey(&XF86XVWindowKeyRec, PRIVATE_WINDOW, 0))
24035c4bbdfSmrg        return FALSE;
24135c4bbdfSmrg    if (!dixRegisterPrivateKey(&XF86XVScreenPrivateKey, PRIVATE_SCREEN, 0))
24235c4bbdfSmrg        return FALSE;
24305b261ecSmrg
24435c4bbdfSmrg    XF86XvScreenKey = XvGetScreenKey();
24505b261ecSmrg
24635c4bbdfSmrg    PortResource = XvGetRTPort();
24705b261ecSmrg
24835c4bbdfSmrg    ScreenPriv = malloc(sizeof(XF86XVScreenRec));
24935c4bbdfSmrg    dixSetPrivate(&pScreen->devPrivates, &XF86XVScreenPrivateKey, ScreenPriv);
25005b261ecSmrg
25135c4bbdfSmrg    if (!ScreenPriv)
25235c4bbdfSmrg        return FALSE;
25305b261ecSmrg
25435c4bbdfSmrg    pScrn = xf86ScreenToScrn(pScreen);
25505b261ecSmrg
25635c4bbdfSmrg    ScreenPriv->DestroyWindow = pScreen->DestroyWindow;
25735c4bbdfSmrg    ScreenPriv->WindowExposures = pScreen->WindowExposures;
25835c4bbdfSmrg    ScreenPriv->PostValidateTree = PostValidateTreeUndefined;
25935c4bbdfSmrg    ScreenPriv->ClipNotify = pScreen->ClipNotify;
26035c4bbdfSmrg    ScreenPriv->CloseScreen = pScreen->CloseScreen;
26135c4bbdfSmrg    ScreenPriv->EnterVT = pScrn->EnterVT;
26235c4bbdfSmrg    ScreenPriv->LeaveVT = pScrn->LeaveVT;
26335c4bbdfSmrg    ScreenPriv->AdjustFrame = pScrn->AdjustFrame;
26435c4bbdfSmrg    ScreenPriv->ModeSet = pScrn->ModeSet;
26505b261ecSmrg
26635c4bbdfSmrg    pScreen->DestroyWindow = xf86XVDestroyWindow;
26735c4bbdfSmrg    pScreen->WindowExposures = xf86XVWindowExposures;
26835c4bbdfSmrg    pScreen->ClipNotify = xf86XVClipNotify;
26935c4bbdfSmrg    pScreen->CloseScreen = xf86XVCloseScreen;
27035c4bbdfSmrg    pScrn->EnterVT = xf86XVEnterVT;
27135c4bbdfSmrg    pScrn->LeaveVT = xf86XVLeaveVT;
27235c4bbdfSmrg    if (pScrn->AdjustFrame)
27335c4bbdfSmrg        pScrn->AdjustFrame = xf86XVAdjustFrame;
27435c4bbdfSmrg    pScrn->ModeSet = xf86XVModeSet;
27505b261ecSmrg
27635c4bbdfSmrg    if (!xf86XVInitAdaptors(pScreen, adaptors, num))
27735c4bbdfSmrg        return FALSE;
27805b261ecSmrg
27935c4bbdfSmrg    return TRUE;
28005b261ecSmrg}
28105b261ecSmrg
28205b261ecSmrgstatic void
28305b261ecSmrgxf86XVFreeAdaptor(XvAdaptorPtr pAdaptor)
28405b261ecSmrg{
28535c4bbdfSmrg    int i;
28635c4bbdfSmrg
28735c4bbdfSmrg    if (pAdaptor->pPorts) {
28835c4bbdfSmrg        XvPortPtr pPort = pAdaptor->pPorts;
28935c4bbdfSmrg        XvPortRecPrivatePtr pPriv;
29035c4bbdfSmrg
29135c4bbdfSmrg        for (i = 0; i < pAdaptor->nPorts; i++, pPort++) {
29235c4bbdfSmrg            pPriv = (XvPortRecPrivatePtr) pPort->devPriv.ptr;
29335c4bbdfSmrg            if (pPriv) {
29435c4bbdfSmrg                if (pPriv->clientClip)
29535c4bbdfSmrg                    RegionDestroy(pPriv->clientClip);
29635c4bbdfSmrg                if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
29735c4bbdfSmrg                    RegionDestroy(pPriv->pCompositeClip);
29835c4bbdfSmrg                if (pPriv->ckeyFilled)
29935c4bbdfSmrg                    RegionDestroy(pPriv->ckeyFilled);
30035c4bbdfSmrg                free(pPriv);
30135c4bbdfSmrg            }
30235c4bbdfSmrg        }
30335c4bbdfSmrg    }
30435c4bbdfSmrg
30535c4bbdfSmrg    XvFreeAdaptor(pAdaptor);
30605b261ecSmrg}
30705b261ecSmrg
30805b261ecSmrgstatic Bool
30935c4bbdfSmrgxf86XVInitAdaptors(ScreenPtr pScreen, XF86VideoAdaptorPtr * infoPtr, int number)
31035c4bbdfSmrg{
31135c4bbdfSmrg    XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
31235c4bbdfSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
31335c4bbdfSmrg    XF86VideoAdaptorPtr adaptorPtr;
31435c4bbdfSmrg    XvAdaptorPtr pAdaptor, pa;
31535c4bbdfSmrg    XvAdaptorRecPrivatePtr adaptorPriv;
31635c4bbdfSmrg    int na, numAdaptor;
31735c4bbdfSmrg    XvPortRecPrivatePtr portPriv;
31835c4bbdfSmrg    XvPortPtr pPort, pp;
31935c4bbdfSmrg    int numPort;
32035c4bbdfSmrg    XF86VideoFormatPtr formatPtr;
32135c4bbdfSmrg    XvFormatPtr pFormat, pf;
32235c4bbdfSmrg    int numFormat, totFormat;
32335c4bbdfSmrg    XF86VideoEncodingPtr encodingPtr;
32435c4bbdfSmrg    XvEncodingPtr pEncode, pe;
32535c4bbdfSmrg    int numVisuals;
32635c4bbdfSmrg    VisualPtr pVisual;
32735c4bbdfSmrg    int i;
32835c4bbdfSmrg
32935c4bbdfSmrg    pxvs->nAdaptors = 0;
33035c4bbdfSmrg    pxvs->pAdaptors = NULL;
33135c4bbdfSmrg
33235c4bbdfSmrg    if (!(pAdaptor = calloc(number, sizeof(XvAdaptorRec))))
33335c4bbdfSmrg        return FALSE;
33435c4bbdfSmrg
33535c4bbdfSmrg    for (pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) {
33635c4bbdfSmrg        adaptorPtr = infoPtr[na];
33735c4bbdfSmrg
33835c4bbdfSmrg        if (!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute ||
33935c4bbdfSmrg            !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize)
34035c4bbdfSmrg            continue;
34135c4bbdfSmrg
34235c4bbdfSmrg        /* client libs expect at least one encoding */
34335c4bbdfSmrg        if (!adaptorPtr->nEncodings || !adaptorPtr->pEncodings)
34435c4bbdfSmrg            continue;
34535c4bbdfSmrg
34635c4bbdfSmrg        pa->type = adaptorPtr->type;
34735c4bbdfSmrg
34835c4bbdfSmrg        if (!adaptorPtr->PutVideo && !adaptorPtr->GetVideo)
34935c4bbdfSmrg            pa->type &= ~XvVideoMask;
35035c4bbdfSmrg
35135c4bbdfSmrg        if (!adaptorPtr->PutStill && !adaptorPtr->GetStill)
35235c4bbdfSmrg            pa->type &= ~XvStillMask;
35335c4bbdfSmrg
35435c4bbdfSmrg        if (!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes)
35535c4bbdfSmrg            pa->type &= ~XvImageMask;
35635c4bbdfSmrg
35735c4bbdfSmrg        if (!adaptorPtr->PutVideo && !adaptorPtr->PutImage &&
35835c4bbdfSmrg            !adaptorPtr->PutStill)
35935c4bbdfSmrg            pa->type &= ~XvInputMask;
36035c4bbdfSmrg
36135c4bbdfSmrg        if (!adaptorPtr->GetVideo && !adaptorPtr->GetStill)
36235c4bbdfSmrg            pa->type &= ~XvOutputMask;
36335c4bbdfSmrg
36435c4bbdfSmrg        if (!(adaptorPtr->type & (XvPixmapMask | XvWindowMask)))
36535c4bbdfSmrg            continue;
36635c4bbdfSmrg        if (!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask)))
36735c4bbdfSmrg            continue;
36835c4bbdfSmrg
36935c4bbdfSmrg        pa->pScreen = pScreen;
37035c4bbdfSmrg        pa->ddPutVideo = xf86XVPutVideo;
37135c4bbdfSmrg        pa->ddPutStill = xf86XVPutStill;
37235c4bbdfSmrg        pa->ddGetVideo = xf86XVGetVideo;
37335c4bbdfSmrg        pa->ddGetStill = xf86XVGetStill;
37435c4bbdfSmrg        pa->ddStopVideo = xf86XVStopVideo;
37535c4bbdfSmrg        pa->ddPutImage = xf86XVPutImage;
37635c4bbdfSmrg        pa->ddSetPortAttribute = xf86XVSetPortAttribute;
37735c4bbdfSmrg        pa->ddGetPortAttribute = xf86XVGetPortAttribute;
37835c4bbdfSmrg        pa->ddQueryBestSize = xf86XVQueryBestSize;
37935c4bbdfSmrg        pa->ddQueryImageAttributes = xf86XVQueryImageAttributes;
38035c4bbdfSmrg        pa->name = strdup(adaptorPtr->name);
38135c4bbdfSmrg
38235c4bbdfSmrg        if (adaptorPtr->nEncodings &&
38335c4bbdfSmrg            (pEncode = calloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) {
38435c4bbdfSmrg
38535c4bbdfSmrg            for (pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0;
38635c4bbdfSmrg                 i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++) {
38735c4bbdfSmrg                pe->id = encodingPtr->id;
38835c4bbdfSmrg                pe->pScreen = pScreen;
38935c4bbdfSmrg                pe->name = strdup(encodingPtr->name);
39035c4bbdfSmrg                pe->width = encodingPtr->width;
39135c4bbdfSmrg                pe->height = encodingPtr->height;
39235c4bbdfSmrg                pe->rate.numerator = encodingPtr->rate.numerator;
39335c4bbdfSmrg                pe->rate.denominator = encodingPtr->rate.denominator;
39435c4bbdfSmrg            }
39535c4bbdfSmrg            pa->nEncodings = adaptorPtr->nEncodings;
39635c4bbdfSmrg            pa->pEncodings = pEncode;
39735c4bbdfSmrg        }
39835c4bbdfSmrg
39935c4bbdfSmrg        if (adaptorPtr->nImages &&
40035c4bbdfSmrg            (pa->pImages = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
40135c4bbdfSmrg            memcpy(pa->pImages, adaptorPtr->pImages,
40235c4bbdfSmrg                   adaptorPtr->nImages * sizeof(XvImageRec));
40335c4bbdfSmrg            pa->nImages = adaptorPtr->nImages;
40435c4bbdfSmrg        }
40535c4bbdfSmrg
40635c4bbdfSmrg        if (adaptorPtr->nAttributes &&
40735c4bbdfSmrg            (pa->pAttributes = calloc(adaptorPtr->nAttributes,
40835c4bbdfSmrg                                      sizeof(XvAttributeRec)))) {
40935c4bbdfSmrg            memcpy(pa->pAttributes, adaptorPtr->pAttributes,
41035c4bbdfSmrg                   adaptorPtr->nAttributes * sizeof(XvAttributeRec));
41135c4bbdfSmrg
41235c4bbdfSmrg            for (i = 0; i < adaptorPtr->nAttributes; i++) {
41335c4bbdfSmrg                pa->pAttributes[i].name =
41435c4bbdfSmrg                    strdup(adaptorPtr->pAttributes[i].name);
41535c4bbdfSmrg            }
41635c4bbdfSmrg
41735c4bbdfSmrg            pa->nAttributes = adaptorPtr->nAttributes;
41835c4bbdfSmrg        }
41935c4bbdfSmrg
42035c4bbdfSmrg        totFormat = adaptorPtr->nFormats;
42135c4bbdfSmrg
42235c4bbdfSmrg        if (!(pFormat = calloc(totFormat, sizeof(XvFormatRec)))) {
42335c4bbdfSmrg            xf86XVFreeAdaptor(pa);
42435c4bbdfSmrg            continue;
42535c4bbdfSmrg        }
42635c4bbdfSmrg        for (pf = pFormat, i = 0, numFormat = 0, formatPtr =
42735c4bbdfSmrg             adaptorPtr->pFormats; i < adaptorPtr->nFormats; i++, formatPtr++) {
42835c4bbdfSmrg            numVisuals = pScreen->numVisuals;
42935c4bbdfSmrg            pVisual = pScreen->visuals;
43035c4bbdfSmrg
43135c4bbdfSmrg            while (numVisuals--) {
43235c4bbdfSmrg                if ((pVisual->class == formatPtr->class) &&
43335c4bbdfSmrg                    (pVisual->nplanes == formatPtr->depth)) {
43435c4bbdfSmrg
43535c4bbdfSmrg                    if (numFormat >= totFormat) {
43635c4bbdfSmrg                        void *moreSpace;
43735c4bbdfSmrg
43835c4bbdfSmrg                        totFormat *= 2;
43935c4bbdfSmrg                        moreSpace = reallocarray(pFormat, totFormat,
44035c4bbdfSmrg                                                 sizeof(XvFormatRec));
44135c4bbdfSmrg                        if (!moreSpace)
44235c4bbdfSmrg                            break;
44335c4bbdfSmrg                        pFormat = moreSpace;
44435c4bbdfSmrg                        pf = pFormat + numFormat;
44535c4bbdfSmrg                    }
44635c4bbdfSmrg
44735c4bbdfSmrg                    pf->visual = pVisual->vid;
44835c4bbdfSmrg                    pf->depth = formatPtr->depth;
44935c4bbdfSmrg
45035c4bbdfSmrg                    pf++;
45135c4bbdfSmrg                    numFormat++;
45235c4bbdfSmrg                }
45335c4bbdfSmrg                pVisual++;
45435c4bbdfSmrg            }
45535c4bbdfSmrg        }
45635c4bbdfSmrg        pa->nFormats = numFormat;
45735c4bbdfSmrg        pa->pFormats = pFormat;
45835c4bbdfSmrg        if (!numFormat) {
45935c4bbdfSmrg            xf86XVFreeAdaptor(pa);
46035c4bbdfSmrg            continue;
46135c4bbdfSmrg        }
46235c4bbdfSmrg
46335c4bbdfSmrg        if (!(adaptorPriv = calloc(1, sizeof(XvAdaptorRecPrivate)))) {
46435c4bbdfSmrg            xf86XVFreeAdaptor(pa);
46535c4bbdfSmrg            continue;
46635c4bbdfSmrg        }
46735c4bbdfSmrg
46835c4bbdfSmrg        adaptorPriv->flags = adaptorPtr->flags;
46935c4bbdfSmrg        adaptorPriv->PutVideo = adaptorPtr->PutVideo;
47035c4bbdfSmrg        adaptorPriv->PutStill = adaptorPtr->PutStill;
47135c4bbdfSmrg        adaptorPriv->GetVideo = adaptorPtr->GetVideo;
47235c4bbdfSmrg        adaptorPriv->GetStill = adaptorPtr->GetStill;
47335c4bbdfSmrg        adaptorPriv->StopVideo = adaptorPtr->StopVideo;
47435c4bbdfSmrg        adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute;
47535c4bbdfSmrg        adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute;
47635c4bbdfSmrg        adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize;
47735c4bbdfSmrg        adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes;
47835c4bbdfSmrg        adaptorPriv->PutImage = adaptorPtr->PutImage;
47935c4bbdfSmrg        adaptorPriv->ReputImage = adaptorPtr->ReputImage;       /* image/still */
48035c4bbdfSmrg
48135c4bbdfSmrg        pa->devPriv.ptr = (void *) adaptorPriv;
48235c4bbdfSmrg
48335c4bbdfSmrg        if (!(pPort = calloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) {
48435c4bbdfSmrg            xf86XVFreeAdaptor(pa);
48535c4bbdfSmrg            continue;
48635c4bbdfSmrg        }
48735c4bbdfSmrg        for (pp = pPort, i = 0, numPort = 0; i < adaptorPtr->nPorts; i++) {
48835c4bbdfSmrg
48935c4bbdfSmrg            if (!(pp->id = FakeClientID(0)))
49035c4bbdfSmrg                continue;
49135c4bbdfSmrg
49235c4bbdfSmrg            if (!(portPriv = calloc(1, sizeof(XvPortRecPrivate))))
49335c4bbdfSmrg                continue;
49435c4bbdfSmrg
49535c4bbdfSmrg            if (!AddResource(pp->id, PortResource, pp)) {
49635c4bbdfSmrg                free(portPriv);
49735c4bbdfSmrg                continue;
49835c4bbdfSmrg            }
49935c4bbdfSmrg
50035c4bbdfSmrg            pp->pAdaptor = pa;
50135c4bbdfSmrg            pp->pNotify = (XvPortNotifyPtr) NULL;
50235c4bbdfSmrg            pp->pDraw = (DrawablePtr) NULL;
50335c4bbdfSmrg            pp->client = (ClientPtr) NULL;
50435c4bbdfSmrg            pp->grab.client = (ClientPtr) NULL;
50535c4bbdfSmrg            pp->time = currentTime;
50635c4bbdfSmrg            pp->devPriv.ptr = portPriv;
50735c4bbdfSmrg
50835c4bbdfSmrg            portPriv->pScrn = pScrn;
50935c4bbdfSmrg            portPriv->AdaptorRec = adaptorPriv;
51035c4bbdfSmrg            portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr;
51135c4bbdfSmrg
51235c4bbdfSmrg            pp++;
51335c4bbdfSmrg            numPort++;
51435c4bbdfSmrg        }
51535c4bbdfSmrg        pa->nPorts = numPort;
51635c4bbdfSmrg        pa->pPorts = pPort;
51735c4bbdfSmrg        if (!numPort) {
51835c4bbdfSmrg            xf86XVFreeAdaptor(pa);
51935c4bbdfSmrg            continue;
52035c4bbdfSmrg        }
52135c4bbdfSmrg
52235c4bbdfSmrg        pa->base_id = pPort->id;
52335c4bbdfSmrg
52435c4bbdfSmrg        pa++;
52535c4bbdfSmrg        numAdaptor++;
52635c4bbdfSmrg    }
52735c4bbdfSmrg
52835c4bbdfSmrg    if (numAdaptor) {
52935c4bbdfSmrg        pxvs->nAdaptors = numAdaptor;
53035c4bbdfSmrg        pxvs->pAdaptors = pAdaptor;
53135c4bbdfSmrg    }
53235c4bbdfSmrg    else {
53335c4bbdfSmrg        free(pAdaptor);
53435c4bbdfSmrg        return FALSE;
53535c4bbdfSmrg    }
53635c4bbdfSmrg
53735c4bbdfSmrg    return TRUE;
53805b261ecSmrg}
53905b261ecSmrg
54005b261ecSmrg/* Video should be clipped to the intersection of the window cliplist
54105b261ecSmrg   and the client cliplist specified in the GC for which the video was
54205b261ecSmrg   initialized.  When we need to reclip a window, the GC that started
54305b261ecSmrg   the video may not even be around anymore.  That's why we save the
54405b261ecSmrg   client clip from the GC when the video is initialized.  We then
54505b261ecSmrg   use xf86XVUpdateCompositeClip to calculate the new composite clip
54605b261ecSmrg   when we need it.  This is different from what DEC did.  They saved
547ed6184dfSmrg   the GC and used its clip list when they needed to reclip the window,
54805b261ecSmrg   even if the client clip was different from the one the video was
54905b261ecSmrg   initialized with.  If the original GC was destroyed, they had to stop
55005b261ecSmrg   the video.  I like the new method better (MArk).
55105b261ecSmrg
55205b261ecSmrg   This function only works for windows.  Will need to rewrite when
55305b261ecSmrg   (if) we support pixmap rendering.
55405b261ecSmrg*/
55505b261ecSmrg
55605b261ecSmrgstatic void
55705b261ecSmrgxf86XVUpdateCompositeClip(XvPortRecPrivatePtr portPriv)
55805b261ecSmrg{
55935c4bbdfSmrg    RegionPtr pregWin, pCompositeClip;
56035c4bbdfSmrg    WindowPtr pWin;
56135c4bbdfSmrg    Bool freeCompClip = FALSE;
56235c4bbdfSmrg
56335c4bbdfSmrg    if (portPriv->pCompositeClip)
56435c4bbdfSmrg        return;
56535c4bbdfSmrg
56635c4bbdfSmrg    pWin = (WindowPtr) portPriv->pDraw;
56735c4bbdfSmrg
56835c4bbdfSmrg    /* get window clip list */
56935c4bbdfSmrg    if (portPriv->subWindowMode == IncludeInferiors) {
57035c4bbdfSmrg        pregWin = NotClippedByChildren(pWin);
57135c4bbdfSmrg        freeCompClip = TRUE;
57235c4bbdfSmrg    }
57335c4bbdfSmrg    else
57435c4bbdfSmrg        pregWin = &pWin->clipList;
57535c4bbdfSmrg
57635c4bbdfSmrg    if (!portPriv->clientClip) {
57735c4bbdfSmrg        portPriv->pCompositeClip = pregWin;
57835c4bbdfSmrg        portPriv->FreeCompositeClip = freeCompClip;
57935c4bbdfSmrg        return;
58035c4bbdfSmrg    }
58135c4bbdfSmrg
58235c4bbdfSmrg    pCompositeClip = RegionCreate(NullBox, 1);
58335c4bbdfSmrg    RegionCopy(pCompositeClip, portPriv->clientClip);
58435c4bbdfSmrg    RegionTranslate(pCompositeClip, portPriv->pDraw->x, portPriv->pDraw->y);
58535c4bbdfSmrg    RegionIntersect(pCompositeClip, pregWin, pCompositeClip);
58635c4bbdfSmrg
58735c4bbdfSmrg    portPriv->pCompositeClip = pCompositeClip;
58835c4bbdfSmrg    portPriv->FreeCompositeClip = TRUE;
58935c4bbdfSmrg
59035c4bbdfSmrg    if (freeCompClip) {
59135c4bbdfSmrg        RegionDestroy(pregWin);
59235c4bbdfSmrg    }
59305b261ecSmrg}
59405b261ecSmrg
59505b261ecSmrg/* Save the current clientClip and update the CompositeClip whenever
59605b261ecSmrg   we have a fresh GC */
59705b261ecSmrg
59805b261ecSmrgstatic void
59935c4bbdfSmrgxf86XVCopyClip(XvPortRecPrivatePtr portPriv, GCPtr pGC)
60035c4bbdfSmrg{
60105b261ecSmrg    /* copy the new clip if it exists */
60235c4bbdfSmrg    if (pGC->clientClip) {
60335c4bbdfSmrg        if (!portPriv->clientClip)
60435c4bbdfSmrg            portPriv->clientClip = RegionCreate(NullBox, 1);
60535c4bbdfSmrg        /* Note: this is in window coordinates */
60635c4bbdfSmrg        RegionCopy(portPriv->clientClip, pGC->clientClip);
60735c4bbdfSmrg        RegionTranslate(portPriv->clientClip, pGC->clipOrg.x, pGC->clipOrg.y);
60835c4bbdfSmrg    }
60935c4bbdfSmrg    else if (portPriv->clientClip) {    /* free the old clientClip */
61035c4bbdfSmrg        RegionDestroy(portPriv->clientClip);
61135c4bbdfSmrg        portPriv->clientClip = NULL;
61205b261ecSmrg    }
61305b261ecSmrg
61405b261ecSmrg    /* get rid of the old clip list */
61535c4bbdfSmrg    if (portPriv->pCompositeClip && portPriv->FreeCompositeClip) {
61635c4bbdfSmrg        RegionDestroy(portPriv->pCompositeClip);
61705b261ecSmrg    }
61805b261ecSmrg
6199ace9065Smrg    portPriv->pCompositeClip = pGC->pCompositeClip;
6209ace9065Smrg    portPriv->FreeCompositeClip = FALSE;
6219ace9065Smrg    portPriv->subWindowMode = pGC->subWindowMode;
6229ace9065Smrg}
6239ace9065Smrg
6249ace9065Smrgstatic void
6259ace9065Smrgxf86XVCopyCompositeClip(XvPortRecPrivatePtr portPriv,
62635c4bbdfSmrg                        GCPtr pGC, DrawablePtr pDraw)
6279ace9065Smrg{
6289ace9065Smrg    if (!portPriv->clientClip)
62935c4bbdfSmrg        portPriv->clientClip = RegionCreate(NullBox, 1);
6309ace9065Smrg    /* Keep the original GC composite clip around for ReputImage */
6319ace9065Smrg    RegionCopy(portPriv->clientClip, pGC->pCompositeClip);
63235c4bbdfSmrg    RegionTranslate(portPriv->clientClip, -pDraw->x, -pDraw->y);
6339ace9065Smrg
6349ace9065Smrg    /* get rid of the old clip list */
6359ace9065Smrg    if (portPriv->pCompositeClip && portPriv->FreeCompositeClip)
63635c4bbdfSmrg        RegionDestroy(portPriv->pCompositeClip);
6379ace9065Smrg
63805b261ecSmrg    portPriv->pCompositeClip = pGC->pCompositeClip;
63905b261ecSmrg    portPriv->FreeCompositeClip = FALSE;
64005b261ecSmrg    portPriv->subWindowMode = pGC->subWindowMode;
64105b261ecSmrg}
64205b261ecSmrg
64305b261ecSmrgstatic int
64405b261ecSmrgxf86XVRegetVideo(XvPortRecPrivatePtr portPriv)
64505b261ecSmrg{
64635c4bbdfSmrg    RegionRec WinRegion;
64735c4bbdfSmrg    RegionRec ClipRegion;
64835c4bbdfSmrg    BoxRec WinBox;
64935c4bbdfSmrg    int ret = Success;
65035c4bbdfSmrg    Bool clippedAway = FALSE;
65135c4bbdfSmrg
65235c4bbdfSmrg    xf86XVUpdateCompositeClip(portPriv);
65335c4bbdfSmrg
65435c4bbdfSmrg    /* translate the video region to the screen */
65535c4bbdfSmrg    WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
65635c4bbdfSmrg    WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
65735c4bbdfSmrg    WinBox.x2 = WinBox.x1 + portPriv->drw_w;
65835c4bbdfSmrg    WinBox.y2 = WinBox.y1 + portPriv->drw_h;
65935c4bbdfSmrg
66035c4bbdfSmrg    /* clip to the window composite clip */
66135c4bbdfSmrg    RegionInit(&WinRegion, &WinBox, 1);
66235c4bbdfSmrg    RegionNull(&ClipRegion);
66335c4bbdfSmrg    RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
66435c4bbdfSmrg
66535c4bbdfSmrg    /* that's all if it's totally obscured */
66635c4bbdfSmrg    if (!RegionNotEmpty(&ClipRegion)) {
66735c4bbdfSmrg        clippedAway = TRUE;
66835c4bbdfSmrg        goto CLIP_VIDEO_BAILOUT;
66935c4bbdfSmrg    }
67035c4bbdfSmrg
67135c4bbdfSmrg    ret = (*portPriv->AdaptorRec->GetVideo) (portPriv->pScrn,
67235c4bbdfSmrg                                             portPriv->vid_x, portPriv->vid_y,
67335c4bbdfSmrg                                             WinBox.x1, WinBox.y1,
67435c4bbdfSmrg                                             portPriv->vid_w, portPriv->vid_h,
67535c4bbdfSmrg                                             portPriv->drw_w, portPriv->drw_h,
67635c4bbdfSmrg                                             &ClipRegion, portPriv->DevPriv.ptr,
67735c4bbdfSmrg                                             portPriv->pDraw);
67835c4bbdfSmrg
67935c4bbdfSmrg    if (ret == Success)
68035c4bbdfSmrg        portPriv->isOn = XV_ON;
68135c4bbdfSmrg
68235c4bbdfSmrg CLIP_VIDEO_BAILOUT:
68305b261ecSmrg
68435c4bbdfSmrg    if ((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) {
68535c4bbdfSmrg        (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
68635c4bbdfSmrg                                            portPriv->DevPriv.ptr, FALSE);
68735c4bbdfSmrg        portPriv->isOn = XV_PENDING;
68835c4bbdfSmrg    }
68935c4bbdfSmrg
69035c4bbdfSmrg    /* This clip was copied and only good for one shot */
69135c4bbdfSmrg    if (!portPriv->FreeCompositeClip)
69235c4bbdfSmrg        portPriv->pCompositeClip = NULL;
69335c4bbdfSmrg
69435c4bbdfSmrg    RegionUninit(&WinRegion);
69535c4bbdfSmrg    RegionUninit(&ClipRegion);
69635c4bbdfSmrg
69735c4bbdfSmrg    return ret;
69835c4bbdfSmrg}
69905b261ecSmrg
70005b261ecSmrgstatic int
70105b261ecSmrgxf86XVReputVideo(XvPortRecPrivatePtr portPriv)
70205b261ecSmrg{
70335c4bbdfSmrg    RegionRec WinRegion;
70435c4bbdfSmrg    RegionRec ClipRegion;
70535c4bbdfSmrg    BoxRec WinBox;
70635c4bbdfSmrg    int ret = Success;
70735c4bbdfSmrg    Bool clippedAway = FALSE;
70835c4bbdfSmrg
70935c4bbdfSmrg    xf86XVUpdateCompositeClip(portPriv);
71035c4bbdfSmrg
71135c4bbdfSmrg    /* translate the video region to the screen */
71235c4bbdfSmrg    WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
71335c4bbdfSmrg    WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
71435c4bbdfSmrg    WinBox.x2 = WinBox.x1 + portPriv->drw_w;
71535c4bbdfSmrg    WinBox.y2 = WinBox.y1 + portPriv->drw_h;
71635c4bbdfSmrg
71735c4bbdfSmrg    /* clip to the window composite clip */
71835c4bbdfSmrg    RegionInit(&WinRegion, &WinBox, 1);
71935c4bbdfSmrg    RegionNull(&ClipRegion);
72035c4bbdfSmrg    RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
72135c4bbdfSmrg
72235c4bbdfSmrg    /* clip and translate to the viewport */
72335c4bbdfSmrg    if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
72435c4bbdfSmrg        RegionRec VPReg;
72535c4bbdfSmrg        BoxRec VPBox;
72635c4bbdfSmrg
72735c4bbdfSmrg        VPBox.x1 = portPriv->pScrn->frameX0;
72835c4bbdfSmrg        VPBox.y1 = portPriv->pScrn->frameY0;
72935c4bbdfSmrg        VPBox.x2 = portPriv->pScrn->frameX1 + 1;
73035c4bbdfSmrg        VPBox.y2 = portPriv->pScrn->frameY1 + 1;
73135c4bbdfSmrg
73235c4bbdfSmrg        RegionInit(&VPReg, &VPBox, 1);
73335c4bbdfSmrg        RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
73435c4bbdfSmrg        RegionUninit(&VPReg);
73535c4bbdfSmrg    }
73635c4bbdfSmrg
73735c4bbdfSmrg    /* that's all if it's totally obscured */
73835c4bbdfSmrg    if (!RegionNotEmpty(&ClipRegion)) {
73935c4bbdfSmrg        clippedAway = TRUE;
74035c4bbdfSmrg        goto CLIP_VIDEO_BAILOUT;
74135c4bbdfSmrg    }
74235c4bbdfSmrg
74335c4bbdfSmrg    ret = (*portPriv->AdaptorRec->PutVideo) (portPriv->pScrn,
74435c4bbdfSmrg                                             portPriv->vid_x, portPriv->vid_y,
74535c4bbdfSmrg                                             WinBox.x1, WinBox.y1,
74635c4bbdfSmrg                                             portPriv->vid_w, portPriv->vid_h,
74735c4bbdfSmrg                                             portPriv->drw_w, portPriv->drw_h,
74835c4bbdfSmrg                                             &ClipRegion, portPriv->DevPriv.ptr,
74935c4bbdfSmrg                                             portPriv->pDraw);
75035c4bbdfSmrg
75135c4bbdfSmrg    if (ret == Success)
75235c4bbdfSmrg        portPriv->isOn = XV_ON;
75335c4bbdfSmrg
75435c4bbdfSmrg CLIP_VIDEO_BAILOUT:
75535c4bbdfSmrg
75635c4bbdfSmrg    if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
75735c4bbdfSmrg        (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
75835c4bbdfSmrg                                            portPriv->DevPriv.ptr, FALSE);
75935c4bbdfSmrg        portPriv->isOn = XV_PENDING;
76035c4bbdfSmrg    }
76135c4bbdfSmrg
76235c4bbdfSmrg    /* This clip was copied and only good for one shot */
76335c4bbdfSmrg    if (!portPriv->FreeCompositeClip)
76435c4bbdfSmrg        portPriv->pCompositeClip = NULL;
76535c4bbdfSmrg
76635c4bbdfSmrg    RegionUninit(&WinRegion);
76735c4bbdfSmrg    RegionUninit(&ClipRegion);
76835c4bbdfSmrg
76935c4bbdfSmrg    return ret;
77005b261ecSmrg}
77105b261ecSmrg
7729ace9065Smrg/* Reput image/still */
77305b261ecSmrgstatic int
77405b261ecSmrgxf86XVReputImage(XvPortRecPrivatePtr portPriv)
77505b261ecSmrg{
77635c4bbdfSmrg    RegionRec WinRegion;
77735c4bbdfSmrg    RegionRec ClipRegion;
77835c4bbdfSmrg    BoxRec WinBox;
77935c4bbdfSmrg    int ret = Success;
78035c4bbdfSmrg    Bool clippedAway = FALSE;
78135c4bbdfSmrg
78235c4bbdfSmrg    xf86XVUpdateCompositeClip(portPriv);
78335c4bbdfSmrg
78435c4bbdfSmrg    /* the clip can get smaller over time */
78535c4bbdfSmrg    RegionCopy(portPriv->clientClip, portPriv->pCompositeClip);
78635c4bbdfSmrg    RegionTranslate(portPriv->clientClip,
78735c4bbdfSmrg                    -portPriv->pDraw->x, -portPriv->pDraw->y);
78835c4bbdfSmrg
78935c4bbdfSmrg    /* translate the video region to the screen */
79035c4bbdfSmrg    WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
79135c4bbdfSmrg    WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
79235c4bbdfSmrg    WinBox.x2 = WinBox.x1 + portPriv->drw_w;
79335c4bbdfSmrg    WinBox.y2 = WinBox.y1 + portPriv->drw_h;
79435c4bbdfSmrg
79535c4bbdfSmrg    /* clip to the window composite clip */
79635c4bbdfSmrg    RegionInit(&WinRegion, &WinBox, 1);
79735c4bbdfSmrg    RegionNull(&ClipRegion);
79835c4bbdfSmrg    RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
79935c4bbdfSmrg
80035c4bbdfSmrg    /* clip and translate to the viewport */
80135c4bbdfSmrg    if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
80235c4bbdfSmrg        RegionRec VPReg;
80335c4bbdfSmrg        BoxRec VPBox;
80435c4bbdfSmrg
80535c4bbdfSmrg        VPBox.x1 = portPriv->pScrn->frameX0;
80635c4bbdfSmrg        VPBox.y1 = portPriv->pScrn->frameY0;
80735c4bbdfSmrg        VPBox.x2 = portPriv->pScrn->frameX1 + 1;
80835c4bbdfSmrg        VPBox.y2 = portPriv->pScrn->frameY1 + 1;
80935c4bbdfSmrg
81035c4bbdfSmrg        RegionInit(&VPReg, &VPBox, 1);
81135c4bbdfSmrg        RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
81235c4bbdfSmrg        RegionUninit(&VPReg);
81335c4bbdfSmrg    }
81435c4bbdfSmrg
81535c4bbdfSmrg    /* that's all if it's totally obscured */
81635c4bbdfSmrg    if (!RegionNotEmpty(&ClipRegion)) {
81735c4bbdfSmrg        clippedAway = TRUE;
81835c4bbdfSmrg        goto CLIP_VIDEO_BAILOUT;
81935c4bbdfSmrg    }
82035c4bbdfSmrg
82135c4bbdfSmrg    ret = (*portPriv->AdaptorRec->ReputImage) (portPriv->pScrn,
82235c4bbdfSmrg                                               portPriv->vid_x, portPriv->vid_y,
82335c4bbdfSmrg                                               WinBox.x1, WinBox.y1,
82435c4bbdfSmrg                                               portPriv->vid_w, portPriv->vid_h,
82535c4bbdfSmrg                                               portPriv->drw_w, portPriv->drw_h,
82635c4bbdfSmrg                                               &ClipRegion,
82735c4bbdfSmrg                                               portPriv->DevPriv.ptr,
82835c4bbdfSmrg                                               portPriv->pDraw);
82905b261ecSmrg
83035c4bbdfSmrg    portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF;
83135c4bbdfSmrg
83235c4bbdfSmrg CLIP_VIDEO_BAILOUT:
83335c4bbdfSmrg
83435c4bbdfSmrg    if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
83535c4bbdfSmrg        (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
83635c4bbdfSmrg                                            portPriv->DevPriv.ptr, FALSE);
83735c4bbdfSmrg        portPriv->isOn = XV_PENDING;
83835c4bbdfSmrg    }
83935c4bbdfSmrg
84035c4bbdfSmrg    /* This clip was copied and only good for one shot */
84135c4bbdfSmrg    if (!portPriv->FreeCompositeClip)
84235c4bbdfSmrg        portPriv->pCompositeClip = NULL;
84335c4bbdfSmrg
84435c4bbdfSmrg    RegionUninit(&WinRegion);
84535c4bbdfSmrg    RegionUninit(&ClipRegion);
84635c4bbdfSmrg
84735c4bbdfSmrg    return ret;
84835c4bbdfSmrg}
84905b261ecSmrg
85005b261ecSmrgstatic int
85135c4bbdfSmrgxf86XVReputAllVideo(WindowPtr pWin, void *data)
85205b261ecSmrg{
85305b261ecSmrg    XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
85405b261ecSmrg
85535c4bbdfSmrg    while (WinPriv) {
85635c4bbdfSmrg        if (WinPriv->PortRec->type == XvInputMask)
85735c4bbdfSmrg            xf86XVReputVideo(WinPriv->PortRec);
85835c4bbdfSmrg        else
85935c4bbdfSmrg            xf86XVRegetVideo(WinPriv->PortRec);
86035c4bbdfSmrg        WinPriv = WinPriv->next;
86105b261ecSmrg    }
86205b261ecSmrg
86305b261ecSmrg    return WT_WALKCHILDREN;
86405b261ecSmrg}
86505b261ecSmrg
86605b261ecSmrgstatic int
86705b261ecSmrgxf86XVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
86805b261ecSmrg{
86935c4bbdfSmrg    XF86XVWindowPtr winPriv, PrivRoot;
87005b261ecSmrg
87135c4bbdfSmrg    winPriv = PrivRoot = GET_XF86XV_WINDOW(pWin);
87205b261ecSmrg
87335c4bbdfSmrg    /* Enlist our port in the window private */
87435c4bbdfSmrg    while (winPriv) {
87535c4bbdfSmrg        if (winPriv->PortRec == portPriv)       /* we're already listed */
87635c4bbdfSmrg            break;
87735c4bbdfSmrg        winPriv = winPriv->next;
87835c4bbdfSmrg    }
87905b261ecSmrg
88035c4bbdfSmrg    if (!winPriv) {
88135c4bbdfSmrg        winPriv = calloc(1, sizeof(XF86XVWindowRec));
88235c4bbdfSmrg        if (!winPriv)
88335c4bbdfSmrg            return BadAlloc;
88435c4bbdfSmrg        winPriv->PortRec = portPriv;
88535c4bbdfSmrg        winPriv->next = PrivRoot;
88635c4bbdfSmrg        dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, winPriv);
88735c4bbdfSmrg    }
88805b261ecSmrg
88935c4bbdfSmrg    portPriv->pDraw = (DrawablePtr) pWin;
89005b261ecSmrg
89135c4bbdfSmrg    return Success;
89205b261ecSmrg}
89305b261ecSmrg
89405b261ecSmrgstatic void
89505b261ecSmrgxf86XVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
89605b261ecSmrg{
89735c4bbdfSmrg    XF86XVWindowPtr winPriv, prevPriv = NULL;
89835c4bbdfSmrg
89935c4bbdfSmrg    winPriv = GET_XF86XV_WINDOW(pWin);
90035c4bbdfSmrg
90135c4bbdfSmrg    while (winPriv) {
90235c4bbdfSmrg        if (winPriv->PortRec == portPriv) {
90335c4bbdfSmrg            if (prevPriv)
90435c4bbdfSmrg                prevPriv->next = winPriv->next;
90535c4bbdfSmrg            else
90635c4bbdfSmrg                dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey,
90735c4bbdfSmrg                              winPriv->next);
90835c4bbdfSmrg            free(winPriv);
90935c4bbdfSmrg            break;
91035c4bbdfSmrg        }
91135c4bbdfSmrg        prevPriv = winPriv;
91235c4bbdfSmrg        winPriv = winPriv->next;
91335c4bbdfSmrg    }
91435c4bbdfSmrg    portPriv->pDraw = NULL;
91535c4bbdfSmrg    if (portPriv->ckeyFilled) {
91635c4bbdfSmrg        RegionDestroy(portPriv->ckeyFilled);
91735c4bbdfSmrg        portPriv->ckeyFilled = NULL;
91835c4bbdfSmrg    }
91935c4bbdfSmrg    portPriv->clipChanged = FALSE;
9209ace9065Smrg}
9219ace9065Smrg
9229ace9065Smrgstatic void
92335c4bbdfSmrgxf86XVReputOrStopPort(XvPortRecPrivatePtr pPriv, WindowPtr pWin, Bool visible)
9249ace9065Smrg{
9259ace9065Smrg    if (!visible) {
92635c4bbdfSmrg        if (pPriv->isOn == XV_ON) {
92735c4bbdfSmrg            (*pPriv->AdaptorRec->StopVideo) (pPriv->pScrn, pPriv->DevPriv.ptr,
92835c4bbdfSmrg                                             FALSE);
92935c4bbdfSmrg            pPriv->isOn = XV_PENDING;
93035c4bbdfSmrg        }
9319ace9065Smrg
93235c4bbdfSmrg        if (!pPriv->type)       /* overlaid still/image */
93335c4bbdfSmrg            xf86XVRemovePortFromWindow(pWin, pPriv);
9349ace9065Smrg
93535c4bbdfSmrg        return;
9369ace9065Smrg    }
9379ace9065Smrg
9389ace9065Smrg    switch (pPriv->type) {
9399ace9065Smrg    case XvInputMask:
94035c4bbdfSmrg        xf86XVReputVideo(pPriv);
94135c4bbdfSmrg        break;
9429ace9065Smrg    case XvOutputMask:
94335c4bbdfSmrg        xf86XVRegetVideo(pPriv);
94435c4bbdfSmrg        break;
94535c4bbdfSmrg    default:                   /* overlaid still/image */
94635c4bbdfSmrg        if (pPriv->AdaptorRec->ReputImage)
94735c4bbdfSmrg            xf86XVReputImage(pPriv);
94835c4bbdfSmrg        break;
9499ace9065Smrg    }
9509ace9065Smrg}
9519ace9065Smrg
9529ace9065Smrgstatic void
9539ace9065Smrgxf86XVReputOrStopAllPorts(ScrnInfoPtr pScrn, Bool onlyChanged)
9549ace9065Smrg{
95535c4bbdfSmrg    ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
9569ace9065Smrg    XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
9579ace9065Smrg    XvAdaptorPtr pa;
9589ace9065Smrg    int c, i;
9599ace9065Smrg
9609ace9065Smrg    for (c = pxvs->nAdaptors, pa = pxvs->pAdaptors; c > 0; c--, pa++) {
96135c4bbdfSmrg        XvPortPtr pPort = pa->pPorts;
9629ace9065Smrg
96335c4bbdfSmrg        for (i = pa->nPorts; i > 0; i--, pPort++) {
96435c4bbdfSmrg            XvPortRecPrivatePtr pPriv =
96535c4bbdfSmrg                (XvPortRecPrivatePtr) pPort->devPriv.ptr;
96635c4bbdfSmrg            WindowPtr pWin = (WindowPtr) pPriv->pDraw;
96735c4bbdfSmrg            Bool visible;
9689ace9065Smrg
96935c4bbdfSmrg            if (pPriv->isOn == XV_OFF || !pWin)
97035c4bbdfSmrg                continue;
9719ace9065Smrg
97235c4bbdfSmrg            if (onlyChanged && !pPriv->clipChanged)
97335c4bbdfSmrg                continue;
9749ace9065Smrg
97535c4bbdfSmrg            visible = pWin->visibility == VisibilityUnobscured ||
97635c4bbdfSmrg                pWin->visibility == VisibilityPartiallyObscured;
9779ace9065Smrg
97835c4bbdfSmrg            /*
97935c4bbdfSmrg             * Stop and remove still/images if
98035c4bbdfSmrg             * ReputImage isn't supported.
98135c4bbdfSmrg             */
98235c4bbdfSmrg            if (!pPriv->type && !pPriv->AdaptorRec->ReputImage)
98335c4bbdfSmrg                visible = FALSE;
9849ace9065Smrg
98535c4bbdfSmrg            xf86XVReputOrStopPort(pPriv, pWin, visible);
9869ace9065Smrg
98735c4bbdfSmrg            pPriv->clipChanged = FALSE;
98835c4bbdfSmrg        }
9899ace9065Smrg    }
99005b261ecSmrg}
99105b261ecSmrg
99205b261ecSmrg/****  ScreenRec fields ****/
99305b261ecSmrg
99405b261ecSmrgstatic Bool
99505b261ecSmrgxf86XVDestroyWindow(WindowPtr pWin)
99605b261ecSmrg{
99735c4bbdfSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
99835c4bbdfSmrg    XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
99935c4bbdfSmrg    XF86XVWindowPtr tmp, WinPriv = GET_XF86XV_WINDOW(pWin);
100035c4bbdfSmrg    int ret;
100105b261ecSmrg
100235c4bbdfSmrg    while (WinPriv) {
100335c4bbdfSmrg        XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
100435c4bbdfSmrg
100535c4bbdfSmrg        if (pPriv->isOn > XV_OFF) {
100635c4bbdfSmrg            (*pPriv->AdaptorRec->StopVideo) (pPriv->pScrn, pPriv->DevPriv.ptr,
100735c4bbdfSmrg                                             TRUE);
100835c4bbdfSmrg            pPriv->isOn = XV_OFF;
100935c4bbdfSmrg        }
101035c4bbdfSmrg
101135c4bbdfSmrg        pPriv->pDraw = NULL;
101235c4bbdfSmrg        tmp = WinPriv;
101335c4bbdfSmrg        WinPriv = WinPriv->next;
101435c4bbdfSmrg        free(tmp);
101535c4bbdfSmrg    }
101605b261ecSmrg
101735c4bbdfSmrg    dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, NULL);
101805b261ecSmrg
101935c4bbdfSmrg    pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
102035c4bbdfSmrg    ret = (*pScreen->DestroyWindow) (pWin);
102135c4bbdfSmrg    pScreen->DestroyWindow = xf86XVDestroyWindow;
102205b261ecSmrg
102335c4bbdfSmrg    return ret;
102405b261ecSmrg}
102505b261ecSmrg
10269ace9065Smrgstatic void
10279ace9065Smrgxf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin, VTKind kind)
10289ace9065Smrg{
10299ace9065Smrg    ScreenPtr pScreen;
10309ace9065Smrg    XF86XVScreenPtr ScreenPriv;
10319ace9065Smrg    ScrnInfoPtr pScrn;
10329ace9065Smrg
10339ace9065Smrg    if (pWin)
103435c4bbdfSmrg        pScreen = pWin->drawable.pScreen;
10359ace9065Smrg    else
103635c4bbdfSmrg        pScreen = pLayerWin->drawable.pScreen;
10379ace9065Smrg
10389ace9065Smrg    ScreenPriv = GET_XF86XV_SCREEN(pScreen);
103935c4bbdfSmrg    pScrn = xf86ScreenToScrn(pScreen);
10409ace9065Smrg
10419ace9065Smrg    xf86XVReputOrStopAllPorts(pScrn, TRUE);
10429ace9065Smrg
10439ace9065Smrg    pScreen->PostValidateTree = ScreenPriv->PostValidateTree;
10449ace9065Smrg    if (pScreen->PostValidateTree) {
104535c4bbdfSmrg        (*pScreen->PostValidateTree) (pWin, pLayerWin, kind);
10469ace9065Smrg    }
10479ace9065Smrg    ScreenPriv->PostValidateTree = PostValidateTreeUndefined;
10489ace9065Smrg}
104905b261ecSmrg
105005b261ecSmrgstatic void
105135c4bbdfSmrgxf86XVWindowExposures(WindowPtr pWin, RegionPtr reg1)
105205b261ecSmrg{
105335c4bbdfSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
105435c4bbdfSmrg    XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
105535c4bbdfSmrg    XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
105635c4bbdfSmrg    XvPortRecPrivatePtr pPriv;
105735c4bbdfSmrg    Bool AreasExposed;
105835c4bbdfSmrg
105935c4bbdfSmrg    AreasExposed = (WinPriv && reg1 && RegionNotEmpty(reg1));
106035c4bbdfSmrg
106135c4bbdfSmrg    pScreen->WindowExposures = ScreenPriv->WindowExposures;
106235c4bbdfSmrg    (*pScreen->WindowExposures) (pWin, reg1);
106335c4bbdfSmrg    pScreen->WindowExposures = xf86XVWindowExposures;
106435c4bbdfSmrg
106535c4bbdfSmrg    /* filter out XClearWindow/Area */
106635c4bbdfSmrg    if (!pWin->valdata)
106735c4bbdfSmrg        return;
106835c4bbdfSmrg
106935c4bbdfSmrg    while (WinPriv) {
107035c4bbdfSmrg        Bool visible = TRUE;
107135c4bbdfSmrg
107235c4bbdfSmrg        pPriv = WinPriv->PortRec;
107335c4bbdfSmrg
107435c4bbdfSmrg        /*
107535c4bbdfSmrg         * Stop and remove still/images if areas were exposed and
107635c4bbdfSmrg         * ReputImage isn't supported.
107735c4bbdfSmrg         */
107835c4bbdfSmrg        if (!pPriv->type && !pPriv->AdaptorRec->ReputImage)
107935c4bbdfSmrg            visible = !AreasExposed;
108035c4bbdfSmrg
108135c4bbdfSmrg        /*
108235c4bbdfSmrg         * Subtract exposed areas from overlaid image to match textured video
108335c4bbdfSmrg         * behavior.
108435c4bbdfSmrg         */
108535c4bbdfSmrg        if (!pPriv->type && pPriv->clientClip)
108635c4bbdfSmrg            RegionSubtract(pPriv->clientClip, pPriv->clientClip, reg1);
108735c4bbdfSmrg
108835c4bbdfSmrg        if (visible && pPriv->ckeyFilled) {
108935c4bbdfSmrg            RegionRec tmp;
109035c4bbdfSmrg
109135c4bbdfSmrg            RegionNull(&tmp);
109235c4bbdfSmrg            RegionCopy(&tmp, reg1);
109335c4bbdfSmrg            RegionTranslate(&tmp, pWin->drawable.x, pWin->drawable.y);
109435c4bbdfSmrg            RegionSubtract(pPriv->ckeyFilled, pPriv->ckeyFilled, &tmp);
109535c4bbdfSmrg        }
109635c4bbdfSmrg
109735c4bbdfSmrg        WinPriv = WinPriv->next;
109835c4bbdfSmrg        xf86XVReputOrStopPort(pPriv, pWin, visible);
109935c4bbdfSmrg
110035c4bbdfSmrg        pPriv->clipChanged = FALSE;
110135c4bbdfSmrg    }
110205b261ecSmrg}
110305b261ecSmrg
110405b261ecSmrgstatic void
110505b261ecSmrgxf86XVClipNotify(WindowPtr pWin, int dx, int dy)
110605b261ecSmrg{
110735c4bbdfSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
110835c4bbdfSmrg    XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
110935c4bbdfSmrg    XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
111035c4bbdfSmrg    XvPortRecPrivatePtr pPriv;
111105b261ecSmrg
111235c4bbdfSmrg    while (WinPriv) {
111335c4bbdfSmrg        pPriv = WinPriv->PortRec;
111405b261ecSmrg
111535c4bbdfSmrg        if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
111635c4bbdfSmrg            RegionDestroy(pPriv->pCompositeClip);
111705b261ecSmrg
111835c4bbdfSmrg        pPriv->pCompositeClip = NULL;
11196747b715Smrg
112035c4bbdfSmrg        pPriv->clipChanged = TRUE;
112105b261ecSmrg
112235c4bbdfSmrg        if (ScreenPriv->PostValidateTree == PostValidateTreeUndefined) {
112335c4bbdfSmrg            ScreenPriv->PostValidateTree = pScreen->PostValidateTree;
112435c4bbdfSmrg            pScreen->PostValidateTree = xf86XVPostValidateTree;
112535c4bbdfSmrg        }
112605b261ecSmrg
112735c4bbdfSmrg        WinPriv = WinPriv->next;
112835c4bbdfSmrg    }
112905b261ecSmrg
113035c4bbdfSmrg    if (ScreenPriv->ClipNotify) {
113135c4bbdfSmrg        pScreen->ClipNotify = ScreenPriv->ClipNotify;
113235c4bbdfSmrg        (*pScreen->ClipNotify) (pWin, dx, dy);
113335c4bbdfSmrg        pScreen->ClipNotify = xf86XVClipNotify;
113435c4bbdfSmrg    }
113505b261ecSmrg}
113605b261ecSmrg
113705b261ecSmrg/**** Required XvScreenRec fields ****/
113805b261ecSmrg
113905b261ecSmrgstatic Bool
114035c4bbdfSmrgxf86XVCloseScreen(ScreenPtr pScreen)
114105b261ecSmrg{
114235c4bbdfSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
114335c4bbdfSmrg    XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
114435c4bbdfSmrg    XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
114535c4bbdfSmrg    XvAdaptorPtr pa;
114635c4bbdfSmrg    int c;
114705b261ecSmrg
114835c4bbdfSmrg    if (!ScreenPriv)
114935c4bbdfSmrg        return TRUE;
115005b261ecSmrg
115135c4bbdfSmrg    pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
115235c4bbdfSmrg    pScreen->WindowExposures = ScreenPriv->WindowExposures;
115335c4bbdfSmrg    pScreen->ClipNotify = ScreenPriv->ClipNotify;
115435c4bbdfSmrg    pScreen->CloseScreen = ScreenPriv->CloseScreen;
115505b261ecSmrg
115635c4bbdfSmrg    pScrn->EnterVT = ScreenPriv->EnterVT;
115735c4bbdfSmrg    pScrn->LeaveVT = ScreenPriv->LeaveVT;
115835c4bbdfSmrg    pScrn->AdjustFrame = ScreenPriv->AdjustFrame;
115935c4bbdfSmrg    pScrn->ModeSet = ScreenPriv->ModeSet;
116005b261ecSmrg
116135c4bbdfSmrg    for (c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) {
116235c4bbdfSmrg        xf86XVFreeAdaptor(pa);
116335c4bbdfSmrg    }
116405b261ecSmrg
116535c4bbdfSmrg    free(pxvs->pAdaptors);
116635c4bbdfSmrg    free(ScreenPriv);
116735c4bbdfSmrg
116835c4bbdfSmrg    return pScreen->CloseScreen(pScreen);
116935c4bbdfSmrg}
117005b261ecSmrg
117105b261ecSmrg/**** ScrnInfoRec fields ****/
117205b261ecSmrg
117305b261ecSmrgstatic Bool
117435c4bbdfSmrgxf86XVEnterVT(ScrnInfoPtr pScrn)
117505b261ecSmrg{
117635c4bbdfSmrg    ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
117705b261ecSmrg    XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
117805b261ecSmrg    Bool ret;
117905b261ecSmrg
11806747b715Smrg    pScrn->EnterVT = ScreenPriv->EnterVT;
118135c4bbdfSmrg    ret = (*ScreenPriv->EnterVT) (pScrn);
11826747b715Smrg    ScreenPriv->EnterVT = pScrn->EnterVT;
11836747b715Smrg    pScrn->EnterVT = xf86XVEnterVT;
118405b261ecSmrg
118535c4bbdfSmrg    if (ret)
118635c4bbdfSmrg        WalkTree(pScreen, xf86XVReputAllVideo, 0);
118705b261ecSmrg
118805b261ecSmrg    return ret;
118905b261ecSmrg}
119005b261ecSmrg
119105b261ecSmrgstatic void
119235c4bbdfSmrgxf86XVLeaveVT(ScrnInfoPtr pScrn)
119305b261ecSmrg{
119435c4bbdfSmrg    ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
119505b261ecSmrg    XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
119605b261ecSmrg    XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
119705b261ecSmrg    XvAdaptorPtr pAdaptor;
119805b261ecSmrg    XvPortPtr pPort;
119905b261ecSmrg    XvPortRecPrivatePtr pPriv;
120005b261ecSmrg    int i, j;
120105b261ecSmrg
120235c4bbdfSmrg    for (i = 0; i < pxvs->nAdaptors; i++) {
120335c4bbdfSmrg        pAdaptor = &pxvs->pAdaptors[i];
120435c4bbdfSmrg        for (j = 0; j < pAdaptor->nPorts; j++) {
120535c4bbdfSmrg            pPort = &pAdaptor->pPorts[j];
120635c4bbdfSmrg            pPriv = (XvPortRecPrivatePtr) pPort->devPriv.ptr;
120735c4bbdfSmrg            if (pPriv->isOn > XV_OFF) {
120805b261ecSmrg
120935c4bbdfSmrg                (*pPriv->AdaptorRec->StopVideo) (pPriv->pScrn,
121035c4bbdfSmrg                                                 pPriv->DevPriv.ptr, TRUE);
121135c4bbdfSmrg                pPriv->isOn = XV_OFF;
121205b261ecSmrg
121335c4bbdfSmrg                if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
121435c4bbdfSmrg                    RegionDestroy(pPriv->pCompositeClip);
121505b261ecSmrg
121635c4bbdfSmrg                pPriv->pCompositeClip = NULL;
121705b261ecSmrg
121835c4bbdfSmrg                if (!pPriv->type && pPriv->pDraw) {     /* still */
121935c4bbdfSmrg                    xf86XVRemovePortFromWindow((WindowPtr) pPriv->pDraw, pPriv);
122035c4bbdfSmrg                }
122135c4bbdfSmrg            }
122235c4bbdfSmrg        }
122305b261ecSmrg    }
122405b261ecSmrg
12256747b715Smrg    pScrn->LeaveVT = ScreenPriv->LeaveVT;
122635c4bbdfSmrg    (*ScreenPriv->LeaveVT) (pScrn);
12276747b715Smrg    ScreenPriv->LeaveVT = pScrn->LeaveVT;
12286747b715Smrg    pScrn->LeaveVT = xf86XVLeaveVT;
122905b261ecSmrg}
123005b261ecSmrg
123105b261ecSmrgstatic void
123235c4bbdfSmrgxf86XVAdjustFrame(ScrnInfoPtr pScrn, int x, int y)
123305b261ecSmrg{
123435c4bbdfSmrg    ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
123535c4bbdfSmrg    XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
123605b261ecSmrg
123735c4bbdfSmrg    if (ScreenPriv->AdjustFrame) {
123835c4bbdfSmrg        pScrn->AdjustFrame = ScreenPriv->AdjustFrame;
123935c4bbdfSmrg        (*pScrn->AdjustFrame) (pScrn, x, y);
124035c4bbdfSmrg        pScrn->AdjustFrame = xf86XVAdjustFrame;
124135c4bbdfSmrg    }
124205b261ecSmrg
124335c4bbdfSmrg    xf86XVReputOrStopAllPorts(pScrn, FALSE);
12449ace9065Smrg}
124505b261ecSmrg
12469ace9065Smrgstatic void
12479ace9065Smrgxf86XVModeSet(ScrnInfoPtr pScrn)
12489ace9065Smrg{
124935c4bbdfSmrg    ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
12509ace9065Smrg    XF86XVScreenPtr ScreenPriv;
125105b261ecSmrg
12529ace9065Smrg    /* Can be called before pScrn->pScreen is set */
12539ace9065Smrg    if (!pScreen)
125435c4bbdfSmrg        return;
125505b261ecSmrg
12569ace9065Smrg    ScreenPriv = GET_XF86XV_SCREEN(pScreen);
125705b261ecSmrg
12589ace9065Smrg    if (ScreenPriv->ModeSet) {
125935c4bbdfSmrg        pScrn->ModeSet = ScreenPriv->ModeSet;
126035c4bbdfSmrg        (*pScrn->ModeSet) (pScrn);
126135c4bbdfSmrg        pScrn->ModeSet = xf86XVModeSet;
12629ace9065Smrg    }
126305b261ecSmrg
12649ace9065Smrg    xf86XVReputOrStopAllPorts(pScrn, FALSE);
126505b261ecSmrg}
126605b261ecSmrg
126705b261ecSmrg/**** XvAdaptorRec fields ****/
126805b261ecSmrg
126905b261ecSmrgstatic int
127035c4bbdfSmrgxf86XVPutVideo(DrawablePtr pDraw,
127135c4bbdfSmrg               XvPortPtr pPort,
127235c4bbdfSmrg               GCPtr pGC,
127335c4bbdfSmrg               INT16 vid_x, INT16 vid_y,
127435c4bbdfSmrg               CARD16 vid_w, CARD16 vid_h,
127535c4bbdfSmrg               INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
127635c4bbdfSmrg{
127735c4bbdfSmrg    XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
127835c4bbdfSmrg    int result;
127905b261ecSmrg
128035c4bbdfSmrg    /* No dumping video to pixmaps... For now anyhow */
128135c4bbdfSmrg    if (pDraw->type != DRAWABLE_WINDOW) {
128235c4bbdfSmrg        pPort->pDraw = (DrawablePtr) NULL;
128335c4bbdfSmrg        return BadAlloc;
128435c4bbdfSmrg    }
128505b261ecSmrg
128635c4bbdfSmrg    /* If we are changing windows, unregister our port in the old window */
128735c4bbdfSmrg    if (portPriv->pDraw && (portPriv->pDraw != pDraw))
128835c4bbdfSmrg        xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
128905b261ecSmrg
129035c4bbdfSmrg    /* Register our port with the new window */
129135c4bbdfSmrg    result = xf86XVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
129235c4bbdfSmrg    if (result != Success)
129335c4bbdfSmrg        return result;
129405b261ecSmrg
129535c4bbdfSmrg    portPriv->type = XvInputMask;
129605b261ecSmrg
129735c4bbdfSmrg    /* save a copy of these parameters */
129835c4bbdfSmrg    portPriv->vid_x = vid_x;
129935c4bbdfSmrg    portPriv->vid_y = vid_y;
130035c4bbdfSmrg    portPriv->vid_w = vid_w;
130135c4bbdfSmrg    portPriv->vid_h = vid_h;
130235c4bbdfSmrg    portPriv->drw_x = drw_x;
130335c4bbdfSmrg    portPriv->drw_y = drw_y;
130435c4bbdfSmrg    portPriv->drw_w = drw_w;
130535c4bbdfSmrg    portPriv->drw_h = drw_h;
130635c4bbdfSmrg
130735c4bbdfSmrg    /* make sure we have the most recent copy of the clientClip */
130835c4bbdfSmrg    xf86XVCopyClip(portPriv, pGC);
130935c4bbdfSmrg
131035c4bbdfSmrg    /* To indicate to the DI layer that we were successful */
131135c4bbdfSmrg    pPort->pDraw = pDraw;
131235c4bbdfSmrg
131335c4bbdfSmrg    if (!portPriv->pScrn->vtSema)
131435c4bbdfSmrg        return Success;         /* Success ? */
131535c4bbdfSmrg
131635c4bbdfSmrg    return (xf86XVReputVideo(portPriv));
131705b261ecSmrg}
131805b261ecSmrg
131905b261ecSmrgstatic int
132035c4bbdfSmrgxf86XVPutStill(DrawablePtr pDraw,
132135c4bbdfSmrg               XvPortPtr pPort,
132235c4bbdfSmrg               GCPtr pGC,
132335c4bbdfSmrg               INT16 vid_x, INT16 vid_y,
132435c4bbdfSmrg               CARD16 vid_w, CARD16 vid_h,
132535c4bbdfSmrg               INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
132635c4bbdfSmrg{
132735c4bbdfSmrg    XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
132835c4bbdfSmrg    RegionRec WinRegion;
132935c4bbdfSmrg    RegionRec ClipRegion;
133035c4bbdfSmrg    BoxRec WinBox;
133135c4bbdfSmrg    int ret = Success;
133235c4bbdfSmrg    Bool clippedAway = FALSE;
133335c4bbdfSmrg
133435c4bbdfSmrg    if (pDraw->type != DRAWABLE_WINDOW)
133535c4bbdfSmrg        return BadAlloc;
133635c4bbdfSmrg
133735c4bbdfSmrg    if (!portPriv->pScrn->vtSema)
133835c4bbdfSmrg        return Success;         /* Success ? */
133935c4bbdfSmrg
134035c4bbdfSmrg    WinBox.x1 = pDraw->x + drw_x;
134135c4bbdfSmrg    WinBox.y1 = pDraw->y + drw_y;
134235c4bbdfSmrg    WinBox.x2 = WinBox.x1 + drw_w;
134335c4bbdfSmrg    WinBox.y2 = WinBox.y1 + drw_h;
134435c4bbdfSmrg
134535c4bbdfSmrg    xf86XVCopyCompositeClip(portPriv, pGC, pDraw);
134635c4bbdfSmrg
134735c4bbdfSmrg    RegionInit(&WinRegion, &WinBox, 1);
134835c4bbdfSmrg    RegionNull(&ClipRegion);
134935c4bbdfSmrg    RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
135035c4bbdfSmrg
135135c4bbdfSmrg    if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
135235c4bbdfSmrg        RegionRec VPReg;
135335c4bbdfSmrg        BoxRec VPBox;
135435c4bbdfSmrg
135535c4bbdfSmrg        VPBox.x1 = portPriv->pScrn->frameX0;
135635c4bbdfSmrg        VPBox.y1 = portPriv->pScrn->frameY0;
135735c4bbdfSmrg        VPBox.x2 = portPriv->pScrn->frameX1 + 1;
135835c4bbdfSmrg        VPBox.y2 = portPriv->pScrn->frameY1 + 1;
135935c4bbdfSmrg
136035c4bbdfSmrg        RegionInit(&VPReg, &VPBox, 1);
136135c4bbdfSmrg        RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
136235c4bbdfSmrg        RegionUninit(&VPReg);
136335c4bbdfSmrg    }
136435c4bbdfSmrg
136535c4bbdfSmrg    if (portPriv->pDraw) {
136635c4bbdfSmrg        xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
136735c4bbdfSmrg    }
136835c4bbdfSmrg
136935c4bbdfSmrg    if (!RegionNotEmpty(&ClipRegion)) {
137035c4bbdfSmrg        clippedAway = TRUE;
137135c4bbdfSmrg        goto PUT_STILL_BAILOUT;
137235c4bbdfSmrg    }
137335c4bbdfSmrg
137435c4bbdfSmrg    ret = (*portPriv->AdaptorRec->PutStill) (portPriv->pScrn,
137535c4bbdfSmrg                                             vid_x, vid_y, WinBox.x1, WinBox.y1,
137635c4bbdfSmrg                                             vid_w, vid_h, drw_w, drw_h,
137735c4bbdfSmrg                                             &ClipRegion, portPriv->DevPriv.ptr,
137835c4bbdfSmrg                                             pDraw);
137935c4bbdfSmrg
138035c4bbdfSmrg    if ((ret == Success) &&
138135c4bbdfSmrg        (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) {
138235c4bbdfSmrg
138335c4bbdfSmrg        xf86XVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
138435c4bbdfSmrg        portPriv->isOn = XV_ON;
138535c4bbdfSmrg        portPriv->vid_x = vid_x;
138635c4bbdfSmrg        portPriv->vid_y = vid_y;
138735c4bbdfSmrg        portPriv->vid_w = vid_w;
138835c4bbdfSmrg        portPriv->vid_h = vid_h;
138935c4bbdfSmrg        portPriv->drw_x = drw_x;
139035c4bbdfSmrg        portPriv->drw_y = drw_y;
139135c4bbdfSmrg        portPriv->drw_w = drw_w;
139235c4bbdfSmrg        portPriv->drw_h = drw_h;
139335c4bbdfSmrg        portPriv->type = 0;     /* no mask means it's transient and should
139435c4bbdfSmrg                                   not be reput once it's removed */
139535c4bbdfSmrg        pPort->pDraw = pDraw;   /* make sure we can get stop requests */
139635c4bbdfSmrg    }
139735c4bbdfSmrg
139835c4bbdfSmrg PUT_STILL_BAILOUT:
139935c4bbdfSmrg
140035c4bbdfSmrg    if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
140135c4bbdfSmrg        (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
140235c4bbdfSmrg                                            portPriv->DevPriv.ptr, FALSE);
140335c4bbdfSmrg        portPriv->isOn = XV_PENDING;
140435c4bbdfSmrg    }
140535c4bbdfSmrg
140635c4bbdfSmrg    /* This clip was copied and only good for one shot */
140735c4bbdfSmrg    if (!portPriv->FreeCompositeClip)
140835c4bbdfSmrg        portPriv->pCompositeClip = NULL;
140935c4bbdfSmrg
141035c4bbdfSmrg    RegionUninit(&WinRegion);
141135c4bbdfSmrg    RegionUninit(&ClipRegion);
141235c4bbdfSmrg
141335c4bbdfSmrg    return ret;
141405b261ecSmrg}
141505b261ecSmrg
141605b261ecSmrgstatic int
141735c4bbdfSmrgxf86XVGetVideo(DrawablePtr pDraw,
141835c4bbdfSmrg               XvPortPtr pPort,
141935c4bbdfSmrg               GCPtr pGC,
142035c4bbdfSmrg               INT16 vid_x, INT16 vid_y,
142135c4bbdfSmrg               CARD16 vid_w, CARD16 vid_h,
142235c4bbdfSmrg               INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
142335c4bbdfSmrg{
142435c4bbdfSmrg    XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
142535c4bbdfSmrg    int result;
142635c4bbdfSmrg
142735c4bbdfSmrg    /* No pixmaps... For now anyhow */
142835c4bbdfSmrg    if (pDraw->type != DRAWABLE_WINDOW) {
142935c4bbdfSmrg        pPort->pDraw = (DrawablePtr) NULL;
143035c4bbdfSmrg        return BadAlloc;
143135c4bbdfSmrg    }
143235c4bbdfSmrg
143335c4bbdfSmrg    /* If we are changing windows, unregister our port in the old window */
143435c4bbdfSmrg    if (portPriv->pDraw && (portPriv->pDraw != pDraw))
143535c4bbdfSmrg        xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
143635c4bbdfSmrg
143735c4bbdfSmrg    /* Register our port with the new window */
143835c4bbdfSmrg    result = xf86XVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
143935c4bbdfSmrg    if (result != Success)
144035c4bbdfSmrg        return result;
144135c4bbdfSmrg
144235c4bbdfSmrg    portPriv->type = XvOutputMask;
144335c4bbdfSmrg
144435c4bbdfSmrg    /* save a copy of these parameters */
144535c4bbdfSmrg    portPriv->vid_x = vid_x;
144635c4bbdfSmrg    portPriv->vid_y = vid_y;
144735c4bbdfSmrg    portPriv->vid_w = vid_w;
144835c4bbdfSmrg    portPriv->vid_h = vid_h;
144935c4bbdfSmrg    portPriv->drw_x = drw_x;
145035c4bbdfSmrg    portPriv->drw_y = drw_y;
145135c4bbdfSmrg    portPriv->drw_w = drw_w;
145235c4bbdfSmrg    portPriv->drw_h = drw_h;
145335c4bbdfSmrg
145435c4bbdfSmrg    /* make sure we have the most recent copy of the clientClip */
145535c4bbdfSmrg    xf86XVCopyClip(portPriv, pGC);
145635c4bbdfSmrg
145735c4bbdfSmrg    /* To indicate to the DI layer that we were successful */
145835c4bbdfSmrg    pPort->pDraw = pDraw;
145935c4bbdfSmrg
146035c4bbdfSmrg    if (!portPriv->pScrn->vtSema)
146135c4bbdfSmrg        return Success;         /* Success ? */
146235c4bbdfSmrg
146335c4bbdfSmrg    return (xf86XVRegetVideo(portPriv));
146405b261ecSmrg}
146505b261ecSmrg
146605b261ecSmrgstatic int
146735c4bbdfSmrgxf86XVGetStill(DrawablePtr pDraw,
146835c4bbdfSmrg               XvPortPtr pPort,
146935c4bbdfSmrg               GCPtr pGC,
147035c4bbdfSmrg               INT16 vid_x, INT16 vid_y,
147135c4bbdfSmrg               CARD16 vid_w, CARD16 vid_h,
147235c4bbdfSmrg               INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
147335c4bbdfSmrg{
147435c4bbdfSmrg    XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
147535c4bbdfSmrg    RegionRec WinRegion;
147635c4bbdfSmrg    RegionRec ClipRegion;
147735c4bbdfSmrg    BoxRec WinBox;
147835c4bbdfSmrg    int ret = Success;
147935c4bbdfSmrg    Bool clippedAway = FALSE;
148035c4bbdfSmrg
148135c4bbdfSmrg    if (pDraw->type != DRAWABLE_WINDOW)
148235c4bbdfSmrg        return BadAlloc;
148335c4bbdfSmrg
148435c4bbdfSmrg    if (!portPriv->pScrn->vtSema)
148535c4bbdfSmrg        return Success;         /* Success ? */
148635c4bbdfSmrg
148735c4bbdfSmrg    WinBox.x1 = pDraw->x + drw_x;
148835c4bbdfSmrg    WinBox.y1 = pDraw->y + drw_y;
148935c4bbdfSmrg    WinBox.x2 = WinBox.x1 + drw_w;
149035c4bbdfSmrg    WinBox.y2 = WinBox.y1 + drw_h;
149135c4bbdfSmrg
149235c4bbdfSmrg    RegionInit(&WinRegion, &WinBox, 1);
149335c4bbdfSmrg    RegionNull(&ClipRegion);
149435c4bbdfSmrg    RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
149535c4bbdfSmrg
149635c4bbdfSmrg    if (portPriv->pDraw) {
149735c4bbdfSmrg        xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
149835c4bbdfSmrg    }
149935c4bbdfSmrg
150035c4bbdfSmrg    if (!RegionNotEmpty(&ClipRegion)) {
150135c4bbdfSmrg        clippedAway = TRUE;
150235c4bbdfSmrg        goto GET_STILL_BAILOUT;
150335c4bbdfSmrg    }
150435c4bbdfSmrg
150535c4bbdfSmrg    ret = (*portPriv->AdaptorRec->GetStill) (portPriv->pScrn,
150635c4bbdfSmrg                                             vid_x, vid_y, WinBox.x1, WinBox.y1,
150735c4bbdfSmrg                                             vid_w, vid_h, drw_w, drw_h,
150835c4bbdfSmrg                                             &ClipRegion, portPriv->DevPriv.ptr,
150935c4bbdfSmrg                                             pDraw);
151035c4bbdfSmrg
151135c4bbdfSmrg GET_STILL_BAILOUT:
151205b261ecSmrg
151335c4bbdfSmrg    if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
151435c4bbdfSmrg        (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
151535c4bbdfSmrg                                            portPriv->DevPriv.ptr, FALSE);
151635c4bbdfSmrg        portPriv->isOn = XV_PENDING;
151735c4bbdfSmrg    }
151835c4bbdfSmrg
151935c4bbdfSmrg    RegionUninit(&WinRegion);
152035c4bbdfSmrg    RegionUninit(&ClipRegion);
152105b261ecSmrg
152235c4bbdfSmrg    return ret;
152335c4bbdfSmrg}
152405b261ecSmrg
152505b261ecSmrgstatic int
152635c4bbdfSmrgxf86XVStopVideo(XvPortPtr pPort, DrawablePtr pDraw)
152735c4bbdfSmrg{
152835c4bbdfSmrg    XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
152905b261ecSmrg
153035c4bbdfSmrg    if (pDraw->type != DRAWABLE_WINDOW)
153135c4bbdfSmrg        return BadAlloc;
153205b261ecSmrg
153335c4bbdfSmrg    xf86XVRemovePortFromWindow((WindowPtr) pDraw, portPriv);
153405b261ecSmrg
153535c4bbdfSmrg    if (!portPriv->pScrn->vtSema)
153635c4bbdfSmrg        return Success;         /* Success ? */
153705b261ecSmrg
153835c4bbdfSmrg    /* Must free resources. */
153905b261ecSmrg
154035c4bbdfSmrg    if (portPriv->isOn > XV_OFF) {
154135c4bbdfSmrg        (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
154235c4bbdfSmrg                                            portPriv->DevPriv.ptr, TRUE);
154335c4bbdfSmrg        portPriv->isOn = XV_OFF;
154435c4bbdfSmrg    }
154505b261ecSmrg
154635c4bbdfSmrg    return Success;
154705b261ecSmrg}
154805b261ecSmrg
154905b261ecSmrgstatic int
155035c4bbdfSmrgxf86XVSetPortAttribute(XvPortPtr pPort, Atom attribute, INT32 value)
155135c4bbdfSmrg{
155235c4bbdfSmrg    XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
155305b261ecSmrg
155435c4bbdfSmrg    return ((*portPriv->AdaptorRec->SetPortAttribute) (portPriv->pScrn,
155535c4bbdfSmrg                                                       attribute, value,
155635c4bbdfSmrg                                                       portPriv->DevPriv.ptr));
155735c4bbdfSmrg}
155805b261ecSmrg
155905b261ecSmrgstatic int
156035c4bbdfSmrgxf86XVGetPortAttribute(XvPortPtr pPort, Atom attribute, INT32 *p_value)
156135c4bbdfSmrg{
156235c4bbdfSmrg    XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
156335c4bbdfSmrg
156435c4bbdfSmrg    return ((*portPriv->AdaptorRec->GetPortAttribute) (portPriv->pScrn,
156535c4bbdfSmrg                                                       attribute, p_value,
156635c4bbdfSmrg                                                       portPriv->DevPriv.ptr));
156705b261ecSmrg}
156805b261ecSmrg
156935c4bbdfSmrgstatic int
157035c4bbdfSmrgxf86XVQueryBestSize(XvPortPtr pPort,
157135c4bbdfSmrg                    CARD8 motion,
157235c4bbdfSmrg                    CARD16 vid_w, CARD16 vid_h,
157335c4bbdfSmrg                    CARD16 drw_w, CARD16 drw_h,
157435c4bbdfSmrg                    unsigned int *p_w, unsigned int *p_h)
157535c4bbdfSmrg{
157635c4bbdfSmrg    XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
157705b261ecSmrg
157835c4bbdfSmrg    (*portPriv->AdaptorRec->QueryBestSize) (portPriv->pScrn,
157935c4bbdfSmrg                                            (Bool) motion, vid_w, vid_h, drw_w,
158035c4bbdfSmrg                                            drw_h, p_w, p_h,
158135c4bbdfSmrg                                            portPriv->DevPriv.ptr);
158205b261ecSmrg
158335c4bbdfSmrg    return Success;
158405b261ecSmrg}
158505b261ecSmrg
158605b261ecSmrgstatic int
158735c4bbdfSmrgxf86XVPutImage(DrawablePtr pDraw,
158835c4bbdfSmrg               XvPortPtr pPort,
158935c4bbdfSmrg               GCPtr pGC,
159035c4bbdfSmrg               INT16 src_x, INT16 src_y,
159135c4bbdfSmrg               CARD16 src_w, CARD16 src_h,
159235c4bbdfSmrg               INT16 drw_x, INT16 drw_y,
159335c4bbdfSmrg               CARD16 drw_w, CARD16 drw_h,
159435c4bbdfSmrg               XvImagePtr format,
159535c4bbdfSmrg               unsigned char *data, Bool sync, CARD16 width, CARD16 height)
159635c4bbdfSmrg{
159735c4bbdfSmrg    XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
159835c4bbdfSmrg    RegionRec WinRegion;
159935c4bbdfSmrg    RegionRec ClipRegion;
160035c4bbdfSmrg    BoxRec WinBox;
160135c4bbdfSmrg    int ret = Success;
160235c4bbdfSmrg    Bool clippedAway = FALSE;
160335c4bbdfSmrg
160435c4bbdfSmrg    if (pDraw->type != DRAWABLE_WINDOW)
160535c4bbdfSmrg        return BadAlloc;
160635c4bbdfSmrg
160735c4bbdfSmrg    if (!portPriv->pScrn->vtSema)
160835c4bbdfSmrg        return Success;         /* Success ? */
160935c4bbdfSmrg
161035c4bbdfSmrg    xf86XVCopyCompositeClip(portPriv, pGC, pDraw);
161135c4bbdfSmrg
161235c4bbdfSmrg    WinBox.x1 = pDraw->x + drw_x;
161335c4bbdfSmrg    WinBox.y1 = pDraw->y + drw_y;
161435c4bbdfSmrg    WinBox.x2 = WinBox.x1 + drw_w;
161535c4bbdfSmrg    WinBox.y2 = WinBox.y1 + drw_h;
161635c4bbdfSmrg
161735c4bbdfSmrg    RegionInit(&WinRegion, &WinBox, 1);
161835c4bbdfSmrg    RegionNull(&ClipRegion);
161935c4bbdfSmrg    RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
162035c4bbdfSmrg
162135c4bbdfSmrg    if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
162235c4bbdfSmrg        RegionRec VPReg;
162335c4bbdfSmrg        BoxRec VPBox;
162435c4bbdfSmrg
162535c4bbdfSmrg        VPBox.x1 = portPriv->pScrn->frameX0;
162635c4bbdfSmrg        VPBox.y1 = portPriv->pScrn->frameY0;
162735c4bbdfSmrg        VPBox.x2 = portPriv->pScrn->frameX1 + 1;
162835c4bbdfSmrg        VPBox.y2 = portPriv->pScrn->frameY1 + 1;
162935c4bbdfSmrg
163035c4bbdfSmrg        RegionInit(&VPReg, &VPBox, 1);
163135c4bbdfSmrg        RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
163235c4bbdfSmrg        RegionUninit(&VPReg);
163335c4bbdfSmrg    }
163435c4bbdfSmrg
163535c4bbdfSmrg    /* If we are changing windows, unregister our port in the old window */
163635c4bbdfSmrg    if (portPriv->pDraw && (portPriv->pDraw != pDraw))
163735c4bbdfSmrg        xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
163835c4bbdfSmrg
163935c4bbdfSmrg    /* Register our port with the new window */
164035c4bbdfSmrg    ret = xf86XVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
164135c4bbdfSmrg    if (ret != Success)
164235c4bbdfSmrg        goto PUT_IMAGE_BAILOUT;
164335c4bbdfSmrg
164435c4bbdfSmrg    if (!RegionNotEmpty(&ClipRegion)) {
164535c4bbdfSmrg        clippedAway = TRUE;
164635c4bbdfSmrg        goto PUT_IMAGE_BAILOUT;
164735c4bbdfSmrg    }
164835c4bbdfSmrg
164935c4bbdfSmrg    ret = (*portPriv->AdaptorRec->PutImage) (portPriv->pScrn,
165035c4bbdfSmrg                                             src_x, src_y, WinBox.x1, WinBox.y1,
165135c4bbdfSmrg                                             src_w, src_h, drw_w, drw_h,
165235c4bbdfSmrg                                             format->id, data, width, height,
165335c4bbdfSmrg                                             sync, &ClipRegion,
165435c4bbdfSmrg                                             portPriv->DevPriv.ptr, pDraw);
165535c4bbdfSmrg
165635c4bbdfSmrg    if ((ret == Success) &&
165735c4bbdfSmrg        (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) {
165835c4bbdfSmrg
165935c4bbdfSmrg        portPriv->isOn = XV_ON;
166035c4bbdfSmrg        portPriv->vid_x = src_x;
166135c4bbdfSmrg        portPriv->vid_y = src_y;
166235c4bbdfSmrg        portPriv->vid_w = src_w;
166335c4bbdfSmrg        portPriv->vid_h = src_h;
166435c4bbdfSmrg        portPriv->drw_x = drw_x;
166535c4bbdfSmrg        portPriv->drw_y = drw_y;
166635c4bbdfSmrg        portPriv->drw_w = drw_w;
166735c4bbdfSmrg        portPriv->drw_h = drw_h;
166835c4bbdfSmrg        portPriv->type = 0;     /* no mask means it's transient and should
166935c4bbdfSmrg                                   not be reput once it's removed */
167035c4bbdfSmrg        pPort->pDraw = pDraw;   /* make sure we can get stop requests */
167135c4bbdfSmrg    }
167235c4bbdfSmrg
167335c4bbdfSmrg PUT_IMAGE_BAILOUT:
167435c4bbdfSmrg
167535c4bbdfSmrg    if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
167635c4bbdfSmrg        (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
167735c4bbdfSmrg                                            portPriv->DevPriv.ptr, FALSE);
167835c4bbdfSmrg        portPriv->isOn = XV_PENDING;
167935c4bbdfSmrg    }
168035c4bbdfSmrg
168135c4bbdfSmrg    /* This clip was copied and only good for one shot */
168235c4bbdfSmrg    if (!portPriv->FreeCompositeClip)
168335c4bbdfSmrg        portPriv->pCompositeClip = NULL;
168435c4bbdfSmrg
168535c4bbdfSmrg    RegionUninit(&WinRegion);
168635c4bbdfSmrg    RegionUninit(&ClipRegion);
168735c4bbdfSmrg
168835c4bbdfSmrg    return ret;
168905b261ecSmrg}
169005b261ecSmrg
169135c4bbdfSmrgstatic int
169235c4bbdfSmrgxf86XVQueryImageAttributes(XvPortPtr pPort,
169335c4bbdfSmrg                           XvImagePtr format,
169435c4bbdfSmrg                           CARD16 *width,
169535c4bbdfSmrg                           CARD16 *height, int *pitches, int *offsets)
169635c4bbdfSmrg{
169735c4bbdfSmrg    XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
169805b261ecSmrg
169935c4bbdfSmrg    return (*portPriv->AdaptorRec->QueryImageAttributes) (portPriv->pScrn,
170035c4bbdfSmrg                                                          format->id, width,
170135c4bbdfSmrg                                                          height, pitches,
170235c4bbdfSmrg                                                          offsets);
170305b261ecSmrg}
170405b261ecSmrg
17056747b715Smrgvoid
170635c4bbdfSmrgxf86XVFillKeyHelperDrawable(DrawablePtr pDraw, CARD32 key, RegionPtr fillboxes)
170705b261ecSmrg{
170835c4bbdfSmrg    ScreenPtr pScreen = pDraw->pScreen;
170935c4bbdfSmrg
171035c4bbdfSmrg    if (!xf86ScreenToScrn(pScreen)->vtSema)
171135c4bbdfSmrg        return;
171235c4bbdfSmrg
171335c4bbdfSmrg    XvFillColorKey(pDraw, key, fillboxes);
171405b261ecSmrg}
171505b261ecSmrg
17169ace9065Smrgvoid
171735c4bbdfSmrgxf86XVFillKeyHelper(ScreenPtr pScreen, CARD32 key, RegionPtr fillboxes)
17189ace9065Smrg{
171935c4bbdfSmrg    xf86XVFillKeyHelperDrawable(&pScreen->root->drawable, key, fillboxes);
17209ace9065Smrg}
17219ace9065Smrg
17229ace9065Smrgvoid
172335c4bbdfSmrgxf86XVFillKeyHelperPort(DrawablePtr pDraw, void *data, CARD32 key,
172435c4bbdfSmrg                        RegionPtr clipboxes, Bool fillEverything)
17259ace9065Smrg{
172635c4bbdfSmrg    WindowPtr pWin = (WindowPtr) pDraw;
17279ace9065Smrg    XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
17289ace9065Smrg    XvPortRecPrivatePtr portPriv = NULL;
17299ace9065Smrg    RegionRec reg;
17309ace9065Smrg    RegionPtr fillboxes;
17319ace9065Smrg
17329ace9065Smrg    while (WinPriv) {
173335c4bbdfSmrg        XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
17349ace9065Smrg
173535c4bbdfSmrg        if (data == pPriv->DevPriv.ptr) {
173635c4bbdfSmrg            portPriv = pPriv;
173735c4bbdfSmrg            break;
173835c4bbdfSmrg        }
17399ace9065Smrg
174035c4bbdfSmrg        WinPriv = WinPriv->next;
17419ace9065Smrg    }
17429ace9065Smrg
17439ace9065Smrg    if (!portPriv)
174435c4bbdfSmrg        return;
17459ace9065Smrg
17469ace9065Smrg    if (!portPriv->ckeyFilled)
174735c4bbdfSmrg        portPriv->ckeyFilled = RegionCreate(NULL, 0);
17489ace9065Smrg
17499ace9065Smrg    if (!fillEverything) {
175035c4bbdfSmrg        RegionNull(&reg);
175135c4bbdfSmrg        fillboxes = &reg;
175235c4bbdfSmrg        RegionSubtract(fillboxes, clipboxes, portPriv->ckeyFilled);
17539ace9065Smrg
175435c4bbdfSmrg        if (!RegionNotEmpty(fillboxes))
175535c4bbdfSmrg            goto out;
175635c4bbdfSmrg    }
175735c4bbdfSmrg    else
175835c4bbdfSmrg        fillboxes = clipboxes;
17599ace9065Smrg
17609ace9065Smrg    RegionCopy(portPriv->ckeyFilled, clipboxes);
17619ace9065Smrg
17629ace9065Smrg    xf86XVFillKeyHelperDrawable(pDraw, key, fillboxes);
176335c4bbdfSmrg out:
17649ace9065Smrg    if (!fillEverything)
17659ace9065Smrg        RegionUninit(&reg);
17669ace9065Smrg}
17679ace9065Smrg
176805b261ecSmrg/* xf86XVClipVideoHelper -
176905b261ecSmrg
177005b261ecSmrg   Takes the dst box in standard X BoxRec form (top and left
177105b261ecSmrg   edges inclusive, bottom and right exclusive).  The new dst
177205b261ecSmrg   box is returned.  The source boundaries are given (x1, y1
177305b261ecSmrg   inclusive, x2, y2 exclusive) and returned are the new source
177405b261ecSmrg   boundaries in 16.16 fixed point.
177505b261ecSmrg*/
177605b261ecSmrg
17776747b715SmrgBool
177835c4bbdfSmrgxf86XVClipVideoHelper(BoxPtr dst,
177935c4bbdfSmrg                      INT32 *xa,
178035c4bbdfSmrg                      INT32 *xb,
178135c4bbdfSmrg                      INT32 *ya,
178235c4bbdfSmrg                      INT32 *yb, RegionPtr reg, INT32 width, INT32 height)
178335c4bbdfSmrg{
178405b261ecSmrg    double xsw, xdw, ysw, ydw;
178505b261ecSmrg    INT32 delta;
17866747b715Smrg    BoxPtr extents = RegionExtents(reg);
178705b261ecSmrg    int diff;
178805b261ecSmrg
178905b261ecSmrg    xsw = (*xb - *xa) << 16;
179005b261ecSmrg    xdw = dst->x2 - dst->x1;
179105b261ecSmrg    ysw = (*yb - *ya) << 16;
179205b261ecSmrg    ydw = dst->y2 - dst->y1;
179305b261ecSmrg
179435c4bbdfSmrg    *xa <<= 16;
179535c4bbdfSmrg    *xb <<= 16;
179635c4bbdfSmrg    *ya <<= 16;
179735c4bbdfSmrg    *yb <<= 16;
179805b261ecSmrg
179905b261ecSmrg    diff = extents->x1 - dst->x1;
180005b261ecSmrg    if (diff > 0) {
180135c4bbdfSmrg        dst->x1 = extents->x1;
180235c4bbdfSmrg        *xa += (diff * xsw) / xdw;
180305b261ecSmrg    }
180405b261ecSmrg    diff = dst->x2 - extents->x2;
180505b261ecSmrg    if (diff > 0) {
180635c4bbdfSmrg        dst->x2 = extents->x2;
180735c4bbdfSmrg        *xb -= (diff * xsw) / xdw;
180805b261ecSmrg    }
180905b261ecSmrg    diff = extents->y1 - dst->y1;
181005b261ecSmrg    if (diff > 0) {
181135c4bbdfSmrg        dst->y1 = extents->y1;
181235c4bbdfSmrg        *ya += (diff * ysw) / ydw;
181305b261ecSmrg    }
181405b261ecSmrg    diff = dst->y2 - extents->y2;
181505b261ecSmrg    if (diff > 0) {
181635c4bbdfSmrg        dst->y2 = extents->y2;
181735c4bbdfSmrg        *yb -= (diff * ysw) / ydw;
181805b261ecSmrg    }
181905b261ecSmrg
182005b261ecSmrg    if (*xa < 0) {
182135c4bbdfSmrg        diff = (((-*xa) * xdw) + xsw - 1) / xsw;
182235c4bbdfSmrg        dst->x1 += diff;
182335c4bbdfSmrg        *xa += (diff * xsw) / xdw;
182405b261ecSmrg    }
182505b261ecSmrg    delta = *xb - (width << 16);
182605b261ecSmrg    if (delta > 0) {
182735c4bbdfSmrg        diff = ((delta * xdw) + xsw - 1) / xsw;
182835c4bbdfSmrg        dst->x2 -= diff;
182935c4bbdfSmrg        *xb -= (diff * xsw) / xdw;
183005b261ecSmrg    }
183135c4bbdfSmrg    if (*xa >= *xb)
183235c4bbdfSmrg        return FALSE;
183305b261ecSmrg
183405b261ecSmrg    if (*ya < 0) {
183535c4bbdfSmrg        diff = (((-*ya) * ydw) + ysw - 1) / ysw;
183635c4bbdfSmrg        dst->y1 += diff;
183735c4bbdfSmrg        *ya += (diff * ysw) / ydw;
183805b261ecSmrg    }
183905b261ecSmrg    delta = *yb - (height << 16);
184005b261ecSmrg    if (delta > 0) {
184135c4bbdfSmrg        diff = ((delta * ydw) + ysw - 1) / ysw;
184235c4bbdfSmrg        dst->y2 -= diff;
184335c4bbdfSmrg        *yb -= (diff * ysw) / ydw;
184405b261ecSmrg    }
184535c4bbdfSmrg    if (*ya >= *yb)
184635c4bbdfSmrg        return FALSE;
184705b261ecSmrg
184805b261ecSmrg    if ((dst->x1 > extents->x1) || (dst->x2 < extents->x2) ||
184935c4bbdfSmrg        (dst->y1 > extents->y1) || (dst->y2 < extents->y2)) {
185035c4bbdfSmrg        RegionRec clipReg;
185135c4bbdfSmrg
185235c4bbdfSmrg        RegionInit(&clipReg, dst, 1);
185335c4bbdfSmrg        RegionIntersect(reg, reg, &clipReg);
185435c4bbdfSmrg        RegionUninit(&clipReg);
185505b261ecSmrg    }
185605b261ecSmrg    return TRUE;
185705b261ecSmrg}
185805b261ecSmrg
18596747b715Smrgvoid
186035c4bbdfSmrgxf86XVCopyYUV12ToPacked(const void *srcy,
186135c4bbdfSmrg                        const void *srcv,
186235c4bbdfSmrg                        const void *srcu,
186335c4bbdfSmrg                        void *dst,
186435c4bbdfSmrg                        int srcPitchy,
186535c4bbdfSmrg                        int srcPitchuv, int dstPitch, int h, int w)
186635c4bbdfSmrg{
186705b261ecSmrg    CARD32 *Dst;
186805b261ecSmrg    const CARD8 *Y, *U, *V;
186905b261ecSmrg    int i, j;
187005b261ecSmrg
187105b261ecSmrg    w >>= 1;
187205b261ecSmrg
187335c4bbdfSmrg    for (j = 0; j < h; j++) {
187435c4bbdfSmrg        Dst = dst;
187535c4bbdfSmrg        Y = srcy;
187635c4bbdfSmrg        V = srcv;
187735c4bbdfSmrg        U = srcu;
187835c4bbdfSmrg        i = w;
187935c4bbdfSmrg        while (i >= 4) {
188005b261ecSmrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN
188135c4bbdfSmrg            Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24);
188235c4bbdfSmrg            Dst[1] = Y[2] | (Y[3] << 16) | (U[1] << 8) | (V[1] << 24);
188335c4bbdfSmrg            Dst[2] = Y[4] | (Y[5] << 16) | (U[2] << 8) | (V[2] << 24);
188435c4bbdfSmrg            Dst[3] = Y[6] | (Y[7] << 16) | (U[3] << 8) | (V[3] << 24);
188505b261ecSmrg#else
188635c4bbdfSmrg            /* This assumes a little-endian framebuffer */
188735c4bbdfSmrg            Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0];
188835c4bbdfSmrg            Dst[1] = (Y[2] << 24) | (Y[3] << 8) | (U[1] << 16) | V[1];
188935c4bbdfSmrg            Dst[2] = (Y[4] << 24) | (Y[5] << 8) | (U[2] << 16) | V[2];
189035c4bbdfSmrg            Dst[3] = (Y[6] << 24) | (Y[7] << 8) | (U[3] << 16) | V[3];
189105b261ecSmrg#endif
189235c4bbdfSmrg            Dst += 4;
189335c4bbdfSmrg            Y += 8;
189435c4bbdfSmrg            V += 4;
189535c4bbdfSmrg            U += 4;
189635c4bbdfSmrg            i -= 4;
189735c4bbdfSmrg        }
189835c4bbdfSmrg
189935c4bbdfSmrg        while (i--) {
190005b261ecSmrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN
190135c4bbdfSmrg            Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24);
190205b261ecSmrg#else
190335c4bbdfSmrg            /* This assumes a little-endian framebuffer */
190435c4bbdfSmrg            Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0];
190505b261ecSmrg#endif
190635c4bbdfSmrg            Dst++;
190735c4bbdfSmrg            Y += 2;
190835c4bbdfSmrg            V++;
190935c4bbdfSmrg            U++;
191035c4bbdfSmrg        }
191135c4bbdfSmrg
191235c4bbdfSmrg        dst = (CARD8 *) dst + dstPitch;
191335c4bbdfSmrg        srcy = (const CARD8 *) srcy + srcPitchy;
191435c4bbdfSmrg        if (j & 1) {
191535c4bbdfSmrg            srcu = (const CARD8 *) srcu + srcPitchuv;
191635c4bbdfSmrg            srcv = (const CARD8 *) srcv + srcPitchuv;
191735c4bbdfSmrg        }
191805b261ecSmrg    }
191905b261ecSmrg}
192005b261ecSmrg
19216747b715Smrgvoid
192235c4bbdfSmrgxf86XVCopyPacked(const void *src,
192335c4bbdfSmrg                 void *dst, int srcPitch, int dstPitch, int h, int w)
192435c4bbdfSmrg{
192505b261ecSmrg    const CARD32 *Src;
192605b261ecSmrg    CARD32 *Dst;
192705b261ecSmrg    int i;
192805b261ecSmrg
192905b261ecSmrg    w >>= 1;
193005b261ecSmrg    while (--h >= 0) {
193135c4bbdfSmrg        do {
193235c4bbdfSmrg            Dst = dst;
193335c4bbdfSmrg            Src = src;
193435c4bbdfSmrg            i = w;
193535c4bbdfSmrg            while (i >= 4) {
193635c4bbdfSmrg                Dst[0] = Src[0];
193735c4bbdfSmrg                Dst[1] = Src[1];
193835c4bbdfSmrg                Dst[2] = Src[2];
193935c4bbdfSmrg                Dst[3] = Src[3];
194035c4bbdfSmrg                Dst += 4;
194135c4bbdfSmrg                Src += 4;
194235c4bbdfSmrg                i -= 4;
194335c4bbdfSmrg            }
194435c4bbdfSmrg            if (!i)
194535c4bbdfSmrg                break;
194635c4bbdfSmrg            Dst[0] = Src[0];
194735c4bbdfSmrg            if (i == 1)
194835c4bbdfSmrg                break;
194935c4bbdfSmrg            Dst[1] = Src[1];
195035c4bbdfSmrg            if (i == 2)
195135c4bbdfSmrg                break;
195235c4bbdfSmrg            Dst[2] = Src[2];
195335c4bbdfSmrg        } while (0);
195435c4bbdfSmrg
195535c4bbdfSmrg        src = (const CARD8 *) src + srcPitch;
195635c4bbdfSmrg        dst = (CARD8 *) dst + dstPitch;
195705b261ecSmrg    }
195805b261ecSmrg}
1959