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