xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

xf86xv.c (60485B)


      1 /*
      2  * XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com)
      3  */
      4 /*
      5  * Copyright (c) 1998-2003 by The XFree86 Project, Inc.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included in
     15  * all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     23  * OTHER DEALINGS IN THE SOFTWARE.
     24  *
     25  * Except as contained in this notice, the name of the copyright holder(s)
     26  * and author(s) shall not be used in advertising or otherwise to promote
     27  * the sale, use or other dealings in this Software without prior written
     28  * authorization from the copyright holder(s) and author(s).
     29  */
     30 
     31 #ifdef HAVE_XORG_CONFIG_H
     32 #include <xorg-config.h>
     33 #endif
     34 
     35 #include "misc.h"
     36 #include "xf86.h"
     37 #include "xf86_OSproc.h"
     38 
     39 #include <X11/X.h>
     40 #include <X11/Xproto.h>
     41 #include "scrnintstr.h"
     42 #include "regionstr.h"
     43 #include "windowstr.h"
     44 #include "pixmapstr.h"
     45 #include "mivalidate.h"
     46 #include "validate.h"
     47 #include "resource.h"
     48 #include "gcstruct.h"
     49 #include "dixstruct.h"
     50 
     51 #include <X11/extensions/Xv.h>
     52 #include <X11/extensions/Xvproto.h>
     53 #include "xvdix.h"
     54 
     55 #include "xf86xvpriv.h"
     56 
     57 /* XvAdaptorRec fields */
     58 
     59 static int xf86XVPutVideo(DrawablePtr, XvPortPtr, GCPtr,
     60                           INT16, INT16, CARD16, CARD16,
     61                           INT16, INT16, CARD16, CARD16);
     62 static int xf86XVPutStill(DrawablePtr, XvPortPtr, GCPtr,
     63                           INT16, INT16, CARD16, CARD16,
     64                           INT16, INT16, CARD16, CARD16);
     65 static int xf86XVGetVideo(DrawablePtr, XvPortPtr, GCPtr,
     66                           INT16, INT16, CARD16, CARD16,
     67                           INT16, INT16, CARD16, CARD16);
     68 static int xf86XVGetStill(DrawablePtr, XvPortPtr, GCPtr,
     69                           INT16, INT16, CARD16, CARD16,
     70                           INT16, INT16, CARD16, CARD16);
     71 static int xf86XVStopVideo(XvPortPtr, DrawablePtr);
     72 static int xf86XVSetPortAttribute(XvPortPtr, Atom, INT32);
     73 static int xf86XVGetPortAttribute(XvPortPtr, Atom, INT32 *);
     74 static int xf86XVQueryBestSize(XvPortPtr, CARD8,
     75                                CARD16, CARD16, CARD16, CARD16,
     76                                unsigned int *, unsigned int *);
     77 static int xf86XVPutImage(DrawablePtr, XvPortPtr, GCPtr,
     78                           INT16, INT16, CARD16, CARD16,
     79                           INT16, INT16, CARD16, CARD16,
     80                           XvImagePtr, unsigned char *, Bool, CARD16, CARD16);
     81 static int xf86XVQueryImageAttributes(XvPortPtr, XvImagePtr,
     82                                       CARD16 *, CARD16 *, int *, int *);
     83 
     84 /* ScreenRec fields */
     85 
     86 static Bool xf86XVDestroyWindow(WindowPtr pWin);
     87 static void xf86XVWindowExposures(WindowPtr pWin, RegionPtr r1);
     88 static void xf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin,
     89                                    VTKind kind);
     90 static void xf86XVClipNotify(WindowPtr pWin, int dx, int dy);
     91 static Bool xf86XVCloseScreen(ScreenPtr);
     92 
     93 #define PostValidateTreeUndefined ((PostValidateTreeProcPtr)-1)
     94 
     95 /* ScrnInfoRec functions */
     96 
     97 static Bool xf86XVEnterVT(ScrnInfoPtr);
     98 static void xf86XVLeaveVT(ScrnInfoPtr);
     99 static void xf86XVAdjustFrame(ScrnInfoPtr, int x, int y);
    100 static void xf86XVModeSet(ScrnInfoPtr pScrn);
    101 
    102 /* misc */
    103 
    104 static Bool xf86XVInitAdaptors(ScreenPtr, XF86VideoAdaptorPtr *, int);
    105 
    106 static DevPrivateKeyRec XF86XVWindowKeyRec;
    107 
    108 #define XF86XVWindowKey (&XF86XVWindowKeyRec)
    109 
    110 /* dixmain.c XvScreenPtr screen private */
    111 DevPrivateKey XF86XvScreenKey;
    112 /** xf86xv.c XF86XVScreenPtr screen private */
    113 static DevPrivateKeyRec XF86XVScreenPrivateKey;
    114 
    115 static unsigned long PortResource = 0;
    116 
    117 #define GET_XV_SCREEN(pScreen) \
    118     ((XvScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, XF86XvScreenKey))
    119 
    120 #define GET_XF86XV_SCREEN(pScreen) \
    121     ((XF86XVScreenPtr)(dixGetPrivate(&pScreen->devPrivates, &XF86XVScreenPrivateKey)))
    122 
    123 #define GET_XF86XV_WINDOW(pWin) \
    124     ((XF86XVWindowPtr)dixLookupPrivate(&(pWin)->devPrivates, XF86XVWindowKey))
    125 
    126 static xf86XVInitGenericAdaptorPtr *GenDrivers = NULL;
    127 static int NumGenDrivers = 0;
    128 
    129 int
    130 xf86XVRegisterGenericAdaptorDriver(xf86XVInitGenericAdaptorPtr InitFunc)
    131 {
    132     xf86XVInitGenericAdaptorPtr *newdrivers;
    133 
    134     newdrivers = reallocarray(GenDrivers, 1 + NumGenDrivers,
    135                               sizeof(xf86XVInitGenericAdaptorPtr));
    136     if (!newdrivers)
    137         return 0;
    138     GenDrivers = newdrivers;
    139 
    140     GenDrivers[NumGenDrivers++] = InitFunc;
    141 
    142     return 1;
    143 }
    144 
    145 int
    146 xf86XVListGenericAdaptors(ScrnInfoPtr pScrn, XF86VideoAdaptorPtr ** adaptors)
    147 {
    148     int i, j, n, num;
    149     XF86VideoAdaptorPtr *DrivAdap, *new;
    150 
    151     num = 0;
    152     *adaptors = NULL;
    153     /*
    154      * The v4l driver registers itself first, but can use surfaces registered
    155      * by other drivers.  So, call the v4l driver last.
    156      */
    157     for (i = NumGenDrivers; --i >= 0;) {
    158         DrivAdap = NULL;
    159         n = (*GenDrivers[i]) (pScrn, &DrivAdap);
    160         if (0 == n)
    161             continue;
    162         new = reallocarray(*adaptors, num + n, sizeof(XF86VideoAdaptorPtr));
    163         if (NULL == new)
    164             continue;
    165         *adaptors = new;
    166         for (j = 0; j < n; j++, num++)
    167             (*adaptors)[num] = DrivAdap[j];
    168     }
    169     return num;
    170 }
    171 
    172 /****************  Offscreen surface stuff *******************/
    173 
    174 typedef struct {
    175     XF86OffscreenImagePtr images;
    176     int num;
    177 } OffscreenImageRec;
    178 
    179 static DevPrivateKeyRec OffscreenPrivateKeyRec;
    180 
    181 #define OffscreenPrivateKey (&OffscreenPrivateKeyRec)
    182 #define GetOffscreenImage(pScreen) ((OffscreenImageRec *) dixLookupPrivate(&(pScreen)->devPrivates, OffscreenPrivateKey))
    183 
    184 Bool
    185 xf86XVRegisterOffscreenImages(ScreenPtr pScreen,
    186                               XF86OffscreenImagePtr images, int num)
    187 {
    188     OffscreenImageRec *OffscreenImage;
    189 
    190     /* This function may be called before xf86XVScreenInit, so there's
    191      * no better place than this to call dixRegisterPrivateKey to ensure we
    192      * have space reserved. After the first call it is a no-op. */
    193     if (!dixRegisterPrivateKey
    194         (OffscreenPrivateKey, PRIVATE_SCREEN, sizeof(OffscreenImageRec)) ||
    195         !(OffscreenImage = GetOffscreenImage(pScreen)))
    196         /* Every X.org driver assumes this function always succeeds, so
    197          * just die on allocation failure. */
    198         FatalError
    199             ("Could not allocate private storage for XV offscreen images.\n");
    200 
    201     OffscreenImage->num = num;
    202     OffscreenImage->images = images;
    203     return TRUE;
    204 }
    205 
    206 XF86OffscreenImagePtr
    207 xf86XVQueryOffscreenImages(ScreenPtr pScreen, int *num)
    208 {
    209     OffscreenImageRec *OffscreenImage = GetOffscreenImage(pScreen);
    210 
    211     *num = OffscreenImage->num;
    212     return OffscreenImage->images;
    213 }
    214 
    215 XF86VideoAdaptorPtr
    216 xf86XVAllocateVideoAdaptorRec(ScrnInfoPtr pScrn)
    217 {
    218     return calloc(1, sizeof(XF86VideoAdaptorRec));
    219 }
    220 
    221 void
    222 xf86XVFreeVideoAdaptorRec(XF86VideoAdaptorPtr ptr)
    223 {
    224     free(ptr);
    225 }
    226 
    227 Bool
    228 xf86XVScreenInit(ScreenPtr pScreen, XF86VideoAdaptorPtr * adaptors, int num)
    229 {
    230     ScrnInfoPtr pScrn;
    231     XF86XVScreenPtr ScreenPriv;
    232 
    233     if (num <= 0 || noXvExtension)
    234         return FALSE;
    235 
    236     if (Success != XvScreenInit(pScreen))
    237         return FALSE;
    238 
    239     if (!dixRegisterPrivateKey(&XF86XVWindowKeyRec, PRIVATE_WINDOW, 0))
    240         return FALSE;
    241     if (!dixRegisterPrivateKey(&XF86XVScreenPrivateKey, PRIVATE_SCREEN, 0))
    242         return FALSE;
    243 
    244     XF86XvScreenKey = XvGetScreenKey();
    245 
    246     PortResource = XvGetRTPort();
    247 
    248     ScreenPriv = malloc(sizeof(XF86XVScreenRec));
    249     dixSetPrivate(&pScreen->devPrivates, &XF86XVScreenPrivateKey, ScreenPriv);
    250 
    251     if (!ScreenPriv)
    252         return FALSE;
    253 
    254     pScrn = xf86ScreenToScrn(pScreen);
    255 
    256     ScreenPriv->DestroyWindow = pScreen->DestroyWindow;
    257     ScreenPriv->WindowExposures = pScreen->WindowExposures;
    258     ScreenPriv->PostValidateTree = PostValidateTreeUndefined;
    259     ScreenPriv->ClipNotify = pScreen->ClipNotify;
    260     ScreenPriv->CloseScreen = pScreen->CloseScreen;
    261     ScreenPriv->EnterVT = pScrn->EnterVT;
    262     ScreenPriv->LeaveVT = pScrn->LeaveVT;
    263     ScreenPriv->AdjustFrame = pScrn->AdjustFrame;
    264     ScreenPriv->ModeSet = pScrn->ModeSet;
    265 
    266     pScreen->DestroyWindow = xf86XVDestroyWindow;
    267     pScreen->WindowExposures = xf86XVWindowExposures;
    268     pScreen->ClipNotify = xf86XVClipNotify;
    269     pScreen->CloseScreen = xf86XVCloseScreen;
    270     pScrn->EnterVT = xf86XVEnterVT;
    271     pScrn->LeaveVT = xf86XVLeaveVT;
    272     if (pScrn->AdjustFrame)
    273         pScrn->AdjustFrame = xf86XVAdjustFrame;
    274     pScrn->ModeSet = xf86XVModeSet;
    275 
    276     if (!xf86XVInitAdaptors(pScreen, adaptors, num))
    277         return FALSE;
    278 
    279     return TRUE;
    280 }
    281 
    282 static void
    283 xf86XVFreeAdaptor(XvAdaptorPtr pAdaptor)
    284 {
    285     int i;
    286 
    287     if (pAdaptor->pPorts) {
    288         XvPortPtr pPort = pAdaptor->pPorts;
    289         XvPortRecPrivatePtr pPriv;
    290 
    291         for (i = 0; i < pAdaptor->nPorts; i++, pPort++) {
    292             pPriv = (XvPortRecPrivatePtr) pPort->devPriv.ptr;
    293             if (pPriv) {
    294                 if (pPriv->clientClip)
    295                     RegionDestroy(pPriv->clientClip);
    296                 if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
    297                     RegionDestroy(pPriv->pCompositeClip);
    298                 if (pPriv->ckeyFilled)
    299                     RegionDestroy(pPriv->ckeyFilled);
    300                 free(pPriv);
    301             }
    302         }
    303     }
    304 
    305     XvFreeAdaptor(pAdaptor);
    306 }
    307 
    308 static Bool
    309 xf86XVInitAdaptors(ScreenPtr pScreen, XF86VideoAdaptorPtr * infoPtr, int number)
    310 {
    311     XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
    312     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    313     XF86VideoAdaptorPtr adaptorPtr;
    314     XvAdaptorPtr pAdaptor, pa;
    315     XvAdaptorRecPrivatePtr adaptorPriv;
    316     int na, numAdaptor;
    317     XvPortRecPrivatePtr portPriv;
    318     XvPortPtr pPort, pp;
    319     int numPort;
    320     XF86VideoFormatPtr formatPtr;
    321     XvFormatPtr pFormat, pf;
    322     int numFormat, totFormat;
    323     XF86VideoEncodingPtr encodingPtr;
    324     XvEncodingPtr pEncode, pe;
    325     int numVisuals;
    326     VisualPtr pVisual;
    327     int i;
    328 
    329     pxvs->nAdaptors = 0;
    330     pxvs->pAdaptors = NULL;
    331 
    332     if (!(pAdaptor = calloc(number, sizeof(XvAdaptorRec))))
    333         return FALSE;
    334 
    335     for (pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) {
    336         adaptorPtr = infoPtr[na];
    337 
    338         if (!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute ||
    339             !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize)
    340             continue;
    341 
    342         /* client libs expect at least one encoding */
    343         if (!adaptorPtr->nEncodings || !adaptorPtr->pEncodings)
    344             continue;
    345 
    346         pa->type = adaptorPtr->type;
    347 
    348         if (!adaptorPtr->PutVideo && !adaptorPtr->GetVideo)
    349             pa->type &= ~XvVideoMask;
    350 
    351         if (!adaptorPtr->PutStill && !adaptorPtr->GetStill)
    352             pa->type &= ~XvStillMask;
    353 
    354         if (!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes)
    355             pa->type &= ~XvImageMask;
    356 
    357         if (!adaptorPtr->PutVideo && !adaptorPtr->PutImage &&
    358             !adaptorPtr->PutStill)
    359             pa->type &= ~XvInputMask;
    360 
    361         if (!adaptorPtr->GetVideo && !adaptorPtr->GetStill)
    362             pa->type &= ~XvOutputMask;
    363 
    364         if (!(adaptorPtr->type & (XvPixmapMask | XvWindowMask)))
    365             continue;
    366         if (!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask)))
    367             continue;
    368 
    369         pa->pScreen = pScreen;
    370         pa->ddPutVideo = xf86XVPutVideo;
    371         pa->ddPutStill = xf86XVPutStill;
    372         pa->ddGetVideo = xf86XVGetVideo;
    373         pa->ddGetStill = xf86XVGetStill;
    374         pa->ddStopVideo = xf86XVStopVideo;
    375         pa->ddPutImage = xf86XVPutImage;
    376         pa->ddSetPortAttribute = xf86XVSetPortAttribute;
    377         pa->ddGetPortAttribute = xf86XVGetPortAttribute;
    378         pa->ddQueryBestSize = xf86XVQueryBestSize;
    379         pa->ddQueryImageAttributes = xf86XVQueryImageAttributes;
    380         pa->name = strdup(adaptorPtr->name);
    381 
    382         if (adaptorPtr->nEncodings &&
    383             (pEncode = calloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) {
    384 
    385             for (pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0;
    386                  i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++) {
    387                 pe->id = encodingPtr->id;
    388                 pe->pScreen = pScreen;
    389                 pe->name = strdup(encodingPtr->name);
    390                 pe->width = encodingPtr->width;
    391                 pe->height = encodingPtr->height;
    392                 pe->rate.numerator = encodingPtr->rate.numerator;
    393                 pe->rate.denominator = encodingPtr->rate.denominator;
    394             }
    395             pa->nEncodings = adaptorPtr->nEncodings;
    396             pa->pEncodings = pEncode;
    397         }
    398 
    399         if (adaptorPtr->nImages &&
    400             (pa->pImages = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
    401             memcpy(pa->pImages, adaptorPtr->pImages,
    402                    adaptorPtr->nImages * sizeof(XvImageRec));
    403             pa->nImages = adaptorPtr->nImages;
    404         }
    405 
    406         if (adaptorPtr->nAttributes &&
    407             (pa->pAttributes = calloc(adaptorPtr->nAttributes,
    408                                       sizeof(XvAttributeRec)))) {
    409             memcpy(pa->pAttributes, adaptorPtr->pAttributes,
    410                    adaptorPtr->nAttributes * sizeof(XvAttributeRec));
    411 
    412             for (i = 0; i < adaptorPtr->nAttributes; i++) {
    413                 pa->pAttributes[i].name =
    414                     strdup(adaptorPtr->pAttributes[i].name);
    415             }
    416 
    417             pa->nAttributes = adaptorPtr->nAttributes;
    418         }
    419 
    420         totFormat = adaptorPtr->nFormats;
    421 
    422         if (!(pFormat = calloc(totFormat, sizeof(XvFormatRec)))) {
    423             xf86XVFreeAdaptor(pa);
    424             continue;
    425         }
    426         for (pf = pFormat, i = 0, numFormat = 0, formatPtr =
    427              adaptorPtr->pFormats; i < adaptorPtr->nFormats; i++, formatPtr++) {
    428             numVisuals = pScreen->numVisuals;
    429             pVisual = pScreen->visuals;
    430 
    431             while (numVisuals--) {
    432                 if ((pVisual->class == formatPtr->class) &&
    433                     (pVisual->nplanes == formatPtr->depth)) {
    434 
    435                     if (numFormat >= totFormat) {
    436                         void *moreSpace;
    437 
    438                         totFormat *= 2;
    439                         moreSpace = reallocarray(pFormat, totFormat,
    440                                                  sizeof(XvFormatRec));
    441                         if (!moreSpace)
    442                             break;
    443                         pFormat = moreSpace;
    444                         pf = pFormat + numFormat;
    445                     }
    446 
    447                     pf->visual = pVisual->vid;
    448                     pf->depth = formatPtr->depth;
    449 
    450                     pf++;
    451                     numFormat++;
    452                 }
    453                 pVisual++;
    454             }
    455         }
    456         pa->nFormats = numFormat;
    457         pa->pFormats = pFormat;
    458         if (!numFormat) {
    459             xf86XVFreeAdaptor(pa);
    460             continue;
    461         }
    462 
    463         if (!(adaptorPriv = calloc(1, sizeof(XvAdaptorRecPrivate)))) {
    464             xf86XVFreeAdaptor(pa);
    465             continue;
    466         }
    467 
    468         adaptorPriv->flags = adaptorPtr->flags;
    469         adaptorPriv->PutVideo = adaptorPtr->PutVideo;
    470         adaptorPriv->PutStill = adaptorPtr->PutStill;
    471         adaptorPriv->GetVideo = adaptorPtr->GetVideo;
    472         adaptorPriv->GetStill = adaptorPtr->GetStill;
    473         adaptorPriv->StopVideo = adaptorPtr->StopVideo;
    474         adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute;
    475         adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute;
    476         adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize;
    477         adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes;
    478         adaptorPriv->PutImage = adaptorPtr->PutImage;
    479         adaptorPriv->ReputImage = adaptorPtr->ReputImage;       /* image/still */
    480 
    481         pa->devPriv.ptr = (void *) adaptorPriv;
    482 
    483         if (!(pPort = calloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) {
    484             xf86XVFreeAdaptor(pa);
    485             continue;
    486         }
    487         for (pp = pPort, i = 0, numPort = 0; i < adaptorPtr->nPorts; i++) {
    488 
    489             if (!(pp->id = FakeClientID(0)))
    490                 continue;
    491 
    492             if (!(portPriv = calloc(1, sizeof(XvPortRecPrivate))))
    493                 continue;
    494 
    495             if (!AddResource(pp->id, PortResource, pp)) {
    496                 free(portPriv);
    497                 continue;
    498             }
    499 
    500             pp->pAdaptor = pa;
    501             pp->pNotify = (XvPortNotifyPtr) NULL;
    502             pp->pDraw = (DrawablePtr) NULL;
    503             pp->client = (ClientPtr) NULL;
    504             pp->grab.client = (ClientPtr) NULL;
    505             pp->time = currentTime;
    506             pp->devPriv.ptr = portPriv;
    507 
    508             portPriv->pScrn = pScrn;
    509             portPriv->AdaptorRec = adaptorPriv;
    510             portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr;
    511 
    512             pp++;
    513             numPort++;
    514         }
    515         pa->nPorts = numPort;
    516         pa->pPorts = pPort;
    517         if (!numPort) {
    518             xf86XVFreeAdaptor(pa);
    519             continue;
    520         }
    521 
    522         pa->base_id = pPort->id;
    523 
    524         pa++;
    525         numAdaptor++;
    526     }
    527 
    528     if (numAdaptor) {
    529         pxvs->nAdaptors = numAdaptor;
    530         pxvs->pAdaptors = pAdaptor;
    531     }
    532     else {
    533         free(pAdaptor);
    534         return FALSE;
    535     }
    536 
    537     return TRUE;
    538 }
    539 
    540 /* Video should be clipped to the intersection of the window cliplist
    541    and the client cliplist specified in the GC for which the video was
    542    initialized.  When we need to reclip a window, the GC that started
    543    the video may not even be around anymore.  That's why we save the
    544    client clip from the GC when the video is initialized.  We then
    545    use xf86XVUpdateCompositeClip to calculate the new composite clip
    546    when we need it.  This is different from what DEC did.  They saved
    547    the GC and used its clip list when they needed to reclip the window,
    548    even if the client clip was different from the one the video was
    549    initialized with.  If the original GC was destroyed, they had to stop
    550    the video.  I like the new method better (MArk).
    551 
    552    This function only works for windows.  Will need to rewrite when
    553    (if) we support pixmap rendering.
    554 */
    555 
    556 static void
    557 xf86XVUpdateCompositeClip(XvPortRecPrivatePtr portPriv)
    558 {
    559     RegionPtr pregWin, pCompositeClip;
    560     WindowPtr pWin;
    561     Bool freeCompClip = FALSE;
    562 
    563     if (portPriv->pCompositeClip)
    564         return;
    565 
    566     pWin = (WindowPtr) portPriv->pDraw;
    567 
    568     /* get window clip list */
    569     if (portPriv->subWindowMode == IncludeInferiors) {
    570         pregWin = NotClippedByChildren(pWin);
    571         freeCompClip = TRUE;
    572     }
    573     else
    574         pregWin = &pWin->clipList;
    575 
    576     if (!portPriv->clientClip) {
    577         portPriv->pCompositeClip = pregWin;
    578         portPriv->FreeCompositeClip = freeCompClip;
    579         return;
    580     }
    581 
    582     pCompositeClip = RegionCreate(NullBox, 1);
    583     RegionCopy(pCompositeClip, portPriv->clientClip);
    584     RegionTranslate(pCompositeClip, portPriv->pDraw->x, portPriv->pDraw->y);
    585     RegionIntersect(pCompositeClip, pregWin, pCompositeClip);
    586 
    587     portPriv->pCompositeClip = pCompositeClip;
    588     portPriv->FreeCompositeClip = TRUE;
    589 
    590     if (freeCompClip) {
    591         RegionDestroy(pregWin);
    592     }
    593 }
    594 
    595 /* Save the current clientClip and update the CompositeClip whenever
    596    we have a fresh GC */
    597 
    598 static void
    599 xf86XVCopyClip(XvPortRecPrivatePtr portPriv, GCPtr pGC)
    600 {
    601     /* copy the new clip if it exists */
    602     if (pGC->clientClip) {
    603         if (!portPriv->clientClip)
    604             portPriv->clientClip = RegionCreate(NullBox, 1);
    605         /* Note: this is in window coordinates */
    606         RegionCopy(portPriv->clientClip, pGC->clientClip);
    607         RegionTranslate(portPriv->clientClip, pGC->clipOrg.x, pGC->clipOrg.y);
    608     }
    609     else if (portPriv->clientClip) {    /* free the old clientClip */
    610         RegionDestroy(portPriv->clientClip);
    611         portPriv->clientClip = NULL;
    612     }
    613 
    614     /* get rid of the old clip list */
    615     if (portPriv->pCompositeClip && portPriv->FreeCompositeClip) {
    616         RegionDestroy(portPriv->pCompositeClip);
    617     }
    618 
    619     portPriv->pCompositeClip = pGC->pCompositeClip;
    620     portPriv->FreeCompositeClip = FALSE;
    621     portPriv->subWindowMode = pGC->subWindowMode;
    622 }
    623 
    624 static void
    625 xf86XVCopyCompositeClip(XvPortRecPrivatePtr portPriv,
    626                         GCPtr pGC, DrawablePtr pDraw)
    627 {
    628     if (!portPriv->clientClip)
    629         portPriv->clientClip = RegionCreate(NullBox, 1);
    630     /* Keep the original GC composite clip around for ReputImage */
    631     RegionCopy(portPriv->clientClip, pGC->pCompositeClip);
    632     RegionTranslate(portPriv->clientClip, -pDraw->x, -pDraw->y);
    633 
    634     /* get rid of the old clip list */
    635     if (portPriv->pCompositeClip && portPriv->FreeCompositeClip)
    636         RegionDestroy(portPriv->pCompositeClip);
    637 
    638     portPriv->pCompositeClip = pGC->pCompositeClip;
    639     portPriv->FreeCompositeClip = FALSE;
    640     portPriv->subWindowMode = pGC->subWindowMode;
    641 }
    642 
    643 static int
    644 xf86XVRegetVideo(XvPortRecPrivatePtr portPriv)
    645 {
    646     RegionRec WinRegion;
    647     RegionRec ClipRegion;
    648     BoxRec WinBox;
    649     int ret = Success;
    650     Bool clippedAway = FALSE;
    651 
    652     xf86XVUpdateCompositeClip(portPriv);
    653 
    654     /* translate the video region to the screen */
    655     WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
    656     WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
    657     WinBox.x2 = WinBox.x1 + portPriv->drw_w;
    658     WinBox.y2 = WinBox.y1 + portPriv->drw_h;
    659 
    660     /* clip to the window composite clip */
    661     RegionInit(&WinRegion, &WinBox, 1);
    662     RegionNull(&ClipRegion);
    663     RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
    664 
    665     /* that's all if it's totally obscured */
    666     if (!RegionNotEmpty(&ClipRegion)) {
    667         clippedAway = TRUE;
    668         goto CLIP_VIDEO_BAILOUT;
    669     }
    670 
    671     ret = (*portPriv->AdaptorRec->GetVideo) (portPriv->pScrn,
    672                                              portPriv->vid_x, portPriv->vid_y,
    673                                              WinBox.x1, WinBox.y1,
    674                                              portPriv->vid_w, portPriv->vid_h,
    675                                              portPriv->drw_w, portPriv->drw_h,
    676                                              &ClipRegion, portPriv->DevPriv.ptr,
    677                                              portPriv->pDraw);
    678 
    679     if (ret == Success)
    680         portPriv->isOn = XV_ON;
    681 
    682  CLIP_VIDEO_BAILOUT:
    683 
    684     if ((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) {
    685         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
    686                                             portPriv->DevPriv.ptr, FALSE);
    687         portPriv->isOn = XV_PENDING;
    688     }
    689 
    690     /* This clip was copied and only good for one shot */
    691     if (!portPriv->FreeCompositeClip)
    692         portPriv->pCompositeClip = NULL;
    693 
    694     RegionUninit(&WinRegion);
    695     RegionUninit(&ClipRegion);
    696 
    697     return ret;
    698 }
    699 
    700 static int
    701 xf86XVReputVideo(XvPortRecPrivatePtr portPriv)
    702 {
    703     RegionRec WinRegion;
    704     RegionRec ClipRegion;
    705     BoxRec WinBox;
    706     int ret = Success;
    707     Bool clippedAway = FALSE;
    708 
    709     xf86XVUpdateCompositeClip(portPriv);
    710 
    711     /* translate the video region to the screen */
    712     WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
    713     WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
    714     WinBox.x2 = WinBox.x1 + portPriv->drw_w;
    715     WinBox.y2 = WinBox.y1 + portPriv->drw_h;
    716 
    717     /* clip to the window composite clip */
    718     RegionInit(&WinRegion, &WinBox, 1);
    719     RegionNull(&ClipRegion);
    720     RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
    721 
    722     /* clip and translate to the viewport */
    723     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
    724         RegionRec VPReg;
    725         BoxRec VPBox;
    726 
    727         VPBox.x1 = portPriv->pScrn->frameX0;
    728         VPBox.y1 = portPriv->pScrn->frameY0;
    729         VPBox.x2 = portPriv->pScrn->frameX1 + 1;
    730         VPBox.y2 = portPriv->pScrn->frameY1 + 1;
    731 
    732         RegionInit(&VPReg, &VPBox, 1);
    733         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
    734         RegionUninit(&VPReg);
    735     }
    736 
    737     /* that's all if it's totally obscured */
    738     if (!RegionNotEmpty(&ClipRegion)) {
    739         clippedAway = TRUE;
    740         goto CLIP_VIDEO_BAILOUT;
    741     }
    742 
    743     ret = (*portPriv->AdaptorRec->PutVideo) (portPriv->pScrn,
    744                                              portPriv->vid_x, portPriv->vid_y,
    745                                              WinBox.x1, WinBox.y1,
    746                                              portPriv->vid_w, portPriv->vid_h,
    747                                              portPriv->drw_w, portPriv->drw_h,
    748                                              &ClipRegion, portPriv->DevPriv.ptr,
    749                                              portPriv->pDraw);
    750 
    751     if (ret == Success)
    752         portPriv->isOn = XV_ON;
    753 
    754  CLIP_VIDEO_BAILOUT:
    755 
    756     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
    757         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
    758                                             portPriv->DevPriv.ptr, FALSE);
    759         portPriv->isOn = XV_PENDING;
    760     }
    761 
    762     /* This clip was copied and only good for one shot */
    763     if (!portPriv->FreeCompositeClip)
    764         portPriv->pCompositeClip = NULL;
    765 
    766     RegionUninit(&WinRegion);
    767     RegionUninit(&ClipRegion);
    768 
    769     return ret;
    770 }
    771 
    772 /* Reput image/still */
    773 static int
    774 xf86XVReputImage(XvPortRecPrivatePtr portPriv)
    775 {
    776     RegionRec WinRegion;
    777     RegionRec ClipRegion;
    778     BoxRec WinBox;
    779     int ret = Success;
    780     Bool clippedAway = FALSE;
    781 
    782     xf86XVUpdateCompositeClip(portPriv);
    783 
    784     /* the clip can get smaller over time */
    785     RegionCopy(portPriv->clientClip, portPriv->pCompositeClip);
    786     RegionTranslate(portPriv->clientClip,
    787                     -portPriv->pDraw->x, -portPriv->pDraw->y);
    788 
    789     /* translate the video region to the screen */
    790     WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
    791     WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
    792     WinBox.x2 = WinBox.x1 + portPriv->drw_w;
    793     WinBox.y2 = WinBox.y1 + portPriv->drw_h;
    794 
    795     /* clip to the window composite clip */
    796     RegionInit(&WinRegion, &WinBox, 1);
    797     RegionNull(&ClipRegion);
    798     RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
    799 
    800     /* clip and translate to the viewport */
    801     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
    802         RegionRec VPReg;
    803         BoxRec VPBox;
    804 
    805         VPBox.x1 = portPriv->pScrn->frameX0;
    806         VPBox.y1 = portPriv->pScrn->frameY0;
    807         VPBox.x2 = portPriv->pScrn->frameX1 + 1;
    808         VPBox.y2 = portPriv->pScrn->frameY1 + 1;
    809 
    810         RegionInit(&VPReg, &VPBox, 1);
    811         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
    812         RegionUninit(&VPReg);
    813     }
    814 
    815     /* that's all if it's totally obscured */
    816     if (!RegionNotEmpty(&ClipRegion)) {
    817         clippedAway = TRUE;
    818         goto CLIP_VIDEO_BAILOUT;
    819     }
    820 
    821     ret = (*portPriv->AdaptorRec->ReputImage) (portPriv->pScrn,
    822                                                portPriv->vid_x, portPriv->vid_y,
    823                                                WinBox.x1, WinBox.y1,
    824                                                portPriv->vid_w, portPriv->vid_h,
    825                                                portPriv->drw_w, portPriv->drw_h,
    826                                                &ClipRegion,
    827                                                portPriv->DevPriv.ptr,
    828                                                portPriv->pDraw);
    829 
    830     portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF;
    831 
    832  CLIP_VIDEO_BAILOUT:
    833 
    834     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
    835         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
    836                                             portPriv->DevPriv.ptr, FALSE);
    837         portPriv->isOn = XV_PENDING;
    838     }
    839 
    840     /* This clip was copied and only good for one shot */
    841     if (!portPriv->FreeCompositeClip)
    842         portPriv->pCompositeClip = NULL;
    843 
    844     RegionUninit(&WinRegion);
    845     RegionUninit(&ClipRegion);
    846 
    847     return ret;
    848 }
    849 
    850 static int
    851 xf86XVReputAllVideo(WindowPtr pWin, void *data)
    852 {
    853     XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
    854 
    855     while (WinPriv) {
    856         if (WinPriv->PortRec->type == XvInputMask)
    857             xf86XVReputVideo(WinPriv->PortRec);
    858         else
    859             xf86XVRegetVideo(WinPriv->PortRec);
    860         WinPriv = WinPriv->next;
    861     }
    862 
    863     return WT_WALKCHILDREN;
    864 }
    865 
    866 static int
    867 xf86XVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
    868 {
    869     XF86XVWindowPtr winPriv, PrivRoot;
    870 
    871     winPriv = PrivRoot = GET_XF86XV_WINDOW(pWin);
    872 
    873     /* Enlist our port in the window private */
    874     while (winPriv) {
    875         if (winPriv->PortRec == portPriv)       /* we're already listed */
    876             break;
    877         winPriv = winPriv->next;
    878     }
    879 
    880     if (!winPriv) {
    881         winPriv = calloc(1, sizeof(XF86XVWindowRec));
    882         if (!winPriv)
    883             return BadAlloc;
    884         winPriv->PortRec = portPriv;
    885         winPriv->next = PrivRoot;
    886         dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, winPriv);
    887     }
    888 
    889     portPriv->pDraw = (DrawablePtr) pWin;
    890 
    891     return Success;
    892 }
    893 
    894 static void
    895 xf86XVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
    896 {
    897     XF86XVWindowPtr winPriv, prevPriv = NULL;
    898 
    899     winPriv = GET_XF86XV_WINDOW(pWin);
    900 
    901     while (winPriv) {
    902         if (winPriv->PortRec == portPriv) {
    903             if (prevPriv)
    904                 prevPriv->next = winPriv->next;
    905             else
    906                 dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey,
    907                               winPriv->next);
    908             free(winPriv);
    909             break;
    910         }
    911         prevPriv = winPriv;
    912         winPriv = winPriv->next;
    913     }
    914     portPriv->pDraw = NULL;
    915     if (portPriv->ckeyFilled) {
    916         RegionDestroy(portPriv->ckeyFilled);
    917         portPriv->ckeyFilled = NULL;
    918     }
    919     portPriv->clipChanged = FALSE;
    920 }
    921 
    922 static void
    923 xf86XVReputOrStopPort(XvPortRecPrivatePtr pPriv, WindowPtr pWin, Bool visible)
    924 {
    925     if (!visible) {
    926         if (pPriv->isOn == XV_ON) {
    927             (*pPriv->AdaptorRec->StopVideo) (pPriv->pScrn, pPriv->DevPriv.ptr,
    928                                              FALSE);
    929             pPriv->isOn = XV_PENDING;
    930         }
    931 
    932         if (!pPriv->type)       /* overlaid still/image */
    933             xf86XVRemovePortFromWindow(pWin, pPriv);
    934 
    935         return;
    936     }
    937 
    938     switch (pPriv->type) {
    939     case XvInputMask:
    940         xf86XVReputVideo(pPriv);
    941         break;
    942     case XvOutputMask:
    943         xf86XVRegetVideo(pPriv);
    944         break;
    945     default:                   /* overlaid still/image */
    946         if (pPriv->AdaptorRec->ReputImage)
    947             xf86XVReputImage(pPriv);
    948         break;
    949     }
    950 }
    951 
    952 static void
    953 xf86XVReputOrStopAllPorts(ScrnInfoPtr pScrn, Bool onlyChanged)
    954 {
    955     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
    956     XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
    957     XvAdaptorPtr pa;
    958     int c, i;
    959 
    960     for (c = pxvs->nAdaptors, pa = pxvs->pAdaptors; c > 0; c--, pa++) {
    961         XvPortPtr pPort = pa->pPorts;
    962 
    963         for (i = pa->nPorts; i > 0; i--, pPort++) {
    964             XvPortRecPrivatePtr pPriv =
    965                 (XvPortRecPrivatePtr) pPort->devPriv.ptr;
    966             WindowPtr pWin = (WindowPtr) pPriv->pDraw;
    967             Bool visible;
    968 
    969             if (pPriv->isOn == XV_OFF || !pWin)
    970                 continue;
    971 
    972             if (onlyChanged && !pPriv->clipChanged)
    973                 continue;
    974 
    975             visible = pWin->visibility == VisibilityUnobscured ||
    976                 pWin->visibility == VisibilityPartiallyObscured;
    977 
    978             /*
    979              * Stop and remove still/images if
    980              * ReputImage isn't supported.
    981              */
    982             if (!pPriv->type && !pPriv->AdaptorRec->ReputImage)
    983                 visible = FALSE;
    984 
    985             xf86XVReputOrStopPort(pPriv, pWin, visible);
    986 
    987             pPriv->clipChanged = FALSE;
    988         }
    989     }
    990 }
    991 
    992 /****  ScreenRec fields ****/
    993 
    994 static Bool
    995 xf86XVDestroyWindow(WindowPtr pWin)
    996 {
    997     ScreenPtr pScreen = pWin->drawable.pScreen;
    998     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
    999     XF86XVWindowPtr tmp, WinPriv = GET_XF86XV_WINDOW(pWin);
   1000     int ret;
   1001 
   1002     while (WinPriv) {
   1003         XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
   1004 
   1005         if (pPriv->isOn > XV_OFF) {
   1006             (*pPriv->AdaptorRec->StopVideo) (pPriv->pScrn, pPriv->DevPriv.ptr,
   1007                                              TRUE);
   1008             pPriv->isOn = XV_OFF;
   1009         }
   1010 
   1011         pPriv->pDraw = NULL;
   1012         tmp = WinPriv;
   1013         WinPriv = WinPriv->next;
   1014         free(tmp);
   1015     }
   1016 
   1017     dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, NULL);
   1018 
   1019     pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
   1020     ret = (*pScreen->DestroyWindow) (pWin);
   1021     pScreen->DestroyWindow = xf86XVDestroyWindow;
   1022 
   1023     return ret;
   1024 }
   1025 
   1026 static void
   1027 xf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin, VTKind kind)
   1028 {
   1029     ScreenPtr pScreen;
   1030     XF86XVScreenPtr ScreenPriv;
   1031     ScrnInfoPtr pScrn;
   1032 
   1033     if (pWin)
   1034         pScreen = pWin->drawable.pScreen;
   1035     else
   1036         pScreen = pLayerWin->drawable.pScreen;
   1037 
   1038     ScreenPriv = GET_XF86XV_SCREEN(pScreen);
   1039     pScrn = xf86ScreenToScrn(pScreen);
   1040 
   1041     xf86XVReputOrStopAllPorts(pScrn, TRUE);
   1042 
   1043     pScreen->PostValidateTree = ScreenPriv->PostValidateTree;
   1044     if (pScreen->PostValidateTree) {
   1045         (*pScreen->PostValidateTree) (pWin, pLayerWin, kind);
   1046     }
   1047     ScreenPriv->PostValidateTree = PostValidateTreeUndefined;
   1048 }
   1049 
   1050 static void
   1051 xf86XVWindowExposures(WindowPtr pWin, RegionPtr reg1)
   1052 {
   1053     ScreenPtr pScreen = pWin->drawable.pScreen;
   1054     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
   1055     XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
   1056     XvPortRecPrivatePtr pPriv;
   1057     Bool AreasExposed;
   1058 
   1059     AreasExposed = (WinPriv && reg1 && RegionNotEmpty(reg1));
   1060 
   1061     pScreen->WindowExposures = ScreenPriv->WindowExposures;
   1062     (*pScreen->WindowExposures) (pWin, reg1);
   1063     pScreen->WindowExposures = xf86XVWindowExposures;
   1064 
   1065     /* filter out XClearWindow/Area */
   1066     if (!pWin->valdata)
   1067         return;
   1068 
   1069     while (WinPriv) {
   1070         Bool visible = TRUE;
   1071 
   1072         pPriv = WinPriv->PortRec;
   1073 
   1074         /*
   1075          * Stop and remove still/images if areas were exposed and
   1076          * ReputImage isn't supported.
   1077          */
   1078         if (!pPriv->type && !pPriv->AdaptorRec->ReputImage)
   1079             visible = !AreasExposed;
   1080 
   1081         /*
   1082          * Subtract exposed areas from overlaid image to match textured video
   1083          * behavior.
   1084          */
   1085         if (!pPriv->type && pPriv->clientClip)
   1086             RegionSubtract(pPriv->clientClip, pPriv->clientClip, reg1);
   1087 
   1088         if (visible && pPriv->ckeyFilled) {
   1089             RegionRec tmp;
   1090 
   1091             RegionNull(&tmp);
   1092             RegionCopy(&tmp, reg1);
   1093             RegionTranslate(&tmp, pWin->drawable.x, pWin->drawable.y);
   1094             RegionSubtract(pPriv->ckeyFilled, pPriv->ckeyFilled, &tmp);
   1095         }
   1096 
   1097         WinPriv = WinPriv->next;
   1098         xf86XVReputOrStopPort(pPriv, pWin, visible);
   1099 
   1100         pPriv->clipChanged = FALSE;
   1101     }
   1102 }
   1103 
   1104 static void
   1105 xf86XVClipNotify(WindowPtr pWin, int dx, int dy)
   1106 {
   1107     ScreenPtr pScreen = pWin->drawable.pScreen;
   1108     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
   1109     XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
   1110     XvPortRecPrivatePtr pPriv;
   1111 
   1112     while (WinPriv) {
   1113         pPriv = WinPriv->PortRec;
   1114 
   1115         if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
   1116             RegionDestroy(pPriv->pCompositeClip);
   1117 
   1118         pPriv->pCompositeClip = NULL;
   1119 
   1120         pPriv->clipChanged = TRUE;
   1121 
   1122         if (ScreenPriv->PostValidateTree == PostValidateTreeUndefined) {
   1123             ScreenPriv->PostValidateTree = pScreen->PostValidateTree;
   1124             pScreen->PostValidateTree = xf86XVPostValidateTree;
   1125         }
   1126 
   1127         WinPriv = WinPriv->next;
   1128     }
   1129 
   1130     if (ScreenPriv->ClipNotify) {
   1131         pScreen->ClipNotify = ScreenPriv->ClipNotify;
   1132         (*pScreen->ClipNotify) (pWin, dx, dy);
   1133         pScreen->ClipNotify = xf86XVClipNotify;
   1134     }
   1135 }
   1136 
   1137 /**** Required XvScreenRec fields ****/
   1138 
   1139 static Bool
   1140 xf86XVCloseScreen(ScreenPtr pScreen)
   1141 {
   1142     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
   1143     XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
   1144     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
   1145     XvAdaptorPtr pa;
   1146     int c;
   1147 
   1148     if (!ScreenPriv)
   1149         return TRUE;
   1150 
   1151     pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
   1152     pScreen->WindowExposures = ScreenPriv->WindowExposures;
   1153     pScreen->ClipNotify = ScreenPriv->ClipNotify;
   1154     pScreen->CloseScreen = ScreenPriv->CloseScreen;
   1155 
   1156     pScrn->EnterVT = ScreenPriv->EnterVT;
   1157     pScrn->LeaveVT = ScreenPriv->LeaveVT;
   1158     pScrn->AdjustFrame = ScreenPriv->AdjustFrame;
   1159     pScrn->ModeSet = ScreenPriv->ModeSet;
   1160 
   1161     for (c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) {
   1162         xf86XVFreeAdaptor(pa);
   1163     }
   1164 
   1165     free(pxvs->pAdaptors);
   1166     free(ScreenPriv);
   1167 
   1168     return pScreen->CloseScreen(pScreen);
   1169 }
   1170 
   1171 /**** ScrnInfoRec fields ****/
   1172 
   1173 static Bool
   1174 xf86XVEnterVT(ScrnInfoPtr pScrn)
   1175 {
   1176     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
   1177     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
   1178     Bool ret;
   1179 
   1180     pScrn->EnterVT = ScreenPriv->EnterVT;
   1181     ret = (*ScreenPriv->EnterVT) (pScrn);
   1182     ScreenPriv->EnterVT = pScrn->EnterVT;
   1183     pScrn->EnterVT = xf86XVEnterVT;
   1184 
   1185     if (ret)
   1186         WalkTree(pScreen, xf86XVReputAllVideo, 0);
   1187 
   1188     return ret;
   1189 }
   1190 
   1191 static void
   1192 xf86XVLeaveVT(ScrnInfoPtr pScrn)
   1193 {
   1194     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
   1195     XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
   1196     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
   1197     XvAdaptorPtr pAdaptor;
   1198     XvPortPtr pPort;
   1199     XvPortRecPrivatePtr pPriv;
   1200     int i, j;
   1201 
   1202     for (i = 0; i < pxvs->nAdaptors; i++) {
   1203         pAdaptor = &pxvs->pAdaptors[i];
   1204         for (j = 0; j < pAdaptor->nPorts; j++) {
   1205             pPort = &pAdaptor->pPorts[j];
   1206             pPriv = (XvPortRecPrivatePtr) pPort->devPriv.ptr;
   1207             if (pPriv->isOn > XV_OFF) {
   1208 
   1209                 (*pPriv->AdaptorRec->StopVideo) (pPriv->pScrn,
   1210                                                  pPriv->DevPriv.ptr, TRUE);
   1211                 pPriv->isOn = XV_OFF;
   1212 
   1213                 if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
   1214                     RegionDestroy(pPriv->pCompositeClip);
   1215 
   1216                 pPriv->pCompositeClip = NULL;
   1217 
   1218                 if (!pPriv->type && pPriv->pDraw) {     /* still */
   1219                     xf86XVRemovePortFromWindow((WindowPtr) pPriv->pDraw, pPriv);
   1220                 }
   1221             }
   1222         }
   1223     }
   1224 
   1225     pScrn->LeaveVT = ScreenPriv->LeaveVT;
   1226     (*ScreenPriv->LeaveVT) (pScrn);
   1227     ScreenPriv->LeaveVT = pScrn->LeaveVT;
   1228     pScrn->LeaveVT = xf86XVLeaveVT;
   1229 }
   1230 
   1231 static void
   1232 xf86XVAdjustFrame(ScrnInfoPtr pScrn, int x, int y)
   1233 {
   1234     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
   1235     XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
   1236 
   1237     if (ScreenPriv->AdjustFrame) {
   1238         pScrn->AdjustFrame = ScreenPriv->AdjustFrame;
   1239         (*pScrn->AdjustFrame) (pScrn, x, y);
   1240         pScrn->AdjustFrame = xf86XVAdjustFrame;
   1241     }
   1242 
   1243     xf86XVReputOrStopAllPorts(pScrn, FALSE);
   1244 }
   1245 
   1246 static void
   1247 xf86XVModeSet(ScrnInfoPtr pScrn)
   1248 {
   1249     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
   1250     XF86XVScreenPtr ScreenPriv;
   1251 
   1252     /* Can be called before pScrn->pScreen is set */
   1253     if (!pScreen)
   1254         return;
   1255 
   1256     ScreenPriv = GET_XF86XV_SCREEN(pScreen);
   1257 
   1258     if (ScreenPriv->ModeSet) {
   1259         pScrn->ModeSet = ScreenPriv->ModeSet;
   1260         (*pScrn->ModeSet) (pScrn);
   1261         pScrn->ModeSet = xf86XVModeSet;
   1262     }
   1263 
   1264     xf86XVReputOrStopAllPorts(pScrn, FALSE);
   1265 }
   1266 
   1267 /**** XvAdaptorRec fields ****/
   1268 
   1269 static int
   1270 xf86XVPutVideo(DrawablePtr pDraw,
   1271                XvPortPtr pPort,
   1272                GCPtr pGC,
   1273                INT16 vid_x, INT16 vid_y,
   1274                CARD16 vid_w, CARD16 vid_h,
   1275                INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
   1276 {
   1277     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
   1278     int result;
   1279 
   1280     /* No dumping video to pixmaps... For now anyhow */
   1281     if (pDraw->type != DRAWABLE_WINDOW) {
   1282         pPort->pDraw = (DrawablePtr) NULL;
   1283         return BadAlloc;
   1284     }
   1285 
   1286     /* If we are changing windows, unregister our port in the old window */
   1287     if (portPriv->pDraw && (portPriv->pDraw != pDraw))
   1288         xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
   1289 
   1290     /* Register our port with the new window */
   1291     result = xf86XVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
   1292     if (result != Success)
   1293         return result;
   1294 
   1295     portPriv->type = XvInputMask;
   1296 
   1297     /* save a copy of these parameters */
   1298     portPriv->vid_x = vid_x;
   1299     portPriv->vid_y = vid_y;
   1300     portPriv->vid_w = vid_w;
   1301     portPriv->vid_h = vid_h;
   1302     portPriv->drw_x = drw_x;
   1303     portPriv->drw_y = drw_y;
   1304     portPriv->drw_w = drw_w;
   1305     portPriv->drw_h = drw_h;
   1306 
   1307     /* make sure we have the most recent copy of the clientClip */
   1308     xf86XVCopyClip(portPriv, pGC);
   1309 
   1310     /* To indicate to the DI layer that we were successful */
   1311     pPort->pDraw = pDraw;
   1312 
   1313     if (!portPriv->pScrn->vtSema)
   1314         return Success;         /* Success ? */
   1315 
   1316     return (xf86XVReputVideo(portPriv));
   1317 }
   1318 
   1319 static int
   1320 xf86XVPutStill(DrawablePtr pDraw,
   1321                XvPortPtr pPort,
   1322                GCPtr pGC,
   1323                INT16 vid_x, INT16 vid_y,
   1324                CARD16 vid_w, CARD16 vid_h,
   1325                INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
   1326 {
   1327     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
   1328     RegionRec WinRegion;
   1329     RegionRec ClipRegion;
   1330     BoxRec WinBox;
   1331     int ret = Success;
   1332     Bool clippedAway = FALSE;
   1333 
   1334     if (pDraw->type != DRAWABLE_WINDOW)
   1335         return BadAlloc;
   1336 
   1337     if (!portPriv->pScrn->vtSema)
   1338         return Success;         /* Success ? */
   1339 
   1340     WinBox.x1 = pDraw->x + drw_x;
   1341     WinBox.y1 = pDraw->y + drw_y;
   1342     WinBox.x2 = WinBox.x1 + drw_w;
   1343     WinBox.y2 = WinBox.y1 + drw_h;
   1344 
   1345     xf86XVCopyCompositeClip(portPriv, pGC, pDraw);
   1346 
   1347     RegionInit(&WinRegion, &WinBox, 1);
   1348     RegionNull(&ClipRegion);
   1349     RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
   1350 
   1351     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
   1352         RegionRec VPReg;
   1353         BoxRec VPBox;
   1354 
   1355         VPBox.x1 = portPriv->pScrn->frameX0;
   1356         VPBox.y1 = portPriv->pScrn->frameY0;
   1357         VPBox.x2 = portPriv->pScrn->frameX1 + 1;
   1358         VPBox.y2 = portPriv->pScrn->frameY1 + 1;
   1359 
   1360         RegionInit(&VPReg, &VPBox, 1);
   1361         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
   1362         RegionUninit(&VPReg);
   1363     }
   1364 
   1365     if (portPriv->pDraw) {
   1366         xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
   1367     }
   1368 
   1369     if (!RegionNotEmpty(&ClipRegion)) {
   1370         clippedAway = TRUE;
   1371         goto PUT_STILL_BAILOUT;
   1372     }
   1373 
   1374     ret = (*portPriv->AdaptorRec->PutStill) (portPriv->pScrn,
   1375                                              vid_x, vid_y, WinBox.x1, WinBox.y1,
   1376                                              vid_w, vid_h, drw_w, drw_h,
   1377                                              &ClipRegion, portPriv->DevPriv.ptr,
   1378                                              pDraw);
   1379 
   1380     if ((ret == Success) &&
   1381         (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) {
   1382 
   1383         xf86XVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
   1384         portPriv->isOn = XV_ON;
   1385         portPriv->vid_x = vid_x;
   1386         portPriv->vid_y = vid_y;
   1387         portPriv->vid_w = vid_w;
   1388         portPriv->vid_h = vid_h;
   1389         portPriv->drw_x = drw_x;
   1390         portPriv->drw_y = drw_y;
   1391         portPriv->drw_w = drw_w;
   1392         portPriv->drw_h = drw_h;
   1393         portPriv->type = 0;     /* no mask means it's transient and should
   1394                                    not be reput once it's removed */
   1395         pPort->pDraw = pDraw;   /* make sure we can get stop requests */
   1396     }
   1397 
   1398  PUT_STILL_BAILOUT:
   1399 
   1400     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
   1401         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
   1402                                             portPriv->DevPriv.ptr, FALSE);
   1403         portPriv->isOn = XV_PENDING;
   1404     }
   1405 
   1406     /* This clip was copied and only good for one shot */
   1407     if (!portPriv->FreeCompositeClip)
   1408         portPriv->pCompositeClip = NULL;
   1409 
   1410     RegionUninit(&WinRegion);
   1411     RegionUninit(&ClipRegion);
   1412 
   1413     return ret;
   1414 }
   1415 
   1416 static int
   1417 xf86XVGetVideo(DrawablePtr pDraw,
   1418                XvPortPtr pPort,
   1419                GCPtr pGC,
   1420                INT16 vid_x, INT16 vid_y,
   1421                CARD16 vid_w, CARD16 vid_h,
   1422                INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
   1423 {
   1424     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
   1425     int result;
   1426 
   1427     /* No pixmaps... For now anyhow */
   1428     if (pDraw->type != DRAWABLE_WINDOW) {
   1429         pPort->pDraw = (DrawablePtr) NULL;
   1430         return BadAlloc;
   1431     }
   1432 
   1433     /* If we are changing windows, unregister our port in the old window */
   1434     if (portPriv->pDraw && (portPriv->pDraw != pDraw))
   1435         xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
   1436 
   1437     /* Register our port with the new window */
   1438     result = xf86XVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
   1439     if (result != Success)
   1440         return result;
   1441 
   1442     portPriv->type = XvOutputMask;
   1443 
   1444     /* save a copy of these parameters */
   1445     portPriv->vid_x = vid_x;
   1446     portPriv->vid_y = vid_y;
   1447     portPriv->vid_w = vid_w;
   1448     portPriv->vid_h = vid_h;
   1449     portPriv->drw_x = drw_x;
   1450     portPriv->drw_y = drw_y;
   1451     portPriv->drw_w = drw_w;
   1452     portPriv->drw_h = drw_h;
   1453 
   1454     /* make sure we have the most recent copy of the clientClip */
   1455     xf86XVCopyClip(portPriv, pGC);
   1456 
   1457     /* To indicate to the DI layer that we were successful */
   1458     pPort->pDraw = pDraw;
   1459 
   1460     if (!portPriv->pScrn->vtSema)
   1461         return Success;         /* Success ? */
   1462 
   1463     return (xf86XVRegetVideo(portPriv));
   1464 }
   1465 
   1466 static int
   1467 xf86XVGetStill(DrawablePtr pDraw,
   1468                XvPortPtr pPort,
   1469                GCPtr pGC,
   1470                INT16 vid_x, INT16 vid_y,
   1471                CARD16 vid_w, CARD16 vid_h,
   1472                INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
   1473 {
   1474     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
   1475     RegionRec WinRegion;
   1476     RegionRec ClipRegion;
   1477     BoxRec WinBox;
   1478     int ret = Success;
   1479     Bool clippedAway = FALSE;
   1480 
   1481     if (pDraw->type != DRAWABLE_WINDOW)
   1482         return BadAlloc;
   1483 
   1484     if (!portPriv->pScrn->vtSema)
   1485         return Success;         /* Success ? */
   1486 
   1487     WinBox.x1 = pDraw->x + drw_x;
   1488     WinBox.y1 = pDraw->y + drw_y;
   1489     WinBox.x2 = WinBox.x1 + drw_w;
   1490     WinBox.y2 = WinBox.y1 + drw_h;
   1491 
   1492     RegionInit(&WinRegion, &WinBox, 1);
   1493     RegionNull(&ClipRegion);
   1494     RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
   1495 
   1496     if (portPriv->pDraw) {
   1497         xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
   1498     }
   1499 
   1500     if (!RegionNotEmpty(&ClipRegion)) {
   1501         clippedAway = TRUE;
   1502         goto GET_STILL_BAILOUT;
   1503     }
   1504 
   1505     ret = (*portPriv->AdaptorRec->GetStill) (portPriv->pScrn,
   1506                                              vid_x, vid_y, WinBox.x1, WinBox.y1,
   1507                                              vid_w, vid_h, drw_w, drw_h,
   1508                                              &ClipRegion, portPriv->DevPriv.ptr,
   1509                                              pDraw);
   1510 
   1511  GET_STILL_BAILOUT:
   1512 
   1513     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
   1514         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
   1515                                             portPriv->DevPriv.ptr, FALSE);
   1516         portPriv->isOn = XV_PENDING;
   1517     }
   1518 
   1519     RegionUninit(&WinRegion);
   1520     RegionUninit(&ClipRegion);
   1521 
   1522     return ret;
   1523 }
   1524 
   1525 static int
   1526 xf86XVStopVideo(XvPortPtr pPort, DrawablePtr pDraw)
   1527 {
   1528     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
   1529 
   1530     if (pDraw->type != DRAWABLE_WINDOW)
   1531         return BadAlloc;
   1532 
   1533     xf86XVRemovePortFromWindow((WindowPtr) pDraw, portPriv);
   1534 
   1535     if (!portPriv->pScrn->vtSema)
   1536         return Success;         /* Success ? */
   1537 
   1538     /* Must free resources. */
   1539 
   1540     if (portPriv->isOn > XV_OFF) {
   1541         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
   1542                                             portPriv->DevPriv.ptr, TRUE);
   1543         portPriv->isOn = XV_OFF;
   1544     }
   1545 
   1546     return Success;
   1547 }
   1548 
   1549 static int
   1550 xf86XVSetPortAttribute(XvPortPtr pPort, Atom attribute, INT32 value)
   1551 {
   1552     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
   1553 
   1554     return ((*portPriv->AdaptorRec->SetPortAttribute) (portPriv->pScrn,
   1555                                                        attribute, value,
   1556                                                        portPriv->DevPriv.ptr));
   1557 }
   1558 
   1559 static int
   1560 xf86XVGetPortAttribute(XvPortPtr pPort, Atom attribute, INT32 *p_value)
   1561 {
   1562     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
   1563 
   1564     return ((*portPriv->AdaptorRec->GetPortAttribute) (portPriv->pScrn,
   1565                                                        attribute, p_value,
   1566                                                        portPriv->DevPriv.ptr));
   1567 }
   1568 
   1569 static int
   1570 xf86XVQueryBestSize(XvPortPtr pPort,
   1571                     CARD8 motion,
   1572                     CARD16 vid_w, CARD16 vid_h,
   1573                     CARD16 drw_w, CARD16 drw_h,
   1574                     unsigned int *p_w, unsigned int *p_h)
   1575 {
   1576     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
   1577 
   1578     (*portPriv->AdaptorRec->QueryBestSize) (portPriv->pScrn,
   1579                                             (Bool) motion, vid_w, vid_h, drw_w,
   1580                                             drw_h, p_w, p_h,
   1581                                             portPriv->DevPriv.ptr);
   1582 
   1583     return Success;
   1584 }
   1585 
   1586 static int
   1587 xf86XVPutImage(DrawablePtr pDraw,
   1588                XvPortPtr pPort,
   1589                GCPtr pGC,
   1590                INT16 src_x, INT16 src_y,
   1591                CARD16 src_w, CARD16 src_h,
   1592                INT16 drw_x, INT16 drw_y,
   1593                CARD16 drw_w, CARD16 drw_h,
   1594                XvImagePtr format,
   1595                unsigned char *data, Bool sync, CARD16 width, CARD16 height)
   1596 {
   1597     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
   1598     RegionRec WinRegion;
   1599     RegionRec ClipRegion;
   1600     BoxRec WinBox;
   1601     int ret = Success;
   1602     Bool clippedAway = FALSE;
   1603 
   1604     if (pDraw->type != DRAWABLE_WINDOW)
   1605         return BadAlloc;
   1606 
   1607     if (!portPriv->pScrn->vtSema)
   1608         return Success;         /* Success ? */
   1609 
   1610     xf86XVCopyCompositeClip(portPriv, pGC, pDraw);
   1611 
   1612     WinBox.x1 = pDraw->x + drw_x;
   1613     WinBox.y1 = pDraw->y + drw_y;
   1614     WinBox.x2 = WinBox.x1 + drw_w;
   1615     WinBox.y2 = WinBox.y1 + drw_h;
   1616 
   1617     RegionInit(&WinRegion, &WinBox, 1);
   1618     RegionNull(&ClipRegion);
   1619     RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
   1620 
   1621     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
   1622         RegionRec VPReg;
   1623         BoxRec VPBox;
   1624 
   1625         VPBox.x1 = portPriv->pScrn->frameX0;
   1626         VPBox.y1 = portPriv->pScrn->frameY0;
   1627         VPBox.x2 = portPriv->pScrn->frameX1 + 1;
   1628         VPBox.y2 = portPriv->pScrn->frameY1 + 1;
   1629 
   1630         RegionInit(&VPReg, &VPBox, 1);
   1631         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
   1632         RegionUninit(&VPReg);
   1633     }
   1634 
   1635     /* If we are changing windows, unregister our port in the old window */
   1636     if (portPriv->pDraw && (portPriv->pDraw != pDraw))
   1637         xf86XVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
   1638 
   1639     /* Register our port with the new window */
   1640     ret = xf86XVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
   1641     if (ret != Success)
   1642         goto PUT_IMAGE_BAILOUT;
   1643 
   1644     if (!RegionNotEmpty(&ClipRegion)) {
   1645         clippedAway = TRUE;
   1646         goto PUT_IMAGE_BAILOUT;
   1647     }
   1648 
   1649     ret = (*portPriv->AdaptorRec->PutImage) (portPriv->pScrn,
   1650                                              src_x, src_y, WinBox.x1, WinBox.y1,
   1651                                              src_w, src_h, drw_w, drw_h,
   1652                                              format->id, data, width, height,
   1653                                              sync, &ClipRegion,
   1654                                              portPriv->DevPriv.ptr, pDraw);
   1655 
   1656     if ((ret == Success) &&
   1657         (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) {
   1658 
   1659         portPriv->isOn = XV_ON;
   1660         portPriv->vid_x = src_x;
   1661         portPriv->vid_y = src_y;
   1662         portPriv->vid_w = src_w;
   1663         portPriv->vid_h = src_h;
   1664         portPriv->drw_x = drw_x;
   1665         portPriv->drw_y = drw_y;
   1666         portPriv->drw_w = drw_w;
   1667         portPriv->drw_h = drw_h;
   1668         portPriv->type = 0;     /* no mask means it's transient and should
   1669                                    not be reput once it's removed */
   1670         pPort->pDraw = pDraw;   /* make sure we can get stop requests */
   1671     }
   1672 
   1673  PUT_IMAGE_BAILOUT:
   1674 
   1675     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
   1676         (*portPriv->AdaptorRec->StopVideo) (portPriv->pScrn,
   1677                                             portPriv->DevPriv.ptr, FALSE);
   1678         portPriv->isOn = XV_PENDING;
   1679     }
   1680 
   1681     /* This clip was copied and only good for one shot */
   1682     if (!portPriv->FreeCompositeClip)
   1683         portPriv->pCompositeClip = NULL;
   1684 
   1685     RegionUninit(&WinRegion);
   1686     RegionUninit(&ClipRegion);
   1687 
   1688     return ret;
   1689 }
   1690 
   1691 static int
   1692 xf86XVQueryImageAttributes(XvPortPtr pPort,
   1693                            XvImagePtr format,
   1694                            CARD16 *width,
   1695                            CARD16 *height, int *pitches, int *offsets)
   1696 {
   1697     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
   1698 
   1699     return (*portPriv->AdaptorRec->QueryImageAttributes) (portPriv->pScrn,
   1700                                                           format->id, width,
   1701                                                           height, pitches,
   1702                                                           offsets);
   1703 }
   1704 
   1705 void
   1706 xf86XVFillKeyHelperDrawable(DrawablePtr pDraw, CARD32 key, RegionPtr fillboxes)
   1707 {
   1708     ScreenPtr pScreen = pDraw->pScreen;
   1709 
   1710     if (!xf86ScreenToScrn(pScreen)->vtSema)
   1711         return;
   1712 
   1713     XvFillColorKey(pDraw, key, fillboxes);
   1714 }
   1715 
   1716 void
   1717 xf86XVFillKeyHelper(ScreenPtr pScreen, CARD32 key, RegionPtr fillboxes)
   1718 {
   1719     xf86XVFillKeyHelperDrawable(&pScreen->root->drawable, key, fillboxes);
   1720 }
   1721 
   1722 void
   1723 xf86XVFillKeyHelperPort(DrawablePtr pDraw, void *data, CARD32 key,
   1724                         RegionPtr clipboxes, Bool fillEverything)
   1725 {
   1726     WindowPtr pWin = (WindowPtr) pDraw;
   1727     XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
   1728     XvPortRecPrivatePtr portPriv = NULL;
   1729     RegionRec reg;
   1730     RegionPtr fillboxes;
   1731 
   1732     while (WinPriv) {
   1733         XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
   1734 
   1735         if (data == pPriv->DevPriv.ptr) {
   1736             portPriv = pPriv;
   1737             break;
   1738         }
   1739 
   1740         WinPriv = WinPriv->next;
   1741     }
   1742 
   1743     if (!portPriv)
   1744         return;
   1745 
   1746     if (!portPriv->ckeyFilled)
   1747         portPriv->ckeyFilled = RegionCreate(NULL, 0);
   1748 
   1749     if (!fillEverything) {
   1750         RegionNull(&reg);
   1751         fillboxes = &reg;
   1752         RegionSubtract(fillboxes, clipboxes, portPriv->ckeyFilled);
   1753 
   1754         if (!RegionNotEmpty(fillboxes))
   1755             goto out;
   1756     }
   1757     else
   1758         fillboxes = clipboxes;
   1759 
   1760     RegionCopy(portPriv->ckeyFilled, clipboxes);
   1761 
   1762     xf86XVFillKeyHelperDrawable(pDraw, key, fillboxes);
   1763  out:
   1764     if (!fillEverything)
   1765         RegionUninit(&reg);
   1766 }
   1767 
   1768 /* xf86XVClipVideoHelper -
   1769 
   1770    Takes the dst box in standard X BoxRec form (top and left
   1771    edges inclusive, bottom and right exclusive).  The new dst
   1772    box is returned.  The source boundaries are given (x1, y1
   1773    inclusive, x2, y2 exclusive) and returned are the new source
   1774    boundaries in 16.16 fixed point.
   1775 */
   1776 
   1777 Bool
   1778 xf86XVClipVideoHelper(BoxPtr dst,
   1779                       INT32 *xa,
   1780                       INT32 *xb,
   1781                       INT32 *ya,
   1782                       INT32 *yb, RegionPtr reg, INT32 width, INT32 height)
   1783 {
   1784     double xsw, xdw, ysw, ydw;
   1785     INT32 delta;
   1786     BoxPtr extents = RegionExtents(reg);
   1787     int diff;
   1788 
   1789     xsw = (*xb - *xa) << 16;
   1790     xdw = dst->x2 - dst->x1;
   1791     ysw = (*yb - *ya) << 16;
   1792     ydw = dst->y2 - dst->y1;
   1793 
   1794     *xa <<= 16;
   1795     *xb <<= 16;
   1796     *ya <<= 16;
   1797     *yb <<= 16;
   1798 
   1799     diff = extents->x1 - dst->x1;
   1800     if (diff > 0) {
   1801         dst->x1 = extents->x1;
   1802         *xa += (diff * xsw) / xdw;
   1803     }
   1804     diff = dst->x2 - extents->x2;
   1805     if (diff > 0) {
   1806         dst->x2 = extents->x2;
   1807         *xb -= (diff * xsw) / xdw;
   1808     }
   1809     diff = extents->y1 - dst->y1;
   1810     if (diff > 0) {
   1811         dst->y1 = extents->y1;
   1812         *ya += (diff * ysw) / ydw;
   1813     }
   1814     diff = dst->y2 - extents->y2;
   1815     if (diff > 0) {
   1816         dst->y2 = extents->y2;
   1817         *yb -= (diff * ysw) / ydw;
   1818     }
   1819 
   1820     if (*xa < 0) {
   1821         diff = (((-*xa) * xdw) + xsw - 1) / xsw;
   1822         dst->x1 += diff;
   1823         *xa += (diff * xsw) / xdw;
   1824     }
   1825     delta = *xb - (width << 16);
   1826     if (delta > 0) {
   1827         diff = ((delta * xdw) + xsw - 1) / xsw;
   1828         dst->x2 -= diff;
   1829         *xb -= (diff * xsw) / xdw;
   1830     }
   1831     if (*xa >= *xb)
   1832         return FALSE;
   1833 
   1834     if (*ya < 0) {
   1835         diff = (((-*ya) * ydw) + ysw - 1) / ysw;
   1836         dst->y1 += diff;
   1837         *ya += (diff * ysw) / ydw;
   1838     }
   1839     delta = *yb - (height << 16);
   1840     if (delta > 0) {
   1841         diff = ((delta * ydw) + ysw - 1) / ysw;
   1842         dst->y2 -= diff;
   1843         *yb -= (diff * ysw) / ydw;
   1844     }
   1845     if (*ya >= *yb)
   1846         return FALSE;
   1847 
   1848     if ((dst->x1 > extents->x1) || (dst->x2 < extents->x2) ||
   1849         (dst->y1 > extents->y1) || (dst->y2 < extents->y2)) {
   1850         RegionRec clipReg;
   1851 
   1852         RegionInit(&clipReg, dst, 1);
   1853         RegionIntersect(reg, reg, &clipReg);
   1854         RegionUninit(&clipReg);
   1855     }
   1856     return TRUE;
   1857 }
   1858 
   1859 void
   1860 xf86XVCopyYUV12ToPacked(const void *srcy,
   1861                         const void *srcv,
   1862                         const void *srcu,
   1863                         void *dst,
   1864                         int srcPitchy,
   1865                         int srcPitchuv, int dstPitch, int h, int w)
   1866 {
   1867     CARD32 *Dst;
   1868     const CARD8 *Y, *U, *V;
   1869     int i, j;
   1870 
   1871     w >>= 1;
   1872 
   1873     for (j = 0; j < h; j++) {
   1874         Dst = dst;
   1875         Y = srcy;
   1876         V = srcv;
   1877         U = srcu;
   1878         i = w;
   1879         while (i >= 4) {
   1880 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
   1881             Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24);
   1882             Dst[1] = Y[2] | (Y[3] << 16) | (U[1] << 8) | (V[1] << 24);
   1883             Dst[2] = Y[4] | (Y[5] << 16) | (U[2] << 8) | (V[2] << 24);
   1884             Dst[3] = Y[6] | (Y[7] << 16) | (U[3] << 8) | (V[3] << 24);
   1885 #else
   1886             /* This assumes a little-endian framebuffer */
   1887             Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0];
   1888             Dst[1] = (Y[2] << 24) | (Y[3] << 8) | (U[1] << 16) | V[1];
   1889             Dst[2] = (Y[4] << 24) | (Y[5] << 8) | (U[2] << 16) | V[2];
   1890             Dst[3] = (Y[6] << 24) | (Y[7] << 8) | (U[3] << 16) | V[3];
   1891 #endif
   1892             Dst += 4;
   1893             Y += 8;
   1894             V += 4;
   1895             U += 4;
   1896             i -= 4;
   1897         }
   1898 
   1899         while (i--) {
   1900 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
   1901             Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24);
   1902 #else
   1903             /* This assumes a little-endian framebuffer */
   1904             Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0];
   1905 #endif
   1906             Dst++;
   1907             Y += 2;
   1908             V++;
   1909             U++;
   1910         }
   1911 
   1912         dst = (CARD8 *) dst + dstPitch;
   1913         srcy = (const CARD8 *) srcy + srcPitchy;
   1914         if (j & 1) {
   1915             srcu = (const CARD8 *) srcu + srcPitchuv;
   1916             srcv = (const CARD8 *) srcv + srcPitchuv;
   1917         }
   1918     }
   1919 }
   1920 
   1921 void
   1922 xf86XVCopyPacked(const void *src,
   1923                  void *dst, int srcPitch, int dstPitch, int h, int w)
   1924 {
   1925     const CARD32 *Src;
   1926     CARD32 *Dst;
   1927     int i;
   1928 
   1929     w >>= 1;
   1930     while (--h >= 0) {
   1931         do {
   1932             Dst = dst;
   1933             Src = src;
   1934             i = w;
   1935             while (i >= 4) {
   1936                 Dst[0] = Src[0];
   1937                 Dst[1] = Src[1];
   1938                 Dst[2] = Src[2];
   1939                 Dst[3] = Src[3];
   1940                 Dst += 4;
   1941                 Src += 4;
   1942                 i -= 4;
   1943             }
   1944             if (!i)
   1945                 break;
   1946             Dst[0] = Src[0];
   1947             if (i == 1)
   1948                 break;
   1949             Dst[1] = Src[1];
   1950             if (i == 2)
   1951                 break;
   1952             Dst[2] = Src[2];
   1953         } while (0);
   1954 
   1955         src = (const CARD8 *) src + srcPitch;
   1956         dst = (CARD8 *) dst + dstPitch;
   1957     }
   1958 }