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