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