ci: Check for DDXen to be built
[xserver.git] / Xext / xvmain.c
blob190360529d7f79891756c2cbbeed8c89dbfe7643
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.
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
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 #include <dix-config.h>
78 #include <string.h>
79 #include <X11/X.h>
80 #include <X11/Xproto.h>
81 #include <X11/extensions/Xv.h>
82 #include <X11/extensions/Xvproto.h>
84 #include "Xext/xvdix_priv.h"
86 #include "misc.h"
87 #include "os.h"
88 #include "scrnintstr.h"
89 #include "windowstr.h"
90 #include "pixmapstr.h"
91 #include "gcstruct.h"
92 #include "extnsionst.h"
93 #include "extinit_priv.h"
94 #include "dixstruct.h"
95 #include "resource.h"
96 #include "opaque.h"
97 #include "input.h"
99 #ifdef PANORAMIX
100 #include "panoramiX.h"
101 #include "panoramiXsrv.h"
102 #endif
103 #include "xvdisp.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;
113 ClientPtr client;
114 unsigned long id;
115 unsigned long mask;
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;
127 int XvReqCode;
128 static int XvEventBase;
129 int XvErrorBase;
131 RESTYPE XvRTPort;
132 static RESTYPE XvRTEncoding;
133 static RESTYPE XvRTGrab;
134 static RESTYPE XvRTVideoNotify;
135 static RESTYPE XvRTVideoNotifyList;
136 static RESTYPE XvRTPortNotify;
138 /* EXTERNAL */
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);
157 ** XvExtensionInit
162 void
163 XvExtensionInit(void)
165 ExtensionEntry *extEntry;
167 if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0))
168 return;
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");
175 return;
177 #ifdef PANORAMIX
178 XineramaRegisterConnectionBlockCallback(XineramifyXv);
179 #endif
180 XvScreenGeneration = serverGeneration;
183 if (XvExtensionGeneration != serverGeneration) {
184 XvExtensionGeneration = serverGeneration;
186 extEntry = AddExtension(XvName, XvNumEvents, XvNumErrors,
187 ProcXvDispatch, SProcXvDispatch,
188 XvResetProc, StandardMinorOpcode);
189 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 SetResourceTypeErrorValue(XvRTPort, _XvBadPort);
203 (void) MakeAtom(XvName, strlen(XvName), xTrue);
208 static Bool
209 CreateResourceTypes(void)
212 if (XvResourceGeneration == serverGeneration)
213 return TRUE;
215 XvResourceGeneration = serverGeneration;
217 if (!(XvRTPort = CreateNewResourceType(XvdiDestroyPort, "XvRTPort"))) {
218 ErrorF("CreateResourceTypes: failed to allocate port resource.\n");
219 return FALSE;
222 if (!(XvRTGrab = CreateNewResourceType(XvdiDestroyGrab, "XvRTGrab"))) {
223 ErrorF("CreateResourceTypes: failed to allocate grab resource.\n");
224 return FALSE;
227 if (!(XvRTEncoding = CreateNewResourceType(XvdiDestroyEncoding,
228 "XvRTEncoding"))) {
229 ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n");
230 return FALSE;
233 if (!(XvRTVideoNotify = CreateNewResourceType(XvdiDestroyVideoNotify,
234 "XvRTVideoNotify"))) {
235 ErrorF
236 ("CreateResourceTypes: failed to allocate video notify resource.\n");
237 return FALSE;
240 if (!
241 (XvRTVideoNotifyList =
242 CreateNewResourceType(XvdiDestroyVideoNotifyList,
243 "XvRTVideoNotifyList"))) {
244 ErrorF
245 ("CreateResourceTypes: failed to allocate video notify list resource.\n");
246 return FALSE;
249 if (!(XvRTPortNotify = CreateNewResourceType(XvdiDestroyPortNotify,
250 "XvRTPortNotify"))) {
251 ErrorF
252 ("CreateResourceTypes: failed to allocate port notify resource.\n");
253 return FALSE;
256 return TRUE;
261 XvScreenInit(ScreenPtr pScreen)
263 XvScreenPtr pxvs;
265 if (XvScreenGeneration != serverGeneration) {
266 if (!CreateResourceTypes()) {
267 ErrorF("XvScreenInit: Unable to allocate resource types\n");
268 return BadAlloc;
270 #ifdef PANORAMIX
271 XineramaRegisterConnectionBlockCallback(XineramifyXv);
272 #endif
273 XvScreenGeneration = serverGeneration;
276 if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0))
277 return BadAlloc;
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));
286 if (!pxvs) {
287 ErrorF("XvScreenInit: Unable to allocate screen private structure\n");
288 return BadAlloc;
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;
301 return Success;
304 static Bool
305 XvCloseScreen(ScreenPtr pScreen)
308 XvScreenPtr pxvs;
310 pxvs = (XvScreenPtr) dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
312 pScreen->DestroyPixmap = pxvs->DestroyPixmap;
313 pScreen->DestroyWindow = pxvs->DestroyWindow;
314 pScreen->CloseScreen = pxvs->CloseScreen;
316 free(pxvs);
318 dixSetPrivate(&pScreen->devPrivates, XvScreenKey, NULL);
320 return (*pScreen->CloseScreen) (pScreen);
323 static void
324 XvResetProc(ExtensionEntry * extEntry)
326 XvResetProcVector();
329 DevPrivateKey
330 XvGetScreenKey(void)
332 return XvScreenKey;
335 unsigned long
336 XvGetRTPort(void)
338 return XvRTPort;
341 static void
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 */
350 while (na--) {
351 XvPortPtr pp = pa->pPorts;
352 int np = pa->nPorts;
354 while (np--) {
355 if (pp->pDraw == pDrawable) {
356 XvdiSendVideoNotify(pp, pDrawable, XvPreempted);
358 (void) (*pp->pAdaptor->ddStopVideo) (pp, pDrawable);
360 pp->pDraw = NULL;
361 pp->client = NULL;
362 pp->time = currentTime;
364 pp++;
366 pa++;
370 static Bool
371 XvDestroyPixmap(PixmapPtr pPix)
373 ScreenPtr pScreen = pPix->drawable.pScreen;
374 Bool status;
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);
383 return status;
387 static Bool
388 XvDestroyWindow(WindowPtr pWin)
390 ScreenPtr pScreen = pWin->drawable.pScreen;
391 Bool status;
393 XvStopAdaptors(&pWin->drawable);
395 SCREEN_PROLOGUE(pScreen, DestroyWindow);
396 status = (*pScreen->DestroyWindow) (pWin);
397 SCREEN_EPILOGUE(pScreen, DestroyWindow, XvDestroyWindow);
399 return status;
403 static int
404 XvdiDestroyPort(void *pPort, XID id)
406 return Success;
409 static int
410 XvdiDestroyGrab(void *pGrab, XID id)
412 ((XvGrabPtr) pGrab)->client = NULL;
413 return Success;
416 static int
417 XvdiDestroyVideoNotify(void *pn, XID id)
419 /* JUST CLEAR OUT THE client POINTER FIELD */
421 ((XvVideoNotifyPtr) pn)->client = NULL;
422 return Success;
425 static int
426 XvdiDestroyPortNotify(void *pn, XID id)
428 /* JUST CLEAR OUT THE client POINTER FIELD */
430 ((XvPortNotifyPtr) pn)->client = NULL;
431 return Success;
434 static int
435 XvdiDestroyVideoNotifyList(void *pn, XID id)
437 XvVideoNotifyPtr npn, cpn;
439 /* ACTUALLY DESTROY THE NOTIFY LIST */
441 cpn = (XvVideoNotifyPtr) pn;
443 while (cpn) {
444 npn = cpn->next;
445 if (cpn->client)
446 FreeResource(cpn->id, XvRTVideoNotify);
447 free(cpn);
448 cpn = npn;
450 return Success;
453 static int
454 XvdiDestroyEncoding(void *value, XID id)
456 return Success;
459 static int
460 XvdiSendVideoNotify(XvPortPtr pPort, DrawablePtr pDraw, int reason)
462 XvVideoNotifyPtr pn;
464 dixLookupResourceByType((void **) &pn, pDraw->id, XvRTVideoNotifyList,
465 serverClient, DixReadAccess);
467 while (pn) {
468 xvEvent event = {
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);
476 pn = pn->next;
479 return Success;
483 static int
484 XvdiSendPortNotify(XvPortPtr pPort, Atom attribute, INT32 value)
486 XvPortNotifyPtr pn;
488 pn = pPort->pNotify;
490 while (pn) {
491 xvEvent event = {
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);
499 pn = pn->next;
502 return Success;
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)) \
510 return BadValue; \
514 XvdiPutVideo(ClientPtr client,
515 DrawablePtr pDraw,
516 XvPortPtr pPort,
517 GCPtr pGC,
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 */
528 UpdateCurrentTime();
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);
535 return Success;
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;
557 return Success;
562 XvdiPutStill(ClientPtr client,
563 DrawablePtr pDraw,
564 XvPortPtr pPort,
565 GCPtr pGC,
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)
570 int status;
572 CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
574 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
576 UpdateCurrentTime();
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);
583 return Success;
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);
592 return status;
597 XvdiPutImage(ClientPtr client,
598 DrawablePtr pDraw,
599 XvPortPtr pPort,
600 GCPtr pGC,
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,
605 XvImagePtr image,
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 */
612 UpdateCurrentTime();
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);
619 return Success;
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,
632 DrawablePtr pDraw,
633 XvPortPtr pPort,
634 GCPtr pGC,
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 */
645 UpdateCurrentTime();
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);
652 return Success;
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;
674 return Success;
679 XvdiGetStill(ClientPtr client,
680 DrawablePtr pDraw,
681 XvPortPtr pPort,
682 GCPtr pGC,
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)
687 int status;
689 CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
691 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
693 UpdateCurrentTime();
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);
700 return Success;
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;
709 return status;
714 XvdiGrabPort(ClientPtr client, XvPortPtr pPort, Time ctime, int *p_result)
716 unsigned long id;
717 TimeStamp time;
719 UpdateCurrentTime();
720 time = ClientTimeToServerTime(ctime);
722 if (pPort->grab.client && (client != pPort->grab.client)) {
723 *p_result = XvAlreadyGrabbed;
724 return Success;
727 if ((CompareTimeStamps(time, currentTime) == LATER) ||
728 (CompareTimeStamps(time, pPort->time) == EARLIER)) {
729 *p_result = XvInvalidTime;
730 return Success;
733 if (client == pPort->grab.client) {
734 *p_result = Success;
735 return Success;
738 id = FakeClientID(client->index);
740 if (!AddResource(id, XvRTGrab, &pPort->grab)) {
741 return BadAlloc;
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;
751 pPort->grab.id = id;
753 pPort->time = currentTime;
755 *p_result = Success;
757 return Success;
762 XvdiUngrabPort(ClientPtr client, XvPortPtr pPort, Time ctime)
764 TimeStamp time;
766 UpdateCurrentTime();
767 time = ClientTimeToServerTime(ctime);
769 if ((!pPort->grab.client) || (client != pPort->grab.client)) {
770 return Success;
773 if ((CompareTimeStamps(time, currentTime) == LATER) ||
774 (CompareTimeStamps(time, pPort->time) == EARLIER)) {
775 return Success;
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;
785 return Success;
790 XvdiSelectVideoNotify(ClientPtr client, DrawablePtr pDraw, BOOL onoff)
792 XvVideoNotifyPtr pn, tpn, fpn;
793 int rc;
795 /* FIND VideoNotify LIST */
797 rc = dixLookupResourceByType((void **) &pn, pDraw->id,
798 XvRTVideoNotifyList, client, DixWriteAccess);
799 if (rc != Success && rc != BadValue)
800 return rc;
802 /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */
804 if (!onoff && !pn)
805 return Success;
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 */
810 if (!pn) {
811 if (!(tpn = malloc(sizeof(XvVideoNotifyRec))))
812 return BadAlloc;
813 tpn->next = NULL;
814 tpn->client = NULL;
815 if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn))
816 return BadAlloc;
818 else {
819 /* LOOK TO SEE IF ENTRY ALREADY EXISTS */
821 fpn = NULL;
822 tpn = pn;
823 while (tpn) {
824 if (tpn->client == client) {
825 if (!onoff) {
826 tpn->client = NULL;
827 FreeResource(tpn->id, XvRTVideoNotify);
829 return Success;
831 if (!tpn->client)
832 fpn = tpn; /* TAKE NOTE OF FREE ENTRY */
833 tpn = tpn->next;
836 /* IF TURNING OFF, THEN JUST RETURN */
838 if (!onoff)
839 return Success;
841 /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */
843 if (fpn) {
844 tpn = fpn;
846 else {
847 if (!(tpn = malloc(sizeof(XvVideoNotifyRec))))
848 return BadAlloc;
849 tpn->next = pn->next;
850 pn->next = tpn;
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 */
857 tpn->client = NULL;
858 tpn->id = FakeClientID(client->index);
859 if (!AddResource(tpn->id, XvRTVideoNotify, tpn))
860 return BadAlloc;
862 tpn->client = client;
863 return Success;
868 XvdiSelectPortNotify(ClientPtr client, XvPortPtr pPort, BOOL onoff)
870 XvPortNotifyPtr pn, tpn;
872 /* SEE IF CLIENT IS ALREADY IN LIST */
874 tpn = NULL;
875 pn = pPort->pNotify;
876 while (pn) {
877 if (!pn->client)
878 tpn = pn; /* TAKE NOTE OF FREE ENTRY */
879 if (pn->client == client)
880 break;
881 pn = pn->next;
884 /* IS THE CLIENT ALREADY ON THE LIST? */
886 if (pn) {
887 /* REMOVE IT? */
889 if (!onoff) {
890 pn->client = NULL;
891 FreeResource(pn->id, XvRTPortNotify);
894 return Success;
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 */
900 if (!tpn) {
901 if (!(tpn = malloc(sizeof(XvPortNotifyRec))))
902 return BadAlloc;
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))
910 return BadAlloc;
912 return Success;
917 XvdiStopVideo(ClientPtr client, XvPortPtr pPort, DrawablePtr pDraw)
919 int status;
921 /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
923 if (!pPort->pDraw || (pPort->pDraw != pDraw)) {
924 XvdiSendVideoNotify(pPort, pDraw, XvStopped);
925 return Success;
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);
933 return Success;
936 XvdiSendVideoNotify(pPort, pDraw, XvStopped);
938 status = (*pPort->pAdaptor->ddStopVideo) (pPort, pDraw);
940 pPort->pDraw = NULL;
941 pPort->client = (ClientPtr) client;
942 pPort->time = currentTime;
944 return status;
949 XvdiMatchPort(XvPortPtr pPort, DrawablePtr pDraw)
952 XvAdaptorPtr pa;
953 XvFormatPtr pf;
954 int nf;
956 pa = pPort->pAdaptor;
958 if (pa->pScreen != pDraw->pScreen)
959 return BadMatch;
961 nf = pa->nFormats;
962 pf = pa->pFormats;
964 while (nf--) {
965 if (pf->depth == pDraw->depth)
966 return Success;
967 pf++;
970 return BadMatch;
975 XvdiSetPortAttribute(ClientPtr client,
976 XvPortPtr pPort, Atom attribute, INT32 value)
978 int status;
980 status =
981 (*pPort->pAdaptor->ddSetPortAttribute) (pPort, attribute,
982 value);
983 if (status == Success)
984 XvdiSendPortNotify(pPort, attribute, value);
986 return status;
990 XvdiGetPortAttribute(ClientPtr client,
991 XvPortPtr pPort, Atom attribute, INT32 *p_value)
994 return
995 (*pPort->pAdaptor->ddGetPortAttribute) (pPort, attribute,
996 p_value);
1000 static void _X_COLD
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);
1014 static void _X_COLD
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);
1027 void
1028 XvFreeAdaptor(XvAdaptorPtr pAdaptor)
1030 int i;
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;
1066 void
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);
1073 xRectangle *rects;
1074 GCPtr gc;
1076 gc = GetScratchGC(pDraw->depth, pScreen);
1077 if (!gc)
1078 return;
1080 pval[0].val = key;
1081 pval[1].val = IncludeInferiors;
1082 (void) ChangeGC(NullClient, gc, GCForeground | GCSubwindowMode, pval);
1083 ValidateGC(pDraw, gc);
1085 rects = xallocarray(nbox, sizeof(xRectangle));
1086 if (rects) {
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);
1096 free(rects);
1098 FreeScratchGC(gc);