1/* 2 * XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com) 3 */ 4/* 5 * Copyright (c) 1998-2003 by The XFree86 Project, Inc. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 * OTHER DEALINGS IN THE SOFTWARE. 24 * 25 * Except as contained in this notice, the name of the copyright holder(s) 26 * and author(s) shall not be used in advertising or otherwise to promote 27 * the sale, use or other dealings in this Software without prior written 28 * authorization from the copyright holder(s) and author(s). 29 */ 30 31 32#ifdef HAVE_XORG_CONFIG_H 33#include <xorg-config.h> 34#endif 35 36#include "misc.h" 37#include "xf86.h" 38#include "xf86_OSproc.h" 39 40#include <X11/X.h> 41#include <X11/Xproto.h> 42#include "scrnintstr.h" 43#include "regionstr.h" 44#include "windowstr.h" 45#include "pixmapstr.h" 46#include "mivalidate.h" 47#include "validate.h" 48#include "resource.h" 49#include "gcstruct.h" 50#include "dixstruct.h" 51 52#include <X11/extensions/Xv.h> 53#include <X11/extensions/Xvproto.h> 54#include "xvdix.h" 55#include "xvmodproc.h" 56 57#include "xf86xvpriv.h" 58 59 60/* XvScreenRec fields */ 61 62static Bool xf86XVCloseScreen(int, ScreenPtr); 63static int xf86XVQueryAdaptors(ScreenPtr, XvAdaptorPtr *, int *); 64 65/* XvAdaptorRec fields */ 66 67static int xf86XVAllocatePort(unsigned long, XvPortPtr, XvPortPtr*); 68static int xf86XVFreePort(XvPortPtr); 69static int xf86XVPutVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, 70 INT16, INT16, CARD16, CARD16, 71 INT16, INT16, CARD16, CARD16); 72static int xf86XVPutStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, 73 INT16, INT16, CARD16, CARD16, 74 INT16, INT16, CARD16, CARD16); 75static int xf86XVGetVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, 76 INT16, INT16, CARD16, CARD16, 77 INT16, INT16, CARD16, CARD16); 78static int xf86XVGetStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, 79 INT16, INT16, CARD16, CARD16, 80 INT16, INT16, CARD16, CARD16); 81static int xf86XVStopVideo(ClientPtr, XvPortPtr, DrawablePtr); 82static int xf86XVSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32); 83static int xf86XVGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32*); 84static int xf86XVQueryBestSize(ClientPtr, XvPortPtr, CARD8, 85 CARD16, CARD16,CARD16, CARD16, 86 unsigned int*, unsigned int*); 87static int xf86XVPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, 88 INT16, INT16, CARD16, CARD16, 89 INT16, INT16, CARD16, CARD16, 90 XvImagePtr, unsigned char*, Bool, 91 CARD16, CARD16); 92static int xf86XVQueryImageAttributes(ClientPtr, XvPortPtr, XvImagePtr, 93 CARD16*, CARD16*, int*, int*); 94 95 96/* ScreenRec fields */ 97 98static Bool xf86XVDestroyWindow(WindowPtr pWin); 99static void xf86XVWindowExposures(WindowPtr pWin, RegionPtr r1, RegionPtr r2); 100static void xf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin, VTKind kind); 101static void xf86XVClipNotify(WindowPtr pWin, int dx, int dy); 102 103#define PostValidateTreeUndefined ((PostValidateTreeProcPtr)-1) 104 105/* ScrnInfoRec functions */ 106 107static Bool xf86XVEnterVT(int, int); 108static void xf86XVLeaveVT(int, int); 109static void xf86XVAdjustFrame(int index, int x, int y, int flags); 110static void xf86XVModeSet(ScrnInfoPtr pScrn); 111 112/* misc */ 113 114static Bool xf86XVInitAdaptors(ScreenPtr, XF86VideoAdaptorPtr*, int); 115 116 117static DevPrivateKeyRec XF86XVWindowKeyRec; 118#define XF86XVWindowKey (&XF86XVWindowKeyRec) 119 120DevPrivateKey XF86XvScreenKey; 121 122static unsigned long PortResource = 0; 123 124DevPrivateKey (*XvGetScreenKeyProc)(void) = NULL; 125unsigned long (*XvGetRTPortProc)(void) = NULL; 126int (*XvScreenInitProc)(ScreenPtr) = NULL; 127 128#define GET_XV_SCREEN(pScreen) \ 129 ((XvScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, XF86XvScreenKey)) 130 131#define GET_XF86XV_SCREEN(pScreen) \ 132 ((XF86XVScreenPtr)(GET_XV_SCREEN(pScreen)->devPriv.ptr)) 133 134#define GET_XF86XV_WINDOW(pWin) \ 135 ((XF86XVWindowPtr)dixLookupPrivate(&(pWin)->devPrivates, XF86XVWindowKey)) 136 137static xf86XVInitGenericAdaptorPtr *GenDrivers = NULL; 138static int NumGenDrivers = 0; 139 140int 141xf86XVRegisterGenericAdaptorDriver( 142 xf86XVInitGenericAdaptorPtr InitFunc 143){ 144 xf86XVInitGenericAdaptorPtr *newdrivers; 145 146 newdrivers = realloc(GenDrivers, sizeof(xf86XVInitGenericAdaptorPtr) * 147 (1 + NumGenDrivers)); 148 if (!newdrivers) 149 return 0; 150 GenDrivers = newdrivers; 151 152 GenDrivers[NumGenDrivers++] = InitFunc; 153 154 return 1; 155} 156 157int 158xf86XVListGenericAdaptors( 159 ScrnInfoPtr pScrn, 160 XF86VideoAdaptorPtr **adaptors 161){ 162 int i,j,n,num; 163 XF86VideoAdaptorPtr *DrivAdap,*new; 164 165 num = 0; 166 *adaptors = NULL; 167 /* 168 * The v4l driver registers itself first, but can use surfaces registered 169 * by other drivers. So, call the v4l driver last. 170 */ 171 for (i = NumGenDrivers; --i >= 0; ) { 172 DrivAdap = NULL; 173 n = (*GenDrivers[i])(pScrn, &DrivAdap); 174 if (0 == n) 175 continue; 176 new = realloc(*adaptors, sizeof(XF86VideoAdaptorPtr) * (num+n)); 177 if (NULL == new) 178 continue; 179 *adaptors = new; 180 for (j = 0; j < n; j++, num++) 181 (*adaptors)[num] = DrivAdap[j]; 182 } 183 return num; 184} 185 186 187/**************** Offscreen surface stuff *******************/ 188 189typedef struct { 190 XF86OffscreenImagePtr images; 191 int num; 192} OffscreenImageRec; 193 194static DevPrivateKeyRec OffscreenPrivateKeyRec; 195#define OffscreenPrivateKey (&OffscreenPrivateKeyRec) 196#define GetOffscreenImage(pScreen) ((OffscreenImageRec *) dixLookupPrivate(&(pScreen)->devPrivates, OffscreenPrivateKey)) 197 198Bool 199xf86XVRegisterOffscreenImages( 200 ScreenPtr pScreen, 201 XF86OffscreenImagePtr images, 202 int num 203){ 204 OffscreenImageRec *OffscreenImage; 205 /* This function may be called before xf86XVScreenInit, so there's 206 * no better place than this to call dixRegisterPrivateKey to ensure we 207 * have space reserved. After the first call it is a no-op. */ 208 if(!dixRegisterPrivateKey(OffscreenPrivateKey, PRIVATE_SCREEN, sizeof(OffscreenImageRec)) || 209 !(OffscreenImage = GetOffscreenImage(pScreen))) 210 /* Every X.org driver assumes this function always succeeds, so 211 * just die on allocation failure. */ 212 FatalError("Could not allocate private storage for XV offscreen images.\n"); 213 214 OffscreenImage->num = num; 215 OffscreenImage->images = images; 216 return TRUE; 217} 218 219XF86OffscreenImagePtr 220xf86XVQueryOffscreenImages( 221 ScreenPtr pScreen, 222 int *num 223){ 224 OffscreenImageRec *OffscreenImage = GetOffscreenImage(pScreen); 225 *num = OffscreenImage->num; 226 return OffscreenImage->images; 227} 228 229 230XF86VideoAdaptorPtr 231xf86XVAllocateVideoAdaptorRec(ScrnInfoPtr pScrn) 232{ 233 return calloc(1, sizeof(XF86VideoAdaptorRec)); 234} 235 236void 237xf86XVFreeVideoAdaptorRec(XF86VideoAdaptorPtr ptr) 238{ 239 free(ptr); 240} 241 242 243Bool 244xf86XVScreenInit( 245 ScreenPtr pScreen, 246 XF86VideoAdaptorPtr *adaptors, 247 int num 248){ 249 ScrnInfoPtr pScrn; 250 XF86XVScreenPtr ScreenPriv; 251 XvScreenPtr pxvs; 252 253 if(num <= 0 || 254 !XvGetScreenKeyProc || !XvGetRTPortProc || !XvScreenInitProc) 255 return FALSE; 256 257 if(Success != (*XvScreenInitProc)(pScreen)) return FALSE; 258 259 if (!dixRegisterPrivateKey(&XF86XVWindowKeyRec, PRIVATE_WINDOW, 0)) 260 return FALSE; 261 262 XF86XvScreenKey = (*XvGetScreenKeyProc)(); 263 264 PortResource = (*XvGetRTPortProc)(); 265 266 pxvs = GET_XV_SCREEN(pScreen); 267 268 /* Anyone initializing the Xv layer must provide these two. 269 The Xv di layer calls them without even checking if they exist! */ 270 271 pxvs->ddCloseScreen = xf86XVCloseScreen; 272 pxvs->ddQueryAdaptors = xf86XVQueryAdaptors; 273 274 /* The Xv di layer provides us with a private hook so that we don't 275 have to allocate our own screen private. They also provide 276 a CloseScreen hook so that we don't have to wrap it. I'm not 277 sure that I appreciate that. */ 278 279 ScreenPriv = malloc(sizeof(XF86XVScreenRec)); 280 pxvs->devPriv.ptr = (pointer)ScreenPriv; 281 282 if(!ScreenPriv) return FALSE; 283 284 pScrn = xf86Screens[pScreen->myNum]; 285 286 ScreenPriv->DestroyWindow = pScreen->DestroyWindow; 287 ScreenPriv->WindowExposures = pScreen->WindowExposures; 288 ScreenPriv->PostValidateTree = PostValidateTreeUndefined; 289 ScreenPriv->ClipNotify = pScreen->ClipNotify; 290 ScreenPriv->EnterVT = pScrn->EnterVT; 291 ScreenPriv->LeaveVT = pScrn->LeaveVT; 292 ScreenPriv->AdjustFrame = pScrn->AdjustFrame; 293 ScreenPriv->ModeSet = pScrn->ModeSet; 294 295 pScreen->DestroyWindow = xf86XVDestroyWindow; 296 pScreen->WindowExposures = xf86XVWindowExposures; 297 pScreen->ClipNotify = xf86XVClipNotify; 298 pScrn->EnterVT = xf86XVEnterVT; 299 pScrn->LeaveVT = xf86XVLeaveVT; 300 if(pScrn->AdjustFrame) 301 pScrn->AdjustFrame = xf86XVAdjustFrame; 302 pScrn->ModeSet = xf86XVModeSet; 303 304 if(!xf86XVInitAdaptors(pScreen, adaptors, num)) 305 return FALSE; 306 307 return TRUE; 308} 309 310static void 311xf86XVFreeAdaptor(XvAdaptorPtr pAdaptor) 312{ 313 int i; 314 315 free(pAdaptor->name); 316 317 if(pAdaptor->pEncodings) { 318 XvEncodingPtr pEncode = pAdaptor->pEncodings; 319 320 for(i = 0; i < pAdaptor->nEncodings; i++, pEncode++) 321 free(pEncode->name); 322 free(pAdaptor->pEncodings); 323 } 324 325 free(pAdaptor->pFormats); 326 327 if(pAdaptor->pPorts) { 328 XvPortPtr pPort = pAdaptor->pPorts; 329 XvPortRecPrivatePtr pPriv; 330 331 for(i = 0; i < pAdaptor->nPorts; i++, pPort++) { 332 pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr; 333 if(pPriv) { 334 if(pPriv->clientClip) 335 RegionDestroy(pPriv->clientClip); 336 if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) 337 RegionDestroy(pPriv->pCompositeClip); 338 if (pPriv->ckeyFilled) 339 RegionDestroy(pPriv->ckeyFilled); 340 free(pPriv); 341 } 342 } 343 free(pAdaptor->pPorts); 344 } 345 346 if(pAdaptor->nAttributes) { 347 XvAttributePtr pAttribute = pAdaptor->pAttributes; 348 349 for(i = 0; i < pAdaptor->nAttributes; i++, pAttribute++) 350 free(pAttribute->name); 351 free(pAdaptor->pAttributes); 352 } 353 354 free(pAdaptor->pImages); 355 free(pAdaptor->devPriv.ptr); 356} 357 358static Bool 359xf86XVInitAdaptors( 360 ScreenPtr pScreen, 361 XF86VideoAdaptorPtr *infoPtr, 362 int number 363) { 364 XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); 365 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 366 XF86VideoAdaptorPtr adaptorPtr; 367 XvAdaptorPtr pAdaptor, pa; 368 XvAdaptorRecPrivatePtr adaptorPriv; 369 int na, numAdaptor; 370 XvPortRecPrivatePtr portPriv; 371 XvPortPtr pPort, pp; 372 int numPort; 373 XF86AttributePtr attributePtr; 374 XvAttributePtr pAttribute, pat; 375 XF86VideoFormatPtr formatPtr; 376 XvFormatPtr pFormat, pf; 377 int numFormat, totFormat; 378 XF86VideoEncodingPtr encodingPtr; 379 XvEncodingPtr pEncode, pe; 380 XF86ImagePtr imagePtr; 381 XvImagePtr pImage, pi; 382 int numVisuals; 383 VisualPtr pVisual; 384 int i; 385 386 pxvs->nAdaptors = 0; 387 pxvs->pAdaptors = NULL; 388 389 if(!(pAdaptor = calloc(number, sizeof(XvAdaptorRec)))) 390 return FALSE; 391 392 for(pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) { 393 adaptorPtr = infoPtr[na]; 394 395 if(!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute || 396 !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize) 397 continue; 398 399 /* client libs expect at least one encoding */ 400 if(!adaptorPtr->nEncodings || !adaptorPtr->pEncodings) 401 continue; 402 403 pa->type = adaptorPtr->type; 404 405 if(!adaptorPtr->PutVideo && !adaptorPtr->GetVideo) 406 pa->type &= ~XvVideoMask; 407 408 if(!adaptorPtr->PutStill && !adaptorPtr->GetStill) 409 pa->type &= ~XvStillMask; 410 411 if(!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes) 412 pa->type &= ~XvImageMask; 413 414 if(!adaptorPtr->PutVideo && !adaptorPtr->PutImage && 415 !adaptorPtr->PutStill) 416 pa->type &= ~XvInputMask; 417 418 if(!adaptorPtr->GetVideo && !adaptorPtr->GetStill) 419 pa->type &= ~XvOutputMask; 420 421 if(!(adaptorPtr->type & (XvPixmapMask | XvWindowMask))) 422 continue; 423 if(!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask))) 424 continue; 425 426 pa->pScreen = pScreen; 427 pa->ddAllocatePort = xf86XVAllocatePort; 428 pa->ddFreePort = xf86XVFreePort; 429 pa->ddPutVideo = xf86XVPutVideo; 430 pa->ddPutStill = xf86XVPutStill; 431 pa->ddGetVideo = xf86XVGetVideo; 432 pa->ddGetStill = xf86XVGetStill; 433 pa->ddStopVideo = xf86XVStopVideo; 434 pa->ddPutImage = xf86XVPutImage; 435 pa->ddSetPortAttribute = xf86XVSetPortAttribute; 436 pa->ddGetPortAttribute = xf86XVGetPortAttribute; 437 pa->ddQueryBestSize = xf86XVQueryBestSize; 438 pa->ddQueryImageAttributes = xf86XVQueryImageAttributes; 439 pa->name = strdup(adaptorPtr->name); 440 441 if(adaptorPtr->nEncodings && 442 (pEncode = calloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) { 443 444 for(pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0; 445 i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++) 446 { 447 pe->id = encodingPtr->id; 448 pe->pScreen = pScreen; 449 pe->name = strdup(encodingPtr->name); 450 pe->width = encodingPtr->width; 451 pe->height = encodingPtr->height; 452 pe->rate.numerator = encodingPtr->rate.numerator; 453 pe->rate.denominator = encodingPtr->rate.denominator; 454 } 455 pa->nEncodings = adaptorPtr->nEncodings; 456 pa->pEncodings = pEncode; 457 } 458 459 if(adaptorPtr->nImages && 460 (pImage = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) { 461 462 for(i = 0, pi = pImage, imagePtr = adaptorPtr->pImages; 463 i < adaptorPtr->nImages; i++, pi++, imagePtr++) 464 { 465 pi->id = imagePtr->id; 466 pi->type = imagePtr->type; 467 pi->byte_order = imagePtr->byte_order; 468 memcpy(pi->guid, imagePtr->guid, 16); 469 pi->bits_per_pixel = imagePtr->bits_per_pixel; 470 pi->format = imagePtr->format; 471 pi->num_planes = imagePtr->num_planes; 472 pi->depth = imagePtr->depth; 473 pi->red_mask = imagePtr->red_mask; 474 pi->green_mask = imagePtr->green_mask; 475 pi->blue_mask = imagePtr->blue_mask; 476 pi->y_sample_bits = imagePtr->y_sample_bits; 477 pi->u_sample_bits = imagePtr->u_sample_bits; 478 pi->v_sample_bits = imagePtr->v_sample_bits; 479 pi->horz_y_period = imagePtr->horz_y_period; 480 pi->horz_u_period = imagePtr->horz_u_period; 481 pi->horz_v_period = imagePtr->horz_v_period; 482 pi->vert_y_period = imagePtr->vert_y_period; 483 pi->vert_u_period = imagePtr->vert_u_period; 484 pi->vert_v_period = imagePtr->vert_v_period; 485 memcpy(pi->component_order, imagePtr->component_order, 32); 486 pi->scanline_order = imagePtr->scanline_order; 487 } 488 pa->nImages = adaptorPtr->nImages; 489 pa->pImages = pImage; 490 } 491 492 if(adaptorPtr->nAttributes && 493 (pAttribute = calloc(adaptorPtr->nAttributes, sizeof(XvAttributeRec)))) 494 { 495 for(pat = pAttribute, attributePtr = adaptorPtr->pAttributes, i = 0; 496 i < adaptorPtr->nAttributes; pat++, i++, attributePtr++) 497 { 498 pat->flags = attributePtr->flags; 499 pat->min_value = attributePtr->min_value; 500 pat->max_value = attributePtr->max_value; 501 pat->name = strdup(attributePtr->name); 502 } 503 pa->nAttributes = adaptorPtr->nAttributes; 504 pa->pAttributes = pAttribute; 505 } 506 507 508 totFormat = adaptorPtr->nFormats; 509 510 if(!(pFormat = calloc(totFormat, sizeof(XvFormatRec)))) { 511 xf86XVFreeAdaptor(pa); 512 continue; 513 } 514 for(pf = pFormat, i = 0, numFormat = 0, formatPtr = adaptorPtr->pFormats; 515 i < adaptorPtr->nFormats; i++, formatPtr++) 516 { 517 numVisuals = pScreen->numVisuals; 518 pVisual = pScreen->visuals; 519 520 while(numVisuals--) { 521 if((pVisual->class == formatPtr->class) && 522 (pVisual->nplanes == formatPtr->depth)) { 523 524 if(numFormat >= totFormat) { 525 void *moreSpace; 526 totFormat *= 2; 527 moreSpace = realloc(pFormat, 528 totFormat * sizeof(XvFormatRec)); 529 if(!moreSpace) break; 530 pFormat = moreSpace; 531 pf = pFormat + numFormat; 532 } 533 534 pf->visual = pVisual->vid; 535 pf->depth = formatPtr->depth; 536 537 pf++; 538 numFormat++; 539 } 540 pVisual++; 541 } 542 } 543 pa->nFormats = numFormat; 544 pa->pFormats = pFormat; 545 if(!numFormat) { 546 xf86XVFreeAdaptor(pa); 547 continue; 548 } 549 550 if(!(adaptorPriv = calloc(1, sizeof(XvAdaptorRecPrivate)))) { 551 xf86XVFreeAdaptor(pa); 552 continue; 553 } 554 555 adaptorPriv->flags = adaptorPtr->flags; 556 adaptorPriv->PutVideo = adaptorPtr->PutVideo; 557 adaptorPriv->PutStill = adaptorPtr->PutStill; 558 adaptorPriv->GetVideo = adaptorPtr->GetVideo; 559 adaptorPriv->GetStill = adaptorPtr->GetStill; 560 adaptorPriv->StopVideo = adaptorPtr->StopVideo; 561 adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute; 562 adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute; 563 adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize; 564 adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes; 565 adaptorPriv->PutImage = adaptorPtr->PutImage; 566 adaptorPriv->ReputImage = adaptorPtr->ReputImage; /* image/still */ 567 568 pa->devPriv.ptr = (pointer)adaptorPriv; 569 570 if(!(pPort = calloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) { 571 xf86XVFreeAdaptor(pa); 572 continue; 573 } 574 for(pp = pPort, i = 0, numPort = 0; 575 i < adaptorPtr->nPorts; i++) { 576 577 if(!(pp->id = FakeClientID(0))) 578 continue; 579 580 if(!(portPriv = calloc(1, sizeof(XvPortRecPrivate)))) 581 continue; 582 583 if(!AddResource(pp->id, PortResource, pp)) { 584 free(portPriv); 585 continue; 586 } 587 588 pp->pAdaptor = pa; 589 pp->pNotify = (XvPortNotifyPtr)NULL; 590 pp->pDraw = (DrawablePtr)NULL; 591 pp->client = (ClientPtr)NULL; 592 pp->grab.client = (ClientPtr)NULL; 593 pp->time = currentTime; 594 pp->devPriv.ptr = portPriv; 595 596 portPriv->pScrn = pScrn; 597 portPriv->AdaptorRec = adaptorPriv; 598 portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr; 599 600 pp++; 601 numPort++; 602 } 603 pa->nPorts = numPort; 604 pa->pPorts = pPort; 605 if(!numPort) { 606 xf86XVFreeAdaptor(pa); 607 continue; 608 } 609 610 pa->base_id = pPort->id; 611 612 pa++; 613 numAdaptor++; 614 } 615 616 if(numAdaptor) { 617 pxvs->nAdaptors = numAdaptor; 618 pxvs->pAdaptors = pAdaptor; 619 } else { 620 free(pAdaptor); 621 return FALSE; 622 } 623 624 return TRUE; 625} 626 627/* Video should be clipped to the intersection of the window cliplist 628 and the client cliplist specified in the GC for which the video was 629 initialized. When we need to reclip a window, the GC that started 630 the video may not even be around anymore. That's why we save the 631 client clip from the GC when the video is initialized. We then 632 use xf86XVUpdateCompositeClip to calculate the new composite clip 633 when we need it. This is different from what DEC did. They saved 634 the GC and used it's clip list when they needed to reclip the window, 635 even if the client clip was different from the one the video was 636 initialized with. If the original GC was destroyed, they had to stop 637 the video. I like the new method better (MArk). 638 639 This function only works for windows. Will need to rewrite when 640 (if) we support pixmap rendering. 641*/ 642 643static void 644xf86XVUpdateCompositeClip(XvPortRecPrivatePtr portPriv) 645{ 646 RegionPtr pregWin, pCompositeClip; 647 WindowPtr pWin; 648 Bool freeCompClip = FALSE; 649 650 if(portPriv->pCompositeClip) 651 return; 652 653 pWin = (WindowPtr)portPriv->pDraw; 654 655 /* get window clip list */ 656 if(portPriv->subWindowMode == IncludeInferiors) { 657 pregWin = NotClippedByChildren(pWin); 658 freeCompClip = TRUE; 659 } else 660 pregWin = &pWin->clipList; 661 662 if(!portPriv->clientClip) { 663 portPriv->pCompositeClip = pregWin; 664 portPriv->FreeCompositeClip = freeCompClip; 665 return; 666 } 667 668 pCompositeClip = RegionCreate(NullBox, 1); 669 RegionCopy(pCompositeClip, portPriv->clientClip); 670 RegionTranslate(pCompositeClip, 671 portPriv->pDraw->x, portPriv->pDraw->y); 672 RegionIntersect(pCompositeClip, pregWin, pCompositeClip); 673 674 portPriv->pCompositeClip = pCompositeClip; 675 portPriv->FreeCompositeClip = TRUE; 676 677 if(freeCompClip) { 678 RegionDestroy(pregWin); 679 } 680} 681 682/* Save the current clientClip and update the CompositeClip whenever 683 we have a fresh GC */ 684 685static void 686xf86XVCopyClip( 687 XvPortRecPrivatePtr portPriv, 688 GCPtr pGC 689){ 690 /* copy the new clip if it exists */ 691 if((pGC->clientClipType == CT_REGION) && pGC->clientClip) { 692 if(!portPriv->clientClip) 693 portPriv->clientClip = RegionCreate(NullBox, 1); 694 /* Note: this is in window coordinates */ 695 RegionCopy(portPriv->clientClip, pGC->clientClip); 696 RegionTranslate(portPriv->clientClip, 697 pGC->clipOrg.x, pGC->clipOrg.y); 698 } else if(portPriv->clientClip) { /* free the old clientClip */ 699 RegionDestroy(portPriv->clientClip); 700 portPriv->clientClip = NULL; 701 } 702 703 /* get rid of the old clip list */ 704 if(portPriv->pCompositeClip && portPriv->FreeCompositeClip) { 705 RegionDestroy(portPriv->pCompositeClip); 706 } 707 708 portPriv->pCompositeClip = pGC->pCompositeClip; 709 portPriv->FreeCompositeClip = FALSE; 710 portPriv->subWindowMode = pGC->subWindowMode; 711} 712 713static void 714xf86XVCopyCompositeClip(XvPortRecPrivatePtr portPriv, 715 GCPtr pGC, 716 DrawablePtr pDraw) 717{ 718 if (!portPriv->clientClip) 719 portPriv->clientClip = RegionCreate(NullBox, 1); 720 /* Keep the original GC composite clip around for ReputImage */ 721 RegionCopy(portPriv->clientClip, pGC->pCompositeClip); 722 RegionTranslate(portPriv->clientClip, 723 -pDraw->x, -pDraw->y); 724 725 /* get rid of the old clip list */ 726 if (portPriv->pCompositeClip && portPriv->FreeCompositeClip) 727 RegionDestroy(portPriv->pCompositeClip); 728 729 portPriv->pCompositeClip = pGC->pCompositeClip; 730 portPriv->FreeCompositeClip = FALSE; 731 portPriv->subWindowMode = pGC->subWindowMode; 732} 733 734static int 735xf86XVRegetVideo(XvPortRecPrivatePtr portPriv) 736{ 737 RegionRec WinRegion; 738 RegionRec ClipRegion; 739 BoxRec WinBox; 740 int ret = Success; 741 Bool clippedAway = FALSE; 742 743 xf86XVUpdateCompositeClip(portPriv); 744 745 /* translate the video region to the screen */ 746 WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; 747 WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; 748 WinBox.x2 = WinBox.x1 + portPriv->drw_w; 749 WinBox.y2 = WinBox.y1 + portPriv->drw_h; 750 751 /* clip to the window composite clip */ 752 RegionInit(&WinRegion, &WinBox, 1); 753 RegionNull(&ClipRegion); 754 RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip); 755 756 /* that's all if it's totally obscured */ 757 if(!RegionNotEmpty(&ClipRegion)) { 758 clippedAway = TRUE; 759 goto CLIP_VIDEO_BAILOUT; 760 } 761 762 if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { 763 RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); 764 } 765 766 ret = (*portPriv->AdaptorRec->GetVideo)(portPriv->pScrn, 767 portPriv->vid_x, portPriv->vid_y, 768 WinBox.x1, WinBox.y1, 769 portPriv->vid_w, portPriv->vid_h, 770 portPriv->drw_w, portPriv->drw_h, 771 &ClipRegion, portPriv->DevPriv.ptr, 772 portPriv->pDraw); 773 774 if(ret == Success) 775 portPriv->isOn = XV_ON; 776 777CLIP_VIDEO_BAILOUT: 778 779 if((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) { 780 (*portPriv->AdaptorRec->StopVideo)( 781 portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); 782 portPriv->isOn = XV_PENDING; 783 } 784 785 /* This clip was copied and only good for one shot */ 786 if(!portPriv->FreeCompositeClip) 787 portPriv->pCompositeClip = NULL; 788 789 RegionUninit(&WinRegion); 790 RegionUninit(&ClipRegion); 791 792 return ret; 793} 794 795 796static int 797xf86XVReputVideo(XvPortRecPrivatePtr portPriv) 798{ 799 RegionRec WinRegion; 800 RegionRec ClipRegion; 801 BoxRec WinBox; 802 int ret = Success; 803 Bool clippedAway = FALSE; 804 805 xf86XVUpdateCompositeClip(portPriv); 806 807 /* translate the video region to the screen */ 808 WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; 809 WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; 810 WinBox.x2 = WinBox.x1 + portPriv->drw_w; 811 WinBox.y2 = WinBox.y1 + portPriv->drw_h; 812 813 /* clip to the window composite clip */ 814 RegionInit(&WinRegion, &WinBox, 1); 815 RegionNull(&ClipRegion); 816 RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip); 817 818 /* clip and translate to the viewport */ 819 if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { 820 RegionRec VPReg; 821 BoxRec VPBox; 822 823 VPBox.x1 = portPriv->pScrn->frameX0; 824 VPBox.y1 = portPriv->pScrn->frameY0; 825 VPBox.x2 = portPriv->pScrn->frameX1 + 1; 826 VPBox.y2 = portPriv->pScrn->frameY1 + 1; 827 828 RegionInit(&VPReg, &VPBox, 1); 829 RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); 830 RegionUninit(&VPReg); 831 } 832 833 /* that's all if it's totally obscured */ 834 if(!RegionNotEmpty(&ClipRegion)) { 835 clippedAway = TRUE; 836 goto CLIP_VIDEO_BAILOUT; 837 } 838 839 /* bailout if we have to clip but the hardware doesn't support it */ 840 if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { 841 BoxPtr clipBox = RegionRects(&ClipRegion); 842 if( (RegionNumRects(&ClipRegion) != 1) || 843 (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || 844 (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) 845 { 846 clippedAway = TRUE; 847 goto CLIP_VIDEO_BAILOUT; 848 } 849 } 850 851 if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { 852 RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); 853 } 854 855 ret = (*portPriv->AdaptorRec->PutVideo)(portPriv->pScrn, 856 portPriv->vid_x, portPriv->vid_y, 857 WinBox.x1, WinBox.y1, 858 portPriv->vid_w, portPriv->vid_h, 859 portPriv->drw_w, portPriv->drw_h, 860 &ClipRegion, portPriv->DevPriv.ptr, 861 portPriv->pDraw); 862 863 if(ret == Success) portPriv->isOn = XV_ON; 864 865CLIP_VIDEO_BAILOUT: 866 867 if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { 868 (*portPriv->AdaptorRec->StopVideo)( 869 portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); 870 portPriv->isOn = XV_PENDING; 871 } 872 873 /* This clip was copied and only good for one shot */ 874 if(!portPriv->FreeCompositeClip) 875 portPriv->pCompositeClip = NULL; 876 877 RegionUninit(&WinRegion); 878 RegionUninit(&ClipRegion); 879 880 return ret; 881} 882 883/* Reput image/still */ 884static int 885xf86XVReputImage(XvPortRecPrivatePtr portPriv) 886{ 887 RegionRec WinRegion; 888 RegionRec ClipRegion; 889 BoxRec WinBox; 890 int ret = Success; 891 Bool clippedAway = FALSE; 892 893 xf86XVUpdateCompositeClip(portPriv); 894 895 /* the clip can get smaller over time */ 896 RegionCopy(portPriv->clientClip, portPriv->pCompositeClip); 897 RegionTranslate(portPriv->clientClip, 898 -portPriv->pDraw->x, -portPriv->pDraw->y); 899 900 /* translate the video region to the screen */ 901 WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; 902 WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; 903 WinBox.x2 = WinBox.x1 + portPriv->drw_w; 904 WinBox.y2 = WinBox.y1 + portPriv->drw_h; 905 906 /* clip to the window composite clip */ 907 RegionInit(&WinRegion, &WinBox, 1); 908 RegionNull(&ClipRegion); 909 RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip); 910 911 /* clip and translate to the viewport */ 912 if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { 913 RegionRec VPReg; 914 BoxRec VPBox; 915 916 VPBox.x1 = portPriv->pScrn->frameX0; 917 VPBox.y1 = portPriv->pScrn->frameY0; 918 VPBox.x2 = portPriv->pScrn->frameX1 + 1; 919 VPBox.y2 = portPriv->pScrn->frameY1 + 1; 920 921 RegionInit(&VPReg, &VPBox, 1); 922 RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); 923 RegionUninit(&VPReg); 924 } 925 926 /* that's all if it's totally obscured */ 927 if(!RegionNotEmpty(&ClipRegion)) { 928 clippedAway = TRUE; 929 goto CLIP_VIDEO_BAILOUT; 930 } 931 932 /* bailout if we have to clip but the hardware doesn't support it */ 933 if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { 934 BoxPtr clipBox = RegionRects(&ClipRegion); 935 if( (RegionNumRects(&ClipRegion) != 1) || 936 (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || 937 (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) 938 { 939 clippedAway = TRUE; 940 goto CLIP_VIDEO_BAILOUT; 941 } 942 } 943 944 if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { 945 RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); 946 } 947 948 ret = (*portPriv->AdaptorRec->ReputImage)(portPriv->pScrn, 949 portPriv->vid_x, portPriv->vid_y, 950 WinBox.x1, WinBox.y1, 951 portPriv->vid_w, portPriv->vid_h, 952 portPriv->drw_w, portPriv->drw_h, 953 &ClipRegion, portPriv->DevPriv.ptr, 954 portPriv->pDraw); 955 956 portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF; 957 958CLIP_VIDEO_BAILOUT: 959 960 if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { 961 (*portPriv->AdaptorRec->StopVideo)( 962 portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); 963 portPriv->isOn = XV_PENDING; 964 } 965 966 /* This clip was copied and only good for one shot */ 967 if(!portPriv->FreeCompositeClip) 968 portPriv->pCompositeClip = NULL; 969 970 RegionUninit(&WinRegion); 971 RegionUninit(&ClipRegion); 972 973 return ret; 974} 975 976 977static int 978xf86XVReputAllVideo(WindowPtr pWin, pointer data) 979{ 980 XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); 981 982 while(WinPriv) { 983 if(WinPriv->PortRec->type == XvInputMask) 984 xf86XVReputVideo(WinPriv->PortRec); 985 else 986 xf86XVRegetVideo(WinPriv->PortRec); 987 WinPriv = WinPriv->next; 988 } 989 990 return WT_WALKCHILDREN; 991} 992 993static int 994xf86XVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv) 995{ 996 XF86XVWindowPtr winPriv, PrivRoot; 997 998 winPriv = PrivRoot = GET_XF86XV_WINDOW(pWin); 999 1000 /* Enlist our port in the window private */ 1001 while(winPriv) { 1002 if(winPriv->PortRec == portPriv) /* we're already listed */ 1003 break; 1004 winPriv = winPriv->next; 1005 } 1006 1007 if(!winPriv) { 1008 winPriv = calloc(1, sizeof(XF86XVWindowRec)); 1009 if(!winPriv) return BadAlloc; 1010 winPriv->PortRec = portPriv; 1011 winPriv->next = PrivRoot; 1012 dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, winPriv); 1013 } 1014 1015 portPriv->pDraw = (DrawablePtr)pWin; 1016 1017 return Success; 1018} 1019 1020 1021static void 1022xf86XVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv) 1023{ 1024 XF86XVWindowPtr winPriv, prevPriv = NULL; 1025 winPriv = GET_XF86XV_WINDOW(pWin); 1026 1027 while(winPriv) { 1028 if(winPriv->PortRec == portPriv) { 1029 if(prevPriv) 1030 prevPriv->next = winPriv->next; 1031 else 1032 dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, 1033 winPriv->next); 1034 free(winPriv); 1035 break; 1036 } 1037 prevPriv = winPriv; 1038 winPriv = winPriv->next; 1039 } 1040 portPriv->pDraw = NULL; 1041 if (portPriv->ckeyFilled) { 1042 RegionDestroy(portPriv->ckeyFilled); 1043 portPriv->ckeyFilled = NULL; 1044 } 1045 portPriv->clipChanged = FALSE; 1046} 1047 1048static void 1049xf86XVReputOrStopPort(XvPortRecPrivatePtr pPriv, 1050 WindowPtr pWin, 1051 Bool visible) 1052{ 1053 if (!visible) { 1054 if (pPriv->isOn == XV_ON) { 1055 (*pPriv->AdaptorRec->StopVideo)(pPriv->pScrn, pPriv->DevPriv.ptr, FALSE); 1056 pPriv->isOn = XV_PENDING; 1057 } 1058 1059 if (!pPriv->type) /* overlaid still/image*/ 1060 xf86XVRemovePortFromWindow(pWin, pPriv); 1061 1062 return; 1063 } 1064 1065 switch (pPriv->type) { 1066 case XvInputMask: 1067 xf86XVReputVideo(pPriv); 1068 break; 1069 case XvOutputMask: 1070 xf86XVRegetVideo(pPriv); 1071 break; 1072 default: /* overlaid still/image*/ 1073 if (pPriv->AdaptorRec->ReputImage) 1074 xf86XVReputImage(pPriv); 1075 break; 1076 } 1077} 1078 1079static void 1080xf86XVReputOrStopAllPorts(ScrnInfoPtr pScrn, Bool onlyChanged) 1081{ 1082 ScreenPtr pScreen = pScrn->pScreen; 1083 XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); 1084 XvAdaptorPtr pa; 1085 int c, i; 1086 1087 for (c = pxvs->nAdaptors, pa = pxvs->pAdaptors; c > 0; c--, pa++) { 1088 XvPortPtr pPort = pa->pPorts; 1089 1090 for (i = pa->nPorts; i > 0; i--, pPort++) { 1091 XvPortRecPrivatePtr pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr; 1092 WindowPtr pWin = (WindowPtr)pPriv->pDraw; 1093 Bool visible; 1094 1095 if (pPriv->isOn == XV_OFF || !pWin) 1096 continue; 1097 1098 if (onlyChanged && !pPriv->clipChanged) 1099 continue; 1100 1101 visible = pWin->visibility == VisibilityUnobscured || 1102 pWin->visibility == VisibilityPartiallyObscured; 1103 1104 /* 1105 * Stop and remove still/images if 1106 * ReputImage isn't supported. 1107 */ 1108 if (!pPriv->type && !pPriv->AdaptorRec->ReputImage) 1109 visible = FALSE; 1110 1111 xf86XVReputOrStopPort(pPriv, pWin, visible); 1112 1113 pPriv->clipChanged = FALSE; 1114 } 1115 } 1116} 1117 1118/**** ScreenRec fields ****/ 1119 1120static Bool 1121xf86XVDestroyWindow(WindowPtr pWin) 1122{ 1123 ScreenPtr pScreen = pWin->drawable.pScreen; 1124 XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); 1125 XF86XVWindowPtr tmp, WinPriv = GET_XF86XV_WINDOW(pWin); 1126 int ret; 1127 1128 while(WinPriv) { 1129 XvPortRecPrivatePtr pPriv = WinPriv->PortRec; 1130 1131 if(pPriv->isOn > XV_OFF) { 1132 (*pPriv->AdaptorRec->StopVideo)( 1133 pPriv->pScrn, pPriv->DevPriv.ptr, TRUE); 1134 pPriv->isOn = XV_OFF; 1135 } 1136 1137 pPriv->pDraw = NULL; 1138 tmp = WinPriv; 1139 WinPriv = WinPriv->next; 1140 free(tmp); 1141 } 1142 1143 dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, NULL); 1144 1145 pScreen->DestroyWindow = ScreenPriv->DestroyWindow; 1146 ret = (*pScreen->DestroyWindow)(pWin); 1147 pScreen->DestroyWindow = xf86XVDestroyWindow; 1148 1149 return ret; 1150} 1151 1152static void 1153xf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin, VTKind kind) 1154{ 1155 ScreenPtr pScreen; 1156 XF86XVScreenPtr ScreenPriv; 1157 ScrnInfoPtr pScrn; 1158 1159 if (pWin) 1160 pScreen = pWin->drawable.pScreen; 1161 else 1162 pScreen = pLayerWin->drawable.pScreen; 1163 1164 ScreenPriv = GET_XF86XV_SCREEN(pScreen); 1165 pScrn = xf86Screens[pScreen->myNum]; 1166 1167 xf86XVReputOrStopAllPorts(pScrn, TRUE); 1168 1169 pScreen->PostValidateTree = ScreenPriv->PostValidateTree; 1170 if (pScreen->PostValidateTree) { 1171 (*pScreen->PostValidateTree)(pWin, pLayerWin, kind); 1172 } 1173 ScreenPriv->PostValidateTree = PostValidateTreeUndefined; 1174} 1175 1176static void 1177xf86XVWindowExposures(WindowPtr pWin, RegionPtr reg1, RegionPtr reg2) 1178{ 1179 ScreenPtr pScreen = pWin->drawable.pScreen; 1180 XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); 1181 XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); 1182 XvPortRecPrivatePtr pPriv; 1183 Bool AreasExposed; 1184 1185 AreasExposed = (WinPriv && reg1 && RegionNotEmpty(reg1)); 1186 1187 pScreen->WindowExposures = ScreenPriv->WindowExposures; 1188 (*pScreen->WindowExposures)(pWin, reg1, reg2); 1189 pScreen->WindowExposures = xf86XVWindowExposures; 1190 1191 /* filter out XClearWindow/Area */ 1192 if (!pWin->valdata) return; 1193 1194 while(WinPriv) { 1195 Bool visible = TRUE; 1196 1197 pPriv = WinPriv->PortRec; 1198 1199 /* 1200 * Stop and remove still/images if areas were exposed and 1201 * ReputImage isn't supported. 1202 */ 1203 if (!pPriv->type && !pPriv->AdaptorRec->ReputImage) 1204 visible = !AreasExposed; 1205 1206 /* 1207 * Subtract exposed areas from overlaid image to match textured video 1208 * behavior. 1209 */ 1210 if (!pPriv->type && pPriv->clientClip) 1211 RegionSubtract(pPriv->clientClip, pPriv->clientClip, reg1); 1212 1213 if (visible && pPriv->ckeyFilled) { 1214 RegionRec tmp; 1215 RegionNull(&tmp); 1216 RegionCopy(&tmp, reg1); 1217 RegionTranslate(&tmp, pWin->drawable.x, pWin->drawable.y); 1218 RegionSubtract(pPriv->ckeyFilled, pPriv->ckeyFilled, &tmp); 1219 } 1220 1221 WinPriv = WinPriv->next; 1222 xf86XVReputOrStopPort(pPriv, pWin, visible); 1223 1224 pPriv->clipChanged = FALSE; 1225 } 1226} 1227 1228static void 1229xf86XVClipNotify(WindowPtr pWin, int dx, int dy) 1230{ 1231 ScreenPtr pScreen = pWin->drawable.pScreen; 1232 XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); 1233 XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); 1234 XvPortRecPrivatePtr pPriv; 1235 1236 while(WinPriv) { 1237 pPriv = WinPriv->PortRec; 1238 1239 if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) 1240 RegionDestroy(pPriv->pCompositeClip); 1241 1242 pPriv->pCompositeClip = NULL; 1243 1244 if (pPriv->AdaptorRec->ClipNotify) 1245 (*pPriv->AdaptorRec->ClipNotify)(pPriv->pScrn, pPriv->DevPriv.ptr, 1246 pWin, dx, dy); 1247 1248 pPriv->clipChanged = TRUE; 1249 1250 if (ScreenPriv->PostValidateTree == PostValidateTreeUndefined) { 1251 ScreenPriv->PostValidateTree = pScreen->PostValidateTree; 1252 pScreen->PostValidateTree = xf86XVPostValidateTree; 1253 } 1254 1255 WinPriv = WinPriv->next; 1256 } 1257 1258 if(ScreenPriv->ClipNotify) { 1259 pScreen->ClipNotify = ScreenPriv->ClipNotify; 1260 (*pScreen->ClipNotify)(pWin, dx, dy); 1261 pScreen->ClipNotify = xf86XVClipNotify; 1262 } 1263} 1264 1265 1266 1267/**** Required XvScreenRec fields ****/ 1268 1269static Bool 1270xf86XVCloseScreen(int i, ScreenPtr pScreen) 1271{ 1272 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1273 XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); 1274 XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); 1275 XvAdaptorPtr pa; 1276 int c; 1277 1278 if(!ScreenPriv) return TRUE; 1279 1280 pScreen->DestroyWindow = ScreenPriv->DestroyWindow; 1281 pScreen->WindowExposures = ScreenPriv->WindowExposures; 1282 pScreen->ClipNotify = ScreenPriv->ClipNotify; 1283 1284 pScrn->EnterVT = ScreenPriv->EnterVT; 1285 pScrn->LeaveVT = ScreenPriv->LeaveVT; 1286 pScrn->AdjustFrame = ScreenPriv->AdjustFrame; 1287 pScrn->ModeSet = ScreenPriv->ModeSet; 1288 1289 for(c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) { 1290 xf86XVFreeAdaptor(pa); 1291 } 1292 1293 free(pxvs->pAdaptors); 1294 free(ScreenPriv); 1295 return TRUE; 1296} 1297 1298 1299static int 1300xf86XVQueryAdaptors( 1301 ScreenPtr pScreen, 1302 XvAdaptorPtr *p_pAdaptors, 1303 int *p_nAdaptors 1304){ 1305 XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); 1306 1307 *p_nAdaptors = pxvs->nAdaptors; 1308 *p_pAdaptors = pxvs->pAdaptors; 1309 1310 return Success; 1311} 1312 1313 1314/**** ScrnInfoRec fields ****/ 1315 1316static Bool 1317xf86XVEnterVT(int index, int flags) 1318{ 1319 ScrnInfoPtr pScrn = xf86Screens[index]; 1320 ScreenPtr pScreen = screenInfo.screens[index]; 1321 XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); 1322 Bool ret; 1323 1324 pScrn->EnterVT = ScreenPriv->EnterVT; 1325 ret = (*ScreenPriv->EnterVT)(index, flags); 1326 ScreenPriv->EnterVT = pScrn->EnterVT; 1327 pScrn->EnterVT = xf86XVEnterVT; 1328 1329 if(ret) WalkTree(pScreen, xf86XVReputAllVideo, 0); 1330 1331 return ret; 1332} 1333 1334static void 1335xf86XVLeaveVT(int index, int flags) 1336{ 1337 ScrnInfoPtr pScrn = xf86Screens[index]; 1338 ScreenPtr pScreen = screenInfo.screens[index]; 1339 XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); 1340 XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); 1341 XvAdaptorPtr pAdaptor; 1342 XvPortPtr pPort; 1343 XvPortRecPrivatePtr pPriv; 1344 int i, j; 1345 1346 for(i = 0; i < pxvs->nAdaptors; i++) { 1347 pAdaptor = &pxvs->pAdaptors[i]; 1348 for(j = 0; j < pAdaptor->nPorts; j++) { 1349 pPort = &pAdaptor->pPorts[j]; 1350 pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr; 1351 if(pPriv->isOn > XV_OFF) { 1352 1353 (*pPriv->AdaptorRec->StopVideo)( 1354 pPriv->pScrn, pPriv->DevPriv.ptr, TRUE); 1355 pPriv->isOn = XV_OFF; 1356 1357 if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) 1358 RegionDestroy(pPriv->pCompositeClip); 1359 1360 pPriv->pCompositeClip = NULL; 1361 1362 if(!pPriv->type && pPriv->pDraw) { /* still */ 1363 xf86XVRemovePortFromWindow((WindowPtr)pPriv->pDraw, pPriv); 1364 } 1365 } 1366 } 1367 } 1368 1369 pScrn->LeaveVT = ScreenPriv->LeaveVT; 1370 (*ScreenPriv->LeaveVT)(index, flags); 1371 ScreenPriv->LeaveVT = pScrn->LeaveVT; 1372 pScrn->LeaveVT = xf86XVLeaveVT; 1373} 1374 1375static void 1376xf86XVAdjustFrame(int index, int x, int y, int flags) 1377{ 1378 ScrnInfoPtr pScrn = xf86Screens[index]; 1379 ScreenPtr pScreen = pScrn->pScreen; 1380 XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); 1381 1382 if(ScreenPriv->AdjustFrame) { 1383 pScrn->AdjustFrame = ScreenPriv->AdjustFrame; 1384 (*pScrn->AdjustFrame)(index, x, y, flags); 1385 pScrn->AdjustFrame = xf86XVAdjustFrame; 1386 } 1387 1388 xf86XVReputOrStopAllPorts(pScrn, FALSE); 1389} 1390 1391static void 1392xf86XVModeSet(ScrnInfoPtr pScrn) 1393{ 1394 ScreenPtr pScreen = pScrn->pScreen; 1395 XF86XVScreenPtr ScreenPriv; 1396 1397 /* Can be called before pScrn->pScreen is set */ 1398 if (!pScreen) 1399 return; 1400 1401 ScreenPriv = GET_XF86XV_SCREEN(pScreen); 1402 1403 if (ScreenPriv->ModeSet) { 1404 pScrn->ModeSet = ScreenPriv->ModeSet; 1405 (*pScrn->ModeSet)(pScrn); 1406 pScrn->ModeSet = xf86XVModeSet; 1407 } 1408 1409 xf86XVReputOrStopAllPorts(pScrn, FALSE); 1410} 1411 1412/**** XvAdaptorRec fields ****/ 1413 1414static int 1415xf86XVAllocatePort( 1416 unsigned long port, 1417 XvPortPtr pPort, 1418 XvPortPtr *ppPort 1419){ 1420 *ppPort = pPort; 1421 return Success; 1422} 1423 1424 1425 1426static int 1427xf86XVFreePort(XvPortPtr pPort) 1428{ 1429 return Success; 1430} 1431 1432 1433static int 1434xf86XVPutVideo( 1435 ClientPtr client, 1436 DrawablePtr pDraw, 1437 XvPortPtr pPort, 1438 GCPtr pGC, 1439 INT16 vid_x, INT16 vid_y, 1440 CARD16 vid_w, CARD16 vid_h, 1441 INT16 drw_x, INT16 drw_y, 1442 CARD16 drw_w, CARD16 drw_h 1443){ 1444 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1445 int result; 1446 1447 /* No dumping video to pixmaps... For now anyhow */ 1448 if(pDraw->type != DRAWABLE_WINDOW) { 1449 pPort->pDraw = (DrawablePtr)NULL; 1450 return BadAlloc; 1451 } 1452 1453 /* If we are changing windows, unregister our port in the old window */ 1454 if(portPriv->pDraw && (portPriv->pDraw != pDraw)) 1455 xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); 1456 1457 /* Register our port with the new window */ 1458 result = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); 1459 if(result != Success) return result; 1460 1461 portPriv->type = XvInputMask; 1462 1463 /* save a copy of these parameters */ 1464 portPriv->vid_x = vid_x; portPriv->vid_y = vid_y; 1465 portPriv->vid_w = vid_w; portPriv->vid_h = vid_h; 1466 portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; 1467 portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; 1468 1469 /* make sure we have the most recent copy of the clientClip */ 1470 xf86XVCopyClip(portPriv, pGC); 1471 1472 /* To indicate to the DI layer that we were successful */ 1473 pPort->pDraw = pDraw; 1474 1475 if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ 1476 1477 return(xf86XVReputVideo(portPriv)); 1478} 1479 1480static int 1481xf86XVPutStill( 1482 ClientPtr client, 1483 DrawablePtr pDraw, 1484 XvPortPtr pPort, 1485 GCPtr pGC, 1486 INT16 vid_x, INT16 vid_y, 1487 CARD16 vid_w, CARD16 vid_h, 1488 INT16 drw_x, INT16 drw_y, 1489 CARD16 drw_w, CARD16 drw_h 1490){ 1491 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1492 RegionRec WinRegion; 1493 RegionRec ClipRegion; 1494 BoxRec WinBox; 1495 int ret = Success; 1496 Bool clippedAway = FALSE; 1497 1498 if (pDraw->type != DRAWABLE_WINDOW) 1499 return BadAlloc; 1500 1501 if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ 1502 1503 WinBox.x1 = pDraw->x + drw_x; 1504 WinBox.y1 = pDraw->y + drw_y; 1505 WinBox.x2 = WinBox.x1 + drw_w; 1506 WinBox.y2 = WinBox.y1 + drw_h; 1507 1508 xf86XVCopyCompositeClip(portPriv, pGC, pDraw); 1509 1510 RegionInit(&WinRegion, &WinBox, 1); 1511 RegionNull(&ClipRegion); 1512 RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip); 1513 1514 if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { 1515 RegionRec VPReg; 1516 BoxRec VPBox; 1517 1518 VPBox.x1 = portPriv->pScrn->frameX0; 1519 VPBox.y1 = portPriv->pScrn->frameY0; 1520 VPBox.x2 = portPriv->pScrn->frameX1 + 1; 1521 VPBox.y2 = portPriv->pScrn->frameY1 + 1; 1522 1523 RegionInit(&VPReg, &VPBox, 1); 1524 RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); 1525 RegionUninit(&VPReg); 1526 } 1527 1528 if(portPriv->pDraw) { 1529 xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); 1530 } 1531 1532 if(!RegionNotEmpty(&ClipRegion)) { 1533 clippedAway = TRUE; 1534 goto PUT_STILL_BAILOUT; 1535 } 1536 1537 if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { 1538 BoxPtr clipBox = RegionRects(&ClipRegion); 1539 if( (RegionNumRects(&ClipRegion) != 1) || 1540 (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || 1541 (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) 1542 { 1543 clippedAway = TRUE; 1544 goto PUT_STILL_BAILOUT; 1545 } 1546 } 1547 1548 if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { 1549 RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); 1550 } 1551 1552 ret = (*portPriv->AdaptorRec->PutStill)(portPriv->pScrn, 1553 vid_x, vid_y, WinBox.x1, WinBox.y1, 1554 vid_w, vid_h, drw_w, drw_h, 1555 &ClipRegion, portPriv->DevPriv.ptr, 1556 pDraw); 1557 1558 if((ret == Success) && 1559 (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) { 1560 1561 xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); 1562 portPriv->isOn = XV_ON; 1563 portPriv->vid_x = vid_x; portPriv->vid_y = vid_y; 1564 portPriv->vid_w = vid_w; portPriv->vid_h = vid_h; 1565 portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; 1566 portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; 1567 portPriv->type = 0; /* no mask means it's transient and should 1568 not be reput once it's removed */ 1569 pPort->pDraw = pDraw; /* make sure we can get stop requests */ 1570 } 1571 1572PUT_STILL_BAILOUT: 1573 1574 if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { 1575 (*portPriv->AdaptorRec->StopVideo)( 1576 portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); 1577 portPriv->isOn = XV_PENDING; 1578 } 1579 1580 /* This clip was copied and only good for one shot */ 1581 if(!portPriv->FreeCompositeClip) 1582 portPriv->pCompositeClip = NULL; 1583 1584 RegionUninit(&WinRegion); 1585 RegionUninit(&ClipRegion); 1586 1587 return ret; 1588} 1589 1590static int 1591xf86XVGetVideo( 1592 ClientPtr client, 1593 DrawablePtr pDraw, 1594 XvPortPtr pPort, 1595 GCPtr pGC, 1596 INT16 vid_x, INT16 vid_y, 1597 CARD16 vid_w, CARD16 vid_h, 1598 INT16 drw_x, INT16 drw_y, 1599 CARD16 drw_w, CARD16 drw_h 1600){ 1601 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1602 int result; 1603 1604 /* No pixmaps... For now anyhow */ 1605 if(pDraw->type != DRAWABLE_WINDOW) { 1606 pPort->pDraw = (DrawablePtr)NULL; 1607 return BadAlloc; 1608 } 1609 1610 /* If we are changing windows, unregister our port in the old window */ 1611 if(portPriv->pDraw && (portPriv->pDraw != pDraw)) 1612 xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); 1613 1614 /* Register our port with the new window */ 1615 result = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); 1616 if(result != Success) return result; 1617 1618 portPriv->type = XvOutputMask; 1619 1620 /* save a copy of these parameters */ 1621 portPriv->vid_x = vid_x; portPriv->vid_y = vid_y; 1622 portPriv->vid_w = vid_w; portPriv->vid_h = vid_h; 1623 portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; 1624 portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; 1625 1626 /* make sure we have the most recent copy of the clientClip */ 1627 xf86XVCopyClip(portPriv, pGC); 1628 1629 /* To indicate to the DI layer that we were successful */ 1630 pPort->pDraw = pDraw; 1631 1632 if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ 1633 1634 return(xf86XVRegetVideo(portPriv)); 1635} 1636 1637static int 1638xf86XVGetStill( 1639 ClientPtr client, 1640 DrawablePtr pDraw, 1641 XvPortPtr pPort, 1642 GCPtr pGC, 1643 INT16 vid_x, INT16 vid_y, 1644 CARD16 vid_w, CARD16 vid_h, 1645 INT16 drw_x, INT16 drw_y, 1646 CARD16 drw_w, CARD16 drw_h 1647){ 1648 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1649 RegionRec WinRegion; 1650 RegionRec ClipRegion; 1651 BoxRec WinBox; 1652 int ret = Success; 1653 Bool clippedAway = FALSE; 1654 1655 if (pDraw->type != DRAWABLE_WINDOW) 1656 return BadAlloc; 1657 1658 if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ 1659 1660 WinBox.x1 = pDraw->x + drw_x; 1661 WinBox.y1 = pDraw->y + drw_y; 1662 WinBox.x2 = WinBox.x1 + drw_w; 1663 WinBox.y2 = WinBox.y1 + drw_h; 1664 1665 RegionInit(&WinRegion, &WinBox, 1); 1666 RegionNull(&ClipRegion); 1667 RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip); 1668 1669 if(portPriv->pDraw) { 1670 xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); 1671 } 1672 1673 if(!RegionNotEmpty(&ClipRegion)) { 1674 clippedAway = TRUE; 1675 goto GET_STILL_BAILOUT; 1676 } 1677 1678 if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { 1679 RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); 1680 } 1681 1682 ret = (*portPriv->AdaptorRec->GetStill)(portPriv->pScrn, 1683 vid_x, vid_y, WinBox.x1, WinBox.y1, 1684 vid_w, vid_h, drw_w, drw_h, 1685 &ClipRegion, portPriv->DevPriv.ptr, 1686 pDraw); 1687 1688GET_STILL_BAILOUT: 1689 1690 if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { 1691 (*portPriv->AdaptorRec->StopVideo)( 1692 portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); 1693 portPriv->isOn = XV_PENDING; 1694 } 1695 1696 RegionUninit(&WinRegion); 1697 RegionUninit(&ClipRegion); 1698 1699 return ret; 1700} 1701 1702 1703 1704static int 1705xf86XVStopVideo( 1706 ClientPtr client, 1707 XvPortPtr pPort, 1708 DrawablePtr pDraw 1709){ 1710 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1711 1712 if(pDraw->type != DRAWABLE_WINDOW) 1713 return BadAlloc; 1714 1715 xf86XVRemovePortFromWindow((WindowPtr)pDraw, portPriv); 1716 1717 if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ 1718 1719 /* Must free resources. */ 1720 1721 if(portPriv->isOn > XV_OFF) { 1722 (*portPriv->AdaptorRec->StopVideo)( 1723 portPriv->pScrn, portPriv->DevPriv.ptr, TRUE); 1724 portPriv->isOn = XV_OFF; 1725 } 1726 1727 return Success; 1728} 1729 1730static int 1731xf86XVSetPortAttribute( 1732 ClientPtr client, 1733 XvPortPtr pPort, 1734 Atom attribute, 1735 INT32 value 1736){ 1737 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1738 1739 return((*portPriv->AdaptorRec->SetPortAttribute)(portPriv->pScrn, 1740 attribute, value, portPriv->DevPriv.ptr)); 1741} 1742 1743 1744static int 1745xf86XVGetPortAttribute( 1746 ClientPtr client, 1747 XvPortPtr pPort, 1748 Atom attribute, 1749 INT32 *p_value 1750){ 1751 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1752 1753 return((*portPriv->AdaptorRec->GetPortAttribute)(portPriv->pScrn, 1754 attribute, p_value, portPriv->DevPriv.ptr)); 1755} 1756 1757 1758 1759static int 1760xf86XVQueryBestSize( 1761 ClientPtr client, 1762 XvPortPtr pPort, 1763 CARD8 motion, 1764 CARD16 vid_w, CARD16 vid_h, 1765 CARD16 drw_w, CARD16 drw_h, 1766 unsigned int *p_w, unsigned int *p_h 1767){ 1768 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1769 1770 (*portPriv->AdaptorRec->QueryBestSize)(portPriv->pScrn, 1771 (Bool)motion, vid_w, vid_h, drw_w, drw_h, 1772 p_w, p_h, portPriv->DevPriv.ptr); 1773 1774 return Success; 1775} 1776 1777 1778static int 1779xf86XVPutImage( 1780 ClientPtr client, 1781 DrawablePtr pDraw, 1782 XvPortPtr pPort, 1783 GCPtr pGC, 1784 INT16 src_x, INT16 src_y, 1785 CARD16 src_w, CARD16 src_h, 1786 INT16 drw_x, INT16 drw_y, 1787 CARD16 drw_w, CARD16 drw_h, 1788 XvImagePtr format, 1789 unsigned char* data, 1790 Bool sync, 1791 CARD16 width, CARD16 height 1792){ 1793 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1794 RegionRec WinRegion; 1795 RegionRec ClipRegion; 1796 BoxRec WinBox; 1797 int ret = Success; 1798 Bool clippedAway = FALSE; 1799 1800 if (pDraw->type != DRAWABLE_WINDOW) 1801 return BadAlloc; 1802 1803 if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ 1804 1805 xf86XVCopyCompositeClip(portPriv, pGC, pDraw); 1806 1807 WinBox.x1 = pDraw->x + drw_x; 1808 WinBox.y1 = pDraw->y + drw_y; 1809 WinBox.x2 = WinBox.x1 + drw_w; 1810 WinBox.y2 = WinBox.y1 + drw_h; 1811 1812 RegionInit(&WinRegion, &WinBox, 1); 1813 RegionNull(&ClipRegion); 1814 RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip); 1815 1816 if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { 1817 RegionRec VPReg; 1818 BoxRec VPBox; 1819 1820 VPBox.x1 = portPriv->pScrn->frameX0; 1821 VPBox.y1 = portPriv->pScrn->frameY0; 1822 VPBox.x2 = portPriv->pScrn->frameX1 + 1; 1823 VPBox.y2 = portPriv->pScrn->frameY1 + 1; 1824 1825 RegionInit(&VPReg, &VPBox, 1); 1826 RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); 1827 RegionUninit(&VPReg); 1828 } 1829 1830 /* If we are changing windows, unregister our port in the old window */ 1831 if(portPriv->pDraw && (portPriv->pDraw != pDraw)) 1832 xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); 1833 1834 /* Register our port with the new window */ 1835 ret = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); 1836 if(ret != Success) goto PUT_IMAGE_BAILOUT; 1837 1838 if(!RegionNotEmpty(&ClipRegion)) { 1839 clippedAway = TRUE; 1840 goto PUT_IMAGE_BAILOUT; 1841 } 1842 1843 if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { 1844 BoxPtr clipBox = RegionRects(&ClipRegion); 1845 if( (RegionNumRects(&ClipRegion) != 1) || 1846 (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || 1847 (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) 1848 { 1849 clippedAway = TRUE; 1850 goto PUT_IMAGE_BAILOUT; 1851 } 1852 } 1853 1854 if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { 1855 RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); 1856 } 1857 1858 ret = (*portPriv->AdaptorRec->PutImage)(portPriv->pScrn, 1859 src_x, src_y, WinBox.x1, WinBox.y1, 1860 src_w, src_h, drw_w, drw_h, format->id, data, width, height, 1861 sync, &ClipRegion, portPriv->DevPriv.ptr, 1862 pDraw); 1863 1864 if((ret == Success) && 1865 (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) { 1866 1867 portPriv->isOn = XV_ON; 1868 portPriv->vid_x = src_x; portPriv->vid_y = src_y; 1869 portPriv->vid_w = src_w; portPriv->vid_h = src_h; 1870 portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; 1871 portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; 1872 portPriv->type = 0; /* no mask means it's transient and should 1873 not be reput once it's removed */ 1874 pPort->pDraw = pDraw; /* make sure we can get stop requests */ 1875 } 1876 1877PUT_IMAGE_BAILOUT: 1878 1879 if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { 1880 (*portPriv->AdaptorRec->StopVideo)( 1881 portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); 1882 portPriv->isOn = XV_PENDING; 1883 } 1884 1885 /* This clip was copied and only good for one shot */ 1886 if(!portPriv->FreeCompositeClip) 1887 portPriv->pCompositeClip = NULL; 1888 1889 RegionUninit(&WinRegion); 1890 RegionUninit(&ClipRegion); 1891 1892 return ret; 1893} 1894 1895 1896static int 1897xf86XVQueryImageAttributes( 1898 ClientPtr client, 1899 XvPortPtr pPort, 1900 XvImagePtr format, 1901 CARD16 *width, 1902 CARD16 *height, 1903 int *pitches, 1904 int *offsets 1905){ 1906 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); 1907 1908 return (*portPriv->AdaptorRec->QueryImageAttributes)(portPriv->pScrn, 1909 format->id, width, height, pitches, offsets); 1910} 1911 1912void 1913xf86XVFillKeyHelperDrawable (DrawablePtr pDraw, CARD32 key, RegionPtr fillboxes) 1914{ 1915 ScreenPtr pScreen = pDraw->pScreen; 1916 ChangeGCVal pval[2]; 1917 BoxPtr pbox = RegionRects(fillboxes); 1918 int i, nbox = RegionNumRects(fillboxes); 1919 xRectangle *rects; 1920 GCPtr gc; 1921 1922 if(!xf86Screens[pScreen->myNum]->vtSema) return; 1923 1924 gc = GetScratchGC(pDraw->depth, pScreen); 1925 pval[0].val = key; 1926 pval[1].val = IncludeInferiors; 1927 (void) ChangeGC(NullClient, gc, GCForeground|GCSubwindowMode, pval); 1928 ValidateGC(pDraw, gc); 1929 1930 rects = malloc(nbox * sizeof(xRectangle)); 1931 1932 for(i = 0; i < nbox; i++, pbox++) 1933 { 1934 rects[i].x = pbox->x1 - pDraw->x; 1935 rects[i].y = pbox->y1 - pDraw->y; 1936 rects[i].width = pbox->x2 - pbox->x1; 1937 rects[i].height = pbox->y2 - pbox->y1; 1938 } 1939 1940 (*gc->ops->PolyFillRect)(pDraw, gc, nbox, rects); 1941 1942 free(rects); 1943 FreeScratchGC (gc); 1944} 1945 1946void 1947xf86XVFillKeyHelper (ScreenPtr pScreen, CARD32 key, RegionPtr fillboxes) 1948{ 1949 xf86XVFillKeyHelperDrawable (&pScreen->root->drawable, key, fillboxes); 1950} 1951 1952void 1953xf86XVFillKeyHelperPort (DrawablePtr pDraw, pointer data, CARD32 key, RegionPtr clipboxes, Bool fillEverything) 1954{ 1955 WindowPtr pWin = (WindowPtr)pDraw; 1956 XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); 1957 XvPortRecPrivatePtr portPriv = NULL; 1958 RegionRec reg; 1959 RegionPtr fillboxes; 1960 1961 while (WinPriv) { 1962 XvPortRecPrivatePtr pPriv = WinPriv->PortRec; 1963 1964 if (data == pPriv->DevPriv.ptr) { 1965 portPriv = pPriv; 1966 break; 1967 } 1968 1969 WinPriv = WinPriv->next; 1970 } 1971 1972 if (!portPriv) 1973 return; 1974 1975 if (!portPriv->ckeyFilled) 1976 portPriv->ckeyFilled = RegionCreate(NULL, 0); 1977 1978 if (!fillEverything) { 1979 RegionNull(®); 1980 fillboxes = ® 1981 RegionSubtract(fillboxes, clipboxes, portPriv->ckeyFilled); 1982 1983 if (!RegionNotEmpty(fillboxes)) 1984 goto out; 1985 } else 1986 fillboxes = clipboxes; 1987 1988 1989 RegionCopy(portPriv->ckeyFilled, clipboxes); 1990 1991 xf86XVFillKeyHelperDrawable(pDraw, key, fillboxes); 1992out: 1993 if (!fillEverything) 1994 RegionUninit(®); 1995} 1996 1997 1998/* xf86XVClipVideoHelper - 1999 2000 Takes the dst box in standard X BoxRec form (top and left 2001 edges inclusive, bottom and right exclusive). The new dst 2002 box is returned. The source boundaries are given (x1, y1 2003 inclusive, x2, y2 exclusive) and returned are the new source 2004 boundaries in 16.16 fixed point. 2005*/ 2006 2007Bool 2008xf86XVClipVideoHelper( 2009 BoxPtr dst, 2010 INT32 *xa, 2011 INT32 *xb, 2012 INT32 *ya, 2013 INT32 *yb, 2014 RegionPtr reg, 2015 INT32 width, 2016 INT32 height 2017){ 2018 double xsw, xdw, ysw, ydw; 2019 INT32 delta; 2020 BoxPtr extents = RegionExtents(reg); 2021 int diff; 2022 2023 xsw = (*xb - *xa) << 16; 2024 xdw = dst->x2 - dst->x1; 2025 ysw = (*yb - *ya) << 16; 2026 ydw = dst->y2 - dst->y1; 2027 2028 *xa <<= 16; *xb <<= 16; 2029 *ya <<= 16; *yb <<= 16; 2030 2031 diff = extents->x1 - dst->x1; 2032 if (diff > 0) { 2033 dst->x1 = extents->x1; 2034 *xa += (diff * xsw) / xdw; 2035 } 2036 diff = dst->x2 - extents->x2; 2037 if (diff > 0) { 2038 dst->x2 = extents->x2; 2039 *xb -= (diff * xsw) / xdw; 2040 } 2041 diff = extents->y1 - dst->y1; 2042 if (diff > 0) { 2043 dst->y1 = extents->y1; 2044 *ya += (diff * ysw) / ydw; 2045 } 2046 diff = dst->y2 - extents->y2; 2047 if (diff > 0) { 2048 dst->y2 = extents->y2; 2049 *yb -= (diff * ysw) / ydw; 2050 } 2051 2052 if (*xa < 0) { 2053 diff = (((-*xa) * xdw) + xsw - 1) / xsw; 2054 dst->x1 += diff; 2055 *xa += (diff * xsw) / xdw; 2056 } 2057 delta = *xb - (width << 16); 2058 if (delta > 0) { 2059 diff = ((delta * xdw) + xsw - 1) / xsw; 2060 dst->x2 -= diff; 2061 *xb -= (diff * xsw) / xdw; 2062 } 2063 if (*xa >= *xb) return FALSE; 2064 2065 if (*ya < 0) { 2066 diff = (((-*ya) * ydw) + ysw - 1) / ysw; 2067 dst->y1 += diff; 2068 *ya += (diff * ysw) / ydw; 2069 } 2070 delta = *yb - (height << 16); 2071 if (delta > 0) { 2072 diff = ((delta * ydw) + ysw - 1) / ysw; 2073 dst->y2 -= diff; 2074 *yb -= (diff * ysw) / ydw; 2075 } 2076 if (*ya >= *yb) return FALSE; 2077 2078 if ((dst->x1 > extents->x1) || (dst->x2 < extents->x2) || 2079 (dst->y1 > extents->y1) || (dst->y2 < extents->y2)) 2080 { 2081 RegionRec clipReg; 2082 RegionInit(&clipReg, dst, 1); 2083 RegionIntersect(reg, reg, &clipReg); 2084 RegionUninit(&clipReg); 2085 } 2086 return TRUE; 2087} 2088 2089void 2090xf86XVCopyYUV12ToPacked( 2091 const void *srcy, 2092 const void *srcv, 2093 const void *srcu, 2094 void *dst, 2095 int srcPitchy, 2096 int srcPitchuv, 2097 int dstPitch, 2098 int h, 2099 int w 2100){ 2101 CARD32 *Dst; 2102 const CARD8 *Y, *U, *V; 2103 int i, j; 2104 2105 w >>= 1; 2106 2107 for (j = 0; j < h; j++) { 2108 Dst = dst; 2109 Y = srcy; V = srcv; U = srcu; 2110 i = w; 2111 while (i >= 4) { 2112#if X_BYTE_ORDER == X_LITTLE_ENDIAN 2113 Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24); 2114 Dst[1] = Y[2] | (Y[3] << 16) | (U[1] << 8) | (V[1] << 24); 2115 Dst[2] = Y[4] | (Y[5] << 16) | (U[2] << 8) | (V[2] << 24); 2116 Dst[3] = Y[6] | (Y[7] << 16) | (U[3] << 8) | (V[3] << 24); 2117#else 2118 /* This assumes a little-endian framebuffer */ 2119 Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0]; 2120 Dst[1] = (Y[2] << 24) | (Y[3] << 8) | (U[1] << 16) | V[1]; 2121 Dst[2] = (Y[4] << 24) | (Y[5] << 8) | (U[2] << 16) | V[2]; 2122 Dst[3] = (Y[6] << 24) | (Y[7] << 8) | (U[3] << 16) | V[3]; 2123#endif 2124 Dst += 4; Y += 8; V += 4; U += 4; 2125 i -= 4; 2126 } 2127 2128 while (i--) { 2129#if X_BYTE_ORDER == X_LITTLE_ENDIAN 2130 Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24); 2131#else 2132 /* This assumes a little-endian framebuffer */ 2133 Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0]; 2134#endif 2135 Dst++; Y += 2; V++; U++; 2136 } 2137 2138 dst = (CARD8 *)dst + dstPitch; 2139 srcy = (const CARD8 *)srcy + srcPitchy; 2140 if (j & 1) { 2141 srcu = (const CARD8 *)srcu + srcPitchuv; 2142 srcv = (const CARD8 *)srcv + srcPitchuv; 2143 } 2144 } 2145} 2146 2147void 2148xf86XVCopyPacked( 2149 const void *src, 2150 void *dst, 2151 int srcPitch, 2152 int dstPitch, 2153 int h, 2154 int w 2155){ 2156 const CARD32 *Src; 2157 CARD32 *Dst; 2158 int i; 2159 2160 w >>= 1; 2161 while (--h >= 0) { 2162 do { 2163 Dst = dst; Src = src; 2164 i = w; 2165 while (i >= 4) { 2166 Dst[0] = Src[0]; 2167 Dst[1] = Src[1]; 2168 Dst[2] = Src[2]; 2169 Dst[3] = Src[3]; 2170 Dst += 4; Src += 4; i -= 4; 2171 } 2172 if (!i) break; 2173 Dst[0] = Src[0]; 2174 if (i == 1) break; 2175 Dst[1] = Src[1]; 2176 if (i == 2) break; 2177 Dst[2] = Src[2]; 2178 } while (0); 2179 2180 src = (const CARD8 *)src + srcPitch; 2181 dst = (CARD8 *)dst + dstPitch; 2182 } 2183} 2184