xvmain.c revision 4642e01f
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 "gc.h" 90#include "extnsionst.h" 91#include "dixstruct.h" 92#include "resource.h" 93#include "opaque.h" 94#include "input.h" 95 96#define GLOBAL 97 98#include <X11/extensions/Xv.h> 99#include <X11/extensions/Xvproto.h> 100#include "xvdix.h" 101 102#ifdef PANORAMIX 103#include "panoramiX.h" 104#include "panoramiXsrv.h" 105#endif 106#include "xvdisp.h" 107 108static int XvScreenKeyIndex; 109static DevPrivateKey XvScreenKey = &XvScreenKeyIndex; 110unsigned long XvExtensionGeneration = 0; 111unsigned long XvScreenGeneration = 0; 112unsigned long XvResourceGeneration = 0; 113 114int XvReqCode; 115int XvEventBase; 116int XvErrorBase; 117 118unsigned long XvRTPort; 119unsigned long XvRTEncoding; 120unsigned long XvRTGrab; 121unsigned long XvRTVideoNotify; 122unsigned long XvRTVideoNotifyList; 123unsigned long XvRTPortNotify; 124 125 126 127/* EXTERNAL */ 128 129extern XID clientErrorValue; 130 131static void WriteSwappedVideoNotifyEvent(xvEvent *, xvEvent *); 132static void WriteSwappedPortNotifyEvent(xvEvent *, xvEvent *); 133static Bool CreateResourceTypes(void); 134 135static Bool XvCloseScreen(int, ScreenPtr); 136static Bool XvDestroyPixmap(PixmapPtr); 137static Bool XvDestroyWindow(WindowPtr); 138static void XvResetProc(ExtensionEntry*); 139static int XvdiDestroyGrab(pointer, XID); 140static int XvdiDestroyEncoding(pointer, XID); 141static int XvdiDestroyVideoNotify(pointer, XID); 142static int XvdiDestroyPortNotify(pointer, XID); 143static int XvdiDestroyVideoNotifyList(pointer, XID); 144static int XvdiDestroyPort(pointer, XID); 145static int XvdiSendVideoNotify(XvPortPtr, DrawablePtr, int); 146 147 148 149 150/* 151** XvExtensionInit 152** 153** 154*/ 155 156void 157XvExtensionInit(void) 158{ 159 ExtensionEntry *extEntry; 160 161 /* LOOK TO SEE IF ANY SCREENS WERE INITIALIZED; IF NOT THEN 162 INIT GLOBAL VARIABLES SO THE EXTENSION CAN FUNCTION */ 163 if (XvScreenGeneration != serverGeneration) 164 { 165 if (!CreateResourceTypes()) 166 { 167 ErrorF("XvExtensionInit: Unable to allocate resource types\n"); 168 return; 169 } 170#ifdef PANORAMIX 171 XineramaRegisterConnectionBlockCallback(XineramifyXv); 172#endif 173 XvScreenGeneration = serverGeneration; 174 } 175 176 if (XvExtensionGeneration != serverGeneration) 177 { 178 XvExtensionGeneration = serverGeneration; 179 180 extEntry = AddExtension(XvName, XvNumEvents, XvNumErrors, 181 ProcXvDispatch, SProcXvDispatch, 182 XvResetProc, StandardMinorOpcode); 183 if (!extEntry) 184 { 185 FatalError("XvExtensionInit: AddExtensions failed\n"); 186 } 187 188 XvReqCode = extEntry->base; 189 XvEventBase = extEntry->eventBase; 190 XvErrorBase = extEntry->errorBase; 191 192 EventSwapVector[XvEventBase+XvVideoNotify] = 193 (EventSwapPtr)WriteSwappedVideoNotifyEvent; 194 EventSwapVector[XvEventBase+XvPortNotify] = 195 (EventSwapPtr)WriteSwappedPortNotifyEvent; 196 197 (void)MakeAtom(XvName, strlen(XvName), xTrue); 198 199 } 200} 201 202static Bool 203CreateResourceTypes(void) 204 205{ 206 207 if (XvResourceGeneration == serverGeneration) return TRUE; 208 209 XvResourceGeneration = serverGeneration; 210 211 if (!(XvRTPort = CreateNewResourceType(XvdiDestroyPort))) 212 { 213 ErrorF("CreateResourceTypes: failed to allocate port resource.\n"); 214 return FALSE; 215 } 216 217 if (!(XvRTGrab = CreateNewResourceType(XvdiDestroyGrab))) 218 { 219 ErrorF("CreateResourceTypes: failed to allocate grab resource.\n"); 220 return FALSE; 221 } 222 223 if (!(XvRTEncoding = CreateNewResourceType(XvdiDestroyEncoding))) 224 { 225 ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n"); 226 return FALSE; 227 } 228 229 if (!(XvRTVideoNotify = CreateNewResourceType(XvdiDestroyVideoNotify))) 230 { 231 ErrorF("CreateResourceTypes: failed to allocate video notify resource.\n"); 232 return FALSE; 233 } 234 235 if (!(XvRTVideoNotifyList = CreateNewResourceType(XvdiDestroyVideoNotifyList))) 236 { 237 ErrorF("CreateResourceTypes: failed to allocate video notify list resource.\n"); 238 return FALSE; 239 } 240 241 if (!(XvRTPortNotify = CreateNewResourceType(XvdiDestroyPortNotify))) 242 { 243 ErrorF("CreateResourceTypes: failed to allocate port notify resource.\n"); 244 return FALSE; 245 } 246 247 return TRUE; 248 249} 250 251_X_EXPORT int 252XvScreenInit(ScreenPtr pScreen) 253{ 254 XvScreenPtr pxvs; 255 256 if (XvScreenGeneration != serverGeneration) 257 { 258 if (!CreateResourceTypes()) 259 { 260 ErrorF("XvScreenInit: Unable to allocate resource types\n"); 261 return BadAlloc; 262 } 263#ifdef PANORAMIX 264 XineramaRegisterConnectionBlockCallback(XineramifyXv); 265#endif 266 XvScreenGeneration = serverGeneration; 267 } 268 269 if (dixLookupPrivate(&pScreen->devPrivates, XvScreenKey)) 270 { 271 ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n"); 272 } 273 274 /* ALLOCATE SCREEN PRIVATE RECORD */ 275 276 pxvs = (XvScreenPtr) xalloc (sizeof (XvScreenRec)); 277 if (!pxvs) 278 { 279 ErrorF("XvScreenInit: Unable to allocate screen private structure\n"); 280 return BadAlloc; 281 } 282 283 dixSetPrivate(&pScreen->devPrivates, XvScreenKey, pxvs); 284 285 286 pxvs->DestroyPixmap = pScreen->DestroyPixmap; 287 pxvs->DestroyWindow = pScreen->DestroyWindow; 288 pxvs->CloseScreen = pScreen->CloseScreen; 289 290 pScreen->DestroyPixmap = XvDestroyPixmap; 291 pScreen->DestroyWindow = XvDestroyWindow; 292 pScreen->CloseScreen = XvCloseScreen; 293 294 return Success; 295} 296 297static Bool 298XvCloseScreen( 299 int ii, 300 ScreenPtr pScreen 301){ 302 303 XvScreenPtr pxvs; 304 305 pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey); 306 307 pScreen->DestroyPixmap = pxvs->DestroyPixmap; 308 pScreen->DestroyWindow = pxvs->DestroyWindow; 309 pScreen->CloseScreen = pxvs->CloseScreen; 310 311 (* pxvs->ddCloseScreen)(ii, pScreen); 312 313 xfree(pxvs); 314 315 dixSetPrivate(&pScreen->devPrivates, XvScreenKey, NULL); 316 317 return (*pScreen->CloseScreen)(ii, pScreen); 318} 319 320static void 321XvResetProc(ExtensionEntry* extEntry) 322{ 323 XvResetProcVector(); 324} 325 326_X_EXPORT DevPrivateKey 327XvGetScreenKey(void) 328{ 329 return XvScreenKey; 330} 331 332_X_EXPORT unsigned long 333XvGetRTPort(void) 334{ 335 return XvRTPort; 336} 337 338static Bool 339XvDestroyPixmap(PixmapPtr pPix) 340{ 341 Bool status; 342 ScreenPtr pScreen; 343 XvScreenPtr pxvs; 344 XvAdaptorPtr pa; 345 int na; 346 XvPortPtr pp; 347 int np; 348 349 pScreen = pPix->drawable.pScreen; 350 351 SCREEN_PROLOGUE(pScreen, DestroyPixmap); 352 353 pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey); 354 355 /* CHECK TO SEE IF THIS PORT IS IN USE */ 356 357 pa = pxvs->pAdaptors; 358 na = pxvs->nAdaptors; 359 while (na--) 360 { 361 np = pa->nPorts; 362 pp = pa->pPorts; 363 364 while (np--) 365 { 366 if (pp->pDraw == (DrawablePtr)pPix) 367 { 368 XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted); 369 370 (void)(* pp->pAdaptor->ddStopVideo)((ClientPtr)NULL, pp, 371 pp->pDraw); 372 373 pp->pDraw = (DrawablePtr)NULL; 374 pp->client = (ClientPtr)NULL; 375 pp->time = currentTime; 376 } 377 pp++; 378 } 379 pa++; 380 } 381 382 status = (* pScreen->DestroyPixmap)(pPix); 383 384 SCREEN_EPILOGUE(pScreen, DestroyPixmap, XvDestroyPixmap); 385 386 return status; 387 388} 389 390static Bool 391XvDestroyWindow(WindowPtr pWin) 392{ 393 Bool status; 394 ScreenPtr pScreen; 395 XvScreenPtr pxvs; 396 XvAdaptorPtr pa; 397 int na; 398 XvPortPtr pp; 399 int np; 400 401 pScreen = pWin->drawable.pScreen; 402 403 SCREEN_PROLOGUE(pScreen, DestroyWindow); 404 405 pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey); 406 407 /* CHECK TO SEE IF THIS PORT IS IN USE */ 408 409 pa = pxvs->pAdaptors; 410 na = pxvs->nAdaptors; 411 while (na--) 412 { 413 np = pa->nPorts; 414 pp = pa->pPorts; 415 416 while (np--) 417 { 418 if (pp->pDraw == (DrawablePtr)pWin) 419 { 420 XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted); 421 422 (void)(* pp->pAdaptor->ddStopVideo)((ClientPtr)NULL, pp, 423 pp->pDraw); 424 425 pp->pDraw = (DrawablePtr)NULL; 426 pp->client = (ClientPtr)NULL; 427 pp->time = currentTime; 428 } 429 pp++; 430 } 431 pa++; 432 } 433 434 435 status = (* pScreen->DestroyWindow)(pWin); 436 437 SCREEN_EPILOGUE(pScreen, DestroyWindow, XvDestroyWindow); 438 439 return status; 440 441} 442 443/* The XvdiVideoStopped procedure is a hook for the device dependent layer. 444 It provides a way for the dd layer to inform the di layer that video has 445 stopped in a port for reasons that the di layer had no control over; note 446 that it doesn't call back into the dd layer */ 447 448int 449XvdiVideoStopped(XvPortPtr pPort, int reason) 450{ 451 452 /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */ 453 454 if (!pPort->pDraw) return Success; 455 456 XvdiSendVideoNotify(pPort, pPort->pDraw, reason); 457 458 pPort->pDraw = (DrawablePtr)NULL; 459 pPort->client = (ClientPtr)NULL; 460 pPort->time = currentTime; 461 462 return Success; 463 464} 465 466static int 467XvdiDestroyPort(pointer pPort, XID id) 468{ 469 return (* ((XvPortPtr)pPort)->pAdaptor->ddFreePort)(pPort); 470} 471 472static int 473XvdiDestroyGrab(pointer pGrab, XID id) 474{ 475 ((XvGrabPtr)pGrab)->client = (ClientPtr)NULL; 476 return Success; 477} 478 479static int 480XvdiDestroyVideoNotify(pointer pn, XID id) 481{ 482 /* JUST CLEAR OUT THE client POINTER FIELD */ 483 484 ((XvVideoNotifyPtr)pn)->client = (ClientPtr)NULL; 485 return Success; 486} 487 488static int 489XvdiDestroyPortNotify(pointer pn, XID id) 490{ 491 /* JUST CLEAR OUT THE client POINTER FIELD */ 492 493 ((XvPortNotifyPtr)pn)->client = (ClientPtr)NULL; 494 return Success; 495} 496 497static int 498XvdiDestroyVideoNotifyList(pointer pn, XID id) 499{ 500 XvVideoNotifyPtr npn,cpn; 501 502 /* ACTUALLY DESTROY THE NOTITY LIST */ 503 504 cpn = (XvVideoNotifyPtr)pn; 505 506 while (cpn) 507 { 508 npn = cpn->next; 509 if (cpn->client) FreeResource(cpn->id, XvRTVideoNotify); 510 xfree(cpn); 511 cpn = npn; 512 } 513 return Success; 514} 515 516static int 517XvdiDestroyEncoding(pointer value, XID id) 518{ 519 return Success; 520} 521 522static int 523XvdiSendVideoNotify(pPort, pDraw, reason) 524 525XvPortPtr pPort; 526DrawablePtr pDraw; 527int reason; 528 529{ 530 xvEvent event; 531 XvVideoNotifyPtr pn; 532 533 pn = (XvVideoNotifyPtr)LookupIDByType(pDraw->id, XvRTVideoNotifyList); 534 535 while (pn) 536 { 537 if (pn->client) 538 { 539 event.u.u.type = XvEventBase + XvVideoNotify; 540 event.u.u.sequenceNumber = pn->client->sequence; 541 event.u.videoNotify.time = currentTime.milliseconds; 542 event.u.videoNotify.drawable = pDraw->id; 543 event.u.videoNotify.port = pPort->id; 544 event.u.videoNotify.reason = reason; 545 TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1, 546 NoEventMask, NoEventMask, NullGrab); 547 } 548 pn = pn->next; 549 } 550 551 return Success; 552 553} 554 555 556int 557XvdiSendPortNotify( 558 XvPortPtr pPort, 559 Atom attribute, 560 INT32 value 561){ 562 xvEvent event; 563 XvPortNotifyPtr pn; 564 565 pn = pPort->pNotify; 566 567 while (pn) 568 { 569 if (pn->client) 570 { 571 event.u.u.type = XvEventBase + XvPortNotify; 572 event.u.u.sequenceNumber = pn->client->sequence; 573 event.u.portNotify.time = currentTime.milliseconds; 574 event.u.portNotify.port = pPort->id; 575 event.u.portNotify.attribute = attribute; 576 event.u.portNotify.value = value; 577 TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1, 578 NoEventMask, NoEventMask, NullGrab); 579 } 580 pn = pn->next; 581 } 582 583 return Success; 584 585} 586 587 588#define CHECK_SIZE(dw, dh, sw, sh) { \ 589 if(!dw || !dh || !sw || !sh) return Success; \ 590 /* The region code will break these if they are too large */ \ 591 if((dw > 32767) || (dh > 32767) || (sw > 32767) || (sh > 32767)) \ 592 return BadValue; \ 593} 594 595 596int 597XvdiPutVideo( 598 ClientPtr client, 599 DrawablePtr pDraw, 600 XvPortPtr pPort, 601 GCPtr pGC, 602 INT16 vid_x, INT16 vid_y, 603 CARD16 vid_w, CARD16 vid_h, 604 INT16 drw_x, INT16 drw_y, 605 CARD16 drw_w, CARD16 drw_h 606){ 607 DrawablePtr pOldDraw; 608 609 CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); 610 611 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ 612 613 UpdateCurrentTime(); 614 615 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN 616 INFORM CLIENT OF ITS FAILURE */ 617 618 if (pPort->grab.client && (pPort->grab.client != client)) 619 { 620 XvdiSendVideoNotify(pPort, pDraw, XvBusy); 621 return Success; 622 } 623 624 /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED 625 EVENTS TO ANY CLIENTS WHO WANT THEM */ 626 627 pOldDraw = pPort->pDraw; 628 if ((pOldDraw) && (pOldDraw != pDraw)) 629 { 630 XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted); 631 } 632 633 (void) (* pPort->pAdaptor->ddPutVideo)(client, pDraw, pPort, pGC, 634 vid_x, vid_y, vid_w, vid_h, 635 drw_x, drw_y, drw_w, drw_h); 636 637 if ((pPort->pDraw) && (pOldDraw != pDraw)) 638 { 639 pPort->client = client; 640 XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted); 641 } 642 643 pPort->time = currentTime; 644 645 return (Success); 646 647} 648 649int 650XvdiPutStill( 651 ClientPtr client, 652 DrawablePtr pDraw, 653 XvPortPtr pPort, 654 GCPtr pGC, 655 INT16 vid_x, INT16 vid_y, 656 CARD16 vid_w, CARD16 vid_h, 657 INT16 drw_x, INT16 drw_y, 658 CARD16 drw_w, CARD16 drw_h 659){ 660 int status; 661 662 CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); 663 664 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ 665 666 UpdateCurrentTime(); 667 668 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN 669 INFORM CLIENT OF ITS FAILURE */ 670 671 if (pPort->grab.client && (pPort->grab.client != client)) 672 { 673 XvdiSendVideoNotify(pPort, pDraw, XvBusy); 674 return Success; 675 } 676 677 pPort->time = currentTime; 678 679 status = (* pPort->pAdaptor->ddPutStill)(client, pDraw, pPort, pGC, 680 vid_x, vid_y, vid_w, vid_h, 681 drw_x, drw_y, drw_w, drw_h); 682 683 return status; 684 685} 686 687int 688XvdiPutImage( 689 ClientPtr client, 690 DrawablePtr pDraw, 691 XvPortPtr pPort, 692 GCPtr pGC, 693 INT16 src_x, INT16 src_y, 694 CARD16 src_w, CARD16 src_h, 695 INT16 drw_x, INT16 drw_y, 696 CARD16 drw_w, CARD16 drw_h, 697 XvImagePtr image, 698 unsigned char* data, 699 Bool sync, 700 CARD16 width, CARD16 height 701){ 702 CHECK_SIZE(drw_w, drw_h, src_w, src_h); 703 704 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ 705 706 UpdateCurrentTime(); 707 708 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN 709 INFORM CLIENT OF ITS FAILURE */ 710 711 if (pPort->grab.client && (pPort->grab.client != client)) 712 { 713 XvdiSendVideoNotify(pPort, pDraw, XvBusy); 714 return Success; 715 } 716 717 pPort->time = currentTime; 718 719 return (* pPort->pAdaptor->ddPutImage)(client, pDraw, pPort, pGC, 720 src_x, src_y, src_w, src_h, 721 drw_x, drw_y, drw_w, drw_h, 722 image, data, sync, width, height); 723} 724 725 726int 727XvdiGetVideo( 728 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, 735 CARD16 drw_w, CARD16 drw_h 736){ 737 DrawablePtr pOldDraw; 738 739 CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); 740 741 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ 742 743 UpdateCurrentTime(); 744 745 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN 746 INFORM CLIENT OF ITS FAILURE */ 747 748 if (pPort->grab.client && (pPort->grab.client != client)) 749 { 750 XvdiSendVideoNotify(pPort, pDraw, XvBusy); 751 return Success; 752 } 753 754 /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED 755 EVENTS TO ANY CLIENTS WHO WANT THEM */ 756 757 pOldDraw = pPort->pDraw; 758 if ((pOldDraw) && (pOldDraw != pDraw)) 759 { 760 XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted); 761 } 762 763 (void) (* pPort->pAdaptor->ddGetVideo)(client, pDraw, pPort, pGC, 764 vid_x, vid_y, vid_w, vid_h, 765 drw_x, drw_y, drw_w, drw_h); 766 767 if ((pPort->pDraw) && (pOldDraw != pDraw)) 768 { 769 pPort->client = client; 770 XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted); 771 } 772 773 pPort->time = currentTime; 774 775 return (Success); 776 777} 778 779int 780XvdiGetStill( 781 ClientPtr client, 782 DrawablePtr pDraw, 783 XvPortPtr pPort, 784 GCPtr pGC, 785 INT16 vid_x, INT16 vid_y, 786 CARD16 vid_w, CARD16 vid_h, 787 INT16 drw_x, INT16 drw_y, 788 CARD16 drw_w, CARD16 drw_h 789){ 790 int status; 791 792 CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); 793 794 /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ 795 796 UpdateCurrentTime(); 797 798 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN 799 INFORM CLIENT OF ITS FAILURE */ 800 801 if (pPort->grab.client && (pPort->grab.client != client)) 802 { 803 XvdiSendVideoNotify(pPort, pDraw, XvBusy); 804 return Success; 805 } 806 807 status = (* pPort->pAdaptor->ddGetStill)(client, pDraw, pPort, pGC, 808 vid_x, vid_y, vid_w, vid_h, 809 drw_x, drw_y, drw_w, drw_h); 810 811 pPort->time = currentTime; 812 813 return status; 814 815} 816 817int 818XvdiGrabPort( 819 ClientPtr client, 820 XvPortPtr pPort, 821 Time ctime, 822 int *p_result 823){ 824 unsigned long id; 825 TimeStamp time; 826 827 UpdateCurrentTime(); 828 time = ClientTimeToServerTime(ctime); 829 830 if (pPort->grab.client && (client != pPort->grab.client)) 831 { 832 *p_result = XvAlreadyGrabbed; 833 return Success; 834 } 835 836 if ((CompareTimeStamps(time, currentTime) == LATER) || 837 (CompareTimeStamps(time, pPort->time) == EARLIER)) 838 { 839 *p_result = XvInvalidTime; 840 return Success; 841 } 842 843 if (client == pPort->grab.client) 844 { 845 *p_result = Success; 846 return Success; 847 } 848 849 id = FakeClientID(client->index); 850 851 if (!AddResource(id, XvRTGrab, &pPort->grab)) 852 { 853 return BadAlloc; 854 } 855 856 /* IF THERE IS ACTIVE VIDEO THEN STOP IT */ 857 858 if ((pPort->pDraw) && (client != pPort->client)) 859 { 860 XVCALL(diStopVideo)((ClientPtr)NULL, pPort, pPort->pDraw); 861 } 862 863 pPort->grab.client = client; 864 pPort->grab.id = id; 865 866 pPort->time = currentTime; 867 868 *p_result = Success; 869 870 return Success; 871 872} 873 874int 875XvdiUngrabPort( 876 ClientPtr client, 877 XvPortPtr pPort, 878 Time ctime 879){ 880 TimeStamp time; 881 882 UpdateCurrentTime(); 883 time = ClientTimeToServerTime(ctime); 884 885 if ((!pPort->grab.client) || (client != pPort->grab.client)) 886 { 887 return Success; 888 } 889 890 if ((CompareTimeStamps(time, currentTime) == LATER) || 891 (CompareTimeStamps(time, pPort->time) == EARLIER)) 892 { 893 return Success; 894 } 895 896 /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */ 897 898 FreeResource(pPort->grab.id, XvRTGrab); 899 pPort->grab.client = (ClientPtr)NULL; 900 901 pPort->time = currentTime; 902 903 return Success; 904 905} 906 907 908int 909XvdiSelectVideoNotify( 910 ClientPtr client, 911 DrawablePtr pDraw, 912 BOOL onoff 913){ 914 XvVideoNotifyPtr pn,tpn,fpn; 915 916 /* FIND VideoNotify LIST */ 917 918 pn = (XvVideoNotifyPtr)LookupIDByType(pDraw->id, XvRTVideoNotifyList); 919 920 /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */ 921 922 if (!onoff && !pn) return Success; 923 924 /* IF ONE DOESN'T EXIST CREATE IT AND ADD A RESOURCE SO THAT THE LIST 925 WILL BE DELETED WHEN THE DRAWABLE IS DESTROYED */ 926 927 if (!pn) 928 { 929 if (!(tpn = (XvVideoNotifyPtr)xalloc(sizeof(XvVideoNotifyRec)))) 930 return BadAlloc; 931 tpn->next = (XvVideoNotifyPtr)NULL; 932 if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn)) 933 { 934 xfree(tpn); 935 return BadAlloc; 936 } 937 } 938 else 939 { 940 /* LOOK TO SEE IF ENTRY ALREADY EXISTS */ 941 942 fpn = (XvVideoNotifyPtr)NULL; 943 tpn = pn; 944 while (tpn) 945 { 946 if (tpn->client == client) 947 { 948 if (!onoff) tpn->client = (ClientPtr)NULL; 949 return Success; 950 } 951 if (!tpn->client) fpn = tpn; /* TAKE NOTE OF FREE ENTRY */ 952 tpn = tpn->next; 953 } 954 955 /* IF TUNNING OFF, THEN JUST RETURN */ 956 957 if (!onoff) return Success; 958 959 /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */ 960 961 if (fpn) 962 { 963 tpn = fpn; 964 } 965 else 966 { 967 if (!(tpn = (XvVideoNotifyPtr)xalloc(sizeof(XvVideoNotifyRec)))) 968 return BadAlloc; 969 tpn->next = pn->next; 970 pn->next = tpn; 971 } 972 } 973 974 /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */ 975 /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */ 976 977 tpn->client = (ClientPtr)NULL; 978 tpn->id = FakeClientID(client->index); 979 AddResource(tpn->id, XvRTVideoNotify, tpn); 980 981 tpn->client = client; 982 return Success; 983 984} 985 986int 987XvdiSelectPortNotify( 988 ClientPtr client, 989 XvPortPtr pPort, 990 BOOL onoff 991){ 992 XvPortNotifyPtr pn,tpn; 993 994 /* SEE IF CLIENT IS ALREADY IN LIST */ 995 996 tpn = (XvPortNotifyPtr)NULL; 997 pn = pPort->pNotify; 998 while (pn) 999 { 1000 if (!pn->client) tpn = pn; /* TAKE NOTE OF FREE ENTRY */ 1001 if (pn->client == client) break; 1002 pn = pn->next; 1003 } 1004 1005 /* IS THE CLIENT ALREADY ON THE LIST? */ 1006 1007 if (pn) 1008 { 1009 /* REMOVE IT? */ 1010 1011 if (!onoff) 1012 { 1013 pn->client = (ClientPtr)NULL; 1014 FreeResource(pn->id, XvRTPortNotify); 1015 } 1016 1017 return Success; 1018 } 1019 1020 /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE 1021 CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */ 1022 1023 if (!tpn) 1024 { 1025 if (!(tpn = (XvPortNotifyPtr)xalloc(sizeof(XvPortNotifyRec)))) 1026 return BadAlloc; 1027 tpn->next = pPort->pNotify; 1028 pPort->pNotify = tpn; 1029 } 1030 1031 tpn->client = client; 1032 tpn->id = FakeClientID(client->index); 1033 AddResource(tpn->id, XvRTPortNotify, tpn); 1034 1035 return Success; 1036 1037} 1038 1039int 1040XvdiStopVideo( 1041 ClientPtr client, 1042 XvPortPtr pPort, 1043 DrawablePtr pDraw 1044){ 1045 int status; 1046 1047 /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */ 1048 1049 if (!pPort->pDraw || (pPort->pDraw != pDraw)) 1050 { 1051 XvdiSendVideoNotify(pPort, pDraw, XvStopped); 1052 return Success; 1053 } 1054 1055 /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN 1056 INFORM CLIENT OF ITS FAILURE */ 1057 1058 if ((client) && (pPort->grab.client) && (pPort->grab.client != client)) 1059 { 1060 XvdiSendVideoNotify(pPort, pDraw, XvBusy); 1061 return Success; 1062 } 1063 1064 XvdiSendVideoNotify(pPort, pDraw, XvStopped); 1065 1066 status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pDraw); 1067 1068 pPort->pDraw = (DrawablePtr)NULL; 1069 pPort->client = (ClientPtr)client; 1070 pPort->time = currentTime; 1071 1072 return status; 1073 1074} 1075 1076int 1077XvdiPreemptVideo( 1078 ClientPtr client, 1079 XvPortPtr pPort, 1080 DrawablePtr pDraw 1081){ 1082 int status; 1083 1084 /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */ 1085 1086 if (!pPort->pDraw || (pPort->pDraw != pDraw)) return Success; 1087 1088 XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted); 1089 1090 status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pPort->pDraw); 1091 1092 pPort->pDraw = (DrawablePtr)NULL; 1093 pPort->client = (ClientPtr)client; 1094 pPort->time = currentTime; 1095 1096 return status; 1097 1098} 1099 1100int 1101XvdiMatchPort( 1102 XvPortPtr pPort, 1103 DrawablePtr pDraw 1104){ 1105 1106 XvAdaptorPtr pa; 1107 XvFormatPtr pf; 1108 int nf; 1109 1110 pa = pPort->pAdaptor; 1111 1112 if (pa->pScreen != pDraw->pScreen) return BadMatch; 1113 1114 nf = pa->nFormats; 1115 pf = pa->pFormats; 1116 1117 while (nf--) 1118 { 1119 if ((pf->depth == pDraw->depth) 1120#if 0 1121 && ((pDraw->type == DRAWABLE_PIXMAP) || 1122 (wVisual(((WindowPtr)pDraw)) == pf->visual)) 1123#endif 1124 ) 1125 return Success; 1126 pf++; 1127 } 1128 1129 return BadMatch; 1130 1131} 1132 1133int 1134XvdiSetPortAttribute( 1135 ClientPtr client, 1136 XvPortPtr pPort, 1137 Atom attribute, 1138 INT32 value 1139){ 1140 1141 XvdiSendPortNotify(pPort, attribute, value); 1142 1143 return 1144 (* pPort->pAdaptor->ddSetPortAttribute)(client, pPort, attribute, value); 1145 1146} 1147 1148int 1149XvdiGetPortAttribute( 1150 ClientPtr client, 1151 XvPortPtr pPort, 1152 Atom attribute, 1153 INT32 *p_value 1154){ 1155 1156 return 1157 (* pPort->pAdaptor->ddGetPortAttribute)(client, pPort, attribute, p_value); 1158 1159} 1160 1161static void 1162WriteSwappedVideoNotifyEvent(xvEvent *from, xvEvent *to) 1163 1164{ 1165 1166 to->u.u.type = from->u.u.type; 1167 to->u.u.detail = from->u.u.detail; 1168 cpswaps(from->u.videoNotify.sequenceNumber, 1169 to->u.videoNotify.sequenceNumber); 1170 cpswapl(from->u.videoNotify.time, to->u.videoNotify.time); 1171 cpswapl(from->u.videoNotify.drawable, to->u.videoNotify.drawable); 1172 cpswapl(from->u.videoNotify.port, to->u.videoNotify.port); 1173 1174} 1175 1176static void 1177WriteSwappedPortNotifyEvent(xvEvent *from, xvEvent *to) 1178 1179{ 1180 1181 to->u.u.type = from->u.u.type; 1182 to->u.u.detail = from->u.u.detail; 1183 cpswaps(from->u.portNotify.sequenceNumber, to->u.portNotify.sequenceNumber); 1184 cpswapl(from->u.portNotify.time, to->u.portNotify.time); 1185 cpswapl(from->u.portNotify.port, to->u.portNotify.port); 1186 cpswapl(from->u.portNotify.value, to->u.portNotify.value); 1187 1188} 1189