xserver

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

kxv.c (43542B)


      1 /*
      2 
      3    XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com)
      4    Adapted for KDrive by Pontus Lidman <pontus.lidman@nokia.com>
      5 
      6    Copyright (C) 2000, 2001 - Nokia Home Communications
      7    Copyright (C) 1998, 1999 - The XFree86 Project Inc.
      8 
      9 All rights reserved.
     10 
     11 Permission is hereby granted, free of charge, to any person obtaining
     12 a copy of this software and associated documentation files (the
     13 "Software"), to deal in the Software without restriction, including
     14 without limitation the rights to use, copy, modify, merge, publish,
     15 distribute, and/or sell copies of the Software, and to permit persons
     16 to whom the Software is furnished to do so, provided that the above
     17 copyright notice(s) and this permission notice appear in all copies of
     18 the Software and that both the above copyright notice(s) and this
     19 permission notice appear in supporting documentation.
     20 
     21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
     24 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     25 HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
     26 SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
     27 RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
     28 CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     29 CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     30 
     31 Except as contained in this notice, the name of a copyright holder
     32 shall not be used in advertising or otherwise to promote the sale, use
     33 or other dealings in this Software without prior written authorization
     34 of the copyright holder.
     35 
     36 */
     37 
     38 #ifdef HAVE_DIX_CONFIG_H
     39 #include <dix-config.h>
     40 #endif
     41 #include "kdrive.h"
     42 
     43 #include "scrnintstr.h"
     44 #include "regionstr.h"
     45 #include "windowstr.h"
     46 #include "pixmapstr.h"
     47 #include "mivalidate.h"
     48 #include "validate.h"
     49 #include "resource.h"
     50 #include "gcstruct.h"
     51 #include "dixstruct.h"
     52 
     53 #include <X11/extensions/Xv.h>
     54 #include <X11/extensions/Xvproto.h>
     55 
     56 #include "kxv.h"
     57 #include "fourcc.h"
     58 
     59 /* XvAdaptorRec fields */
     60 
     61 static int KdXVPutVideo(DrawablePtr, XvPortPtr, GCPtr,
     62                         INT16, INT16, CARD16, CARD16,
     63                         INT16, INT16, CARD16, CARD16);
     64 static int KdXVPutStill(DrawablePtr, XvPortPtr, GCPtr,
     65                         INT16, INT16, CARD16, CARD16,
     66                         INT16, INT16, CARD16, CARD16);
     67 static int KdXVGetVideo(DrawablePtr, XvPortPtr, GCPtr,
     68                         INT16, INT16, CARD16, CARD16,
     69                         INT16, INT16, CARD16, CARD16);
     70 static int KdXVGetStill(DrawablePtr, XvPortPtr, GCPtr,
     71                         INT16, INT16, CARD16, CARD16,
     72                         INT16, INT16, CARD16, CARD16);
     73 static int KdXVStopVideo(XvPortPtr, DrawablePtr);
     74 static int KdXVSetPortAttribute(XvPortPtr, Atom, INT32);
     75 static int KdXVGetPortAttribute(XvPortPtr, Atom, INT32 *);
     76 static int KdXVQueryBestSize(XvPortPtr, CARD8,
     77                              CARD16, CARD16, CARD16, CARD16,
     78                              unsigned int *, unsigned int *);
     79 static int KdXVPutImage(DrawablePtr, XvPortPtr, GCPtr,
     80                         INT16, INT16, CARD16, CARD16,
     81                         INT16, INT16, CARD16, CARD16,
     82                         XvImagePtr, unsigned char *, Bool, CARD16, CARD16);
     83 static int KdXVQueryImageAttributes(XvPortPtr, XvImagePtr,
     84                                     CARD16 *, CARD16 *, int *, int *);
     85 
     86 /* ScreenRec fields */
     87 
     88 static Bool KdXVDestroyWindow(WindowPtr pWin);
     89 static void KdXVWindowExposures(WindowPtr pWin, RegionPtr r1);
     90 static void KdXVClipNotify(WindowPtr pWin, int dx, int dy);
     91 static Bool KdXVCloseScreen(ScreenPtr);
     92 
     93 /* misc */
     94 static Bool KdXVInitAdaptors(ScreenPtr, KdVideoAdaptorPtr, int);
     95 
     96 static DevPrivateKeyRec KdXVWindowKeyRec;
     97 
     98 #define KdXVWindowKey (&KdXVWindowKeyRec)
     99 static DevPrivateKey KdXvScreenKey;
    100 static DevPrivateKeyRec KdXVScreenPrivateKey;
    101 static unsigned long KdXVGeneration = 0;
    102 static unsigned long PortResource = 0;
    103 
    104 #define GET_XV_SCREEN(pScreen) ((XvScreenPtr) \
    105     dixLookupPrivate(&(pScreen)->devPrivates, KdXvScreenKey))
    106 
    107 #define GET_KDXV_SCREEN(pScreen) \
    108     ((KdXVScreenPtr)(dixGetPrivate(&pScreen->devPrivates, &KdXVScreenPrivateKey)))
    109 
    110 #define GET_KDXV_WINDOW(pWin) ((KdXVWindowPtr) \
    111     dixLookupPrivate(&(pWin)->devPrivates, KdXVWindowKey))
    112 
    113 Bool
    114 KdXVScreenInit(ScreenPtr pScreen, KdVideoAdaptorPtr adaptors, int num)
    115 {
    116     KdXVScreenPtr ScreenPriv;
    117 
    118 /*   fprintf(stderr,"KdXVScreenInit initializing %d adaptors\n",num); */
    119 
    120     if (KdXVGeneration != serverGeneration)
    121         KdXVGeneration = serverGeneration;
    122 
    123     if (noXvExtension)
    124         return FALSE;
    125 
    126     if (!dixRegisterPrivateKey(&KdXVWindowKeyRec, PRIVATE_WINDOW, 0))
    127         return FALSE;
    128     if (!dixRegisterPrivateKey(&KdXVScreenPrivateKey, PRIVATE_SCREEN, 0))
    129         return FALSE;
    130 
    131     if (Success != XvScreenInit(pScreen))
    132         return FALSE;
    133 
    134     KdXvScreenKey = XvGetScreenKey();
    135     PortResource = XvGetRTPort();
    136 
    137     ScreenPriv = malloc(sizeof(KdXVScreenRec));
    138     dixSetPrivate(&pScreen->devPrivates, &KdXVScreenPrivateKey, ScreenPriv);
    139 
    140     if (!ScreenPriv)
    141         return FALSE;
    142 
    143     ScreenPriv->DestroyWindow = pScreen->DestroyWindow;
    144     ScreenPriv->WindowExposures = pScreen->WindowExposures;
    145     ScreenPriv->ClipNotify = pScreen->ClipNotify;
    146     ScreenPriv->CloseScreen = pScreen->CloseScreen;
    147 
    148 /*   fprintf(stderr,"XV: Wrapping screen funcs\n"); */
    149 
    150     pScreen->DestroyWindow = KdXVDestroyWindow;
    151     pScreen->WindowExposures = KdXVWindowExposures;
    152     pScreen->ClipNotify = KdXVClipNotify;
    153     pScreen->CloseScreen = KdXVCloseScreen;
    154 
    155     if (!KdXVInitAdaptors(pScreen, adaptors, num))
    156         return FALSE;
    157 
    158     return TRUE;
    159 }
    160 
    161 static void
    162 KdXVFreeAdaptor(XvAdaptorPtr pAdaptor)
    163 {
    164     int i;
    165 
    166     if (pAdaptor->pPorts) {
    167         XvPortPtr pPort = pAdaptor->pPorts;
    168         XvPortRecPrivatePtr pPriv;
    169 
    170         for (i = 0; i < pAdaptor->nPorts; i++, pPort++) {
    171             pPriv = (XvPortRecPrivatePtr) pPort->devPriv.ptr;
    172             if (pPriv) {
    173                 if (pPriv->clientClip)
    174                     RegionDestroy(pPriv->clientClip);
    175                 if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
    176                     RegionDestroy(pPriv->pCompositeClip);
    177                 free(pPriv);
    178             }
    179         }
    180     }
    181 
    182     XvFreeAdaptor(pAdaptor);
    183 }
    184 
    185 static Bool
    186 KdXVInitAdaptors(ScreenPtr pScreen, KdVideoAdaptorPtr infoPtr, int number)
    187 {
    188     KdScreenPriv(pScreen);
    189     KdScreenInfo *screen = pScreenPriv->screen;
    190 
    191     XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
    192     KdVideoAdaptorPtr adaptorPtr;
    193     XvAdaptorPtr pAdaptor, pa;
    194     XvAdaptorRecPrivatePtr adaptorPriv;
    195     int na, numAdaptor;
    196     XvPortRecPrivatePtr portPriv;
    197     XvPortPtr pPort, pp;
    198     int numPort;
    199     KdVideoFormatPtr formatPtr;
    200     XvFormatPtr pFormat, pf;
    201     int numFormat, totFormat;
    202     KdVideoEncodingPtr encodingPtr;
    203     XvEncodingPtr pEncode, pe;
    204     int numVisuals;
    205     VisualPtr pVisual;
    206     int i;
    207 
    208     pxvs->nAdaptors = 0;
    209     pxvs->pAdaptors = NULL;
    210 
    211     if (!(pAdaptor = calloc(number, sizeof(XvAdaptorRec))))
    212         return FALSE;
    213 
    214     for (pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) {
    215         adaptorPtr = &infoPtr[na];
    216 
    217         if (!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute ||
    218             !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize)
    219             continue;
    220 
    221         /* client libs expect at least one encoding */
    222         if (!adaptorPtr->nEncodings || !adaptorPtr->pEncodings)
    223             continue;
    224 
    225         pa->type = adaptorPtr->type;
    226 
    227         if (!adaptorPtr->PutVideo && !adaptorPtr->GetVideo)
    228             pa->type &= ~XvVideoMask;
    229 
    230         if (!adaptorPtr->PutStill && !adaptorPtr->GetStill)
    231             pa->type &= ~XvStillMask;
    232 
    233         if (!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes)
    234             pa->type &= ~XvImageMask;
    235 
    236         if (!adaptorPtr->PutVideo && !adaptorPtr->PutImage &&
    237             !adaptorPtr->PutStill)
    238             pa->type &= ~XvInputMask;
    239 
    240         if (!adaptorPtr->GetVideo && !adaptorPtr->GetStill)
    241             pa->type &= ~XvOutputMask;
    242 
    243         if (!(adaptorPtr->type & (XvPixmapMask | XvWindowMask)))
    244             continue;
    245         if (!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask)))
    246             continue;
    247 
    248         pa->pScreen = pScreen;
    249         pa->ddPutVideo = KdXVPutVideo;
    250         pa->ddPutStill = KdXVPutStill;
    251         pa->ddGetVideo = KdXVGetVideo;
    252         pa->ddGetStill = KdXVGetStill;
    253         pa->ddStopVideo = KdXVStopVideo;
    254         pa->ddPutImage = KdXVPutImage;
    255         pa->ddSetPortAttribute = KdXVSetPortAttribute;
    256         pa->ddGetPortAttribute = KdXVGetPortAttribute;
    257         pa->ddQueryBestSize = KdXVQueryBestSize;
    258         pa->ddQueryImageAttributes = KdXVQueryImageAttributes;
    259         pa->name = strdup(adaptorPtr->name);
    260 
    261         if (adaptorPtr->nEncodings &&
    262             (pEncode = calloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) {
    263 
    264             for (pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0;
    265                  i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++) {
    266                 pe->id = encodingPtr->id;
    267                 pe->pScreen = pScreen;
    268                 pe->name = strdup(encodingPtr->name);
    269                 pe->width = encodingPtr->width;
    270                 pe->height = encodingPtr->height;
    271                 pe->rate.numerator = encodingPtr->rate.numerator;
    272                 pe->rate.denominator = encodingPtr->rate.denominator;
    273             }
    274             pa->nEncodings = adaptorPtr->nEncodings;
    275             pa->pEncodings = pEncode;
    276         }
    277 
    278         if (adaptorPtr->nImages &&
    279             (pa->pImages = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
    280             memcpy(pa->pImages, adaptorPtr->pImages,
    281                    adaptorPtr->nImages * sizeof(XvImageRec));
    282             pa->nImages = adaptorPtr->nImages;
    283         }
    284 
    285         if (adaptorPtr->nAttributes &&
    286             (pa->pAttributes = calloc(adaptorPtr->nAttributes,
    287                                       sizeof(XvAttributeRec)))) {
    288             memcpy(pa->pAttributes, adaptorPtr->pAttributes,
    289                    adaptorPtr->nAttributes * sizeof(XvAttributeRec));
    290 
    291             for (i = 0; i < adaptorPtr->nAttributes; i++) {
    292                 pa->pAttributes[i].name =
    293                     strdup(adaptorPtr->pAttributes[i].name);
    294             }
    295 
    296             pa->nAttributes = adaptorPtr->nAttributes;
    297         }
    298 
    299         totFormat = adaptorPtr->nFormats;
    300 
    301         if (!(pFormat = calloc(totFormat, sizeof(XvFormatRec)))) {
    302             KdXVFreeAdaptor(pa);
    303             continue;
    304         }
    305         for (pf = pFormat, i = 0, numFormat = 0, formatPtr =
    306              adaptorPtr->pFormats; i < adaptorPtr->nFormats; i++, formatPtr++) {
    307             numVisuals = pScreen->numVisuals;
    308             pVisual = pScreen->visuals;
    309 
    310             while (numVisuals--) {
    311                 if ((pVisual->class == formatPtr->class) &&
    312                     (pVisual->nplanes == formatPtr->depth)) {
    313 
    314                     if (numFormat >= totFormat) {
    315                         void *moreSpace;
    316 
    317                         totFormat *= 2;
    318                         moreSpace = reallocarray(pFormat, totFormat,
    319                                                  sizeof(XvFormatRec));
    320                         if (!moreSpace)
    321                             break;
    322                         pFormat = moreSpace;
    323                         pf = pFormat + numFormat;
    324                     }
    325 
    326                     pf->visual = pVisual->vid;
    327                     pf->depth = formatPtr->depth;
    328 
    329                     pf++;
    330                     numFormat++;
    331                 }
    332                 pVisual++;
    333             }
    334         }
    335         pa->nFormats = numFormat;
    336         pa->pFormats = pFormat;
    337         if (!numFormat) {
    338             KdXVFreeAdaptor(pa);
    339             continue;
    340         }
    341 
    342         if (!(adaptorPriv = calloc(1, sizeof(XvAdaptorRecPrivate)))) {
    343             KdXVFreeAdaptor(pa);
    344             continue;
    345         }
    346 
    347         adaptorPriv->flags = adaptorPtr->flags;
    348         adaptorPriv->PutVideo = adaptorPtr->PutVideo;
    349         adaptorPriv->PutStill = adaptorPtr->PutStill;
    350         adaptorPriv->GetVideo = adaptorPtr->GetVideo;
    351         adaptorPriv->GetStill = adaptorPtr->GetStill;
    352         adaptorPriv->StopVideo = adaptorPtr->StopVideo;
    353         adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute;
    354         adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute;
    355         adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize;
    356         adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes;
    357         adaptorPriv->PutImage = adaptorPtr->PutImage;
    358         adaptorPriv->ReputImage = adaptorPtr->ReputImage;
    359 
    360         pa->devPriv.ptr = (void *) adaptorPriv;
    361 
    362         if (!(pPort = calloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) {
    363             KdXVFreeAdaptor(pa);
    364             continue;
    365         }
    366         for (pp = pPort, i = 0, numPort = 0; i < adaptorPtr->nPorts; i++) {
    367 
    368             if (!(pp->id = FakeClientID(0)))
    369                 continue;
    370 
    371             if (!(portPriv = calloc(1, sizeof(XvPortRecPrivate))))
    372                 continue;
    373 
    374             if (!AddResource(pp->id, PortResource, pp)) {
    375                 free(portPriv);
    376                 continue;
    377             }
    378 
    379             pp->pAdaptor = pa;
    380             pp->pNotify = (XvPortNotifyPtr) NULL;
    381             pp->pDraw = (DrawablePtr) NULL;
    382             pp->client = (ClientPtr) NULL;
    383             pp->grab.client = (ClientPtr) NULL;
    384             pp->time = currentTime;
    385             pp->devPriv.ptr = portPriv;
    386 
    387             portPriv->screen = screen;
    388             portPriv->AdaptorRec = adaptorPriv;
    389             portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr;
    390 
    391             pp++;
    392             numPort++;
    393         }
    394         pa->nPorts = numPort;
    395         pa->pPorts = pPort;
    396         if (!numPort) {
    397             KdXVFreeAdaptor(pa);
    398             continue;
    399         }
    400 
    401         pa->base_id = pPort->id;
    402 
    403         pa++;
    404         numAdaptor++;
    405     }
    406 
    407     if (numAdaptor) {
    408         pxvs->nAdaptors = numAdaptor;
    409         pxvs->pAdaptors = pAdaptor;
    410     }
    411     else {
    412         free(pAdaptor);
    413         return FALSE;
    414     }
    415 
    416     return TRUE;
    417 }
    418 
    419 /* Video should be clipped to the intersection of the window cliplist
    420    and the client cliplist specified in the GC for which the video was
    421    initialized.  When we need to reclip a window, the GC that started
    422    the video may not even be around anymore.  That's why we save the
    423    client clip from the GC when the video is initialized.  We then
    424    use KdXVUpdateCompositeClip to calculate the new composite clip
    425    when we need it.  This is different from what DEC did.  They saved
    426    the GC and used its clip list when they needed to reclip the window,
    427    even if the client clip was different from the one the video was
    428    initialized with.  If the original GC was destroyed, they had to stop
    429    the video.  I like the new method better (MArk).
    430 
    431    This function only works for windows.  Will need to rewrite when
    432    (if) we support pixmap rendering.
    433 */
    434 
    435 static void
    436 KdXVUpdateCompositeClip(XvPortRecPrivatePtr portPriv)
    437 {
    438     RegionPtr pregWin, pCompositeClip;
    439     WindowPtr pWin;
    440     Bool freeCompClip = FALSE;
    441 
    442     if (portPriv->pCompositeClip)
    443         return;
    444 
    445     pWin = (WindowPtr) portPriv->pDraw;
    446 
    447     /* get window clip list */
    448     if (portPriv->subWindowMode == IncludeInferiors) {
    449         pregWin = NotClippedByChildren(pWin);
    450         freeCompClip = TRUE;
    451     }
    452     else
    453         pregWin = &pWin->clipList;
    454 
    455     if (!portPriv->clientClip) {
    456         portPriv->pCompositeClip = pregWin;
    457         portPriv->FreeCompositeClip = freeCompClip;
    458         return;
    459     }
    460 
    461     pCompositeClip = RegionCreate(NullBox, 1);
    462     RegionCopy(pCompositeClip, portPriv->clientClip);
    463     RegionTranslate(pCompositeClip,
    464                     portPriv->pDraw->x + portPriv->clipOrg.x,
    465                     portPriv->pDraw->y + portPriv->clipOrg.y);
    466     RegionIntersect(pCompositeClip, pregWin, pCompositeClip);
    467 
    468     portPriv->pCompositeClip = pCompositeClip;
    469     portPriv->FreeCompositeClip = TRUE;
    470 
    471     if (freeCompClip) {
    472         RegionDestroy(pregWin);
    473     }
    474 }
    475 
    476 /* Save the current clientClip and update the CompositeClip whenever
    477    we have a fresh GC */
    478 
    479 static void
    480 KdXVCopyClip(XvPortRecPrivatePtr portPriv, GCPtr pGC)
    481 {
    482     /* copy the new clip if it exists */
    483     if (pGC->clientClip) {
    484         if (!portPriv->clientClip)
    485             portPriv->clientClip = RegionCreate(NullBox, 1);
    486         /* Note: this is in window coordinates */
    487         RegionCopy(portPriv->clientClip, pGC->clientClip);
    488     }
    489     else if (portPriv->clientClip) {    /* free the old clientClip */
    490         RegionDestroy(portPriv->clientClip);
    491         portPriv->clientClip = NULL;
    492     }
    493 
    494     /* get rid of the old clip list */
    495     if (portPriv->pCompositeClip && portPriv->FreeCompositeClip) {
    496         RegionDestroy(portPriv->pCompositeClip);
    497     }
    498 
    499     portPriv->clipOrg = pGC->clipOrg;
    500     portPriv->pCompositeClip = pGC->pCompositeClip;
    501     portPriv->FreeCompositeClip = FALSE;
    502     portPriv->subWindowMode = pGC->subWindowMode;
    503 }
    504 
    505 static int
    506 KdXVRegetVideo(XvPortRecPrivatePtr portPriv)
    507 {
    508     RegionRec WinRegion;
    509     RegionRec ClipRegion;
    510     BoxRec WinBox;
    511     int ret = Success;
    512     Bool clippedAway = FALSE;
    513 
    514     KdXVUpdateCompositeClip(portPriv);
    515 
    516     /* translate the video region to the screen */
    517     WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
    518     WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
    519     WinBox.x2 = WinBox.x1 + portPriv->drw_w;
    520     WinBox.y2 = WinBox.y1 + portPriv->drw_h;
    521 
    522     /* clip to the window composite clip */
    523     RegionInit(&WinRegion, &WinBox, 1);
    524     RegionInit(&ClipRegion, NullBox, 1);
    525     RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
    526 
    527     /* that's all if it's totally obscured */
    528     if (!RegionNotEmpty(&ClipRegion)) {
    529         clippedAway = TRUE;
    530         goto CLIP_VIDEO_BAILOUT;
    531     }
    532 
    533     ret = (*portPriv->AdaptorRec->GetVideo) (portPriv->screen, portPriv->pDraw,
    534                                              portPriv->vid_x, portPriv->vid_y,
    535                                              WinBox.x1, WinBox.y1,
    536                                              portPriv->vid_w, portPriv->vid_h,
    537                                              portPriv->drw_w, portPriv->drw_h,
    538                                              &ClipRegion,
    539                                              portPriv->DevPriv.ptr);
    540 
    541     if (ret == Success)
    542         portPriv->isOn = XV_ON;
    543 
    544  CLIP_VIDEO_BAILOUT:
    545 
    546     if ((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) {
    547         (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
    548                                             portPriv->DevPriv.ptr, FALSE);
    549         portPriv->isOn = XV_PENDING;
    550     }
    551 
    552     /* This clip was copied and only good for one shot */
    553     if (!portPriv->FreeCompositeClip)
    554         portPriv->pCompositeClip = NULL;
    555 
    556     RegionUninit(&WinRegion);
    557     RegionUninit(&ClipRegion);
    558 
    559     return ret;
    560 }
    561 
    562 static int
    563 KdXVReputVideo(XvPortRecPrivatePtr portPriv)
    564 {
    565     RegionRec WinRegion;
    566     RegionRec ClipRegion;
    567     BoxRec WinBox;
    568     ScreenPtr pScreen = portPriv->pDraw->pScreen;
    569 
    570     KdScreenPriv(pScreen);
    571     KdScreenInfo *screen = pScreenPriv->screen;
    572     int ret = Success;
    573     Bool clippedAway = FALSE;
    574 
    575     KdXVUpdateCompositeClip(portPriv);
    576 
    577     /* translate the video region to the screen */
    578     WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
    579     WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
    580     WinBox.x2 = WinBox.x1 + portPriv->drw_w;
    581     WinBox.y2 = WinBox.y1 + portPriv->drw_h;
    582 
    583     /* clip to the window composite clip */
    584     RegionInit(&WinRegion, &WinBox, 1);
    585     RegionInit(&ClipRegion, NullBox, 1);
    586     RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
    587 
    588     /* clip and translate to the viewport */
    589     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
    590         RegionRec VPReg;
    591         BoxRec VPBox;
    592 
    593         VPBox.x1 = 0;
    594         VPBox.y1 = 0;
    595         VPBox.x2 = screen->width;
    596         VPBox.y2 = screen->height;
    597 
    598         RegionInit(&VPReg, &VPBox, 1);
    599         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
    600         RegionUninit(&VPReg);
    601     }
    602 
    603     /* that's all if it's totally obscured */
    604     if (!RegionNotEmpty(&ClipRegion)) {
    605         clippedAway = TRUE;
    606         goto CLIP_VIDEO_BAILOUT;
    607     }
    608 
    609     ret = (*portPriv->AdaptorRec->PutVideo) (portPriv->screen, portPriv->pDraw,
    610                                              portPriv->vid_x, portPriv->vid_y,
    611                                              WinBox.x1, WinBox.y1,
    612                                              portPriv->vid_w, portPriv->vid_h,
    613                                              portPriv->drw_w, portPriv->drw_h,
    614                                              &ClipRegion,
    615                                              portPriv->DevPriv.ptr);
    616 
    617     if (ret == Success)
    618         portPriv->isOn = XV_ON;
    619 
    620  CLIP_VIDEO_BAILOUT:
    621 
    622     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
    623         (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
    624                                             portPriv->DevPriv.ptr, FALSE);
    625         portPriv->isOn = XV_PENDING;
    626     }
    627 
    628     /* This clip was copied and only good for one shot */
    629     if (!portPriv->FreeCompositeClip)
    630         portPriv->pCompositeClip = NULL;
    631 
    632     RegionUninit(&WinRegion);
    633     RegionUninit(&ClipRegion);
    634 
    635     return ret;
    636 }
    637 
    638 static int
    639 KdXVReputImage(XvPortRecPrivatePtr portPriv)
    640 {
    641     RegionRec WinRegion;
    642     RegionRec ClipRegion;
    643     BoxRec WinBox;
    644     ScreenPtr pScreen = portPriv->pDraw->pScreen;
    645 
    646     KdScreenPriv(pScreen);
    647     KdScreenInfo *screen = pScreenPriv->screen;
    648     int ret = Success;
    649     Bool clippedAway = FALSE;
    650 
    651     KdXVUpdateCompositeClip(portPriv);
    652 
    653     /* translate the video region to the screen */
    654     WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
    655     WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
    656     WinBox.x2 = WinBox.x1 + portPriv->drw_w;
    657     WinBox.y2 = WinBox.y1 + portPriv->drw_h;
    658 
    659     /* clip to the window composite clip */
    660     RegionInit(&WinRegion, &WinBox, 1);
    661     RegionInit(&ClipRegion, NullBox, 1);
    662     RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
    663 
    664     /* clip and translate to the viewport */
    665     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
    666         RegionRec VPReg;
    667         BoxRec VPBox;
    668 
    669         VPBox.x1 = 0;
    670         VPBox.y1 = 0;
    671         VPBox.x2 = screen->width;
    672         VPBox.y2 = screen->height;
    673 
    674         RegionInit(&VPReg, &VPBox, 1);
    675         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
    676         RegionUninit(&VPReg);
    677     }
    678 
    679     /* that's all if it's totally obscured */
    680     if (!RegionNotEmpty(&ClipRegion)) {
    681         clippedAway = TRUE;
    682         goto CLIP_VIDEO_BAILOUT;
    683     }
    684 
    685     ret =
    686         (*portPriv->AdaptorRec->ReputImage) (portPriv->screen, portPriv->pDraw,
    687                                              WinBox.x1, WinBox.y1, &ClipRegion,
    688                                              portPriv->DevPriv.ptr);
    689 
    690     portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF;
    691 
    692  CLIP_VIDEO_BAILOUT:
    693 
    694     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
    695         (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
    696                                             portPriv->DevPriv.ptr, FALSE);
    697         portPriv->isOn = XV_PENDING;
    698     }
    699 
    700     /* This clip was copied and only good for one shot */
    701     if (!portPriv->FreeCompositeClip)
    702         portPriv->pCompositeClip = NULL;
    703 
    704     RegionUninit(&WinRegion);
    705     RegionUninit(&ClipRegion);
    706 
    707     return ret;
    708 }
    709 
    710 static int
    711 KdXVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
    712 {
    713     KdXVWindowPtr winPriv, PrivRoot;
    714 
    715     winPriv = PrivRoot = GET_KDXV_WINDOW(pWin);
    716 
    717     /* Enlist our port in the window private */
    718     while (winPriv) {
    719         if (winPriv->PortRec == portPriv)       /* we're already listed */
    720             break;
    721         winPriv = winPriv->next;
    722     }
    723 
    724     if (!winPriv) {
    725         winPriv = malloc(sizeof(KdXVWindowRec));
    726         if (!winPriv)
    727             return BadAlloc;
    728         winPriv->PortRec = portPriv;
    729         winPriv->next = PrivRoot;
    730         dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, winPriv);
    731     }
    732     return Success;
    733 }
    734 
    735 static void
    736 KdXVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
    737 {
    738     KdXVWindowPtr winPriv, prevPriv = NULL;
    739 
    740     winPriv = GET_KDXV_WINDOW(pWin);
    741 
    742     while (winPriv) {
    743         if (winPriv->PortRec == portPriv) {
    744             if (prevPriv)
    745                 prevPriv->next = winPriv->next;
    746             else
    747                 dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, winPriv->next);
    748             free(winPriv);
    749             break;
    750         }
    751         prevPriv = winPriv;
    752         winPriv = winPriv->next;
    753     }
    754     portPriv->pDraw = NULL;
    755 }
    756 
    757 /****  ScreenRec fields ****/
    758 
    759 static Bool
    760 KdXVDestroyWindow(WindowPtr pWin)
    761 {
    762     ScreenPtr pScreen = pWin->drawable.pScreen;
    763     KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
    764     KdXVWindowPtr tmp, WinPriv = GET_KDXV_WINDOW(pWin);
    765     int ret;
    766 
    767     while (WinPriv) {
    768         XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
    769 
    770         if (pPriv->isOn > XV_OFF) {
    771             (*pPriv->AdaptorRec->StopVideo) (pPriv->screen, pPriv->DevPriv.ptr,
    772                                              TRUE);
    773             pPriv->isOn = XV_OFF;
    774         }
    775 
    776         pPriv->pDraw = NULL;
    777         tmp = WinPriv;
    778         WinPriv = WinPriv->next;
    779         free(tmp);
    780     }
    781 
    782     dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, NULL);
    783 
    784     pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
    785     ret = (*pScreen->DestroyWindow) (pWin);
    786     pScreen->DestroyWindow = KdXVDestroyWindow;
    787 
    788     return ret;
    789 }
    790 
    791 static void
    792 KdXVWindowExposures(WindowPtr pWin, RegionPtr reg1)
    793 {
    794     ScreenPtr pScreen = pWin->drawable.pScreen;
    795     KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
    796     KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin);
    797     KdXVWindowPtr pPrev;
    798     XvPortRecPrivatePtr pPriv;
    799     Bool AreasExposed;
    800 
    801     AreasExposed = (WinPriv && reg1 && RegionNotEmpty(reg1));
    802 
    803     pScreen->WindowExposures = ScreenPriv->WindowExposures;
    804     (*pScreen->WindowExposures) (pWin, reg1);
    805     pScreen->WindowExposures = KdXVWindowExposures;
    806 
    807     /* filter out XClearWindow/Area */
    808     if (!pWin->valdata)
    809         return;
    810 
    811     pPrev = NULL;
    812 
    813     while (WinPriv) {
    814         pPriv = WinPriv->PortRec;
    815 
    816         /* Reput anyone with a reput function */
    817 
    818         switch (pPriv->type) {
    819         case XvInputMask:
    820             KdXVReputVideo(pPriv);
    821             break;
    822         case XvOutputMask:
    823             KdXVRegetVideo(pPriv);
    824             break;
    825         default:               /* overlaid still/image */
    826             if (pPriv->AdaptorRec->ReputImage)
    827                 KdXVReputImage(pPriv);
    828             else if (AreasExposed) {
    829                 KdXVWindowPtr tmp;
    830 
    831                 if (pPriv->isOn == XV_ON) {
    832                     (*pPriv->AdaptorRec->StopVideo) (pPriv->screen,
    833                                                      pPriv->DevPriv.ptr, FALSE);
    834                     pPriv->isOn = XV_PENDING;
    835                 }
    836                 pPriv->pDraw = NULL;
    837 
    838                 if (!pPrev)
    839                     dixSetPrivate(&pWin->devPrivates, KdXVWindowKey,
    840                                   WinPriv->next);
    841                 else
    842                     pPrev->next = WinPriv->next;
    843                 tmp = WinPriv;
    844                 WinPriv = WinPriv->next;
    845                 free(tmp);
    846                 continue;
    847             }
    848             break;
    849         }
    850         pPrev = WinPriv;
    851         WinPriv = WinPriv->next;
    852     }
    853 }
    854 
    855 static void
    856 KdXVClipNotify(WindowPtr pWin, int dx, int dy)
    857 {
    858     ScreenPtr pScreen = pWin->drawable.pScreen;
    859     KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
    860     KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin);
    861     KdXVWindowPtr tmp, pPrev = NULL;
    862     XvPortRecPrivatePtr pPriv;
    863     Bool visible = (pWin->visibility == VisibilityUnobscured) ||
    864         (pWin->visibility == VisibilityPartiallyObscured);
    865 
    866     while (WinPriv) {
    867         pPriv = WinPriv->PortRec;
    868 
    869         if (pPriv->pCompositeClip && pPriv->FreeCompositeClip)
    870             RegionDestroy(pPriv->pCompositeClip);
    871 
    872         pPriv->pCompositeClip = NULL;
    873 
    874         /* Stop everything except images, but stop them too if the
    875            window isn't visible.  But we only remove the images. */
    876 
    877         if (pPriv->type || !visible) {
    878             if (pPriv->isOn == XV_ON) {
    879                 (*pPriv->AdaptorRec->StopVideo) (pPriv->screen,
    880                                                  pPriv->DevPriv.ptr, FALSE);
    881                 pPriv->isOn = XV_PENDING;
    882             }
    883 
    884             if (!pPriv->type) { /* overlaid still/image */
    885                 pPriv->pDraw = NULL;
    886 
    887                 if (!pPrev)
    888                     dixSetPrivate(&pWin->devPrivates, KdXVWindowKey,
    889                                   WinPriv->next);
    890                 else
    891                     pPrev->next = WinPriv->next;
    892                 tmp = WinPriv;
    893                 WinPriv = WinPriv->next;
    894                 free(tmp);
    895                 continue;
    896             }
    897         }
    898 
    899         pPrev = WinPriv;
    900         WinPriv = WinPriv->next;
    901     }
    902 
    903     if (ScreenPriv->ClipNotify) {
    904         pScreen->ClipNotify = ScreenPriv->ClipNotify;
    905         (*pScreen->ClipNotify) (pWin, dx, dy);
    906         pScreen->ClipNotify = KdXVClipNotify;
    907     }
    908 }
    909 
    910 /**** Required XvScreenRec fields ****/
    911 
    912 static Bool
    913 KdXVCloseScreen(ScreenPtr pScreen)
    914 {
    915     XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
    916     KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen);
    917     XvAdaptorPtr pa;
    918     int c;
    919 
    920     if (!ScreenPriv)
    921         return TRUE;
    922 
    923     pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
    924     pScreen->WindowExposures = ScreenPriv->WindowExposures;
    925     pScreen->ClipNotify = ScreenPriv->ClipNotify;
    926     pScreen->CloseScreen = ScreenPriv->CloseScreen;
    927 
    928 /*   fprintf(stderr,"XV: Unwrapping screen funcs\n"); */
    929 
    930     for (c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) {
    931         KdXVFreeAdaptor(pa);
    932     }
    933 
    934     free(pxvs->pAdaptors);
    935     free(ScreenPriv);
    936 
    937     return pScreen->CloseScreen(pScreen);
    938 }
    939 
    940 /**** XvAdaptorRec fields ****/
    941 
    942 static int
    943 KdXVPutVideo(DrawablePtr pDraw,
    944              XvPortPtr pPort,
    945              GCPtr pGC,
    946              INT16 vid_x, INT16 vid_y,
    947              CARD16 vid_w, CARD16 vid_h,
    948              INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
    949 {
    950     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
    951 
    952     KdScreenPriv(portPriv->screen->pScreen);
    953     int result;
    954 
    955     /* No dumping video to pixmaps... For now anyhow */
    956     if (pDraw->type != DRAWABLE_WINDOW) {
    957         pPort->pDraw = (DrawablePtr) NULL;
    958         return BadAlloc;
    959     }
    960 
    961     /* If we are changing windows, unregister our port in the old window */
    962     if (portPriv->pDraw && (portPriv->pDraw != pDraw))
    963         KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
    964 
    965     /* Register our port with the new window */
    966     result = KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
    967     if (result != Success)
    968         return result;
    969 
    970     portPriv->pDraw = pDraw;
    971     portPriv->type = XvInputMask;
    972 
    973     /* save a copy of these parameters */
    974     portPriv->vid_x = vid_x;
    975     portPriv->vid_y = vid_y;
    976     portPriv->vid_w = vid_w;
    977     portPriv->vid_h = vid_h;
    978     portPriv->drw_x = drw_x;
    979     portPriv->drw_y = drw_y;
    980     portPriv->drw_w = drw_w;
    981     portPriv->drw_h = drw_h;
    982 
    983     /* make sure we have the most recent copy of the clientClip */
    984     KdXVCopyClip(portPriv, pGC);
    985 
    986     /* To indicate to the DI layer that we were successful */
    987     pPort->pDraw = pDraw;
    988 
    989     if (!pScreenPriv->enabled)
    990         return Success;
    991 
    992     return (KdXVReputVideo(portPriv));
    993 }
    994 
    995 static int
    996 KdXVPutStill(DrawablePtr pDraw,
    997              XvPortPtr pPort,
    998              GCPtr pGC,
    999              INT16 vid_x, INT16 vid_y,
   1000              CARD16 vid_w, CARD16 vid_h,
   1001              INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
   1002 {
   1003     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
   1004     ScreenPtr pScreen = pDraw->pScreen;
   1005 
   1006     KdScreenPriv(pScreen);
   1007     KdScreenInfo *screen = pScreenPriv->screen;
   1008     RegionRec WinRegion;
   1009     RegionRec ClipRegion;
   1010     BoxRec WinBox;
   1011     int ret = Success;
   1012     Bool clippedAway = FALSE;
   1013 
   1014     if (pDraw->type != DRAWABLE_WINDOW)
   1015         return BadAlloc;
   1016 
   1017     if (!pScreenPriv->enabled)
   1018         return Success;
   1019 
   1020     WinBox.x1 = pDraw->x + drw_x;
   1021     WinBox.y1 = pDraw->y + drw_y;
   1022     WinBox.x2 = WinBox.x1 + drw_w;
   1023     WinBox.y2 = WinBox.y1 + drw_h;
   1024 
   1025     RegionInit(&WinRegion, &WinBox, 1);
   1026     RegionInit(&ClipRegion, NullBox, 1);
   1027     RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
   1028 
   1029     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
   1030         RegionRec VPReg;
   1031         BoxRec VPBox;
   1032 
   1033         VPBox.x1 = 0;
   1034         VPBox.y1 = 0;
   1035         VPBox.x2 = screen->width;
   1036         VPBox.y2 = screen->height;
   1037 
   1038         RegionInit(&VPReg, &VPBox, 1);
   1039         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
   1040         RegionUninit(&VPReg);
   1041     }
   1042 
   1043     if (portPriv->pDraw) {
   1044         KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
   1045     }
   1046 
   1047     if (!RegionNotEmpty(&ClipRegion)) {
   1048         clippedAway = TRUE;
   1049         goto PUT_STILL_BAILOUT;
   1050     }
   1051 
   1052     ret = (*portPriv->AdaptorRec->PutStill) (portPriv->screen, pDraw,
   1053                                              vid_x, vid_y, WinBox.x1, WinBox.y1,
   1054                                              vid_w, vid_h, drw_w, drw_h,
   1055                                              &ClipRegion,
   1056                                              portPriv->DevPriv.ptr);
   1057 
   1058     if ((ret == Success) &&
   1059         (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) {
   1060 
   1061         KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
   1062         portPriv->isOn = XV_ON;
   1063         portPriv->pDraw = pDraw;
   1064         portPriv->drw_x = drw_x;
   1065         portPriv->drw_y = drw_y;
   1066         portPriv->drw_w = drw_w;
   1067         portPriv->drw_h = drw_h;
   1068         portPriv->type = 0;     /* no mask means it's transient and should
   1069                                    not be reput once it's removed */
   1070         pPort->pDraw = pDraw;   /* make sure we can get stop requests */
   1071     }
   1072 
   1073  PUT_STILL_BAILOUT:
   1074 
   1075     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
   1076         (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
   1077                                             portPriv->DevPriv.ptr, FALSE);
   1078         portPriv->isOn = XV_PENDING;
   1079     }
   1080 
   1081     RegionUninit(&WinRegion);
   1082     RegionUninit(&ClipRegion);
   1083 
   1084     return ret;
   1085 }
   1086 
   1087 static int
   1088 KdXVGetVideo(DrawablePtr pDraw,
   1089              XvPortPtr pPort,
   1090              GCPtr pGC,
   1091              INT16 vid_x, INT16 vid_y,
   1092              CARD16 vid_w, CARD16 vid_h,
   1093              INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
   1094 {
   1095     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
   1096     int result;
   1097 
   1098     KdScreenPriv(portPriv->screen->pScreen);
   1099 
   1100     /* No pixmaps... For now anyhow */
   1101     if (pDraw->type != DRAWABLE_WINDOW) {
   1102         pPort->pDraw = (DrawablePtr) NULL;
   1103         return BadAlloc;
   1104     }
   1105 
   1106     /* If we are changing windows, unregister our port in the old window */
   1107     if (portPriv->pDraw && (portPriv->pDraw != pDraw))
   1108         KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
   1109 
   1110     /* Register our port with the new window */
   1111     result = KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
   1112     if (result != Success)
   1113         return result;
   1114 
   1115     portPriv->pDraw = pDraw;
   1116     portPriv->type = XvOutputMask;
   1117 
   1118     /* save a copy of these parameters */
   1119     portPriv->vid_x = vid_x;
   1120     portPriv->vid_y = vid_y;
   1121     portPriv->vid_w = vid_w;
   1122     portPriv->vid_h = vid_h;
   1123     portPriv->drw_x = drw_x;
   1124     portPriv->drw_y = drw_y;
   1125     portPriv->drw_w = drw_w;
   1126     portPriv->drw_h = drw_h;
   1127 
   1128     /* make sure we have the most recent copy of the clientClip */
   1129     KdXVCopyClip(portPriv, pGC);
   1130 
   1131     /* To indicate to the DI layer that we were successful */
   1132     pPort->pDraw = pDraw;
   1133 
   1134     if (!pScreenPriv->enabled)
   1135         return Success;
   1136 
   1137     return (KdXVRegetVideo(portPriv));
   1138 }
   1139 
   1140 static int
   1141 KdXVGetStill(DrawablePtr pDraw,
   1142              XvPortPtr pPort,
   1143              GCPtr pGC,
   1144              INT16 vid_x, INT16 vid_y,
   1145              CARD16 vid_w, CARD16 vid_h,
   1146              INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
   1147 {
   1148     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
   1149     ScreenPtr pScreen = pDraw->pScreen;
   1150 
   1151     KdScreenPriv(pScreen);
   1152     RegionRec WinRegion;
   1153     RegionRec ClipRegion;
   1154     BoxRec WinBox;
   1155     int ret = Success;
   1156     Bool clippedAway = FALSE;
   1157 
   1158     if (pDraw->type != DRAWABLE_WINDOW)
   1159         return BadAlloc;
   1160 
   1161     if (!pScreenPriv->enabled)
   1162         return Success;
   1163 
   1164     WinBox.x1 = pDraw->x + drw_x;
   1165     WinBox.y1 = pDraw->y + drw_y;
   1166     WinBox.x2 = WinBox.x1 + drw_w;
   1167     WinBox.y2 = WinBox.y1 + drw_h;
   1168 
   1169     RegionInit(&WinRegion, &WinBox, 1);
   1170     RegionInit(&ClipRegion, NullBox, 1);
   1171     RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
   1172 
   1173     if (portPriv->pDraw) {
   1174         KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
   1175     }
   1176 
   1177     if (!RegionNotEmpty(&ClipRegion)) {
   1178         clippedAway = TRUE;
   1179         goto GET_STILL_BAILOUT;
   1180     }
   1181 
   1182     ret = (*portPriv->AdaptorRec->GetStill) (portPriv->screen, pDraw,
   1183                                              vid_x, vid_y, WinBox.x1, WinBox.y1,
   1184                                              vid_w, vid_h, drw_w, drw_h,
   1185                                              &ClipRegion,
   1186                                              portPriv->DevPriv.ptr);
   1187 
   1188  GET_STILL_BAILOUT:
   1189 
   1190     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
   1191         (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
   1192                                             portPriv->DevPriv.ptr, FALSE);
   1193         portPriv->isOn = XV_PENDING;
   1194     }
   1195 
   1196     RegionUninit(&WinRegion);
   1197     RegionUninit(&ClipRegion);
   1198 
   1199     return ret;
   1200 }
   1201 
   1202 static int
   1203 KdXVStopVideo(XvPortPtr pPort, DrawablePtr pDraw)
   1204 {
   1205     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
   1206 
   1207     KdScreenPriv(portPriv->screen->pScreen);
   1208 
   1209     if (pDraw->type != DRAWABLE_WINDOW)
   1210         return BadAlloc;
   1211 
   1212     KdXVRemovePortFromWindow((WindowPtr) pDraw, portPriv);
   1213 
   1214     if (!pScreenPriv->enabled)
   1215         return Success;
   1216 
   1217     /* Must free resources. */
   1218 
   1219     if (portPriv->isOn > XV_OFF) {
   1220         (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
   1221                                             portPriv->DevPriv.ptr, TRUE);
   1222         portPriv->isOn = XV_OFF;
   1223     }
   1224 
   1225     return Success;
   1226 }
   1227 
   1228 static int
   1229 KdXVSetPortAttribute(XvPortPtr pPort, Atom attribute, INT32 value)
   1230 {
   1231     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
   1232 
   1233     return ((*portPriv->AdaptorRec->SetPortAttribute) (portPriv->screen,
   1234                                                        attribute, value,
   1235                                                        portPriv->DevPriv.ptr));
   1236 }
   1237 
   1238 static int
   1239 KdXVGetPortAttribute(XvPortPtr pPort, Atom attribute, INT32 *p_value)
   1240 {
   1241     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
   1242 
   1243     return ((*portPriv->AdaptorRec->GetPortAttribute) (portPriv->screen,
   1244                                                        attribute,
   1245                                                        (int *) p_value,
   1246                                                        portPriv->DevPriv.ptr));
   1247 }
   1248 
   1249 static int
   1250 KdXVQueryBestSize(XvPortPtr pPort,
   1251                   CARD8 motion,
   1252                   CARD16 vid_w, CARD16 vid_h,
   1253                   CARD16 drw_w, CARD16 drw_h,
   1254                   unsigned int *p_w, unsigned int *p_h)
   1255 {
   1256     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
   1257 
   1258     (*portPriv->AdaptorRec->QueryBestSize) (portPriv->screen,
   1259                                             (Bool) motion, vid_w, vid_h, drw_w,
   1260                                             drw_h, p_w, p_h,
   1261                                             portPriv->DevPriv.ptr);
   1262 
   1263     return Success;
   1264 }
   1265 
   1266 static int
   1267 KdXVPutImage(DrawablePtr pDraw,
   1268              XvPortPtr pPort,
   1269              GCPtr pGC,
   1270              INT16 src_x, INT16 src_y,
   1271              CARD16 src_w, CARD16 src_h,
   1272              INT16 drw_x, INT16 drw_y,
   1273              CARD16 drw_w, CARD16 drw_h,
   1274              XvImagePtr format,
   1275              unsigned char *data, Bool sync, CARD16 width, CARD16 height)
   1276 {
   1277     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
   1278     ScreenPtr pScreen = pDraw->pScreen;
   1279 
   1280     KdScreenPriv(pScreen);
   1281     RegionRec WinRegion;
   1282     RegionRec ClipRegion;
   1283     BoxRec WinBox;
   1284     int ret = Success;
   1285     Bool clippedAway = FALSE;
   1286 
   1287     if (pDraw->type != DRAWABLE_WINDOW)
   1288         return BadAlloc;
   1289 
   1290     if (!pScreenPriv->enabled)
   1291         return Success;
   1292 
   1293     WinBox.x1 = pDraw->x + drw_x;
   1294     WinBox.y1 = pDraw->y + drw_y;
   1295     WinBox.x2 = WinBox.x1 + drw_w;
   1296     WinBox.y2 = WinBox.y1 + drw_h;
   1297 
   1298     RegionInit(&WinRegion, &WinBox, 1);
   1299     RegionInit(&ClipRegion, NullBox, 1);
   1300     RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
   1301 
   1302     if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
   1303         RegionRec VPReg;
   1304         BoxRec VPBox;
   1305 
   1306         VPBox.x1 = 0;
   1307         VPBox.y1 = 0;
   1308         VPBox.x2 = pScreen->width;
   1309         VPBox.y2 = pScreen->height;
   1310 
   1311         RegionInit(&VPReg, &VPBox, 1);
   1312         RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
   1313         RegionUninit(&VPReg);
   1314     }
   1315 
   1316     if (portPriv->pDraw) {
   1317         KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv);
   1318     }
   1319 
   1320     if (!RegionNotEmpty(&ClipRegion)) {
   1321         clippedAway = TRUE;
   1322         goto PUT_IMAGE_BAILOUT;
   1323     }
   1324 
   1325     ret = (*portPriv->AdaptorRec->PutImage) (portPriv->screen, pDraw,
   1326                                              src_x, src_y, WinBox.x1, WinBox.y1,
   1327                                              src_w, src_h, drw_w, drw_h,
   1328                                              format->id, data, width, height,
   1329                                              sync, &ClipRegion,
   1330                                              portPriv->DevPriv.ptr);
   1331 
   1332     if ((ret == Success) &&
   1333         (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) {
   1334 
   1335         KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv);
   1336         portPriv->isOn = XV_ON;
   1337         portPriv->pDraw = pDraw;
   1338         portPriv->drw_x = drw_x;
   1339         portPriv->drw_y = drw_y;
   1340         portPriv->drw_w = drw_w;
   1341         portPriv->drw_h = drw_h;
   1342         portPriv->type = 0;     /* no mask means it's transient and should
   1343                                    not be reput once it's removed */
   1344         pPort->pDraw = pDraw;   /* make sure we can get stop requests */
   1345     }
   1346 
   1347  PUT_IMAGE_BAILOUT:
   1348 
   1349     if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
   1350         (*portPriv->AdaptorRec->StopVideo) (portPriv->screen,
   1351                                             portPriv->DevPriv.ptr, FALSE);
   1352         portPriv->isOn = XV_PENDING;
   1353     }
   1354 
   1355     RegionUninit(&WinRegion);
   1356     RegionUninit(&ClipRegion);
   1357 
   1358     return ret;
   1359 }
   1360 
   1361 static int
   1362 KdXVQueryImageAttributes(XvPortPtr pPort,
   1363                          XvImagePtr format,
   1364                          CARD16 *width,
   1365                          CARD16 *height, int *pitches, int *offsets)
   1366 {
   1367     XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr);
   1368 
   1369     return (*portPriv->AdaptorRec->QueryImageAttributes) (portPriv->screen,
   1370                                                           format->id, width,
   1371                                                           height, pitches,
   1372                                                           offsets);
   1373 }