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