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"
92 #include "dixstruct.h"
99 #include <X11/extensions/Xv.h>
100 #include <X11/extensions/Xvproto.h>
104 #include "panoramiX.h"
105 #include "panoramiXsrv.h"
109 static DevPrivateKeyRec XvScreenKeyRec
;
111 #define XvScreenKey (&XvScreenKeyRec)
112 unsigned long XvExtensionGeneration
= 0;
113 unsigned long XvScreenGeneration
= 0;
114 unsigned long XvResourceGeneration
= 0;
121 RESTYPE XvRTEncoding
;
123 RESTYPE XvRTVideoNotify
;
124 RESTYPE XvRTVideoNotifyList
;
125 RESTYPE XvRTPortNotify
;
129 static void WriteSwappedVideoNotifyEvent(xvEvent
*, xvEvent
*);
130 static void WriteSwappedPortNotifyEvent(xvEvent
*, xvEvent
*);
131 static Bool
CreateResourceTypes(void);
133 static Bool
XvCloseScreen(ScreenPtr
);
134 static Bool
XvDestroyPixmap(PixmapPtr
);
135 static Bool
XvDestroyWindow(WindowPtr
);
136 static void XvResetProc(ExtensionEntry
*);
137 static int XvdiDestroyGrab(pointer
, XID
);
138 static int XvdiDestroyEncoding(pointer
, XID
);
139 static int XvdiDestroyVideoNotify(pointer
, XID
);
140 static int XvdiDestroyPortNotify(pointer
, XID
);
141 static int XvdiDestroyVideoNotifyList(pointer
, XID
);
142 static int XvdiDestroyPort(pointer
, XID
);
143 static int XvdiSendVideoNotify(XvPortPtr
, DrawablePtr
, int);
152 XvExtensionInit(void)
154 ExtensionEntry
*extEntry
;
156 if (!dixRegisterPrivateKey(&XvScreenKeyRec
, PRIVATE_SCREEN
, 0))
159 /* Look to see if any screens were initialized; if not then
160 init global variables so the extension can function */
161 if (XvScreenGeneration
!= serverGeneration
) {
162 if (!CreateResourceTypes()) {
163 ErrorF("XvExtensionInit: Unable to allocate resource types\n");
167 XineramaRegisterConnectionBlockCallback(XineramifyXv
);
169 XvScreenGeneration
= serverGeneration
;
172 if (XvExtensionGeneration
!= serverGeneration
) {
173 XvExtensionGeneration
= serverGeneration
;
175 extEntry
= AddExtension(XvName
, XvNumEvents
, XvNumErrors
,
176 ProcXvDispatch
, SProcXvDispatch
,
177 XvResetProc
, StandardMinorOpcode
);
179 FatalError("XvExtensionInit: AddExtensions failed\n");
182 XvReqCode
= extEntry
->base
;
183 XvEventBase
= extEntry
->eventBase
;
184 XvErrorBase
= extEntry
->errorBase
;
186 EventSwapVector
[XvEventBase
+ XvVideoNotify
] =
187 (EventSwapPtr
) WriteSwappedVideoNotifyEvent
;
188 EventSwapVector
[XvEventBase
+ XvPortNotify
] =
189 (EventSwapPtr
) WriteSwappedPortNotifyEvent
;
191 SetResourceTypeErrorValue(XvRTPort
, _XvBadPort
);
192 (void) MakeAtom(XvName
, strlen(XvName
), xTrue
);
198 CreateResourceTypes(void)
201 if (XvResourceGeneration
== serverGeneration
)
204 XvResourceGeneration
= serverGeneration
;
206 if (!(XvRTPort
= CreateNewResourceType(XvdiDestroyPort
, "XvRTPort"))) {
207 ErrorF("CreateResourceTypes: failed to allocate port resource.\n");
211 if (!(XvRTGrab
= CreateNewResourceType(XvdiDestroyGrab
, "XvRTGrab"))) {
212 ErrorF("CreateResourceTypes: failed to allocate grab resource.\n");
216 if (!(XvRTEncoding
= CreateNewResourceType(XvdiDestroyEncoding
,
218 ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n");
222 if (!(XvRTVideoNotify
= CreateNewResourceType(XvdiDestroyVideoNotify
,
223 "XvRTVideoNotify"))) {
225 ("CreateResourceTypes: failed to allocate video notify resource.\n");
230 (XvRTVideoNotifyList
=
231 CreateNewResourceType(XvdiDestroyVideoNotifyList
,
232 "XvRTVideoNotifyList"))) {
234 ("CreateResourceTypes: failed to allocate video notify list resource.\n");
238 if (!(XvRTPortNotify
= CreateNewResourceType(XvdiDestroyPortNotify
,
239 "XvRTPortNotify"))) {
241 ("CreateResourceTypes: failed to allocate port notify resource.\n");
250 XvScreenInit(ScreenPtr pScreen
)
254 if (XvScreenGeneration
!= serverGeneration
) {
255 if (!CreateResourceTypes()) {
256 ErrorF("XvScreenInit: Unable to allocate resource types\n");
260 XineramaRegisterConnectionBlockCallback(XineramifyXv
);
262 XvScreenGeneration
= serverGeneration
;
265 if (!dixRegisterPrivateKey(&XvScreenKeyRec
, PRIVATE_SCREEN
, 0))
268 if (dixLookupPrivate(&pScreen
->devPrivates
, XvScreenKey
)) {
269 ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n");
272 /* ALLOCATE SCREEN PRIVATE RECORD */
274 pxvs
= malloc(sizeof(XvScreenRec
));
276 ErrorF("XvScreenInit: Unable to allocate screen private structure\n");
280 dixSetPrivate(&pScreen
->devPrivates
, XvScreenKey
, pxvs
);
282 pxvs
->DestroyPixmap
= pScreen
->DestroyPixmap
;
283 pxvs
->DestroyWindow
= pScreen
->DestroyWindow
;
284 pxvs
->CloseScreen
= pScreen
->CloseScreen
;
286 pScreen
->DestroyPixmap
= XvDestroyPixmap
;
287 pScreen
->DestroyWindow
= XvDestroyWindow
;
288 pScreen
->CloseScreen
= XvCloseScreen
;
294 XvCloseScreen(ScreenPtr pScreen
)
299 pxvs
= (XvScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
, XvScreenKey
);
301 pScreen
->DestroyPixmap
= pxvs
->DestroyPixmap
;
302 pScreen
->DestroyWindow
= pxvs
->DestroyWindow
;
303 pScreen
->CloseScreen
= pxvs
->CloseScreen
;
305 (*pxvs
->ddCloseScreen
) (pScreen
);
309 dixSetPrivate(&pScreen
->devPrivates
, XvScreenKey
, NULL
);
311 return (*pScreen
->CloseScreen
) (pScreen
);
315 XvResetProc(ExtensionEntry
* extEntry
)
333 XvDestroyPixmap(PixmapPtr pPix
)
343 pScreen
= pPix
->drawable
.pScreen
;
345 SCREEN_PROLOGUE(pScreen
, DestroyPixmap
);
347 pxvs
= (XvScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
, XvScreenKey
);
349 /* CHECK TO SEE IF THIS PORT IS IN USE */
351 pa
= pxvs
->pAdaptors
;
352 na
= pxvs
->nAdaptors
;
358 if (pp
->pDraw
== (DrawablePtr
) pPix
) {
359 XvdiSendVideoNotify(pp
, pp
->pDraw
, XvPreempted
);
361 (void) (*pp
->pAdaptor
->ddStopVideo
) (NULL
, pp
, pp
->pDraw
);
365 pp
->time
= currentTime
;
372 status
= (*pScreen
->DestroyPixmap
) (pPix
);
374 SCREEN_EPILOGUE(pScreen
, DestroyPixmap
, XvDestroyPixmap
);
381 XvDestroyWindow(WindowPtr pWin
)
391 pScreen
= pWin
->drawable
.pScreen
;
393 SCREEN_PROLOGUE(pScreen
, DestroyWindow
);
395 pxvs
= (XvScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
, XvScreenKey
);
397 /* CHECK TO SEE IF THIS PORT IS IN USE */
399 pa
= pxvs
->pAdaptors
;
400 na
= pxvs
->nAdaptors
;
406 if (pp
->pDraw
== (DrawablePtr
) pWin
) {
407 XvdiSendVideoNotify(pp
, pp
->pDraw
, XvPreempted
);
409 (void) (*pp
->pAdaptor
->ddStopVideo
) (NULL
, pp
, pp
->pDraw
);
413 pp
->time
= currentTime
;
420 status
= (*pScreen
->DestroyWindow
) (pWin
);
422 SCREEN_EPILOGUE(pScreen
, DestroyWindow
, XvDestroyWindow
);
428 /* The XvdiVideoStopped procedure is a hook for the device dependent layer.
429 It provides a way for the dd layer to inform the di layer that video has
430 stopped in a port for reasons that the di layer had no control over; note
431 that it doesn't call back into the dd layer */
434 XvdiVideoStopped(XvPortPtr pPort
, int reason
)
437 /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
442 XvdiSendVideoNotify(pPort
, pPort
->pDraw
, reason
);
445 pPort
->client
= NULL
;
446 pPort
->time
= currentTime
;
453 XvdiDestroyPort(pointer pPort
, XID id
)
455 return (*((XvPortPtr
) pPort
)->pAdaptor
->ddFreePort
) (pPort
);
459 XvdiDestroyGrab(pointer pGrab
, XID id
)
461 ((XvGrabPtr
) pGrab
)->client
= NULL
;
466 XvdiDestroyVideoNotify(pointer pn
, XID id
)
468 /* JUST CLEAR OUT THE client POINTER FIELD */
470 ((XvVideoNotifyPtr
) pn
)->client
= NULL
;
475 XvdiDestroyPortNotify(pointer pn
, XID id
)
477 /* JUST CLEAR OUT THE client POINTER FIELD */
479 ((XvPortNotifyPtr
) pn
)->client
= NULL
;
484 XvdiDestroyVideoNotifyList(pointer pn
, XID id
)
486 XvVideoNotifyPtr npn
, cpn
;
488 /* ACTUALLY DESTROY THE NOTITY LIST */
490 cpn
= (XvVideoNotifyPtr
) pn
;
495 FreeResource(cpn
->id
, XvRTVideoNotify
);
503 XvdiDestroyEncoding(pointer value
, XID id
)
509 XvdiSendVideoNotify(XvPortPtr pPort
, DrawablePtr pDraw
, int reason
)
513 dixLookupResourceByType((pointer
*) &pn
, pDraw
->id
, XvRTVideoNotifyList
,
514 serverClient
, DixReadAccess
);
518 .u
.videoNotify
.reason
= reason
,
519 .u
.videoNotify
.time
= currentTime
.milliseconds
,
520 .u
.videoNotify
.drawable
= pDraw
->id
,
521 .u
.videoNotify
.port
= pPort
->id
523 event
.u
.u
.type
= XvEventBase
+ XvVideoNotify
;
524 WriteEventsToClient(pn
->client
, 1, (xEventPtr
) &event
);
533 XvdiSendPortNotify(XvPortPtr pPort
, Atom attribute
, INT32 value
)
541 .u
.portNotify
.time
= currentTime
.milliseconds
,
542 .u
.portNotify
.port
= pPort
->id
,
543 .u
.portNotify
.attribute
= attribute
,
544 .u
.portNotify
.value
= value
546 event
.u
.u
.type
= XvEventBase
+ XvPortNotify
;
547 WriteEventsToClient(pn
->client
, 1, (xEventPtr
) &event
);
555 #define CHECK_SIZE(dw, dh, sw, sh) { \
556 if(!dw || !dh || !sw || !sh) return Success; \
557 /* The region code will break these if they are too large */ \
558 if((dw > 32767) || (dh > 32767) || (sw > 32767) || (sh > 32767)) \
563 XvdiPutVideo(ClientPtr client
,
567 INT16 vid_x
, INT16 vid_y
,
568 CARD16 vid_w
, CARD16 vid_h
,
569 INT16 drw_x
, INT16 drw_y
, CARD16 drw_w
, CARD16 drw_h
)
571 DrawablePtr pOldDraw
;
573 CHECK_SIZE(drw_w
, drw_h
, vid_w
, vid_h
);
575 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
579 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
580 INFORM CLIENT OF ITS FAILURE */
582 if (pPort
->grab
.client
&& (pPort
->grab
.client
!= client
)) {
583 XvdiSendVideoNotify(pPort
, pDraw
, XvBusy
);
587 /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
588 EVENTS TO ANY CLIENTS WHO WANT THEM */
590 pOldDraw
= pPort
->pDraw
;
591 if ((pOldDraw
) && (pOldDraw
!= pDraw
)) {
592 XvdiSendVideoNotify(pPort
, pPort
->pDraw
, XvPreempted
);
595 (void) (*pPort
->pAdaptor
->ddPutVideo
) (client
, pDraw
, pPort
, pGC
,
596 vid_x
, vid_y
, vid_w
, vid_h
,
597 drw_x
, drw_y
, drw_w
, drw_h
);
599 if ((pPort
->pDraw
) && (pOldDraw
!= pDraw
)) {
600 pPort
->client
= client
;
601 XvdiSendVideoNotify(pPort
, pPort
->pDraw
, XvStarted
);
604 pPort
->time
= currentTime
;
611 XvdiPutStill(ClientPtr client
,
615 INT16 vid_x
, INT16 vid_y
,
616 CARD16 vid_w
, CARD16 vid_h
,
617 INT16 drw_x
, INT16 drw_y
, CARD16 drw_w
, CARD16 drw_h
)
621 CHECK_SIZE(drw_w
, drw_h
, vid_w
, vid_h
);
623 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
627 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
628 INFORM CLIENT OF ITS FAILURE */
630 if (pPort
->grab
.client
&& (pPort
->grab
.client
!= client
)) {
631 XvdiSendVideoNotify(pPort
, pDraw
, XvBusy
);
635 pPort
->time
= currentTime
;
637 status
= (*pPort
->pAdaptor
->ddPutStill
) (client
, pDraw
, pPort
, pGC
,
638 vid_x
, vid_y
, vid_w
, vid_h
,
639 drw_x
, drw_y
, drw_w
, drw_h
);
646 XvdiPutImage(ClientPtr client
,
650 INT16 src_x
, INT16 src_y
,
651 CARD16 src_w
, CARD16 src_h
,
652 INT16 drw_x
, INT16 drw_y
,
653 CARD16 drw_w
, CARD16 drw_h
,
655 unsigned char *data
, Bool sync
, CARD16 width
, CARD16 height
)
657 CHECK_SIZE(drw_w
, drw_h
, src_w
, src_h
);
659 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
663 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
664 INFORM CLIENT OF ITS FAILURE */
666 if (pPort
->grab
.client
&& (pPort
->grab
.client
!= client
)) {
667 XvdiSendVideoNotify(pPort
, pDraw
, XvBusy
);
671 pPort
->time
= currentTime
;
673 return (*pPort
->pAdaptor
->ddPutImage
) (client
, pDraw
, pPort
, pGC
,
674 src_x
, src_y
, src_w
, src_h
,
675 drw_x
, drw_y
, drw_w
, drw_h
,
676 image
, data
, sync
, width
, height
);
680 XvdiGetVideo(ClientPtr client
,
684 INT16 vid_x
, INT16 vid_y
,
685 CARD16 vid_w
, CARD16 vid_h
,
686 INT16 drw_x
, INT16 drw_y
, CARD16 drw_w
, CARD16 drw_h
)
688 DrawablePtr pOldDraw
;
690 CHECK_SIZE(drw_w
, drw_h
, vid_w
, vid_h
);
692 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
696 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
697 INFORM CLIENT OF ITS FAILURE */
699 if (pPort
->grab
.client
&& (pPort
->grab
.client
!= client
)) {
700 XvdiSendVideoNotify(pPort
, pDraw
, XvBusy
);
704 /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
705 EVENTS TO ANY CLIENTS WHO WANT THEM */
707 pOldDraw
= pPort
->pDraw
;
708 if ((pOldDraw
) && (pOldDraw
!= pDraw
)) {
709 XvdiSendVideoNotify(pPort
, pPort
->pDraw
, XvPreempted
);
712 (void) (*pPort
->pAdaptor
->ddGetVideo
) (client
, pDraw
, pPort
, pGC
,
713 vid_x
, vid_y
, vid_w
, vid_h
,
714 drw_x
, drw_y
, drw_w
, drw_h
);
716 if ((pPort
->pDraw
) && (pOldDraw
!= pDraw
)) {
717 pPort
->client
= client
;
718 XvdiSendVideoNotify(pPort
, pPort
->pDraw
, XvStarted
);
721 pPort
->time
= currentTime
;
728 XvdiGetStill(ClientPtr client
,
732 INT16 vid_x
, INT16 vid_y
,
733 CARD16 vid_w
, CARD16 vid_h
,
734 INT16 drw_x
, INT16 drw_y
, CARD16 drw_w
, CARD16 drw_h
)
738 CHECK_SIZE(drw_w
, drw_h
, vid_w
, vid_h
);
740 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
744 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
745 INFORM CLIENT OF ITS FAILURE */
747 if (pPort
->grab
.client
&& (pPort
->grab
.client
!= client
)) {
748 XvdiSendVideoNotify(pPort
, pDraw
, XvBusy
);
752 status
= (*pPort
->pAdaptor
->ddGetStill
) (client
, pDraw
, pPort
, pGC
,
753 vid_x
, vid_y
, vid_w
, vid_h
,
754 drw_x
, drw_y
, drw_w
, drw_h
);
756 pPort
->time
= currentTime
;
763 XvdiGrabPort(ClientPtr client
, XvPortPtr pPort
, Time ctime
, int *p_result
)
769 time
= ClientTimeToServerTime(ctime
);
771 if (pPort
->grab
.client
&& (client
!= pPort
->grab
.client
)) {
772 *p_result
= XvAlreadyGrabbed
;
776 if ((CompareTimeStamps(time
, currentTime
) == LATER
) ||
777 (CompareTimeStamps(time
, pPort
->time
) == EARLIER
)) {
778 *p_result
= XvInvalidTime
;
782 if (client
== pPort
->grab
.client
) {
787 id
= FakeClientID(client
->index
);
789 if (!AddResource(id
, XvRTGrab
, &pPort
->grab
)) {
793 /* IF THERE IS ACTIVE VIDEO THEN STOP IT */
795 if ((pPort
->pDraw
) && (client
!= pPort
->client
)) {
796 XvdiStopVideo(NULL
, pPort
, pPort
->pDraw
);
799 pPort
->grab
.client
= client
;
802 pPort
->time
= currentTime
;
811 XvdiUngrabPort(ClientPtr client
, XvPortPtr pPort
, Time ctime
)
816 time
= ClientTimeToServerTime(ctime
);
818 if ((!pPort
->grab
.client
) || (client
!= pPort
->grab
.client
)) {
822 if ((CompareTimeStamps(time
, currentTime
) == LATER
) ||
823 (CompareTimeStamps(time
, pPort
->time
) == EARLIER
)) {
827 /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */
829 FreeResource(pPort
->grab
.id
, XvRTGrab
);
830 pPort
->grab
.client
= NULL
;
832 pPort
->time
= currentTime
;
839 XvdiSelectVideoNotify(ClientPtr client
, DrawablePtr pDraw
, BOOL onoff
)
841 XvVideoNotifyPtr pn
, tpn
, fpn
;
844 /* FIND VideoNotify LIST */
846 rc
= dixLookupResourceByType((pointer
*) &pn
, pDraw
->id
,
847 XvRTVideoNotifyList
, client
, DixWriteAccess
);
848 if (rc
!= Success
&& rc
!= BadValue
)
851 /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */
856 /* IF ONE DOESN'T EXIST CREATE IT AND ADD A RESOURCE SO THAT THE LIST
857 WILL BE DELETED WHEN THE DRAWABLE IS DESTROYED */
860 if (!(tpn
= malloc(sizeof(XvVideoNotifyRec
))))
863 if (!AddResource(pDraw
->id
, XvRTVideoNotifyList
, tpn
)) {
869 /* LOOK TO SEE IF ENTRY ALREADY EXISTS */
874 if (tpn
->client
== client
) {
880 fpn
= tpn
; /* TAKE NOTE OF FREE ENTRY */
884 /* IF TUNNING OFF, THEN JUST RETURN */
889 /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */
895 if (!(tpn
= malloc(sizeof(XvVideoNotifyRec
))))
897 tpn
->next
= pn
->next
;
902 /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */
903 /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */
906 tpn
->id
= FakeClientID(client
->index
);
907 AddResource(tpn
->id
, XvRTVideoNotify
, tpn
);
909 tpn
->client
= client
;
915 XvdiSelectPortNotify(ClientPtr client
, XvPortPtr pPort
, BOOL onoff
)
917 XvPortNotifyPtr pn
, tpn
;
919 /* SEE IF CLIENT IS ALREADY IN LIST */
925 tpn
= pn
; /* TAKE NOTE OF FREE ENTRY */
926 if (pn
->client
== client
)
931 /* IS THE CLIENT ALREADY ON THE LIST? */
938 FreeResource(pn
->id
, XvRTPortNotify
);
944 /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE
945 CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */
948 if (!(tpn
= malloc(sizeof(XvPortNotifyRec
))))
950 tpn
->next
= pPort
->pNotify
;
951 pPort
->pNotify
= tpn
;
954 tpn
->client
= client
;
955 tpn
->id
= FakeClientID(client
->index
);
956 AddResource(tpn
->id
, XvRTPortNotify
, tpn
);
963 XvdiStopVideo(ClientPtr client
, XvPortPtr pPort
, DrawablePtr pDraw
)
967 /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
969 if (!pPort
->pDraw
|| (pPort
->pDraw
!= pDraw
)) {
970 XvdiSendVideoNotify(pPort
, pDraw
, XvStopped
);
974 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
975 INFORM CLIENT OF ITS FAILURE */
977 if ((client
) && (pPort
->grab
.client
) && (pPort
->grab
.client
!= client
)) {
978 XvdiSendVideoNotify(pPort
, pDraw
, XvBusy
);
982 XvdiSendVideoNotify(pPort
, pDraw
, XvStopped
);
984 status
= (*pPort
->pAdaptor
->ddStopVideo
) (client
, pPort
, pDraw
);
987 pPort
->client
= (ClientPtr
) client
;
988 pPort
->time
= currentTime
;
995 XvdiPreemptVideo(ClientPtr client
, XvPortPtr pPort
, DrawablePtr pDraw
)
999 /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
1001 if (!pPort
->pDraw
|| (pPort
->pDraw
!= pDraw
))
1004 XvdiSendVideoNotify(pPort
, pPort
->pDraw
, XvPreempted
);
1006 status
= (*pPort
->pAdaptor
->ddStopVideo
) (client
, pPort
, pPort
->pDraw
);
1008 pPort
->pDraw
= NULL
;
1009 pPort
->client
= (ClientPtr
) client
;
1010 pPort
->time
= currentTime
;
1017 XvdiMatchPort(XvPortPtr pPort
, DrawablePtr pDraw
)
1024 pa
= pPort
->pAdaptor
;
1026 if (pa
->pScreen
!= pDraw
->pScreen
)
1033 if (pf
->depth
== pDraw
->depth
)
1043 XvdiSetPortAttribute(ClientPtr client
,
1044 XvPortPtr pPort
, Atom attribute
, INT32 value
)
1049 (*pPort
->pAdaptor
->ddSetPortAttribute
) (client
, pPort
, attribute
,
1051 if (status
== Success
)
1052 XvdiSendPortNotify(pPort
, attribute
, value
);
1058 XvdiGetPortAttribute(ClientPtr client
,
1059 XvPortPtr pPort
, Atom attribute
, INT32
*p_value
)
1063 (*pPort
->pAdaptor
->ddGetPortAttribute
) (client
, pPort
, attribute
,
1069 WriteSwappedVideoNotifyEvent(xvEvent
* from
, xvEvent
* to
)
1072 to
->u
.u
.type
= from
->u
.u
.type
;
1073 to
->u
.u
.detail
= from
->u
.u
.detail
;
1074 cpswaps(from
->u
.videoNotify
.sequenceNumber
,
1075 to
->u
.videoNotify
.sequenceNumber
);
1076 cpswapl(from
->u
.videoNotify
.time
, to
->u
.videoNotify
.time
);
1077 cpswapl(from
->u
.videoNotify
.drawable
, to
->u
.videoNotify
.drawable
);
1078 cpswapl(from
->u
.videoNotify
.port
, to
->u
.videoNotify
.port
);
1083 WriteSwappedPortNotifyEvent(xvEvent
* from
, xvEvent
* to
)
1086 to
->u
.u
.type
= from
->u
.u
.type
;
1087 to
->u
.u
.detail
= from
->u
.u
.detail
;
1088 cpswaps(from
->u
.portNotify
.sequenceNumber
, to
->u
.portNotify
.sequenceNumber
);
1089 cpswapl(from
->u
.portNotify
.time
, to
->u
.portNotify
.time
);
1090 cpswapl(from
->u
.portNotify
.port
, to
->u
.portNotify
.port
);
1091 cpswapl(from
->u
.portNotify
.value
, to
->u
.portNotify
.value
);