xvmain.c revision 35c4bbdf
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
42835c4bbdfSmrg    /* ACTUALLY DESTROY THE NOTITY 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) {
81435c4bbdfSmrg                if (!onoff)
81535c4bbdfSmrg                    tpn->client = NULL;
81635c4bbdfSmrg                return Success;
81735c4bbdfSmrg            }
81835c4bbdfSmrg            if (!tpn->client)
81935c4bbdfSmrg                fpn = tpn;      /* TAKE NOTE OF FREE ENTRY */
82035c4bbdfSmrg            tpn = tpn->next;
82135c4bbdfSmrg        }
82235c4bbdfSmrg
82335c4bbdfSmrg        /* IF TUNNING OFF, THEN JUST RETURN */
82435c4bbdfSmrg
82535c4bbdfSmrg        if (!onoff)
82635c4bbdfSmrg            return Success;
82735c4bbdfSmrg
82835c4bbdfSmrg        /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */
82935c4bbdfSmrg
83035c4bbdfSmrg        if (fpn) {
83135c4bbdfSmrg            tpn = fpn;
83235c4bbdfSmrg        }
83335c4bbdfSmrg        else {
83435c4bbdfSmrg            if (!(tpn = malloc(sizeof(XvVideoNotifyRec))))
83535c4bbdfSmrg                return BadAlloc;
83635c4bbdfSmrg            tpn->next = pn->next;
83735c4bbdfSmrg            pn->next = tpn;
83835c4bbdfSmrg        }
83905b261ecSmrg    }
84005b261ecSmrg
84135c4bbdfSmrg    /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */
84235c4bbdfSmrg    /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */
84305b261ecSmrg
84435c4bbdfSmrg    tpn->client = NULL;
84535c4bbdfSmrg    tpn->id = FakeClientID(client->index);
84635c4bbdfSmrg    if (!AddResource(tpn->id, XvRTVideoNotify, tpn))
84735c4bbdfSmrg        return BadAlloc;
84805b261ecSmrg
84935c4bbdfSmrg    tpn->client = client;
85035c4bbdfSmrg    return Success;
85105b261ecSmrg
85205b261ecSmrg}
85305b261ecSmrg
85405b261ecSmrgint
85535c4bbdfSmrgXvdiSelectPortNotify(ClientPtr client, XvPortPtr pPort, BOOL onoff)
85635c4bbdfSmrg{
85735c4bbdfSmrg    XvPortNotifyPtr pn, tpn;
85835c4bbdfSmrg
85935c4bbdfSmrg    /* SEE IF CLIENT IS ALREADY IN LIST */
86035c4bbdfSmrg
86135c4bbdfSmrg    tpn = NULL;
86235c4bbdfSmrg    pn = pPort->pNotify;
86335c4bbdfSmrg    while (pn) {
86435c4bbdfSmrg        if (!pn->client)
86535c4bbdfSmrg            tpn = pn;           /* TAKE NOTE OF FREE ENTRY */
86635c4bbdfSmrg        if (pn->client == client)
86735c4bbdfSmrg            break;
86835c4bbdfSmrg        pn = pn->next;
86905b261ecSmrg    }
87005b261ecSmrg
87135c4bbdfSmrg    /* IS THE CLIENT ALREADY ON THE LIST? */
87205b261ecSmrg
87335c4bbdfSmrg    if (pn) {
87435c4bbdfSmrg        /* REMOVE IT? */
87505b261ecSmrg
87635c4bbdfSmrg        if (!onoff) {
87735c4bbdfSmrg            pn->client = NULL;
87835c4bbdfSmrg            FreeResource(pn->id, XvRTPortNotify);
87935c4bbdfSmrg        }
88005b261ecSmrg
88135c4bbdfSmrg        return Success;
88205b261ecSmrg    }
88305b261ecSmrg
88435c4bbdfSmrg    /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE
88535c4bbdfSmrg       CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */
88605b261ecSmrg
88735c4bbdfSmrg    if (!tpn) {
88835c4bbdfSmrg        if (!(tpn = malloc(sizeof(XvPortNotifyRec))))
88935c4bbdfSmrg            return BadAlloc;
89035c4bbdfSmrg        tpn->next = pPort->pNotify;
89135c4bbdfSmrg        pPort->pNotify = tpn;
89205b261ecSmrg    }
89305b261ecSmrg
89435c4bbdfSmrg    tpn->client = client;
89535c4bbdfSmrg    tpn->id = FakeClientID(client->index);
89635c4bbdfSmrg    if (!AddResource(tpn->id, XvRTPortNotify, tpn))
89735c4bbdfSmrg        return BadAlloc;
89805b261ecSmrg
89935c4bbdfSmrg    return Success;
90005b261ecSmrg
90105b261ecSmrg}
90205b261ecSmrg
90305b261ecSmrgint
90435c4bbdfSmrgXvdiStopVideo(ClientPtr client, XvPortPtr pPort, DrawablePtr pDraw)
90535c4bbdfSmrg{
90635c4bbdfSmrg    int status;
90735c4bbdfSmrg
90835c4bbdfSmrg    /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
90935c4bbdfSmrg
91035c4bbdfSmrg    if (!pPort->pDraw || (pPort->pDraw != pDraw)) {
91135c4bbdfSmrg        XvdiSendVideoNotify(pPort, pDraw, XvStopped);
91235c4bbdfSmrg        return Success;
91305b261ecSmrg    }
91405b261ecSmrg
91535c4bbdfSmrg    /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
91635c4bbdfSmrg       INFORM CLIENT OF ITS FAILURE */
91705b261ecSmrg
91835c4bbdfSmrg    if ((client) && (pPort->grab.client) && (pPort->grab.client != client)) {
91935c4bbdfSmrg        XvdiSendVideoNotify(pPort, pDraw, XvBusy);
92035c4bbdfSmrg        return Success;
92105b261ecSmrg    }
92205b261ecSmrg
92335c4bbdfSmrg    XvdiSendVideoNotify(pPort, pDraw, XvStopped);
92405b261ecSmrg
92535c4bbdfSmrg    status = (*pPort->pAdaptor->ddStopVideo) (pPort, pDraw);
92605b261ecSmrg
92735c4bbdfSmrg    pPort->pDraw = NULL;
92835c4bbdfSmrg    pPort->client = (ClientPtr) client;
92935c4bbdfSmrg    pPort->time = currentTime;
93005b261ecSmrg
93135c4bbdfSmrg    return status;
93205b261ecSmrg
93305b261ecSmrg}
93405b261ecSmrg
93505b261ecSmrgint
93635c4bbdfSmrgXvdiMatchPort(XvPortPtr pPort, DrawablePtr pDraw)
93735c4bbdfSmrg{
93805b261ecSmrg
93935c4bbdfSmrg    XvAdaptorPtr pa;
94035c4bbdfSmrg    XvFormatPtr pf;
94135c4bbdfSmrg    int nf;
94205b261ecSmrg
94335c4bbdfSmrg    pa = pPort->pAdaptor;
94405b261ecSmrg
94535c4bbdfSmrg    if (pa->pScreen != pDraw->pScreen)
94635c4bbdfSmrg        return BadMatch;
94705b261ecSmrg
94835c4bbdfSmrg    nf = pa->nFormats;
94935c4bbdfSmrg    pf = pa->pFormats;
95005b261ecSmrg
95135c4bbdfSmrg    while (nf--) {
95235c4bbdfSmrg        if (pf->depth == pDraw->depth)
95335c4bbdfSmrg            return Success;
95435c4bbdfSmrg        pf++;
95535c4bbdfSmrg    }
95605b261ecSmrg
95735c4bbdfSmrg    return BadMatch;
95805b261ecSmrg
95905b261ecSmrg}
96005b261ecSmrg
96105b261ecSmrgint
96235c4bbdfSmrgXvdiSetPortAttribute(ClientPtr client,
96335c4bbdfSmrg                     XvPortPtr pPort, Atom attribute, INT32 value)
96435c4bbdfSmrg{
96535c4bbdfSmrg    int status;
96605b261ecSmrg
96735c4bbdfSmrg    status =
96835c4bbdfSmrg        (*pPort->pAdaptor->ddSetPortAttribute) (pPort, attribute,
96935c4bbdfSmrg                                                value);
97035c4bbdfSmrg    if (status == Success)
97135c4bbdfSmrg        XvdiSendPortNotify(pPort, attribute, value);
97205b261ecSmrg
97335c4bbdfSmrg    return status;
97435c4bbdfSmrg}
97505b261ecSmrg
97635c4bbdfSmrgint
97735c4bbdfSmrgXvdiGetPortAttribute(ClientPtr client,
97835c4bbdfSmrg                     XvPortPtr pPort, Atom attribute, INT32 *p_value)
97935c4bbdfSmrg{
98005b261ecSmrg
98135c4bbdfSmrg    return
98235c4bbdfSmrg        (*pPort->pAdaptor->ddGetPortAttribute) (pPort, attribute,
98335c4bbdfSmrg                                                p_value);
98405b261ecSmrg
98535c4bbdfSmrg}
98605b261ecSmrg
98735c4bbdfSmrgstatic void
98835c4bbdfSmrgWriteSwappedVideoNotifyEvent(xvEvent * from, xvEvent * to)
98935c4bbdfSmrg{
99005b261ecSmrg
99135c4bbdfSmrg    to->u.u.type = from->u.u.type;
99235c4bbdfSmrg    to->u.u.detail = from->u.u.detail;
99335c4bbdfSmrg    cpswaps(from->u.videoNotify.sequenceNumber,
99435c4bbdfSmrg            to->u.videoNotify.sequenceNumber);
99535c4bbdfSmrg    cpswapl(from->u.videoNotify.time, to->u.videoNotify.time);
99635c4bbdfSmrg    cpswapl(from->u.videoNotify.drawable, to->u.videoNotify.drawable);
99735c4bbdfSmrg    cpswapl(from->u.videoNotify.port, to->u.videoNotify.port);
99805b261ecSmrg
99905b261ecSmrg}
100005b261ecSmrg
100135c4bbdfSmrgstatic void
100235c4bbdfSmrgWriteSwappedPortNotifyEvent(xvEvent * from, xvEvent * to)
100335c4bbdfSmrg{
100405b261ecSmrg
100535c4bbdfSmrg    to->u.u.type = from->u.u.type;
100635c4bbdfSmrg    to->u.u.detail = from->u.u.detail;
100735c4bbdfSmrg    cpswaps(from->u.portNotify.sequenceNumber, to->u.portNotify.sequenceNumber);
100835c4bbdfSmrg    cpswapl(from->u.portNotify.time, to->u.portNotify.time);
100935c4bbdfSmrg    cpswapl(from->u.portNotify.port, to->u.portNotify.port);
101035c4bbdfSmrg    cpswapl(from->u.portNotify.value, to->u.portNotify.value);
101105b261ecSmrg
101205b261ecSmrg}
101305b261ecSmrg
101435c4bbdfSmrgvoid
101535c4bbdfSmrgXvFreeAdaptor(XvAdaptorPtr pAdaptor)
101605b261ecSmrg{
101735c4bbdfSmrg    int i;
101805b261ecSmrg
101935c4bbdfSmrg    free(pAdaptor->name);
102035c4bbdfSmrg    pAdaptor->name = NULL;
102105b261ecSmrg
102235c4bbdfSmrg    if (pAdaptor->pEncodings) {
102335c4bbdfSmrg        XvEncodingPtr pEncode = pAdaptor->pEncodings;
102405b261ecSmrg
102535c4bbdfSmrg        for (i = 0; i < pAdaptor->nEncodings; i++, pEncode++)
102635c4bbdfSmrg            free(pEncode->name);
102735c4bbdfSmrg        free(pAdaptor->pEncodings);
102835c4bbdfSmrg        pAdaptor->pEncodings = NULL;
102935c4bbdfSmrg    }
103005b261ecSmrg
103135c4bbdfSmrg    free(pAdaptor->pFormats);
103235c4bbdfSmrg    pAdaptor->pFormats = NULL;
103335c4bbdfSmrg
103435c4bbdfSmrg    free(pAdaptor->pPorts);
103535c4bbdfSmrg    pAdaptor->pPorts = NULL;
103635c4bbdfSmrg
103735c4bbdfSmrg    if (pAdaptor->pAttributes) {
103835c4bbdfSmrg        XvAttributePtr pAttribute = pAdaptor->pAttributes;
103905b261ecSmrg
104035c4bbdfSmrg        for (i = 0; i < pAdaptor->nAttributes; i++, pAttribute++)
104135c4bbdfSmrg            free(pAttribute->name);
104235c4bbdfSmrg        free(pAdaptor->pAttributes);
104335c4bbdfSmrg        pAdaptor->pAttributes = NULL;
104435c4bbdfSmrg    }
104535c4bbdfSmrg
104635c4bbdfSmrg    free(pAdaptor->pImages);
104735c4bbdfSmrg    pAdaptor->pImages = NULL;
104835c4bbdfSmrg
104935c4bbdfSmrg    free(pAdaptor->devPriv.ptr);
105035c4bbdfSmrg    pAdaptor->devPriv.ptr = NULL;
105135c4bbdfSmrg}
105205b261ecSmrg
105335c4bbdfSmrgvoid
105435c4bbdfSmrgXvFillColorKey(DrawablePtr pDraw, CARD32 key, RegionPtr region)
105535c4bbdfSmrg{
105635c4bbdfSmrg    ScreenPtr pScreen = pDraw->pScreen;
105735c4bbdfSmrg    ChangeGCVal pval[2];
105835c4bbdfSmrg    BoxPtr pbox = RegionRects(region);
105935c4bbdfSmrg    int i, nbox = RegionNumRects(region);
106035c4bbdfSmrg    xRectangle *rects;
106135c4bbdfSmrg    GCPtr gc;
106235c4bbdfSmrg
106335c4bbdfSmrg    gc = GetScratchGC(pDraw->depth, pScreen);
106435c4bbdfSmrg    if (!gc)
106535c4bbdfSmrg        return;
106635c4bbdfSmrg
106735c4bbdfSmrg    pval[0].val = key;
106835c4bbdfSmrg    pval[1].val = IncludeInferiors;
106935c4bbdfSmrg    (void) ChangeGC(NullClient, gc, GCForeground | GCSubwindowMode, pval);
107035c4bbdfSmrg    ValidateGC(pDraw, gc);
107135c4bbdfSmrg
107235c4bbdfSmrg    rects = xallocarray(nbox, sizeof(xRectangle));
107335c4bbdfSmrg    if (rects) {
107435c4bbdfSmrg        for (i = 0; i < nbox; i++, pbox++) {
107535c4bbdfSmrg            rects[i].x = pbox->x1 - pDraw->x;
107635c4bbdfSmrg            rects[i].y = pbox->y1 - pDraw->y;
107735c4bbdfSmrg            rects[i].width = pbox->x2 - pbox->x1;
107835c4bbdfSmrg            rects[i].height = pbox->y2 - pbox->y1;
107935c4bbdfSmrg        }
108035c4bbdfSmrg
108135c4bbdfSmrg        (*gc->ops->PolyFillRect) (pDraw, gc, nbox, rects);
108235c4bbdfSmrg
108335c4bbdfSmrg        free(rects);
108435c4bbdfSmrg    }
108535c4bbdfSmrg    FreeScratchGC(gc);
108605b261ecSmrg}
1087