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