xvmain.c (28186B)
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 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 free(pxvs); 306 307 dixSetPrivate(&pScreen->devPrivates, XvScreenKey, NULL); 308 309 return (*pScreen->CloseScreen) (pScreen); 310 } 311 312 static void 313 XvResetProc(ExtensionEntry * extEntry) 314 { 315 XvResetProcVector(); 316 } 317 318 DevPrivateKey 319 XvGetScreenKey(void) 320 { 321 return XvScreenKey; 322 } 323 324 unsigned long 325 XvGetRTPort(void) 326 { 327 return XvRTPort; 328 } 329 330 static void 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 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 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 393 XvdiDestroyPort(void *pPort, XID id) 394 { 395 return Success; 396 } 397 398 static int 399 XvdiDestroyGrab(void *pGrab, XID id) 400 { 401 ((XvGrabPtr) pGrab)->client = NULL; 402 return Success; 403 } 404 405 static int 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 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 424 XvdiDestroyVideoNotifyList(void *pn, XID id) 425 { 426 XvVideoNotifyPtr npn, cpn; 427 428 /* ACTUALLY DESTROY THE NOTIFY 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 443 XvdiDestroyEncoding(void *value, XID id) 444 { 445 return Success; 446 } 447 448 static int 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 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 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 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 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 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 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 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 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 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 TURNING 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 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 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 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 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 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 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 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 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 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 }