kxv.c revision 35c4bbdf
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/* XvAdaptorRec fields */ 60 61static int KdXVPutVideo(DrawablePtr, XvPortPtr, GCPtr, 62 INT16, INT16, CARD16, CARD16, 63 INT16, INT16, CARD16, CARD16); 64static int KdXVPutStill(DrawablePtr, XvPortPtr, GCPtr, 65 INT16, INT16, CARD16, CARD16, 66 INT16, INT16, CARD16, CARD16); 67static int KdXVGetVideo(DrawablePtr, XvPortPtr, GCPtr, 68 INT16, INT16, CARD16, CARD16, 69 INT16, INT16, CARD16, CARD16); 70static int KdXVGetStill(DrawablePtr, XvPortPtr, GCPtr, 71 INT16, INT16, CARD16, CARD16, 72 INT16, INT16, CARD16, CARD16); 73static int KdXVStopVideo(XvPortPtr, DrawablePtr); 74static int KdXVSetPortAttribute(XvPortPtr, Atom, INT32); 75static int KdXVGetPortAttribute(XvPortPtr, Atom, INT32 *); 76static int KdXVQueryBestSize(XvPortPtr, CARD8, 77 CARD16, CARD16, CARD16, CARD16, 78 unsigned int *, unsigned int *); 79static int KdXVPutImage(DrawablePtr, XvPortPtr, GCPtr, 80 INT16, INT16, CARD16, CARD16, 81 INT16, INT16, CARD16, CARD16, 82 XvImagePtr, unsigned char *, Bool, CARD16, CARD16); 83static int KdXVQueryImageAttributes(XvPortPtr, XvImagePtr, 84 CARD16 *, CARD16 *, int *, int *); 85 86/* ScreenRec fields */ 87 88static Bool KdXVDestroyWindow(WindowPtr pWin); 89static void KdXVWindowExposures(WindowPtr pWin, RegionPtr r1); 90static void KdXVClipNotify(WindowPtr pWin, int dx, int dy); 91static Bool KdXVCloseScreen(ScreenPtr); 92 93/* misc */ 94static Bool KdXVInitAdaptors(ScreenPtr, KdVideoAdaptorPtr, int); 95 96static DevPrivateKeyRec KdXVWindowKeyRec; 97 98#define KdXVWindowKey (&KdXVWindowKeyRec) 99static DevPrivateKey KdXvScreenKey; 100static DevPrivateKeyRec KdXVScreenPrivateKey; 101static unsigned long KdXVGeneration = 0; 102static unsigned long PortResource = 0; 103 104#define GET_XV_SCREEN(pScreen) ((XvScreenPtr) \ 105 dixLookupPrivate(&(pScreen)->devPrivates, KdXvScreenKey)) 106 107#define GET_KDXV_SCREEN(pScreen) \ 108 ((KdXVScreenPtr)(dixGetPrivate(&pScreen->devPrivates, &KdXVScreenPrivateKey))) 109 110#define GET_KDXV_WINDOW(pWin) ((KdXVWindowPtr) \ 111 dixLookupPrivate(&(pWin)->devPrivates, KdXVWindowKey)) 112 113KdVideoAdaptorPtr 114KdXVAllocateVideoAdaptorRec(KdScreenInfo * screen) 115{ 116 return calloc(1, sizeof(KdVideoAdaptorRec)); 117} 118 119void 120KdXVFreeVideoAdaptorRec(KdVideoAdaptorPtr ptr) 121{ 122 free(ptr); 123} 124 125Bool 126KdXVScreenInit(ScreenPtr pScreen, KdVideoAdaptorPtr adaptors, int num) 127{ 128 KdXVScreenPtr ScreenPriv; 129 130/* fprintf(stderr,"KdXVScreenInit initializing %d adaptors\n",num); */ 131 132 if (KdXVGeneration != serverGeneration) 133 KdXVGeneration = serverGeneration; 134 135 if (noXvExtension) 136 return FALSE; 137 138 if (!dixRegisterPrivateKey(&KdXVWindowKeyRec, PRIVATE_WINDOW, 0)) 139 return FALSE; 140 if (!dixRegisterPrivateKey(&KdXVScreenPrivateKey, PRIVATE_SCREEN, 0)) 141 return FALSE; 142 143 if (Success != XvScreenInit(pScreen)) 144 return FALSE; 145 146 KdXvScreenKey = XvGetScreenKey(); 147 PortResource = XvGetRTPort(); 148 149 ScreenPriv = malloc(sizeof(KdXVScreenRec)); 150 dixSetPrivate(&pScreen->devPrivates, &KdXVScreenPrivateKey, ScreenPriv); 151 152 if (!ScreenPriv) 153 return FALSE; 154 155 ScreenPriv->DestroyWindow = pScreen->DestroyWindow; 156 ScreenPriv->WindowExposures = pScreen->WindowExposures; 157 ScreenPriv->ClipNotify = pScreen->ClipNotify; 158 ScreenPriv->CloseScreen = pScreen->CloseScreen; 159 160/* fprintf(stderr,"XV: Wrapping screen funcs\n"); */ 161 162 pScreen->DestroyWindow = KdXVDestroyWindow; 163 pScreen->WindowExposures = KdXVWindowExposures; 164 pScreen->ClipNotify = KdXVClipNotify; 165 pScreen->CloseScreen = KdXVCloseScreen; 166 167 if (!KdXVInitAdaptors(pScreen, adaptors, num)) 168 return FALSE; 169 170 return TRUE; 171} 172 173static void 174KdXVFreeAdaptor(XvAdaptorPtr pAdaptor) 175{ 176 int i; 177 178 if (pAdaptor->pPorts) { 179 XvPortPtr pPort = pAdaptor->pPorts; 180 XvPortRecPrivatePtr pPriv; 181 182 for (i = 0; i < pAdaptor->nPorts; i++, pPort++) { 183 pPriv = (XvPortRecPrivatePtr) pPort->devPriv.ptr; 184 if (pPriv) { 185 if (pPriv->clientClip) 186 RegionDestroy(pPriv->clientClip); 187 if (pPriv->pCompositeClip && pPriv->FreeCompositeClip) 188 RegionDestroy(pPriv->pCompositeClip); 189 free(pPriv); 190 } 191 } 192 } 193 194 XvFreeAdaptor(pAdaptor); 195} 196 197static Bool 198KdXVInitAdaptors(ScreenPtr pScreen, KdVideoAdaptorPtr infoPtr, int number) 199{ 200 KdScreenPriv(pScreen); 201 KdScreenInfo *screen = pScreenPriv->screen; 202 203 XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); 204 KdVideoAdaptorPtr adaptorPtr; 205 XvAdaptorPtr pAdaptor, pa; 206 XvAdaptorRecPrivatePtr adaptorPriv; 207 int na, numAdaptor; 208 XvPortRecPrivatePtr portPriv; 209 XvPortPtr pPort, pp; 210 int numPort; 211 KdVideoFormatPtr formatPtr; 212 XvFormatPtr pFormat, pf; 213 int numFormat, totFormat; 214 KdVideoEncodingPtr encodingPtr; 215 XvEncodingPtr pEncode, pe; 216 int numVisuals; 217 VisualPtr pVisual; 218 int i; 219 220 pxvs->nAdaptors = 0; 221 pxvs->pAdaptors = NULL; 222 223 if (!(pAdaptor = calloc(number, sizeof(XvAdaptorRec)))) 224 return FALSE; 225 226 for (pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) { 227 adaptorPtr = &infoPtr[na]; 228 229 if (!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute || 230 !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize) 231 continue; 232 233 /* client libs expect at least one encoding */ 234 if (!adaptorPtr->nEncodings || !adaptorPtr->pEncodings) 235 continue; 236 237 pa->type = adaptorPtr->type; 238 239 if (!adaptorPtr->PutVideo && !adaptorPtr->GetVideo) 240 pa->type &= ~XvVideoMask; 241 242 if (!adaptorPtr->PutStill && !adaptorPtr->GetStill) 243 pa->type &= ~XvStillMask; 244 245 if (!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes) 246 pa->type &= ~XvImageMask; 247 248 if (!adaptorPtr->PutVideo && !adaptorPtr->PutImage && 249 !adaptorPtr->PutStill) 250 pa->type &= ~XvInputMask; 251 252 if (!adaptorPtr->GetVideo && !adaptorPtr->GetStill) 253 pa->type &= ~XvOutputMask; 254 255 if (!(adaptorPtr->type & (XvPixmapMask | XvWindowMask))) 256 continue; 257 if (!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask))) 258 continue; 259 260 pa->pScreen = pScreen; 261 pa->ddPutVideo = KdXVPutVideo; 262 pa->ddPutStill = KdXVPutStill; 263 pa->ddGetVideo = KdXVGetVideo; 264 pa->ddGetStill = KdXVGetStill; 265 pa->ddStopVideo = KdXVStopVideo; 266 pa->ddPutImage = KdXVPutImage; 267 pa->ddSetPortAttribute = KdXVSetPortAttribute; 268 pa->ddGetPortAttribute = KdXVGetPortAttribute; 269 pa->ddQueryBestSize = KdXVQueryBestSize; 270 pa->ddQueryImageAttributes = KdXVQueryImageAttributes; 271 pa->name = strdup(adaptorPtr->name); 272 273 if (adaptorPtr->nEncodings && 274 (pEncode = calloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) { 275 276 for (pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0; 277 i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++) { 278 pe->id = encodingPtr->id; 279 pe->pScreen = pScreen; 280 pe->name = strdup(encodingPtr->name); 281 pe->width = encodingPtr->width; 282 pe->height = encodingPtr->height; 283 pe->rate.numerator = encodingPtr->rate.numerator; 284 pe->rate.denominator = encodingPtr->rate.denominator; 285 } 286 pa->nEncodings = adaptorPtr->nEncodings; 287 pa->pEncodings = pEncode; 288 } 289 290 if (adaptorPtr->nImages && 291 (pa->pImages = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) { 292 memcpy(pa->pImages, adaptorPtr->pImages, 293 adaptorPtr->nImages * sizeof(XvImageRec)); 294 pa->nImages = adaptorPtr->nImages; 295 } 296 297 if (adaptorPtr->nAttributes && 298 (pa->pAttributes = calloc(adaptorPtr->nAttributes, 299 sizeof(XvAttributeRec)))) { 300 memcpy(pa->pAttributes, adaptorPtr->pAttributes, 301 adaptorPtr->nAttributes * sizeof(XvAttributeRec)); 302 303 for (i = 0; i < adaptorPtr->nAttributes; i++) { 304 pa->pAttributes[i].name = 305 strdup(adaptorPtr->pAttributes[i].name); 306 } 307 308 pa->nAttributes = adaptorPtr->nAttributes; 309 } 310 311 totFormat = adaptorPtr->nFormats; 312 313 if (!(pFormat = calloc(totFormat, sizeof(XvFormatRec)))) { 314 KdXVFreeAdaptor(pa); 315 continue; 316 } 317 for (pf = pFormat, i = 0, numFormat = 0, formatPtr = 318 adaptorPtr->pFormats; i < adaptorPtr->nFormats; i++, formatPtr++) { 319 numVisuals = pScreen->numVisuals; 320 pVisual = pScreen->visuals; 321 322 while (numVisuals--) { 323 if ((pVisual->class == formatPtr->class) && 324 (pVisual->nplanes == formatPtr->depth)) { 325 326 if (numFormat >= totFormat) { 327 void *moreSpace; 328 329 totFormat *= 2; 330 moreSpace = reallocarray(pFormat, totFormat, 331 sizeof(XvFormatRec)); 332 if (!moreSpace) 333 break; 334 pFormat = moreSpace; 335 pf = pFormat + numFormat; 336 } 337 338 pf->visual = pVisual->vid; 339 pf->depth = formatPtr->depth; 340 341 pf++; 342 numFormat++; 343 } 344 pVisual++; 345 } 346 } 347 pa->nFormats = numFormat; 348 pa->pFormats = pFormat; 349 if (!numFormat) { 350 KdXVFreeAdaptor(pa); 351 continue; 352 } 353 354 if (!(adaptorPriv = calloc(1, sizeof(XvAdaptorRecPrivate)))) { 355 KdXVFreeAdaptor(pa); 356 continue; 357 } 358 359 adaptorPriv->flags = adaptorPtr->flags; 360 adaptorPriv->PutVideo = adaptorPtr->PutVideo; 361 adaptorPriv->PutStill = adaptorPtr->PutStill; 362 adaptorPriv->GetVideo = adaptorPtr->GetVideo; 363 adaptorPriv->GetStill = adaptorPtr->GetStill; 364 adaptorPriv->StopVideo = adaptorPtr->StopVideo; 365 adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute; 366 adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute; 367 adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize; 368 adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes; 369 adaptorPriv->PutImage = adaptorPtr->PutImage; 370 adaptorPriv->ReputImage = adaptorPtr->ReputImage; 371 372 pa->devPriv.ptr = (void *) adaptorPriv; 373 374 if (!(pPort = calloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) { 375 KdXVFreeAdaptor(pa); 376 continue; 377 } 378 for (pp = pPort, i = 0, numPort = 0; i < adaptorPtr->nPorts; i++) { 379 380 if (!(pp->id = FakeClientID(0))) 381 continue; 382 383 if (!(portPriv = calloc(1, sizeof(XvPortRecPrivate)))) 384 continue; 385 386 if (!AddResource(pp->id, PortResource, pp)) { 387 free(portPriv); 388 continue; 389 } 390 391 pp->pAdaptor = pa; 392 pp->pNotify = (XvPortNotifyPtr) NULL; 393 pp->pDraw = (DrawablePtr) NULL; 394 pp->client = (ClientPtr) NULL; 395 pp->grab.client = (ClientPtr) NULL; 396 pp->time = currentTime; 397 pp->devPriv.ptr = portPriv; 398 399 portPriv->screen = screen; 400 portPriv->AdaptorRec = adaptorPriv; 401 portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr; 402 403 pp++; 404 numPort++; 405 } 406 pa->nPorts = numPort; 407 pa->pPorts = pPort; 408 if (!numPort) { 409 KdXVFreeAdaptor(pa); 410 continue; 411 } 412 413 pa->base_id = pPort->id; 414 415 pa++; 416 numAdaptor++; 417 } 418 419 if (numAdaptor) { 420 pxvs->nAdaptors = numAdaptor; 421 pxvs->pAdaptors = pAdaptor; 422 } 423 else { 424 free(pAdaptor); 425 return FALSE; 426 } 427 428 return TRUE; 429} 430 431/* Video should be clipped to the intersection of the window cliplist 432 and the client cliplist specified in the GC for which the video was 433 initialized. When we need to reclip a window, the GC that started 434 the video may not even be around anymore. That's why we save the 435 client clip from the GC when the video is initialized. We then 436 use KdXVUpdateCompositeClip to calculate the new composite clip 437 when we need it. This is different from what DEC did. They saved 438 the GC and used it's clip list when they needed to reclip the window, 439 even if the client clip was different from the one the video was 440 initialized with. If the original GC was destroyed, they had to stop 441 the video. I like the new method better (MArk). 442 443 This function only works for windows. Will need to rewrite when 444 (if) we support pixmap rendering. 445*/ 446 447static void 448KdXVUpdateCompositeClip(XvPortRecPrivatePtr portPriv) 449{ 450 RegionPtr pregWin, pCompositeClip; 451 WindowPtr pWin; 452 Bool freeCompClip = FALSE; 453 454 if (portPriv->pCompositeClip) 455 return; 456 457 pWin = (WindowPtr) portPriv->pDraw; 458 459 /* get window clip list */ 460 if (portPriv->subWindowMode == IncludeInferiors) { 461 pregWin = NotClippedByChildren(pWin); 462 freeCompClip = TRUE; 463 } 464 else 465 pregWin = &pWin->clipList; 466 467 if (!portPriv->clientClip) { 468 portPriv->pCompositeClip = pregWin; 469 portPriv->FreeCompositeClip = freeCompClip; 470 return; 471 } 472 473 pCompositeClip = RegionCreate(NullBox, 1); 474 RegionCopy(pCompositeClip, portPriv->clientClip); 475 RegionTranslate(pCompositeClip, 476 portPriv->pDraw->x + portPriv->clipOrg.x, 477 portPriv->pDraw->y + portPriv->clipOrg.y); 478 RegionIntersect(pCompositeClip, pregWin, pCompositeClip); 479 480 portPriv->pCompositeClip = pCompositeClip; 481 portPriv->FreeCompositeClip = TRUE; 482 483 if (freeCompClip) { 484 RegionDestroy(pregWin); 485 } 486} 487 488/* Save the current clientClip and update the CompositeClip whenever 489 we have a fresh GC */ 490 491static void 492KdXVCopyClip(XvPortRecPrivatePtr portPriv, GCPtr pGC) 493{ 494 /* copy the new clip if it exists */ 495 if (pGC->clientClip) { 496 if (!portPriv->clientClip) 497 portPriv->clientClip = RegionCreate(NullBox, 1); 498 /* Note: this is in window coordinates */ 499 RegionCopy(portPriv->clientClip, pGC->clientClip); 500 } 501 else if (portPriv->clientClip) { /* free the old clientClip */ 502 RegionDestroy(portPriv->clientClip); 503 portPriv->clientClip = NULL; 504 } 505 506 /* get rid of the old clip list */ 507 if (portPriv->pCompositeClip && portPriv->FreeCompositeClip) { 508 RegionDestroy(portPriv->pCompositeClip); 509 } 510 511 portPriv->clipOrg = pGC->clipOrg; 512 portPriv->pCompositeClip = pGC->pCompositeClip; 513 portPriv->FreeCompositeClip = FALSE; 514 portPriv->subWindowMode = pGC->subWindowMode; 515} 516 517static int 518KdXVRegetVideo(XvPortRecPrivatePtr portPriv) 519{ 520 RegionRec WinRegion; 521 RegionRec ClipRegion; 522 BoxRec WinBox; 523 int ret = Success; 524 Bool clippedAway = FALSE; 525 526 KdXVUpdateCompositeClip(portPriv); 527 528 /* translate the video region to the screen */ 529 WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; 530 WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; 531 WinBox.x2 = WinBox.x1 + portPriv->drw_w; 532 WinBox.y2 = WinBox.y1 + portPriv->drw_h; 533 534 /* clip to the window composite clip */ 535 RegionInit(&WinRegion, &WinBox, 1); 536 RegionInit(&ClipRegion, NullBox, 1); 537 RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip); 538 539 /* that's all if it's totally obscured */ 540 if (!RegionNotEmpty(&ClipRegion)) { 541 clippedAway = TRUE; 542 goto CLIP_VIDEO_BAILOUT; 543 } 544 545 ret = (*portPriv->AdaptorRec->GetVideo) (portPriv->screen, portPriv->pDraw, 546 portPriv->vid_x, portPriv->vid_y, 547 WinBox.x1, WinBox.y1, 548 portPriv->vid_w, portPriv->vid_h, 549 portPriv->drw_w, portPriv->drw_h, 550 &ClipRegion, 551 portPriv->DevPriv.ptr); 552 553 if (ret == Success) 554 portPriv->isOn = XV_ON; 555 556 CLIP_VIDEO_BAILOUT: 557 558 if ((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) { 559 (*portPriv->AdaptorRec->StopVideo) (portPriv->screen, 560 portPriv->DevPriv.ptr, FALSE); 561 portPriv->isOn = XV_PENDING; 562 } 563 564 /* This clip was copied and only good for one shot */ 565 if (!portPriv->FreeCompositeClip) 566 portPriv->pCompositeClip = NULL; 567 568 RegionUninit(&WinRegion); 569 RegionUninit(&ClipRegion); 570 571 return ret; 572} 573 574static int 575KdXVReputVideo(XvPortRecPrivatePtr portPriv) 576{ 577 RegionRec WinRegion; 578 RegionRec ClipRegion; 579 BoxRec WinBox; 580 ScreenPtr pScreen = portPriv->pDraw->pScreen; 581 582 KdScreenPriv(pScreen); 583 KdScreenInfo *screen = pScreenPriv->screen; 584 int ret = Success; 585 Bool clippedAway = FALSE; 586 587 KdXVUpdateCompositeClip(portPriv); 588 589 /* translate the video region to the screen */ 590 WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; 591 WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; 592 WinBox.x2 = WinBox.x1 + portPriv->drw_w; 593 WinBox.y2 = WinBox.y1 + portPriv->drw_h; 594 595 /* clip to the window composite clip */ 596 RegionInit(&WinRegion, &WinBox, 1); 597 RegionInit(&ClipRegion, NullBox, 1); 598 RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip); 599 600 /* clip and translate to the viewport */ 601 if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { 602 RegionRec VPReg; 603 BoxRec VPBox; 604 605 VPBox.x1 = 0; 606 VPBox.y1 = 0; 607 VPBox.x2 = screen->width; 608 VPBox.y2 = screen->height; 609 610 RegionInit(&VPReg, &VPBox, 1); 611 RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); 612 RegionUninit(&VPReg); 613 } 614 615 /* that's all if it's totally obscured */ 616 if (!RegionNotEmpty(&ClipRegion)) { 617 clippedAway = TRUE; 618 goto CLIP_VIDEO_BAILOUT; 619 } 620 621 ret = (*portPriv->AdaptorRec->PutVideo) (portPriv->screen, portPriv->pDraw, 622 portPriv->vid_x, portPriv->vid_y, 623 WinBox.x1, WinBox.y1, 624 portPriv->vid_w, portPriv->vid_h, 625 portPriv->drw_w, portPriv->drw_h, 626 &ClipRegion, 627 portPriv->DevPriv.ptr); 628 629 if (ret == Success) 630 portPriv->isOn = XV_ON; 631 632 CLIP_VIDEO_BAILOUT: 633 634 if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { 635 (*portPriv->AdaptorRec->StopVideo) (portPriv->screen, 636 portPriv->DevPriv.ptr, FALSE); 637 portPriv->isOn = XV_PENDING; 638 } 639 640 /* This clip was copied and only good for one shot */ 641 if (!portPriv->FreeCompositeClip) 642 portPriv->pCompositeClip = NULL; 643 644 RegionUninit(&WinRegion); 645 RegionUninit(&ClipRegion); 646 647 return ret; 648} 649 650static int 651KdXVReputImage(XvPortRecPrivatePtr portPriv) 652{ 653 RegionRec WinRegion; 654 RegionRec ClipRegion; 655 BoxRec WinBox; 656 ScreenPtr pScreen = portPriv->pDraw->pScreen; 657 658 KdScreenPriv(pScreen); 659 KdScreenInfo *screen = pScreenPriv->screen; 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 /* clip and translate to the viewport */ 677 if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { 678 RegionRec VPReg; 679 BoxRec VPBox; 680 681 VPBox.x1 = 0; 682 VPBox.y1 = 0; 683 VPBox.x2 = screen->width; 684 VPBox.y2 = screen->height; 685 686 RegionInit(&VPReg, &VPBox, 1); 687 RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); 688 RegionUninit(&VPReg); 689 } 690 691 /* that's all if it's totally obscured */ 692 if (!RegionNotEmpty(&ClipRegion)) { 693 clippedAway = TRUE; 694 goto CLIP_VIDEO_BAILOUT; 695 } 696 697 ret = 698 (*portPriv->AdaptorRec->ReputImage) (portPriv->screen, portPriv->pDraw, 699 WinBox.x1, WinBox.y1, &ClipRegion, 700 portPriv->DevPriv.ptr); 701 702 portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF; 703 704 CLIP_VIDEO_BAILOUT: 705 706 if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { 707 (*portPriv->AdaptorRec->StopVideo) (portPriv->screen, 708 portPriv->DevPriv.ptr, FALSE); 709 portPriv->isOn = XV_PENDING; 710 } 711 712 /* This clip was copied and only good for one shot */ 713 if (!portPriv->FreeCompositeClip) 714 portPriv->pCompositeClip = NULL; 715 716 RegionUninit(&WinRegion); 717 RegionUninit(&ClipRegion); 718 719 return ret; 720} 721 722static int 723KdXVReputAllVideo(WindowPtr pWin, void *data) 724{ 725 KdXVWindowPtr WinPriv; 726 727 if (pWin->drawable.type != DRAWABLE_WINDOW) 728 return WT_DONTWALKCHILDREN; 729 730 WinPriv = GET_KDXV_WINDOW(pWin); 731 732 while (WinPriv) { 733 if (WinPriv->PortRec->type == XvInputMask) 734 KdXVReputVideo(WinPriv->PortRec); 735 else 736 KdXVRegetVideo(WinPriv->PortRec); 737 WinPriv = WinPriv->next; 738 } 739 740 return WT_WALKCHILDREN; 741} 742 743static int 744KdXVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv) 745{ 746 KdXVWindowPtr winPriv, PrivRoot; 747 748 winPriv = PrivRoot = GET_KDXV_WINDOW(pWin); 749 750 /* Enlist our port in the window private */ 751 while (winPriv) { 752 if (winPriv->PortRec == portPriv) /* we're already listed */ 753 break; 754 winPriv = winPriv->next; 755 } 756 757 if (!winPriv) { 758 winPriv = malloc(sizeof(KdXVWindowRec)); 759 if (!winPriv) 760 return BadAlloc; 761 winPriv->PortRec = portPriv; 762 winPriv->next = PrivRoot; 763 dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, winPriv); 764 } 765 return Success; 766} 767 768static void 769KdXVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv) 770{ 771 KdXVWindowPtr winPriv, prevPriv = NULL; 772 773 winPriv = GET_KDXV_WINDOW(pWin); 774 775 while (winPriv) { 776 if (winPriv->PortRec == portPriv) { 777 if (prevPriv) 778 prevPriv->next = winPriv->next; 779 else 780 dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, winPriv->next); 781 free(winPriv); 782 break; 783 } 784 prevPriv = winPriv; 785 winPriv = winPriv->next; 786 } 787 portPriv->pDraw = NULL; 788} 789 790/**** ScreenRec fields ****/ 791 792static Bool 793KdXVDestroyWindow(WindowPtr pWin) 794{ 795 ScreenPtr pScreen = pWin->drawable.pScreen; 796 KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen); 797 KdXVWindowPtr tmp, WinPriv = GET_KDXV_WINDOW(pWin); 798 int ret; 799 800 while (WinPriv) { 801 XvPortRecPrivatePtr pPriv = WinPriv->PortRec; 802 803 if (pPriv->isOn > XV_OFF) { 804 (*pPriv->AdaptorRec->StopVideo) (pPriv->screen, pPriv->DevPriv.ptr, 805 TRUE); 806 pPriv->isOn = XV_OFF; 807 } 808 809 pPriv->pDraw = NULL; 810 tmp = WinPriv; 811 WinPriv = WinPriv->next; 812 free(tmp); 813 } 814 815 dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, NULL); 816 817 pScreen->DestroyWindow = ScreenPriv->DestroyWindow; 818 ret = (*pScreen->DestroyWindow) (pWin); 819 pScreen->DestroyWindow = KdXVDestroyWindow; 820 821 return ret; 822} 823 824static void 825KdXVWindowExposures(WindowPtr pWin, RegionPtr reg1) 826{ 827 ScreenPtr pScreen = pWin->drawable.pScreen; 828 KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen); 829 KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin); 830 KdXVWindowPtr pPrev; 831 XvPortRecPrivatePtr pPriv; 832 Bool AreasExposed; 833 834 AreasExposed = (WinPriv && reg1 && RegionNotEmpty(reg1)); 835 836 pScreen->WindowExposures = ScreenPriv->WindowExposures; 837 (*pScreen->WindowExposures) (pWin, reg1); 838 pScreen->WindowExposures = KdXVWindowExposures; 839 840 /* filter out XClearWindow/Area */ 841 if (!pWin->valdata) 842 return; 843 844 pPrev = NULL; 845 846 while (WinPriv) { 847 pPriv = WinPriv->PortRec; 848 849 /* Reput anyone with a reput function */ 850 851 switch (pPriv->type) { 852 case XvInputMask: 853 KdXVReputVideo(pPriv); 854 break; 855 case XvOutputMask: 856 KdXVRegetVideo(pPriv); 857 break; 858 default: /* overlaid still/image */ 859 if (pPriv->AdaptorRec->ReputImage) 860 KdXVReputImage(pPriv); 861 else if (AreasExposed) { 862 KdXVWindowPtr tmp; 863 864 if (pPriv->isOn == XV_ON) { 865 (*pPriv->AdaptorRec->StopVideo) (pPriv->screen, 866 pPriv->DevPriv.ptr, FALSE); 867 pPriv->isOn = XV_PENDING; 868 } 869 pPriv->pDraw = NULL; 870 871 if (!pPrev) 872 dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, 873 WinPriv->next); 874 else 875 pPrev->next = WinPriv->next; 876 tmp = WinPriv; 877 WinPriv = WinPriv->next; 878 free(tmp); 879 continue; 880 } 881 break; 882 } 883 pPrev = WinPriv; 884 WinPriv = WinPriv->next; 885 } 886} 887 888static void 889KdXVClipNotify(WindowPtr pWin, int dx, int dy) 890{ 891 ScreenPtr pScreen = pWin->drawable.pScreen; 892 KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen); 893 KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin); 894 KdXVWindowPtr tmp, pPrev = NULL; 895 XvPortRecPrivatePtr pPriv; 896 Bool visible = (pWin->visibility == VisibilityUnobscured) || 897 (pWin->visibility == VisibilityPartiallyObscured); 898 899 while (WinPriv) { 900 pPriv = WinPriv->PortRec; 901 902 if (pPriv->pCompositeClip && pPriv->FreeCompositeClip) 903 RegionDestroy(pPriv->pCompositeClip); 904 905 pPriv->pCompositeClip = NULL; 906 907 /* Stop everything except images, but stop them too if the 908 window isn't visible. But we only remove the images. */ 909 910 if (pPriv->type || !visible) { 911 if (pPriv->isOn == XV_ON) { 912 (*pPriv->AdaptorRec->StopVideo) (pPriv->screen, 913 pPriv->DevPriv.ptr, FALSE); 914 pPriv->isOn = XV_PENDING; 915 } 916 917 if (!pPriv->type) { /* overlaid still/image */ 918 pPriv->pDraw = NULL; 919 920 if (!pPrev) 921 dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, 922 WinPriv->next); 923 else 924 pPrev->next = WinPriv->next; 925 tmp = WinPriv; 926 WinPriv = WinPriv->next; 927 free(tmp); 928 continue; 929 } 930 } 931 932 pPrev = WinPriv; 933 WinPriv = WinPriv->next; 934 } 935 936 if (ScreenPriv->ClipNotify) { 937 pScreen->ClipNotify = ScreenPriv->ClipNotify; 938 (*pScreen->ClipNotify) (pWin, dx, dy); 939 pScreen->ClipNotify = KdXVClipNotify; 940 } 941} 942 943/**** Required XvScreenRec fields ****/ 944 945static Bool 946KdXVCloseScreen(ScreenPtr pScreen) 947{ 948 XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); 949 KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen); 950 XvAdaptorPtr pa; 951 int c; 952 953 if (!ScreenPriv) 954 return TRUE; 955 956 pScreen->DestroyWindow = ScreenPriv->DestroyWindow; 957 pScreen->WindowExposures = ScreenPriv->WindowExposures; 958 pScreen->ClipNotify = ScreenPriv->ClipNotify; 959 pScreen->CloseScreen = ScreenPriv->CloseScreen; 960 961/* fprintf(stderr,"XV: Unwrapping screen funcs\n"); */ 962 963 for (c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) { 964 KdXVFreeAdaptor(pa); 965 } 966 967 free(pxvs->pAdaptors); 968 free(ScreenPriv); 969 970 return pScreen->CloseScreen(pScreen); 971} 972 973static Bool 974KdXVRunning(ScreenPtr pScreen) 975{ 976 return (KdXVGeneration == serverGeneration && GET_XV_SCREEN(pScreen) != 0); 977} 978 979Bool 980KdXVEnable(ScreenPtr pScreen) 981{ 982 if (!KdXVRunning(pScreen)) 983 return TRUE; 984 985 WalkTree(pScreen, KdXVReputAllVideo, 0); 986 987 return TRUE; 988} 989 990void 991KdXVDisable(ScreenPtr pScreen) 992{ 993 XvScreenPtr pxvs; 994 XvAdaptorPtr pAdaptor; 995 XvPortPtr pPort; 996 XvPortRecPrivatePtr pPriv; 997 int i, j; 998 999 if (!KdXVRunning(pScreen)) 1000 return; 1001 1002 pxvs = GET_XV_SCREEN(pScreen); 1003 1004 for (i = 0; i < pxvs->nAdaptors; i++) { 1005 pAdaptor = &pxvs->pAdaptors[i]; 1006 for (j = 0; j < pAdaptor->nPorts; j++) { 1007 pPort = &pAdaptor->pPorts[j]; 1008 pPriv = (XvPortRecPrivatePtr) pPort->devPriv.ptr; 1009 if (pPriv->isOn > XV_OFF) { 1010 1011 (*pPriv->AdaptorRec->StopVideo) (pPriv->screen, 1012 pPriv->DevPriv.ptr, TRUE); 1013 pPriv->isOn = XV_OFF; 1014 1015 if (pPriv->pCompositeClip && pPriv->FreeCompositeClip) 1016 RegionDestroy(pPriv->pCompositeClip); 1017 1018 pPriv->pCompositeClip = NULL; 1019 1020 if (!pPriv->type && pPriv->pDraw) { /* still */ 1021 KdXVRemovePortFromWindow((WindowPtr) pPriv->pDraw, pPriv); 1022 } 1023 } 1024 } 1025 } 1026} 1027 1028/**** XvAdaptorRec fields ****/ 1029 1030static int 1031KdXVPutVideo(DrawablePtr pDraw, 1032 XvPortPtr pPort, 1033 GCPtr pGC, 1034 INT16 vid_x, INT16 vid_y, 1035 CARD16 vid_w, CARD16 vid_h, 1036 INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h) 1037{ 1038 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr); 1039 1040 KdScreenPriv(portPriv->screen->pScreen); 1041 int result; 1042 1043 /* No dumping video to pixmaps... For now anyhow */ 1044 if (pDraw->type != DRAWABLE_WINDOW) { 1045 pPort->pDraw = (DrawablePtr) NULL; 1046 return BadAlloc; 1047 } 1048 1049 /* If we are changing windows, unregister our port in the old window */ 1050 if (portPriv->pDraw && (portPriv->pDraw != pDraw)) 1051 KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv); 1052 1053 /* Register our port with the new window */ 1054 result = KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv); 1055 if (result != Success) 1056 return result; 1057 1058 portPriv->pDraw = pDraw; 1059 portPriv->type = XvInputMask; 1060 1061 /* save a copy of these parameters */ 1062 portPriv->vid_x = vid_x; 1063 portPriv->vid_y = vid_y; 1064 portPriv->vid_w = vid_w; 1065 portPriv->vid_h = vid_h; 1066 portPriv->drw_x = drw_x; 1067 portPriv->drw_y = drw_y; 1068 portPriv->drw_w = drw_w; 1069 portPriv->drw_h = drw_h; 1070 1071 /* make sure we have the most recent copy of the clientClip */ 1072 KdXVCopyClip(portPriv, pGC); 1073 1074 /* To indicate to the DI layer that we were successful */ 1075 pPort->pDraw = pDraw; 1076 1077 if (!pScreenPriv->enabled) 1078 return Success; 1079 1080 return (KdXVReputVideo(portPriv)); 1081} 1082 1083static int 1084KdXVPutStill(DrawablePtr pDraw, 1085 XvPortPtr pPort, 1086 GCPtr pGC, 1087 INT16 vid_x, INT16 vid_y, 1088 CARD16 vid_w, CARD16 vid_h, 1089 INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h) 1090{ 1091 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr); 1092 ScreenPtr pScreen = pDraw->pScreen; 1093 1094 KdScreenPriv(pScreen); 1095 KdScreenInfo *screen = pScreenPriv->screen; 1096 RegionRec WinRegion; 1097 RegionRec ClipRegion; 1098 BoxRec WinBox; 1099 int ret = Success; 1100 Bool clippedAway = FALSE; 1101 1102 if (pDraw->type != DRAWABLE_WINDOW) 1103 return BadAlloc; 1104 1105 if (!pScreenPriv->enabled) 1106 return Success; 1107 1108 WinBox.x1 = pDraw->x + drw_x; 1109 WinBox.y1 = pDraw->y + drw_y; 1110 WinBox.x2 = WinBox.x1 + drw_w; 1111 WinBox.y2 = WinBox.y1 + drw_h; 1112 1113 RegionInit(&WinRegion, &WinBox, 1); 1114 RegionInit(&ClipRegion, NullBox, 1); 1115 RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip); 1116 1117 if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { 1118 RegionRec VPReg; 1119 BoxRec VPBox; 1120 1121 VPBox.x1 = 0; 1122 VPBox.y1 = 0; 1123 VPBox.x2 = screen->width; 1124 VPBox.y2 = screen->height; 1125 1126 RegionInit(&VPReg, &VPBox, 1); 1127 RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); 1128 RegionUninit(&VPReg); 1129 } 1130 1131 if (portPriv->pDraw) { 1132 KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv); 1133 } 1134 1135 if (!RegionNotEmpty(&ClipRegion)) { 1136 clippedAway = TRUE; 1137 goto PUT_STILL_BAILOUT; 1138 } 1139 1140 ret = (*portPriv->AdaptorRec->PutStill) (portPriv->screen, pDraw, 1141 vid_x, vid_y, WinBox.x1, WinBox.y1, 1142 vid_w, vid_h, drw_w, drw_h, 1143 &ClipRegion, 1144 portPriv->DevPriv.ptr); 1145 1146 if ((ret == Success) && 1147 (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) { 1148 1149 KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv); 1150 portPriv->isOn = XV_ON; 1151 portPriv->pDraw = pDraw; 1152 portPriv->drw_x = drw_x; 1153 portPriv->drw_y = drw_y; 1154 portPriv->drw_w = drw_w; 1155 portPriv->drw_h = drw_h; 1156 portPriv->type = 0; /* no mask means it's transient and should 1157 not be reput once it's removed */ 1158 pPort->pDraw = pDraw; /* make sure we can get stop requests */ 1159 } 1160 1161 PUT_STILL_BAILOUT: 1162 1163 if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { 1164 (*portPriv->AdaptorRec->StopVideo) (portPriv->screen, 1165 portPriv->DevPriv.ptr, FALSE); 1166 portPriv->isOn = XV_PENDING; 1167 } 1168 1169 RegionUninit(&WinRegion); 1170 RegionUninit(&ClipRegion); 1171 1172 return ret; 1173} 1174 1175static int 1176KdXVGetVideo(DrawablePtr pDraw, 1177 XvPortPtr pPort, 1178 GCPtr pGC, 1179 INT16 vid_x, INT16 vid_y, 1180 CARD16 vid_w, CARD16 vid_h, 1181 INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h) 1182{ 1183 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr); 1184 int result; 1185 1186 KdScreenPriv(portPriv->screen->pScreen); 1187 1188 /* No pixmaps... For now anyhow */ 1189 if (pDraw->type != DRAWABLE_WINDOW) { 1190 pPort->pDraw = (DrawablePtr) NULL; 1191 return BadAlloc; 1192 } 1193 1194 /* If we are changing windows, unregister our port in the old window */ 1195 if (portPriv->pDraw && (portPriv->pDraw != pDraw)) 1196 KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv); 1197 1198 /* Register our port with the new window */ 1199 result = KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv); 1200 if (result != Success) 1201 return result; 1202 1203 portPriv->pDraw = pDraw; 1204 portPriv->type = XvOutputMask; 1205 1206 /* save a copy of these parameters */ 1207 portPriv->vid_x = vid_x; 1208 portPriv->vid_y = vid_y; 1209 portPriv->vid_w = vid_w; 1210 portPriv->vid_h = vid_h; 1211 portPriv->drw_x = drw_x; 1212 portPriv->drw_y = drw_y; 1213 portPriv->drw_w = drw_w; 1214 portPriv->drw_h = drw_h; 1215 1216 /* make sure we have the most recent copy of the clientClip */ 1217 KdXVCopyClip(portPriv, pGC); 1218 1219 /* To indicate to the DI layer that we were successful */ 1220 pPort->pDraw = pDraw; 1221 1222 if (!pScreenPriv->enabled) 1223 return Success; 1224 1225 return (KdXVRegetVideo(portPriv)); 1226} 1227 1228static int 1229KdXVGetStill(DrawablePtr pDraw, 1230 XvPortPtr pPort, 1231 GCPtr pGC, 1232 INT16 vid_x, INT16 vid_y, 1233 CARD16 vid_w, CARD16 vid_h, 1234 INT16 drw_x, INT16 drw_y, CARD16 drw_w, CARD16 drw_h) 1235{ 1236 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr); 1237 ScreenPtr pScreen = pDraw->pScreen; 1238 1239 KdScreenPriv(pScreen); 1240 RegionRec WinRegion; 1241 RegionRec ClipRegion; 1242 BoxRec WinBox; 1243 int ret = Success; 1244 Bool clippedAway = FALSE; 1245 1246 if (pDraw->type != DRAWABLE_WINDOW) 1247 return BadAlloc; 1248 1249 if (!pScreenPriv->enabled) 1250 return Success; 1251 1252 WinBox.x1 = pDraw->x + drw_x; 1253 WinBox.y1 = pDraw->y + drw_y; 1254 WinBox.x2 = WinBox.x1 + drw_w; 1255 WinBox.y2 = WinBox.y1 + drw_h; 1256 1257 RegionInit(&WinRegion, &WinBox, 1); 1258 RegionInit(&ClipRegion, NullBox, 1); 1259 RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip); 1260 1261 if (portPriv->pDraw) { 1262 KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv); 1263 } 1264 1265 if (!RegionNotEmpty(&ClipRegion)) { 1266 clippedAway = TRUE; 1267 goto GET_STILL_BAILOUT; 1268 } 1269 1270 ret = (*portPriv->AdaptorRec->GetStill) (portPriv->screen, pDraw, 1271 vid_x, vid_y, WinBox.x1, WinBox.y1, 1272 vid_w, vid_h, drw_w, drw_h, 1273 &ClipRegion, 1274 portPriv->DevPriv.ptr); 1275 1276 GET_STILL_BAILOUT: 1277 1278 if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { 1279 (*portPriv->AdaptorRec->StopVideo) (portPriv->screen, 1280 portPriv->DevPriv.ptr, FALSE); 1281 portPriv->isOn = XV_PENDING; 1282 } 1283 1284 RegionUninit(&WinRegion); 1285 RegionUninit(&ClipRegion); 1286 1287 return ret; 1288} 1289 1290static int 1291KdXVStopVideo(XvPortPtr pPort, DrawablePtr pDraw) 1292{ 1293 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr); 1294 1295 KdScreenPriv(portPriv->screen->pScreen); 1296 1297 if (pDraw->type != DRAWABLE_WINDOW) 1298 return BadAlloc; 1299 1300 KdXVRemovePortFromWindow((WindowPtr) pDraw, portPriv); 1301 1302 if (!pScreenPriv->enabled) 1303 return Success; 1304 1305 /* Must free resources. */ 1306 1307 if (portPriv->isOn > XV_OFF) { 1308 (*portPriv->AdaptorRec->StopVideo) (portPriv->screen, 1309 portPriv->DevPriv.ptr, TRUE); 1310 portPriv->isOn = XV_OFF; 1311 } 1312 1313 return Success; 1314} 1315 1316static int 1317KdXVSetPortAttribute(XvPortPtr pPort, Atom attribute, INT32 value) 1318{ 1319 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr); 1320 1321 return ((*portPriv->AdaptorRec->SetPortAttribute) (portPriv->screen, 1322 attribute, value, 1323 portPriv->DevPriv.ptr)); 1324} 1325 1326static int 1327KdXVGetPortAttribute(XvPortPtr pPort, Atom attribute, INT32 *p_value) 1328{ 1329 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr); 1330 1331 return ((*portPriv->AdaptorRec->GetPortAttribute) (portPriv->screen, 1332 attribute, 1333 (int *) p_value, 1334 portPriv->DevPriv.ptr)); 1335} 1336 1337static int 1338KdXVQueryBestSize(XvPortPtr pPort, 1339 CARD8 motion, 1340 CARD16 vid_w, CARD16 vid_h, 1341 CARD16 drw_w, CARD16 drw_h, 1342 unsigned int *p_w, unsigned int *p_h) 1343{ 1344 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr); 1345 1346 (*portPriv->AdaptorRec->QueryBestSize) (portPriv->screen, 1347 (Bool) motion, vid_w, vid_h, drw_w, 1348 drw_h, p_w, p_h, 1349 portPriv->DevPriv.ptr); 1350 1351 return Success; 1352} 1353 1354static int 1355KdXVPutImage(DrawablePtr pDraw, 1356 XvPortPtr pPort, 1357 GCPtr pGC, 1358 INT16 src_x, INT16 src_y, 1359 CARD16 src_w, CARD16 src_h, 1360 INT16 drw_x, INT16 drw_y, 1361 CARD16 drw_w, CARD16 drw_h, 1362 XvImagePtr format, 1363 unsigned char *data, Bool sync, CARD16 width, CARD16 height) 1364{ 1365 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr); 1366 ScreenPtr pScreen = pDraw->pScreen; 1367 1368 KdScreenPriv(pScreen); 1369 RegionRec WinRegion; 1370 RegionRec ClipRegion; 1371 BoxRec WinBox; 1372 int ret = Success; 1373 Bool clippedAway = FALSE; 1374 1375 if (pDraw->type != DRAWABLE_WINDOW) 1376 return BadAlloc; 1377 1378 if (!pScreenPriv->enabled) 1379 return Success; 1380 1381 WinBox.x1 = pDraw->x + drw_x; 1382 WinBox.y1 = pDraw->y + drw_y; 1383 WinBox.x2 = WinBox.x1 + drw_w; 1384 WinBox.y2 = WinBox.y1 + drw_h; 1385 1386 RegionInit(&WinRegion, &WinBox, 1); 1387 RegionInit(&ClipRegion, NullBox, 1); 1388 RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip); 1389 1390 if (portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { 1391 RegionRec VPReg; 1392 BoxRec VPBox; 1393 1394 VPBox.x1 = 0; 1395 VPBox.y1 = 0; 1396 VPBox.x2 = pScreen->width; 1397 VPBox.y2 = pScreen->height; 1398 1399 RegionInit(&VPReg, &VPBox, 1); 1400 RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); 1401 RegionUninit(&VPReg); 1402 } 1403 1404 if (portPriv->pDraw) { 1405 KdXVRemovePortFromWindow((WindowPtr) (portPriv->pDraw), portPriv); 1406 } 1407 1408 if (!RegionNotEmpty(&ClipRegion)) { 1409 clippedAway = TRUE; 1410 goto PUT_IMAGE_BAILOUT; 1411 } 1412 1413 ret = (*portPriv->AdaptorRec->PutImage) (portPriv->screen, pDraw, 1414 src_x, src_y, WinBox.x1, WinBox.y1, 1415 src_w, src_h, drw_w, drw_h, 1416 format->id, data, width, height, 1417 sync, &ClipRegion, 1418 portPriv->DevPriv.ptr); 1419 1420 if ((ret == Success) && 1421 (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) { 1422 1423 KdXVEnlistPortInWindow((WindowPtr) pDraw, portPriv); 1424 portPriv->isOn = XV_ON; 1425 portPriv->pDraw = pDraw; 1426 portPriv->drw_x = drw_x; 1427 portPriv->drw_y = drw_y; 1428 portPriv->drw_w = drw_w; 1429 portPriv->drw_h = drw_h; 1430 portPriv->type = 0; /* no mask means it's transient and should 1431 not be reput once it's removed */ 1432 pPort->pDraw = pDraw; /* make sure we can get stop requests */ 1433 } 1434 1435 PUT_IMAGE_BAILOUT: 1436 1437 if ((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { 1438 (*portPriv->AdaptorRec->StopVideo) (portPriv->screen, 1439 portPriv->DevPriv.ptr, FALSE); 1440 portPriv->isOn = XV_PENDING; 1441 } 1442 1443 RegionUninit(&WinRegion); 1444 RegionUninit(&ClipRegion); 1445 1446 return ret; 1447} 1448 1449static int 1450KdXVQueryImageAttributes(XvPortPtr pPort, 1451 XvImagePtr format, 1452 CARD16 *width, 1453 CARD16 *height, int *pitches, int *offsets) 1454{ 1455 XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr) (pPort->devPriv.ptr); 1456 1457 return (*portPriv->AdaptorRec->QueryImageAttributes) (portPriv->screen, 1458 format->id, width, 1459 height, pitches, 1460 offsets); 1461} 1462 1463/**************** Common video manipulation functions *******************/ 1464 1465void 1466KdXVCopyPackedData(KdScreenInfo * screen, CARD8 *src, CARD8 *dst, int randr, 1467 int srcPitch, int dstPitch, int srcW, int srcH, int top, 1468 int left, int h, int w) 1469{ 1470 int srcDown = srcPitch, srcRight = 2, srcNext; 1471 int p; 1472 1473 switch (randr & RR_Rotate_All) { 1474 case RR_Rotate_0: 1475 srcDown = srcPitch; 1476 srcRight = 2; 1477 break; 1478 case RR_Rotate_90: 1479 src += (srcH - 1) * 2; 1480 srcDown = -2; 1481 srcRight = srcPitch; 1482 break; 1483 case RR_Rotate_180: 1484 src += srcPitch * (srcH - 1) + (srcW - 1) * 2; 1485 srcDown = -srcPitch; 1486 srcRight = -2; 1487 break; 1488 case RR_Rotate_270: 1489 src += srcPitch * (srcW - 1); 1490 srcDown = 2; 1491 srcRight = -srcPitch; 1492 break; 1493 } 1494 1495 src = src + top * srcDown + left * srcRight; 1496 1497 w >>= 1; 1498 /* srcRight >>= 1; */ 1499 srcNext = srcRight >> 1; 1500 while (h--) { 1501 CARD16 *s = (CARD16 *) src; 1502 CARD32 *d = (CARD32 *) dst; 1503 1504 p = w; 1505 while (p--) { 1506 *d++ = s[0] | (s[srcNext] << 16); 1507 s += srcRight; 1508 } 1509 src += srcPitch; 1510 dst += dstPitch; 1511 } 1512} 1513 1514void 1515KdXVCopyPlanarData(KdScreenInfo * screen, CARD8 *src, CARD8 *dst, int randr, 1516 int srcPitch, int srcPitch2, int dstPitch, int srcW, 1517 int srcH, int height, int top, int left, int h, int w, 1518 int id) 1519{ 1520 int i, j; 1521 CARD8 *src1, *src2, *src3, *dst1; 1522 int srcDown = srcPitch, srcDown2 = srcPitch2; 1523 int srcRight = 2, srcRight2 = 1, srcNext = 1; 1524 1525 /* compute source data pointers */ 1526 src1 = src; 1527 src2 = src1 + height * srcPitch; 1528 src3 = src2 + (height >> 1) * srcPitch2; 1529 switch (randr & RR_Rotate_All) { 1530 case RR_Rotate_0: 1531 srcDown = srcPitch; 1532 srcDown2 = srcPitch2; 1533 srcRight = 2; 1534 srcRight2 = 1; 1535 srcNext = 1; 1536 break; 1537 case RR_Rotate_90: 1538 src1 = src1 + srcH - 1; 1539 src2 = src2 + (srcH >> 1) - 1; 1540 src3 = src3 + (srcH >> 1) - 1; 1541 srcDown = -1; 1542 srcDown2 = -1; 1543 srcRight = srcPitch * 2; 1544 srcRight2 = srcPitch2; 1545 srcNext = srcPitch; 1546 break; 1547 case RR_Rotate_180: 1548 src1 = src1 + srcPitch * (srcH - 1) + (srcW - 1); 1549 src2 = src2 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1); 1550 src3 = src3 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1); 1551 srcDown = -srcPitch; 1552 srcDown2 = -srcPitch2; 1553 srcRight = -2; 1554 srcRight2 = -1; 1555 srcNext = -1; 1556 break; 1557 case RR_Rotate_270: 1558 src1 = src1 + srcPitch * (srcW - 1); 1559 src2 = src2 + srcPitch2 * ((srcW >> 1) - 1); 1560 src3 = src3 + srcPitch2 * ((srcW >> 1) - 1); 1561 srcDown = 1; 1562 srcDown2 = 1; 1563 srcRight = -srcPitch * 2; 1564 srcRight2 = -srcPitch2; 1565 srcNext = -srcPitch; 1566 break; 1567 } 1568 1569 /* adjust for origin */ 1570 src1 += top * srcDown + left * srcNext; 1571 src2 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2; 1572 src3 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2; 1573 1574 if (id == FOURCC_I420) { 1575 CARD8 *srct = src2; 1576 1577 src2 = src3; 1578 src3 = srct; 1579 } 1580 1581 dst1 = dst; 1582 1583 w >>= 1; 1584 for (j = 0; j < h; j++) { 1585 CARD32 *dst32 = (CARD32 *) dst1; 1586 CARD8 *s1l = src1; 1587 CARD8 *s1r = src1 + srcNext; 1588 CARD8 *s2 = src2; 1589 CARD8 *s3 = src3; 1590 1591 for (i = 0; i < w; i++) { 1592 *dst32++ = *s1l | (*s1r << 16) | (*s3 << 8) | (*s2 << 24); 1593 s1l += srcRight; 1594 s1r += srcRight; 1595 s2 += srcRight2; 1596 s3 += srcRight2; 1597 } 1598 src1 += srcDown; 1599 dst1 += dstPitch; 1600 if (j & 1) { 1601 src2 += srcDown2; 1602 src3 += srcDown2; 1603 } 1604 } 1605} 1606