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