1066 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1066 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
/***********************************************************
 | 
						|
Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
 | 
						|
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
 | 
						|
 | 
						|
                        All Rights Reserved
 | 
						|
 | 
						|
Permission to use, copy, modify, and distribute this software and its
 | 
						|
documentation for any purpose and without fee is hereby granted,
 | 
						|
provided that the above copyright notice appear in all copies and that
 | 
						|
both that copyright notice and this permission notice appear in
 | 
						|
supporting documentation, and that the names of Digital or MIT not be
 | 
						|
used in advertising or publicity pertaining to distribution of the
 | 
						|
software without specific, written prior permission.
 | 
						|
 | 
						|
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 | 
						|
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 | 
						|
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 | 
						|
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 | 
						|
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 | 
						|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 | 
						|
SOFTWARE.
 | 
						|
 | 
						|
******************************************************************/
 | 
						|
 | 
						|
/*
 | 
						|
** File:
 | 
						|
**
 | 
						|
**   xvmain.c --- Xv server extension main device independent module.
 | 
						|
**
 | 
						|
** Author:
 | 
						|
**
 | 
						|
**   David Carver (Digital Workstation Engineering/Project Athena)
 | 
						|
**
 | 
						|
** Revisions:
 | 
						|
**
 | 
						|
**   04.09.91 Carver
 | 
						|
**     - change: stop video always generates an event even when video
 | 
						|
**       wasn't active
 | 
						|
**
 | 
						|
**   29.08.91 Carver
 | 
						|
**     - change: unrealizing windows no longer preempts video
 | 
						|
**
 | 
						|
**   11.06.91 Carver
 | 
						|
**     - changed SetPortControl to SetPortAttribute
 | 
						|
**     - changed GetPortControl to GetPortAttribute
 | 
						|
**     - changed QueryBestSize
 | 
						|
**
 | 
						|
**   28.05.91 Carver
 | 
						|
**     - fixed Put and Get requests to not preempt operations to same drawable
 | 
						|
**
 | 
						|
**   15.05.91 Carver
 | 
						|
**     - version 2.0 upgrade
 | 
						|
**
 | 
						|
**   19.03.91 Carver
 | 
						|
**     - fixed Put and Get requests to honor grabbed ports.
 | 
						|
**     - fixed Video requests to update di structure with new drawable, and
 | 
						|
**       client after calling ddx.
 | 
						|
**
 | 
						|
**   24.01.91 Carver
 | 
						|
**     - version 1.4 upgrade
 | 
						|
**
 | 
						|
** Notes:
 | 
						|
**
 | 
						|
**   Port structures reference client structures in a two different
 | 
						|
**   ways: when grabs, or video is active.  Each reference is encoded
 | 
						|
**   as fake client resources and thus when the client is goes away so
 | 
						|
**   does the reference (it is zeroed).  No other action is taken, so
 | 
						|
**   video doesn't necessarily stop.  It probably will as a result of
 | 
						|
**   other resources going away, but if a client starts video using
 | 
						|
**   none of its own resources, then the video will continue to play
 | 
						|
**   after the client disappears.
 | 
						|
**
 | 
						|
**
 | 
						|
*/
 | 
						|
 | 
						|
#include <dix-config.h>
 | 
						|
 | 
						|
#include <string.h>
 | 
						|
#include <X11/X.h>
 | 
						|
#include <X11/Xproto.h>
 | 
						|
#include <X11/extensions/Xv.h>
 | 
						|
#include <X11/extensions/Xvproto.h>
 | 
						|
 | 
						|
#include "dix/screen_hooks_priv.h"
 | 
						|
#include "miext/extinit_priv.h"
 | 
						|
#include "Xext/panoramiX.h"
 | 
						|
#include "Xext/panoramiXsrv.h"
 | 
						|
#include "Xext/xvdix_priv.h"
 | 
						|
 | 
						|
#include "misc.h"
 | 
						|
#include "os.h"
 | 
						|
#include "scrnintstr.h"
 | 
						|
#include "windowstr.h"
 | 
						|
#include "pixmapstr.h"
 | 
						|
#include "gcstruct.h"
 | 
						|
#include "extnsionst.h"
 | 
						|
#include "dixstruct.h"
 | 
						|
#include "resource.h"
 | 
						|
#include "opaque.h"
 | 
						|
#include "input.h"
 | 
						|
#include "xvdisp.h"
 | 
						|
 | 
						|
#define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = ((XvScreenPtr) \
 | 
						|
    dixLookupPrivate(&(pScreen)->devPrivates, XvScreenKey))->field)
 | 
						|
 | 
						|
#define SCREEN_EPILOGUE(pScreen, field, wrapper)\
 | 
						|
    ((pScreen)->field = wrapper)
 | 
						|
 | 
						|
typedef struct _XvVideoNotifyRec {
 | 
						|
    struct _XvVideoNotifyRec *next;
 | 
						|
    ClientPtr client;
 | 
						|
    unsigned long id;
 | 
						|
    unsigned long mask;
 | 
						|
} XvVideoNotifyRec, *XvVideoNotifyPtr;
 | 
						|
 | 
						|
static DevPrivateKeyRec XvScreenKeyRec;
 | 
						|
 | 
						|
Bool noXvExtension = FALSE;
 | 
						|
 | 
						|
#define XvScreenKey (&XvScreenKeyRec)
 | 
						|
static unsigned long XvExtensionGeneration = 0;
 | 
						|
static unsigned long XvScreenGeneration = 0;
 | 
						|
