1706f2543Smrg/***********************************************************
2706f2543SmrgCopyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
3706f2543Smrgand the Massachusetts Institute of Technology, Cambridge, Massachusetts.
4706f2543Smrg
5706f2543Smrg                        All Rights Reserved
6706f2543Smrg
7706f2543SmrgPermission to use, copy, modify, and distribute this software and its
8706f2543Smrgdocumentation for any purpose and without fee is hereby granted,
9706f2543Smrgprovided that the above copyright notice appear in all copies and that
10706f2543Smrgboth that copyright notice and this permission notice appear in
11706f2543Smrgsupporting documentation, and that the names of Digital or MIT not be
12706f2543Smrgused in advertising or publicity pertaining to distribution of the
13706f2543Smrgsoftware without specific, written prior permission.
14706f2543Smrg
15706f2543SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16706f2543SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17706f2543SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18706f2543SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20706f2543SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21706f2543SmrgSOFTWARE.
22706f2543Smrg
23706f2543Smrg******************************************************************/
24706f2543Smrg
25706f2543Smrg/*
26706f2543Smrg** File:
27706f2543Smrg**
28706f2543Smrg**   xvmain.c --- Xv server extension main device independent module.
29706f2543Smrg**
30706f2543Smrg** Author:
31706f2543Smrg**
32706f2543Smrg**   David Carver (Digital Workstation Engineering/Project Athena)
33706f2543Smrg**
34706f2543Smrg** Revisions:
35706f2543Smrg**
36706f2543Smrg**   04.09.91 Carver
37706f2543Smrg**     - change: stop video always generates an event even when video
38706f2543Smrg**       wasn't active
39706f2543Smrg**
40706f2543Smrg**   29.08.91 Carver
41706f2543Smrg**     - change: unrealizing windows no longer preempts video
42706f2543Smrg**
43706f2543Smrg**   11.06.91 Carver
44706f2543Smrg**     - changed SetPortControl to SetPortAttribute
45706f2543Smrg**     - changed GetPortControl to GetPortAttribute
46706f2543Smrg**     - changed QueryBestSize
47706f2543Smrg**
48706f2543Smrg**   28.05.91 Carver
49706f2543Smrg**     - fixed Put and Get requests to not preempt operations to same drawable
50706f2543Smrg**
51706f2543Smrg**   15.05.91 Carver
52706f2543Smrg**     - version 2.0 upgrade
53706f2543Smrg**
54706f2543Smrg**   19.03.91 Carver
55706f2543Smrg**     - fixed Put and Get requests to honor grabbed ports.
56706f2543Smrg**     - fixed Video requests to update di structure with new drawable, and
57706f2543Smrg**       client after calling ddx.
58706f2543Smrg**
59706f2543Smrg**   24.01.91 Carver
60706f2543Smrg**     - version 1.4 upgrade
61706f2543Smrg**
62706f2543Smrg** Notes:
63706f2543Smrg**
64706f2543Smrg**   Port structures reference client structures in a two different
65706f2543Smrg**   ways: when grabs, or video is active.  Each reference is encoded
66706f2543Smrg**   as fake client resources and thus when the client is goes away so
67706f2543Smrg**   does the reference (it is zeroed).  No other action is taken, so
68706f2543Smrg**   video doesn't necessarily stop.  It probably will as a result of
69706f2543Smrg**   other resources going away, but if a client starts video using
70706f2543Smrg**   none of its own resources, then the video will continue to play
71706f2543Smrg**   after the client disappears.
72706f2543Smrg**
73706f2543Smrg**
74706f2543Smrg*/
75706f2543Smrg
76706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
77706f2543Smrg#include <dix-config.h>
78706f2543Smrg#endif
79706f2543Smrg
80706f2543Smrg#include <string.h>
81706f2543Smrg
82706f2543Smrg#include <X11/X.h>
83706f2543Smrg#include <X11/Xproto.h>
84706f2543Smrg#include "misc.h"
85706f2543Smrg#include "os.h"
86706f2543Smrg#include "scrnintstr.h"
87706f2543Smrg#include "windowstr.h"
88706f2543Smrg#include "pixmapstr.h"
89706f2543Smrg#include "gc.h"
90706f2543Smrg#include "extnsionst.h"
91706f2543Smrg#include "dixstruct.h"
92706f2543Smrg#include "resource.h"
93706f2543Smrg#include "opaque.h"
94706f2543Smrg#include "input.h"
95706f2543Smrg
96706f2543Smrg#define GLOBAL
97706f2543Smrg
98706f2543Smrg#include <X11/extensions/Xv.h>
99706f2543Smrg#include <X11/extensions/Xvproto.h>
100706f2543Smrg#include "xvdix.h"
101706f2543Smrg
102706f2543Smrg#ifdef PANORAMIX
103706f2543Smrg#include "panoramiX.h"
104706f2543Smrg#include "panoramiXsrv.h"
105706f2543Smrg#endif
106706f2543Smrg#include "xvdisp.h"
107706f2543Smrg
108706f2543Smrgstatic DevPrivateKeyRec XvScreenKeyRec;
109706f2543Smrg#define XvScreenKey (&XvScreenKeyRec)
110706f2543Smrgunsigned long XvExtensionGeneration = 0;
111706f2543Smrgunsigned long XvScreenGeneration = 0;
112706f2543Smrgunsigned long XvResourceGeneration = 0;
113706f2543Smrg
114706f2543Smrgint XvReqCode;
115706f2543Smrgint XvEventBase;
116706f2543Smrgint XvErrorBase;
117706f2543Smrg
118706f2543Smrgunsigned long XvRTPort;
119706f2543Smrgunsigned long XvRTEncoding;
120706f2543Smrgunsigned long XvRTGrab;
121706f2543Smrgunsigned long XvRTVideoNotify;
122706f2543Smrgunsigned long XvRTVideoNotifyList;
123706f2543Smrgunsigned long XvRTPortNotify;
124706f2543Smrg
125706f2543Smrg
126706f2543Smrg
127706f2543Smrg/* EXTERNAL */
128706f2543Smrg
129706f2543Smrgstatic void WriteSwappedVideoNotifyEvent(xvEvent *, xvEvent *);
130706f2543Smrgstatic void WriteSwappedPortNotifyEvent(xvEvent *, xvEvent *);
131706f2543Smrgstatic Bool CreateResourceTypes(void);
132706f2543Smrg
133706f2543Smrgstatic Bool XvCloseScreen(int, ScreenPtr);
134706f2543Smrgstatic Bool XvDestroyPixmap(PixmapPtr);
135706f2543Smrgstatic Bool XvDestroyWindow(WindowPtr);
136706f2543Smrgstatic void XvResetProc(ExtensionEntry*);
137706f2543Smrgstatic int XvdiDestroyGrab(pointer, XID);
138706f2543Smrgstatic int XvdiDestroyEncoding(pointer, XID);
139706f2543Smrgstatic int XvdiDestroyVideoNotify(pointer, XID);
140706f2543Smrgstatic int XvdiDestroyPortNotify(pointer, XID);
141706f2543Smrgstatic int XvdiDestroyVideoNotifyList(pointer, XID);
142706f2543Smrgstatic int XvdiDestroyPort(pointer, XID);
143706f2543Smrgstatic int XvdiSendVideoNotify(XvPortPtr, DrawablePtr, int);
144706f2543Smrg
145706f2543Smrg
146706f2543Smrg
147706f2543Smrg
148706f2543Smrg/*
149706f2543Smrg** XvExtensionInit
150706f2543Smrg**
151706f2543Smrg**
152706f2543Smrg*/
153706f2543Smrg
154706f2543Smrgvoid
155706f2543SmrgXvExtensionInit(void)
156706f2543Smrg{
157706f2543Smrg  ExtensionEntry *extEntry;
158706f2543Smrg
159706f2543Smrg  if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0))
160706f2543Smrg      return;
161706f2543Smrg
162706f2543Smrg  /* LOOK TO SEE IF ANY SCREENS WERE INITIALIZED; IF NOT THEN
163706f2543Smrg     INIT GLOBAL VARIABLES SO THE EXTENSION CAN FUNCTION */
164706f2543Smrg  if (XvScreenGeneration != serverGeneration)
165706f2543Smrg    {
166706f2543Smrg      if (!CreateResourceTypes())
167706f2543Smrg	{
168706f2543Smrg	  ErrorF("XvExtensionInit: Unable to allocate resource types\n");
169706f2543Smrg	  return;
170706f2543Smrg	}
171706f2543Smrg#ifdef PANORAMIX
172706f2543Smrg        XineramaRegisterConnectionBlockCallback(XineramifyXv);
173706f2543Smrg#endif
174706f2543Smrg      XvScreenGeneration = serverGeneration;
175706f2543Smrg    }
176706f2543Smrg
177706f2543Smrg  if (XvExtensionGeneration != serverGeneration)
178706f2543Smrg    {
179706f2543Smrg      XvExtensionGeneration = serverGeneration;
180706f2543Smrg
181706f2543Smrg      extEntry = AddExtension(XvName, XvNumEvents, XvNumErrors,
182706f2543Smrg			      ProcXvDispatch, SProcXvDispatch,
183706f2543Smrg			      XvResetProc, StandardMinorOpcode);
184706f2543Smrg      if (!extEntry)
185706f2543Smrg	{
186706f2543Smrg	  FatalError("XvExtensionInit: AddExtensions failed\n");
187706f2543Smrg	}
188706f2543Smrg
189706f2543Smrg      XvReqCode = extEntry->base;
190706f2543Smrg      XvEventBase = extEntry->eventBase;
191706f2543Smrg      XvErrorBase = extEntry->errorBase;
192706f2543Smrg
193706f2543Smrg      EventSwapVector[XvEventBase+XvVideoNotify] =
194706f2543Smrg	(EventSwapPtr)WriteSwappedVideoNotifyEvent;
195706f2543Smrg      EventSwapVector[XvEventBase+XvPortNotify] =
196706f2543Smrg	(EventSwapPtr)WriteSwappedPortNotifyEvent;
197706f2543Smrg
198706f2543Smrg      SetResourceTypeErrorValue(XvRTPort, _XvBadPort);
199706f2543Smrg      (void)MakeAtom(XvName, strlen(XvName), xTrue);
200706f2543Smrg
201706f2543Smrg    }
202706f2543Smrg}
203706f2543Smrg
204706f2543Smrgstatic Bool
205706f2543SmrgCreateResourceTypes(void)
206706f2543Smrg
207706f2543Smrg{
208706f2543Smrg
209706f2543Smrg  if (XvResourceGeneration == serverGeneration) return TRUE;
210706f2543Smrg
211706f2543Smrg  XvResourceGeneration = serverGeneration;
212706f2543Smrg
213706f2543Smrg  if (!(XvRTPort = CreateNewResourceType(XvdiDestroyPort, "XvRTPort")))
214706f2543Smrg    {
215706f2543Smrg      ErrorF("CreateResourceTypes: failed to allocate port resource.\n");
216706f2543Smrg      return FALSE;
217706f2543Smrg    }
218706f2543Smrg
219706f2543Smrg  if (!(XvRTGrab = CreateNewResourceType(XvdiDestroyGrab, "XvRTGrab")))
220706f2543Smrg    {
221706f2543Smrg      ErrorF("CreateResourceTypes: failed to allocate grab resource.\n");
222706f2543Smrg      return FALSE;
223706f2543Smrg    }
224706f2543Smrg
225706f2543Smrg  if (!(XvRTEncoding = CreateNewResourceType(XvdiDestroyEncoding,
226706f2543Smrg					     "XvRTEncoding")))
227706f2543Smrg    {
228706f2543Smrg      ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n");
229706f2543Smrg      return FALSE;
230706f2543Smrg    }
231706f2543Smrg
232706f2543Smrg  if (!(XvRTVideoNotify = CreateNewResourceType(XvdiDestroyVideoNotify,
233706f2543Smrg						"XvRTVideoNotify")))
234706f2543Smrg    {
235706f2543Smrg      ErrorF("CreateResourceTypes: failed to allocate video notify resource.\n");
236706f2543Smrg      return FALSE;
237706f2543Smrg    }
238706f2543Smrg
239706f2543Smrg  if (!(XvRTVideoNotifyList = CreateNewResourceType(XvdiDestroyVideoNotifyList,
240706f2543Smrg						    "XvRTVideoNotifyList")))
241706f2543Smrg    {
242706f2543Smrg      ErrorF("CreateResourceTypes: failed to allocate video notify list resource.\n");
243706f2543Smrg      return FALSE;
244706f2543Smrg    }
245706f2543Smrg
246706f2543Smrg  if (!(XvRTPortNotify = CreateNewResourceType(XvdiDestroyPortNotify,
247706f2543Smrg					       "XvRTPortNotify")))
248706f2543Smrg    {
249706f2543Smrg      ErrorF("CreateResourceTypes: failed to allocate port notify resource.\n");
250706f2543Smrg      return FALSE;
251706f2543Smrg    }
252706f2543Smrg
253706f2543Smrg  return TRUE;
254706f2543Smrg
255706f2543Smrg}
256706f2543Smrg
257706f2543Smrgint
258706f2543SmrgXvScreenInit(ScreenPtr pScreen)
259706f2543Smrg{
260706f2543Smrg  XvScreenPtr pxvs;
261706f2543Smrg
262706f2543Smrg  if (XvScreenGeneration != serverGeneration)
263706f2543Smrg    {
264706f2543Smrg      if (!CreateResourceTypes())
265706f2543Smrg	{
266706f2543Smrg	  ErrorF("XvScreenInit: Unable to allocate resource types\n");
267706f2543Smrg	  return BadAlloc;
268706f2543Smrg	}
269706f2543Smrg#ifdef PANORAMIX
270706f2543Smrg        XineramaRegisterConnectionBlockCallback(XineramifyXv);
271706f2543Smrg#endif
272706f2543Smrg      XvScreenGeneration = serverGeneration;
273706f2543Smrg    }
274706f2543Smrg
275706f2543Smrg  if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0))
276706f2543Smrg      return BadAlloc;
277706f2543Smrg
278706f2543Smrg  if (dixLookupPrivate(&pScreen->devPrivates, XvScreenKey))
279706f2543Smrg    {
280706f2543Smrg      ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n");
281706f2543Smrg    }
282706f2543Smrg
283706f2543Smrg  /* ALLOCATE SCREEN PRIVATE RECORD */
284706f2543Smrg
285706f2543Smrg  pxvs = malloc(sizeof (XvScreenRec));
286706f2543Smrg  if (!pxvs)
287706f2543Smrg    {
288706f2543Smrg      ErrorF("XvScreenInit: Unable to allocate screen private structure\n");
289706f2543Smrg      return BadAlloc;
290706f2543Smrg    }
291706f2543Smrg
292706f2543Smrg  dixSetPrivate(&pScreen->devPrivates, XvScreenKey, pxvs);
293706f2543Smrg
294706f2543Smrg  pxvs->DestroyPixmap = pScreen->DestroyPixmap;
295706f2543Smrg  pxvs->DestroyWindow = pScreen->DestroyWindow;
296706f2543Smrg  pxvs->CloseScreen = pScreen->CloseScreen;
297706f2543Smrg
298706f2543Smrg  pScreen->DestroyPixmap = XvDestroyPixmap;
299706f2543Smrg  pScreen->DestroyWindow = XvDestroyWindow;
300706f2543Smrg  pScreen->CloseScreen = XvCloseScreen;
301706f2543Smrg
302706f2543Smrg  return Success;
303706f2543Smrg}
304706f2543Smrg
305706f2543Smrgstatic Bool
306706f2543SmrgXvCloseScreen(
307706f2543Smrg  int ii,
308706f2543Smrg  ScreenPtr pScreen
309706f2543Smrg){
310706f2543Smrg
311706f2543Smrg  XvScreenPtr pxvs;
312706f2543Smrg
313706f2543Smrg  pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
314706f2543Smrg
315706f2543Smrg  pScreen->DestroyPixmap = pxvs->DestroyPixmap;
316706f2543Smrg  pScreen->DestroyWindow = pxvs->DestroyWindow;
317706f2543Smrg  pScreen->CloseScreen = pxvs->CloseScreen;
318706f2543Smrg
319706f2543Smrg  (* pxvs->ddCloseScreen)(ii, pScreen);
320706f2543Smrg
321706f2543Smrg  free(pxvs);
322706f2543Smrg
323706f2543Smrg  dixSetPrivate(&pScreen->devPrivates, XvScreenKey, NULL);
324706f2543Smrg
325706f2543Smrg  return (*pScreen->CloseScreen)(ii, pScreen);
326706f2543Smrg}
327706f2543Smrg
328706f2543Smrgstatic void
329706f2543SmrgXvResetProc(ExtensionEntry* extEntry)
330706f2543Smrg{
331706f2543Smrg    XvResetProcVector();
332706f2543Smrg}
333706f2543Smrg
334706f2543SmrgDevPrivateKey
335706f2543SmrgXvGetScreenKey(void)
336706f2543Smrg{
337706f2543Smrg    return XvScreenKey;
338706f2543Smrg}
339706f2543Smrg
340706f2543Smrgunsigned long
341706f2543SmrgXvGetRTPort(void)
342706f2543Smrg{
343706f2543Smrg  return XvRTPort;
344706f2543Smrg}
345706f2543Smrg
346706f2543Smrgstatic Bool
347706f2543SmrgXvDestroyPixmap(PixmapPtr pPix)
348706f2543Smrg{
349706f2543Smrg  Bool status;
350706f2543Smrg  ScreenPtr pScreen;
351706f2543Smrg  XvScreenPtr pxvs;
352706f2543Smrg  XvAdaptorPtr pa;
353706f2543Smrg  int na;
354706f2543Smrg  XvPortPtr pp;
355706f2543Smrg  int np;
356706f2543Smrg
357706f2543Smrg  pScreen = pPix->drawable.pScreen;
358706f2543Smrg
359706f2543Smrg  SCREEN_PROLOGUE(pScreen, DestroyPixmap);
360706f2543Smrg
361706f2543Smrg  pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
362706f2543Smrg
363706f2543Smrg  /* CHECK TO SEE IF THIS PORT IS IN USE */
364706f2543Smrg
365706f2543Smrg  pa = pxvs->pAdaptors;
366706f2543Smrg  na = pxvs->nAdaptors;
367706f2543Smrg  while (na--)
368706f2543Smrg    {
369706f2543Smrg      np = pa->nPorts;
370706f2543Smrg      pp = pa->pPorts;
371706f2543Smrg
372706f2543Smrg      while (np--)
373706f2543Smrg	{
374706f2543Smrg	  if (pp->pDraw == (DrawablePtr)pPix)
375706f2543Smrg	    {
376706f2543Smrg	      XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted);
377706f2543Smrg
378706f2543Smrg	      (void)(* pp->pAdaptor->ddStopVideo)(NULL, pp, pp->pDraw);
379706f2543Smrg
380706f2543Smrg	      pp->pDraw = NULL;
381706f2543Smrg	      pp->client = NULL;
382706f2543Smrg	      pp->time = currentTime;
383706f2543Smrg	    }
384706f2543Smrg	  pp++;
385706f2543Smrg	}
386706f2543Smrg      pa++;
387706f2543Smrg    }
388706f2543Smrg
389706f2543Smrg  status = (* pScreen->DestroyPixmap)(pPix);
390706f2543Smrg
391706f2543Smrg  SCREEN_EPILOGUE(pScreen, DestroyPixmap, XvDestroyPixmap);
392706f2543Smrg
393706f2543Smrg  return status;
394706f2543Smrg
395706f2543Smrg}
396706f2543Smrg
397706f2543Smrgstatic Bool
398706f2543SmrgXvDestroyWindow(WindowPtr pWin)
399706f2543Smrg{
400706f2543Smrg  Bool status;
401706f2543Smrg  ScreenPtr pScreen;
402706f2543Smrg  XvScreenPtr pxvs;
403706f2543Smrg  XvAdaptorPtr pa;
404706f2543Smrg  int na;
405706f2543Smrg  XvPortPtr pp;
406706f2543Smrg  int np;
407706f2543Smrg
408706f2543Smrg  pScreen = pWin->drawable.pScreen;
409706f2543Smrg
410706f2543Smrg  SCREEN_PROLOGUE(pScreen, DestroyWindow);
411706f2543Smrg
412706f2543Smrg  pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
413706f2543Smrg
414706f2543Smrg  /* CHECK TO SEE IF THIS PORT IS IN USE */
415706f2543Smrg
416706f2543Smrg  pa = pxvs->pAdaptors;
417706f2543Smrg  na = pxvs->nAdaptors;
418706f2543Smrg  while (na--)
419706f2543Smrg    {
420706f2543Smrg      np = pa->nPorts;
421706f2543Smrg      pp = pa->pPorts;
422706f2543Smrg
423706f2543Smrg      while (np--)
424706f2543Smrg	{
425706f2543Smrg	  if (pp->pDraw == (DrawablePtr)pWin)
426706f2543Smrg	    {
427706f2543Smrg	      XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted);
428706f2543Smrg
429706f2543Smrg	      (void)(* pp->pAdaptor->ddStopVideo)(NULL, pp, pp->pDraw);
430706f2543Smrg
431706f2543Smrg	      pp->pDraw = NULL;
432706f2543Smrg	      pp->client = NULL;
433706f2543Smrg	      pp->time = currentTime;
434706f2543Smrg	    }
435706f2543Smrg	  pp++;
436706f2543Smrg	}
437706f2543Smrg      pa++;
438706f2543Smrg    }
439706f2543Smrg
440706f2543Smrg
441706f2543Smrg  status = (* pScreen->DestroyWindow)(pWin);
442706f2543Smrg
443706f2543Smrg  SCREEN_EPILOGUE(pScreen, DestroyWindow, XvDestroyWindow);
444706f2543Smrg
445706f2543Smrg  return status;
446706f2543Smrg
447706f2543Smrg}
448706f2543Smrg
449706f2543Smrg/* The XvdiVideoStopped procedure is a hook for the device dependent layer.
450706f2543Smrg   It provides a way for the dd layer to inform the di layer that video has
451706f2543Smrg   stopped in a port for reasons that the di layer had no control over; note
452706f2543Smrg   that it doesn't call back into the dd layer */
453706f2543Smrg
454706f2543Smrgint
455706f2543SmrgXvdiVideoStopped(XvPortPtr pPort, int reason)
456706f2543Smrg{
457706f2543Smrg
458706f2543Smrg  /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
459706f2543Smrg
460706f2543Smrg  if (!pPort->pDraw) return Success;
461706f2543Smrg
462706f2543Smrg  XvdiSendVideoNotify(pPort, pPort->pDraw, reason);
463706f2543Smrg
464706f2543Smrg  pPort->pDraw = NULL;
465706f2543Smrg  pPort->client = NULL;
466706f2543Smrg  pPort->time = currentTime;
467706f2543Smrg
468706f2543Smrg  return Success;
469706f2543Smrg
470706f2543Smrg}
471706f2543Smrg
472706f2543Smrgstatic int
473706f2543SmrgXvdiDestroyPort(pointer pPort, XID id)
474706f2543Smrg{
475706f2543Smrg  return (* ((XvPortPtr)pPort)->pAdaptor->ddFreePort)(pPort);
476706f2543Smrg}
477706f2543Smrg
478706f2543Smrgstatic int
479706f2543SmrgXvdiDestroyGrab(pointer pGrab, XID id)
480706f2543Smrg{
481706f2543Smrg  ((XvGrabPtr)pGrab)->client = NULL;
482706f2543Smrg  return Success;
483706f2543Smrg}
484706f2543Smrg
485706f2543Smrgstatic int
486706f2543SmrgXvdiDestroyVideoNotify(pointer pn, XID id)
487706f2543Smrg{
488706f2543Smrg  /* JUST CLEAR OUT THE client POINTER FIELD */
489706f2543Smrg
490706f2543Smrg  ((XvVideoNotifyPtr)pn)->client = NULL;
491706f2543Smrg  return Success;
492706f2543Smrg}
493706f2543Smrg
494706f2543Smrgstatic int
495706f2543SmrgXvdiDestroyPortNotify(pointer pn, XID id)
496706f2543Smrg{
497706f2543Smrg  /* JUST CLEAR OUT THE client POINTER FIELD */
498706f2543Smrg
499706f2543Smrg  ((XvPortNotifyPtr)pn)->client = NULL;
500706f2543Smrg  return Success;
501706f2543Smrg}
502706f2543Smrg
503706f2543Smrgstatic int
504706f2543SmrgXvdiDestroyVideoNotifyList(pointer pn, XID id)
505706f2543Smrg{
506706f2543Smrg  XvVideoNotifyPtr npn,cpn;
507706f2543Smrg
508706f2543Smrg  /* ACTUALLY DESTROY THE NOTITY LIST */
509706f2543Smrg
510706f2543Smrg  cpn = (XvVideoNotifyPtr)pn;
511706f2543Smrg
512706f2543Smrg  while (cpn)
513706f2543Smrg    {
514706f2543Smrg      npn = cpn->next;
515706f2543Smrg      if (cpn->client) FreeResource(cpn->id, XvRTVideoNotify);
516706f2543Smrg      free(cpn);
517706f2543Smrg      cpn = npn;
518706f2543Smrg    }
519706f2543Smrg  return Success;
520706f2543Smrg}
521706f2543Smrg
522706f2543Smrgstatic int
523706f2543SmrgXvdiDestroyEncoding(pointer value, XID id)
524706f2543Smrg{
525706f2543Smrg  return Success;
526706f2543Smrg}
527706f2543Smrg
528706f2543Smrgstatic int
529706f2543SmrgXvdiSendVideoNotify(XvPortPtr pPort, DrawablePtr pDraw, int reason)
530706f2543Smrg{
531706f2543Smrg  xvEvent event;
532706f2543Smrg  XvVideoNotifyPtr pn;
533706f2543Smrg
534706f2543Smrg  dixLookupResourceByType((pointer *)&pn, pDraw->id, XvRTVideoNotifyList,
535706f2543Smrg			  serverClient, DixReadAccess);
536706f2543Smrg
537706f2543Smrg  while (pn)
538706f2543Smrg    {
539706f2543Smrg      event.u.u.type = XvEventBase + XvVideoNotify;
540706f2543Smrg      event.u.videoNotify.time = currentTime.milliseconds;
541706f2543Smrg      event.u.videoNotify.drawable = pDraw->id;
542706f2543Smrg      event.u.videoNotify.port = pPort->id;
543706f2543Smrg      event.u.videoNotify.reason = reason;
544706f2543Smrg      WriteEventsToClient(pn->client, 1, (xEventPtr)&event);
545706f2543Smrg      pn = pn->next;
546706f2543Smrg    }
547706f2543Smrg
548706f2543Smrg  return Success;
549706f2543Smrg
550706f2543Smrg}
551706f2543Smrg
552706f2543Smrg
553706f2543Smrgint
554706f2543SmrgXvdiSendPortNotify(
555706f2543Smrg  XvPortPtr pPort,
556706f2543Smrg  Atom attribute,
557706f2543Smrg  INT32 value
558706f2543Smrg){
559706f2543Smrg  xvEvent event;
560706f2543Smrg  XvPortNotifyPtr pn;
561706f2543Smrg
562706f2543Smrg  pn = pPort->pNotify;
563706f2543Smrg
564706f2543Smrg  while (pn)
565706f2543Smrg    {
566706f2543Smrg      event.u.u.type = XvEventBase + XvPortNotify;
567706f2543Smrg      event.u.portNotify.time = currentTime.milliseconds;
568706f2543Smrg      event.u.portNotify.port = pPort->id;
569706f2543Smrg      event.u.portNotify.attribute = attribute;
570706f2543Smrg      event.u.portNotify.value = value;
571706f2543Smrg      WriteEventsToClient(pn->client, 1, (xEventPtr)&event);
572706f2543Smrg      pn = pn->next;
573706f2543Smrg    }
574706f2543Smrg
575706f2543Smrg  return Success;
576706f2543Smrg
577706f2543Smrg}
578706f2543Smrg
579706f2543Smrg
580706f2543Smrg#define CHECK_SIZE(dw, dh, sw, sh) {                                  \
581706f2543Smrg  if(!dw || !dh || !sw || !sh)  return Success;                       \
582706f2543Smrg  /* The region code will break these if they are too large */        \
583706f2543Smrg  if((dw > 32767) || (dh > 32767) || (sw > 32767) || (sh > 32767))    \
584706f2543Smrg        return BadValue;                                              \
585706f2543Smrg}
586706f2543Smrg
587706f2543Smrg
588706f2543Smrgint
589706f2543SmrgXvdiPutVideo(
590706f2543Smrg   ClientPtr client,
591706f2543Smrg   DrawablePtr pDraw,
592706f2543Smrg   XvPortPtr pPort,
593706f2543Smrg   GCPtr pGC,
594706f2543Smrg   INT16 vid_x, INT16 vid_y,
595706f2543Smrg   CARD16 vid_w, CARD16 vid_h,
596706f2543Smrg   INT16 drw_x, INT16 drw_y,
597706f2543Smrg   CARD16 drw_w, CARD16 drw_h
598706f2543Smrg){
599706f2543Smrg  DrawablePtr pOldDraw;
600706f2543Smrg
601706f2543Smrg  CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
602706f2543Smrg
603706f2543Smrg  /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
604706f2543Smrg
605706f2543Smrg  UpdateCurrentTime();
606706f2543Smrg
607706f2543Smrg  /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
608706f2543Smrg     INFORM CLIENT OF ITS FAILURE */
609706f2543Smrg
610706f2543Smrg  if (pPort->grab.client && (pPort->grab.client != client))
611706f2543Smrg    {
612706f2543Smrg      XvdiSendVideoNotify(pPort, pDraw, XvBusy);
613706f2543Smrg      return Success;
614706f2543Smrg    }
615706f2543Smrg
616706f2543Smrg  /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
617706f2543Smrg     EVENTS TO ANY CLIENTS WHO WANT THEM */
618706f2543Smrg
619706f2543Smrg  pOldDraw = pPort->pDraw;
620706f2543Smrg  if ((pOldDraw) && (pOldDraw != pDraw))
621706f2543Smrg    {
622706f2543Smrg      XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
623706f2543Smrg    }
624706f2543Smrg
625706f2543Smrg  (void) (* pPort->pAdaptor->ddPutVideo)(client, pDraw, pPort, pGC,
626706f2543Smrg					   vid_x, vid_y, vid_w, vid_h,
627706f2543Smrg					   drw_x, drw_y, drw_w, drw_h);
628706f2543Smrg
629706f2543Smrg  if ((pPort->pDraw) && (pOldDraw != pDraw))
630706f2543Smrg    {
631706f2543Smrg      pPort->client = client;
632706f2543Smrg      XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
633706f2543Smrg    }
634706f2543Smrg
635706f2543Smrg  pPort->time = currentTime;
636706f2543Smrg
637706f2543Smrg  return Success;
638706f2543Smrg
639706f2543Smrg}
640706f2543Smrg
641706f2543Smrgint
642706f2543SmrgXvdiPutStill(
643706f2543Smrg   ClientPtr client,
644706f2543Smrg   DrawablePtr pDraw,
645706f2543Smrg   XvPortPtr pPort,
646706f2543Smrg   GCPtr pGC,
647706f2543Smrg   INT16 vid_x, INT16 vid_y,
648706f2543Smrg   CARD16 vid_w, CARD16 vid_h,
649706f2543Smrg   INT16 drw_x, INT16 drw_y,
650706f2543Smrg   CARD16 drw_w, CARD16 drw_h
651706f2543Smrg){
652706f2543Smrg  int status;
653706f2543Smrg
654706f2543Smrg  CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
655706f2543Smrg
656706f2543Smrg  /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
657706f2543Smrg
658706f2543Smrg  UpdateCurrentTime();
659706f2543Smrg
660706f2543Smrg  /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
661706f2543Smrg     INFORM CLIENT OF ITS FAILURE */
662706f2543Smrg
663706f2543Smrg  if (pPort->grab.client && (pPort->grab.client != client))
664706f2543Smrg    {
665706f2543Smrg      XvdiSendVideoNotify(pPort, pDraw, XvBusy);
666706f2543Smrg      return Success;
667706f2543Smrg    }
668706f2543Smrg
669706f2543Smrg  pPort->time = currentTime;
670706f2543Smrg
671706f2543Smrg  status = (* pPort->pAdaptor->ddPutStill)(client, pDraw, pPort, pGC,
672706f2543Smrg					   vid_x, vid_y, vid_w, vid_h,
673706f2543Smrg					   drw_x, drw_y, drw_w, drw_h);
674706f2543Smrg
675706f2543Smrg  return status;
676706f2543Smrg
677706f2543Smrg}
678706f2543Smrg
679706f2543Smrgint
680706f2543SmrgXvdiPutImage(
681706f2543Smrg   ClientPtr client,
682706f2543Smrg   DrawablePtr pDraw,
683706f2543Smrg   XvPortPtr pPort,
684706f2543Smrg   GCPtr pGC,
685706f2543Smrg   INT16 src_x, INT16 src_y,
686706f2543Smrg   CARD16 src_w, CARD16 src_h,
687706f2543Smrg   INT16 drw_x, INT16 drw_y,
688706f2543Smrg   CARD16 drw_w, CARD16 drw_h,
689706f2543Smrg   XvImagePtr image,
690706f2543Smrg   unsigned char* data,
691706f2543Smrg   Bool sync,
692706f2543Smrg   CARD16 width, CARD16 height
693706f2543Smrg){
694706f2543Smrg  CHECK_SIZE(drw_w, drw_h, src_w, src_h);
695706f2543Smrg
696706f2543Smrg  /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
697706f2543Smrg
698706f2543Smrg  UpdateCurrentTime();
699706f2543Smrg
700706f2543Smrg  /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
701706f2543Smrg     INFORM CLIENT OF ITS FAILURE */
702706f2543Smrg
703706f2543Smrg  if (pPort->grab.client && (pPort->grab.client != client))
704706f2543Smrg    {
705706f2543Smrg      XvdiSendVideoNotify(pPort, pDraw, XvBusy);
706706f2543Smrg      return Success;
707706f2543Smrg    }
708706f2543Smrg
709706f2543Smrg  pPort->time = currentTime;
710706f2543Smrg
711706f2543Smrg  return (* pPort->pAdaptor->ddPutImage)(client, pDraw, pPort, pGC,
712706f2543Smrg					   src_x, src_y, src_w, src_h,
713706f2543Smrg					   drw_x, drw_y, drw_w, drw_h,
714706f2543Smrg					   image, data, sync, width, height);
715706f2543Smrg}
716706f2543Smrg
717706f2543Smrg
718706f2543Smrgint
719706f2543SmrgXvdiGetVideo(
720706f2543Smrg   ClientPtr client,
721706f2543Smrg   DrawablePtr pDraw,
722706f2543Smrg   XvPortPtr pPort,
723706f2543Smrg   GCPtr pGC,
724706f2543Smrg   INT16 vid_x, INT16 vid_y,
725706f2543Smrg   CARD16 vid_w, CARD16 vid_h,
726706f2543Smrg   INT16 drw_x, INT16 drw_y,
727706f2543Smrg   CARD16 drw_w, CARD16 drw_h
728706f2543Smrg){
729706f2543Smrg  DrawablePtr pOldDraw;
730706f2543Smrg
731706f2543Smrg  CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
732706f2543Smrg
733706f2543Smrg  /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
734706f2543Smrg
735706f2543Smrg  UpdateCurrentTime();
736706f2543Smrg
737706f2543Smrg  /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
738706f2543Smrg     INFORM CLIENT OF ITS FAILURE */
739706f2543Smrg
740706f2543Smrg  if (pPort->grab.client && (pPort->grab.client != client))
741706f2543Smrg    {
742706f2543Smrg      XvdiSendVideoNotify(pPort, pDraw, XvBusy);
743706f2543Smrg      return Success;
744706f2543Smrg    }
745706f2543Smrg
746706f2543Smrg  /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
747706f2543Smrg     EVENTS TO ANY CLIENTS WHO WANT THEM */
748706f2543Smrg
749706f2543Smrg  pOldDraw = pPort->pDraw;
750706f2543Smrg  if ((pOldDraw) && (pOldDraw != pDraw))
751706f2543Smrg    {
752706f2543Smrg      XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
753706f2543Smrg    }
754706f2543Smrg
755706f2543Smrg  (void) (* pPort->pAdaptor->ddGetVideo)(client, pDraw, pPort, pGC,
756706f2543Smrg					   vid_x, vid_y, vid_w, vid_h,
757706f2543Smrg					   drw_x, drw_y, drw_w, drw_h);
758706f2543Smrg
759706f2543Smrg  if ((pPort->pDraw) && (pOldDraw != pDraw))
760706f2543Smrg    {
761706f2543Smrg      pPort->client = client;
762706f2543Smrg      XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
763706f2543Smrg    }
764706f2543Smrg
765706f2543Smrg  pPort->time = currentTime;
766706f2543Smrg
767706f2543Smrg  return Success;
768706f2543Smrg
769706f2543Smrg}
770706f2543Smrg
771706f2543Smrgint
772706f2543SmrgXvdiGetStill(
773706f2543Smrg   ClientPtr client,
774706f2543Smrg   DrawablePtr pDraw,
775706f2543Smrg   XvPortPtr pPort,
776706f2543Smrg   GCPtr pGC,
777706f2543Smrg   INT16 vid_x, INT16 vid_y,
778706f2543Smrg   CARD16 vid_w, CARD16 vid_h,
779706f2543Smrg   INT16 drw_x, INT16 drw_y,
780706f2543Smrg   CARD16 drw_w, CARD16 drw_h
781706f2543Smrg){
782706f2543Smrg  int status;
783706f2543Smrg
784706f2543Smrg  CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
785706f2543Smrg
786706f2543Smrg  /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
787706f2543Smrg
788706f2543Smrg  UpdateCurrentTime();
789706f2543Smrg
790706f2543Smrg  /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
791706f2543Smrg     INFORM CLIENT OF ITS FAILURE */
792706f2543Smrg
793706f2543Smrg  if (pPort->grab.client && (pPort->grab.client != client))
794706f2543Smrg    {
795706f2543Smrg      XvdiSendVideoNotify(pPort, pDraw, XvBusy);
796706f2543Smrg      return Success;
797706f2543Smrg    }
798706f2543Smrg
799706f2543Smrg  status = (* pPort->pAdaptor->ddGetStill)(client, pDraw, pPort, pGC,
800706f2543Smrg					   vid_x, vid_y, vid_w, vid_h,
801706f2543Smrg					   drw_x, drw_y, drw_w, drw_h);
802706f2543Smrg
803706f2543Smrg  pPort->time = currentTime;
804706f2543Smrg
805706f2543Smrg  return status;
806706f2543Smrg
807706f2543Smrg}
808706f2543Smrg
809706f2543Smrgint
810706f2543SmrgXvdiGrabPort(
811706f2543Smrg   ClientPtr client,
812706f2543Smrg   XvPortPtr pPort,
813706f2543Smrg   Time ctime,
814706f2543Smrg   int *p_result
815706f2543Smrg){
816706f2543Smrg  unsigned long id;
817706f2543Smrg  TimeStamp time;
818706f2543Smrg
819706f2543Smrg  UpdateCurrentTime();
820706f2543Smrg  time = ClientTimeToServerTime(ctime);
821706f2543Smrg
822706f2543Smrg  if (pPort->grab.client && (client != pPort->grab.client))
823706f2543Smrg    {
824706f2543Smrg      *p_result = XvAlreadyGrabbed;
825706f2543Smrg      return Success;
826706f2543Smrg    }
827706f2543Smrg
828706f2543Smrg  if ((CompareTimeStamps(time, currentTime) == LATER) ||
829706f2543Smrg      (CompareTimeStamps(time, pPort->time) == EARLIER))
830706f2543Smrg    {
831706f2543Smrg      *p_result = XvInvalidTime;
832706f2543Smrg      return Success;
833706f2543Smrg    }
834706f2543Smrg
835706f2543Smrg  if (client == pPort->grab.client)
836706f2543Smrg    {
837706f2543Smrg      *p_result = Success;
838706f2543Smrg      return Success;
839706f2543Smrg    }
840706f2543Smrg
841706f2543Smrg  id = FakeClientID(client->index);
842706f2543Smrg
843706f2543Smrg  if (!AddResource(id, XvRTGrab, &pPort->grab))
844706f2543Smrg    {
845706f2543Smrg      return BadAlloc;
846706f2543Smrg    }
847706f2543Smrg
848706f2543Smrg  /* IF THERE IS ACTIVE VIDEO THEN STOP IT */
849706f2543Smrg
850706f2543Smrg  if ((pPort->pDraw) && (client != pPort->client))
851706f2543Smrg    {
852706f2543Smrg      XvdiStopVideo(NULL, pPort, pPort->pDraw);
853706f2543Smrg    }
854706f2543Smrg
855706f2543Smrg  pPort->grab.client = client;
856706f2543Smrg  pPort->grab.id = id;
857706f2543Smrg
858706f2543Smrg  pPort->time = currentTime;
859706f2543Smrg
860706f2543Smrg  *p_result = Success;
861706f2543Smrg
862706f2543Smrg  return Success;
863706f2543Smrg
864706f2543Smrg}
865706f2543Smrg
866706f2543Smrgint
867706f2543SmrgXvdiUngrabPort(
868706f2543Smrg  ClientPtr client,
869706f2543Smrg  XvPortPtr pPort,
870706f2543Smrg  Time ctime
871706f2543Smrg){
872706f2543Smrg  TimeStamp time;
873706f2543Smrg
874706f2543Smrg  UpdateCurrentTime();
875706f2543Smrg  time = ClientTimeToServerTime(ctime);
876706f2543Smrg
877706f2543Smrg  if ((!pPort->grab.client) || (client != pPort->grab.client))
878706f2543Smrg    {
879706f2543Smrg      return Success;
880706f2543Smrg    }
881706f2543Smrg
882706f2543Smrg  if ((CompareTimeStamps(time, currentTime) == LATER) ||
883706f2543Smrg      (CompareTimeStamps(time, pPort->time) == EARLIER))
884706f2543Smrg    {
885706f2543Smrg      return Success;
886706f2543Smrg    }
887706f2543Smrg
888706f2543Smrg  /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */
889706f2543Smrg
890706f2543Smrg  FreeResource(pPort->grab.id, XvRTGrab);
891706f2543Smrg  pPort->grab.client = NULL;
892706f2543Smrg
893706f2543Smrg  pPort->time = currentTime;
894706f2543Smrg
895706f2543Smrg  return Success;
896706f2543Smrg
897706f2543Smrg}
898706f2543Smrg
899706f2543Smrg
900706f2543Smrgint
901706f2543SmrgXvdiSelectVideoNotify(
902706f2543Smrg  ClientPtr client,
903706f2543Smrg  DrawablePtr pDraw,
904706f2543Smrg  BOOL onoff
905706f2543Smrg){
906706f2543Smrg  XvVideoNotifyPtr pn,tpn,fpn;
907706f2543Smrg  int rc;
908706f2543Smrg
909706f2543Smrg  /* FIND VideoNotify LIST */
910706f2543Smrg
911706f2543Smrg  rc = dixLookupResourceByType((pointer *)&pn, pDraw->id, XvRTVideoNotifyList,
912706f2543Smrg			       client, DixWriteAccess);
913706f2543Smrg  if (rc != Success && rc != BadValue)
914706f2543Smrg      return rc;
915706f2543Smrg
916706f2543Smrg  /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */
917706f2543Smrg
918706f2543Smrg  if (!onoff && !pn) return Success;
919706f2543Smrg
920706f2543Smrg  /* IF ONE DOESN'T EXIST CREATE IT AND ADD A RESOURCE SO THAT THE LIST
921706f2543Smrg     WILL BE DELETED WHEN THE DRAWABLE IS DESTROYED */
922706f2543Smrg
923706f2543Smrg  if (!pn)
924706f2543Smrg    {
925706f2543Smrg      if (!(tpn = malloc(sizeof(XvVideoNotifyRec))))
926706f2543Smrg	return BadAlloc;
927706f2543Smrg      tpn->next = NULL;
928706f2543Smrg      if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn))
929706f2543Smrg	{
930706f2543Smrg	  free(tpn);
931706f2543Smrg	  return BadAlloc;
932706f2543Smrg	}
933706f2543Smrg    }
934706f2543Smrg  else
935706f2543Smrg    {
936706f2543Smrg      /* LOOK TO SEE IF ENTRY ALREADY EXISTS */
937706f2543Smrg
938706f2543Smrg      fpn = NULL;
939706f2543Smrg      tpn = pn;
940706f2543Smrg      while (tpn)
941706f2543Smrg	{
942706f2543Smrg	  if (tpn->client == client)
943706f2543Smrg	    {
944706f2543Smrg	      if (!onoff) tpn->client = NULL;
945706f2543Smrg	      return Success;
946706f2543Smrg	    }
947706f2543Smrg	  if (!tpn->client) fpn = tpn; /* TAKE NOTE OF FREE ENTRY */
948706f2543Smrg	  tpn = tpn->next;
949706f2543Smrg	}
950706f2543Smrg
951706f2543Smrg      /* IF TUNNING OFF, THEN JUST RETURN */
952706f2543Smrg
953706f2543Smrg      if (!onoff) return Success;
954706f2543Smrg
955706f2543Smrg      /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */
956706f2543Smrg
957706f2543Smrg      if (fpn)
958706f2543Smrg	{
959706f2543Smrg	  tpn = fpn;
960706f2543Smrg	}
961706f2543Smrg      else
962706f2543Smrg	{
963706f2543Smrg	  if (!(tpn = malloc(sizeof(XvVideoNotifyRec))))
964706f2543Smrg	    return BadAlloc;
965706f2543Smrg	  tpn->next = pn->next;
966706f2543Smrg	  pn->next = tpn;
967706f2543Smrg	}
968706f2543Smrg    }
969706f2543Smrg
970706f2543Smrg  /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */
971706f2543Smrg  /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */
972706f2543Smrg
973706f2543Smrg  tpn->client = NULL;
974706f2543Smrg  tpn->id = FakeClientID(client->index);
975706f2543Smrg  AddResource(tpn->id, XvRTVideoNotify, tpn);
976706f2543Smrg
977706f2543Smrg  tpn->client = client;
978706f2543Smrg  return Success;
979706f2543Smrg
980706f2543Smrg}
981706f2543Smrg
982706f2543Smrgint
983706f2543SmrgXvdiSelectPortNotify(
984706f2543Smrg   ClientPtr client,
985706f2543Smrg   XvPortPtr pPort,
986706f2543Smrg   BOOL onoff
987706f2543Smrg){
988706f2543Smrg  XvPortNotifyPtr pn,tpn;
989706f2543Smrg
990706f2543Smrg  /* SEE IF CLIENT IS ALREADY IN LIST */
991706f2543Smrg
992706f2543Smrg  tpn = NULL;
993706f2543Smrg  pn = pPort->pNotify;
994706f2543Smrg  while (pn)
995706f2543Smrg    {
996706f2543Smrg      if (!pn->client) tpn = pn; /* TAKE NOTE OF FREE ENTRY */
997706f2543Smrg      if (pn->client == client) break;
998706f2543Smrg      pn = pn->next;
999706f2543Smrg    }
1000706f2543Smrg
1001706f2543Smrg  /* IS THE CLIENT ALREADY ON THE LIST? */
1002706f2543Smrg
1003706f2543Smrg  if (pn)
1004706f2543Smrg    {
1005706f2543Smrg      /* REMOVE IT? */
1006706f2543Smrg
1007706f2543Smrg      if (!onoff)
1008706f2543Smrg	{
1009706f2543Smrg	  pn->client = NULL;
1010706f2543Smrg	  FreeResource(pn->id, XvRTPortNotify);
1011706f2543Smrg	}
1012706f2543Smrg
1013706f2543Smrg      return Success;
1014706f2543Smrg    }
1015706f2543Smrg
1016706f2543Smrg  /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE
1017706f2543Smrg     CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */
1018706f2543Smrg
1019706f2543Smrg  if (!tpn)
1020706f2543Smrg    {
1021706f2543Smrg      if (!(tpn = malloc(sizeof(XvPortNotifyRec))))
1022706f2543Smrg	return BadAlloc;
1023706f2543Smrg      tpn->next = pPort->pNotify;
1024706f2543Smrg      pPort->pNotify = tpn;
1025706f2543Smrg    }
1026706f2543Smrg
1027706f2543Smrg  tpn->client = client;
1028706f2543Smrg  tpn->id = FakeClientID(client->index);
1029706f2543Smrg  AddResource(tpn->id, XvRTPortNotify, tpn);
1030706f2543Smrg
1031706f2543Smrg  return Success;
1032706f2543Smrg
1033706f2543Smrg}
1034706f2543Smrg
1035706f2543Smrgint
1036706f2543SmrgXvdiStopVideo(
1037706f2543Smrg  ClientPtr client,
1038706f2543Smrg  XvPortPtr pPort,
1039706f2543Smrg  DrawablePtr pDraw
1040706f2543Smrg){
1041706f2543Smrg  int status;
1042706f2543Smrg
1043706f2543Smrg  /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
1044706f2543Smrg
1045706f2543Smrg  if (!pPort->pDraw || (pPort->pDraw != pDraw))
1046706f2543Smrg    {
1047706f2543Smrg      XvdiSendVideoNotify(pPort, pDraw, XvStopped);
1048706f2543Smrg      return Success;
1049706f2543Smrg    }
1050706f2543Smrg
1051706f2543Smrg  /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
1052706f2543Smrg     INFORM CLIENT OF ITS FAILURE */
1053706f2543Smrg
1054706f2543Smrg  if ((client) && (pPort->grab.client) && (pPort->grab.client != client))
1055706f2543Smrg    {
1056706f2543Smrg      XvdiSendVideoNotify(pPort, pDraw, XvBusy);
1057706f2543Smrg      return Success;
1058706f2543Smrg    }
1059706f2543Smrg
1060706f2543Smrg  XvdiSendVideoNotify(pPort, pDraw, XvStopped);
1061706f2543Smrg
1062706f2543Smrg  status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pDraw);
1063706f2543Smrg
1064706f2543Smrg  pPort->pDraw = NULL;
1065706f2543Smrg  pPort->client = (ClientPtr)client;
1066706f2543Smrg  pPort->time = currentTime;
1067706f2543Smrg
1068706f2543Smrg  return status;
1069706f2543Smrg
1070706f2543Smrg}
1071706f2543Smrg
1072706f2543Smrgint
1073706f2543SmrgXvdiPreemptVideo(
1074706f2543Smrg  ClientPtr client,
1075706f2543Smrg  XvPortPtr pPort,
1076706f2543Smrg  DrawablePtr pDraw
1077706f2543Smrg){
1078706f2543Smrg  int status;
1079706f2543Smrg
1080706f2543Smrg  /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
1081706f2543Smrg
1082706f2543Smrg  if (!pPort->pDraw || (pPort->pDraw != pDraw)) return Success;
1083706f2543Smrg
1084706f2543Smrg  XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
1085706f2543Smrg
1086706f2543Smrg  status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pPort->pDraw);
1087706f2543Smrg
1088706f2543Smrg  pPort->pDraw = NULL;
1089706f2543Smrg  pPort->client = (ClientPtr)client;
1090706f2543Smrg  pPort->time = currentTime;
1091706f2543Smrg
1092706f2543Smrg  return status;
1093706f2543Smrg
1094706f2543Smrg}
1095706f2543Smrg
1096706f2543Smrgint
1097706f2543SmrgXvdiMatchPort(
1098706f2543Smrg  XvPortPtr pPort,
1099706f2543Smrg  DrawablePtr pDraw
1100706f2543Smrg){
1101706f2543Smrg
1102706f2543Smrg  XvAdaptorPtr pa;
1103706f2543Smrg  XvFormatPtr pf;
1104706f2543Smrg  int nf;
1105706f2543Smrg
1106706f2543Smrg  pa = pPort->pAdaptor;
1107706f2543Smrg
1108706f2543Smrg  if (pa->pScreen != pDraw->pScreen) return BadMatch;
1109706f2543Smrg
1110706f2543Smrg  nf = pa->nFormats;
1111706f2543Smrg  pf = pa->pFormats;
1112706f2543Smrg
1113706f2543Smrg  while (nf--)
1114706f2543Smrg    {
1115706f2543Smrg      if ((pf->depth == pDraw->depth)
1116706f2543Smrg#if 0
1117706f2543Smrg         && ((pDraw->type == DRAWABLE_PIXMAP) ||
1118706f2543Smrg	   (wVisual(((WindowPtr)pDraw)) == pf->visual))
1119706f2543Smrg#endif
1120706f2543Smrg	)
1121706f2543Smrg	return Success;
1122706f2543Smrg      pf++;
1123706f2543Smrg    }
1124706f2543Smrg
1125706f2543Smrg  return BadMatch;
1126706f2543Smrg
1127706f2543Smrg}
1128706f2543Smrg
1129706f2543Smrgint
1130706f2543SmrgXvdiSetPortAttribute(
1131706f2543Smrg  ClientPtr client,
1132706f2543Smrg  XvPortPtr pPort,
1133706f2543Smrg  Atom attribute,
1134706f2543Smrg  INT32 value
1135706f2543Smrg){
1136706f2543Smrg  int status;
1137706f2543Smrg
1138706f2543Smrg  status = (* pPort->pAdaptor->ddSetPortAttribute)(client, pPort, attribute, value);
1139706f2543Smrg  if (status == Success)
1140706f2543Smrg    XvdiSendPortNotify(pPort, attribute, value);
1141706f2543Smrg
1142706f2543Smrg  return status;
1143706f2543Smrg}
1144706f2543Smrg
1145706f2543Smrgint
1146706f2543SmrgXvdiGetPortAttribute(
1147706f2543Smrg  ClientPtr client,
1148706f2543Smrg  XvPortPtr pPort,
1149706f2543Smrg  Atom attribute,
1150706f2543Smrg  INT32 *p_value
1151706f2543Smrg){
1152706f2543Smrg
1153706f2543Smrg  return
1154706f2543Smrg    (* pPort->pAdaptor->ddGetPortAttribute)(client, pPort, attribute, p_value);
1155706f2543Smrg
1156706f2543Smrg}
1157706f2543Smrg
1158706f2543Smrgstatic void
1159706f2543SmrgWriteSwappedVideoNotifyEvent(xvEvent *from, xvEvent *to)
1160706f2543Smrg
1161706f2543Smrg{
1162706f2543Smrg
1163706f2543Smrg  to->u.u.type = from->u.u.type;
1164706f2543Smrg  to->u.u.detail = from->u.u.detail;
1165706f2543Smrg  cpswaps(from->u.videoNotify.sequenceNumber,
1166706f2543Smrg	  to->u.videoNotify.sequenceNumber);
1167706f2543Smrg  cpswapl(from->u.videoNotify.time, to->u.videoNotify.time);
1168706f2543Smrg  cpswapl(from->u.videoNotify.drawable, to->u.videoNotify.drawable);
1169706f2543Smrg  cpswapl(from->u.videoNotify.port, to->u.videoNotify.port);
1170706f2543Smrg
1171706f2543Smrg}
1172706f2543Smrg
1173706f2543Smrgstatic void
1174706f2543SmrgWriteSwappedPortNotifyEvent(xvEvent *from, xvEvent *to)
1175706f2543Smrg
1176706f2543Smrg{
1177706f2543Smrg
1178706f2543Smrg  to->u.u.type = from->u.u.type;
1179706f2543Smrg  to->u.u.detail = from->u.u.detail;
1180706f2543Smrg  cpswaps(from->u.portNotify.sequenceNumber, to->u.portNotify.sequenceNumber);
1181706f2543Smrg  cpswapl(from->u.portNotify.time, to->u.portNotify.time);
1182706f2543Smrg  cpswapl(from->u.portNotify.port, to->u.portNotify.port);
1183706f2543Smrg  cpswapl(from->u.portNotify.value, to->u.portNotify.value);
1184706f2543Smrg
1185706f2543Smrg}
1186