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