First import
[xorg_rtime.git] / xorg-server-1.4 / Xext / xvmain.c
blobddf3d1d6b1cd5da173f93bbc62427f2b5d93746d
1 /***********************************************************
2 Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
3 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Digital or MIT not be
12 used in advertising or publicity pertaining to distribution of the
13 software without specific, written prior permission.
15 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21 SOFTWARE.
23 ******************************************************************/
26 ** File:
28 ** xvmain.c --- Xv server extension main device independent module.
29 **
30 ** Author:
32 ** David Carver (Digital Workstation Engineering/Project Athena)
34 ** Revisions:
36 ** 04.09.91 Carver
37 ** - change: stop video always generates an event even when video
38 ** wasn't active
40 ** 29.08.91 Carver
41 ** - change: unrealizing windows no longer preempts video
43 ** 11.06.91 Carver
44 ** - changed SetPortControl to SetPortAttribute
45 ** - changed GetPortControl to GetPortAttribute
46 ** - changed QueryBestSize
48 ** 28.05.91 Carver
49 ** - fixed Put and Get requests to not preempt operations to same drawable
51 ** 15.05.91 Carver
52 ** - version 2.0 upgrade
54 ** 19.03.91 Carver
55 ** - fixed Put and Get requests to honor grabbed ports.
56 ** - fixed Video requests to update di structure with new drawable, and
57 ** client after calling ddx.
59 ** 24.01.91 Carver
60 ** - version 1.4 upgrade
61 **
62 ** Notes:
64 ** Port structures reference client structures in a two different
65 ** ways: when grabs, or video is active. Each reference is encoded
66 ** as fake client resources and thus when the client is goes away so
67 ** does the reference (it is zeroed). No other action is taken, so
68 ** video doesn't necessarily stop. It probably will as a result of
69 ** other resources going away, but if a client starts video using
70 ** none of its own resources, then the video will continue to play
71 ** after the client disappears.
76 #ifdef HAVE_DIX_CONFIG_H
77 #include <dix-config.h>
78 #endif
80 #include <string.h>
82 #include <X11/X.h>
83 #include <X11/Xproto.h>
84 #include "misc.h"
85 #include "os.h"
86 #include "scrnintstr.h"
87 #include "windowstr.h"
88 #include "pixmapstr.h"
89 #include "gc.h"
90 #include "extnsionst.h"
91 #include "dixstruct.h"
92 #include "resource.h"
93 #include "opaque.h"
94 #include "input.h"
96 #define GLOBAL
98 #include <X11/extensions/Xv.h>
99 #include <X11/extensions/Xvproto.h>
100 #include "xvdix.h"
102 #ifdef PANORAMIX
103 #include "panoramiX.h"
104 #include "panoramiXsrv.h"
105 #include "xvdisp.h"
106 #endif
108 int XvScreenIndex = -1;
109 unsigned long XvExtensionGeneration = 0;
110 unsigned long XvScreenGeneration = 0;
111 unsigned long XvResourceGeneration = 0;
113 int XvReqCode;
114 int XvEventBase;
115 int XvErrorBase;
117 unsigned long XvRTPort;
118 unsigned long XvRTEncoding;
119 unsigned long XvRTGrab;
120 unsigned long XvRTVideoNotify;
121 unsigned long XvRTVideoNotifyList;
122 unsigned long XvRTPortNotify;
126 /* EXTERNAL */
128 extern XID clientErrorValue;
130 static void WriteSwappedVideoNotifyEvent(xvEvent *, xvEvent *);
131 static void WriteSwappedPortNotifyEvent(xvEvent *, xvEvent *);
132 static Bool CreateResourceTypes(void);
134 static Bool XvCloseScreen(int, ScreenPtr);
135 static Bool XvDestroyPixmap(PixmapPtr);
136 static Bool XvDestroyWindow(WindowPtr);
137 static void XvResetProc(ExtensionEntry*);
138 static int XvdiDestroyGrab(pointer, XID);
139 static int XvdiDestroyEncoding(pointer, XID);
140 static int XvdiDestroyVideoNotify(pointer, XID);
141 static int XvdiDestroyPortNotify(pointer, XID);
142 static int XvdiDestroyVideoNotifyList(pointer, XID);
143 static int XvdiDestroyPort(pointer, XID);
144 static int XvdiSendVideoNotify(XvPortPtr, DrawablePtr, int);
150 ** XvExtensionInit
155 void
156 XvExtensionInit(void)
158 ExtensionEntry *extEntry;
160 /* LOOK TO SEE IF ANY SCREENS WERE INITIALIZED; IF NOT THEN
161 INIT GLOBAL VARIABLES SO THE EXTENSION CAN FUNCTION */
162 if (XvScreenGeneration != serverGeneration)
164 if (!CreateResourceTypes())
166 ErrorF("XvExtensionInit: Unable to allocate resource types\n");
167 return;
169 XvScreenIndex = AllocateScreenPrivateIndex ();
170 if (XvScreenIndex < 0)
172 ErrorF("XvExtensionInit: Unable to allocate screen private index\n");
173 return;
175 #ifdef PANORAMIX
176 XineramaRegisterConnectionBlockCallback(XineramifyXv);
177 #endif
178 XvScreenGeneration = serverGeneration;
181 if (XvExtensionGeneration != serverGeneration)
183 XvExtensionGeneration = serverGeneration;
185 extEntry = AddExtension(XvName, XvNumEvents, XvNumErrors,
186 ProcXvDispatch, SProcXvDispatch,
187 XvResetProc, StandardMinorOpcode);
188 if (!extEntry)
190 FatalError("XvExtensionInit: AddExtensions failed\n");
193 XvReqCode = extEntry->base;
194 XvEventBase = extEntry->eventBase;
195 XvErrorBase = extEntry->errorBase;
197 EventSwapVector[XvEventBase+XvVideoNotify] =
198 (EventSwapPtr)WriteSwappedVideoNotifyEvent;
199 EventSwapVector[XvEventBase+XvPortNotify] =
200 (EventSwapPtr)WriteSwappedPortNotifyEvent;
202 (void)MakeAtom(XvName, strlen(XvName), xTrue);
207 static Bool
208 CreateResourceTypes(void)
212 if (XvResourceGeneration == serverGeneration) return TRUE;
214 XvResourceGeneration = serverGeneration;
216 if (!(XvRTPort = CreateNewResourceType(XvdiDestroyPort)))
218 ErrorF("CreateResourceTypes: failed to allocate port resource.\n");
219 return FALSE;
222 if (!(XvRTGrab = CreateNewResourceType(XvdiDestroyGrab)))
224 ErrorF("CreateResourceTypes: failed to allocate grab resource.\n");
225 return FALSE;
228 if (!(XvRTEncoding = CreateNewResourceType(XvdiDestroyEncoding)))
230 ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n");
231 return FALSE;
234 if (!(XvRTVideoNotify = CreateNewResourceType(XvdiDestroyVideoNotify)))
236 ErrorF("CreateResourceTypes: failed to allocate video notify resource.\n");
237 return FALSE;
240 if (!(XvRTVideoNotifyList = CreateNewResourceType(XvdiDestroyVideoNotifyList)))
242 ErrorF("CreateResourceTypes: failed to allocate video notify list resource.\n");
243 return FALSE;
246 if (!(XvRTPortNotify = CreateNewResourceType(XvdiDestroyPortNotify)))
248 ErrorF("CreateResourceTypes: failed to allocate port notify resource.\n");
249 return FALSE;
252 return TRUE;
256 _X_EXPORT int
257 XvScreenInit(ScreenPtr pScreen)
259 XvScreenPtr pxvs;
261 if (XvScreenGeneration != serverGeneration)
263 if (!CreateResourceTypes())
265 ErrorF("XvScreenInit: Unable to allocate resource types\n");
266 return BadAlloc;
268 XvScreenIndex = AllocateScreenPrivateIndex ();
269 if (XvScreenIndex < 0)
271 ErrorF("XvScreenInit: Unable to allocate screen private index\n");
272 return BadAlloc;
274 #ifdef PANORAMIX
275 XineramaRegisterConnectionBlockCallback(XineramifyXv);
276 #endif
277 XvScreenGeneration = serverGeneration;
280 if (pScreen->devPrivates[XvScreenIndex].ptr)
282 ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n");
285 /* ALLOCATE SCREEN PRIVATE RECORD */
287 pxvs = (XvScreenPtr) xalloc (sizeof (XvScreenRec));
288 if (!pxvs)
290 ErrorF("XvScreenInit: Unable to allocate screen private structure\n");
291 return BadAlloc;
294 pScreen->devPrivates[XvScreenIndex].ptr = (pointer)pxvs;
297 pxvs->DestroyPixmap = pScreen->DestroyPixmap;
298 pxvs->DestroyWindow = pScreen->DestroyWindow;
299 pxvs->CloseScreen = pScreen->CloseScreen;
301 pScreen->DestroyPixmap = XvDestroyPixmap;
302 pScreen->DestroyWindow = XvDestroyWindow;
303 pScreen->CloseScreen = XvCloseScreen;
305 return Success;
308 static Bool
309 XvCloseScreen(
310 int ii,
311 ScreenPtr pScreen
314 XvScreenPtr pxvs;
316 pxvs = (XvScreenPtr) pScreen->devPrivates[XvScreenIndex].ptr;
318 pScreen->DestroyPixmap = pxvs->DestroyPixmap;
319 pScreen->DestroyWindow = pxvs->DestroyWindow;
320 pScreen->CloseScreen = pxvs->CloseScreen;
322 (* pxvs->ddCloseScreen)(ii, pScreen);
324 xfree(pxvs);
326 pScreen->devPrivates[XvScreenIndex].ptr = (pointer)NULL;
328 return (*pScreen->CloseScreen)(ii, pScreen);
332 static void
333 XvResetProc(ExtensionEntry* extEntry)
337 _X_EXPORT int
338 XvGetScreenIndex(void)
340 return XvScreenIndex;
343 _X_EXPORT unsigned long
344 XvGetRTPort(void)
346 return XvRTPort;
349 static Bool
350 XvDestroyPixmap(PixmapPtr pPix)
352 Bool status;
353 ScreenPtr pScreen;
354 XvScreenPtr pxvs;
355 XvAdaptorPtr pa;
356 int na;
357 XvPortPtr pp;
358 int np;
360 pScreen = pPix->drawable.pScreen;
362 SCREEN_PROLOGUE(pScreen, DestroyPixmap);
364 pxvs = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr;
366 /* CHECK TO SEE IF THIS PORT IS IN USE */
368 pa = pxvs->pAdaptors;
369 na = pxvs->nAdaptors;
370 while (na--)
372 np = pa->nPorts;
373 pp = pa->pPorts;
375 while (np--)
377 if (pp->pDraw == (DrawablePtr)pPix)
379 XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted);
381 (void)(* pp->pAdaptor->ddStopVideo)((ClientPtr)NULL, pp,
382 pp->pDraw);
384 pp->pDraw = (DrawablePtr)NULL;
385 pp->client = (ClientPtr)NULL;
386 pp->time = currentTime;
388 pp++;
390 pa++;
393 status = (* pScreen->DestroyPixmap)(pPix);
395 SCREEN_EPILOGUE(pScreen, DestroyPixmap, XvDestroyPixmap);
397 return status;
401 static Bool
402 XvDestroyWindow(WindowPtr pWin)
404 Bool status;
405 ScreenPtr pScreen;
406 XvScreenPtr pxvs;
407 XvAdaptorPtr pa;
408 int na;
409 XvPortPtr pp;
410 int np;
412 pScreen = pWin->drawable.pScreen;
414 SCREEN_PROLOGUE(pScreen, DestroyWindow);
416 pxvs = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr;
418 /* CHECK TO SEE IF THIS PORT IS IN USE */
420 pa = pxvs->pAdaptors;
421 na = pxvs->nAdaptors;
422 while (na--)
424 np = pa->nPorts;
425 pp = pa->pPorts;
427 while (np--)
429 if (pp->pDraw == (DrawablePtr)pWin)
431 XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted);
433 (void)(* pp->pAdaptor->ddStopVideo)((ClientPtr)NULL, pp,
434 pp->pDraw);
436 pp->pDraw = (DrawablePtr)NULL;
437 pp->client = (ClientPtr)NULL;
438 pp->time = currentTime;
440 pp++;
442 pa++;
446 status = (* pScreen->DestroyWindow)(pWin);
448 SCREEN_EPILOGUE(pScreen, DestroyWindow, XvDestroyWindow);
450 return status;
454 /* The XvdiVideoStopped procedure is a hook for the device dependent layer.
455 It provides a way for the dd layer to inform the di layer that video has
456 stopped in a port for reasons that the di layer had no control over; note
457 that it doesn't call back into the dd layer */
460 XvdiVideoStopped(XvPortPtr pPort, int reason)
463 /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
465 if (!pPort->pDraw) return Success;
467 XvdiSendVideoNotify(pPort, pPort->pDraw, reason);
469 pPort->pDraw = (DrawablePtr)NULL;
470 pPort->client = (ClientPtr)NULL;
471 pPort->time = currentTime;
473 return Success;
477 static int
478 XvdiDestroyPort(pointer pPort, XID id)
480 return (* ((XvPortPtr)pPort)->pAdaptor->ddFreePort)(pPort);
483 static int
484 XvdiDestroyGrab(pointer pGrab, XID id)
486 ((XvGrabPtr)pGrab)->client = (ClientPtr)NULL;
487 return Success;
490 static int
491 XvdiDestroyVideoNotify(pointer pn, XID id)
493 /* JUST CLEAR OUT THE client POINTER FIELD */
495 ((XvVideoNotifyPtr)pn)->client = (ClientPtr)NULL;
496 return Success;
499 static int
500 XvdiDestroyPortNotify(pointer pn, XID id)
502 /* JUST CLEAR OUT THE client POINTER FIELD */
504 ((XvPortNotifyPtr)pn)->client = (ClientPtr)NULL;
505 return Success;
508 static int
509 XvdiDestroyVideoNotifyList(pointer pn, XID id)
511 XvVideoNotifyPtr npn,cpn;
513 /* ACTUALLY DESTROY THE NOTITY LIST */
515 cpn = (XvVideoNotifyPtr)pn;
517 while (cpn)
519 npn = cpn->next;
520 if (cpn->client) FreeResource(cpn->id, XvRTVideoNotify);
521 xfree(cpn);
522 cpn = npn;
524 return Success;
527 static int
528 XvdiDestroyEncoding(pointer value, XID id)
530 return Success;
533 static int
534 XvdiSendVideoNotify(pPort, pDraw, reason)
536 XvPortPtr pPort;
537 DrawablePtr pDraw;
538 int reason;
541 xvEvent event;
542 XvVideoNotifyPtr pn;
544 pn = (XvVideoNotifyPtr)LookupIDByType(pDraw->id, XvRTVideoNotifyList);
546 while (pn)
548 if (pn->client)
550 event.u.u.type = XvEventBase + XvVideoNotify;
551 event.u.u.sequenceNumber = pn->client->sequence;
552 event.u.videoNotify.time = currentTime.milliseconds;
553 event.u.videoNotify.drawable = pDraw->id;
554 event.u.videoNotify.port = pPort->id;
555 event.u.videoNotify.reason = reason;
556 (void) TryClientEvents(pn->client, (xEventPtr)&event, 1, NoEventMask,
557 NoEventMask, NullGrab);
559 pn = pn->next;
562 return Success;
568 XvdiSendPortNotify(
569 XvPortPtr pPort,
570 Atom attribute,
571 INT32 value
573 xvEvent event;
574 XvPortNotifyPtr pn;
576 pn = pPort->pNotify;
578 while (pn)
580 if (pn->client)
582 event.u.u.type = XvEventBase + XvPortNotify;
583 event.u.u.sequenceNumber = pn->client->sequence;
584 event.u.portNotify.time = currentTime.milliseconds;
585 event.u.portNotify.port = pPort->id;
586 event.u.portNotify.attribute = attribute;
587 event.u.portNotify.value = value;
588 (void) TryClientEvents(pn->client, (xEventPtr)&event, 1, NoEventMask,
589 NoEventMask, NullGrab);
591 pn = pn->next;
594 return Success;
599 #define CHECK_SIZE(dw, dh, sw, sh) { \
600 if(!dw || !dh || !sw || !sh) return Success; \
601 /* The region code will break these if they are too large */ \
602 if((dw > 32767) || (dh > 32767) || (sw > 32767) || (sh > 32767)) \
603 return BadValue; \
608 XvdiPutVideo(
609 ClientPtr client,
610 DrawablePtr pDraw,
611 XvPortPtr pPort,
612 GCPtr pGC,
613 INT16 vid_x, INT16 vid_y,
614 CARD16 vid_w, CARD16 vid_h,
615 INT16 drw_x, INT16 drw_y,
616 CARD16 drw_w, CARD16 drw_h
618 DrawablePtr pOldDraw;
620 CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
622 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
624 UpdateCurrentTime();
626 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
627 INFORM CLIENT OF ITS FAILURE */
629 if (pPort->grab.client && (pPort->grab.client != client))
631 XvdiSendVideoNotify(pPort, pDraw, XvBusy);
632 return Success;
635 /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
636 EVENTS TO ANY CLIENTS WHO WANT THEM */
638 pOldDraw = pPort->pDraw;
639 if ((pOldDraw) && (pOldDraw != pDraw))
641 XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
644 (void) (* pPort->pAdaptor->ddPutVideo)(client, pDraw, pPort, pGC,
645 vid_x, vid_y, vid_w, vid_h,
646 drw_x, drw_y, drw_w, drw_h);
648 if ((pPort->pDraw) && (pOldDraw != pDraw))
650 pPort->client = client;
651 XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
654 pPort->time = currentTime;
656 return (Success);
661 XvdiPutStill(
662 ClientPtr client,
663 DrawablePtr pDraw,
664 XvPortPtr pPort,
665 GCPtr pGC,
666 INT16 vid_x, INT16 vid_y,
667 CARD16 vid_w, CARD16 vid_h,
668 INT16 drw_x, INT16 drw_y,
669 CARD16 drw_w, CARD16 drw_h
671 int status;
673 CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
675 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
677 UpdateCurrentTime();
679 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
680 INFORM CLIENT OF ITS FAILURE */
682 if (pPort->grab.client && (pPort->grab.client != client))
684 XvdiSendVideoNotify(pPort, pDraw, XvBusy);
685 return Success;
688 pPort->time = currentTime;
690 status = (* pPort->pAdaptor->ddPutStill)(client, pDraw, pPort, pGC,
691 vid_x, vid_y, vid_w, vid_h,
692 drw_x, drw_y, drw_w, drw_h);
694 return status;
699 XvdiPutImage(
700 ClientPtr client,
701 DrawablePtr pDraw,
702 XvPortPtr pPort,
703 GCPtr pGC,
704 INT16 src_x, INT16 src_y,
705 CARD16 src_w, CARD16 src_h,
706 INT16 drw_x, INT16 drw_y,
707 CARD16 drw_w, CARD16 drw_h,
708 XvImagePtr image,
709 unsigned char* data,
710 Bool sync,
711 CARD16 width, CARD16 height
713 CHECK_SIZE(drw_w, drw_h, src_w, src_h);
715 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
717 UpdateCurrentTime();
719 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
720 INFORM CLIENT OF ITS FAILURE */
722 if (pPort->grab.client && (pPort->grab.client != client))
724 XvdiSendVideoNotify(pPort, pDraw, XvBusy);
725 return Success;
728 pPort->time = currentTime;
730 return (* pPort->pAdaptor->ddPutImage)(client, pDraw, pPort, pGC,
731 src_x, src_y, src_w, src_h,
732 drw_x, drw_y, drw_w, drw_h,
733 image, data, sync, width, height);
738 XvdiGetVideo(
739 ClientPtr client,
740 DrawablePtr pDraw,
741 XvPortPtr pPort,
742 GCPtr pGC,
743 INT16 vid_x, INT16 vid_y,
744 CARD16 vid_w, CARD16 vid_h,
745 INT16 drw_x, INT16 drw_y,
746 CARD16 drw_w, CARD16 drw_h
748 DrawablePtr pOldDraw;
750 CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
752 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
754 UpdateCurrentTime();
756 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
757 INFORM CLIENT OF ITS FAILURE */
759 if (pPort->grab.client && (pPort->grab.client != client))
761 XvdiSendVideoNotify(pPort, pDraw, XvBusy);
762 return Success;
765 /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
766 EVENTS TO ANY CLIENTS WHO WANT THEM */
768 pOldDraw = pPort->pDraw;
769 if ((pOldDraw) && (pOldDraw != pDraw))
771 XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
774 (void) (* pPort->pAdaptor->ddGetVideo)(client, pDraw, pPort, pGC,
775 vid_x, vid_y, vid_w, vid_h,
776 drw_x, drw_y, drw_w, drw_h);
778 if ((pPort->pDraw) && (pOldDraw != pDraw))
780 pPort->client = client;
781 XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
784 pPort->time = currentTime;
786 return (Success);
791 XvdiGetStill(
792 ClientPtr client,
793 DrawablePtr pDraw,
794 XvPortPtr pPort,
795 GCPtr pGC,
796 INT16 vid_x, INT16 vid_y,
797 CARD16 vid_w, CARD16 vid_h,
798 INT16 drw_x, INT16 drw_y,
799 CARD16 drw_w, CARD16 drw_h
801 int status;
803 CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
805 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
807 UpdateCurrentTime();
809 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
810 INFORM CLIENT OF ITS FAILURE */
812 if (pPort->grab.client && (pPort->grab.client != client))
814 XvdiSendVideoNotify(pPort, pDraw, XvBusy);
815 return Success;
818 status = (* pPort->pAdaptor->ddGetStill)(client, pDraw, pPort, pGC,
819 vid_x, vid_y, vid_w, vid_h,
820 drw_x, drw_y, drw_w, drw_h);
822 pPort->time = currentTime;
824 return status;
829 XvdiGrabPort(
830 ClientPtr client,
831 XvPortPtr pPort,
832 Time ctime,
833 int *p_result
835 unsigned long id;
836 TimeStamp time;
838 UpdateCurrentTime();
839 time = ClientTimeToServerTime(ctime);
841 if (pPort->grab.client && (client != pPort->grab.client))
843 *p_result = XvAlreadyGrabbed;
844 return Success;
847 if ((CompareTimeStamps(time, currentTime) == LATER) ||
848 (CompareTimeStamps(time, pPort->time) == EARLIER))
850 *p_result = XvInvalidTime;
851 return Success;
854 if (client == pPort->grab.client)
856 *p_result = Success;
857 return Success;
860 id = FakeClientID(client->index);
862 if (!AddResource(id, XvRTGrab, &pPort->grab))
864 return BadAlloc;
867 /* IF THERE IS ACTIVE VIDEO THEN STOP IT */
869 if ((pPort->pDraw) && (client != pPort->client))
871 XVCALL(diStopVideo)((ClientPtr)NULL, pPort, pPort->pDraw);
874 pPort->grab.client = client;
875 pPort->grab.id = id;
877 pPort->time = currentTime;
879 *p_result = Success;
881 return Success;
886 XvdiUngrabPort(
887 ClientPtr client,
888 XvPortPtr pPort,
889 Time ctime
891 TimeStamp time;
893 UpdateCurrentTime();
894 time = ClientTimeToServerTime(ctime);
896 if ((!pPort->grab.client) || (client != pPort->grab.client))
898 return Success;
901 if ((CompareTimeStamps(time, currentTime) == LATER) ||
902 (CompareTimeStamps(time, pPort->time) == EARLIER))
904 return Success;
907 /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */
909 FreeResource(pPort->grab.id, XvRTGrab);
910 pPort->grab.client = (ClientPtr)NULL;
912 pPort->time = currentTime;
914 return Success;
920 XvdiSelectVideoNotify(
921 ClientPtr client,
922 DrawablePtr pDraw,
923 BOOL onoff
925 XvVideoNotifyPtr pn,tpn,fpn;
927 /* FIND VideoNotify LIST */
929 pn = (XvVideoNotifyPtr)LookupIDByType(pDraw->id, XvRTVideoNotifyList);
931 /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */
933 if (!onoff && !pn) return Success;
935 /* IF ONE DOESN'T EXIST CREATE IT AND ADD A RESOURCE SO THAT THE LIST
936 WILL BE DELETED WHEN THE DRAWABLE IS DESTROYED */
938 if (!pn)
940 if (!(tpn = (XvVideoNotifyPtr)xalloc(sizeof(XvVideoNotifyRec))))
941 return BadAlloc;
942 tpn->next = (XvVideoNotifyPtr)NULL;
943 if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn))
945 xfree(tpn);
946 return BadAlloc;
949 else
951 /* LOOK TO SEE IF ENTRY ALREADY EXISTS */
953 fpn = (XvVideoNotifyPtr)NULL;
954 tpn = pn;
955 while (tpn)
957 if (tpn->client == client)
959 if (!onoff) tpn->client = (ClientPtr)NULL;
960 return Success;
962 if (!tpn->client) fpn = tpn; /* TAKE NOTE OF FREE ENTRY */
963 tpn = tpn->next;
966 /* IF TUNNING OFF, THEN JUST RETURN */
968 if (!onoff) return Success;
970 /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */
972 if (fpn)
974 tpn = fpn;
976 else
978 if (!(tpn = (XvVideoNotifyPtr)xalloc(sizeof(XvVideoNotifyRec))))
979 return BadAlloc;
980 tpn->next = pn->next;
981 pn->next = tpn;
985 /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */
986 /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */
988 tpn->client = (ClientPtr)NULL;
989 tpn->id = FakeClientID(client->index);
990 AddResource(tpn->id, XvRTVideoNotify, tpn);
992 tpn->client = client;
993 return Success;
998 XvdiSelectPortNotify(
999 ClientPtr client,
1000 XvPortPtr pPort,
1001 BOOL onoff
1003 XvPortNotifyPtr pn,tpn;
1005 /* SEE IF CLIENT IS ALREADY IN LIST */
1007 tpn = (XvPortNotifyPtr)NULL;
1008 pn = pPort->pNotify;
1009 while (pn)
1011 if (!pn->client) tpn = pn; /* TAKE NOTE OF FREE ENTRY */
1012 if (pn->client == client) break;
1013 pn = pn->next;
1016 /* IS THE CLIENT ALREADY ON THE LIST? */
1018 if (pn)
1020 /* REMOVE IT? */
1022 if (!onoff)
1024 pn->client = (ClientPtr)NULL;
1025 FreeResource(pn->id, XvRTPortNotify);
1028 return Success;
1031 /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE
1032 CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */
1034 if (!tpn)
1036 if (!(tpn = (XvPortNotifyPtr)xalloc(sizeof(XvPortNotifyRec))))
1037 return BadAlloc;
1038 tpn->next = pPort->pNotify;
1039 pPort->pNotify = tpn;
1042 tpn->client = client;
1043 tpn->id = FakeClientID(client->index);
1044 AddResource(tpn->id, XvRTPortNotify, tpn);
1046 return Success;
1051 XvdiStopVideo(
1052 ClientPtr client,
1053 XvPortPtr pPort,
1054 DrawablePtr pDraw
1056 int status;
1058 /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
1060 if (!pPort->pDraw || (pPort->pDraw != pDraw))
1062 XvdiSendVideoNotify(pPort, pDraw, XvStopped);
1063 return Success;
1066 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
1067 INFORM CLIENT OF ITS FAILURE */
1069 if ((client) && (pPort->grab.client) && (pPort->grab.client != client))
1071 XvdiSendVideoNotify(pPort, pDraw, XvBusy);
1072 return Success;
1075 XvdiSendVideoNotify(pPort, pDraw, XvStopped);
1077 status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pDraw);
1079 pPort->pDraw = (DrawablePtr)NULL;
1080 pPort->client = (ClientPtr)client;
1081 pPort->time = currentTime;
1083 return status;
1088 XvdiPreemptVideo(
1089 ClientPtr client,
1090 XvPortPtr pPort,
1091 DrawablePtr pDraw
1093 int status;
1095 /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
1097 if (!pPort->pDraw || (pPort->pDraw != pDraw)) return Success;
1099 XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
1101 status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pPort->pDraw);
1103 pPort->pDraw = (DrawablePtr)NULL;
1104 pPort->client = (ClientPtr)client;
1105 pPort->time = currentTime;
1107 return status;
1112 XvdiMatchPort(
1113 XvPortPtr pPort,
1114 DrawablePtr pDraw
1117 XvAdaptorPtr pa;
1118 XvFormatPtr pf;
1119 int nf;
1121 pa = pPort->pAdaptor;
1123 if (pa->pScreen != pDraw->pScreen) return BadMatch;
1125 nf = pa->nFormats;
1126 pf = pa->pFormats;
1128 while (nf--)
1130 if ((pf->depth == pDraw->depth)
1131 #if 0
1132 && ((pDraw->type == DRAWABLE_PIXMAP) ||
1133 (wVisual(((WindowPtr)pDraw)) == pf->visual))
1134 #endif
1136 return Success;
1137 pf++;
1140 return BadMatch;
1145 XvdiSetPortAttribute(
1146 ClientPtr client,
1147 XvPortPtr pPort,
1148 Atom attribute,
1149 INT32 value
1152 XvdiSendPortNotify(pPort, attribute, value);
1154 return
1155 (* pPort->pAdaptor->ddSetPortAttribute)(client, pPort, attribute, value);
1160 XvdiGetPortAttribute(
1161 ClientPtr client,
1162 XvPortPtr pPort,
1163 Atom attribute,
1164 INT32 *p_value
1167 return
1168 (* pPort->pAdaptor->ddGetPortAttribute)(client, pPort, attribute, p_value);
1172 static void
1173 WriteSwappedVideoNotifyEvent(xvEvent *from, xvEvent *to)
1177 to->u.u.type = from->u.u.type;
1178 to->u.u.detail = from->u.u.detail;
1179 cpswaps(from->u.videoNotify.sequenceNumber,
1180 to->u.videoNotify.sequenceNumber);
1181 cpswapl(from->u.videoNotify.time, to->u.videoNotify.time);
1182 cpswapl(from->u.videoNotify.drawable, to->u.videoNotify.drawable);
1183 cpswapl(from->u.videoNotify.port, to->u.videoNotify.port);
1187 static void
1188 WriteSwappedPortNotifyEvent(xvEvent *from, xvEvent *to)
1192 to->u.u.type = from->u.u.type;
1193 to->u.u.detail = from->u.u.detail;
1194 cpswaps(from->u.portNotify.sequenceNumber, to->u.portNotify.sequenceNumber);
1195 cpswapl(from->u.portNotify.time, to->u.portNotify.time);
1196 cpswapl(from->u.portNotify.port, to->u.portNotify.port);
1197 cpswapl(from->u.portNotify.value, to->u.portNotify.value);