static unsigned long XvResourceGeneration = 0;
 | 
						|
 | 
						|
int XvReqCode;
 | 
						|
static int XvEventBase;
 | 
						|
int XvErrorBase;
 | 
						|
 | 
						|
int xvUseXinerama = 0;
 | 
						|
 | 
						|
RESTYPE XvRTPort;
 | 
						|
static RESTYPE XvRTEncoding;
 | 
						|
static RESTYPE XvRTGrab;
 | 
						|
static RESTYPE XvRTVideoNotify;
 | 
						|
static RESTYPE XvRTVideoNotifyList;
 | 
						|
static RESTYPE XvRTPortNotify;
 | 
						|
 | 
						|
/* EXTERNAL */
 | 
						|
 | 
						|
static void WriteSwappedVideoNotifyEvent(xvEvent *, xvEvent *);
 | 
						|
static void WriteSwappedPortNotifyEvent(xvEvent *, xvEvent *);
 | 
						|
static Bool CreateResourceTypes(void);
 | 
						|
 | 
						|
static void XvScreenClose(CallbackListPtr *pcbl, ScreenPtr, void *arg);
 | 
						|
static void XvResetProc(ExtensionEntry *);
 | 
						|
static int XvdiDestroyGrab(void *, XID);
 | 
						|
static int XvdiDestroyEncoding(void *, XID);
 | 
						|
static int XvdiDestroyVideoNotify(void *, XID);
 | 
						|
static int XvdiDestroyPortNotify(void *, XID);
 | 
						|
static int XvdiDestroyVideoNotifyList(void *, XID);
 | 
						|
static int XvdiDestroyPort(void *, XID);
 | 
						|
static int XvdiSendVideoNotify(XvPortPtr, DrawablePtr, int);
 | 
						|
static void XvStopAdaptors(DrawablePtr pDrawable);
 | 
						|
 | 
						|
/*
 | 
						|
** XvExtensionInit
 | 
						|
**
 | 
						|
**
 | 
						|
*/
 | 
						|
 | 
						|
void
 | 
						|
