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