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 #include <dix-config.h>
80 #include <X11/Xproto.h>
81 #include <X11/extensions/Xv.h>
82 #include <X11/extensions/Xvproto.h>
84 #include "Xext/xvdix_priv.h"
88 #include "scrnintstr.h"
89 #include "windowstr.h"
90 #include "pixmapstr.h"
92 #include "extnsionst.h"
93 #include "extinit_priv.h"
94 #include "dixstruct.h"
100 #include "panoramiX.h"
101 #include "panoramiXsrv.h"
105 #define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = ((XvScreenPtr) \
106 dixLookupPrivate(&(pScreen)->devPrivates, XvScreenKey))->field)
108 #define SCREEN_EPILOGUE(pScreen, field, wrapper)\
109 ((pScreen)->field = wrapper)
111 typedef struct _XvVideoNotifyRec
{
112 struct _XvVideoNotifyRec
*next
;
116 } XvVideoNotifyRec
, *XvVideoNotifyPtr
;
118 static DevPrivateKeyRec XvScreenKeyRec
;
120 Bool noXvExtension
= FALSE
;
122 #define XvScreenKey (&XvScreenKeyRec)
123 static unsigned long XvExtensionGeneration
= 0;
124 static unsigned long XvScreenGeneration
= 0;
125 static unsigned long XvResourceGeneration
= 0;
128 static int XvEventBase
;
132 static RESTYPE XvRTEncoding
;
133 static RESTYPE XvRTGrab
;
134 static RESTYPE XvRTVideoNotify
;
135 static RESTYPE XvRTVideoNotifyList
;
136 static RESTYPE XvRTPortNotify
;
140 static void WriteSwappedVideoNotifyEvent(xvEvent
*, xvEvent
*);
141 static void WriteSwappedPortNotifyEvent(xvEvent
*, xvEvent
*);
142 static Bool
CreateResourceTypes(void);
144 static Bool
XvCloseScreen(ScreenPtr
);
145 static Bool
XvDestroyPixmap(PixmapPtr
);
146 static Bool
XvDestroyWindow(WindowPtr
);
147 static void XvResetProc(ExtensionEntry
*);
148 static int XvdiDestroyGrab(void *, XID
);
149 static int XvdiDestroyEncoding(void *, XID
);
150 static int XvdiDestroyVideoNotify(void *, XID
);
151 static int XvdiDestroyPortNotify(void *, XID
);
152 static int XvdiDestroyVideoNotifyList(void *, XID
);
153 static int XvdiDestroyPort(void *, XID
);
154 static int XvdiSendVideoNotify(XvPortPtr
, DrawablePtr
, int);
163 XvExtensionInit(void)
165 ExtensionEntry
*extEntry
;
167 if (!dixRegisterPrivateKey(&XvScreenKeyRec
, PRIVATE_SCREEN
, 0))
170 /* Look to see if any screens were initialized; if not then
171 init global variables so the extension can function */
172 if (XvScreenGeneration
!= serverGeneration
) {
173 if (!CreateResourceTypes()) {
174 ErrorF("XvExtensionInit: Unable to allocate resource types\n");
178 XineramaRegisterConnectionBlockCallback(XineramifyXv
);
180 XvScreenGeneration
= serverGeneration
;
183 if (XvExtensionGeneration
!= serverGeneration
) {
184 XvExtensionGeneration
= serverGeneration
;
186 extEntry
= AddExtension(XvName
, XvNumEvents
, XvNumErrors
,
187 ProcXvDispatch
, SProcXvDispatch
,
188 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 SetResourceTypeErrorValue(XvRTPort
, _XvBadPort
);
203 (void) MakeAtom(XvName
, strlen(XvName
), xTrue
);
209 CreateResourceTypes(void)
212 if (XvResourceGeneration
== serverGeneration
)
215 XvResourceGeneration
= serverGeneration
;
217 if (!(XvRTPort
= CreateNewResourceType(XvdiDestroyPort
, "XvRTPort"))) {
218 ErrorF("CreateResourceTypes: failed to allocate port resource.\n");
222 if (!(XvRTGrab
= CreateNewResourceType(XvdiDestroyGrab
, "XvRTGrab"))) {
223 ErrorF("CreateResourceTypes: failed to allocate grab resource.\n");
227 if (!(XvRTEncoding
= CreateNewResourceType(XvdiDestroyEncoding
,
229 ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n");
233 if (!(XvRTVideoNotify
= CreateNewResourceType(XvdiDestroyVideoNotify
,
234 "XvRTVideoNotify"))) {
236 ("CreateResourceTypes: failed to allocate video notify resource.\n");
241 (XvRTVideoNotifyList
=
242 CreateNewResourceType(XvdiDestroyVideoNotifyList
,
243 "XvRTVideoNotifyList"))) {
245 ("CreateResourceTypes: failed to allocate video notify list resource.\n");
249 if (!(XvRTPortNotify
= CreateNewResourceType(XvdiDestroyPortNotify
,
250 "XvRTPortNotify"))) {
252 ("CreateResourceTypes: failed to allocate port notify resource.\n");
261 XvScreenInit(ScreenPtr pScreen
)
265 if (XvScreenGeneration
!= serverGeneration
) {
266 if (!CreateResourceTypes()) {
267 ErrorF("XvScreenInit: Unable to allocate resource types\n");
271 XineramaRegisterConnectionBlockCallback(XineramifyXv
);
273 XvScreenGeneration
= serverGeneration
;
276 if (!dixRegisterPrivateKey(&XvScreenKeyRec
, PRIVATE_SCREEN
, 0))
279 if (dixLookupPrivate(&pScreen
->devPrivates
, XvScreenKey
)) {
280 ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n");
283 /* ALLOCATE SCREEN PRIVATE RECORD */
285 pxvs
= malloc(sizeof(XvScreenRec
));
287 ErrorF("XvScreenInit: Unable to allocate screen private structure\n");
291 dixSetPrivate(&pScreen
->devPrivates
, XvScreenKey
, pxvs
);
293 pxvs
->DestroyPixmap
= pScreen
->DestroyPixmap
;
294 pxvs
->DestroyWindow
= pScreen
->DestroyWindow
;
295 pxvs
->CloseScreen
= pScreen
->CloseScreen
;
297 pScreen
->DestroyPixmap
= XvDestroyPixmap
;
298 pScreen
->DestroyWindow
= XvDestroyWindow
;
299 pScreen
->CloseScreen
= XvCloseScreen
;
305 XvCloseScreen(ScreenPtr pScreen
)
310 pxvs
= (XvScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
, XvScreenKey
);
312 pScreen
->DestroyPixmap
= pxvs
->DestroyPixmap
;
313 pScreen
->DestroyWindow
= pxvs
->DestroyWindow
;
314 pScreen
->CloseScreen
= pxvs
->CloseScreen
;
318 dixSetPrivate(&pScreen
->devPrivates
, XvScreenKey
, NULL
);
320 return (*pScreen
->CloseScreen
) (pScreen
);
324 XvResetProc(ExtensionEntry
* extEntry
)
342 XvStopAdaptors(DrawablePtr pDrawable
)
344 ScreenPtr pScreen
= pDrawable
->pScreen
;
345 XvScreenPtr pxvs
= dixLookupPrivate(&pScreen
->devPrivates
, XvScreenKey
);
346 XvAdaptorPtr pa
= pxvs
->pAdaptors
;
347 int na
= pxvs
->nAdaptors
;
349 /* CHECK TO SEE IF THIS PORT IS IN USE */
351 XvPortPtr pp
= pa
->pPorts
;
355 if (pp
->pDraw
== pDrawable
) {
356 XvdiSendVideoNotify(pp
, pDrawable
, XvPreempted
);
358 (void) (*pp
->pAdaptor
->ddStopVideo
) (pp
, pDrawable
);
362 pp
->time
= currentTime
;
371 XvDestroyPixmap(PixmapPtr pPix
)
373 ScreenPtr pScreen
= pPix
->drawable
.pScreen
;
376 if (pPix
->refcnt
== 1)
377 XvStopAdaptors(&pPix
->drawable
);
379 SCREEN_PROLOGUE(pScreen
, DestroyPixmap
);
380 status
= (*pScreen
->DestroyPixmap
) (pPix
);
381 SCREEN_EPILOGUE(pScreen
, DestroyPixmap
, XvDestroyPixmap
);
388 XvDestroyWindow(WindowPtr pWin
)
390 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
393 XvStopAdaptors(&pWin
->drawable
);
395 SCREEN_PROLOGUE(pScreen
, DestroyWindow
);
396 status
= (*pScreen
->DestroyWindow
) (pWin
);
397 SCREEN_EPILOGUE(pScreen
, DestroyWindow
, XvDestroyWindow
);
404 XvdiDestroyPort(void *pPort
, XID id
)
410 XvdiDestroyGrab(void *pGrab
, XID id
)
412 ((XvGrabPtr
) pGrab
)->client
= NULL
;
417 XvdiDestroyVideoNotify(void *pn
, XID id
)
419 /* JUST CLEAR OUT THE client POINTER FIELD */
421 ((XvVideoNotifyPtr
) pn
)->client
= NULL
;
426 XvdiDestroyPortNotify(void *pn
, XID id
)
428 /* JUST CLEAR OUT THE client POINTER FIELD */
430 ((XvPortNotifyPtr
) pn
)->client
= NULL
;
435 XvdiDestroyVideoNotifyList(void *pn
, XID id
)
437 XvVideoNotifyPtr npn
, cpn
;
439 /* ACTUALLY DESTROY THE NOTIFY LIST */
441 cpn
= (XvVideoNotifyPtr
) pn
;
446 FreeResource(cpn
->id
, XvRTVideoNotify
);
454 XvdiDestroyEncoding(void *value
, XID id
)
460 XvdiSendVideoNotify(XvPortPtr pPort
, DrawablePtr pDraw
, int reason
)
464 dixLookupResourceByType((void **) &pn
, pDraw
->id
, XvRTVideoNotifyList
,
465 serverClient
, DixReadAccess
);
469 .u
.videoNotify
.reason
= reason
,
470 .u
.videoNotify
.time
= currentTime
.milliseconds
,
471 .u
.videoNotify
.drawable
= pDraw
->id
,
472 .u
.videoNotify
.port
= pPort
->id
474 event
.u
.u
.type
= XvEventBase
+ XvVideoNotify
;
475 WriteEventsToClient(pn
->client
, 1, (xEventPtr
) &event
);
484 XvdiSendPortNotify(XvPortPtr pPort
, Atom attribute
, INT32 value
)
492 .u
.portNotify
.time
= currentTime
.milliseconds
,
493 .u
.portNotify
.port
= pPort
->id
,
494 .u
.portNotify
.attribute
= attribute
,
495 .u
.portNotify
.value
= value
497 event
.u
.u
.type
= XvEventBase
+ XvPortNotify
;
498 WriteEventsToClient(pn
->client
, 1, (xEventPtr
) &event
);
506 #define CHECK_SIZE(dw, dh, sw, sh) { \
507 if(!dw || !dh || !sw || !sh) return Success; \
508 /* The region code will break these if they are too large */ \
509 if((dw > 32767) || (dh > 32767) || (sw > 32767) || (sh > 32767)) \
514 XvdiPutVideo(ClientPtr client
,
518 INT16 vid_x
, INT16 vid_y
,
519 CARD16 vid_w
, CARD16 vid_h
,
520 INT16 drw_x
, INT16 drw_y
, CARD16 drw_w
, CARD16 drw_h
)
522 DrawablePtr pOldDraw
;
524 CHECK_SIZE(drw_w
, drw_h
, vid_w
, vid_h
);
526 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
530 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
531 INFORM CLIENT OF ITS FAILURE */
533 if (pPort
->grab
.client
&& (pPort
->grab
.client
!= client
)) {
534 XvdiSendVideoNotify(pPort
, pDraw
, XvBusy
);
538 /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
539 EVENTS TO ANY CLIENTS WHO WANT THEM */
541 pOldDraw
= pPort
->pDraw
;
542 if ((pOldDraw
) && (pOldDraw
!= pDraw
)) {
543 XvdiSendVideoNotify(pPort
, pPort
->pDraw
, XvPreempted
);
546 (void) (*pPort
->pAdaptor
->ddPutVideo
) (pDraw
, pPort
, pGC
,
547 vid_x
, vid_y
, vid_w
, vid_h
,
548 drw_x
, drw_y
, drw_w
, drw_h
);
550 if ((pPort
->pDraw
) && (pOldDraw
!= pDraw
)) {
551 pPort
->client
= client
;
552 XvdiSendVideoNotify(pPort
, pPort
->pDraw
, XvStarted
);
555 pPort
->time
= currentTime
;
562 XvdiPutStill(ClientPtr client
,
566 INT16 vid_x
, INT16 vid_y
,
567 CARD16 vid_w
, CARD16 vid_h
,
568 INT16 drw_x
, INT16 drw_y
, CARD16 drw_w
, CARD16 drw_h
)
572 CHECK_SIZE(drw_w
, drw_h
, vid_w
, vid_h
);
574 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
578 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
579 INFORM CLIENT OF ITS FAILURE */
581 if (pPort
->grab
.client
&& (pPort
->grab
.client
!= client
)) {
582 XvdiSendVideoNotify(pPort
, pDraw
, XvBusy
);
586 pPort
->time
= currentTime
;
588 status
= (*pPort
->pAdaptor
->ddPutStill
) (pDraw
, pPort
, pGC
,
589 vid_x
, vid_y
, vid_w
, vid_h
,
590 drw_x
, drw_y
, drw_w
, drw_h
);
597 XvdiPutImage(ClientPtr client
,
601 INT16 src_x
, INT16 src_y
,
602 CARD16 src_w
, CARD16 src_h
,
603 INT16 drw_x
, INT16 drw_y
,
604 CARD16 drw_w
, CARD16 drw_h
,
606 unsigned char *data
, Bool sync
, CARD16 width
, CARD16 height
)
608 CHECK_SIZE(drw_w
, drw_h
, src_w
, src_h
);
610 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
614 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
615 INFORM CLIENT OF ITS FAILURE */
617 if (pPort
->grab
.client
&& (pPort
->grab
.client
!= client
)) {
618 XvdiSendVideoNotify(pPort
, pDraw
, XvBusy
);
622 pPort
->time
= currentTime
;
624 return (*pPort
->pAdaptor
->ddPutImage
) (pDraw
, pPort
, pGC
,
625 src_x
, src_y
, src_w
, src_h
,
626 drw_x
, drw_y
, drw_w
, drw_h
,
627 image
, data
, sync
, width
, height
);
631 XvdiGetVideo(ClientPtr client
,
635 INT16 vid_x
, INT16 vid_y
,
636 CARD16 vid_w
, CARD16 vid_h
,
637 INT16 drw_x
, INT16 drw_y
, CARD16 drw_w
, CARD16 drw_h
)
639 DrawablePtr pOldDraw
;
641 CHECK_SIZE(drw_w
, drw_h
, vid_w
, vid_h
);
643 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
647 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
648 INFORM CLIENT OF ITS FAILURE */
650 if (pPort
->grab
.client
&& (pPort
->grab
.client
!= client
)) {
651 XvdiSendVideoNotify(pPort
, pDraw
, XvBusy
);
655 /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
656 EVENTS TO ANY CLIENTS WHO WANT THEM */
658 pOldDraw
= pPort
->pDraw
;
659 if ((pOldDraw
) && (pOldDraw
!= pDraw
)) {
660 XvdiSendVideoNotify(pPort
, pPort
->pDraw
, XvPreempted
);
663 (void) (*pPort
->pAdaptor
->ddGetVideo
) (pDraw
, pPort
, pGC
,
664 vid_x
, vid_y
, vid_w
, vid_h
,
665 drw_x
, drw_y
, drw_w
, drw_h
);
667 if ((pPort
->pDraw
) && (pOldDraw
!= pDraw
)) {
668 pPort
->client
= client
;
669 XvdiSendVideoNotify(pPort
, pPort
->pDraw
, XvStarted
);
672 pPort
->time
= currentTime
;
679 XvdiGetStill(ClientPtr client
,
683 INT16 vid_x
, INT16 vid_y
,
684 CARD16 vid_w
, CARD16 vid_h
,
685 INT16 drw_x
, INT16 drw_y
, CARD16 drw_w
, CARD16 drw_h
)
689 CHECK_SIZE(drw_w
, drw_h
, vid_w
, vid_h
);
691 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
695 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
696 INFORM CLIENT OF ITS FAILURE */
698 if (pPort
->grab
.client
&& (pPort
->grab
.client
!= client
)) {
699 XvdiSendVideoNotify(pPort
, pDraw
, XvBusy
);
703 status
= (*pPort
->pAdaptor
->ddGetStill
) (pDraw
, pPort
, pGC
,
704 vid_x
, vid_y
, vid_w
, vid_h
,
705 drw_x
, drw_y
, drw_w
, drw_h
);
707 pPort
->time
= currentTime
;
714 XvdiGrabPort(ClientPtr client
, XvPortPtr pPort
, Time ctime
, int *p_result
)
720 time
= ClientTimeToServerTime(ctime
);
722 if (pPort
->grab
.client
&& (client
!= pPort
->grab
.client
)) {
723 *p_result
= XvAlreadyGrabbed
;
727 if ((CompareTimeStamps(time
, currentTime
) == LATER
) ||
728 (CompareTimeStamps(time
, pPort
->time
) == EARLIER
)) {
729 *p_result
= XvInvalidTime
;
733 if (client
== pPort
->grab
.client
) {
738 id
= FakeClientID(client
->index
);
740 if (!AddResource(id
, XvRTGrab
, &pPort
->grab
)) {
744 /* IF THERE IS ACTIVE VIDEO THEN STOP IT */
746 if ((pPort
->pDraw
) && (client
!= pPort
->client
)) {
747 XvdiStopVideo(NULL
, pPort
, pPort
->pDraw
);
750 pPort
->grab
.client
= client
;
753 pPort
->time
= currentTime
;
762 XvdiUngrabPort(ClientPtr client
, XvPortPtr pPort
, Time ctime
)
767 time
= ClientTimeToServerTime(ctime
);
769 if ((!pPort
->grab
.client
) || (client
!= pPort
->grab
.client
)) {
773 if ((CompareTimeStamps(time
, currentTime
) == LATER
) ||
774 (CompareTimeStamps(time
, pPort
->time
) == EARLIER
)) {
778 /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */
780 FreeResource(pPort
->grab
.id
, XvRTGrab
);
781 pPort
->grab
.client
= NULL
;
783 pPort
->time
= currentTime
;
790 XvdiSelectVideoNotify(ClientPtr client
, DrawablePtr pDraw
, BOOL onoff
)
792 XvVideoNotifyPtr pn
, tpn
, fpn
;
795 /* FIND VideoNotify LIST */
797 rc
= dixLookupResourceByType((void **) &pn
, pDraw
->id
,
798 XvRTVideoNotifyList
, client
, DixWriteAccess
);
799 if (rc
!= Success
&& rc
!= BadValue
)
802 /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */
807 /* IF ONE DOESN'T EXIST CREATE IT AND ADD A RESOURCE SO THAT THE LIST
808 WILL BE DELETED WHEN THE DRAWABLE IS DESTROYED */
811 if (!(tpn
= malloc(sizeof(XvVideoNotifyRec
))))
815 if (!AddResource(pDraw
->id
, XvRTVideoNotifyList
, tpn
))
819 /* LOOK TO SEE IF ENTRY ALREADY EXISTS */
824 if (tpn
->client
== client
) {
827 FreeResource(tpn
->id
, XvRTVideoNotify
);
832 fpn
= tpn
; /* TAKE NOTE OF FREE ENTRY */
836 /* IF TURNING OFF, THEN JUST RETURN */
841 /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */
847 if (!(tpn
= malloc(sizeof(XvVideoNotifyRec
))))
849 tpn
->next
= pn
->next
;
854 /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */
855 /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */
858 tpn
->id
= FakeClientID(client
->index
);
859 if (!AddResource(tpn
->id
, XvRTVideoNotify
, tpn
))
862 tpn
->client
= client
;
868 XvdiSelectPortNotify(ClientPtr client
, XvPortPtr pPort
, BOOL onoff
)
870 XvPortNotifyPtr pn
, tpn
;
872 /* SEE IF CLIENT IS ALREADY IN LIST */
878 tpn
= pn
; /* TAKE NOTE OF FREE ENTRY */
879 if (pn
->client
== client
)
884 /* IS THE CLIENT ALREADY ON THE LIST? */
891 FreeResource(pn
->id
, XvRTPortNotify
);
897 /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE
898 CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */
901 if (!(tpn
= malloc(sizeof(XvPortNotifyRec
))))
903 tpn
->next
= pPort
->pNotify
;
904 pPort
->pNotify
= tpn
;
907 tpn
->client
= client
;
908 tpn
->id
= FakeClientID(client
->index
);
909 if (!AddResource(tpn
->id
, XvRTPortNotify
, tpn
))
917 XvdiStopVideo(ClientPtr client
, XvPortPtr pPort
, DrawablePtr pDraw
)
921 /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
923 if (!pPort
->pDraw
|| (pPort
->pDraw
!= pDraw
)) {
924 XvdiSendVideoNotify(pPort
, pDraw
, XvStopped
);
928 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
929 INFORM CLIENT OF ITS FAILURE */
931 if ((client
) && (pPort
->grab
.client
) && (pPort
->grab
.client
!= client
)) {
932 XvdiSendVideoNotify(pPort
, pDraw
, XvBusy
);
936 XvdiSendVideoNotify(pPort
, pDraw
, XvStopped
);
938 status
= (*pPort
->pAdaptor
->ddStopVideo
) (pPort
, pDraw
);
941 pPort
->client
= (ClientPtr
) client
;
942 pPort
->time
= currentTime
;
949 XvdiMatchPort(XvPortPtr pPort
, DrawablePtr pDraw
)
956 pa
= pPort
->pAdaptor
;
958 if (pa
->pScreen
!= pDraw
->pScreen
)
965 if (pf
->depth
== pDraw
->depth
)
975 XvdiSetPortAttribute(ClientPtr client
,
976 XvPortPtr pPort
, Atom attribute
, INT32 value
)
981 (*pPort
->pAdaptor
->ddSetPortAttribute
) (pPort
, attribute
,
983 if (status
== Success
)
984 XvdiSendPortNotify(pPort
, attribute
, value
);
990 XvdiGetPortAttribute(ClientPtr client
,
991 XvPortPtr pPort
, Atom attribute
, INT32
*p_value
)
995 (*pPort
->pAdaptor
->ddGetPortAttribute
) (pPort
, attribute
,
1001 WriteSwappedVideoNotifyEvent(xvEvent
* from
, xvEvent
* to
)
1004 to
->u
.u
.type
= from
->u
.u
.type
;
1005 to
->u
.u
.detail
= from
->u
.u
.detail
;
1006 cpswaps(from
->u
.videoNotify
.sequenceNumber
,
1007 to
->u
.videoNotify
.sequenceNumber
);
1008 cpswapl(from
->u
.videoNotify
.time
, to
->u
.videoNotify
.time
);
1009 cpswapl(from
->u
.videoNotify
.drawable
, to
->u
.videoNotify
.drawable
);
1010 cpswapl(from
->u
.videoNotify
.port
, to
->u
.videoNotify
.port
);
1015 WriteSwappedPortNotifyEvent(xvEvent
* from
, xvEvent
* to
)
1018 to
->u
.u
.type
= from
->u
.u
.type
;
1019 to
->u
.u
.detail
= from
->u
.u
.detail
;
1020 cpswaps(from
->u
.portNotify
.sequenceNumber
, to
->u
.portNotify
.sequenceNumber
);
1021 cpswapl(from
->u
.portNotify
.time
, to
->u
.portNotify
.time
);
1022 cpswapl(from
->u
.portNotify
.port
, to
->u
.portNotify
.port
);
1023 cpswapl(from
->u
.portNotify
.value
, to
->u
.portNotify
.value
);
1028 XvFreeAdaptor(XvAdaptorPtr pAdaptor
)
1032 free(pAdaptor
->name
);
1033 pAdaptor
->name
= NULL
;
1035 if (pAdaptor
->pEncodings
) {
1036 XvEncodingPtr pEncode
= pAdaptor
->pEncodings
;
1038 for (i
= 0; i
< pAdaptor
->nEncodings
; i
++, pEncode
++)
1039 free(pEncode
->name
);
1040 free(pAdaptor
->pEncodings
);
1041 pAdaptor
->pEncodings
= NULL
;
1044 free(pAdaptor
->pFormats
);
1045 pAdaptor
->pFormats
= NULL
;
1047 free(pAdaptor
->pPorts
);
1048 pAdaptor
->pPorts
= NULL
;
1050 if (pAdaptor
->pAttributes
) {
1051 XvAttributePtr pAttribute
= pAdaptor
->pAttributes
;
1053 for (i
= 0; i
< pAdaptor
->nAttributes
; i
++, pAttribute
++)
1054 free(pAttribute
->name
);
1055 free(pAdaptor
->pAttributes
);
1056 pAdaptor
->pAttributes
= NULL
;
1059 free(pAdaptor
->pImages
);
1060 pAdaptor
->pImages
= NULL
;
1062 free(pAdaptor
->devPriv
.ptr
);
1063 pAdaptor
->devPriv
.ptr
= NULL
;
1067 XvFillColorKey(DrawablePtr pDraw
, CARD32 key
, RegionPtr region
)
1069 ScreenPtr pScreen
= pDraw
->pScreen
;
1070 ChangeGCVal pval
[2];
1071 BoxPtr pbox
= RegionRects(region
);
1072 int i
, nbox
= RegionNumRects(region
);
1076 gc
= GetScratchGC(pDraw
->depth
, pScreen
);
1081 pval
[1].val
= IncludeInferiors
;
1082 (void) ChangeGC(NullClient
, gc
, GCForeground
| GCSubwindowMode
, pval
);
1083 ValidateGC(pDraw
, gc
);
1085 rects
= xallocarray(nbox
, sizeof(xRectangle
));
1087 for (i
= 0; i
< nbox
; i
++, pbox
++) {
1088 rects
[i
].x
= pbox
->x1
- pDraw
->x
;
1089 rects
[i
].y
= pbox
->y1
- pDraw
->y
;
1090 rects
[i
].width
= pbox
->x2
- pbox
->x1
;
1091 rects
[i
].height
= pbox
->y2
- pbox
->y1
;
1094 (*gc
->ops
->PolyFillRect
) (pDraw
, gc
, nbox
, rects
);