105b261ecSmrg/***********************************************************
205b261ecSmrgCopyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
305b261ecSmrgand the Massachusetts Institute of Technology, Cambridge, Massachusetts.
405b261ecSmrg
505b261ecSmrg                        All Rights Reserved
605b261ecSmrg
735c4bbdfSmrgPermission to use, copy, modify, and distribute this software and its
835c4bbdfSmrgdocumentation for any purpose and without fee is hereby granted,
905b261ecSmrgprovided that the above copyright notice appear in all copies and that
1035c4bbdfSmrgboth that copyright notice and this permission notice appear in
1105b261ecSmrgsupporting documentation, and that the names of Digital or MIT not be
1205b261ecSmrgused in advertising or publicity pertaining to distribution of the
1335c4bbdfSmrgsoftware without specific, written prior permission.
1405b261ecSmrg
1505b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
1605b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
1705b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
1805b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
1905b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2005b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2105b261ecSmrgSOFTWARE.
2205b261ecSmrg
2305b261ecSmrg******************************************************************/
2405b261ecSmrg
2505b261ecSmrg/*
2635c4bbdfSmrg** File:
2705b261ecSmrg**
2805b261ecSmrg**   xvmain.c --- Xv server extension main device independent module.
2935c4bbdfSmrg**
3035c4bbdfSmrg** Author:
3105b261ecSmrg**
3205b261ecSmrg**   David Carver (Digital Workstation Engineering/Project Athena)
3305b261ecSmrg**
3405b261ecSmrg** Revisions:
3505b261ecSmrg**
3605b261ecSmrg**   04.09.91 Carver
3705b261ecSmrg**     - change: stop video always generates an event even when video
3805b261ecSmrg**       wasn't active
3905b261ecSmrg**
4005b261ecSmrg**   29.08.91 Carver
4105b261ecSmrg**     - change: unrealizing windows no longer preempts video
4205b261ecSmrg**
4305b261ecSmrg**   11.06.91 Carver
4405b261ecSmrg**     - changed SetPortControl to SetPortAttribute
4505b261ecSmrg**     - changed GetPortControl to GetPortAttribute
4605b261ecSmrg**     - changed QueryBestSize
4705b261ecSmrg**
4805b261ecSmrg**   28.05.91 Carver
4905b261ecSmrg**     - fixed Put and Get requests to not preempt operations to same drawable
5005b261ecSmrg**
5105b261ecSmrg**   15.05.91 Carver
5205b261ecSmrg**     - version 2.0 upgrade
5305b261ecSmrg**
5405b261ecSmrg**   19.03.91 Carver
5505b261ecSmrg**     - fixed Put and Get requests to honor grabbed ports.
5605b261ecSmrg**     - fixed Video requests to update di structure with new drawable, and
5705b261ecSmrg**       client after calling ddx.
5805b261ecSmrg**
5905b261ecSmrg**   24.01.91 Carver
6005b261ecSmrg**     - version 1.4 upgrade
6135c4bbdfSmrg**
6205b261ecSmrg** Notes:
6305b261ecSmrg**
6405b261ecSmrg**   Port structures reference client structures in a two different
6505b261ecSmrg**   ways: when grabs, or video is active.  Each reference is encoded
6605b261ecSmrg**   as fake client resources and thus when the client is goes away so
6705b261ecSmrg**   does the reference (it is zeroed).  No other action is taken, so
6805b261ecSmrg**   video doesn't necessarily stop.  It probably will as a result of
6905b261ecSmrg**   other resources going away, but if a client starts video using
7005b261ecSmrg**   none of its own resources, then the video will continue to play
7105b261ecSmrg**   after the client disappears.
7205b261ecSmrg**
7305b261ecSmrg**
7405b261ecSmrg*/
7505b261ecSmrg
7605b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
7705b261ecSmrg#include <dix-config.h>
7805b261ecSmrg#endif
7905b261ecSmrg
8005b261ecSmrg#include <string.h>
8105b261ecSmrg
8205b261ecSmrg#include <X11/X.h>
8305b261ecSmrg#include <X11/Xproto.h>
8405b261ecSmrg#include "misc.h"
8505b261ecSmrg#include "os.h"
8605b261ecSmrg#include "scrnintstr.h"
8705b261ecSmrg#include "windowstr.h"
8805b261ecSmrg#include "pixmapstr.h"
8935c4bbdfSmrg#include "gcstruct.h"
9005b261ecSmrg#include "extnsionst.h"
9135c4bbdfSmrg#include "extinit.h"
9205b261ecSmrg#include "dixstruct.h"
9305b261ecSmrg#include "resource.h"
9405b261ecSmrg#include "opaque.h"
9505b261ecSmrg#include "input.h"
9605b261ecSmrg
9705b261ecSmrg#define GLOBAL
9805b261ecSmrg
9905b261ecSmrg#include <X11/extensions/Xv.h>
10005b261ecSmrg#include <X11/extensions/Xvproto.h>
10105b261ecSmrg#include "xvdix.h"
10205b261ecSmrg
10305b261ecSmrg#ifdef PANORAMIX
10405b261ecSmrg#include "panoramiX.h"
10505b261ecSmrg#include "panoramiXsrv.h"
10605b261ecSmrg#endif
1074642e01fSmrg#include "xvdisp.h"
10805b261ecSmrg
1096747b715Smrgstatic DevPrivateKeyRec XvScreenKeyRec;
11035c4bbdfSmrg
1116747b715Smrg#define XvScreenKey (&XvScreenKeyRec)
11205b261ecSmrgunsigned long XvExtensionGeneration = 0;
11305b261ecSmrgunsigned long XvScreenGeneration = 0;
11405b261ecSmrgunsigned long XvResourceGeneration = 0;
11505b261ecSmrg
11605b261ecSmrgint XvReqCode;
11705b261ecSmrgint XvEventBase;
11805b261ecSmrgint XvErrorBase;
11905b261ecSmrg
12035c4bbdfSmrgRESTYPE XvRTPort;
12135c4bbdfSmrgRESTYPE XvRTEncoding;
12235c4bbdfSmrgRESTYPE XvRTGrab;
12335c4bbdfSmrgRESTYPE XvRTVideoNotify;
12435c4bbdfSmrgRESTYPE XvRTVideoNotifyList;
12535c4bbdfSmrgRESTYPE XvRTPortNotify;
12605b261ecSmrg
12705b261ecSmrg/* EXTERNAL */
12805b261ecSmrg
12905b261ecSmrgstatic void WriteSwappedVideoNotifyEvent(xvEvent *, xvEvent *);
13005b261ecSmrgstatic void WriteSwappedPortNotifyEvent(xvEvent *, xvEvent *);
13105b261ecSmrgstatic Bool CreateResourceTypes(void);
13205b261ecSmrg
13335c4bbdfSmrgstatic Bool XvCloseScreen(ScreenPtr);
13405b261ecSmrgstatic Bool XvDestroyPixmap(PixmapPtr);
13505b261ecSmrgstatic Bool XvDestroyWindow(WindowPtr);
13635c4bbdfSmrgstatic void XvResetProc(ExtensionEntry *);
13735c4bbdfSmrgstatic int XvdiDestroyGrab(void *, XID);
13835c4bbdfSmrgstatic int XvdiDestroyEncoding(void *, XID);
13935c4bbdfSmrgstatic int XvdiDestroyVideoNotify(void *, XID);
14035c4bbdfSmrgstatic int XvdiDestroyPortNotify(void *, XID);
14135c4bbdfSmrgstatic int XvdiDestroyVideoNotifyList(void *, XID);
14235c4bbdfSmrgstatic int XvdiDestroyPort(void *, XID);
14305b261ecSmrgstatic int XvdiSendVideoNotify(XvPortPtr, DrawablePtr, int);
14405b261ecSmrg
14505b261ecSmrg/*
14605b261ecSmrg** XvExtensionInit
14705b261ecSmrg**
14805b261ecSmrg**
14905b261ecSmrg*/
15005b261ecSmrg
1516747b715Smrgvoid
15205b261ecSmrgXvExtensionInit(void)
15305b261ecSmrg{
15435c4bbdfSmrg    ExtensionEntry *extEntry;
15535c4bbdfSmrg
15635c4bbdfSmrg    if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0))
15735c4bbdfSmrg        return;
15835c4bbdfSmrg
15935c4bbdfSmrg    /* Look to see if any screens were initialized; if not then
16035c4bbdfSmrg       init global variables so the extension can function */
16135c4bbdfSmrg    if (XvScreenGeneration != serverGeneration) {
16235c4bbdfSmrg        if (!CreateResourceTypes()) {
16335c4bbdfSmrg            ErrorF("XvExtensionInit: Unable to allocate resource types\n");
16435c4bbdfSmrg            return;
16535c4bbdfSmrg        }
16605b261ecSmrg#ifdef PANORAMIX
16705b261ecSmrg        XineramaRegisterConnectionBlockCallback(XineramifyXv);
16805b261ecSmrg#endif
16935c4bbdfSmrg        XvScreenGeneration = serverGeneration;
17005b261ecSmrg    }
17105b261ecSmrg
17235c4bbdfSmrg    if (XvExtensionGeneration != serverGeneration) {
17335c4bbdfSmrg        XvExtensionGeneration = serverGeneration;
17405b261ecSmrg
17535c4bbdfSmrg        extEntry = AddExtension(XvName, XvNumEvents, XvNumErrors,
17635c4bbdfSmrg                                ProcXvDispatch, SProcXvDispatch,
17735c4bbdfSmrg                                XvResetProc, StandardMinorOpcode);
17835c4bbdfSmrg        if (!extEntry) {
17935c4bbdfSmrg            FatalError("XvExtensionInit: AddExtensions failed\n");
18035c4bbdfSmrg        }
18105b261ecSmrg
18235c4bbdfSmrg        XvReqCode = extEntry->base;
18335c4bbdfSmrg        XvEventBase = extEntry->eventBase;
18435c4bbdfSmrg        XvErrorBase = extEntry->errorBase;
18505b261ecSmrg
18635c4bbdfSmrg        EventSwapVector[XvEventBase + XvVideoNotify] =
18735c4bbdfSmrg            (EventSwapPtr) WriteSwappedVideoNotifyEvent;
18835c4bbdfSmrg        EventSwapVector[XvEventBase + XvPortNotify] =
18935c4bbdfSmrg            (EventSwapPtr) WriteSwappedPortNotifyEvent;
19005b261ecSmrg
19135c4bbdfSmrg        SetResourceTypeErrorValue(XvRTPort, _XvBadPort);
19235c4bbdfSmrg        (void) MakeAtom(XvName, strlen(XvName), xTrue);
19305b261ecSmrg
19405b261ecSmrg    }
19505b261ecSmrg}
19605b261ecSmrg
19705b261ecSmrgstatic Bool
19805b261ecSmrgCreateResourceTypes(void)
19905b261ecSmrg{
20005b261ecSmrg
20135c4bbdfSmrg    if (XvResourceGeneration == serverGeneration)
20235c4bbdfSmrg        return TRUE;
20335c4bbdfSmrg
20435c4bbdfSmrg    XvResourceGeneration = serverGeneration;
20505b261ecSmrg
20635c4bbdfSmrg    if (!(XvRTPort = CreateNewResourceType(XvdiDestroyPort, "XvRTPort"))) {
20735c4bbdfSmrg        ErrorF("CreateResourceTypes: failed to allocate port resource.\n");
20835c4bbdfSmrg        return FALSE;
20905b261ecSmrg    }
2106747b715Smrg
21135c4bbdfSmrg    if (!(XvRTGrab = CreateNewResourceType(XvdiDestroyGrab, "XvRTGrab"))) {
21235c4bbdfSmrg        ErrorF("CreateResourceTypes: failed to allocate grab resource.\n");
21335c4bbdfSmrg        return FALSE;
21405b261ecSmrg    }
2156747b715Smrg
21635c4bbdfSmrg    if (!(XvRTEncoding = CreateNewResourceType(XvdiDestroyEncoding,
21735c4bbdfSmrg                                               "XvRTEncoding"))) {
21835c4bbdfSmrg        ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n");
21935c4bbdfSmrg        return FALSE;
22005b261ecSmrg    }
2216747b715Smrg
22235c4bbdfSmrg    if (!(XvRTVideoNotify = CreateNewResourceType(XvdiDestroyVideoNotify,
22335c4bbdfSmrg                                                  "XvRTVideoNotify"))) {
22435c4bbdfSmrg        ErrorF
22535c4bbdfSmrg            ("CreateResourceTypes: failed to allocate video notify resource.\n");
22635c4bbdfSmrg        return FALSE;
22705b261ecSmrg    }
2286747b715Smrg
22935c4bbdfSmrg    if (!
23035c4bbdfSmrg        (XvRTVideoNotifyList =
23135c4bbdfSmrg         CreateNewResourceType(XvdiDestroyVideoNotifyList,
23235c4bbdfSmrg                               "XvRTVideoNotifyList"))) {
23335c4bbdfSmrg        ErrorF
23435c4bbdfSmrg            ("CreateResourceTypes: failed to allocate video notify list resource.\n");
23535c4bbdfSmrg        return FALSE;
23605b261ecSmrg    }
23705b261ecSmrg
23835c4bbdfSmrg    if (!(XvRTPortNotify = CreateNewResourceType(XvdiDestroyPortNotify,
23935c4bbdfSmrg                                                 "XvRTPortNotify"))) {
24035c4bbdfSmrg        ErrorF
24135c4bbdfSmrg            ("CreateResourceTypes: failed to allocate port notify resource.\n");
24235c4bbdfSmrg        return FALSE;
24305b261ecSmrg    }
24405b261ecSmrg
24535c4bbdfSmrg    return TRUE;
24605b261ecSmrg
24705b261ecSmrg}
24805b261ecSmrg
2496747b715Smrgint
25005b261ecSmrgXvScreenInit(ScreenPtr pScreen)
25105b261ecSmrg{
25235c4bbdfSmrg    XvScreenPtr pxvs;
25335c4bbdfSmrg
25435c4bbdfSmrg    if (XvScreenGeneration != serverGeneration) {
25535c4bbdfSmrg        if (!CreateResourceTypes()) {
25635c4bbdfSmrg            ErrorF("XvScreenInit: Unable to allocate resource types\n");
25735c4bbdfSmrg            return BadAlloc;
25835c4bbdfSmrg        }
25905b261ecSmrg#ifdef PANORAMIX
26005b261ecSmrg        XineramaRegisterConnectionBlockCallback(XineramifyXv);
26105b261ecSmrg#endif
26235c4bbdfSmrg        XvScreenGeneration = serverGeneration;
26305b261ecSmrg    }
26405b261ecSmrg
26535c4bbdfSmrg    if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0))
26635c4bbdfSmrg        return BadAlloc;
2676747b715Smrg
26835c4bbdfSmrg    if (dixLookupPrivate(&pScreen->devPrivates, XvScreenKey)) {
26935c4bbdfSmrg        ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n");
27005b261ecSmrg    }
27105b261ecSmrg
27235c4bbdfSmrg    /* ALLOCATE SCREEN PRIVATE RECORD */
27335c4bbdfSmrg
27435c4bbdfSmrg    pxvs = malloc(sizeof(XvScreenRec));
27535c4bbdfSmrg    if (!pxvs) {
27635c4bbdfSmrg        ErrorF("XvScreenInit: Unable to allocate screen private structure\n");
27735c4bbdfSmrg        return BadAlloc;
27805b261ecSmrg    }
27905b261ecSmrg
28035c4bbdfSmrg    dixSetPrivate(&pScreen->devPrivates, XvScreenKey, pxvs);
28135c4bbdfSmrg
28235c4bbdfSmrg    pxvs->DestroyPixmap = pScreen->DestroyPixmap;
28335c4bbdfSmrg    pxvs->DestroyWindow = pScreen->DestroyWindow;
28435c4bbdfSmrg    pxvs->CloseScreen = pScreen->CloseScreen;
28535c4bbdfSmrg
28635c4bbdfSmrg    pScreen->DestroyPixmap = XvDestroyPixmap;
28735c4bbdfSmrg    pScreen->DestroyWindow = XvDestroyWindow;
28835c4bbdfSmrg    pScreen->CloseScreen = XvCloseScreen;
28935c4bbdfSmrg
29035c4bbdfSmrg    return Success;
29105b261ecSmrg}
29205b261ecSmrg
29305b261ecSmrgstatic Bool
29435c4bbdfSmrgXvCloseScreen(ScreenPtr pScreen)
29535c4bbdfSmrg{
29605b261ecSmrg
29735c4bbdfSmrg    XvScreenPtr pxvs;
29805b261ecSmrg
29935c4bbdfSmrg    pxvs = (XvScreenPtr) dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
30005b261ecSmrg
30135c4bbdfSmrg    pScreen->DestroyPixmap = pxvs->DestroyPixmap;
30235c4bbdfSmrg    pScreen->DestroyWindow = pxvs->DestroyWindow;
30335c4bbdfSmrg    pScreen->CloseScreen = pxvs->CloseScreen;
30405b261ecSmrg
30535c4bbdfSmrg    free(pxvs);
30605b261ecSmrg
30735c4bbdfSmrg    dixSetPrivate(&pScreen->devPrivates, XvScreenKey, NULL);
30805b261ecSmrg
30935c4bbdfSmrg    return (*pScreen->CloseScreen) (pScreen);
31005b261ecSmrg}
31105b261ecSmrg
31205b261ecSmrgstatic void
31335c4bbdfSmrgXvResetProc(ExtensionEntry * extEntry)
31405b261ecSmrg{
3154642e01fSmrg    XvResetProcVector();
31605b261ecSmrg}
31705b261ecSmrg
3186747b715SmrgDevPrivateKey
3194642e01fSmrgXvGetScreenKey(void)
32005b261ecSmrg{
3214642e01fSmrg    return XvScreenKey;
32205b261ecSmrg}
32305b261ecSmrg
3246747b715Smrgunsigned long
32505b261ecSmrgXvGetRTPort(void)
32605b261ecSmrg{
32735c4bbdfSmrg    return XvRTPort;
32805b261ecSmrg}
32905b261ecSmrg
33035c4bbdfSmrgstatic void
33135c4bbdfSmrgXvStopAdaptors(DrawablePtr pDrawable)
33205b261ecSmrg{
33335c4bbdfSmrg    ScreenPtr pScreen = pDrawable->pScreen;
33435c4bbdfSmrg    XvScreenPtr pxvs = dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
33535c4bbdfSmrg    XvAdaptorPtr pa = pxvs->pAdaptors;
33635c4bbdfSmrg    int na = pxvs->nAdaptors;
33735c4bbdfSmrg
33835c4bbdfSmrg    /* CHECK TO SEE IF THIS PORT IS IN USE */
33935c4bbdfSmrg    while (na--) {
34035c4bbdfSmrg        XvPortPtr pp = pa->pPorts;
34135c4bbdfSmrg        int np = pa->nPorts;
34235c4bbdfSmrg
34335c4bbdfSmrg        while (np--) {
34435c4bbdfSmrg            if (pp->pDraw == pDrawable) {
34535c4bbdfSmrg                XvdiSendVideoNotify(pp, pDrawable, XvPreempted);
34635c4bbdfSmrg
34735c4bbdfSmrg                (void) (*pp->pAdaptor->ddStopVideo) (pp, pDrawable);
34835c4bbdfSmrg
34935c4bbdfSmrg                pp->pDraw = NULL;
35035c4bbdfSmrg                pp->client = NULL;
35135c4bbdfSmrg                pp->time = currentTime;
35235c4bbdfSmrg            }
35335c4bbdfSmrg            pp++;
35435c4bbdfSmrg        }
35535c4bbdfSmrg        pa++;
35605b261ecSmrg    }
35705b261ecSmrg}
35805b261ecSmrg
35905b261ecSmrgstatic Bool
36035c4bbdfSmrgXvDestroyPixmap(PixmapPtr pPix)
36105b261ecSmrg{
36235c4bbdfSmrg    ScreenPtr pScreen = pPix->drawable.pScreen;
36335c4bbdfSmrg    Bool status;
36405b261ecSmrg
36535c4bbdfSmrg    if (pPix->refcnt == 1)
36635c4bbdfSmrg        XvStopAdaptors(&pPix->drawable);
36705b261ecSmrg
36835c4bbdfSmrg    SCREEN_PROLOGUE(pScreen, DestroyPixmap);
36935c4bbdfSmrg    status = (*pScreen->DestroyPixmap) (pPix);
37035c4bbdfSmrg    SCREEN_EPILOGUE(pScreen, DestroyPixmap, XvDestroyPixmap);
37105b261ecSmrg
37235c4bbdfSmrg    return status;
37305b261ecSmrg
37405b261ecSmrg}
37505b261ecSmrg
37635c4bbdfSmrgstatic Bool
37735c4bbdfSmrgXvDestroyWindow(WindowPtr pWin)
37805b261ecSmrg{
37935c4bbdfSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
38035c4bbdfSmrg    Bool status;
38105b261ecSmrg
38235c4bbdfSmrg    XvStopAdaptors(&pWin->drawable);
38305b261ecSmrg
38435c4bbdfSmrg    SCREEN_PROLOGUE(pScreen, DestroyWindow);
38535c4bbdfSmrg    status = (*pScreen->DestroyWindow) (pWin);
38635c4bbdfSmrg    SCREEN_EPILOGUE(pScreen, DestroyWindow, XvDestroyWindow);
38705b261ecSmrg
38835c4bbdfSmrg    return status;
38905b261ecSmrg
39005b261ecSmrg}
39105b261ecSmrg
39235c4bbdfSmrgstatic int
39335c4bbdfSmrgXvdiDestroyPort(void *pPort, XID id)
39405b261ecSmrg{
39535c4bbdfSmrg    return Success;
39605b261ecSmrg}
39705b261ecSmrg
39805b261ecSmrgstatic int
39935c4bbdfSmrgXvdiDestroyGrab(void *pGrab, XID id)
40005b261ecSmrg{
40135c4bbdfSmrg    ((XvGrabPtr) pGrab)->client = NULL;
40235c4bbdfSmrg    return Success;
40305b261ecSmrg}
40405b261ecSmrg
40505b261ecSmrgstatic int
40635c4bbdfSmrgXvdiDestroyVideoNotify(void *pn, XID id)
40705b261ecSmrg{
40835c4bbdfSmrg    /* JUST CLEAR OUT THE client POINTER FIELD */
40905b261ecSmrg
41035c4bbdfSmrg    ((XvVideoNotifyPtr) pn)->client = NULL;
41135c4bbdfSmrg    return Success;
41205b261ecSmrg}
41305b261ecSmrg
41405b261ecSmrgstatic int
41535c4bbdfSmrgXvdiDestroyPortNotify(void *pn, XID id)
41605b261ecSmrg{
41735c4bbdfSmrg    /* JUST CLEAR OUT THE client POINTER FIELD */
41805b261ecSmrg
41935c4bbdfSmrg    ((XvPortNotifyPtr) pn)->client = NULL;
42035c4bbdfSmrg    return Success;
42105b261ecSmrg}
42205b261ecSmrg
42305b261ecSmrgstatic int
42435c4bbdfSmrgXvdiDestroyVideoNotifyList(void *pn, XID id)
42505b261ecSmrg{
42635c4bbdfSmrg    XvVideoNotifyPtr npn, cpn;
42705b261ecSmrg
428ed6184dfSmrg    /* ACTUALLY DESTROY THE NOTIFY LIST */
42905b261ecSmrg
43035c4bbdfSmrg    cpn = (XvVideoNotifyPtr) pn;
43105b261ecSmrg
43235c4bbdfSmrg    while (cpn) {
43335c4bbdfSmrg        npn = cpn->next;
43435c4bbdfSmrg        if (cpn->client)
43535c4bbdfSmrg            FreeResource(cpn->id, XvRTVideoNotify);
43635c4bbdfSmrg        free(cpn);
43735c4bbdfSmrg        cpn = npn;
43805b261ecSmrg    }
43935c4bbdfSmrg    return Success;
44005b261ecSmrg}
44105b261ecSmrg
44205b261ecSmrgstatic int
44335c4bbdfSmrgXvdiDestroyEncoding(void *value, XID id)
44405b261ecSmrg{
44535c4bbdfSmrg    return Success;
44605b261ecSmrg}
44705b261ecSmrg
44805b261ecSmrgstatic int
4496747b715SmrgXvdiSendVideoNotify(XvPortPtr pPort, DrawablePtr pDraw, int reason)
45005b261ecSmrg{
45135c4bbdfSmrg    XvVideoNotifyPtr pn;
45235c4bbdfSmrg
45335c4bbdfSmrg    dixLookupResourceByType((void **) &pn, pDraw->id, XvRTVideoNotifyList,
45435c4bbdfSmrg                            serverClient, DixReadAccess);
45535c4bbdfSmrg
45635c4bbdfSmrg    while (pn) {
45735c4bbdfSmrg        xvEvent event = {
45835c4bbdfSmrg            .u.videoNotify.reason = reason,
45935c4bbdfSmrg            .u.videoNotify.time = currentTime.milliseconds,
46035c4bbdfSmrg            .u.videoNotify.drawable = pDraw->id,
46135c4bbdfSmrg            .u.videoNotify.port = pPort->id
46235c4bbdfSmrg        };
46335c4bbdfSmrg        event.u.u.type = XvEventBase + XvVideoNotify;
46435c4bbdfSmrg        WriteEventsToClient(pn->client, 1, (xEventPtr) &event);
46535c4bbdfSmrg        pn = pn->next;
46605b261ecSmrg    }
46705b261ecSmrg
46835c4bbdfSmrg    return Success;
46905b261ecSmrg
47005b261ecSmrg}
47105b261ecSmrg
47205b261ecSmrgint
47335c4bbdfSmrgXvdiSendPortNotify(XvPortPtr pPort, Atom attribute, INT32 value)
47435c4bbdfSmrg{
47535c4bbdfSmrg    XvPortNotifyPtr pn;
47635c4bbdfSmrg
47735c4bbdfSmrg    pn = pPort->pNotify;
47835c4bbdfSmrg
47935c4bbdfSmrg    while (pn) {
48035c4bbdfSmrg        xvEvent event = {
48135c4bbdfSmrg            .u.portNotify.time = currentTime.milliseconds,
48235c4bbdfSmrg            .u.portNotify.port = pPort->id,
48335c4bbdfSmrg            .u.portNotify.attribute = attribute,
48435c4bbdfSmrg            .u.portNotify.value = value
48535c4bbdfSmrg        };
48635c4bbdfSmrg        event.u.u.type = XvEventBase + XvPortNotify;
48735c4bbdfSmrg        WriteEventsToClient(pn->client, 1, (xEventPtr) &event);
48835c4bbdfSmrg        pn = pn->next;
48905b261ecSmrg    }
49005b261ecSmrg
49135c4bbdfSmrg    return Success;
49205b261ecSmrg
49305b261ecSmrg}
49405b261ecSmrg
49505b261ecSmrg#define CHECK_SIZE(dw, dh, sw, sh) {                                  \
49605b261ecSmrg  if(!dw || !dh || !sw || !sh)  return Success;                       \
49705b261ecSmrg  /* The region code will break these if they are too large */        \
49805b261ecSmrg  if((dw > 32767) || (dh > 32767) || (sw > 32767) || (sh > 32767))    \
49905b261ecSmrg        return BadValue;                                              \
50005b261ecSmrg}
50105b261ecSmrg
50205b261ecSmrgint
50335c4bbdfSmrgXvdiPutVideo(ClientPtr client,
50435c4bbdfSmrg             DrawablePtr pDraw,
50535c4bbdfSmrg             XvPortPtr pPort,
50635c4bbdfSmrg             GCPtr pGC,
50735c4bbdfSmrg             INT16 vid_x, INT16 vid_y,
50835c4bbdfSmrg             CARD16 vid_w, CARD16 vid_h,
50935c4bbdfSmrg             INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
51035c4bbdfSmrg{
51135c4bbdfSmrg    DrawablePtr pOldDraw;
51235c4bbdfSmrg
51335c4bbdfSmrg    CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
51435c4bbdfSmrg
51535c4bbdfSmrg    /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
51635c4bbdfSmrg
51735c4bbdfSmrg    UpdateCurrentTime();
51835c4bbdfSmrg
51935c4bbdfSmrg    /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
52035c4bbdfSmrg       INFORM CLIENT OF ITS FAILURE */
52135c4bbdfSmrg
52235c4bbdfSmrg    if (pPort->grab.client && (pPort->grab.client != client)) {
52335c4bbdfSmrg        XvdiSendVideoNotify(pPort, pDraw, XvBusy);
52435c4bbdfSmrg        return Success;
52505b261ecSmrg    }
52605b261ecSmrg
52735c4bbdfSmrg    /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
52835c4bbdfSmrg       EVENTS TO ANY CLIENTS WHO WANT THEM */
52905b261ecSmrg
53035c4bbdfSmrg    pOldDraw = pPort->pDraw;
53135c4bbdfSmrg    if ((pOldDraw) && (pOldDraw != pDraw)) {
53235c4bbdfSmrg        XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
53305b261ecSmrg    }
53405b261ecSmrg
53535c4bbdfSmrg    (void) (*pPort->pAdaptor->ddPutVideo) (pDraw, pPort, pGC,
53635c4bbdfSmrg                                           vid_x, vid_y, vid_w, vid_h,
53735c4bbdfSmrg                                           drw_x, drw_y, drw_w, drw_h);
53805b261ecSmrg
53935c4bbdfSmrg    if ((pPort->pDraw) && (pOldDraw != pDraw)) {
54035c4bbdfSmrg        pPort->client = client;
54135c4bbdfSmrg        XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
54205b261ecSmrg    }
54305b261ecSmrg
54435c4bbdfSmrg    pPort->time = currentTime;
54505b261ecSmrg
54635c4bbdfSmrg    return Success;
54705b261ecSmrg
54805b261ecSmrg}
54905b261ecSmrg
55005b261ecSmrgint
55135c4bbdfSmrgXvdiPutStill(ClientPtr client,
55235c4bbdfSmrg             DrawablePtr pDraw,
55335c4bbdfSmrg             XvPortPtr pPort,
55435c4bbdfSmrg             GCPtr pGC,
55535c4bbdfSmrg             INT16 vid_x, INT16 vid_y,
55635c4bbdfSmrg             CARD16 vid_w, CARD16 vid_h,
55735c4bbdfSmrg             INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
55835c4bbdfSmrg{
55935c4bbdfSmrg    int status;
56035c4bbdfSmrg
56135c4bbdfSmrg    CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
56235c4bbdfSmrg
56335c4bbdfSmrg    /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
56435c4bbdfSmrg
56535c4bbdfSmrg    UpdateCurrentTime();
56635c4bbdfSmrg
56735c4bbdfSmrg    /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
56835c4bbdfSmrg       INFORM CLIENT OF ITS FAILURE */
56935c4bbdfSmrg
57035c4bbdfSmrg    if (pPort->grab.client && (pPort->grab.client != client)) {
57135c4bbdfSmrg        XvdiSendVideoNotify(pPort, pDraw, XvBusy);
57235c4bbdfSmrg        return Success;
57305b261ecSmrg    }
57405b261ecSmrg
57535c4bbdfSmrg    pPort->time = currentTime;
57605b261ecSmrg
57735c4bbdfSmrg    status = (*pPort->pAdaptor->ddPutStill) (pDraw, pPort, pGC,
57835c4bbdfSmrg                                             vid_x, vid_y, vid_w, vid_h,
57935c4bbdfSmrg                                             drw_x, drw_y, drw_w, drw_h);
58005b261ecSmrg
58135c4bbdfSmrg    return status;
58205b261ecSmrg
58305b261ecSmrg}
58405b261ecSmrg
58505b261ecSmrgint
58635c4bbdfSmrgXvdiPutImage(ClientPtr client,
58735c4bbdfSmrg             DrawablePtr pDraw,
58835c4bbdfSmrg             XvPortPtr pPort,
58935c4bbdfSmrg             GCPtr pGC,
59035c4bbdfSmrg             INT16 src_x, INT16 src_y,
59135c4bbdfSmrg             CARD16 src_w, CARD16 src_h,
59235c4bbdfSmrg             INT16 drw_x, INT16 drw_y,
59335c4bbdfSmrg             CARD16 drw_w, CARD16 drw_h,
59435c4bbdfSmrg             XvImagePtr image,
59535c4bbdfSmrg             unsigned char *data, Bool sync, CARD16 width, CARD16 height)
59635c4bbdfSmrg{
59735c4bbdfSmrg    CHECK_SIZE(drw_w, drw_h, src_w, src_h);
59835c4bbdfSmrg
59935c4bbdfSmrg    /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
60035c4bbdfSmrg
60135c4bbdfSmrg    UpdateCurrentTime();
60235c4bbdfSmrg
60335c4bbdfSmrg    /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
60435c4bbdfSmrg       INFORM CLIENT OF ITS FAILURE */
60535c4bbdfSmrg
60635c4bbdfSmrg    if (pPort->grab.client && (pPort->grab.client != client)) {
60735c4bbdfSmrg        XvdiSendVideoNotify(pPort, pDraw, XvBusy);
60835c4bbdfSmrg        return Success;
60905b261ecSmrg    }
61005b261ecSmrg
61135c4bbdfSmrg    pPort->time = currentTime;
61205b261ecSmrg
61335c4bbdfSmrg    return (*pPort->pAdaptor->ddPutImage) (pDraw, pPort, pGC,
61435c4bbdfSmrg                                           src_x, src_y, src_w, src_h,
61535c4bbdfSmrg                                           drw_x, drw_y, drw_w, drw_h,
61635c4bbdfSmrg                                           image, data, sync, width, height);
61705b261ecSmrg}
61805b261ecSmrg
61905b261ecSmrgint
62035c4bbdfSmrgXvdiGetVideo(ClientPtr client,
62135c4bbdfSmrg             DrawablePtr pDraw,
62235c4bbdfSmrg             XvPortPtr pPort,
62335c4bbdfSmrg             GCPtr pGC,
62435c4bbdfSmrg             INT16 vid_x, INT16 vid_y,
62535c4bbdfSmrg             CARD16 vid_w, CARD16 vid_h,
62635c4bbdfSmrg             INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
62735c4bbdfSmrg{
62835c4bbdfSmrg    DrawablePtr pOldDraw;
62935c4bbdfSmrg
63035c4bbdfSmrg    CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
63135c4bbdfSmrg
63235c4bbdfSmrg    /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
63335c4bbdfSmrg
63435c4bbdfSmrg    UpdateCurrentTime();
63535c4bbdfSmrg
63635c4bbdfSmrg    /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
63735c4bbdfSmrg       INFORM CLIENT OF ITS FAILURE */
63835c4bbdfSmrg
63935c4bbdfSmrg    if (pPort->grab.client && (pPort->grab.client != client)) {
64035c4bbdfSmrg        XvdiSendVideoNotify(pPort, pDraw, XvBusy);
64135c4bbdfSmrg        return Success;
64205b261ecSmrg    }
64305b261ecSmrg
64435c4bbdfSmrg    /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
64535c4bbdfSmrg       EVENTS TO ANY CLIENTS WHO WANT THEM */
64605b261ecSmrg
64735c4bbdfSmrg    pOldDraw = pPort->pDraw;
64835c4bbdfSmrg    if ((pOldDraw) && (pOldDraw != pDraw)) {
64935c4bbdfSmrg        XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
65005b261ecSmrg    }
65105b261ecSmrg
65235c4bbdfSmrg    (void) (*pPort->pAdaptor->ddGetVideo) (pDraw, pPort, pGC,
65335c4bbdfSmrg                                           vid_x, vid_y, vid_w, vid_h,
65435c4bbdfSmrg                                           drw_x, drw_y, drw_w, drw_h);
65505b261ecSmrg
65635c4bbdfSmrg    if ((pPort->pDraw) && (pOldDraw != pDraw)) {
65735c4bbdfSmrg        pPort->client = client;
65835c4bbdfSmrg        XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
65905b261ecSmrg    }
66005b261ecSmrg
66135c4bbdfSmrg    pPort->time = currentTime;
66205b261ecSmrg
66335c4bbdfSmrg    return Success;
66405b261ecSmrg
66505b261ecSmrg}
66605b261ecSmrg
66705b261ecSmrgint
66835c4bbdfSmrgXvdiGetStill(ClientPtr client,
66935c4bbdfSmrg             DrawablePtr pDraw,
67035c4bbdfSmrg             XvPortPtr pPort,
67135c4bbdfSmrg             GCPtr pGC,
67235c4bbdfSmrg             INT16 vid_x, INT16 vid_y,
67335c4bbdfSmrg             CARD16 vid_w, CARD16 vid_h,
67435c4bbdfSmrg             INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
67535c4bbdfSmrg{
67635c4bbdfSmrg    int status;
67735c4bbdfSmrg
67835c4bbdfSmrg    CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
67935c4bbdfSmrg
68035c4bbdfSmrg    /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
68135c4bbdfSmrg
68235c4bbdfSmrg    UpdateCurrentTime();
68335c4bbdfSmrg
68435c4bbdfSmrg    /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
68535c4bbdfSmrg       INFORM CLIENT OF ITS FAILURE */
68635c4bbdfSmrg
68735c4bbdfSmrg    if (pPort->grab.client && (pPort->grab.client != client)) {
68835c4bbdfSmrg        XvdiSendVideoNotify(pPort, pDraw, XvBusy);
68935c4bbdfSmrg        return Success;
69005b261ecSmrg    }
69105b261ecSmrg
69235c4bbdfSmrg    status = (*pPort->pAdaptor->ddGetStill) (pDraw, pPort, pGC,
69335c4bbdfSmrg                                             vid_x, vid_y, vid_w, vid_h,
69435c4bbdfSmrg                                             drw_x, drw_y, drw_w, drw_h);
69505b261ecSmrg
69635c4bbdfSmrg    pPort->time = currentTime;
69705b261ecSmrg
69835c4bbdfSmrg    return status;
69905b261ecSmrg
70005b261ecSmrg}
70105b261ecSmrg
70205b261ecSmrgint
70335c4bbdfSmrgXvdiGrabPort(ClientPtr client, XvPortPtr pPort, Time ctime, int *p_result)
70435c4bbdfSmrg{
70535c4bbdfSmrg    unsigned long id;
70635c4bbdfSmrg    TimeStamp time;
70735c4bbdfSmrg
70835c4bbdfSmrg    UpdateCurrentTime();
70935c4bbdfSmrg    time = ClientTimeToServerTime(ctime);
71035c4bbdfSmrg
71135c4bbdfSmrg    if (pPort->grab.client && (client != pPort->grab.client)) {
71235c4bbdfSmrg        *p_result = XvAlreadyGrabbed;
71335c4bbdfSmrg        return Success;
71405b261ecSmrg    }
71505b261ecSmrg
71635c4bbdfSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
71735c4bbdfSmrg        (CompareTimeStamps(time, pPort->time) == EARLIER)) {
71835c4bbdfSmrg        *p_result = XvInvalidTime;
71935c4bbdfSmrg        return Success;
72005b261ecSmrg    }
72105b261ecSmrg
72235c4bbdfSmrg    if (client == pPort->grab.client) {
72335c4bbdfSmrg        *p_result = Success;
72435c4bbdfSmrg        return Success;
72505b261ecSmrg    }
72605b261ecSmrg
72735c4bbdfSmrg    id = FakeClientID(client->index);
72805b261ecSmrg
72935c4bbdfSmrg    if (!AddResource(id, XvRTGrab, &pPort->grab)) {
73035c4bbdfSmrg        return BadAlloc;
73105b261ecSmrg    }
73205b261ecSmrg
73335c4bbdfSmrg    /* IF THERE IS ACTIVE VIDEO THEN STOP IT */
73405b261ecSmrg
73535c4bbdfSmrg    if ((pPort->pDraw) && (client != pPort->client)) {
73635c4bbdfSmrg        XvdiStopVideo(NULL, pPort, pPort->pDraw);
73705b261ecSmrg    }
73805b261ecSmrg
73935c4bbdfSmrg    pPort->grab.client = client;
74035c4bbdfSmrg    pPort->grab.id = id;
74105b261ecSmrg
74235c4bbdfSmrg    pPort->time = currentTime;
74305b261ecSmrg
74435c4bbdfSmrg    *p_result = Success;
74505b261ecSmrg
74635c4bbdfSmrg    return Success;
74705b261ecSmrg
74805b261ecSmrg}
74905b261ecSmrg
75005b261ecSmrgint
75135c4bbdfSmrgXvdiUngrabPort(ClientPtr client, XvPortPtr pPort, Time ctime)
75235c4bbdfSmrg{
75335c4bbdfSmrg    TimeStamp time;
75435c4bbdfSmrg
75535c4bbdfSmrg    UpdateCurrentTime();
75635c4bbdfSmrg    time = ClientTimeToServerTime(ctime);
75735c4bbdfSmrg
75835c4bbdfSmrg    if ((!pPort->grab.client) || (client != pPort->grab.client)) {
75935c4bbdfSmrg        return Success;
76005b261ecSmrg    }
76105b261ecSmrg
76235c4bbdfSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
76335c4bbdfSmrg        (CompareTimeStamps(time, pPort->time) == EARLIER)) {
76435c4bbdfSmrg        return Success;
76505b261ecSmrg    }
76605b261ecSmrg
76735c4bbdfSmrg    /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */
76805b261ecSmrg
76935c4bbdfSmrg    FreeResource(pPort->grab.id, XvRTGrab);
77035c4bbdfSmrg    pPort->grab.client = NULL;
77105b261ecSmrg
77235c4bbdfSmrg    pPort->time = currentTime;
77305b261ecSmrg
77435c4bbdfSmrg    return Success;
77505b261ecSmrg
77605b261ecSmrg}
77705b261ecSmrg
77805b261ecSmrgint
77935c4bbdfSmrgXvdiSelectVideoNotify(ClientPtr client, DrawablePtr pDraw, BOOL onoff)
78035c4bbdfSmrg{
78135c4bbdfSmrg    XvVideoNotifyPtr pn, tpn, fpn;
78235c4bbdfSmrg    int rc;
78335c4bbdfSmrg
78435c4bbdfSmrg    /* FIND VideoNotify LIST */
78535c4bbdfSmrg
78635c4bbdfSmrg    rc = dixLookupResourceByType((void **) &pn, pDraw->id,
78735c4bbdfSmrg                                 XvRTVideoNotifyList, client, DixWriteAccess);
78835c4bbdfSmrg    if (rc != Success && rc != BadValue)
78935c4bbdfSmrg        return rc;
79035c4bbdfSmrg
79135c4bbdfSmrg    /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */
79235c4bbdfSmrg
79335c4bbdfSmrg    if (!onoff && !pn)
79435c4bbdfSmrg        return Success;
79535c4bbdfSmrg
79635c4bbdfSmrg    /* IF ONE DOESN'T EXIST CREATE IT AND ADD A RESOURCE SO THAT THE LIST
79735c4bbdfSmrg       WILL BE DELETED WHEN THE DRAWABLE IS DESTROYED */
79835c4bbdfSmrg
79935c4bbdfSmrg    if (!pn) {
80035c4bbdfSmrg        if (!(tpn = malloc(sizeof(XvVideoNotifyRec))))
80135c4bbdfSmrg            return BadAlloc;
80235c4bbdfSmrg        tpn->next = NULL;
80335c4bbdfSmrg        tpn->client = NULL;
80435c4bbdfSmrg        if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn))
80535c4bbdfSmrg            return BadAlloc;
80605b261ecSmrg    }
80735c4bbdfSmrg    else {
80835c4bbdfSmrg        /* LOOK TO SEE IF ENTRY ALREADY EXISTS */
80935c4bbdfSmrg
81035c4bbdfSmrg        fpn = NULL;
81135c4bbdfSmrg        tpn = pn;
81235c4bbdfSmrg        while (tpn) {
81335c4bbdfSmrg            if (tpn->client == client) {
814c82838c1Smrg                if (!onoff) {
81535c4bbdfSmrg                    tpn->client = NULL;
816c82838c1Smrg                    FreeResource(tpn->id, XvRTVideoNotify);
817c82838c1Smrg                }
81835c4bbdfSmrg                return Success;
81935c4bbdfSmrg            }
82035c4bbdfSmrg            if (!tpn->client)
82135c4bbdfSmrg                fpn = tpn;      /* TAKE NOTE OF FREE ENTRY */
82235c4bbdfSmrg            tpn = tpn->next;
82335c4bbdfSmrg        }
82435c4bbdfSmrg
825ed6184dfSmrg        /* IF TURNING OFF, THEN JUST RETURN */
82635c4bbdfSmrg
82735c4bbdfSmrg        if (!onoff)
82835c4bbdfSmrg            return Success;
82935c4bbdfSmrg
83035c4bbdfSmrg        /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */
83135c4bbdfSmrg
83235c4bbdfSmrg        if (fpn) {
83335c4bbdfSmrg            tpn = fpn;
83435c4bbdfSmrg        }
83535c4bbdfSmrg        else {
83635c4bbdfSmrg            if (!(tpn = malloc(sizeof(XvVideoNotifyRec))))
83735c4bbdfSmrg                return BadAlloc;
83835c4bbdfSmrg            tpn->next = pn->next;
83935c4bbdfSmrg            pn->next = tpn;
84035c4bbdfSmrg        }
84105b261ecSmrg    }
84205b261ecSmrg
84335c4bbdfSmrg    /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */
84435c4bbdfSmrg    /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */
84505b261ecSmrg
84635c4bbdfSmrg    tpn->client = NULL;
84735c4bbdfSmrg    tpn->id = FakeClientID(client->index);
84835c4bbdfSmrg    if (!AddResource(tpn->id, XvRTVideoNotify, tpn))
84935c4bbdfSmrg        return BadAlloc;
85005b261ecSmrg
85135c4bbdfSmrg    tpn->client = client;
85235c4bbdfSmrg    return Success;
85305b261ecSmrg
85405b261ecSmrg}
85505b261ecSmrg
85605b261ecSmrgint
85735c4bbdfSmrgXvdiSelectPortNotify(ClientPtr client, XvPortPtr pPort, BOOL onoff)
85835c4bbdfSmrg{
85935c4bbdfSmrg    XvPortNotifyPtr pn, tpn;
86035c4bbdfSmrg
86135c4bbdfSmrg    /* SEE IF CLIENT IS ALREADY IN LIST */
86235c4bbdfSmrg
86335c4bbdfSmrg    tpn = NULL;
86435c4bbdfSmrg    pn = pPort->pNotify;
86535c4bbdfSmrg    while (pn) {
86635c4bbdfSmrg        if (!pn->client)
86735c4bbdfSmrg            tpn = pn;           /* TAKE NOTE OF FREE ENTRY */
86835c4bbdfSmrg        if (pn->client == client)
86935c4bbdfSmrg            break;
87035c4bbdfSmrg        pn = pn->next;
87105b261ecSmrg    }
87205b261ecSmrg
87335c4bbdfSmrg    /* IS THE CLIENT ALREADY ON THE LIST? */
87405b261ecSmrg
87535c4bbdfSmrg    if (pn) {
87635c4bbdfSmrg        /* REMOVE IT? */
87705b261ecSmrg
87835c4bbdfSmrg        if (!onoff) {
87935c4bbdfSmrg            pn->client = NULL;
88035c4bbdfSmrg            FreeResource(pn->id, XvRTPortNotify);
88135c4bbdfSmrg        }
88205b261ecSmrg
88335c4bbdfSmrg        return Success;
88405b261ecSmrg    }
88505b261ecSmrg
88635c4bbdfSmrg    /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE
88735c4bbdfSmrg       CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */
88805b261ecSmrg
88935c4bbdfSmrg    if (!tpn) {
89035c4bbdfSmrg        if (!(tpn = malloc(sizeof(XvPortNotifyRec))))
89135c4bbdfSmrg            return BadAlloc;
89235c4bbdfSmrg        tpn->next = pPort->pNotify;
89335c4bbdfSmrg        pPort->pNotify = tpn;
89405b261ecSmrg    }
89505b261ecSmrg
89635c4bbdfSmrg    tpn->client = client;
89735c4bbdfSmrg    tpn->id = FakeClientID(client->index);
89835c4bbdfSmrg    if (!AddResource(tpn->id, XvRTPortNotify, tpn))
89935c4bbdfSmrg        return BadAlloc;
90005b261ecSmrg
90135c4bbdfSmrg    return Success;
90205b261ecSmrg
90305b261ecSmrg}
90405b261ecSmrg
90505b261ecSmrgint
90635c4bbdfSmrgXvdiStopVideo(ClientPtr client, XvPortPtr pPort, DrawablePtr pDraw)
90735c4bbdfSmrg{
90835c4bbdfSmrg    int status;
90935c4bbdfSmrg
91035c4bbdfSmrg    /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
91135c4bbdfSmrg
91235c4bbdfSmrg    if (!pPort->pDraw || (pPort->pDraw != pDraw)) {
91335c4bbdfSmrg        XvdiSendVideoNotify(pPort, pDraw, XvStopped);
91435c4bbdfSmrg        return Success;
91505b261ecSmrg    }
91605b261ecSmrg
91735c4bbdfSmrg    /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
91835c4bbdfSmrg       INFORM CLIENT OF ITS FAILURE */
91905b261ecSmrg
92035c4bbdfSmrg    if ((client) && (pPort->grab.client) && (pPort->grab.client != client)) {
92135c4bbdfSmrg        XvdiSendVideoNotify(pPort, pDraw, XvBusy);
92235c4bbdfSmrg        return Success;
92305b261ecSmrg    }
92405b261ecSmrg
92535c4bbdfSmrg    XvdiSendVideoNotify(pPort, pDraw, XvStopped);
92605b261ecSmrg
92735c4bbdfSmrg    status = (*pPort->pAdaptor->ddStopVideo) (pPort, pDraw);
92805b261ecSmrg
92935c4bbdfSmrg    pPort->pDraw = NULL;
93035c4bbdfSmrg    pPort->client = (ClientPtr) client;
93135c4bbdfSmrg    pPort->time = currentTime;
93205b261ecSmrg
93335c4bbdfSmrg    return status;
93405b261ecSmrg
93505b261ecSmrg}
93605b261ecSmrg
93705b261ecSmrgint
93835c4bbdfSmrgXvdiMatchPort(XvPortPtr pPort, DrawablePtr pDraw)
93935c4bbdfSmrg{
94005b261ecSmrg
94135c4bbdfSmrg    XvAdaptorPtr pa;
94235c4bbdfSmrg    XvFormatPtr pf;
94335c4bbdfSmrg    int nf;
94405b261ecSmrg
94535c4bbdfSmrg    pa = pPort->pAdaptor;
94605b261ecSmrg
94735c4bbdfSmrg    if (pa->pScreen != pDraw->pScreen)
94835c4bbdfSmrg        return BadMatch;
94905b261ecSmrg
95035c4bbdfSmrg    nf = pa->nFormats;
95135c4bbdfSmrg    pf = pa->pFormats;
95205b261ecSmrg
95335c4bbdfSmrg    while (nf--) {
95435c4bbdfSmrg        if (pf->depth == pDraw->depth)
95535c4bbdfSmrg            return Success;
95635c4bbdfSmrg        pf++;
95735c4bbdfSmrg    }
95805b261ecSmrg
95935c4bbdfSmrg    return BadMatch;
96005b261ecSmrg
96105b261ecSmrg}
96205b261ecSmrg
96305b261ecSmrgint
96435c4bbdfSmrgXvdiSetPortAttribute(ClientPtr client,
96535c4bbdfSmrg                     XvPortPtr pPort, Atom attribute, INT32 value)
96635c4bbdfSmrg{
96735c4bbdfSmrg    int status;
96805b261ecSmrg
96935c4bbdfSmrg    status =
97035c4bbdfSmrg        (*pPort->pAdaptor->ddSetPortAttribute) (pPort, attribute,
97135c4bbdfSmrg                                                value);
97235c4bbdfSmrg    if (status == Success)
97335c4bbdfSmrg        XvdiSendPortNotify(pPort, attribute, value);
97405b261ecSmrg
97535c4bbdfSmrg    return status;
97635c4bbdfSmrg}
97705b261ecSmrg
97835c4bbdfSmrgint
97935c4bbdfSmrgXvdiGetPortAttribute(ClientPtr client,
98035c4bbdfSmrg                     XvPortPtr pPort, Atom attribute, INT32 *p_value)
98135c4bbdfSmrg{
98205b261ecSmrg
98335c4bbdfSmrg    return
98435c4bbdfSmrg        (*pPort->pAdaptor->ddGetPortAttribute) (pPort, attribute,
98535c4bbdfSmrg                                                p_value);
98605b261ecSmrg
98735c4bbdfSmrg}
98805b261ecSmrg
9891b5d61b8Smrgstatic void _X_COLD
99035c4bbdfSmrgWriteSwappedVideoNotifyEvent(xvEvent * from, xvEvent * to)
99135c4bbdfSmrg{
99205b261ecSmrg
99335c4bbdfSmrg    to->u.u.type = from->u.u.type;
99435c4bbdfSmrg    to->u.u.detail = from->u.u.detail;
99535c4bbdfSmrg    cpswaps(from->u.videoNotify.sequenceNumber,
99635c4bbdfSmrg            to->u.videoNotify.sequenceNumber);
99735c4bbdfSmrg    cpswapl(from->u.videoNotify.time, to->u.videoNotify.time);
99835c4bbdfSmrg    cpswapl(from->u.videoNotify.drawable, to->u.videoNotify.drawable);
99935c4bbdfSmrg    cpswapl(from->u.videoNotify.port, to->u.videoNotify.port);
100005b261ecSmrg
100105b261ecSmrg}
100205b261ecSmrg
10031b5d61b8Smrgstatic void _X_COLD
100435c4bbdfSmrgWriteSwappedPortNotifyEvent(xvEvent * from, xvEvent * to)
100535c4bbdfSmrg{
100605b261ecSmrg
100735c4bbdfSmrg    to->u.u.type = from->u.u.type;
100835c4bbdfSmrg    to->u.u.detail = from->u.u.detail;
100935c4bbdfSmrg    cpswaps(from->u.portNotify.sequenceNumber, to->u.portNotify.sequenceNumber);
101035c4bbdfSmrg    cpswapl(from->u.portNotify.time, to->u.portNotify.time);
101135c4bbdfSmrg    cpswapl(from->u.portNotify.port, to->u.portNotify.port);
101235c4bbdfSmrg    cpswapl(from->u.portNotify.value, to->u.portNotify.value);
101305b261ecSmrg
101405b261ecSmrg}
101505b261ecSmrg
101635c4bbdfSmrgvoid
101735c4bbdfSmrgXvFreeAdaptor(XvAdaptorPtr pAdaptor)
101805b261ecSmrg{
101935c4bbdfSmrg    int i;
102005b261ecSmrg
102135c4bbdfSmrg    free(pAdaptor->name);
102235c4bbdfSmrg    pAdaptor->name = NULL;
102305b261ecSmrg
102435c4bbdfSmrg    if (pAdaptor->pEncodings) {
102535c4bbdfSmrg        XvEncodingPtr pEncode = pAdaptor->pEncodings;
102605b261ecSmrg
102735c4bbdfSmrg        for (i = 0; i < pAdaptor->nEncodings; i++, pEncode++)
102835c4bbdfSmrg            free(pEncode->name);
102935c4bbdfSmrg        free(pAdaptor->pEncodings);
103035c4bbdfSmrg        pAdaptor->pEncodings = NULL;
103135c4bbdfSmrg    }
103205b261ecSmrg
103335c4bbdfSmrg    free(pAdaptor->pFormats);
103435c4bbdfSmrg    pAdaptor->pFormats = NULL;
103535c4bbdfSmrg
103635c4bbdfSmrg    free(pAdaptor->pPorts);
103735c4bbdfSmrg    pAdaptor->pPorts = NULL;
103835c4bbdfSmrg
103935c4bbdfSmrg    if (pAdaptor->pAttributes) {
104035c4bbdfSmrg        XvAttributePtr pAttribute = pAdaptor->pAttributes;
104105b261ecSmrg
104235c4bbdfSmrg        for (i = 0; i < pAdaptor->nAttributes; i++, pAttribute++)
104335c4bbdfSmrg            free(pAttribute->name);
104435c4bbdfSmrg        free(pAdaptor->pAttributes);
104535c4bbdfSmrg        pAdaptor->pAttributes = NULL;
104635c4bbdfSmrg    }
104735c4bbdfSmrg
104835c4bbdfSmrg    free(pAdaptor->pImages);
104935c4bbdfSmrg    pAdaptor->pImages = NULL;
105035c4bbdfSmrg
105135c4bbdfSmrg    free(pAdaptor->devPriv.ptr);
105235c4bbdfSmrg    pAdaptor->devPriv.ptr = NULL;
105335c4bbdfSmrg}
105405b261ecSmrg
105535c4bbdfSmrgvoid
105635c4bbdfSmrgXvFillColorKey(DrawablePtr pDraw, CARD32 key, RegionPtr region)
105735c4bbdfSmrg{
105835c4bbdfSmrg    ScreenPtr pScreen = pDraw->pScreen;
105935c4bbdfSmrg    ChangeGCVal pval[2];
106035c4bbdfSmrg    BoxPtr pbox = RegionRects(region);
106135c4bbdfSmrg    int i, nbox = RegionNumRects(region);
106235c4bbdfSmrg    xRectangle *rects;
106335c4bbdfSmrg    GCPtr gc;
106435c4bbdfSmrg
106535c4bbdfSmrg    gc = GetScratchGC(pDraw->depth, pScreen);
106635c4bbdfSmrg    if (!gc)
106735c4bbdfSmrg        return;
106835c4bbdfSmrg
106935c4bbdfSmrg    pval[0].val = key;
107035c4bbdfSmrg    pval[1].val = IncludeInferiors;
107135c4bbdfSmrg    (void) ChangeGC(NullClient, gc, GCForeground | GCSubwindowMode, pval);
107235c4bbdfSmrg    ValidateGC(pDraw, gc);
107335c4bbdfSmrg
107435c4bbdfSmrg    rects = xallocarray(nbox, sizeof(xRectangle));
107535c4bbdfSmrg    if (rects) {
107635c4bbdfSmrg        for (i = 0; i < nbox; i++, pbox++) {
107735c4bbdfSmrg            rects[i].x = pbox->x1 - pDraw->x;
107835c4bbdfSmrg            rects[i].y = pbox->y1 - pDraw->y;
107935c4bbdfSmrg            rects[i].width = pbox->x2 - pbox->x1;
108035c4bbdfSmrg            rects[i].height = pbox->y2 - pbox->y1;
108135c4bbdfSmrg        }
108235c4bbdfSmrg
108335c4bbdfSmrg        (*gc->ops->PolyFillRect) (pDraw, gc, nbox, rects);
108435c4bbdfSmrg
108535c4bbdfSmrg        free(rects);
108635c4bbdfSmrg    }
108735c4bbdfSmrg    FreeScratchGC(gc);
108805b261ecSmrg}
1089