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