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