1 /***********************************************************
2 Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
3 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
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
23 ******************************************************************/
28 ** xvmain.c --- Xv server extension main device independent module.
32 ** David Carver (Digital Workstation Engineering/Project Athena)
37 ** - change: stop video always generates an event even when video
41 ** - change: unrealizing windows no longer preempts video
44 ** - changed SetPortControl to SetPortAttribute
45 ** - changed GetPortControl to GetPortAttribute
46 ** - changed QueryBestSize
49 ** - fixed Put and Get requests to not preempt operations to same drawable
52 ** - version 2.0 upgrade
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.
60 ** - version 1.4 upgrade
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>
83 #include <X11/Xproto.h>
86 #include "scrnintstr.h"
87 #include "windowstr.h"
88 #include "pixmapstr.h"
90 #include "extnsionst.h"
91 #include "dixstruct.h"
98 #include <X11/extensions/Xv.h>
99 #include <X11/extensions/Xvproto.h>
103 #include "panoramiX.h"
104 #include "panoramiXsrv.h"
108 int XvScreenIndex
= -1;
109 unsigned long XvExtensionGeneration
= 0;
110 unsigned long XvScreenGeneration
= 0;
111 unsigned long XvResourceGeneration
= 0;
117 unsigned long XvRTPort
;
118 unsigned long XvRTEncoding
;
119 unsigned long XvRTGrab
;
120 unsigned long XvRTVideoNotify
;
121 unsigned long XvRTVideoNotifyList
;
122 unsigned long XvRTPortNotify
;
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);
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");
169 XvScreenIndex
= AllocateScreenPrivateIndex ();
170 if (XvScreenIndex
< 0)
172 ErrorF("XvExtensionInit: Unable to allocate screen private index\n");
176 XineramaRegisterConnectionBlockCallback(XineramifyXv
);
178 XvScreenGeneration
= serverGeneration
;
181 if (XvExtensionGeneration
!= serverGeneration
)
183 XvExtensionGeneration
= serverGeneration
;
185 extEntry
= AddExtension(XvName
, XvNumEvents
, XvNumErrors
,
186 ProcXvDispatch
, SProcXvDispatch
,
187 XvResetProc
, StandardMinorOpcode
);
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
);
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");
222 if (!(XvRTGrab
= CreateNewResourceType(XvdiDestroyGrab
)))
224 ErrorF("CreateResourceTypes: failed to allocate grab resource.\n");
228 if (!(XvRTEncoding
= CreateNewResourceType(XvdiDestroyEncoding
)))
230 ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n");
234 if (!(XvRTVideoNotify
= CreateNewResourceType(XvdiDestroyVideoNotify
)))
236 ErrorF("CreateResourceTypes: failed to allocate video notify resource.\n");
240 if (!(XvRTVideoNotifyList
= CreateNewResourceType(XvdiDestroyVideoNotifyList
)))
242 ErrorF("CreateResourceTypes: failed to allocate video notify list resource.\n");
246 if (!(XvRTPortNotify
= CreateNewResourceType(XvdiDestroyPortNotify
)))
248 ErrorF("CreateResourceTypes: failed to allocate port notify resource.\n");
257 XvScreenInit(ScreenPtr pScreen
)
261 if (XvScreenGeneration
!= serverGeneration
)
263 if (!CreateResourceTypes())
265 ErrorF("XvScreenInit: Unable to allocate resource types\n");
268 XvScreenIndex
= AllocateScreenPrivateIndex ();
269 if (XvScreenIndex
< 0)
271 ErrorF("XvScreenInit: Unable to allocate screen private index\n");
275 XineramaRegisterConnectionBlockCallback(XineramifyXv
);
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
));
290 ErrorF("XvScreenInit: Unable to allocate screen private structure\n");
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
;
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
);
326 pScreen
->devPrivates
[XvScreenIndex
].ptr
= (pointer
)NULL
;
328 return (*pScreen
->CloseScreen
)(ii
, pScreen
);
333 XvResetProc(ExtensionEntry
* extEntry
)
338 XvGetScreenIndex(void)
340 return XvScreenIndex
;
343 _X_EXPORT
unsigned long
350 XvDestroyPixmap(PixmapPtr pPix
)
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
;
377 if (pp
->pDraw
== (DrawablePtr
)pPix
)
379 XvdiSendVideoNotify(pp
, pp
->pDraw
, XvPreempted
);
381 (void)(* pp
->pAdaptor
->ddStopVideo
)((ClientPtr
)NULL
, pp
,
384 pp
->pDraw
= (DrawablePtr
)NULL
;
385 pp
->client
= (ClientPtr
)NULL
;
386 pp
->time
= currentTime
;
393 status
= (* pScreen
->DestroyPixmap
)(pPix
);
395 SCREEN_EPILOGUE(pScreen
, DestroyPixmap
, XvDestroyPixmap
);
402 XvDestroyWindow(WindowPtr pWin
)
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
;
429 if (pp
->pDraw
== (DrawablePtr
)pWin
)
431 XvdiSendVideoNotify(pp
, pp
->pDraw
, XvPreempted
);
433 (void)(* pp
->pAdaptor
->ddStopVideo
)((ClientPtr
)NULL
, pp
,
436 pp
->pDraw
= (DrawablePtr
)NULL
;
437 pp
->client
= (ClientPtr
)NULL
;
438 pp
->time
= currentTime
;
446 status
= (* pScreen
->DestroyWindow
)(pWin
);
448 SCREEN_EPILOGUE(pScreen
, DestroyWindow
, XvDestroyWindow
);
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
;
478 XvdiDestroyPort(pointer pPort
, XID id
)
480 return (* ((XvPortPtr
)pPort
)->pAdaptor
->ddFreePort
)(pPort
);
484 XvdiDestroyGrab(pointer pGrab
, XID id
)
486 ((XvGrabPtr
)pGrab
)->client
= (ClientPtr
)NULL
;
491 XvdiDestroyVideoNotify(pointer pn
, XID id
)
493 /* JUST CLEAR OUT THE client POINTER FIELD */
495 ((XvVideoNotifyPtr
)pn
)->client
= (ClientPtr
)NULL
;
500 XvdiDestroyPortNotify(pointer pn
, XID id
)
502 /* JUST CLEAR OUT THE client POINTER FIELD */
504 ((XvPortNotifyPtr
)pn
)->client
= (ClientPtr
)NULL
;
509 XvdiDestroyVideoNotifyList(pointer pn
, XID id
)
511 XvVideoNotifyPtr npn
,cpn
;
513 /* ACTUALLY DESTROY THE NOTITY LIST */
515 cpn
= (XvVideoNotifyPtr
)pn
;
520 if (cpn
->client
) FreeResource(cpn
->id
, XvRTVideoNotify
);
528 XvdiDestroyEncoding(pointer value
, XID id
)
534 XvdiSendVideoNotify(pPort
, pDraw
, reason
)
544 pn
= (XvVideoNotifyPtr
)LookupIDByType(pDraw
->id
, XvRTVideoNotifyList
);
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
);
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
);
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)) \
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 */
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
);
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
;
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
673 CHECK_SIZE(drw_w
, drw_h
, vid_w
, vid_h
);
675 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
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
);
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
);
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
,
711 CARD16 width
, CARD16 height
713 CHECK_SIZE(drw_w
, drw_h
, src_w
, src_h
);
715 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
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
);
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
);
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 */
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
);
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
;
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
803 CHECK_SIZE(drw_w
, drw_h
, vid_w
, vid_h
);
805 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
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
);
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
;
839 time
= ClientTimeToServerTime(ctime
);
841 if (pPort
->grab
.client
&& (client
!= pPort
->grab
.client
))
843 *p_result
= XvAlreadyGrabbed
;
847 if ((CompareTimeStamps(time
, currentTime
) == LATER
) ||
848 (CompareTimeStamps(time
, pPort
->time
) == EARLIER
))
850 *p_result
= XvInvalidTime
;
854 if (client
== pPort
->grab
.client
)
860 id
= FakeClientID(client
->index
);
862 if (!AddResource(id
, XvRTGrab
, &pPort
->grab
))
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
;
877 pPort
->time
= currentTime
;
894 time
= ClientTimeToServerTime(ctime
);
896 if ((!pPort
->grab
.client
) || (client
!= pPort
->grab
.client
))
901 if ((CompareTimeStamps(time
, currentTime
) == LATER
) ||
902 (CompareTimeStamps(time
, pPort
->time
) == EARLIER
))
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
;
920 XvdiSelectVideoNotify(
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 */
940 if (!(tpn
= (XvVideoNotifyPtr
)xalloc(sizeof(XvVideoNotifyRec
))))
942 tpn
->next
= (XvVideoNotifyPtr
)NULL
;
943 if (!AddResource(pDraw
->id
, XvRTVideoNotifyList
, tpn
))
951 /* LOOK TO SEE IF ENTRY ALREADY EXISTS */
953 fpn
= (XvVideoNotifyPtr
)NULL
;
957 if (tpn
->client
== client
)
959 if (!onoff
) tpn
->client
= (ClientPtr
)NULL
;
962 if (!tpn
->client
) fpn
= tpn
; /* TAKE NOTE OF FREE ENTRY */
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 */
978 if (!(tpn
= (XvVideoNotifyPtr
)xalloc(sizeof(XvVideoNotifyRec
))))
980 tpn
->next
= pn
->next
;
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
;
998 XvdiSelectPortNotify(
1003 XvPortNotifyPtr pn
,tpn
;
1005 /* SEE IF CLIENT IS ALREADY IN LIST */
1007 tpn
= (XvPortNotifyPtr
)NULL
;
1008 pn
= pPort
->pNotify
;
1011 if (!pn
->client
) tpn
= pn
; /* TAKE NOTE OF FREE ENTRY */
1012 if (pn
->client
== client
) break;
1016 /* IS THE CLIENT ALREADY ON THE LIST? */
1024 pn
->client
= (ClientPtr
)NULL
;
1025 FreeResource(pn
->id
, XvRTPortNotify
);
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 */
1036 if (!(tpn
= (XvPortNotifyPtr
)xalloc(sizeof(XvPortNotifyRec
))))
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
);
1058 /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
1060 if (!pPort
->pDraw
|| (pPort
->pDraw
!= pDraw
))
1062 XvdiSendVideoNotify(pPort
, pDraw
, XvStopped
);
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
);
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
;
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
;
1121 pa
= pPort
->pAdaptor
;
1123 if (pa
->pScreen
!= pDraw
->pScreen
) return BadMatch
;
1130 if ((pf
->depth
== pDraw
->depth
)
1132 && ((pDraw
->type
== DRAWABLE_PIXMAP
) ||
1133 (wVisual(((WindowPtr
)pDraw
)) == pf
->visual
))
1145 XvdiSetPortAttribute(
1152 XvdiSendPortNotify(pPort
, attribute
, value
);
1155 (* pPort
->pAdaptor
->ddSetPortAttribute
)(client
, pPort
, attribute
, value
);
1160 XvdiGetPortAttribute(
1168 (* pPort
->pAdaptor
->ddGetPortAttribute
)(client
, pPort
, attribute
, p_value
);
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
);
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
);