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