XvExtensionInit(void)
 | 
						|
{
 | 
						|
    ExtensionEntry *extEntry;
 | 
						|
 | 
						|
    if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0))
 | 
						|
        return;
 | 
						|
 | 
						|
    /* Look to see if any screens were initialized; if not then
 | 
						|
       init global variables so the extension can function */
 | 
						|
    if (XvScreenGeneration != serverGeneration) {
 | 
						|
        if (!CreateResourceTypes()) {
 | 
						|
            ErrorF("XvExtensionInit: Unable to allocate resource types\n");
 | 
						|
            return;
 | 
						|
        }
 | 
						|
#ifdef XINERAMA
 | 
						|
        XineramaRegisterConnectionBlockCallback(XineramifyXv);
 | 
						|
#endif /* XINERAMA */
 | 
						|
        XvScreenGeneration = serverGeneration;
 | 
						|
    }
 | 
						|
 | 
						|
    if (XvExtensionGeneration != serverGeneration) {
 | 
						|
        XvExtensionGeneration = serverGeneration;
 | 
						|
 | 
						|
        extEntry = AddExtension(XvName, XvNumEvents, XvNumErrors,
 | 
						|
                                ProcXvDispatch, SProcXvDispatch,
 | 
						|
                                XvResetProc, StandardMinorOpcode);
 | 
						|
        if (!extEntry) {
 | 
						|
            FatalError("XvExtensionInit: AddExtensions failed\n");
 | 
						|
        }
 | 
						|
 | 
						|
        XvReqCode = extEntry->base;
 | 
						|
        XvEventBase = extEntry->eventBase;
 | 
						|
        XvErrorBase = extEntry->errorBase;
 | 
						|
 | 
						|
        EventSwapVector[XvEventBase + XvVideoNotify] =
 | 
						|
            (EventSwapPtr) WriteSwappedVideoNotifyEvent;
 | 
						|
        EventSwapVector[XvEventBase + XvPortNotify] =
 | 
						|
            (EventSwapPtr) WriteSwappedPortNotifyEvent;
 | 
						|
 | 
						|
        SetResourceTypeErrorValue(XvRTPort, _XvBadPort);
 | 
						|
        (void) MakeAtom(XvName, strlen(XvName), xTrue);
 | 
						|
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
CreateResourceTypes(void)
 | 
						|
{
 | 
						|
 | 
						|
    if (XvResourceGeneration == serverGeneration)
 | 
						|
        return TRUE;
 | 
						|
 | 
						|
    XvResourceGeneration = serverGeneration;
 | 
						|
 | 
						|
    if (!(XvRTPort = CreateNewResourceType(XvdiDestroyPort, "XvRTPort"))) {
 | 
						|
        ErrorF("CreateResourceTypes: failed to allocate port resource.\n");
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!(XvRTGrab = CreateNewResourceType(XvdiDestroyGrab, "XvRTGrab"))) {
 | 
						|
        ErrorF("CreateResourceTypes: failed to allocate grab resource.\n");
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!(XvRTEncoding = CreateNewResourceType(XvdiDestroyEncoding,
 | 
						|
                                               "XvRTEncoding"))) {
 | 
						|
        ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n");
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!(XvRTVideoNotify = CreateNewResourceType(XvdiDestroyVideoNotify,
 | 
						|
                                                  "XvRTVideoNotify"))) {
 | 
						|
        ErrorF
 | 
						|
            ("CreateResourceTypes: failed to allocate video notify resource.\n");
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!
 | 
						|
        (XvRTVideoNotifyList =
 | 
						|
         CreateNewResourceType(XvdiDestroyVideoNotifyList,
 | 
						|
                               "XvRTVideoNotifyList"))) {
 | 
						|
        ErrorF
 | 
						|
            ("CreateResourceTypes: failed to allocate video notify list resource.\n");
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!(XvRTPortNotify = CreateNewResourceType(XvdiDestroyPortNotify,
 | 
						|
                                                 "XvRTPortNotify"))) {
 | 
						|
        ErrorF
 | 
						|
            ("CreateResourceTypes: failed to allocate port notify resource.\n");
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
static void XvWindowDestroy(CallbackListPtr *pcbl, ScreenPtr pScreen, WindowPtr pWin)
 | 
						|
{
 | 
						|
    XvStopAdaptors(&pWin->drawable);
 | 
						|
}
 | 
						|
 | 
						|
static void XvPixmapDestroy(CallbackListPtr *pcbl, ScreenPtr pScreen, PixmapPtr pPixmap)
 | 
						|
{
 | 
						|
    XvStopAdaptors(&pPixmap->drawable);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
XvScreenInit(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    if (XvScreenGeneration != serverGeneration) {
 | 
						|
        if (!CreateResourceTypes()) {
 | 
						|
            ErrorF("XvScreenInit: Unable to allocate resource types\n");
 | 
						|
            return BadAlloc;
 | 
						|
        }
 | 
						|
#ifdef XINERAMA
 | 
						|
        XineramaRegisterConnectionBlockCallback(XineramifyXv);
 | 
						|
#endif /* XINERAMA */
 | 
						|
        XvScreenGeneration = serverGeneration;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0))
 | 
						|
        return BadAlloc;
 | 
						|
 | 
						|
    if (dixLookupPrivate(&pScreen->devPrivates, XvScreenKey)) {
 | 
						|
        ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n");
 | 
						|
    }
 | 
						|
 | 
						|
    /* ALLOCATE SCREEN PRIVATE RECORD */
 | 
						|
 | 
						|
    XvScreenPtr pxvs = calloc(1, sizeof(XvScreenRec));
 | 
						|
    if (!pxvs) {
 | 
						|
        ErrorF("XvScreenInit: Unable to allocate screen private structure\n");
 | 
						|
        return BadAlloc;
 | 
						|
    }
 | 
						|
 | 
						|
    dixSetPrivate(&pScreen->devPrivates, XvScreenKey, pxvs);
 | 
						|
 | 
						|
    dixScreenHookWindowDestroy(pScreen, XvWindowDestroy);
 | 
						|
    dixScreenHookClose(pScreen, XvScreenClose);
 | 
						|
    dixScreenHookPixmapDestroy(pScreen, XvPixmapDestroy);
 | 
						|
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
static void XvScreenClose(CallbackListPtr *pcbl, ScreenPtr pScreen, void *unused)
 | 
						|
{
 | 
						|
    XvScreenPtr pxvs;
 | 
						|
 | 
						|
    pxvs = (XvScreenPtr) dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
 | 
						|
 | 
						|
    dixScreenUnhookWindowDestroy(pScreen, XvWindowDestroy);
 | 
						|
    dixScreenUnhookClose(pScreen, XvScreenClose);
 | 
						|
    dixScreenUnhookPixmapDestroy(pScreen, XvPixmapDestroy);
 | 
						|
 | 
						|
    free(pxvs);
 | 
						|
 | 
						|
    dixSetPrivate(&pScreen->devPrivates, XvScreenKey, NULL);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
XvResetProc(ExtensionEntry * extEntry)
 | 
						|
{
 | 
						|
    xvUseXinerama = 0;
 | 
						|
}
 | 
						|
 | 
						|
DevPrivateKey
 | 
						|
XvGetScreenKey(void)
 | 
						|
{
 | 
						|
    return XvScreenKey;
 | 
						|
}
 | 
						|
 | 
						|
unsigned long
 | 
						|
XvGetRTPort(void)
 | 
						|
{
 | 
						|
    return XvRTPort;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
XvStopAdaptors(DrawablePtr pDrawable)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pDrawable->pScreen;
 | 
						|
    XvScreenPtr pxvs = dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
 | 
						|
    XvAdaptorPtr pa = pxvs->pAdaptors;
 | 
						|
    int na = pxvs->nAdaptors;
 | 
						|
 | 
						|
    /* CHECK TO SEE IF THIS PORT IS IN USE */
 | 
						|
    while (na--) {
 | 
						|
        XvPortPtr pp = pa->pPorts;
 | 
						|
        int np = pa->nPorts;
 | 
						|
 | 
						|
        while ((np--) && (pp)) {
 | 
						|
            if (pp->pDraw == pDrawable) {
 | 
						|
                XvdiSendVideoNotify(pp, pDrawable, XvPreempted);
 | 
						|
 | 
						|
                (void) (*pp->pAdaptor->ddStopVideo) (pp, pDrawable);
 | 
						|
 | 
						|
                pp->pDraw = NULL;
 | 
						|
                pp->client = NULL;
 | 
						|
                pp->time = currentTime;
 | 
						|
            }
 | 
						|
            pp++;
 | 
						|
        }
 | 
						|
        pa++;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
XvdiDestroyPort(void *pPort, XID id)
 | 
						|
{
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
XvdiDestroyGrab(void *pGrab, XID id)
 | 
						|
{
 | 
						|
    ((XvGrabPtr) pGrab)->client = NULL;
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
XvdiDestroyVideoNotify(void *pn, XID id)
 | 
						|
{
 | 
						|
    /* JUST CLEAR OUT THE client POINTER FIELD */
 | 
						|
 | 
						|
    ((XvVideoNotifyPtr) pn)->client = NULL;
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
XvdiDestroyPortNotify(void *pn, XID id)
 | 
						|
{
 | 
						|
    /* JUST CLEAR OUT THE client POINTER FIELD */
 | 
						|
 | 
						|
    ((XvPortNotifyPtr) pn)->client = NULL;
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
XvdiDestroyVideoNotifyList(void *pn, XID id)
 | 
						|
{
 | 
						|
    XvVideoNotifyPtr npn, cpn;
 | 
						|
 | 
						|
    /* ACTUALLY DESTROY THE NOTIFY LIST */
 | 
						|
 | 
						|
    cpn = (XvVideoNotifyPtr) pn;
 | 
						|
 | 
						|
    while (cpn) {
 | 
						|
        npn = cpn->next;
 | 
						|
        if (cpn->client)
 | 
						|
            FreeResource(cpn->id, XvRTVideoNotify);
 | 
						|
        free(cpn);
 | 
						|
        cpn = npn;
 | 
						|
    }
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
XvdiDestroyEncoding(void *value, XID id)
 | 
						|
{
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
XvdiSendVideoNotify(XvPortPtr pPort, DrawablePtr pDraw, int reason)
 | 
						|
{
 | 
						|
    XvVideoNotifyPtr pn;
 | 
						|
 | 
						|
    dixLookupResourceByType((void **) &pn, pDraw->id, XvRTVideoNotifyList,
 | 
						|
                            serverClient, DixReadAccess);
 | 
						|
 | 
						|
    while (pn) {
 | 
						|
        xvEvent event = {
 | 
						|
            .u.videoNotify.reason = reason,
 | 
						|
            .u.videoNotify.time = currentTime.milliseconds,
 | 
						|
            .u.videoNotify.drawable = pDraw->id,
 | 
						|
            .u.videoNotify.port = pPort->id
 | 
						|
        };
 | 
						|
        event.u.u.type = XvEventBase + XvVideoNotify;
 | 
						|
        WriteEventsToClient(pn->client, 1, (xEventPtr) &event);
 | 
						|
        pn = pn->next;
 | 
						|
    }
 | 
						|
 | 
						|
    return Success;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
XvdiSendPortNotify(XvPortPtr pPort, Atom attribute, INT32 value)
 | 
						|
{
 | 
						|
    XvPortNotifyPtr pn;
 | 
						|
 | 
						|
    pn = pPort->pNotify;
 | 
						|
 | 
						|
    while (pn) {
 | 
						|
        xvEvent event = {
 | 
						|
            .u.portNotify.time = currentTime.milliseconds,
 | 
						|
            .u.portNotify.port = pPort->id,
 | 
						|
            .u.portNotify.attribute = attribute,
 | 
						|
            .u.portNotify.value = value
 | 
						|
        };
 | 
						|
        event.u.u.type = XvEventBase + XvPortNotify;
 | 
						|
        WriteEventsToClient(pn->client, 1, (xEventPtr) &event);
 | 
						|
        pn = pn->next;
 | 
						|
    }
 | 
						|
 | 
						|
    return Success;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
#define CHECK_SIZE(dw, dh, sw, sh) {                                  \
 | 
						|
  if(!dw || !dh || !sw || !sh)  return Success;                       \
 | 
						|
  /* The region code will break these if they are too large */        \
 | 
						|
  if((dw > 32767) || (dh > 32767) || (sw > 32767) || (sh > 32767))    \
 | 
						|
        return BadValue;                                              \
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
XvdiPutVideo(ClientPtr client,
 | 
						|
             DrawablePtr pDraw,
 | 
						|
             XvPortPtr pPort,
 | 
						|
             GCPtr pGC,
 | 
						|
             INT16 vid_x, INT16 vid_y,
 | 
						|
             CARD16 vid_w, CARD16 vid_h,
 | 
						|
             INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
 | 
						|
{
 | 
						|
    DrawablePtr pOldDraw;
 | 
						|
 | 
						|
    CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
 | 
						|
 | 
						|
    /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
 | 
						|
 | 
						|
    UpdateCurrentTime();
 | 
						|
 | 
						|
    /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
 | 
						|
       INFORM CLIENT OF ITS FAILURE */
 | 
						|
 | 
						|
    if (pPort->grab.client && (pPort->grab.client != client)) {
 | 
						|
        XvdiSendVideoNotify(pPort, pDraw, XvBusy);
 | 
						|
        return Success;
 | 
						|
    }
 | 
						|
 | 
						|
    /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
 | 
						|
       EVENTS TO ANY CLIENTS WHO WANT THEM */
 | 
						|
 | 
						|
    pOldDraw = pPort->pDraw;
 | 
						|
    if ((pOldDraw) && (pOldDraw != pDraw)) {
 | 
						|
        XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
 | 
						|
    }
 | 
						|
 | 
						|
    (void) (*pPort->pAdaptor->ddPutVideo) (pDraw, pPort, pGC,
 | 
						|
                                           vid_x, vid_y, vid_w, vid_h,
 | 
						|
                                           drw_x, drw_y, drw_w, drw_h);
 | 
						|
 | 
						|
    if ((pPort->pDraw) && (pOldDraw != pDraw)) {
 | 
						|
        pPort->client = client;
 | 
						|
        XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
 | 
						|
    }
 | 
						|
 | 
						|
    pPort->time = currentTime;
 | 
						|
 | 
						|
    return Success;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
XvdiPutStill(ClientPtr client,
 | 
						|
             DrawablePtr pDraw,
 | 
						|
             XvPortPtr pPort,
 | 
						|
             GCPtr pGC,
 | 
						|
             INT16 vid_x, INT16 vid_y,
 | 
						|
             CARD16 vid_w, CARD16 vid_h,
 | 
						|
             INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
 | 
						|
{
 | 
						|
    int status;
 | 
						|
 | 
						|
    CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
 | 
						|
 | 
						|
    /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
 | 
						|
 | 
						|
    UpdateCurrentTime();
 | 
						|
 | 
						|
    /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
 | 
						|
       INFORM CLIENT OF ITS FAILURE */
 | 
						|
 | 
						|
    if (pPort->grab.client && (pPort->grab.client != client)) {
 | 
						|
        XvdiSendVideoNotify(pPort, pDraw, XvBusy);
 | 
						|
        return Success;
 | 
						|
    }
 | 
						|
 | 
						|
    pPort->time = currentTime;
 | 
						|
 | 
						|
    status = (*pPort->pAdaptor->ddPutStill) (pDraw, pPort, pGC,
 | 
						|
                                             vid_x, vid_y, vid_w, vid_h,
 | 
						|
                                             drw_x, drw_y, drw_w, drw_h);
 | 
						|
 | 
						|
    return status;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
XvdiPutImage(ClientPtr client,
 | 
						|
             DrawablePtr pDraw,
 | 
						|
             XvPortPtr pPort,
 | 
						|
             GCPtr pGC,
 | 
						|
             INT16 src_x, INT16 src_y,
 | 
						|
             CARD16 src_w, CARD16 src_h,
 | 
						|
             INT16 drw_x, INT16 drw_y,
 | 
						|
             CARD16 drw_w, CARD16 drw_h,
 | 
						|
             XvImagePtr image,
 | 
						|
             unsigned char *data, Bool sync, CARD16 width, CARD16 height)
 | 
						|
{
 | 
						|
    CHECK_SIZE(drw_w, drw_h, src_w, src_h);
 | 
						|
 | 
						|
    /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
 | 
						|
 | 
						|
    UpdateCurrentTime();
 | 
						|
 | 
						|
    /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
 | 
						|
       INFORM CLIENT OF ITS FAILURE */
 | 
						|
 | 
						|
    if (pPort->grab.client && (pPort->grab.client != client)) {
 | 
						|
        XvdiSendVideoNotify(pPort, pDraw, XvBusy);
 | 
						|
        return Success;
 | 
						|
    }
 | 
						|
 | 
						|
    pPort->time = currentTime;
 | 
						|
 | 
						|
    return (*pPort->pAdaptor->ddPutImage) (pDraw, pPort, pGC,
 | 
						|
                                           src_x, src_y, src_w, src_h,
 | 
						|
                                           drw_x, drw_y, drw_w, drw_h,
 | 
						|
                                           image, data, sync, width, height);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
XvdiGetVideo(ClientPtr client,
 | 
						|
             DrawablePtr pDraw,
 | 
						|
             XvPortPtr pPort,
 | 
						|
             GCPtr pGC,
 | 
						|
             INT16 vid_x, INT16 vid_y,
 | 
						|
             CARD16 vid_w, CARD16 vid_h,
 | 
						|
             INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
 | 
						|
{
 | 
						|
    DrawablePtr pOldDraw;
 | 
						|
 | 
						|
    CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
 | 
						|
 | 
						|
    /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
 | 
						|
 | 
						|
    UpdateCurrentTime();
 | 
						|
 | 
						|
    /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
 | 
						|
       INFORM CLIENT OF ITS FAILURE */
 | 
						|
 | 
						|
    if (pPort->grab.client && (pPort->grab.client != client)) {
 | 
						|
        XvdiSendVideoNotify(pPort, pDraw, XvBusy);
 | 
						|
        return Success;
 | 
						|
    }
 | 
						|
 | 
						|
    /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
 | 
						|
       EVENTS TO ANY CLIENTS WHO WANT THEM */
 | 
						|
 | 
						|
    pOldDraw = pPort->pDraw;
 | 
						|
    if ((pOldDraw) && (pOldDraw != pDraw)) {
 | 
						|
        XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
 | 
						|
    }
 | 
						|
 | 
						|
    (void) (*pPort->pAdaptor->ddGetVideo) (pDraw, pPort, pGC,
 | 
						|
                                           vid_x, vid_y, vid_w, vid_h,
 | 
						|
                                           drw_x, drw_y, drw_w, drw_h);
 | 
						|
 | 
						|
    if ((pPort->pDraw) && (pOldDraw != pDraw)) {
 | 
						|
        pPort->client = client;
 | 
						|
        XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
 | 
						|
    }
 | 
						|
 | 
						|
    pPort->time = currentTime;
 | 
						|
 | 
						|
    return Success;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
XvdiGetStill(ClientPtr client,
 | 
						|
             DrawablePtr pDraw,
 | 
						|
             XvPortPtr pPort,
 | 
						|
             GCPtr pGC,
 | 
						|
             INT16 vid_x, INT16 vid_y,
 | 
						|
             CARD16 vid_w, CARD16 vid_h,
 | 
						|
             INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
 | 
						|
{
 | 
						|
    int status;
 | 
						|
 | 
						|
    CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
 | 
						|
 | 
						|
    /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
 | 
						|
 | 
						|
    UpdateCurrentTime();
 | 
						|
 | 
						|
    /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
 | 
						|
       INFORM CLIENT OF ITS FAILURE */
 | 
						|
 | 
						|
    if (pPort->grab.client && (pPort->grab.client != client)) {
 | 
						|
        XvdiSendVideoNotify(pPort, pDraw, XvBusy);
 | 
						|
        return Success;
 | 
						|
    }
 | 
						|
 | 
						|
    status = (*pPort->pAdaptor->ddGetStill) (pDraw, pPort, pGC,
 | 
						|
                                             vid_x, vid_y, vid_w, vid_h,
 | 
						|
                                             drw_x, drw_y, drw_w, drw_h);
 | 
						|
 | 
						|
    pPort->time = currentTime;
 | 
						|
 | 
						|
    return status;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
XvdiGrabPort(ClientPtr client, XvPortPtr pPort, Time ctime, int *p_result)
 | 
						|
{
 | 
						|
    unsigned long id;
 | 
						|
    TimeStamp time;
 | 
						|
 | 
						|
    UpdateCurrentTime();
 | 
						|
    time = ClientTimeToServerTime(ctime);
 | 
						|
 | 
						|
    if (pPort->grab.client && (client != pPort->grab.client)) {
 | 
						|
        *p_result = XvAlreadyGrabbed;
 | 
						|
        return Success;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((CompareTimeStamps(time, currentTime) == LATER) ||
 | 
						|
        (CompareTimeStamps(time, pPort->time) == EARLIER)) {
 | 
						|
        *p_result = XvInvalidTime;
 | 
						|
        return Success;
 | 
						|
    }
 | 
						|
 | 
						|
    if (client == pPort->grab.client) {
 | 
						|
        *p_result = Success;
 | 
						|
        return Success;
 | 
						|
    }
 | 
						|
 | 
						|
    id = FakeClientID(client->index);
 | 
						|
 | 
						|
    if (!AddResource(id, XvRTGrab, &pPort->grab)) {
 | 
						|
        return BadAlloc;
 | 
						|
    }
 | 
						|
 | 
						|
    /* IF THERE IS ACTIVE VIDEO THEN STOP IT */
 | 
						|
 | 
						|
    if ((pPort->pDraw) && (client != pPort->client)) {
 | 
						|
        XvdiStopVideo(NULL, pPort, pPort->pDraw);
 | 
						|
    }
 | 
						|
 | 
						|
    pPort->grab.client = client;
 | 
						|
    pPort->grab.id = id;
 | 
						|
 | 
						|
    pPort->time = currentTime;
 | 
						|
 | 
						|
    *p_result = Success;
 | 
						|
 | 
						|
    return Success;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
XvdiUngrabPort(ClientPtr client, XvPortPtr pPort, Time ctime)
 | 
						|
{
 | 
						|
    TimeStamp time;
 | 
						|
 | 
						|
    UpdateCurrentTime();
 | 
						|
    time = ClientTimeToServerTime(ctime);
 | 
						|
 | 
						|
    if ((!pPort->grab.client) || (client != pPort->grab.client)) {
 | 
						|
        return Success;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((CompareTimeStamps(time, currentTime) == LATER) ||
 | 
						|
        (CompareTimeStamps(time, pPort->time) == EARLIER)) {
 | 
						|
        return Success;
 | 
						|
    }
 | 
						|
 | 
						|
    /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */
 | 
						|
 | 
						|
    FreeResource(pPort->grab.id, XvRTGrab);
 | 
						|
    pPort->grab.client = NULL;
 | 
						|
 | 
						|
    pPort->time = currentTime;
 | 
						|
 | 
						|
    return Success;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
XvdiSelectVideoNotify(ClientPtr client, DrawablePtr pDraw, BOOL onoff)
 | 
						|
{
 | 
						|
    XvVideoNotifyPtr pn, tpn, fpn;
 | 
						|
    int rc;
 | 
						|
 | 
						|
    /* FIND VideoNotify LIST */
 | 
						|
 | 
						|
    rc = dixLookupResourceByType((void **) &pn, pDraw->id,
 | 
						|
                                 XvRTVideoNotifyList, client, DixWriteAccess);
 | 
						|
    if (rc != Success && rc != BadValue)
 | 
						|
        return rc;
 | 
						|
 | 
						|
    /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */
 | 
						|
 | 
						|
    if (!onoff && !pn)
 | 
						|
        return Success;
 | 
						|
 | 
						|
    /* IF ONE DOESN'T EXIST CREATE IT AND ADD A RESOURCE SO THAT THE LIST
 | 
						|
       WILL BE DELETED WHEN THE DRAWABLE IS DESTROYED */
 | 
						|
 | 
						|
    if (!pn) {
 | 
						|
        if (!(tpn = calloc(1, sizeof(XvVideoNotifyRec))))
 | 
						|
            return BadAlloc;
 | 
						|
        tpn->next = NULL;
 | 
						|
        tpn->client = NULL;
 | 
						|
        if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn))
 | 
						|
            return BadAlloc;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        /* LOOK TO SEE IF ENTRY ALREADY EXISTS */
 | 
						|
 | 
						|
        fpn = NULL;
 | 
						|
        tpn = pn;
 | 
						|
        while (tpn) {
 | 
						|
            if (tpn->client == client) {
 | 
						|
                if (!onoff) {
 | 
						|
                    tpn->client = NULL;
 | 
						|
                    FreeResource(tpn->id, XvRTVideoNotify);
 | 
						|
                }
 | 
						|
                return Success;
 | 
						|
            }
 | 
						|
            if (!tpn->client)
 | 
						|
                fpn = tpn;      /* TAKE NOTE OF FREE ENTRY */
 | 
						|
            tpn = tpn->next;
 | 
						|
        }
 | 
						|
 | 
						|
        /* IF TURNING OFF, THEN JUST RETURN */
 | 
						|
 | 
						|
        if (!onoff)
 | 
						|
            return Success;
 | 
						|
 | 
						|
        /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */
 | 
						|
 | 
						|
        if (fpn) {
 | 
						|
            tpn = fpn;
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            if (!(tpn = calloc(1, sizeof(XvVideoNotifyRec))))
 | 
						|
                return BadAlloc;
 | 
						|
            tpn->next = pn->next;
 | 
						|
            pn->next = tpn;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */
 | 
						|
    /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */
 | 
						|
 | 
						|
    tpn->client = NULL;
 | 
						|
    tpn->id = FakeClientID(client->index);
 | 
						|
    if (!AddResource(tpn->id, XvRTVideoNotify, tpn))
 | 
						|
        return BadAlloc;
 | 
						|
 | 
						|
    tpn->client = client;
 | 
						|
    return Success;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
XvdiSelectPortNotify(ClientPtr client, XvPortPtr pPort, BOOL onoff)
 | 
						|
{
 | 
						|
    XvPortNotifyPtr pn, tpn;
 | 
						|
 | 
						|
    /* SEE IF CLIENT IS ALREADY IN LIST */
 | 
						|
 | 
						|
    tpn = NULL;
 | 
						|
    pn = pPort->pNotify;
 | 
						|
    while (pn) {
 | 
						|
        if (!pn->client)
 | 
						|
            tpn = pn;           /* TAKE NOTE OF FREE ENTRY */
 | 
						|
        if (pn->client == client)
 | 
						|
            break;
 | 
						|
        pn = pn->next;
 | 
						|
    }
 | 
						|
 | 
						|
    /* IS THE CLIENT ALREADY ON THE LIST? */
 | 
						|
 | 
						|
    if (pn) {
 | 
						|
        /* REMOVE IT? */
 | 
						|
 | 
						|
        if (!onoff) {
 | 
						|
            pn->client = NULL;
 | 
						|
            FreeResource(pn->id, XvRTPortNotify);
 | 
						|
        }
 | 
						|
 | 
						|
        return Success;
 | 
						|
    }
 | 
						|
 | 
						|
    /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE
 | 
						|
       CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */
 | 
						|
 | 
						|
    if (!tpn) {
 | 
						|
        if (!(tpn = calloc(1, sizeof(XvPortNotifyRec))))
 | 
						|
            return BadAlloc;
 | 
						|
        tpn->next = pPort->pNotify;
 | 
						|
        pPort->pNotify = tpn;
 | 
						|
    }
 | 
						|
 | 
						|
    tpn->client = client;
 | 
						|
    tpn->id = FakeClientID(client->index);
 | 
						|
    if (!AddResource(tpn->id, XvRTPortNotify, tpn))
 | 
						|
        return BadAlloc;
 | 
						|
 | 
						|
    return Success;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
XvdiStopVideo(ClientPtr client, XvPortPtr pPort, DrawablePtr pDraw)
 | 
						|
{
 | 
						|
    int status;
 | 
						|
 | 
						|
    /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
 | 
						|
 | 
						|
    if (!pPort->pDraw || (pPort->pDraw != pDraw)) {
 | 
						|
        XvdiSendVideoNotify(pPort, pDraw, XvStopped);
 | 
						|
        return Success;
 | 
						|
    }
 | 
						|
 | 
						|
    /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
 | 
						|
       INFORM CLIENT OF ITS FAILURE */
 | 
						|
 | 
						|
    if ((client) && (pPort->grab.client) && (pPort->grab.client != client)) {
 | 
						|
        XvdiSendVideoNotify(pPort, pDraw, XvBusy);
 | 
						|
        return Success;
 | 
						|
    }
 | 
						|
 | 
						|
    XvdiSendVideoNotify(pPort, pDraw, XvStopped);
 | 
						|
 | 
						|
    status = (*pPort->pAdaptor->ddStopVideo) (pPort, pDraw);
 | 
						|
 | 
						|
    pPort->pDraw = NULL;
 | 
						|
    pPort->client = (ClientPtr) client;
 | 
						|
    pPort->time = currentTime;
 | 
						|
 | 
						|
    return status;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
XvdiMatchPort(XvPortPtr pPort, DrawablePtr pDraw)
 | 
						|
{
 | 
						|
 | 
						|
    XvAdaptorPtr pa;
 | 
						|
    XvFormatPtr pf;
 | 
						|
    int nf;
 | 
						|
 | 
						|
    pa = pPort->pAdaptor;
 | 
						|
 | 
						|
    if (pa->pScreen != pDraw->pScreen)
 | 
						|
        return BadMatch;
 | 
						|
 | 
						|
    nf = pa->nFormats;
 | 
						|
    pf = pa->pFormats;
 | 
						|
 | 
						|
    while (nf--) {
 | 
						|
        if (pf->depth == pDraw->depth)
 | 
						|
            return Success;
 | 
						|
        pf++;
 | 
						|
    }
 | 
						|
 | 
						|
    return BadMatch;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
XvdiSetPortAttribute(ClientPtr client,
 | 
						|
                     XvPortPtr pPort, Atom attribute, INT32 value)
 | 
						|
{
 | 
						|
    int status;
 | 
						|
 | 
						|
    status =
 | 
						|
        (*pPort->pAdaptor->ddSetPortAttribute) (pPort, attribute,
 | 
						|
                                                value);
 | 
						|
    if (status == Success)
 | 
						|
        XvdiSendPortNotify(pPort, attribute, value);
 | 
						|
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
XvdiGetPortAttribute(ClientPtr client,
 | 
						|
                     XvPortPtr pPort, Atom attribute, INT32 *p_value)
 | 
						|
{
 | 
						|
 | 
						|
    return
 | 
						|
        (*pPort->pAdaptor->ddGetPortAttribute) (pPort, attribute,
 | 
						|
                                                p_value);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
static void _X_COLD
 | 
						|
WriteSwappedVideoNotifyEvent(xvEvent * from, xvEvent * to)
 | 
						|
{
 | 
						|
 | 
						|
    to->u.u.type = from->u.u.type;
 | 
						|
    to->u.u.detail = from->u.u.detail;
 | 
						|
    cpswaps(from->u.videoNotify.sequenceNumber,
 | 
						|
            to->u.videoNotify.sequenceNumber);
 | 
						|
    cpswapl(from->u.videoNotify.time, to->u.videoNotify.time);
 | 
						|
    cpswapl(from->u.videoNotify.drawable, to->u.videoNotify.drawable);
 | 
						|
    cpswapl(from->u.videoNotify.port, to->u.videoNotify.port);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
static void _X_COLD
 | 
						|
WriteSwappedPortNotifyEvent(xvEvent * from, xvEvent * to)
 | 
						|
{
 | 
						|
 | 
						|
    to->u.u.type = from->u.u.type;
 | 
						|
    to->u.u.detail = from->u.u.detail;
 | 
						|
    cpswaps(from->u.portNotify.sequenceNumber, to->u.portNotify.sequenceNumber);
 | 
						|
    cpswapl(from->u.portNotify.time, to->u.portNotify.time);
 | 
						|
    cpswapl(from->u.portNotify.port, to->u.portNotify.port);
 | 
						|
    cpswapl(from->u.portNotify.value, to->u.portNotify.value);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
XvFreeAdaptor(XvAdaptorPtr pAdaptor)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    free(pAdaptor->name);
 | 
						|
    pAdaptor->name = NULL;
 | 
						|
 | 
						|
    if (pAdaptor->pEncodings) {
 | 
						|
        XvEncodingPtr pEncode = pAdaptor->pEncodings;
 | 
						|
 | 
						|
        for (i = 0; i < pAdaptor->nEncodings; i++, pEncode++)
 | 
						|
            free(pEncode->name);
 | 
						|
        free(pAdaptor->pEncodings);
 | 
						|
        pAdaptor->pEncodings = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    free(pAdaptor->pFormats);
 | 
						|
    pAdaptor->pFormats = NULL;
 | 
						|
 | 
						|
    free(pAdaptor->pPorts);
 | 
						|
    pAdaptor->pPorts = NULL;
 | 
						|
 | 
						|
    if (pAdaptor->pAttributes) {
 | 
						|
        XvAttributePtr pAttribute = pAdaptor->pAttributes;
 | 
						|
 | 
						|
        for (i = 0; i < pAdaptor->nAttributes; i++, pAttribute++)
 | 
						|
            free(pAttribute->name);
 | 
						|
        free(pAdaptor->pAttributes);
 | 
						|
        pAdaptor->pAttributes = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    free(pAdaptor->pImages);
 | 
						|
    pAdaptor->pImages = NULL;
 | 
						|
 | 
						|
    free(pAdaptor->devPriv.ptr);
 | 
						|
    pAdaptor->devPriv.ptr = NULL;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
XvFillColorKey(DrawablePtr pDraw, CARD32 key, RegionPtr region)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pDraw->pScreen;
 | 
						|
    ChangeGCVal pval[2];
 | 
						|
    BoxPtr pbox = RegionRects(region);
 | 
						|
    int i, nbox = RegionNumRects(region);
 | 
						|
    xRectangle *rects;
 | 
						|
    GCPtr gc;
 | 
						|
 | 
						|
    gc = GetScratchGC(pDraw->depth, pScreen);
 | 
						|
    if (!gc)
 | 
						|
        return;
 | 
						|
 | 
						|
    pval[0].val = key;
 | 
						|
    pval[1].val = IncludeInferiors;
 | 
						|
    (void) ChangeGC(NullClient, gc, GCForeground | GCSubwindowMode, pval);
 | 
						|
    ValidateGC(pDraw, gc);
 | 
						|
 | 
						|
    rects = calloc(nbox, sizeof(xRectangle));
 | 
						|
    if (rects) {
 | 
						|
        for (i = 0; i < nbox; i++, pbox++) {
 | 
						|
            rects[i].x = pbox->x1 - pDraw->x;
 | 
						|
            rects[i].y = pbox->y1 - pDraw->y;
 | 
						|
            rects[i].width = pbox->x2 - pbox->x1;
 | 
						|
            rects[i].height = pbox->y2 - pbox->y1;
 | 
						|
        }
 | 
						|
 | 
						|
        (*gc->ops->PolyFillRect) (pDraw, gc, nbox, rects);
 | 
						|
 | 
						|
        free(rects);
 | 
						|
    }
 | 
						|
    FreeScratchGC(gc);
 | 
						|
}
 |