xvmain.c revision 4642e01f
105b261ecSmrg/***********************************************************
205b261ecSmrgCopyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
305b261ecSmrgand the Massachusetts Institute of Technology, Cambridge, Massachusetts.
405b261ecSmrg
505b261ecSmrg                        All Rights Reserved
605b261ecSmrg
705b261ecSmrgPermission to use, copy, modify, and distribute this software and its
805b261ecSmrgdocumentation for any purpose and without fee is hereby granted,
905b261ecSmrgprovided that the above copyright notice appear in all copies and that
1005b261ecSmrgboth 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
1305b261ecSmrgsoftware 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/*
2605b261ecSmrg** File:
2705b261ecSmrg**
2805b261ecSmrg**   xvmain.c --- Xv server extension main device independent module.
2905b261ecSmrg**
3005b261ecSmrg** 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
6105b261ecSmrg**
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"
8905b261ecSmrg#include "gc.h"
9005b261ecSmrg#include "extnsionst.h"
9105b261ecSmrg#include "dixstruct.h"
9205b261ecSmrg#include "resource.h"
9305b261ecSmrg#include "opaque.h"
9405b261ecSmrg#include "input.h"
9505b261ecSmrg
9605b261ecSmrg#define GLOBAL
9705b261ecSmrg
9805b261ecSmrg#include <X11/extensions/Xv.h>
9905b261ecSmrg#include <X11/extensions/Xvproto.h>
10005b261ecSmrg#include "xvdix.h"
10105b261ecSmrg
10205b261ecSmrg#ifdef PANORAMIX
10305b261ecSmrg#include "panoramiX.h"
10405b261ecSmrg#include "panoramiXsrv.h"
10505b261ecSmrg#endif
1064642e01fSmrg#include "xvdisp.h"
10705b261ecSmrg
1084642e01fSmrgstatic int XvScreenKeyIndex;
1094642e01fSmrgstatic DevPrivateKey XvScreenKey = &XvScreenKeyIndex;
11005b261ecSmrgunsigned long XvExtensionGeneration = 0;
11105b261ecSmrgunsigned long XvScreenGeneration = 0;
11205b261ecSmrgunsigned long XvResourceGeneration = 0;
11305b261ecSmrg
11405b261ecSmrgint XvReqCode;
11505b261ecSmrgint XvEventBase;
11605b261ecSmrgint XvErrorBase;
11705b261ecSmrg
11805b261ecSmrgunsigned long XvRTPort;
11905b261ecSmrgunsigned long XvRTEncoding;
12005b261ecSmrgunsigned long XvRTGrab;
12105b261ecSmrgunsigned long XvRTVideoNotify;
12205b261ecSmrgunsigned long XvRTVideoNotifyList;
12305b261ecSmrgunsigned long XvRTPortNotify;
12405b261ecSmrg
12505b261ecSmrg
12605b261ecSmrg
12705b261ecSmrg/* EXTERNAL */
12805b261ecSmrg
12905b261ecSmrgextern XID clientErrorValue;
13005b261ecSmrg
13105b261ecSmrgstatic void WriteSwappedVideoNotifyEvent(xvEvent *, xvEvent *);
13205b261ecSmrgstatic void WriteSwappedPortNotifyEvent(xvEvent *, xvEvent *);
13305b261ecSmrgstatic Bool CreateResourceTypes(void);
13405b261ecSmrg
13505b261ecSmrgstatic Bool XvCloseScreen(int, ScreenPtr);
13605b261ecSmrgstatic Bool XvDestroyPixmap(PixmapPtr);
13705b261ecSmrgstatic Bool XvDestroyWindow(WindowPtr);
13805b261ecSmrgstatic void XvResetProc(ExtensionEntry*);
13905b261ecSmrgstatic int XvdiDestroyGrab(pointer, XID);
14005b261ecSmrgstatic int XvdiDestroyEncoding(pointer, XID);
14105b261ecSmrgstatic int XvdiDestroyVideoNotify(pointer, XID);
14205b261ecSmrgstatic int XvdiDestroyPortNotify(pointer, XID);
14305b261ecSmrgstatic int XvdiDestroyVideoNotifyList(pointer, XID);
14405b261ecSmrgstatic int XvdiDestroyPort(pointer, XID);
14505b261ecSmrgstatic int XvdiSendVideoNotify(XvPortPtr, DrawablePtr, int);
14605b261ecSmrg
14705b261ecSmrg
14805b261ecSmrg
14905b261ecSmrg
15005b261ecSmrg/*
15105b261ecSmrg** XvExtensionInit
15205b261ecSmrg**
15305b261ecSmrg**
15405b261ecSmrg*/
15505b261ecSmrg
15605b261ecSmrgvoid
15705b261ecSmrgXvExtensionInit(void)
15805b261ecSmrg{
15905b261ecSmrg  ExtensionEntry *extEntry;
16005b261ecSmrg
16105b261ecSmrg  /* LOOK TO SEE IF ANY SCREENS WERE INITIALIZED; IF NOT THEN
16205b261ecSmrg     INIT GLOBAL VARIABLES SO THE EXTENSION CAN FUNCTION */
16305b261ecSmrg  if (XvScreenGeneration != serverGeneration)
16405b261ecSmrg    {
16505b261ecSmrg      if (!CreateResourceTypes())
16605b261ecSmrg	{
16705b261ecSmrg	  ErrorF("XvExtensionInit: Unable to allocate resource types\n");
16805b261ecSmrg	  return;
16905b261ecSmrg	}
17005b261ecSmrg#ifdef PANORAMIX
17105b261ecSmrg        XineramaRegisterConnectionBlockCallback(XineramifyXv);
17205b261ecSmrg#endif
17305b261ecSmrg      XvScreenGeneration = serverGeneration;
17405b261ecSmrg    }
17505b261ecSmrg
17605b261ecSmrg  if (XvExtensionGeneration != serverGeneration)
17705b261ecSmrg    {
17805b261ecSmrg      XvExtensionGeneration = serverGeneration;
17905b261ecSmrg
18005b261ecSmrg      extEntry = AddExtension(XvName, XvNumEvents, XvNumErrors,
18105b261ecSmrg			      ProcXvDispatch, SProcXvDispatch,
18205b261ecSmrg			      XvResetProc, StandardMinorOpcode);
18305b261ecSmrg      if (!extEntry)
18405b261ecSmrg	{
18505b261ecSmrg	  FatalError("XvExtensionInit: AddExtensions failed\n");
18605b261ecSmrg	}
18705b261ecSmrg
18805b261ecSmrg      XvReqCode = extEntry->base;
18905b261ecSmrg      XvEventBase = extEntry->eventBase;
19005b261ecSmrg      XvErrorBase = extEntry->errorBase;
19105b261ecSmrg
19205b261ecSmrg      EventSwapVector[XvEventBase+XvVideoNotify] =
19305b261ecSmrg	(EventSwapPtr)WriteSwappedVideoNotifyEvent;
19405b261ecSmrg      EventSwapVector[XvEventBase+XvPortNotify] =
19505b261ecSmrg	(EventSwapPtr)WriteSwappedPortNotifyEvent;
19605b261ecSmrg
19705b261ecSmrg      (void)MakeAtom(XvName, strlen(XvName), xTrue);
19805b261ecSmrg
19905b261ecSmrg    }
20005b261ecSmrg}
20105b261ecSmrg
20205b261ecSmrgstatic Bool
20305b261ecSmrgCreateResourceTypes(void)
20405b261ecSmrg
20505b261ecSmrg{
20605b261ecSmrg
20705b261ecSmrg  if (XvResourceGeneration == serverGeneration) return TRUE;
20805b261ecSmrg
20905b261ecSmrg  XvResourceGeneration = serverGeneration;
21005b261ecSmrg
21105b261ecSmrg  if (!(XvRTPort = CreateNewResourceType(XvdiDestroyPort)))
21205b261ecSmrg    {
21305b261ecSmrg      ErrorF("CreateResourceTypes: failed to allocate port resource.\n");
21405b261ecSmrg      return FALSE;
21505b261ecSmrg    }
21605b261ecSmrg
21705b261ecSmrg  if (!(XvRTGrab = CreateNewResourceType(XvdiDestroyGrab)))
21805b261ecSmrg    {
21905b261ecSmrg      ErrorF("CreateResourceTypes: failed to allocate grab resource.\n");
22005b261ecSmrg      return FALSE;
22105b261ecSmrg    }
22205b261ecSmrg
22305b261ecSmrg  if (!(XvRTEncoding = CreateNewResourceType(XvdiDestroyEncoding)))
22405b261ecSmrg    {
22505b261ecSmrg      ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n");
22605b261ecSmrg      return FALSE;
22705b261ecSmrg    }
22805b261ecSmrg
22905b261ecSmrg  if (!(XvRTVideoNotify = CreateNewResourceType(XvdiDestroyVideoNotify)))
23005b261ecSmrg    {
23105b261ecSmrg      ErrorF("CreateResourceTypes: failed to allocate video notify resource.\n");
23205b261ecSmrg      return FALSE;
23305b261ecSmrg    }
23405b261ecSmrg
23505b261ecSmrg  if (!(XvRTVideoNotifyList = CreateNewResourceType(XvdiDestroyVideoNotifyList)))
23605b261ecSmrg    {
23705b261ecSmrg      ErrorF("CreateResourceTypes: failed to allocate video notify list resource.\n");
23805b261ecSmrg      return FALSE;
23905b261ecSmrg    }
24005b261ecSmrg
24105b261ecSmrg  if (!(XvRTPortNotify = CreateNewResourceType(XvdiDestroyPortNotify)))
24205b261ecSmrg    {
24305b261ecSmrg      ErrorF("CreateResourceTypes: failed to allocate port notify resource.\n");
24405b261ecSmrg      return FALSE;
24505b261ecSmrg    }
24605b261ecSmrg
24705b261ecSmrg  return TRUE;
24805b261ecSmrg
24905b261ecSmrg}
25005b261ecSmrg
25105b261ecSmrg_X_EXPORT int
25205b261ecSmrgXvScreenInit(ScreenPtr pScreen)
25305b261ecSmrg{
25405b261ecSmrg  XvScreenPtr pxvs;
25505b261ecSmrg
25605b261ecSmrg  if (XvScreenGeneration != serverGeneration)
25705b261ecSmrg    {
25805b261ecSmrg      if (!CreateResourceTypes())
25905b261ecSmrg	{
26005b261ecSmrg	  ErrorF("XvScreenInit: Unable to allocate resource types\n");
26105b261ecSmrg	  return BadAlloc;
26205b261ecSmrg	}
26305b261ecSmrg#ifdef PANORAMIX
26405b261ecSmrg        XineramaRegisterConnectionBlockCallback(XineramifyXv);
26505b261ecSmrg#endif
26605b261ecSmrg      XvScreenGeneration = serverGeneration;
26705b261ecSmrg    }
26805b261ecSmrg
2694642e01fSmrg  if (dixLookupPrivate(&pScreen->devPrivates, XvScreenKey))
27005b261ecSmrg    {
27105b261ecSmrg      ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n");
27205b261ecSmrg    }
27305b261ecSmrg
27405b261ecSmrg  /* ALLOCATE SCREEN PRIVATE RECORD */
27505b261ecSmrg
27605b261ecSmrg  pxvs = (XvScreenPtr) xalloc (sizeof (XvScreenRec));
27705b261ecSmrg  if (!pxvs)
27805b261ecSmrg    {
27905b261ecSmrg      ErrorF("XvScreenInit: Unable to allocate screen private structure\n");
28005b261ecSmrg      return BadAlloc;
28105b261ecSmrg    }
28205b261ecSmrg
2834642e01fSmrg  dixSetPrivate(&pScreen->devPrivates, XvScreenKey, pxvs);
28405b261ecSmrg
28505b261ecSmrg
28605b261ecSmrg  pxvs->DestroyPixmap = pScreen->DestroyPixmap;
28705b261ecSmrg  pxvs->DestroyWindow = pScreen->DestroyWindow;
28805b261ecSmrg  pxvs->CloseScreen = pScreen->CloseScreen;
28905b261ecSmrg
29005b261ecSmrg  pScreen->DestroyPixmap = XvDestroyPixmap;
29105b261ecSmrg  pScreen->DestroyWindow = XvDestroyWindow;
29205b261ecSmrg  pScreen->CloseScreen = XvCloseScreen;
29305b261ecSmrg
29405b261ecSmrg  return Success;
29505b261ecSmrg}
29605b261ecSmrg
29705b261ecSmrgstatic Bool
29805b261ecSmrgXvCloseScreen(
29905b261ecSmrg  int ii,
30005b261ecSmrg  ScreenPtr pScreen
30105b261ecSmrg){
30205b261ecSmrg
30305b261ecSmrg  XvScreenPtr pxvs;
30405b261ecSmrg
3054642e01fSmrg  pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
30605b261ecSmrg
30705b261ecSmrg  pScreen->DestroyPixmap = pxvs->DestroyPixmap;
30805b261ecSmrg  pScreen->DestroyWindow = pxvs->DestroyWindow;
30905b261ecSmrg  pScreen->CloseScreen = pxvs->CloseScreen;
31005b261ecSmrg
31105b261ecSmrg  (* pxvs->ddCloseScreen)(ii, pScreen);
31205b261ecSmrg
31305b261ecSmrg  xfree(pxvs);
31405b261ecSmrg
3154642e01fSmrg  dixSetPrivate(&pScreen->devPrivates, XvScreenKey, NULL);
31605b261ecSmrg
31705b261ecSmrg  return (*pScreen->CloseScreen)(ii, pScreen);
31805b261ecSmrg}
31905b261ecSmrg
32005b261ecSmrgstatic void
32105b261ecSmrgXvResetProc(ExtensionEntry* extEntry)
32205b261ecSmrg{
3234642e01fSmrg    XvResetProcVector();
32405b261ecSmrg}
32505b261ecSmrg
3264642e01fSmrg_X_EXPORT DevPrivateKey
3274642e01fSmrgXvGetScreenKey(void)
32805b261ecSmrg{
3294642e01fSmrg    return XvScreenKey;
33005b261ecSmrg}
33105b261ecSmrg
33205b261ecSmrg_X_EXPORT unsigned long
33305b261ecSmrgXvGetRTPort(void)
33405b261ecSmrg{
33505b261ecSmrg  return XvRTPort;
33605b261ecSmrg}
33705b261ecSmrg
33805b261ecSmrgstatic Bool
33905b261ecSmrgXvDestroyPixmap(PixmapPtr pPix)
34005b261ecSmrg{
34105b261ecSmrg  Bool status;
34205b261ecSmrg  ScreenPtr pScreen;
34305b261ecSmrg  XvScreenPtr pxvs;
34405b261ecSmrg  XvAdaptorPtr pa;
34505b261ecSmrg  int na;
34605b261ecSmrg  XvPortPtr pp;
34705b261ecSmrg  int np;
34805b261ecSmrg
34905b261ecSmrg  pScreen = pPix->drawable.pScreen;
35005b261ecSmrg
35105b261ecSmrg  SCREEN_PROLOGUE(pScreen, DestroyPixmap);
35205b261ecSmrg
3534642e01fSmrg  pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
35405b261ecSmrg
35505b261ecSmrg  /* CHECK TO SEE IF THIS PORT IS IN USE */
35605b261ecSmrg
35705b261ecSmrg  pa = pxvs->pAdaptors;
35805b261ecSmrg  na = pxvs->nAdaptors;
35905b261ecSmrg  while (na--)
36005b261ecSmrg    {
36105b261ecSmrg      np = pa->nPorts;
36205b261ecSmrg      pp = pa->pPorts;
36305b261ecSmrg
36405b261ecSmrg      while (np--)
36505b261ecSmrg	{
36605b261ecSmrg	  if (pp->pDraw == (DrawablePtr)pPix)
36705b261ecSmrg	    {
36805b261ecSmrg	      XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted);
36905b261ecSmrg
37005b261ecSmrg	      (void)(* pp->pAdaptor->ddStopVideo)((ClientPtr)NULL, pp,
37105b261ecSmrg						  pp->pDraw);
37205b261ecSmrg
37305b261ecSmrg	      pp->pDraw = (DrawablePtr)NULL;
37405b261ecSmrg	      pp->client = (ClientPtr)NULL;
37505b261ecSmrg	      pp->time = currentTime;
37605b261ecSmrg	    }
37705b261ecSmrg	  pp++;
37805b261ecSmrg	}
37905b261ecSmrg      pa++;
38005b261ecSmrg    }
38105b261ecSmrg
38205b261ecSmrg  status = (* pScreen->DestroyPixmap)(pPix);
38305b261ecSmrg
38405b261ecSmrg  SCREEN_EPILOGUE(pScreen, DestroyPixmap, XvDestroyPixmap);
38505b261ecSmrg
38605b261ecSmrg  return status;
38705b261ecSmrg
38805b261ecSmrg}
38905b261ecSmrg
39005b261ecSmrgstatic Bool
39105b261ecSmrgXvDestroyWindow(WindowPtr pWin)
39205b261ecSmrg{
39305b261ecSmrg  Bool status;
39405b261ecSmrg  ScreenPtr pScreen;
39505b261ecSmrg  XvScreenPtr pxvs;
39605b261ecSmrg  XvAdaptorPtr pa;
39705b261ecSmrg  int na;
39805b261ecSmrg  XvPortPtr pp;
39905b261ecSmrg  int np;
40005b261ecSmrg
40105b261ecSmrg  pScreen = pWin->drawable.pScreen;
40205b261ecSmrg
40305b261ecSmrg  SCREEN_PROLOGUE(pScreen, DestroyWindow);
40405b261ecSmrg
4054642e01fSmrg  pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
40605b261ecSmrg
40705b261ecSmrg  /* CHECK TO SEE IF THIS PORT IS IN USE */
40805b261ecSmrg
40905b261ecSmrg  pa = pxvs->pAdaptors;
41005b261ecSmrg  na = pxvs->nAdaptors;
41105b261ecSmrg  while (na--)
41205b261ecSmrg    {
41305b261ecSmrg      np = pa->nPorts;
41405b261ecSmrg      pp = pa->pPorts;
41505b261ecSmrg
41605b261ecSmrg      while (np--)
41705b261ecSmrg	{
41805b261ecSmrg	  if (pp->pDraw == (DrawablePtr)pWin)
41905b261ecSmrg	    {
42005b261ecSmrg	      XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted);
42105b261ecSmrg
42205b261ecSmrg	      (void)(* pp->pAdaptor->ddStopVideo)((ClientPtr)NULL, pp,
42305b261ecSmrg						  pp->pDraw);
42405b261ecSmrg
42505b261ecSmrg	      pp->pDraw = (DrawablePtr)NULL;
42605b261ecSmrg	      pp->client = (ClientPtr)NULL;
42705b261ecSmrg	      pp->time = currentTime;
42805b261ecSmrg	    }
42905b261ecSmrg	  pp++;
43005b261ecSmrg	}
43105b261ecSmrg      pa++;
43205b261ecSmrg    }
43305b261ecSmrg
43405b261ecSmrg
43505b261ecSmrg  status = (* pScreen->DestroyWindow)(pWin);
43605b261ecSmrg
43705b261ecSmrg  SCREEN_EPILOGUE(pScreen, DestroyWindow, XvDestroyWindow);
43805b261ecSmrg
43905b261ecSmrg  return status;
44005b261ecSmrg
44105b261ecSmrg}
44205b261ecSmrg
44305b261ecSmrg/* The XvdiVideoStopped procedure is a hook for the device dependent layer.
44405b261ecSmrg   It provides a way for the dd layer to inform the di layer that video has
44505b261ecSmrg   stopped in a port for reasons that the di layer had no control over; note
44605b261ecSmrg   that it doesn't call back into the dd layer */
44705b261ecSmrg
44805b261ecSmrgint
44905b261ecSmrgXvdiVideoStopped(XvPortPtr pPort, int reason)
45005b261ecSmrg{
45105b261ecSmrg
45205b261ecSmrg  /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
45305b261ecSmrg
45405b261ecSmrg  if (!pPort->pDraw) return Success;
45505b261ecSmrg
45605b261ecSmrg  XvdiSendVideoNotify(pPort, pPort->pDraw, reason);
45705b261ecSmrg
45805b261ecSmrg  pPort->pDraw = (DrawablePtr)NULL;
45905b261ecSmrg  pPort->client = (ClientPtr)NULL;
46005b261ecSmrg  pPort->time = currentTime;
46105b261ecSmrg
46205b261ecSmrg  return Success;
46305b261ecSmrg
46405b261ecSmrg}
46505b261ecSmrg
46605b261ecSmrgstatic int
46705b261ecSmrgXvdiDestroyPort(pointer pPort, XID id)
46805b261ecSmrg{
46905b261ecSmrg  return (* ((XvPortPtr)pPort)->pAdaptor->ddFreePort)(pPort);
47005b261ecSmrg}
47105b261ecSmrg
47205b261ecSmrgstatic int
47305b261ecSmrgXvdiDestroyGrab(pointer pGrab, XID id)
47405b261ecSmrg{
47505b261ecSmrg  ((XvGrabPtr)pGrab)->client = (ClientPtr)NULL;
47605b261ecSmrg  return Success;
47705b261ecSmrg}
47805b261ecSmrg
47905b261ecSmrgstatic int
48005b261ecSmrgXvdiDestroyVideoNotify(pointer pn, XID id)
48105b261ecSmrg{
48205b261ecSmrg  /* JUST CLEAR OUT THE client POINTER FIELD */
48305b261ecSmrg
48405b261ecSmrg  ((XvVideoNotifyPtr)pn)->client = (ClientPtr)NULL;
48505b261ecSmrg  return Success;
48605b261ecSmrg}
48705b261ecSmrg
48805b261ecSmrgstatic int
48905b261ecSmrgXvdiDestroyPortNotify(pointer pn, XID id)
49005b261ecSmrg{
49105b261ecSmrg  /* JUST CLEAR OUT THE client POINTER FIELD */
49205b261ecSmrg
49305b261ecSmrg  ((XvPortNotifyPtr)pn)->client = (ClientPtr)NULL;
49405b261ecSmrg  return Success;
49505b261ecSmrg}
49605b261ecSmrg
49705b261ecSmrgstatic int
49805b261ecSmrgXvdiDestroyVideoNotifyList(pointer pn, XID id)
49905b261ecSmrg{
50005b261ecSmrg  XvVideoNotifyPtr npn,cpn;
50105b261ecSmrg
50205b261ecSmrg  /* ACTUALLY DESTROY THE NOTITY LIST */
50305b261ecSmrg
50405b261ecSmrg  cpn = (XvVideoNotifyPtr)pn;
50505b261ecSmrg
50605b261ecSmrg  while (cpn)
50705b261ecSmrg    {
50805b261ecSmrg      npn = cpn->next;
50905b261ecSmrg      if (cpn->client) FreeResource(cpn->id, XvRTVideoNotify);
51005b261ecSmrg      xfree(cpn);
51105b261ecSmrg      cpn = npn;
51205b261ecSmrg    }
51305b261ecSmrg  return Success;
51405b261ecSmrg}
51505b261ecSmrg
51605b261ecSmrgstatic int
51705b261ecSmrgXvdiDestroyEncoding(pointer value, XID id)
51805b261ecSmrg{
51905b261ecSmrg  return Success;
52005b261ecSmrg}
52105b261ecSmrg
52205b261ecSmrgstatic int
52305b261ecSmrgXvdiSendVideoNotify(pPort, pDraw, reason)
52405b261ecSmrg
52505b261ecSmrgXvPortPtr pPort;
52605b261ecSmrgDrawablePtr pDraw;
52705b261ecSmrgint reason;
52805b261ecSmrg
52905b261ecSmrg{
53005b261ecSmrg  xvEvent event;
53105b261ecSmrg  XvVideoNotifyPtr pn;
53205b261ecSmrg
53305b261ecSmrg  pn = (XvVideoNotifyPtr)LookupIDByType(pDraw->id, XvRTVideoNotifyList);
53405b261ecSmrg
53505b261ecSmrg  while (pn)
53605b261ecSmrg    {
53705b261ecSmrg      if (pn->client)
53805b261ecSmrg	{
53905b261ecSmrg	  event.u.u.type = XvEventBase + XvVideoNotify;
54005b261ecSmrg	  event.u.u.sequenceNumber = pn->client->sequence;
54105b261ecSmrg	  event.u.videoNotify.time = currentTime.milliseconds;
54205b261ecSmrg	  event.u.videoNotify.drawable = pDraw->id;
54305b261ecSmrg	  event.u.videoNotify.port = pPort->id;
54405b261ecSmrg	  event.u.videoNotify.reason = reason;
5454642e01fSmrg	  TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1,
5464642e01fSmrg                          NoEventMask, NoEventMask, NullGrab);
54705b261ecSmrg	}
54805b261ecSmrg      pn = pn->next;
54905b261ecSmrg    }
55005b261ecSmrg
55105b261ecSmrg  return Success;
55205b261ecSmrg
55305b261ecSmrg}
55405b261ecSmrg
55505b261ecSmrg
55605b261ecSmrgint
55705b261ecSmrgXvdiSendPortNotify(
55805b261ecSmrg  XvPortPtr pPort,
55905b261ecSmrg  Atom attribute,
56005b261ecSmrg  INT32 value
56105b261ecSmrg){
56205b261ecSmrg  xvEvent event;
56305b261ecSmrg  XvPortNotifyPtr pn;
56405b261ecSmrg
56505b261ecSmrg  pn = pPort->pNotify;
56605b261ecSmrg
56705b261ecSmrg  while (pn)
56805b261ecSmrg    {
56905b261ecSmrg      if (pn->client)
57005b261ecSmrg	{
57105b261ecSmrg	  event.u.u.type = XvEventBase + XvPortNotify;
57205b261ecSmrg	  event.u.u.sequenceNumber = pn->client->sequence;
57305b261ecSmrg	  event.u.portNotify.time = currentTime.milliseconds;
57405b261ecSmrg	  event.u.portNotify.port = pPort->id;
57505b261ecSmrg	  event.u.portNotify.attribute = attribute;
57605b261ecSmrg	  event.u.portNotify.value = value;
5774642e01fSmrg	  TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1,
5784642e01fSmrg                          NoEventMask, NoEventMask, NullGrab);
57905b261ecSmrg	}
58005b261ecSmrg      pn = pn->next;
58105b261ecSmrg    }
58205b261ecSmrg
58305b261ecSmrg  return Success;
58405b261ecSmrg
58505b261ecSmrg}
58605b261ecSmrg
58705b261ecSmrg
58805b261ecSmrg#define CHECK_SIZE(dw, dh, sw, sh) {                                  \
58905b261ecSmrg  if(!dw || !dh || !sw || !sh)  return Success;                       \
59005b261ecSmrg  /* The region code will break these if they are too large */        \
59105b261ecSmrg  if((dw > 32767) || (dh > 32767) || (sw > 32767) || (sh > 32767))    \
59205b261ecSmrg        return BadValue;                                              \
59305b261ecSmrg}
59405b261ecSmrg
59505b261ecSmrg
59605b261ecSmrgint
59705b261ecSmrgXvdiPutVideo(
59805b261ecSmrg   ClientPtr client,
59905b261ecSmrg   DrawablePtr pDraw,
60005b261ecSmrg   XvPortPtr pPort,
60105b261ecSmrg   GCPtr pGC,
60205b261ecSmrg   INT16 vid_x, INT16 vid_y,
60305b261ecSmrg   CARD16 vid_w, CARD16 vid_h,
60405b261ecSmrg   INT16 drw_x, INT16 drw_y,
60505b261ecSmrg   CARD16 drw_w, CARD16 drw_h
60605b261ecSmrg){
60705b261ecSmrg  DrawablePtr pOldDraw;
60805b261ecSmrg
60905b261ecSmrg  CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
61005b261ecSmrg
61105b261ecSmrg  /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
61205b261ecSmrg
61305b261ecSmrg  UpdateCurrentTime();
61405b261ecSmrg
61505b261ecSmrg  /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
61605b261ecSmrg     INFORM CLIENT OF ITS FAILURE */
61705b261ecSmrg
61805b261ecSmrg  if (pPort->grab.client && (pPort->grab.client != client))
61905b261ecSmrg    {
62005b261ecSmrg      XvdiSendVideoNotify(pPort, pDraw, XvBusy);
62105b261ecSmrg      return Success;
62205b261ecSmrg    }
62305b261ecSmrg
62405b261ecSmrg  /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
62505b261ecSmrg     EVENTS TO ANY CLIENTS WHO WANT THEM */
62605b261ecSmrg
62705b261ecSmrg  pOldDraw = pPort->pDraw;
62805b261ecSmrg  if ((pOldDraw) && (pOldDraw != pDraw))
62905b261ecSmrg    {
63005b261ecSmrg      XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
63105b261ecSmrg    }
63205b261ecSmrg
63305b261ecSmrg  (void) (* pPort->pAdaptor->ddPutVideo)(client, pDraw, pPort, pGC,
63405b261ecSmrg					   vid_x, vid_y, vid_w, vid_h,
63505b261ecSmrg					   drw_x, drw_y, drw_w, drw_h);
63605b261ecSmrg
63705b261ecSmrg  if ((pPort->pDraw) && (pOldDraw != pDraw))
63805b261ecSmrg    {
63905b261ecSmrg      pPort->client = client;
64005b261ecSmrg      XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
64105b261ecSmrg    }
64205b261ecSmrg
64305b261ecSmrg  pPort->time = currentTime;
64405b261ecSmrg
64505b261ecSmrg  return (Success);
64605b261ecSmrg
64705b261ecSmrg}
64805b261ecSmrg
64905b261ecSmrgint
65005b261ecSmrgXvdiPutStill(
65105b261ecSmrg   ClientPtr client,
65205b261ecSmrg   DrawablePtr pDraw,
65305b261ecSmrg   XvPortPtr pPort,
65405b261ecSmrg   GCPtr pGC,
65505b261ecSmrg   INT16 vid_x, INT16 vid_y,
65605b261ecSmrg   CARD16 vid_w, CARD16 vid_h,
65705b261ecSmrg   INT16 drw_x, INT16 drw_y,
65805b261ecSmrg   CARD16 drw_w, CARD16 drw_h
65905b261ecSmrg){
66005b261ecSmrg  int status;
66105b261ecSmrg
66205b261ecSmrg  CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
66305b261ecSmrg
66405b261ecSmrg  /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
66505b261ecSmrg
66605b261ecSmrg  UpdateCurrentTime();
66705b261ecSmrg
66805b261ecSmrg  /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
66905b261ecSmrg     INFORM CLIENT OF ITS FAILURE */
67005b261ecSmrg
67105b261ecSmrg  if (pPort->grab.client && (pPort->grab.client != client))
67205b261ecSmrg    {
67305b261ecSmrg      XvdiSendVideoNotify(pPort, pDraw, XvBusy);
67405b261ecSmrg      return Success;
67505b261ecSmrg    }
67605b261ecSmrg
67705b261ecSmrg  pPort->time = currentTime;
67805b261ecSmrg
67905b261ecSmrg  status = (* pPort->pAdaptor->ddPutStill)(client, pDraw, pPort, pGC,
68005b261ecSmrg					   vid_x, vid_y, vid_w, vid_h,
68105b261ecSmrg					   drw_x, drw_y, drw_w, drw_h);
68205b261ecSmrg
68305b261ecSmrg  return status;
68405b261ecSmrg
68505b261ecSmrg}
68605b261ecSmrg
68705b261ecSmrgint
68805b261ecSmrgXvdiPutImage(
68905b261ecSmrg   ClientPtr client,
69005b261ecSmrg   DrawablePtr pDraw,
69105b261ecSmrg   XvPortPtr pPort,
69205b261ecSmrg   GCPtr pGC,
69305b261ecSmrg   INT16 src_x, INT16 src_y,
69405b261ecSmrg   CARD16 src_w, CARD16 src_h,
69505b261ecSmrg   INT16 drw_x, INT16 drw_y,
69605b261ecSmrg   CARD16 drw_w, CARD16 drw_h,
69705b261ecSmrg   XvImagePtr image,
69805b261ecSmrg   unsigned char* data,
69905b261ecSmrg   Bool sync,
70005b261ecSmrg   CARD16 width, CARD16 height
70105b261ecSmrg){
70205b261ecSmrg  CHECK_SIZE(drw_w, drw_h, src_w, src_h);
70305b261ecSmrg
70405b261ecSmrg  /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
70505b261ecSmrg
70605b261ecSmrg  UpdateCurrentTime();
70705b261ecSmrg
70805b261ecSmrg  /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
70905b261ecSmrg     INFORM CLIENT OF ITS FAILURE */
71005b261ecSmrg
71105b261ecSmrg  if (pPort->grab.client && (pPort->grab.client != client))
71205b261ecSmrg    {
71305b261ecSmrg      XvdiSendVideoNotify(pPort, pDraw, XvBusy);
71405b261ecSmrg      return Success;
71505b261ecSmrg    }
71605b261ecSmrg
71705b261ecSmrg  pPort->time = currentTime;
71805b261ecSmrg
71905b261ecSmrg  return (* pPort->pAdaptor->ddPutImage)(client, pDraw, pPort, pGC,
72005b261ecSmrg					   src_x, src_y, src_w, src_h,
72105b261ecSmrg					   drw_x, drw_y, drw_w, drw_h,
72205b261ecSmrg					   image, data, sync, width, height);
72305b261ecSmrg}
72405b261ecSmrg
72505b261ecSmrg
72605b261ecSmrgint
72705b261ecSmrgXvdiGetVideo(
72805b261ecSmrg   ClientPtr client,
72905b261ecSmrg   DrawablePtr pDraw,
73005b261ecSmrg   XvPortPtr pPort,
73105b261ecSmrg   GCPtr pGC,
73205b261ecSmrg   INT16 vid_x, INT16 vid_y,
73305b261ecSmrg   CARD16 vid_w, CARD16 vid_h,
73405b261ecSmrg   INT16 drw_x, INT16 drw_y,
73505b261ecSmrg   CARD16 drw_w, CARD16 drw_h
73605b261ecSmrg){
73705b261ecSmrg  DrawablePtr pOldDraw;
73805b261ecSmrg
73905b261ecSmrg  CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
74005b261ecSmrg
74105b261ecSmrg  /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
74205b261ecSmrg
74305b261ecSmrg  UpdateCurrentTime();
74405b261ecSmrg
74505b261ecSmrg  /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
74605b261ecSmrg     INFORM CLIENT OF ITS FAILURE */
74705b261ecSmrg
74805b261ecSmrg  if (pPort->grab.client && (pPort->grab.client != client))
74905b261ecSmrg    {
75005b261ecSmrg      XvdiSendVideoNotify(pPort, pDraw, XvBusy);
75105b261ecSmrg      return Success;
75205b261ecSmrg    }
75305b261ecSmrg
75405b261ecSmrg  /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
75505b261ecSmrg     EVENTS TO ANY CLIENTS WHO WANT THEM */
75605b261ecSmrg
75705b261ecSmrg  pOldDraw = pPort->pDraw;
75805b261ecSmrg  if ((pOldDraw) && (pOldDraw != pDraw))
75905b261ecSmrg    {
76005b261ecSmrg      XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
76105b261ecSmrg    }
76205b261ecSmrg
76305b261ecSmrg  (void) (* pPort->pAdaptor->ddGetVideo)(client, pDraw, pPort, pGC,
76405b261ecSmrg					   vid_x, vid_y, vid_w, vid_h,
76505b261ecSmrg					   drw_x, drw_y, drw_w, drw_h);
76605b261ecSmrg
76705b261ecSmrg  if ((pPort->pDraw) && (pOldDraw != pDraw))
76805b261ecSmrg    {
76905b261ecSmrg      pPort->client = client;
77005b261ecSmrg      XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
77105b261ecSmrg    }
77205b261ecSmrg
77305b261ecSmrg  pPort->time = currentTime;
77405b261ecSmrg
77505b261ecSmrg  return (Success);
77605b261ecSmrg
77705b261ecSmrg}
77805b261ecSmrg
77905b261ecSmrgint
78005b261ecSmrgXvdiGetStill(
78105b261ecSmrg   ClientPtr client,
78205b261ecSmrg   DrawablePtr pDraw,
78305b261ecSmrg   XvPortPtr pPort,
78405b261ecSmrg   GCPtr pGC,
78505b261ecSmrg   INT16 vid_x, INT16 vid_y,
78605b261ecSmrg   CARD16 vid_w, CARD16 vid_h,
78705b261ecSmrg   INT16 drw_x, INT16 drw_y,
78805b261ecSmrg   CARD16 drw_w, CARD16 drw_h
78905b261ecSmrg){
79005b261ecSmrg  int status;
79105b261ecSmrg
79205b261ecSmrg  CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
79305b261ecSmrg
79405b261ecSmrg  /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
79505b261ecSmrg
79605b261ecSmrg  UpdateCurrentTime();
79705b261ecSmrg
79805b261ecSmrg  /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
79905b261ecSmrg     INFORM CLIENT OF ITS FAILURE */
80005b261ecSmrg
80105b261ecSmrg  if (pPort->grab.client && (pPort->grab.client != client))
80205b261ecSmrg    {
80305b261ecSmrg      XvdiSendVideoNotify(pPort, pDraw, XvBusy);
80405b261ecSmrg      return Success;
80505b261ecSmrg    }
80605b261ecSmrg
80705b261ecSmrg  status = (* pPort->pAdaptor->ddGetStill)(client, pDraw, pPort, pGC,
80805b261ecSmrg					   vid_x, vid_y, vid_w, vid_h,
80905b261ecSmrg					   drw_x, drw_y, drw_w, drw_h);
81005b261ecSmrg
81105b261ecSmrg  pPort->time = currentTime;
81205b261ecSmrg
81305b261ecSmrg  return status;
81405b261ecSmrg
81505b261ecSmrg}
81605b261ecSmrg
81705b261ecSmrgint
81805b261ecSmrgXvdiGrabPort(
81905b261ecSmrg   ClientPtr client,
82005b261ecSmrg   XvPortPtr pPort,
82105b261ecSmrg   Time ctime,
82205b261ecSmrg   int *p_result
82305b261ecSmrg){
82405b261ecSmrg  unsigned long id;
82505b261ecSmrg  TimeStamp time;
82605b261ecSmrg
82705b261ecSmrg  UpdateCurrentTime();
82805b261ecSmrg  time = ClientTimeToServerTime(ctime);
82905b261ecSmrg
83005b261ecSmrg  if (pPort->grab.client && (client != pPort->grab.client))
83105b261ecSmrg    {
83205b261ecSmrg      *p_result = XvAlreadyGrabbed;
83305b261ecSmrg      return Success;
83405b261ecSmrg    }
83505b261ecSmrg
83605b261ecSmrg  if ((CompareTimeStamps(time, currentTime) == LATER) ||
83705b261ecSmrg      (CompareTimeStamps(time, pPort->time) == EARLIER))
83805b261ecSmrg    {
83905b261ecSmrg      *p_result = XvInvalidTime;
84005b261ecSmrg      return Success;
84105b261ecSmrg    }
84205b261ecSmrg
84305b261ecSmrg  if (client == pPort->grab.client)
84405b261ecSmrg    {
84505b261ecSmrg      *p_result = Success;
84605b261ecSmrg      return Success;
84705b261ecSmrg    }
84805b261ecSmrg
84905b261ecSmrg  id = FakeClientID(client->index);
85005b261ecSmrg
85105b261ecSmrg  if (!AddResource(id, XvRTGrab, &pPort->grab))
85205b261ecSmrg    {
85305b261ecSmrg      return BadAlloc;
85405b261ecSmrg    }
85505b261ecSmrg
85605b261ecSmrg  /* IF THERE IS ACTIVE VIDEO THEN STOP IT */
85705b261ecSmrg
85805b261ecSmrg  if ((pPort->pDraw) && (client != pPort->client))
85905b261ecSmrg    {
86005b261ecSmrg      XVCALL(diStopVideo)((ClientPtr)NULL, pPort, pPort->pDraw);
86105b261ecSmrg    }
86205b261ecSmrg
86305b261ecSmrg  pPort->grab.client = client;
86405b261ecSmrg  pPort->grab.id = id;
86505b261ecSmrg
86605b261ecSmrg  pPort->time = currentTime;
86705b261ecSmrg
86805b261ecSmrg  *p_result = Success;
86905b261ecSmrg
87005b261ecSmrg  return Success;
87105b261ecSmrg
87205b261ecSmrg}
87305b261ecSmrg
87405b261ecSmrgint
87505b261ecSmrgXvdiUngrabPort(
87605b261ecSmrg  ClientPtr client,
87705b261ecSmrg  XvPortPtr pPort,
87805b261ecSmrg  Time ctime
87905b261ecSmrg){
88005b261ecSmrg  TimeStamp time;
88105b261ecSmrg
88205b261ecSmrg  UpdateCurrentTime();
88305b261ecSmrg  time = ClientTimeToServerTime(ctime);
88405b261ecSmrg
88505b261ecSmrg  if ((!pPort->grab.client) || (client != pPort->grab.client))
88605b261ecSmrg    {
88705b261ecSmrg      return Success;
88805b261ecSmrg    }
88905b261ecSmrg
89005b261ecSmrg  if ((CompareTimeStamps(time, currentTime) == LATER) ||
89105b261ecSmrg      (CompareTimeStamps(time, pPort->time) == EARLIER))
89205b261ecSmrg    {
89305b261ecSmrg      return Success;
89405b261ecSmrg    }
89505b261ecSmrg
89605b261ecSmrg  /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */
89705b261ecSmrg
89805b261ecSmrg  FreeResource(pPort->grab.id, XvRTGrab);
89905b261ecSmrg  pPort->grab.client = (ClientPtr)NULL;
90005b261ecSmrg
90105b261ecSmrg  pPort->time = currentTime;
90205b261ecSmrg
90305b261ecSmrg  return Success;
90405b261ecSmrg
90505b261ecSmrg}
90605b261ecSmrg
90705b261ecSmrg
90805b261ecSmrgint
90905b261ecSmrgXvdiSelectVideoNotify(
91005b261ecSmrg  ClientPtr client,
91105b261ecSmrg  DrawablePtr pDraw,
91205b261ecSmrg  BOOL onoff
91305b261ecSmrg){
91405b261ecSmrg  XvVideoNotifyPtr pn,tpn,fpn;
91505b261ecSmrg
91605b261ecSmrg  /* FIND VideoNotify LIST */
91705b261ecSmrg
91805b261ecSmrg  pn = (XvVideoNotifyPtr)LookupIDByType(pDraw->id, XvRTVideoNotifyList);
91905b261ecSmrg
92005b261ecSmrg  /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */
92105b261ecSmrg
92205b261ecSmrg  if (!onoff && !pn) return Success;
92305b261ecSmrg
92405b261ecSmrg  /* IF ONE DOESN'T EXIST CREATE IT AND ADD A RESOURCE SO THAT THE LIST
92505b261ecSmrg     WILL BE DELETED WHEN THE DRAWABLE IS DESTROYED */
92605b261ecSmrg
92705b261ecSmrg  if (!pn)
92805b261ecSmrg    {
92905b261ecSmrg      if (!(tpn = (XvVideoNotifyPtr)xalloc(sizeof(XvVideoNotifyRec))))
93005b261ecSmrg	return BadAlloc;
93105b261ecSmrg      tpn->next = (XvVideoNotifyPtr)NULL;
93205b261ecSmrg      if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn))
93305b261ecSmrg	{
93405b261ecSmrg	  xfree(tpn);
93505b261ecSmrg	  return BadAlloc;
93605b261ecSmrg	}
93705b261ecSmrg    }
93805b261ecSmrg  else
93905b261ecSmrg    {
94005b261ecSmrg      /* LOOK TO SEE IF ENTRY ALREADY EXISTS */
94105b261ecSmrg
94205b261ecSmrg      fpn = (XvVideoNotifyPtr)NULL;
94305b261ecSmrg      tpn = pn;
94405b261ecSmrg      while (tpn)
94505b261ecSmrg	{
94605b261ecSmrg	  if (tpn->client == client)
94705b261ecSmrg	    {
94805b261ecSmrg	      if (!onoff) tpn->client = (ClientPtr)NULL;
94905b261ecSmrg	      return Success;
95005b261ecSmrg	    }
95105b261ecSmrg	  if (!tpn->client) fpn = tpn; /* TAKE NOTE OF FREE ENTRY */
95205b261ecSmrg	  tpn = tpn->next;
95305b261ecSmrg	}
95405b261ecSmrg
95505b261ecSmrg      /* IF TUNNING OFF, THEN JUST RETURN */
95605b261ecSmrg
95705b261ecSmrg      if (!onoff) return Success;
95805b261ecSmrg
95905b261ecSmrg      /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */
96005b261ecSmrg
96105b261ecSmrg      if (fpn)
96205b261ecSmrg	{
96305b261ecSmrg	  tpn = fpn;
96405b261ecSmrg	}
96505b261ecSmrg      else
96605b261ecSmrg	{
96705b261ecSmrg	  if (!(tpn = (XvVideoNotifyPtr)xalloc(sizeof(XvVideoNotifyRec))))
96805b261ecSmrg	    return BadAlloc;
96905b261ecSmrg	  tpn->next = pn->next;
97005b261ecSmrg	  pn->next = tpn;
97105b261ecSmrg	}
97205b261ecSmrg    }
97305b261ecSmrg
97405b261ecSmrg  /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */
97505b261ecSmrg  /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */
97605b261ecSmrg
97705b261ecSmrg  tpn->client = (ClientPtr)NULL;
97805b261ecSmrg  tpn->id = FakeClientID(client->index);
97905b261ecSmrg  AddResource(tpn->id, XvRTVideoNotify, tpn);
98005b261ecSmrg
98105b261ecSmrg  tpn->client = client;
98205b261ecSmrg  return Success;
98305b261ecSmrg
98405b261ecSmrg}
98505b261ecSmrg
98605b261ecSmrgint
98705b261ecSmrgXvdiSelectPortNotify(
98805b261ecSmrg   ClientPtr client,
98905b261ecSmrg   XvPortPtr pPort,
99005b261ecSmrg   BOOL onoff
99105b261ecSmrg){
99205b261ecSmrg  XvPortNotifyPtr pn,tpn;
99305b261ecSmrg
99405b261ecSmrg  /* SEE IF CLIENT IS ALREADY IN LIST */
99505b261ecSmrg
99605b261ecSmrg  tpn = (XvPortNotifyPtr)NULL;
99705b261ecSmrg  pn = pPort->pNotify;
99805b261ecSmrg  while (pn)
99905b261ecSmrg    {
100005b261ecSmrg      if (!pn->client) tpn = pn; /* TAKE NOTE OF FREE ENTRY */
100105b261ecSmrg      if (pn->client == client) break;
100205b261ecSmrg      pn = pn->next;
100305b261ecSmrg    }
100405b261ecSmrg
100505b261ecSmrg  /* IS THE CLIENT ALREADY ON THE LIST? */
100605b261ecSmrg
100705b261ecSmrg  if (pn)
100805b261ecSmrg    {
100905b261ecSmrg      /* REMOVE IT? */
101005b261ecSmrg
101105b261ecSmrg      if (!onoff)
101205b261ecSmrg	{
101305b261ecSmrg	  pn->client = (ClientPtr)NULL;
101405b261ecSmrg	  FreeResource(pn->id, XvRTPortNotify);
101505b261ecSmrg	}
101605b261ecSmrg
101705b261ecSmrg      return Success;
101805b261ecSmrg    }
101905b261ecSmrg
102005b261ecSmrg  /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE
102105b261ecSmrg     CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */
102205b261ecSmrg
102305b261ecSmrg  if (!tpn)
102405b261ecSmrg    {
102505b261ecSmrg      if (!(tpn = (XvPortNotifyPtr)xalloc(sizeof(XvPortNotifyRec))))
102605b261ecSmrg	return BadAlloc;
102705b261ecSmrg      tpn->next = pPort->pNotify;
102805b261ecSmrg      pPort->pNotify = tpn;
102905b261ecSmrg    }
103005b261ecSmrg
103105b261ecSmrg  tpn->client = client;
103205b261ecSmrg  tpn->id = FakeClientID(client->index);
103305b261ecSmrg  AddResource(tpn->id, XvRTPortNotify, tpn);
103405b261ecSmrg
103505b261ecSmrg  return Success;
103605b261ecSmrg
103705b261ecSmrg}
103805b261ecSmrg
103905b261ecSmrgint
104005b261ecSmrgXvdiStopVideo(
104105b261ecSmrg  ClientPtr client,
104205b261ecSmrg  XvPortPtr pPort,
104305b261ecSmrg  DrawablePtr pDraw
104405b261ecSmrg){
104505b261ecSmrg  int status;
104605b261ecSmrg
104705b261ecSmrg  /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
104805b261ecSmrg
104905b261ecSmrg  if (!pPort->pDraw || (pPort->pDraw != pDraw))
105005b261ecSmrg    {
105105b261ecSmrg      XvdiSendVideoNotify(pPort, pDraw, XvStopped);
105205b261ecSmrg      return Success;
105305b261ecSmrg    }
105405b261ecSmrg
105505b261ecSmrg  /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
105605b261ecSmrg     INFORM CLIENT OF ITS FAILURE */
105705b261ecSmrg
105805b261ecSmrg  if ((client) && (pPort->grab.client) && (pPort->grab.client != client))
105905b261ecSmrg    {
106005b261ecSmrg      XvdiSendVideoNotify(pPort, pDraw, XvBusy);
106105b261ecSmrg      return Success;
106205b261ecSmrg    }
106305b261ecSmrg
106405b261ecSmrg  XvdiSendVideoNotify(pPort, pDraw, XvStopped);
106505b261ecSmrg
106605b261ecSmrg  status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pDraw);
106705b261ecSmrg
106805b261ecSmrg  pPort->pDraw = (DrawablePtr)NULL;
106905b261ecSmrg  pPort->client = (ClientPtr)client;
107005b261ecSmrg  pPort->time = currentTime;
107105b261ecSmrg
107205b261ecSmrg  return status;
107305b261ecSmrg
107405b261ecSmrg}
107505b261ecSmrg
107605b261ecSmrgint
107705b261ecSmrgXvdiPreemptVideo(
107805b261ecSmrg  ClientPtr client,
107905b261ecSmrg  XvPortPtr pPort,
108005b261ecSmrg  DrawablePtr pDraw
108105b261ecSmrg){
108205b261ecSmrg  int status;
108305b261ecSmrg
108405b261ecSmrg  /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
108505b261ecSmrg
108605b261ecSmrg  if (!pPort->pDraw || (pPort->pDraw != pDraw)) return Success;
108705b261ecSmrg
108805b261ecSmrg  XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
108905b261ecSmrg
109005b261ecSmrg  status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pPort->pDraw);
109105b261ecSmrg
109205b261ecSmrg  pPort->pDraw = (DrawablePtr)NULL;
109305b261ecSmrg  pPort->client = (ClientPtr)client;
109405b261ecSmrg  pPort->time = currentTime;
109505b261ecSmrg
109605b261ecSmrg  return status;
109705b261ecSmrg
109805b261ecSmrg}
109905b261ecSmrg
110005b261ecSmrgint
110105b261ecSmrgXvdiMatchPort(
110205b261ecSmrg  XvPortPtr pPort,
110305b261ecSmrg  DrawablePtr pDraw
110405b261ecSmrg){
110505b261ecSmrg
110605b261ecSmrg  XvAdaptorPtr pa;
110705b261ecSmrg  XvFormatPtr pf;
110805b261ecSmrg  int nf;
110905b261ecSmrg
111005b261ecSmrg  pa = pPort->pAdaptor;
111105b261ecSmrg
111205b261ecSmrg  if (pa->pScreen != pDraw->pScreen) return BadMatch;
111305b261ecSmrg
111405b261ecSmrg  nf = pa->nFormats;
111505b261ecSmrg  pf = pa->pFormats;
111605b261ecSmrg
111705b261ecSmrg  while (nf--)
111805b261ecSmrg    {
111905b261ecSmrg      if ((pf->depth == pDraw->depth)
112005b261ecSmrg#if 0
112105b261ecSmrg         && ((pDraw->type == DRAWABLE_PIXMAP) ||
112205b261ecSmrg	   (wVisual(((WindowPtr)pDraw)) == pf->visual))
112305b261ecSmrg#endif
112405b261ecSmrg	)
112505b261ecSmrg	return Success;
112605b261ecSmrg      pf++;
112705b261ecSmrg    }
112805b261ecSmrg
112905b261ecSmrg  return BadMatch;
113005b261ecSmrg
113105b261ecSmrg}
113205b261ecSmrg
113305b261ecSmrgint
113405b261ecSmrgXvdiSetPortAttribute(
113505b261ecSmrg  ClientPtr client,
113605b261ecSmrg  XvPortPtr pPort,
113705b261ecSmrg  Atom attribute,
113805b261ecSmrg  INT32 value
113905b261ecSmrg){
114005b261ecSmrg
114105b261ecSmrg    XvdiSendPortNotify(pPort, attribute, value);
114205b261ecSmrg
114305b261ecSmrg  return
114405b261ecSmrg    (* pPort->pAdaptor->ddSetPortAttribute)(client, pPort, attribute, value);
114505b261ecSmrg
114605b261ecSmrg}
114705b261ecSmrg
114805b261ecSmrgint
114905b261ecSmrgXvdiGetPortAttribute(
115005b261ecSmrg  ClientPtr client,
115105b261ecSmrg  XvPortPtr pPort,
115205b261ecSmrg  Atom attribute,
115305b261ecSmrg  INT32 *p_value
115405b261ecSmrg){
115505b261ecSmrg
115605b261ecSmrg  return
115705b261ecSmrg    (* pPort->pAdaptor->ddGetPortAttribute)(client, pPort, attribute, p_value);
115805b261ecSmrg
115905b261ecSmrg}
116005b261ecSmrg
116105b261ecSmrgstatic void
116205b261ecSmrgWriteSwappedVideoNotifyEvent(xvEvent *from, xvEvent *to)
116305b261ecSmrg
116405b261ecSmrg{
116505b261ecSmrg
116605b261ecSmrg  to->u.u.type = from->u.u.type;
116705b261ecSmrg  to->u.u.detail = from->u.u.detail;
116805b261ecSmrg  cpswaps(from->u.videoNotify.sequenceNumber,
116905b261ecSmrg	  to->u.videoNotify.sequenceNumber);
117005b261ecSmrg  cpswapl(from->u.videoNotify.time, to->u.videoNotify.time);
117105b261ecSmrg  cpswapl(from->u.videoNotify.drawable, to->u.videoNotify.drawable);
117205b261ecSmrg  cpswapl(from->u.videoNotify.port, to->u.videoNotify.port);
117305b261ecSmrg
117405b261ecSmrg}
117505b261ecSmrg
117605b261ecSmrgstatic void
117705b261ecSmrgWriteSwappedPortNotifyEvent(xvEvent *from, xvEvent *to)
117805b261ecSmrg
117905b261ecSmrg{
118005b261ecSmrg
118105b261ecSmrg  to->u.u.type = from->u.u.type;
118205b261ecSmrg  to->u.u.detail = from->u.u.detail;
118305b261ecSmrg  cpswaps(from->u.portNotify.sequenceNumber, to->u.portNotify.sequenceNumber);
118405b261ecSmrg  cpswapl(from->u.portNotify.time, to->u.portNotify.time);
118505b261ecSmrg  cpswapl(from->u.portNotify.port, to->u.portNotify.port);
118605b261ecSmrg  cpswapl(from->u.portNotify.value, to->u.portNotify.value);
118705b261ecSmrg
118805b261ecSmrg}
1189