Add patch that contain Mali fixes.
[deb_xorg-server.git] / Xext / xvmain.c
1 /***********************************************************
2 Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
3 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
4
5 All Rights Reserved
6
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.
14
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.
22
23 ******************************************************************/
24
25 /*
26 ** File:
27 **
28 ** xvmain.c --- Xv server extension main device independent module.
29 **
30 ** Author:
31 **
32 ** David Carver (Digital Workstation Engineering/Project Athena)
33 **
34 ** Revisions:
35 **
36 ** 04.09.91 Carver
37 ** - change: stop video always generates an event even when video
38 ** wasn't active
39 **
40 ** 29.08.91 Carver
41 ** - change: unrealizing windows no longer preempts video
42 **
43 ** 11.06.91 Carver
44 ** - changed SetPortControl to SetPortAttribute
45 ** - changed GetPortControl to GetPortAttribute
46 ** - changed QueryBestSize
47 **
48 ** 28.05.91 Carver
49 ** - fixed Put and Get requests to not preempt operations to same drawable
50 **
51 ** 15.05.91 Carver
52 ** - version 2.0 upgrade
53 **
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.
58 **
59 ** 24.01.91 Carver
60 ** - version 1.4 upgrade
61 **
62 ** Notes:
63 **
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.
72 **
73 **
74 */
75
76 #ifdef HAVE_DIX_CONFIG_H
77 #include <dix-config.h>
78 #endif
79
80 #include <string.h>
81
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 "extinit.h"
92 #include "dixstruct.h"
93 #include "resource.h"
94 #include "opaque.h"
95 #include "input.h"
96
97 #define GLOBAL
98
99 #include <X11/extensions/Xv.h>
100 #include <X11/extensions/Xvproto.h>
101 #include "xvdix.h"
102
103 #ifdef PANORAMIX
104 #include "panoramiX.h"
105 #include "panoramiXsrv.h"
106 #endif
107 #include "xvdisp.h"
108
109 static DevPrivateKeyRec XvScreenKeyRec;
110
111 #define XvScreenKey (&XvScreenKeyRec)
112 unsigned long XvExtensionGeneration = 0;
113 unsigned long XvScreenGeneration = 0;
114 unsigned long XvResourceGeneration = 0;
115
116 int XvReqCode;
117 int XvEventBase;
118 int XvErrorBase;
119
120 RESTYPE XvRTPort;
121 RESTYPE XvRTEncoding;
122 RESTYPE XvRTGrab;
123 RESTYPE XvRTVideoNotify;
124 RESTYPE XvRTVideoNotifyList;
125 RESTYPE XvRTPortNotify;
126
127 /* EXTERNAL */
128
129 static void WriteSwappedVideoNotifyEvent(xvEvent *, xvEvent *);
130 static void WriteSwappedPortNotifyEvent(xvEvent *, xvEvent *);
131 static Bool CreateResourceTypes(void);
132
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);
144
145 /*
146 ** XvExtensionInit
147 **
148 **
149 */
150
151 void
152 XvExtensionInit(void)
153 {
154 ExtensionEntry *extEntry;
155
156 if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0))
157 return;
158
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");
164 return;
165 }
166 #ifdef PANORAMIX
167 XineramaRegisterConnectionBlockCallback(XineramifyXv);
168 #endif
169 XvScreenGeneration = serverGeneration;
170 }
171
172 if (XvExtensionGeneration != serverGeneration) {
173 XvExtensionGeneration = serverGeneration;
174
175 extEntry = AddExtension(XvName, XvNumEvents, XvNumErrors,
176 ProcXvDispatch, SProcXvDispatch,
177 XvResetProc, StandardMinorOpcode);
178 if (!extEntry) {
179 FatalError("XvExtensionInit: AddExtensions failed\n");
180 }
181
182 XvReqCode = extEntry->base;
183 XvEventBase = extEntry->eventBase;
184 XvErrorBase = extEntry->errorBase;
185
186 EventSwapVector[XvEventBase + XvVideoNotify] =
187 (EventSwapPtr) WriteSwappedVideoNotifyEvent;
188 EventSwapVector[XvEventBase + XvPortNotify] =
189 (EventSwapPtr) WriteSwappedPortNotifyEvent;
190
191 SetResourceTypeErrorValue(XvRTPort, _XvBadPort);
192 (void) MakeAtom(XvName, strlen(XvName), xTrue);
193
194 }
195 }
196
197 static Bool
198 CreateResourceTypes(void)
199 {
200
201 if (XvResourceGeneration == serverGeneration)
202 return TRUE;
203
204 XvResourceGeneration = serverGeneration;
205
206 if (!(XvRTPort = CreateNewResourceType(XvdiDestroyPort, "XvRTPort"))) {
207 ErrorF("CreateResourceTypes: failed to allocate port resource.\n");
208 return FALSE;
209 }
210
211 if (!(XvRTGrab = CreateNewResourceType(XvdiDestroyGrab, "XvRTGrab"))) {
212 ErrorF("CreateResourceTypes: failed to allocate grab resource.\n");
213 return FALSE;
214 }
215
216 if (!(XvRTEncoding = CreateNewResourceType(XvdiDestroyEncoding,
217 "XvRTEncoding"))) {
218 ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n");
219 return FALSE;
220 }
221
222 if (!(XvRTVideoNotify = CreateNewResourceType(XvdiDestroyVideoNotify,
223 "XvRTVideoNotify"))) {
224 ErrorF
225 ("CreateResourceTypes: failed to allocate video notify resource.\n");
226 return FALSE;
227 }
228
229 if (!
230 (XvRTVideoNotifyList =
231 CreateNewResourceType(XvdiDestroyVideoNotifyList,
232 "XvRTVideoNotifyList"))) {
233 ErrorF
234 ("CreateResourceTypes: failed to allocate video notify list resource.\n");
235 return FALSE;
236 }
237
238 if (!(XvRTPortNotify = CreateNewResourceType(XvdiDestroyPortNotify,
239 "XvRTPortNotify"))) {
240 ErrorF
241 ("CreateResourceTypes: failed to allocate port notify resource.\n");
242 return FALSE;
243 }
244
245 return TRUE;
246
247 }
248
249 int
250 XvScreenInit(ScreenPtr pScreen)
251 {
252 XvScreenPtr pxvs;
253
254 if (XvScreenGeneration != serverGeneration) {
255 if (!CreateResourceTypes()) {
256 ErrorF("XvScreenInit: Unable to allocate resource types\n");
257 return BadAlloc;
258 }
259 #ifdef PANORAMIX
260 XineramaRegisterConnectionBlockCallback(XineramifyXv);
261 #endif
262 XvScreenGeneration = serverGeneration;
263 }
264
265 if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0))
266 return BadAlloc;
267
268 if (dixLookupPrivate(&pScreen->devPrivates, XvScreenKey)) {
269 ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n");
270 }
271
272 /* ALLOCATE SCREEN PRIVATE RECORD */
273
274 pxvs = malloc(sizeof(XvScreenRec));
275 if (!pxvs) {
276 ErrorF("XvScreenInit: Unable to allocate screen private structure\n");
277 return BadAlloc;
278 }
279
280 dixSetPrivate(&pScreen->devPrivates, XvScreenKey, pxvs);
281
282 pxvs->DestroyPixmap = pScreen->DestroyPixmap;
283 pxvs->DestroyWindow = pScreen->DestroyWindow;
284 pxvs->CloseScreen = pScreen->CloseScreen;
285
286 pScreen->DestroyPixmap = XvDestroyPixmap;
287 pScreen->DestroyWindow = XvDestroyWindow;
288 pScreen->CloseScreen = XvCloseScreen;
289
290 return Success;
291 }
292
293 static Bool
294 XvCloseScreen(ScreenPtr pScreen)
295 {
296
297 XvScreenPtr pxvs;
298
299 pxvs = (XvScreenPtr) dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
300
301 pScreen->DestroyPixmap = pxvs->DestroyPixmap;
302 pScreen->DestroyWindow = pxvs->DestroyWindow;
303 pScreen->CloseScreen = pxvs->CloseScreen;
304
305 (*pxvs->ddCloseScreen) (pScreen);
306
307 free(pxvs);
308
309 dixSetPrivate(&pScreen->devPrivates, XvScreenKey, NULL);
310
311 return (*pScreen->CloseScreen) (pScreen);
312 }
313
314 static void
315 XvResetProc(ExtensionEntry * extEntry)
316 {
317 XvResetProcVector();
318 }
319
320 DevPrivateKey
321 XvGetScreenKey(void)
322 {
323 return XvScreenKey;
324 }
325
326 unsigned long
327 XvGetRTPort(void)
328 {
329 return XvRTPort;
330 }
331
332 static Bool
333 XvDestroyPixmap(PixmapPtr pPix)
334 {
335 Bool status;
336 ScreenPtr pScreen;
337 XvScreenPtr pxvs;
338 XvAdaptorPtr pa;
339 int na;
340 XvPortPtr pp;
341 int np;
342
343 pScreen = pPix->drawable.pScreen;
344
345 SCREEN_PROLOGUE(pScreen, DestroyPixmap);
346
347 pxvs = (XvScreenPtr) dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
348
349 /* CHECK TO SEE IF THIS PORT IS IN USE */
350
351 pa = pxvs->pAdaptors;
352 na = pxvs->nAdaptors;
353 while (na--) {
354 np = pa->nPorts;
355 pp = pa->pPorts;
356
357 while (np--) {
358 if (pp->pDraw == (DrawablePtr) pPix) {
359 XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted);
360
361 (void) (*pp->pAdaptor->ddStopVideo) (NULL, pp, pp->pDraw);
362
363 pp->pDraw = NULL;
364 pp->client = NULL;
365 pp->time = currentTime;
366 }
367 pp++;
368 }
369 pa++;
370 }
371
372 status = (*pScreen->DestroyPixmap) (pPix);
373
374 SCREEN_EPILOGUE(pScreen, DestroyPixmap, XvDestroyPixmap);
375
376 return status;
377
378 }
379
380 static Bool
381 XvDestroyWindow(WindowPtr pWin)
382 {
383 Bool status;
384 ScreenPtr pScreen;
385 XvScreenPtr pxvs;
386 XvAdaptorPtr pa;
387 int na;
388 XvPortPtr pp;
389 int np;
390
391 pScreen = pWin->drawable.pScreen;
392
393 SCREEN_PROLOGUE(pScreen, DestroyWindow);
394
395 pxvs = (XvScreenPtr) dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
396
397 /* CHECK TO SEE IF THIS PORT IS IN USE */
398
399 pa = pxvs->pAdaptors;
400 na = pxvs->nAdaptors;
401 while (na--) {
402 np = pa->nPorts;
403 pp = pa->pPorts;
404
405 while (np--) {
406 if (pp->pDraw == (DrawablePtr) pWin) {
407 XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted);
408
409 (void) (*pp->pAdaptor->ddStopVideo) (NULL, pp, pp->pDraw);
410
411 pp->pDraw = NULL;
412 pp->client = NULL;
413 pp->time = currentTime;
414 }
415 pp++;
416 }
417 pa++;
418 }
419
420 status = (*pScreen->DestroyWindow) (pWin);
421
422 SCREEN_EPILOGUE(pScreen, DestroyWindow, XvDestroyWindow);
423
424 return status;
425
426 }
427
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 */
432
433 int
434 XvdiVideoStopped(XvPortPtr pPort, int reason)
435 {
436
437 /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
438
439 if (!pPort->pDraw)
440 return Success;
441
442 XvdiSendVideoNotify(pPort, pPort->pDraw, reason);
443
444 pPort->pDraw = NULL;
445 pPort->client = NULL;
446 pPort->time = currentTime;
447
448 return Success;
449
450 }
451
452 static int
453 XvdiDestroyPort(pointer pPort, XID id)
454 {
455 return (*((XvPortPtr) pPort)->pAdaptor->ddFreePort) (pPort);
456 }
457
458 static int
459 XvdiDestroyGrab(pointer pGrab, XID id)
460 {
461 ((XvGrabPtr) pGrab)->client = NULL;
462 return Success;
463 }
464
465 static int
466 XvdiDestroyVideoNotify(pointer pn, XID id)
467 {
468 /* JUST CLEAR OUT THE client POINTER FIELD */
469
470 ((XvVideoNotifyPtr) pn)->client = NULL;
471 return Success;
472 }
473
474 static int
475 XvdiDestroyPortNotify(pointer pn, XID id)
476 {
477 /* JUST CLEAR OUT THE client POINTER FIELD */
478
479 ((XvPortNotifyPtr) pn)->client = NULL;
480 return Success;
481 }
482
483 static int
484 XvdiDestroyVideoNotifyList(pointer pn, XID id)
485 {
486 XvVideoNotifyPtr npn, cpn;
487
488 /* ACTUALLY DESTROY THE NOTITY LIST */
489
490 cpn = (XvVideoNotifyPtr) pn;
491
492 while (cpn) {
493 npn = cpn->next;
494 if (cpn->client)
495 FreeResource(cpn->id, XvRTVideoNotify);
496 free(cpn);
497 cpn = npn;
498 }
499 return Success;
500 }
501
502 static int
503 XvdiDestroyEncoding(pointer value, XID id)
504 {
505 return Success;
506 }
507
508 static int
509 XvdiSendVideoNotify(XvPortPtr pPort, DrawablePtr pDraw, int reason)
510 {
511 XvVideoNotifyPtr pn;
512
513 dixLookupResourceByType((pointer *) &pn, pDraw->id, XvRTVideoNotifyList,
514 serverClient, DixReadAccess);
515
516 while (pn) {
517 xvEvent event = {
518 .u.videoNotify.reason = reason,
519 .u.videoNotify.time = currentTime.milliseconds,
520 .u.videoNotify.drawable = pDraw->id,
521 .u.videoNotify.port = pPort->id
522 };
523 event.u.u.type = XvEventBase + XvVideoNotify;
524 WriteEventsToClient(pn->client, 1, (xEventPtr) &event);
525 pn = pn->next;
526 }
527
528 return Success;
529
530 }
531
532 int
533 XvdiSendPortNotify(XvPortPtr pPort, Atom attribute, INT32 value)
534 {
535 XvPortNotifyPtr pn;
536
537 pn = pPort->pNotify;
538
539 while (pn) {
540 xvEvent event = {
541 .u.portNotify.time = currentTime.milliseconds,
542 .u.portNotify.port = pPort->id,
543 .u.portNotify.attribute = attribute,
544 .u.portNotify.value = value
545 };
546 event.u.u.type = XvEventBase + XvPortNotify;
547 WriteEventsToClient(pn->client, 1, (xEventPtr) &event);
548 pn = pn->next;
549 }
550
551 return Success;
552
553 }
554
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)) \
559 return BadValue; \
560 }
561
562 int
563 XvdiPutVideo(ClientPtr client,
564 DrawablePtr pDraw,
565 XvPortPtr pPort,
566 GCPtr pGC,
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)
570 {
571 DrawablePtr pOldDraw;
572
573 CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
574
575 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
576
577 UpdateCurrentTime();
578
579 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
580 INFORM CLIENT OF ITS FAILURE */
581
582 if (pPort->grab.client && (pPort->grab.client != client)) {
583 XvdiSendVideoNotify(pPort, pDraw, XvBusy);
584 return Success;
585 }
586
587 /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
588 EVENTS TO ANY CLIENTS WHO WANT THEM */
589
590 pOldDraw = pPort->pDraw;
591 if ((pOldDraw) && (pOldDraw != pDraw)) {
592 XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
593 }
594
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);
598
599 if ((pPort->pDraw) && (pOldDraw != pDraw)) {
600 pPort->client = client;
601 XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
602 }
603
604 pPort->time = currentTime;
605
606 return Success;
607
608 }
609
610 int
611 XvdiPutStill(ClientPtr client,
612 DrawablePtr pDraw,
613 XvPortPtr pPort,
614 GCPtr pGC,
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)
618 {
619 int status;
620
621 CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
622
623 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
624
625 UpdateCurrentTime();
626
627 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
628 INFORM CLIENT OF ITS FAILURE */
629
630 if (pPort->grab.client && (pPort->grab.client != client)) {
631 XvdiSendVideoNotify(pPort, pDraw, XvBusy);
632 return Success;
633 }
634
635 pPort->time = currentTime;
636
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);
640
641 return status;
642
643 }
644
645 int
646 XvdiPutImage(ClientPtr client,
647 DrawablePtr pDraw,
648 XvPortPtr pPort,
649 GCPtr pGC,
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,
654 XvImagePtr image,
655 unsigned char *data, Bool sync, CARD16 width, CARD16 height)
656 {
657 CHECK_SIZE(drw_w, drw_h, src_w, src_h);
658
659 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
660
661 UpdateCurrentTime();
662
663 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
664 INFORM CLIENT OF ITS FAILURE */
665
666 if (pPort->grab.client && (pPort->grab.client != client)) {
667 XvdiSendVideoNotify(pPort, pDraw, XvBusy);
668 return Success;
669 }
670
671 pPort->time = currentTime;
672
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);
677 }
678
679 int
680 XvdiGetVideo(ClientPtr client,
681 DrawablePtr pDraw,
682 XvPortPtr pPort,
683 GCPtr pGC,
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)
687 {
688 DrawablePtr pOldDraw;
689
690 CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
691
692 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
693
694 UpdateCurrentTime();
695
696 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
697 INFORM CLIENT OF ITS FAILURE */
698
699 if (pPort->grab.client && (pPort->grab.client != client)) {
700 XvdiSendVideoNotify(pPort, pDraw, XvBusy);
701 return Success;
702 }
703
704 /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
705 EVENTS TO ANY CLIENTS WHO WANT THEM */
706
707 pOldDraw = pPort->pDraw;
708 if ((pOldDraw) && (pOldDraw != pDraw)) {
709 XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
710 }
711
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);
715
716 if ((pPort->pDraw) && (pOldDraw != pDraw)) {
717 pPort->client = client;
718 XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
719 }
720
721 pPort->time = currentTime;
722
723 return Success;
724
725 }
726
727 int
728 XvdiGetStill(ClientPtr client,
729 DrawablePtr pDraw,
730 XvPortPtr pPort,
731 GCPtr pGC,
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)
735 {
736 int status;
737
738 CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
739
740 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
741
742 UpdateCurrentTime();
743
744 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
745 INFORM CLIENT OF ITS FAILURE */
746
747 if (pPort->grab.client && (pPort->grab.client != client)) {
748 XvdiSendVideoNotify(pPort, pDraw, XvBusy);
749 return Success;
750 }
751
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);
755
756 pPort->time = currentTime;
757
758 return status;
759
760 }
761
762 int
763 XvdiGrabPort(ClientPtr client, XvPortPtr pPort, Time ctime, int *p_result)
764 {
765 unsigned long id;
766 TimeStamp time;
767
768 UpdateCurrentTime();
769 time = ClientTimeToServerTime(ctime);
770
771 if (pPort->grab.client && (client != pPort->grab.client)) {
772 *p_result = XvAlreadyGrabbed;
773 return Success;
774 }
775
776 if ((CompareTimeStamps(time, currentTime) == LATER) ||
777 (CompareTimeStamps(time, pPort->time) == EARLIER)) {
778 *p_result = XvInvalidTime;
779 return Success;
780 }
781
782 if (client == pPort->grab.client) {
783 *p_result = Success;
784 return Success;
785 }
786
787 id = FakeClientID(client->index);
788
789 if (!AddResource(id, XvRTGrab, &pPort->grab)) {
790 return BadAlloc;
791 }
792
793 /* IF THERE IS ACTIVE VIDEO THEN STOP IT */
794
795 if ((pPort->pDraw) && (client != pPort->client)) {
796 XvdiStopVideo(NULL, pPort, pPort->pDraw);
797 }
798
799 pPort->grab.client = client;
800 pPort->grab.id = id;
801
802 pPort->time = currentTime;
803
804 *p_result = Success;
805
806 return Success;
807
808 }
809
810 int
811 XvdiUngrabPort(ClientPtr client, XvPortPtr pPort, Time ctime)
812 {
813 TimeStamp time;
814
815 UpdateCurrentTime();
816 time = ClientTimeToServerTime(ctime);
817
818 if ((!pPort->grab.client) || (client != pPort->grab.client)) {
819 return Success;
820 }
821
822 if ((CompareTimeStamps(time, currentTime) == LATER) ||
823 (CompareTimeStamps(time, pPort->time) == EARLIER)) {
824 return Success;
825 }
826
827 /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */
828
829 FreeResource(pPort->grab.id, XvRTGrab);
830 pPort->grab.client = NULL;
831
832 pPort->time = currentTime;
833
834 return Success;
835
836 }
837
838 int
839 XvdiSelectVideoNotify(ClientPtr client, DrawablePtr pDraw, BOOL onoff)
840 {
841 XvVideoNotifyPtr pn, tpn, fpn;
842 int rc;
843
844 /* FIND VideoNotify LIST */
845
846 rc = dixLookupResourceByType((pointer *) &pn, pDraw->id,
847 XvRTVideoNotifyList, client, DixWriteAccess);
848 if (rc != Success && rc != BadValue)
849 return rc;
850
851 /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */
852
853 if (!onoff && !pn)
854 return Success;
855
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 */
858
859 if (!pn) {
860 if (!(tpn = malloc(sizeof(XvVideoNotifyRec))))
861 return BadAlloc;
862 tpn->next = NULL;
863 if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn)) {
864 free(tpn);
865 return BadAlloc;
866 }
867 }
868 else {
869 /* LOOK TO SEE IF ENTRY ALREADY EXISTS */
870
871 fpn = NULL;
872 tpn = pn;
873 while (tpn) {
874 if (tpn->client == client) {
875 if (!onoff)
876 tpn->client = NULL;
877 return Success;
878 }
879 if (!tpn->client)
880 fpn = tpn; /* TAKE NOTE OF FREE ENTRY */
881 tpn = tpn->next;
882 }
883
884 /* IF TUNNING OFF, THEN JUST RETURN */
885
886 if (!onoff)
887 return Success;
888
889 /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */
890
891 if (fpn) {
892 tpn = fpn;
893 }
894 else {
895 if (!(tpn = malloc(sizeof(XvVideoNotifyRec))))
896 return BadAlloc;
897 tpn->next = pn->next;
898 pn->next = tpn;
899 }
900 }
901
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 */
904
905 tpn->client = NULL;
906 tpn->id = FakeClientID(client->index);
907 AddResource(tpn->id, XvRTVideoNotify, tpn);
908
909 tpn->client = client;
910 return Success;
911
912 }
913
914 int
915 XvdiSelectPortNotify(ClientPtr client, XvPortPtr pPort, BOOL onoff)
916 {
917 XvPortNotifyPtr pn, tpn;
918
919 /* SEE IF CLIENT IS ALREADY IN LIST */
920
921 tpn = NULL;
922 pn = pPort->pNotify;
923 while (pn) {
924 if (!pn->client)
925 tpn = pn; /* TAKE NOTE OF FREE ENTRY */
926 if (pn->client == client)
927 break;
928 pn = pn->next;
929 }
930
931 /* IS THE CLIENT ALREADY ON THE LIST? */
932
933 if (pn) {
934 /* REMOVE IT? */
935
936 if (!onoff) {
937 pn->client = NULL;
938 FreeResource(pn->id, XvRTPortNotify);
939 }
940
941 return Success;
942 }
943
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 */
946
947 if (!tpn) {
948 if (!(tpn = malloc(sizeof(XvPortNotifyRec))))
949 return BadAlloc;
950 tpn->next = pPort->pNotify;
951 pPort->pNotify = tpn;
952 }
953
954 tpn->client = client;
955 tpn->id = FakeClientID(client->index);
956 AddResource(tpn->id, XvRTPortNotify, tpn);
957
958 return Success;
959
960 }
961
962 int
963 XvdiStopVideo(ClientPtr client, XvPortPtr pPort, DrawablePtr pDraw)
964 {
965 int status;
966
967 /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
968
969 if (!pPort->pDraw || (pPort->pDraw != pDraw)) {
970 XvdiSendVideoNotify(pPort, pDraw, XvStopped);
971 return Success;
972 }
973
974 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
975 INFORM CLIENT OF ITS FAILURE */
976
977 if ((client) && (pPort->grab.client) && (pPort->grab.client != client)) {
978 XvdiSendVideoNotify(pPort, pDraw, XvBusy);
979 return Success;
980 }
981
982 XvdiSendVideoNotify(pPort, pDraw, XvStopped);
983
984 status = (*pPort->pAdaptor->ddStopVideo) (client, pPort, pDraw);
985
986 pPort->pDraw = NULL;
987 pPort->client = (ClientPtr) client;
988 pPort->time = currentTime;
989
990 return status;
991
992 }
993
994 int
995 XvdiPreemptVideo(ClientPtr client, XvPortPtr pPort, DrawablePtr pDraw)
996 {
997 int status;
998
999 /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
1000
1001 if (!pPort->pDraw || (pPort->pDraw != pDraw))
1002 return Success;
1003
1004 XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
1005
1006 status = (*pPort->pAdaptor->ddStopVideo) (client, pPort, pPort->pDraw);
1007
1008 pPort->pDraw = NULL;
1009 pPort->client = (ClientPtr) client;
1010 pPort->time = currentTime;
1011
1012 return status;
1013
1014 }
1015
1016 int
1017 XvdiMatchPort(XvPortPtr pPort, DrawablePtr pDraw)
1018 {
1019
1020 XvAdaptorPtr pa;
1021 XvFormatPtr pf;
1022 int nf;
1023
1024 pa = pPort->pAdaptor;
1025
1026 if (pa->pScreen != pDraw->pScreen)
1027 return BadMatch;
1028
1029 nf = pa->nFormats;
1030 pf = pa->pFormats;
1031
1032 while (nf--) {
1033 if (pf->depth == pDraw->depth)
1034 return Success;
1035 pf++;
1036 }
1037
1038 return BadMatch;
1039
1040 }
1041
1042 int
1043 XvdiSetPortAttribute(ClientPtr client,
1044 XvPortPtr pPort, Atom attribute, INT32 value)
1045 {
1046 int status;
1047
1048 status =
1049 (*pPort->pAdaptor->ddSetPortAttribute) (client, pPort, attribute,
1050 value);
1051 if (status == Success)
1052 XvdiSendPortNotify(pPort, attribute, value);
1053
1054 return status;
1055 }
1056
1057 int
1058 XvdiGetPortAttribute(ClientPtr client,
1059 XvPortPtr pPort, Atom attribute, INT32 *p_value)
1060 {
1061
1062 return
1063 (*pPort->pAdaptor->ddGetPortAttribute) (client, pPort, attribute,
1064 p_value);
1065
1066 }
1067
1068 static void
1069 WriteSwappedVideoNotifyEvent(xvEvent * from, xvEvent * to)
1070 {
1071
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);
1079
1080 }
1081
1082 static void
1083 WriteSwappedPortNotifyEvent(xvEvent * from, xvEvent * to)
1084 {
1085
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);
1092
1093 }