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 "gcstruct.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(void *, XID);
138 static int XvdiDestroyEncoding(void *, XID);
139 static int XvdiDestroyVideoNotify(void *, XID);
140 static int XvdiDestroyPortNotify(void *, XID);
141 static int XvdiDestroyVideoNotifyList(void *, XID);
142 static int XvdiDestroyPort(void *, XID);
143 static int XvdiSendVideoNotify(XvPortPtr, DrawablePtr, int);
144
145 /*
146 ** XvExtensionInit
147 **
148 **
149 */
150
151 void
XvExtensionInit(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
CreateResourceTypes(void)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
XvScreenInit(ScreenPtr pScreen)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
XvCloseScreen(ScreenPtr pScreen)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 free(pxvs);
306
307 dixSetPrivate(&pScreen->devPrivates, XvScreenKey, NULL);
308
309 return (*pScreen->CloseScreen) (pScreen);
310 }
311
312 static void
XvResetProc(ExtensionEntry * extEntry)313 XvResetProc(ExtensionEntry * extEntry)
314 {
315 XvResetProcVector();
316 }
317
318 DevPrivateKey
XvGetScreenKey(void)319 XvGetScreenKey(void)
320 {
321 return XvScreenKey;
322 }
323
324 unsigned long
XvGetRTPort(void)325 XvGetRTPort(void)
326 {
327 return XvRTPort;
328 }
329
330 static void
XvStopAdaptors(DrawablePtr pDrawable)331 XvStopAdaptors(DrawablePtr pDrawable)
332 {
333 ScreenPtr pScreen = pDrawable->pScreen;
334 XvScreenPtr pxvs = dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
335 XvAdaptorPtr pa = pxvs->pAdaptors;
336 int na = pxvs->nAdaptors;
337
338 /* CHECK TO SEE IF THIS PORT IS IN USE */
339 while (na--) {
340 XvPortPtr pp = pa->pPorts;
341 int np = pa->nPorts;
342
343 while (np--) {
344 if (pp->pDraw == pDrawable) {
345 XvdiSendVideoNotify(pp, pDrawable, XvPreempted);
346
347 (void) (*pp->pAdaptor->ddStopVideo) (pp, pDrawable);
348
349 pp->pDraw = NULL;
350 pp->client = NULL;
351 pp->time = currentTime;
352 }
353 pp++;
354 }
355 pa++;
356 }
357 }
358
359 static Bool
XvDestroyPixmap(PixmapPtr pPix)360 XvDestroyPixmap(PixmapPtr pPix)
361 {
362 ScreenPtr pScreen = pPix->drawable.pScreen;
363 Bool status;
364
365 if (pPix->refcnt == 1)
366 XvStopAdaptors(&pPix->drawable);
367
368 SCREEN_PROLOGUE(pScreen, DestroyPixmap);
369 status = (*pScreen->DestroyPixmap) (pPix);
370 SCREEN_EPILOGUE(pScreen, DestroyPixmap, XvDestroyPixmap);
371
372 return status;
373
374 }
375
376 static Bool
XvDestroyWindow(WindowPtr pWin)377 XvDestroyWindow(WindowPtr pWin)
378 {
379 ScreenPtr pScreen = pWin->drawable.pScreen;
380 Bool status;
381
382 XvStopAdaptors(&pWin->drawable);
383
384 SCREEN_PROLOGUE(pScreen, DestroyWindow);
385 status = (*pScreen->DestroyWindow) (pWin);
386 SCREEN_EPILOGUE(pScreen, DestroyWindow, XvDestroyWindow);
387
388 return status;
389
390 }
391
392 static int
XvdiDestroyPort(void * pPort,XID id)393 XvdiDestroyPort(void *pPort, XID id)
394 {
395 return Success;
396 }
397
398 static int
XvdiDestroyGrab(void * pGrab,XID id)399 XvdiDestroyGrab(void *pGrab, XID id)
400 {
401 ((XvGrabPtr) pGrab)->client = NULL;
402 return Success;
403 }
404
405 static int
XvdiDestroyVideoNotify(void * pn,XID id)406 XvdiDestroyVideoNotify(void *pn, XID id)
407 {
408 /* JUST CLEAR OUT THE client POINTER FIELD */
409
410 ((XvVideoNotifyPtr) pn)->client = NULL;
411 return Success;
412 }
413
414 static int
XvdiDestroyPortNotify(void * pn,XID id)415 XvdiDestroyPortNotify(void *pn, XID id)
416 {
417 /* JUST CLEAR OUT THE client POINTER FIELD */
418
419 ((XvPortNotifyPtr) pn)->client = NULL;
420 return Success;
421 }
422
423 static int
XvdiDestroyVideoNotifyList(void * pn,XID id)424 XvdiDestroyVideoNotifyList(void *pn, XID id)
425 {
426 XvVideoNotifyPtr npn, cpn;
427
428 /* ACTUALLY DESTROY THE NOTITY LIST */
429
430 cpn = (XvVideoNotifyPtr) pn;
431
432 while (cpn) {
433 npn = cpn->next;
434 if (cpn->client)
435 FreeResource(cpn->id, XvRTVideoNotify);
436 free(cpn);
437 cpn = npn;
438 }
439 return Success;
440 }
441
442 static int
XvdiDestroyEncoding(void * value,XID id)443 XvdiDestroyEncoding(void *value, XID id)
444 {
445 return Success;
446 }
447
448 static int
XvdiSendVideoNotify(XvPortPtr pPort,DrawablePtr pDraw,int reason)449 XvdiSendVideoNotify(XvPortPtr pPort, DrawablePtr pDraw, int reason)
450 {
451 XvVideoNotifyPtr pn;
452
453 dixLookupResourceByType((void **) &pn, pDraw->id, XvRTVideoNotifyList,
454 serverClient, DixReadAccess);
455
456 while (pn) {
457 xvEvent event = {
458 .u.videoNotify.reason = reason,
459 .u.videoNotify.time = currentTime.milliseconds,
460 .u.videoNotify.drawable = pDraw->id,
461 .u.videoNotify.port = pPort->id
462 };
463 event.u.u.type = XvEventBase + XvVideoNotify;
464 WriteEventsToClient(pn->client, 1, (xEventPtr) &event);
465 pn = pn->next;
466 }
467
468 return Success;
469
470 }
471
472 int
XvdiSendPortNotify(XvPortPtr pPort,Atom attribute,INT32 value)473 XvdiSendPortNotify(XvPortPtr pPort, Atom attribute, INT32 value)
474 {
475 XvPortNotifyPtr pn;
476
477 pn = pPort->pNotify;
478
479 while (pn) {
480 xvEvent event = {
481 .u.portNotify.time = currentTime.milliseconds,
482 .u.portNotify.port = pPort->id,
483 .u.portNotify.attribute = attribute,
484 .u.portNotify.value = value
485 };
486 event.u.u.type = XvEventBase + XvPortNotify;
487 WriteEventsToClient(pn->client, 1, (xEventPtr) &event);
488 pn = pn->next;
489 }
490
491 return Success;
492
493 }
494
495 #define CHECK_SIZE(dw, dh, sw, sh) { \
496 if(!dw || !dh || !sw || !sh) return Success; \
497 /* The region code will break these if they are too large */ \
498 if((dw > 32767) || (dh > 32767) || (sw > 32767) || (sh > 32767)) \
499 return BadValue; \
500 }
501
502 int
XvdiPutVideo(ClientPtr client,DrawablePtr pDraw,XvPortPtr pPort,GCPtr pGC,INT16 vid_x,INT16 vid_y,CARD16 vid_w,CARD16 vid_h,INT16 drw_x,INT16 drw_y,CARD16 drw_w,CARD16 drw_h)503 XvdiPutVideo(ClientPtr client,
504 DrawablePtr pDraw,
505 XvPortPtr pPort,
506 GCPtr pGC,
507 INT16 vid_x, INT16 vid_y,
508 CARD16 vid_w, CARD16 vid_h,
509 INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
510 {
511 DrawablePtr pOldDraw;
512
513 CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
514
515 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
516
517 UpdateCurrentTime();
518
519 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
520 INFORM CLIENT OF ITS FAILURE */
521
522 if (pPort->grab.client && (pPort->grab.client != client)) {
523 XvdiSendVideoNotify(pPort, pDraw, XvBusy);
524 return Success;
525 }
526
527 /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
528 EVENTS TO ANY CLIENTS WHO WANT THEM */
529
530 pOldDraw = pPort->pDraw;
531 if ((pOldDraw) && (pOldDraw != pDraw)) {
532 XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
533 }
534
535 (void) (*pPort->pAdaptor->ddPutVideo) (pDraw, pPort, pGC,
536 vid_x, vid_y, vid_w, vid_h,
537 drw_x, drw_y, drw_w, drw_h);
538
539 if ((pPort->pDraw) && (pOldDraw != pDraw)) {
540 pPort->client = client;
541 XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
542 }
543
544 pPort->time = currentTime;
545
546 return Success;
547
548 }
549
550 int
XvdiPutStill(ClientPtr client,DrawablePtr pDraw,XvPortPtr pPort,GCPtr pGC,INT16 vid_x,INT16 vid_y,CARD16 vid_w,CARD16 vid_h,INT16 drw_x,INT16 drw_y,CARD16 drw_w,CARD16 drw_h)551 XvdiPutStill(ClientPtr client,
552 DrawablePtr pDraw,
553 XvPortPtr pPort,
554 GCPtr pGC,
555 INT16 vid_x, INT16 vid_y,
556 CARD16 vid_w, CARD16 vid_h,
557 INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
558 {
559 int status;
560
561 CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
562
563 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
564
565 UpdateCurrentTime();
566
567 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
568 INFORM CLIENT OF ITS FAILURE */
569
570 if (pPort->grab.client && (pPort->grab.client != client)) {
571 XvdiSendVideoNotify(pPort, pDraw, XvBusy);
572 return Success;
573 }
574
575 pPort->time = currentTime;
576
577 status = (*pPort->pAdaptor->ddPutStill) (pDraw, pPort, pGC,
578 vid_x, vid_y, vid_w, vid_h,
579 drw_x, drw_y, drw_w, drw_h);
580
581 return status;
582
583 }
584
585 int
XvdiPutImage(ClientPtr client,DrawablePtr pDraw,XvPortPtr pPort,GCPtr pGC,INT16 src_x,INT16 src_y,CARD16 src_w,CARD16 src_h,INT16 drw_x,INT16 drw_y,CARD16 drw_w,CARD16 drw_h,XvImagePtr image,unsigned char * data,Bool sync,CARD16 width,CARD16 height)586 XvdiPutImage(ClientPtr client,
587 DrawablePtr pDraw,
588 XvPortPtr pPort,
589 GCPtr pGC,
590 INT16 src_x, INT16 src_y,
591 CARD16 src_w, CARD16 src_h,
592 INT16 drw_x, INT16 drw_y,
593 CARD16 drw_w, CARD16 drw_h,
594 XvImagePtr image,
595 unsigned char *data, Bool sync, CARD16 width, CARD16 height)
596 {
597 CHECK_SIZE(drw_w, drw_h, src_w, src_h);
598
599 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
600
601 UpdateCurrentTime();
602
603 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
604 INFORM CLIENT OF ITS FAILURE */
605
606 if (pPort->grab.client && (pPort->grab.client != client)) {
607 XvdiSendVideoNotify(pPort, pDraw, XvBusy);
608 return Success;
609 }
610
611 pPort->time = currentTime;
612
613 return (*pPort->pAdaptor->ddPutImage) (pDraw, pPort, pGC,
614 src_x, src_y, src_w, src_h,
615 drw_x, drw_y, drw_w, drw_h,
616 image, data, sync, width, height);
617 }
618
619 int
XvdiGetVideo(ClientPtr client,DrawablePtr pDraw,XvPortPtr pPort,GCPtr pGC,INT16 vid_x,INT16 vid_y,CARD16 vid_w,CARD16 vid_h,INT16 drw_x,INT16 drw_y,CARD16 drw_w,CARD16 drw_h)620 XvdiGetVideo(ClientPtr client,
621 DrawablePtr pDraw,
622 XvPortPtr pPort,
623 GCPtr pGC,
624 INT16 vid_x, INT16 vid_y,
625 CARD16 vid_w, CARD16 vid_h,
626 INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
627 {
628 DrawablePtr pOldDraw;
629
630 CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
631
632 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
633
634 UpdateCurrentTime();
635
636 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
637 INFORM CLIENT OF ITS FAILURE */
638
639 if (pPort->grab.client && (pPort->grab.client != client)) {
640 XvdiSendVideoNotify(pPort, pDraw, XvBusy);
641 return Success;
642 }
643
644 /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
645 EVENTS TO ANY CLIENTS WHO WANT THEM */
646
647 pOldDraw = pPort->pDraw;
648 if ((pOldDraw) && (pOldDraw != pDraw)) {
649 XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
650 }
651
652 (void) (*pPort->pAdaptor->ddGetVideo) (pDraw, pPort, pGC,
653 vid_x, vid_y, vid_w, vid_h,
654 drw_x, drw_y, drw_w, drw_h);
655
656 if ((pPort->pDraw) && (pOldDraw != pDraw)) {
657 pPort->client = client;
658 XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
659 }
660
661 pPort->time = currentTime;
662
663 return Success;
664
665 }
666
667 int
XvdiGetStill(ClientPtr client,DrawablePtr pDraw,XvPortPtr pPort,GCPtr pGC,INT16 vid_x,INT16 vid_y,CARD16 vid_w,CARD16 vid_h,INT16 drw_x,INT16 drw_y,CARD16 drw_w,CARD16 drw_h)668 XvdiGetStill(ClientPtr client,
669 DrawablePtr pDraw,
670 XvPortPtr pPort,
671 GCPtr pGC,
672 INT16 vid_x, INT16 vid_y,
673 CARD16 vid_w, CARD16 vid_h,
674 INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h)
675 {
676 int status;
677
678 CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
679
680 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
681
682 UpdateCurrentTime();
683
684 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
685 INFORM CLIENT OF ITS FAILURE */
686
687 if (pPort->grab.client && (pPort->grab.client != client)) {
688 XvdiSendVideoNotify(pPort, pDraw, XvBusy);
689 return Success;
690 }
691
692 status = (*pPort->pAdaptor->ddGetStill) (pDraw, pPort, pGC,
693 vid_x, vid_y, vid_w, vid_h,
694 drw_x, drw_y, drw_w, drw_h);
695
696 pPort->time = currentTime;
697
698 return status;
699
700 }
701
702 int
XvdiGrabPort(ClientPtr client,XvPortPtr pPort,Time ctime,int * p_result)703 XvdiGrabPort(ClientPtr client, XvPortPtr pPort, Time ctime, int *p_result)
704 {
705 unsigned long id;
706 TimeStamp time;
707
708 UpdateCurrentTime();
709 time = ClientTimeToServerTime(ctime);
710
711 if (pPort->grab.client && (client != pPort->grab.client)) {
712 *p_result = XvAlreadyGrabbed;
713 return Success;
714 }
715
716 if ((CompareTimeStamps(time, currentTime) == LATER) ||
717 (CompareTimeStamps(time, pPort->time) == EARLIER)) {
718 *p_result = XvInvalidTime;
719 return Success;
720 }
721
722 if (client == pPort->grab.client) {
723 *p_result = Success;
724 return Success;
725 }
726
727 id = FakeClientID(client->index);
728
729 if (!AddResource(id, XvRTGrab, &pPort->grab)) {
730 return BadAlloc;
731 }
732
733 /* IF THERE IS ACTIVE VIDEO THEN STOP IT */
734
735 if ((pPort->pDraw) && (client != pPort->client)) {
736 XvdiStopVideo(NULL, pPort, pPort->pDraw);
737 }
738
739 pPort->grab.client = client;
740 pPort->grab.id = id;
741
742 pPort->time = currentTime;
743
744 *p_result = Success;
745
746 return Success;
747
748 }
749
750 int
XvdiUngrabPort(ClientPtr client,XvPortPtr pPort,Time ctime)751 XvdiUngrabPort(ClientPtr client, XvPortPtr pPort, Time ctime)
752 {
753 TimeStamp time;
754
755 UpdateCurrentTime();
756 time = ClientTimeToServerTime(ctime);
757
758 if ((!pPort->grab.client) || (client != pPort->grab.client)) {
759 return Success;
760 }
761
762 if ((CompareTimeStamps(time, currentTime) == LATER) ||
763 (CompareTimeStamps(time, pPort->time) == EARLIER)) {
764 return Success;
765 }
766
767 /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */
768
769 FreeResource(pPort->grab.id, XvRTGrab);
770 pPort->grab.client = NULL;
771
772 pPort->time = currentTime;
773
774 return Success;
775
776 }
777
778 int
XvdiSelectVideoNotify(ClientPtr client,DrawablePtr pDraw,BOOL onoff)779 XvdiSelectVideoNotify(ClientPtr client, DrawablePtr pDraw, BOOL onoff)
780 {
781 XvVideoNotifyPtr pn, tpn, fpn;
782 int rc;
783
784 /* FIND VideoNotify LIST */
785
786 rc = dixLookupResourceByType((void **) &pn, pDraw->id,
787 XvRTVideoNotifyList, client, DixWriteAccess);
788 if (rc != Success && rc != BadValue)
789 return rc;
790
791 /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */
792
793 if (!onoff && !pn)
794 return Success;
795
796 /* IF ONE DOESN'T EXIST CREATE IT AND ADD A RESOURCE SO THAT THE LIST
797 WILL BE DELETED WHEN THE DRAWABLE IS DESTROYED */
798
799 if (!pn) {
800 if (!(tpn = malloc(sizeof(XvVideoNotifyRec))))
801 return BadAlloc;
802 tpn->next = NULL;
803 tpn->client = NULL;
804 if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn))
805 return BadAlloc;
806 }
807 else {
808 /* LOOK TO SEE IF ENTRY ALREADY EXISTS */
809
810 fpn = NULL;
811 tpn = pn;
812 while (tpn) {
813 if (tpn->client == client) {
814 if (!onoff)
815 tpn->client = NULL;
816 return Success;
817 }
818 if (!tpn->client)
819 fpn = tpn; /* TAKE NOTE OF FREE ENTRY */
820 tpn = tpn->next;
821 }
822
823 /* IF TUNNING OFF, THEN JUST RETURN */
824
825 if (!onoff)
826 return Success;
827
828 /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */
829
830 if (fpn) {
831 tpn = fpn;
832 }
833 else {
834 if (!(tpn = malloc(sizeof(XvVideoNotifyRec))))
835 return BadAlloc;
836 tpn->next = pn->next;
837 pn->next = tpn;
838 }
839 }
840
841 /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */
842 /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */
843
844 tpn->client = NULL;
845 tpn->id = FakeClientID(client->index);
846 if (!AddResource(tpn->id, XvRTVideoNotify, tpn))
847 return BadAlloc;
848
849 tpn->client = client;
850 return Success;
851
852 }
853
854 int
XvdiSelectPortNotify(ClientPtr client,XvPortPtr pPort,BOOL onoff)855 XvdiSelectPortNotify(ClientPtr client, XvPortPtr pPort, BOOL onoff)
856 {
857 XvPortNotifyPtr pn, tpn;
858
859 /* SEE IF CLIENT IS ALREADY IN LIST */
860
861 tpn = NULL;
862 pn = pPort->pNotify;
863 while (pn) {
864 if (!pn->client)
865 tpn = pn; /* TAKE NOTE OF FREE ENTRY */
866 if (pn->client == client)
867 break;
868 pn = pn->next;
869 }
870
871 /* IS THE CLIENT ALREADY ON THE LIST? */
872
873 if (pn) {
874 /* REMOVE IT? */
875
876 if (!onoff) {
877 pn->client = NULL;
878 FreeResource(pn->id, XvRTPortNotify);
879 }
880
881 return Success;
882 }
883
884 /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE
885 CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */
886
887 if (!tpn) {
888 if (!(tpn = malloc(sizeof(XvPortNotifyRec))))
889 return BadAlloc;
890 tpn->next = pPort->pNotify;
891 pPort->pNotify = tpn;
892 }
893
894 tpn->client = client;
895 tpn->id = FakeClientID(client->index);
896 if (!AddResource(tpn->id, XvRTPortNotify, tpn))
897 return BadAlloc;
898
899 return Success;
900
901 }
902
903 int
XvdiStopVideo(ClientPtr client,XvPortPtr pPort,DrawablePtr pDraw)904 XvdiStopVideo(ClientPtr client, XvPortPtr pPort, DrawablePtr pDraw)
905 {
906 int status;
907
908 /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
909
910 if (!pPort->pDraw || (pPort->pDraw != pDraw)) {
911 XvdiSendVideoNotify(pPort, pDraw, XvStopped);
912 return Success;
913 }
914
915 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
916 INFORM CLIENT OF ITS FAILURE */
917
918 if ((client) && (pPort->grab.client) && (pPort->grab.client != client)) {
919 XvdiSendVideoNotify(pPort, pDraw, XvBusy);
920 return Success;
921 }
922
923 XvdiSendVideoNotify(pPort, pDraw, XvStopped);
924
925 status = (*pPort->pAdaptor->ddStopVideo) (pPort, pDraw);
926
927 pPort->pDraw = NULL;
928 pPort->client = (ClientPtr) client;
929 pPort->time = currentTime;
930
931 return status;
932
933 }
934
935 int
XvdiMatchPort(XvPortPtr pPort,DrawablePtr pDraw)936 XvdiMatchPort(XvPortPtr pPort, DrawablePtr pDraw)
937 {
938
939 XvAdaptorPtr pa;
940 XvFormatPtr pf;
941 int nf;
942
943 pa = pPort->pAdaptor;
944
945 if (pa->pScreen != pDraw->pScreen)
946 return BadMatch;
947
948 nf = pa->nFormats;
949 pf = pa->pFormats;
950
951 while (nf--) {
952 if (pf->depth == pDraw->depth)
953 return Success;
954 pf++;
955 }
956
957 return BadMatch;
958
959 }
960
961 int
XvdiSetPortAttribute(ClientPtr client,XvPortPtr pPort,Atom attribute,INT32 value)962 XvdiSetPortAttribute(ClientPtr client,
963 XvPortPtr pPort, Atom attribute, INT32 value)
964 {
965 int status;
966
967 status =
968 (*pPort->pAdaptor->ddSetPortAttribute) (pPort, attribute,
969 value);
970 if (status == Success)
971 XvdiSendPortNotify(pPort, attribute, value);
972
973 return status;
974 }
975
976 int
XvdiGetPortAttribute(ClientPtr client,XvPortPtr pPort,Atom attribute,INT32 * p_value)977 XvdiGetPortAttribute(ClientPtr client,
978 XvPortPtr pPort, Atom attribute, INT32 *p_value)
979 {
980
981 return
982 (*pPort->pAdaptor->ddGetPortAttribute) (pPort, attribute,
983 p_value);
984
985 }
986
987 static void _X_COLD
WriteSwappedVideoNotifyEvent(xvEvent * from,xvEvent * to)988 WriteSwappedVideoNotifyEvent(xvEvent * from, xvEvent * to)
989 {
990
991 to->u.u.type = from->u.u.type;
992 to->u.u.detail = from->u.u.detail;
993 cpswaps(from->u.videoNotify.sequenceNumber,
994 to->u.videoNotify.sequenceNumber);
995 cpswapl(from->u.videoNotify.time, to->u.videoNotify.time);
996 cpswapl(from->u.videoNotify.drawable, to->u.videoNotify.drawable);
997 cpswapl(from->u.videoNotify.port, to->u.videoNotify.port);
998
999 }
1000
1001 static void _X_COLD
WriteSwappedPortNotifyEvent(xvEvent * from,xvEvent * to)1002 WriteSwappedPortNotifyEvent(xvEvent * from, xvEvent * to)
1003 {
1004
1005 to->u.u.type = from->u.u.type;
1006 to->u.u.detail = from->u.u.detail;
1007 cpswaps(from->u.portNotify.sequenceNumber, to->u.portNotify.sequenceNumber);
1008 cpswapl(from->u.portNotify.time, to->u.portNotify.time);
1009 cpswapl(from->u.portNotify.port, to->u.portNotify.port);
1010 cpswapl(from->u.portNotify.value, to->u.portNotify.value);
1011
1012 }
1013
1014 void
XvFreeAdaptor(XvAdaptorPtr pAdaptor)1015 XvFreeAdaptor(XvAdaptorPtr pAdaptor)
1016 {
1017 int i;
1018
1019 free(pAdaptor->name);
1020 pAdaptor->name = NULL;
1021
1022 if (pAdaptor->pEncodings) {
1023 XvEncodingPtr pEncode = pAdaptor->pEncodings;
1024
1025 for (i = 0; i < pAdaptor->nEncodings; i++, pEncode++)
1026 free(pEncode->name);
1027 free(pAdaptor->pEncodings);
1028 pAdaptor->pEncodings = NULL;
1029 }
1030
1031 free(pAdaptor->pFormats);
1032 pAdaptor->pFormats = NULL;
1033
1034 free(pAdaptor->pPorts);
1035 pAdaptor->pPorts = NULL;
1036
1037 if (pAdaptor->pAttributes) {
1038 XvAttributePtr pAttribute = pAdaptor->pAttributes;
1039
1040 for (i = 0; i < pAdaptor->nAttributes; i++, pAttribute++)
1041 free(pAttribute->name);
1042 free(pAdaptor->pAttributes);
1043 pAdaptor->pAttributes = NULL;
1044 }
1045
1046 free(pAdaptor->pImages);
1047 pAdaptor->pImages = NULL;
1048
1049 free(pAdaptor->devPriv.ptr);
1050 pAdaptor->devPriv.ptr = NULL;
1051 }
1052
1053 void
XvFillColorKey(DrawablePtr pDraw,CARD32 key,RegionPtr region)1054 XvFillColorKey(DrawablePtr pDraw, CARD32 key, RegionPtr region)
1055 {
1056 ScreenPtr pScreen = pDraw->pScreen;
1057 ChangeGCVal pval[2];
1058 BoxPtr pbox = RegionRects(region);
1059 int i, nbox = RegionNumRects(region);
1060 xRectangle *rects;
1061 GCPtr gc;
1062
1063 gc = GetScratchGC(pDraw->depth, pScreen);
1064 if (!gc)
1065 return;
1066
1067 pval[0].val = key;
1068 pval[1].val = IncludeInferiors;
1069 (void) ChangeGC(NullClient, gc, GCForeground | GCSubwindowMode, pval);
1070 ValidateGC(pDraw, gc);
1071
1072 rects = xallocarray(nbox, sizeof(xRectangle));
1073 if (rects) {
1074 for (i = 0; i < nbox; i++, pbox++) {
1075 rects[i].x = pbox->x1 - pDraw->x;
1076 rects[i].y = pbox->y1 - pDraw->y;
1077 rects[i].width = pbox->x2 - pbox->x1;
1078 rects[i].height = pbox->y2 - pbox->y1;
1079 }
1080
1081 (*gc->ops->PolyFillRect) (pDraw, gc, nbox, rects);
1082
1083 free(rects);
1084 }
1085 FreeScratchGC(gc);
1086 }
1087