xvmain.c revision 35c4bbdf
1/*********************************************************** 2Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, 3and the Massachusetts Institute of Technology, Cambridge, Massachusetts. 4 5 All Rights Reserved 6 7Permission to use, copy, modify, and distribute this software and its 8documentation for any purpose and without fee is hereby granted, 9provided that the above copyright notice appear in all copies and that 10both that copyright notice and this permission notice appear in 11supporting documentation, and that the names of Digital or MIT not be 12used in advertising or publicity pertaining to distribution of the 13software without specific, written prior permission. 14 15DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 16ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 17DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 18ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 19WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 20ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 21SOFTWARE. 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 109static DevPrivateKeyRec XvScreenKeyRec; 110 111#define XvScreenKey (&XvScreenKeyRec) 112unsigned long XvExtensionGeneration = 0; 113unsigned long XvScreenGeneration = 0; 114unsigned long XvResourceGeneration = 0; 115 116int XvReqCode; 117int XvEventBase; 118int XvErrorBase; 119 120RESTYPE XvRTPort; 121RESTYPE XvRTEncoding; 122RESTYPE XvRTGrab; 123RESTYPE XvRTVideoNotify; 124RESTYPE XvRTVideoNotifyList; 125RESTYPE XvRTPortNotify; 126 127/* EXTERNAL */ 128 129static void WriteSwappedVideoNotifyEvent(xvEvent *, xvEvent *); 130static void WriteSwappedPortNotifyEvent(xvEvent *, xvEvent *); 131static Bool CreateResourceTypes(void); 132 133static Bool XvCloseScreen(ScreenPtr); 134static Bool XvDestroyPixmap(PixmapPtr); 135static Bool XvDestroyWindow(WindowPtr); 136static void XvResetProc(ExtensionEntry *); 137static int XvdiDestroyGrab(void *, XID); 138static int XvdiDestroyEncoding(void *, XID); 139static int XvdiDestroyVideoNotify(void *, XID); 140static int XvdiDestroyPortNotify(void *, XID); 141static int XvdiDestroyVideoNotifyList(void *, XID); 142static int XvdiDestroyPort(void *, XID); 143static int XvdiSendVideoNotify(XvPortPtr, DrawablePtr, int); 144 145/* 146** XvExtensionInit 147** 148** 149*/ 150 151void 152XvExtensionInit(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 197static Bool 198CreateResourceTypes(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 249int 250XvScreenInit(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 293static Bool 294XvCloseScreen(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 312static void 313XvResetProc(ExtensionEntry * extEntry) 314{ 315 XvResetProcVector(); 316} 317 318DevPrivateKey 319XvGetScreenKey(void) 320{ 321 return XvScreenKey; 322} 323 324unsigned long 325XvGetRTPort(void) 326{ 327 return XvRTPort; 328} 329 330static void 331XvStopAdaptors(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 359static Bool 360XvDestroyPixmap(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 376static Bool 377XvDestroyWindow(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 392static int 393XvdiDestroyPort(void *pPort, XID id) 394{ 395 return Success; 396} 397 398static int 399XvdiDestroyGrab(void *pGrab, XID id) 400{ 401 ((XvGrabPtr) pGrab)->client = NULL; 402 return Success; 403} 404 405static int 406XvdiDestroyVideoNotify(void *pn, XID id) 407{ 408 /* JUST CLEAR OUT THE client POINTER FIELD */ 409 410 ((XvVideoNotifyPtr) pn)->client = NULL; 411 return Success; 412} 413 414static int 415XvdiDestroyPortNotify(void *pn, XID id) 416{ 417 /* JUST CLEAR OUT THE client POINTER FIELD */ 418 419 ((XvPortNotifyPtr) pn)->client = NULL; 420 return Success; 421} 422 423static int 424XvdiDestroyVideoNotifyList(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 442static int 443XvdiDestroyEncoding(void *value, XID id) 444{ 445 return Success; 446} 447 448static int 449XvdiSendVideoNotify(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 472int 473XvdiSendPortNotify(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 502int 503XvdiPutVideo(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 550int 551XvdiPutStill(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 585int 586XvdiPutImage(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 619int 620XvdiGetVideo(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 667int 668XvdiGetStill(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 702int 703XvdiGrabPort(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 750int 751XvdiUngrabPort(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 778int 779XvdiSelectVideoNotify(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 854int 855XvdiSelectPortNotify(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 903int 904XvdiStopVideo(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 935int 936XvdiMatchPort(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 961int 962XvdiSetPortAttribute(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 976int 977XvdiGetPortAttribute(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 987static void 988WriteSwappedVideoNotifyEvent(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 1001static void 1002WriteSwappedPortNotifyEvent(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 1014void 1015XvFreeAdaptor(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 1053void 1054XvFillColorKey(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