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