xserver

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

xvmain.c (28186B)


      1 /***********************************************************
      2 Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
      3 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
      4 
      5                         All Rights Reserved
      6 
      7 Permission to use, copy, modify, and distribute this software and its
      8 documentation for any purpose and without fee is hereby granted,
      9 provided that the above copyright notice appear in all copies and that
     10 both that copyright notice and this permission notice appear in
     11 supporting documentation, and that the names of Digital or MIT not be
     12 used in advertising or publicity pertaining to distribution of the
     13 software without specific, written prior permission.
     14 
     15 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     16 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     17 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     18 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     19 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     20 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     21 SOFTWARE.
     22 
     23 ******************************************************************/
     24 
     25 /*
     26 ** File:
     27 **
     28 **   xvmain.c --- Xv server extension main device independent module.
     29 **
     30 ** Author:
     31 **
     32 **   David Carver (Digital Workstation Engineering/Project Athena)
     33 **
     34 ** Revisions:
     35 **
     36 **   04.09.91 Carver
     37 **     - change: stop video always generates an event even when video
     38 **       wasn't active
     39 **
     40 **   29.08.91 Carver
     41 **     - change: unrealizing windows no longer preempts video
     42 **
     43 **   11.06.91 Carver
     44 **     - changed SetPortControl to SetPortAttribute
     45 **     - changed GetPortControl to GetPortAttribute
     46 **     - changed QueryBestSize
     47 **
     48 **   28.05.91 Carver
     49 **     - fixed Put and Get requests to not preempt operations to same drawable
     50 **
     51 **   15.05.91 Carver
     52 **     - version 2.0 upgrade
     53 **
     54 **   19.03.91 Carver
     55 **     - fixed Put and Get requests to honor grabbed ports.
     56 **     - fixed Video requests to update di structure with new drawable, and
     57 **       client after calling ddx.
     58 **
     59 **   24.01.91 Carver
     60 **     - version 1.4 upgrade
     61 **
     62 ** Notes:
     63 **
     64 **   Port structures reference client structures in a two different
     65 **   ways: when grabs, or video is active.  Each reference is encoded
     66 **   as fake client resources and thus when the client is goes away so
     67 **   does the reference (it is zeroed).  No other action is taken, so
     68 **   video doesn't necessarily stop.  It probably will as a result of
     69 **   other resources going away, but if a client starts video using
     70 **   none of its own resources, then the video will continue to play
     71 **   after the client disappears.
     72 **
     73 **
     74 */
     75 
     76 #ifdef HAVE_DIX_CONFIG_H
     77 #include <dix-config.h>
     78 #endif
     79 
     80 #include <string.h>
     81 
     82 #include <X11/X.h>
     83 #include <X11/Xproto.h>
     84 #include "misc.h"
     85 #include "os.h"
     86 #include "scrnintstr.h"
     87 #include "windowstr.h"
     88 #include "pixmapstr.h"
     89 #include "gcstruct.h"
     90 #include "extnsionst.h"
     91 #include "extinit.h"
     92 #include "dixstruct.h"
     93 #include "resource.h"
     94 #include "opaque.h"
     95 #include "input.h"
     96 
     97 #define GLOBAL
     98 
     99 #include <X11/extensions/Xv.h>
    100 #include <X11/extensions/Xvproto.h>
    101 #include "xvdix.h"
    102 
    103 #ifdef PANORAMIX
    104 #include "panoramiX.h"
    105 #include "panoramiXsrv.h"
    106 #endif
    107 #include "xvdisp.h"
    108 
    109 static DevPrivateKeyRec XvScreenKeyRec;
    110 
    111 #define XvScreenKey (&XvScreenKeyRec)
    112 unsigned long XvExtensionGeneration = 0;
    113 unsigned long XvScreenGeneration = 0;
    114 unsigned long XvResourceGeneration = 0;
    115 
    116 int XvReqCode;
    117 int XvEventBase;
    118 int XvErrorBase;
    119 
    120 RESTYPE XvRTPort;
    121 RESTYPE XvRTEncoding;
    122 RESTYPE XvRTGrab;
    123 RESTYPE XvRTVideoNotify;
    124 RESTYPE XvRTVideoNotifyList;
    125 RESTYPE XvRTPortNotify;
    126 
    127 /* EXTERNAL */
    128 
    129 static void WriteSwappedVideoNotifyEvent(xvEvent *, xvEvent *);
    130 static void WriteSwappedPortNotifyEvent(xvEvent *, xvEvent *);
    131 static Bool CreateResourceTypes(void);
    132 
    133 static Bool XvCloseScreen(ScreenPtr);
    134 static Bool XvDestroyPixmap(PixmapPtr);
    135 static Bool XvDestroyWindow(WindowPtr);
    136 static void XvResetProc(ExtensionEntry *);
    137 static int XvdiDestroyGrab(void *, XID);
    138 static int XvdiDestroyEncoding(void *, XID);
    139 static int XvdiDestroyVideoNotify(void *, XID);
    140 static int XvdiDestroyPortNotify(void *, XID);
    141 static int XvdiDestroyVideoNotifyList(void *, XID);
    142 static int XvdiDestroyPort(void *, XID);
    143 static int XvdiSendVideoNotify(XvPortPtr, DrawablePtr, int);
    144 
    145 /*
    146 ** XvExtensionInit
    147 **
    148 **
    149 */
    150 
    151 void
    152 XvExtensionInit(void)
    153 {
    154     ExtensionEntry *extEntry;
    155 
    156     if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0))
    157         return;
    158 
    159     /* Look to see if any screens were initialized; if not then
    160        init global variables so the extension can function */
    161     if (XvScreenGeneration != serverGeneration) {
    162         if (!CreateResourceTypes()) {
    163             ErrorF("XvExtensionInit: Unable to allocate resource types\n");
    164             return;
    165         }
    166 #ifdef PANORAMIX
    167         XineramaRegisterConnectionBlockCallback(XineramifyXv);
    168 #endif
    169         XvScreenGeneration = serverGeneration;
    170     }
    171 
    172     if (XvExtensionGeneration != serverGeneration) {
    173         XvExtensionGeneration = serverGeneration;
    174 
    175         extEntry = AddExtension(XvName, XvNumEvents, XvNumErrors,
    176                                 ProcXvDispatch, SProcXvDispatch,
    177                                 XvResetProc, StandardMinorOpcode);
    178         if (!extEntry) {
    179             FatalError("XvExtensionInit: AddExtensions failed\n");
    180         }
    181 
    182         XvReqCode = extEntry->base;
    183         XvEventBase = extEntry->eventBase;
    184         XvErrorBase = extEntry->errorBase;
    185 
    186         EventSwapVector[XvEventBase + XvVideoNotify] =
    187             (EventSwapPtr) WriteSwappedVideoNotifyEvent;
    188         EventSwapVector[XvEventBase + XvPortNotify] =
    189             (EventSwapPtr) WriteSwappedPortNotifyEvent;
    190 
    191         SetResourceTypeErrorValue(XvRTPort, _XvBadPort);
    192         (void) MakeAtom(XvName, strlen(XvName), xTrue);
    193 
    194     }
    195 }
    196 
    197 static Bool
    198 CreateResourceTypes(void)
    199 {
    200 
    201     if (XvResourceGeneration == serverGeneration)
    202         return TRUE;
    203 
    204     XvResourceGeneration = serverGeneration;
    205 
    206     if (!(XvRTPort = CreateNewResourceType(XvdiDestroyPort, "XvRTPort"))) {
    207         ErrorF("CreateResourceTypes: failed to allocate port resource.\n");
    208         return FALSE;
    209     }
    210 
    211     if (!(XvRTGrab = CreateNewResourceType(XvdiDestroyGrab, "XvRTGrab"))) {
    212         ErrorF("CreateResourceTypes: failed to allocate grab resource.\n");
    213         return FALSE;
    214     }
    215 
    216     if (!(XvRTEncoding = CreateNewResourceType(XvdiDestroyEncoding,
    217                                                "XvRTEncoding"))) {
    218         ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n");
    219         return FALSE;
    220     }
    221 
    222     if (!(XvRTVideoNotify = CreateNewResourceType(XvdiDestroyVideoNotify,
    223                                                   "XvRTVideoNotify"))) {
    224         ErrorF
    225             ("CreateResourceTypes: failed to allocate video notify resource.\n");
    226         return FALSE;
    227     }
    228 
    229     if (!
    230         (XvRTVideoNotifyList =
    231          CreateNewResourceType(XvdiDestroyVideoNotifyList,
    232                                "XvRTVideoNotifyList"))) {
    233         ErrorF
    234             ("CreateResourceTypes: failed to allocate video notify list resource.\n");
    235         return FALSE;
    236     }
    237 
    238     if (!(XvRTPortNotify = CreateNewResourceType(XvdiDestroyPortNotify,
    239                                                  "XvRTPortNotify"))) {
    240         ErrorF
    241             ("CreateResourceTypes: failed to allocate port notify resource.\n");
    242         return FALSE;
    243     }
    244 
    245     return TRUE;
    246 
    247 }
    248 
    249 int
    250 XvScreenInit(ScreenPtr pScreen)
    251 {
    252     XvScreenPtr pxvs;
    253 
    254     if (XvScreenGeneration != serverGeneration) {
    255         if (!CreateResourceTypes()) {
    256             ErrorF("XvScreenInit: Unable to allocate resource types\n");
    257             return BadAlloc;
    258         }
    259 #ifdef PANORAMIX
    260         XineramaRegisterConnectionBlockCallback(XineramifyXv);
    261 #endif
    262         XvScreenGeneration = serverGeneration;
    263     }
    264 
    265     if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0))
    266         return BadAlloc;
    267 
    268     if (dixLookupPrivate(&pScreen->devPrivates, XvScreenKey)) {
    269         ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n");
    270     }
    271 
    272     /* ALLOCATE SCREEN PRIVATE RECORD */
    273 
    274     pxvs = malloc(sizeof(XvScreenRec));
    275     if (!pxvs) {
    276         ErrorF("XvScreenInit: Unable to allocate screen private structure\n");
    277         return BadAlloc;
    278     }
    279 
    280     dixSetPrivate(&pScreen->devPrivates, XvScreenKey, pxvs);
    281 
    282     pxvs->DestroyPixmap = pScreen->DestroyPixmap;
    283     pxvs->DestroyWindow = pScreen->DestroyWindow;
    284     pxvs->CloseScreen = pScreen->CloseScreen;
    285 
    286     pScreen->DestroyPixmap = XvDestroyPixmap;
    287     pScreen->DestroyWindow = XvDestroyWindow;
    288     pScreen->CloseScreen = XvCloseScreen;
    289 
    290     return Success;
    291 }
    292 
    293 static Bool
    294 XvCloseScreen(ScreenPtr pScreen)
    295 {
    296 
    297     XvScreenPtr pxvs;
    298 
    299     pxvs = (XvScreenPtr) dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
    300 
    301     pScreen->DestroyPixmap = pxvs->DestroyPixmap;
    302     pScreen->DestroyWindow = pxvs->DestroyWindow;
    303     pScreen->CloseScreen = pxvs->CloseScreen;
    304 
    305     free(pxvs);
    306 
    307     dixSetPrivate(&pScreen->devPrivates, XvScreenKey, NULL);
    308 
    309     return (*pScreen->CloseScreen) (pScreen);
    310 }
    311 
    312 static void
    313 XvResetProc(ExtensionEntry * extEntry)
    314 {
    315     XvResetProcVector();
    316 }
    317 
    318 DevPrivateKey
    319 XvGetScreenKey(void)
    320 {
    321     return XvScreenKey;
    322 }
    323 
    324 unsigned long
    325 XvGetRTPort(void)
    326 {
    327     return XvRTPort;
    328 }
    329 
    330 static void
    331 XvStopAdaptors(DrawablePtr pDrawable)
    332 {
    333     ScreenPtr pScreen = pDrawable->pScreen;
    334     XvScreenPtr pxvs = dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
    335     XvAdaptorPtr pa = pxvs->pAdaptors;
    336     int na = pxvs->nAdaptors;
    337 
    338     /* CHECK TO SEE IF THIS PORT IS IN USE */
    339     while (na--) {
    340         XvPortPtr pp = pa->pPorts;
    341         int np = pa->nPorts;
    342 
    343         while (np--) {
    344             if (pp->pDraw == pDrawable) {
    345                 XvdiSendVideoNotify(pp, pDrawable, XvPreempted);
    346 
    347                 (void) (*pp->pAdaptor->ddStopVideo) (pp, pDrawable);
    348 
    349                 pp->pDraw = NULL;
    350                 pp->client = NULL;
    351                 pp->time = currentTime;
    352             }
    353             pp++;
    354         }
    355         pa++;
    356     }
    357 }
    358 
    359 static Bool
    360 XvDestroyPixmap(PixmapPtr pPix)
    361 {
    362     ScreenPtr pScreen = pPix->drawable.pScreen;
    363     Bool status;
    364 
    365     if (pPix->refcnt == 1)
    366         XvStopAdaptors(&pPix->drawable);
    367 
    368     SCREEN_PROLOGUE(pScreen, DestroyPixmap);
    369     status = (*pScreen->DestroyPixmap) (pPix);
    370     SCREEN_EPILOGUE(pScreen, DestroyPixmap, XvDestroyPixmap);
    371 
    372     return status;
    373 
    374 }
    375 
    376 static Bool
    377 XvDestroyWindow(WindowPtr pWin)
    378 {
    379     ScreenPtr pScreen = pWin->drawable.pScreen;
    380     Bool status;
    381 
    382     XvStopAdaptors(&pWin->drawable);
    383 
    384     SCREEN_PROLOGUE(pScreen, DestroyWindow);
    385     status = (*pScreen->DestroyWindow) (pWin);
    386     SCREEN_EPILOGUE(pScreen, DestroyWindow, XvDestroyWindow);
    387 
    388     return status;
    389 
    390 }
    391 
    392 static int
    393 XvdiDestroyPort(void *pPort, XID id)
    394 {
    395     return Success;
    396 }
    397 
    398 static int
    399 XvdiDestroyGrab(void *pGrab, XID id)
    400 {
    401     ((XvGrabPtr) pGrab)->client = NULL;
    402     return Success;
    403 }
    404 
    405 static int
    406 XvdiDestroyVideoNotify(void *pn, XID id)
    407 {
    408     /* JUST CLEAR OUT THE client POINTER FIELD */
    409 
    410     ((XvVideoNotifyPtr) pn)->client = NULL;
    411     return Success;
    412 }
    413 
    414 static int
    415 XvdiDestroyPortNotify(void *pn, XID id)
    416 {
    417     /* JUST CLEAR OUT THE client POINTER FIELD */
    418 
    419     ((XvPortNotifyPtr) pn)->client = NULL;
    420     return Success;
    421 }
    422 
    423 static int
    424 XvdiDestroyVideoNotifyList(void *pn, XID id)
    425 {
    426     XvVideoNotifyPtr npn, cpn;
    427 
    428     /* ACTUALLY DESTROY THE NOTIFY LIST */
    429 
    430     cpn = (XvVideoNotifyPtr) pn;
    431 
    432     while (cpn) {
    433         npn = cpn->next;
    434         if (cpn->client)
    435             FreeResource(cpn->id, XvRTVideoNotify);
    436         free(cpn);
    437         cpn = npn;
    438     }
    439     return Success;
    440 }
    441 
    442 static int
    443 XvdiDestroyEncoding(void *value, XID id)
    444 {
    445     return Success;
    446 }
    447 
    448 static int
    449 XvdiSendVideoNotify(XvPortPtr pPort, DrawablePtr pDraw, int reason)
    450 {
    451     XvVideoNotifyPtr pn;
    452 
    453     dixLookupResourceByType((void **) &pn, pDraw->id, XvRTVideoNotifyList,
    454                             serverClient, DixReadAccess);
    455 
    456     while (pn) {
    457         xvEvent event = {
    458             .u.videoNotify.reason = reason,
    459             .u.videoNotify.time = currentTime.milliseconds,
    460             .u.videoNotify.drawable = pDraw->id,
    461             .u.videoNotify.port = pPort->id
    462         };
    463         event.u.u.type = XvEventBase + XvVideoNotify;
    464         WriteEventsToClient(pn->client, 1, (xEventPtr) &event);
    465         pn = pn->next;
    466     }
    467 
    468     return Success;
    469 
    470 }
    471 
    472 int
    473 XvdiSendPortNotify(XvPortPtr pPort, Atom attribute, INT32 value)
    474 {
    475     XvPortNotifyPtr pn;
    476 
    477     pn = pPort->pNotify;
    478 
    479     while (pn) {
    480         xvEvent event = {
    481             .u.portNotify.time = currentTime.milliseconds,
    482             .u.portNotify.port = pPort->id,
    483             .u.portNotify.attribute = attribute,
    484             .u.portNotify.value = value
    485         };
    486         event.u.u.type = XvEventBase + XvPortNotify;
    487         WriteEventsToClient(pn->client, 1, (xEventPtr) &event);
    488         pn = pn->next;
    489     }
    490 
    491     return Success;
    492 
    493 }
    494 
    495 #define CHECK_SIZE(dw, dh, sw, sh) {                                  \
    496   if(!dw || !dh || !sw || !sh)  return Success;                       \
    497   /* The region code will break these if they are too large */        \
    498   if((dw > 32767) || (dh > 32767) || (sw > 32767) || (sh > 32767))    \
    499         return BadValue;                                              \
    500 }
    501 
    502 int
    503 XvdiPutVideo(ClientPtr client,
    504              DrawablePtr pDraw,
    505              XvPortPtr pPort,
    506              GCPtr pGC,
    507              INT16 vid_x, INT16 vid_y,
    508              CARD16 vid_w, CARD16 vid_h,
    509              INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
    510 {
    511     DrawablePtr pOldDraw;
    512 
    513     CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
    514 
    515     /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
    516 
    517     UpdateCurrentTime();
    518 
    519     /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
    520        INFORM CLIENT OF ITS FAILURE */
    521 
    522     if (pPort->grab.client && (pPort->grab.client != client)) {
    523         XvdiSendVideoNotify(pPort, pDraw, XvBusy);
    524         return Success;
    525     }
    526 
    527     /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
    528        EVENTS TO ANY CLIENTS WHO WANT THEM */
    529 
    530     pOldDraw = pPort->pDraw;
    531     if ((pOldDraw) && (pOldDraw != pDraw)) {
    532         XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
    533     }
    534 
    535     (void) (*pPort->pAdaptor->ddPutVideo) (pDraw, pPort, pGC,
    536                                            vid_x, vid_y, vid_w, vid_h,
    537                                            drw_x, drw_y, drw_w, drw_h);
    538 
    539     if ((pPort->pDraw) && (pOldDraw != pDraw)) {
    540         pPort->client = client;
    541         XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
    542     }
    543 
    544     pPort->time = currentTime;
    545 
    546     return Success;
    547 
    548 }
    549 
    550 int
    551 XvdiPutStill(ClientPtr client,
    552              DrawablePtr pDraw,
    553              XvPortPtr pPort,
    554              GCPtr pGC,
    555              INT16 vid_x, INT16 vid_y,
    556              CARD16 vid_w, CARD16 vid_h,
    557              INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
    558 {
    559     int status;
    560 
    561     CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
    562 
    563     /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
    564 
    565     UpdateCurrentTime();
    566 
    567     /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
    568        INFORM CLIENT OF ITS FAILURE */
    569 
    570     if (pPort->grab.client && (pPort->grab.client != client)) {
    571         XvdiSendVideoNotify(pPort, pDraw, XvBusy);
    572         return Success;
    573     }
    574 
    575     pPort->time = currentTime;
    576 
    577     status = (*pPort->pAdaptor->ddPutStill) (pDraw, pPort, pGC,
    578                                              vid_x, vid_y, vid_w, vid_h,
    579                                              drw_x, drw_y, drw_w, drw_h);
    580 
    581     return status;
    582 
    583 }
    584 
    585 int
    586 XvdiPutImage(ClientPtr client,
    587              DrawablePtr pDraw,
    588              XvPortPtr pPort,
    589              GCPtr pGC,
    590              INT16 src_x, INT16 src_y,
    591              CARD16 src_w, CARD16 src_h,
    592              INT16 drw_x, INT16 drw_y,
    593              CARD16 drw_w, CARD16 drw_h,
    594              XvImagePtr image,
    595              unsigned char *data, Bool sync, CARD16 width, CARD16 height)
    596 {
    597     CHECK_SIZE(drw_w, drw_h, src_w, src_h);
    598 
    599     /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
    600 
    601     UpdateCurrentTime();
    602 
    603     /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
    604        INFORM CLIENT OF ITS FAILURE */
    605 
    606     if (pPort->grab.client && (pPort->grab.client != client)) {
    607         XvdiSendVideoNotify(pPort, pDraw, XvBusy);
    608         return Success;
    609     }
    610 
    611     pPort->time = currentTime;
    612 
    613     return (*pPort->pAdaptor->ddPutImage) (pDraw, pPort, pGC,
    614                                            src_x, src_y, src_w, src_h,
    615                                            drw_x, drw_y, drw_w, drw_h,
    616                                            image, data, sync, width, height);
    617 }
    618 
    619 int
    620 XvdiGetVideo(ClientPtr client,
    621              DrawablePtr pDraw,
    622              XvPortPtr pPort,
    623              GCPtr pGC,
    624              INT16 vid_x, INT16 vid_y,
    625              CARD16 vid_w, CARD16 vid_h,
    626              INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
    627 {
    628     DrawablePtr pOldDraw;
    629 
    630     CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
    631 
    632     /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
    633 
    634     UpdateCurrentTime();
    635 
    636     /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
    637        INFORM CLIENT OF ITS FAILURE */
    638 
    639     if (pPort->grab.client && (pPort->grab.client != client)) {
    640         XvdiSendVideoNotify(pPort, pDraw, XvBusy);
    641         return Success;
    642     }
    643 
    644     /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
    645        EVENTS TO ANY CLIENTS WHO WANT THEM */
    646 
    647     pOldDraw = pPort->pDraw;
    648     if ((pOldDraw) && (pOldDraw != pDraw)) {
    649         XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
    650     }
    651 
    652     (void) (*pPort->pAdaptor->ddGetVideo) (pDraw, pPort, pGC,
    653                                            vid_x, vid_y, vid_w, vid_h,
    654                                            drw_x, drw_y, drw_w, drw_h);
    655 
    656     if ((pPort->pDraw) && (pOldDraw != pDraw)) {
    657         pPort->client = client;
    658         XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
    659     }
    660 
    661     pPort->time = currentTime;
    662 
    663     return Success;
    664 
    665 }
    666 
    667 int
    668 XvdiGetStill(ClientPtr client,
    669              DrawablePtr pDraw,
    670              XvPortPtr pPort,
    671              GCPtr pGC,
    672              INT16 vid_x, INT16 vid_y,
    673              CARD16 vid_w, CARD16 vid_h,
    674              INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
    675 {
    676     int status;
    677 
    678     CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
    679 
    680     /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
    681 
    682     UpdateCurrentTime();
    683 
    684     /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
    685        INFORM CLIENT OF ITS FAILURE */
    686 
    687     if (pPort->grab.client && (pPort->grab.client != client)) {
    688         XvdiSendVideoNotify(pPort, pDraw, XvBusy);
    689         return Success;
    690     }
    691 
    692     status = (*pPort->pAdaptor->ddGetStill) (pDraw, pPort, pGC,
    693                                              vid_x, vid_y, vid_w, vid_h,
    694                                              drw_x, drw_y, drw_w, drw_h);
    695 
    696     pPort->time = currentTime;
    697 
    698     return status;
    699 
    700 }
    701 
    702 int
    703 XvdiGrabPort(ClientPtr client, XvPortPtr pPort, Time ctime, int *p_result)
    704 {
    705     unsigned long id;
    706     TimeStamp time;
    707 
    708     UpdateCurrentTime();
    709     time = ClientTimeToServerTime(ctime);
    710 
    711     if (pPort->grab.client && (client != pPort->grab.client)) {
    712         *p_result = XvAlreadyGrabbed;
    713         return Success;
    714     }
    715 
    716     if ((CompareTimeStamps(time, currentTime) == LATER) ||
    717         (CompareTimeStamps(time, pPort->time) == EARLIER)) {
    718         *p_result = XvInvalidTime;
    719         return Success;
    720     }
    721 
    722     if (client == pPort->grab.client) {
    723         *p_result = Success;
    724         return Success;
    725     }
    726 
    727     id = FakeClientID(client->index);
    728 
    729     if (!AddResource(id, XvRTGrab, &pPort->grab)) {
    730         return BadAlloc;
    731     }
    732 
    733     /* IF THERE IS ACTIVE VIDEO THEN STOP IT */
    734 
    735     if ((pPort->pDraw) && (client != pPort->client)) {
    736         XvdiStopVideo(NULL, pPort, pPort->pDraw);
    737     }
    738 
    739     pPort->grab.client = client;
    740     pPort->grab.id = id;
    741 
    742     pPort->time = currentTime;
    743 
    744     *p_result = Success;
    745 
    746     return Success;
    747 
    748 }
    749 
    750 int
    751 XvdiUngrabPort(ClientPtr client, XvPortPtr pPort, Time ctime)
    752 {
    753     TimeStamp time;
    754 
    755     UpdateCurrentTime();
    756     time = ClientTimeToServerTime(ctime);
    757 
    758     if ((!pPort->grab.client) || (client != pPort->grab.client)) {
    759         return Success;
    760     }
    761 
    762     if ((CompareTimeStamps(time, currentTime) == LATER) ||
    763         (CompareTimeStamps(time, pPort->time) == EARLIER)) {
    764         return Success;
    765     }
    766 
    767     /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */
    768 
    769     FreeResource(pPort->grab.id, XvRTGrab);
    770     pPort->grab.client = NULL;
    771 
    772     pPort->time = currentTime;
    773 
    774     return Success;
    775 
    776 }
    777 
    778 int
    779 XvdiSelectVideoNotify(ClientPtr client, DrawablePtr pDraw, BOOL onoff)
    780 {
    781     XvVideoNotifyPtr pn, tpn, fpn;
    782     int rc;
    783 
    784     /* FIND VideoNotify LIST */
    785 
    786     rc = dixLookupResourceByType((void **) &pn, pDraw->id,
    787                                  XvRTVideoNotifyList, client, DixWriteAccess);
    788     if (rc != Success && rc != BadValue)
    789         return rc;
    790 
    791     /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */
    792 
    793     if (!onoff && !pn)
    794         return Success;
    795 
    796     /* IF ONE DOESN'T EXIST CREATE IT AND ADD A RESOURCE SO THAT THE LIST
    797        WILL BE DELETED WHEN THE DRAWABLE IS DESTROYED */
    798 
    799     if (!pn) {
    800         if (!(tpn = malloc(sizeof(XvVideoNotifyRec))))
    801             return BadAlloc;
    802         tpn->next = NULL;
    803         tpn->client = NULL;
    804         if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn))
    805             return BadAlloc;
    806     }
    807     else {
    808         /* LOOK TO SEE IF ENTRY ALREADY EXISTS */
    809 
    810         fpn = NULL;
    811         tpn = pn;
    812         while (tpn) {
    813             if (tpn->client == client) {
    814                 if (!onoff)
    815                     tpn->client = NULL;
    816                 return Success;
    817             }
    818             if (!tpn->client)
    819                 fpn = tpn;      /* TAKE NOTE OF FREE ENTRY */
    820             tpn = tpn->next;
    821         }
    822 
    823         /* IF TURNING OFF, THEN JUST RETURN */
    824 
    825         if (!onoff)
    826             return Success;
    827 
    828         /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */
    829 
    830         if (fpn) {
    831             tpn = fpn;
    832         }
    833         else {
    834             if (!(tpn = malloc(sizeof(XvVideoNotifyRec))))
    835                 return BadAlloc;
    836             tpn->next = pn->next;
    837             pn->next = tpn;
    838         }
    839     }
    840 
    841     /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */
    842     /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */
    843 
    844     tpn->client = NULL;
    845     tpn->id = FakeClientID(client->index);
    846     if (!AddResource(tpn->id, XvRTVideoNotify, tpn))
    847         return BadAlloc;
    848 
    849     tpn->client = client;
    850     return Success;
    851 
    852 }
    853 
    854 int
    855 XvdiSelectPortNotify(ClientPtr client, XvPortPtr pPort, BOOL onoff)
    856 {
    857     XvPortNotifyPtr pn, tpn;
    858 
    859     /* SEE IF CLIENT IS ALREADY IN LIST */
    860 
    861     tpn = NULL;
    862     pn = pPort->pNotify;
    863     while (pn) {
    864         if (!pn->client)
    865             tpn = pn;           /* TAKE NOTE OF FREE ENTRY */
    866         if (pn->client == client)
    867             break;
    868         pn = pn->next;
    869     }
    870 
    871     /* IS THE CLIENT ALREADY ON THE LIST? */
    872 
    873     if (pn) {
    874         /* REMOVE IT? */
    875 
    876         if (!onoff) {
    877             pn->client = NULL;
    878             FreeResource(pn->id, XvRTPortNotify);
    879         }
    880 
    881         return Success;
    882     }
    883 
    884     /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE
    885        CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */
    886 
    887     if (!tpn) {
    888         if (!(tpn = malloc(sizeof(XvPortNotifyRec))))
    889             return BadAlloc;
    890         tpn->next = pPort->pNotify;
    891         pPort->pNotify = tpn;
    892     }
    893 
    894     tpn->client = client;
    895     tpn->id = FakeClientID(client->index);
    896     if (!AddResource(tpn->id, XvRTPortNotify, tpn))
    897         return BadAlloc;
    898 
    899     return Success;
    900 
    901 }
    902 
    903 int
    904 XvdiStopVideo(ClientPtr client, XvPortPtr pPort, DrawablePtr pDraw)
    905 {
    906     int status;
    907 
    908     /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
    909 
    910     if (!pPort->pDraw || (pPort->pDraw != pDraw)) {
    911         XvdiSendVideoNotify(pPort, pDraw, XvStopped);
    912         return Success;
    913     }
    914 
    915     /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
    916        INFORM CLIENT OF ITS FAILURE */
    917 
    918     if ((client) && (pPort->grab.client) && (pPort->grab.client != client)) {
    919         XvdiSendVideoNotify(pPort, pDraw, XvBusy);
    920         return Success;
    921     }
    922 
    923     XvdiSendVideoNotify(pPort, pDraw, XvStopped);
    924 
    925     status = (*pPort->pAdaptor->ddStopVideo) (pPort, pDraw);
    926 
    927     pPort->pDraw = NULL;
    928     pPort->client = (ClientPtr) client;
    929     pPort->time = currentTime;
    930 
    931     return status;
    932 
    933 }
    934 
    935 int
    936 XvdiMatchPort(XvPortPtr pPort, DrawablePtr pDraw)
    937 {
    938 
    939     XvAdaptorPtr pa;
    940     XvFormatPtr pf;
    941     int nf;
    942 
    943     pa = pPort->pAdaptor;
    944 
    945     if (pa->pScreen != pDraw->pScreen)
    946         return BadMatch;
    947 
    948     nf = pa->nFormats;
    949     pf = pa->pFormats;
    950 
    951     while (nf--) {
    952         if (pf->depth == pDraw->depth)
    953             return Success;
    954         pf++;
    955     }
    956 
    957     return BadMatch;
    958 
    959 }
    960 
    961 int
    962 XvdiSetPortAttribute(ClientPtr client,
    963                      XvPortPtr pPort, Atom attribute, INT32 value)
    964 {
    965     int status;
    966 
    967     status =
    968         (*pPort->pAdaptor->ddSetPortAttribute) (pPort, attribute,
    969                                                 value);
    970     if (status == Success)
    971         XvdiSendPortNotify(pPort, attribute, value);
    972 
    973     return status;
    974 }
    975 
    976 int
    977 XvdiGetPortAttribute(ClientPtr client,
    978                      XvPortPtr pPort, Atom attribute, INT32 *p_value)
    979 {
    980 
    981     return
    982         (*pPort->pAdaptor->ddGetPortAttribute) (pPort, attribute,
    983                                                 p_value);
    984 
    985 }
    986 
    987 static void _X_COLD
    988 WriteSwappedVideoNotifyEvent(xvEvent * from, xvEvent * to)
    989 {
    990 
    991     to->u.u.type = from->u.u.type;
    992     to->u.u.detail = from->u.u.detail;
    993     cpswaps(from->u.videoNotify.sequenceNumber,
    994             to->u.videoNotify.sequenceNumber);
    995     cpswapl(from->u.videoNotify.time, to->u.videoNotify.time);
    996     cpswapl(from->u.videoNotify.drawable, to->u.videoNotify.drawable);
    997     cpswapl(from->u.videoNotify.port, to->u.videoNotify.port);
    998 
    999 }
   1000 
   1001 static void _X_COLD
   1002 WriteSwappedPortNotifyEvent(xvEvent * from, xvEvent * to)
   1003 {
   1004 
   1005     to->u.u.type = from->u.u.type;
   1006     to->u.u.detail = from->u.u.detail;
   1007     cpswaps(from->u.portNotify.sequenceNumber, to->u.portNotify.sequenceNumber);
   1008     cpswapl(from->u.portNotify.time, to->u.portNotify.time);
   1009     cpswapl(from->u.portNotify.port, to->u.portNotify.port);
   1010     cpswapl(from->u.portNotify.value, to->u.portNotify.value);
   1011 
   1012 }
   1013 
   1014 void
   1015 XvFreeAdaptor(XvAdaptorPtr pAdaptor)
   1016 {
   1017     int i;
   1018 
   1019     free(pAdaptor->name);
   1020     pAdaptor->name = NULL;
   1021 
   1022     if (pAdaptor->pEncodings) {
   1023         XvEncodingPtr pEncode = pAdaptor->pEncodings;
   1024 
   1025         for (i = 0; i < pAdaptor->nEncodings; i++, pEncode++)
   1026             free(pEncode->name);
   1027         free(pAdaptor->pEncodings);
   1028         pAdaptor->pEncodings = NULL;
   1029     }
   1030 
   1031     free(pAdaptor->pFormats);
   1032     pAdaptor->pFormats = NULL;
   1033 
   1034     free(pAdaptor->pPorts);
   1035     pAdaptor->pPorts = NULL;
   1036 
   1037     if (pAdaptor->pAttributes) {
   1038         XvAttributePtr pAttribute = pAdaptor->pAttributes;
   1039 
   1040         for (i = 0; i < pAdaptor->nAttributes; i++, pAttribute++)
   1041             free(pAttribute->name);
   1042         free(pAdaptor->pAttributes);
   1043         pAdaptor->pAttributes = NULL;
   1044     }
   1045 
   1046     free(pAdaptor->pImages);
   1047     pAdaptor->pImages = NULL;
   1048 
   1049     free(pAdaptor->devPriv.ptr);
   1050     pAdaptor->devPriv.ptr = NULL;
   1051 }
   1052 
   1053 void
   1054 XvFillColorKey(DrawablePtr pDraw, CARD32 key, RegionPtr region)
   1055 {
   1056     ScreenPtr pScreen = pDraw->pScreen;
   1057     ChangeGCVal pval[2];
   1058     BoxPtr pbox = RegionRects(region);
   1059     int i, nbox = RegionNumRects(region);
   1060     xRectangle *rects;
   1061     GCPtr gc;
   1062 
   1063     gc = GetScratchGC(pDraw->depth, pScreen);
   1064     if (!gc)
   1065         return;
   1066 
   1067     pval[0].val = key;
   1068     pval[1].val = IncludeInferiors;
   1069     (void) ChangeGC(NullClient, gc, GCForeground | GCSubwindowMode, pval);
   1070     ValidateGC(pDraw, gc);
   1071 
   1072     rects = xallocarray(nbox, sizeof(xRectangle));
   1073     if (rects) {
   1074         for (i = 0; i < nbox; i++, pbox++) {
   1075             rects[i].x = pbox->x1 - pDraw->x;
   1076             rects[i].y = pbox->y1 - pDraw->y;
   1077             rects[i].width = pbox->x2 - pbox->x1;
   1078             rects[i].height = pbox->y2 - pbox->y1;
   1079         }
   1080 
   1081         (*gc->ops->PolyFillRect) (pDraw, gc, nbox, rects);
   1082 
   1083         free(rects);
   1084     }
   1085     FreeScratchGC(gc);
   1086 }