nv_video.c revision d422ce2e
1#ifdef HAVE_CONFIG_H 2#include "config.h" 3#endif 4 5#include "xf86.h" 6#include "xf86_OSproc.h" 7#include "compiler.h" 8#include "pci_ids.h" 9#include "xf86Pci.h" 10#include "xf86fbman.h" 11#include "regionstr.h" 12 13#include "xf86xv.h" 14#include <X11/extensions/Xv.h> 15#include "dixstruct.h" 16#include "fourcc.h" 17 18#include "nv_include.h" 19#include "nv_dma.h" 20 21#define OFF_DELAY 500 /* milliseconds */ 22#define FREE_DELAY 5000 23 24#define OFF_TIMER 0x01 25#define FREE_TIMER 0x02 26#define CLIENT_VIDEO_ON 0x04 27 28#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 29 30#define NUM_BLIT_PORTS 32 31 32typedef struct _NVPortPrivRec { 33 short brightness; 34 short contrast; 35 short saturation; 36 short hue; 37 RegionRec clip; 38 CARD32 colorKey; 39 Bool autopaintColorKey; 40 Bool doubleBuffer; 41 CARD32 videoStatus; 42 int currentBuffer; 43 Time videoTime; 44 Bool grabbedByV4L; 45 Bool iturbt_709; 46 Bool blitter; 47 Bool SyncToVBlank; 48 FBLinearPtr linear; 49 int pitch; 50 int offset; 51} NVPortPrivRec, *NVPortPrivPtr; 52 53 54static XF86VideoAdaptorPtr NVSetupOverlayVideo(ScreenPtr); 55static XF86VideoAdaptorPtr NVSetupBlitVideo(ScreenPtr); 56 57static void NVStopOverlay (ScrnInfoPtr); 58static void NVPutOverlayImage(ScrnInfoPtr pScrnInfo, 59 int offset, 60 int id, 61 int dstPitch, 62 BoxPtr dstBox, 63 int x1, int y1, int x2, int y2, 64 short width, short height, 65 short src_w, short src_h, 66 short dst_w, short dst_h, 67 RegionPtr cliplist); 68 69static int NVSetOverlayPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 70static int NVGetOverlayPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); 71static int NVSetBlitPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 72static int NVGetBlitPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); 73 74 75static void NVStopOverlayVideo(ScrnInfoPtr, pointer, Bool); 76static void NVStopBlitVideo(ScrnInfoPtr, pointer, Bool); 77 78static int NVPutImage( ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer, DrawablePtr); 79 80static void NVQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, unsigned int *, unsigned int *, pointer); 81static int NVQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *, int *, int *); 82 83static void NVVideoTimerCallback(ScrnInfoPtr, Time); 84 85static void NVInitOffscreenImages (ScreenPtr pScreen); 86 87 88#define GET_OVERLAY_PRIVATE(pNv) \ 89 (NVPortPrivPtr)((pNv)->overlayAdaptor->pPortPrivates[0].ptr) 90 91#define GET_BLIT_PRIVATE(pNv) \ 92 (NVPortPrivPtr)((pNv)->blitAdaptor->pPortPrivates[0].ptr) 93 94#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 95 96static Atom xvBrightness, xvContrast, xvColorKey, xvSaturation, 97 xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer, 98 xvITURBT709, xvSyncToVBlank; 99 100/* client libraries expect an encoding */ 101static XF86VideoEncodingRec DummyEncoding = 102{ 103 0, 104 "XV_IMAGE", 105 2046, 2046, 106 {1, 1} 107}; 108 109#define NUM_FORMATS_ALL 6 110 111XF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] = 112{ 113 {15, TrueColor}, {16, TrueColor}, {24, TrueColor}, 114 {15, DirectColor}, {16, DirectColor}, {24, DirectColor} 115}; 116 117#define NUM_OVERLAY_ATTRIBUTES 9 118XF86AttributeRec NVOverlayAttributes[NUM_OVERLAY_ATTRIBUTES] = 119{ 120 {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"}, 121 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 122 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}, 123 {XvSettable , 0, 0, "XV_SET_DEFAULTS"}, 124 {XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"}, 125 {XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"}, 126 {XvSettable | XvGettable, 0, 8191, "XV_SATURATION"}, 127 {XvSettable | XvGettable, 0, 360, "XV_HUE"}, 128 {XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"} 129}; 130 131#define NUM_BLIT_ATTRIBUTES 2 132XF86AttributeRec NVBlitAttributes[NUM_BLIT_ATTRIBUTES] = 133{ 134 {XvSettable , 0, 0, "XV_SET_DEFAULTS"}, 135 {XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"} 136}; 137 138 139#define NUM_IMAGES_YUV 4 140#define NUM_IMAGES_ALL 5 141 142#define FOURCC_RGB 0x0000003 143#define XVIMAGE_RGB \ 144 { \ 145 FOURCC_RGB, \ 146 XvRGB, \ 147 LSBFirst, \ 148 { 0x03, 0x00, 0x00, 0x00, \ 149 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ 150 32, \ 151 XvPacked, \ 152 1, \ 153 24, 0x00ff0000, 0x0000ff00, 0x000000ff, \ 154 0, 0, 0, \ 155 0, 0, 0, \ 156 0, 0, 0, \ 157 {'B','G','R','X',\ 158 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ 159 XvTopToBottom \ 160 } 161 162static XF86ImageRec NVImages[NUM_IMAGES_ALL] = 163{ 164 XVIMAGE_YUY2, 165 XVIMAGE_YV12, 166 XVIMAGE_UYVY, 167 XVIMAGE_I420, 168 XVIMAGE_RGB 169}; 170 171static void 172NVSetPortDefaults (ScrnInfoPtr pScrnInfo, NVPortPrivPtr pPriv) 173{ 174 NVPtr pNv = NVPTR(pScrnInfo); 175 176 pPriv->brightness = 0; 177 pPriv->contrast = 4096; 178 pPriv->saturation = 4096; 179 pPriv->hue = 0; 180 pPriv->colorKey = pNv->videoKey; 181 pPriv->autopaintColorKey = TRUE; 182 pPriv->doubleBuffer = TRUE; 183 pPriv->iturbt_709 = FALSE; 184} 185 186 187void 188NVResetVideo (ScrnInfoPtr pScrnInfo) 189{ 190 NVPtr pNv = NVPTR(pScrnInfo); 191 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 192 int satSine, satCosine; 193 double angle; 194 195 angle = (double)pPriv->hue * 3.1415927 / 180.0; 196 197 satSine = pPriv->saturation * sin(angle); 198 if (satSine < -1024) 199 satSine = -1024; 200 satCosine = pPriv->saturation * cos(angle); 201 if (satCosine < -1024) 202 satCosine = -1024; 203 204 pNv->PMC[0x8910/4] = (pPriv->brightness << 16) | pPriv->contrast; 205 pNv->PMC[0x8914/4] = (pPriv->brightness << 16) | pPriv->contrast; 206 pNv->PMC[0x8918/4] = (satSine << 16) | (satCosine & 0xffff); 207 pNv->PMC[0x891C/4] = (satSine << 16) | (satCosine & 0xffff); 208 pNv->PMC[0x8b00/4] = pPriv->colorKey; 209} 210 211 212 213static void 214NVStopOverlay (ScrnInfoPtr pScrnInfo) 215{ 216 NVPtr pNv = NVPTR(pScrnInfo); 217 218 pNv->PMC[0x00008704/4] = 1; 219} 220 221static FBLinearPtr 222NVAllocateOverlayMemory( 223 ScrnInfoPtr pScrn, 224 FBLinearPtr linear, 225 int size 226){ 227 ScreenPtr pScreen; 228 FBLinearPtr new_linear; 229 230 if(linear) { 231 if(linear->size >= size) 232 return linear; 233 234 if(xf86ResizeOffscreenLinear(linear, size)) 235 return linear; 236 237 xf86FreeOffscreenLinear(linear); 238 } 239 240 pScreen = xf86ScrnToScreen(pScrn); 241 242 new_linear = xf86AllocateOffscreenLinear(pScreen, size, 32, 243 NULL, NULL, NULL); 244 245 if(!new_linear) { 246 int max_size; 247 248 xf86QueryLargestOffscreenLinear(pScreen, &max_size, 32, 249 PRIORITY_EXTREME); 250 251 if(max_size < size) 252 return NULL; 253 254 xf86PurgeUnlockedOffscreenAreas(pScreen); 255 new_linear = xf86AllocateOffscreenLinear(pScreen, size, 32, 256 NULL, NULL, NULL); 257 } 258 259 return new_linear; 260} 261 262static void NVFreeOverlayMemory(ScrnInfoPtr pScrnInfo) 263{ 264 NVPtr pNv = NVPTR(pScrnInfo); 265 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 266 267 if(pPriv->linear) { 268 xf86FreeOffscreenLinear(pPriv->linear); 269 pPriv->linear = NULL; 270 } 271} 272 273 274static void NVFreeBlitMemory(ScrnInfoPtr pScrnInfo) 275{ 276 NVPtr pNv = NVPTR(pScrnInfo); 277 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv); 278 279 if(pPriv->linear) { 280 xf86FreeOffscreenLinear(pPriv->linear); 281 pPriv->linear = NULL; 282 } 283} 284 285 286void NVInitVideo (ScreenPtr pScreen) 287{ 288 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 289 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 290 XF86VideoAdaptorPtr overlayAdaptor = NULL; 291 XF86VideoAdaptorPtr blitAdaptor = NULL; 292 NVPtr pNv = NVPTR(pScrn); 293 int num_adaptors; 294 295 if((pScrn->bitsPerPixel != 8) && (pNv->Architecture >= NV_ARCH_10) && 296 ((pNv->Architecture <= NV_ARCH_30) || 297 ((pNv->Chipset & 0xfff0) == 0x0040))) 298 { 299 overlayAdaptor = NVSetupOverlayVideo(pScreen); 300 301 if(overlayAdaptor) 302 NVInitOffscreenImages(pScreen); 303 } 304 305 if((pScrn->bitsPerPixel != 8) && !pNv->NoAccel) 306 blitAdaptor = NVSetupBlitVideo(pScreen); 307 308 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 309 310 if(blitAdaptor || overlayAdaptor) { 311 int size = num_adaptors; 312 313 if(overlayAdaptor) size++; 314 if(blitAdaptor) size++; 315 316 if((newAdaptors = malloc(size * sizeof(XF86VideoAdaptorPtr*)))) { 317 if(num_adaptors) { 318 memcpy(newAdaptors, adaptors, 319 num_adaptors * sizeof(XF86VideoAdaptorPtr)); 320 } 321 if(overlayAdaptor) { 322 newAdaptors[num_adaptors] = overlayAdaptor; 323 num_adaptors++; 324 } 325 if(blitAdaptor) { 326 newAdaptors[num_adaptors] = blitAdaptor; 327 num_adaptors++; 328 } 329 adaptors = newAdaptors; 330 } 331 } 332 333 if (num_adaptors) 334 xf86XVScreenInit(pScreen, adaptors, num_adaptors); 335 336 if (newAdaptors) 337 free(newAdaptors); 338} 339 340 341static XF86VideoAdaptorPtr 342NVSetupBlitVideo (ScreenPtr pScreen) 343{ 344 ScrnInfoPtr pScrnInfo = xf86ScreenToScrn(pScreen); 345 NVPtr pNv = NVPTR(pScrnInfo); 346 XF86VideoAdaptorPtr adapt; 347 NVPortPrivPtr pPriv; 348 int i; 349 350 if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 351 sizeof(NVPortPrivRec) + 352 (sizeof(DevUnion) * NUM_BLIT_PORTS)))) 353 { 354 return NULL; 355 } 356 357 adapt->type = XvWindowMask | XvInputMask | XvImageMask; 358 adapt->flags = 0; 359 adapt->name = "NV Video Blitter"; 360 adapt->nEncodings = 1; 361 adapt->pEncodings = &DummyEncoding; 362 adapt->nFormats = NUM_FORMATS_ALL; 363 adapt->pFormats = NVFormats; 364 adapt->nPorts = NUM_BLIT_PORTS; 365 adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 366 367 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]); 368 for(i = 0; i < NUM_BLIT_PORTS; i++) 369 adapt->pPortPrivates[i].ptr = (pointer)(pPriv); 370 371 if(pNv->WaitVSyncPossible) { 372 adapt->pAttributes = NVBlitAttributes; 373 adapt->nAttributes = NUM_BLIT_ATTRIBUTES; 374 } else { 375 adapt->pAttributes = NULL; 376 adapt->nAttributes = 0; 377 } 378 adapt->pImages = NVImages; 379 adapt->nImages = NUM_IMAGES_ALL; 380 adapt->PutVideo = NULL; 381 adapt->PutStill = NULL; 382 adapt->GetVideo = NULL; 383 adapt->GetStill = NULL; 384 adapt->StopVideo = NVStopBlitVideo; 385 adapt->SetPortAttribute = NVSetBlitPortAttribute; 386 adapt->GetPortAttribute = NVGetBlitPortAttribute; 387 adapt->QueryBestSize = NVQueryBestSize; 388 adapt->PutImage = NVPutImage; 389 adapt->QueryImageAttributes = NVQueryImageAttributes; 390 391 pPriv->videoStatus = 0; 392 pPriv->grabbedByV4L = FALSE; 393 pPriv->blitter = TRUE; 394 pPriv->doubleBuffer = FALSE; 395 pPriv->SyncToVBlank = pNv->WaitVSyncPossible; 396 397 pNv->blitAdaptor = adapt; 398 399 xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK"); 400 401 return adapt; 402} 403 404static XF86VideoAdaptorPtr 405NVSetupOverlayVideo (ScreenPtr pScreen) 406{ 407 ScrnInfoPtr pScrnInfo = xf86ScreenToScrn(pScreen); 408 NVPtr pNv = NVPTR(pScrnInfo); 409 XF86VideoAdaptorPtr adapt; 410 NVPortPrivPtr pPriv; 411 412 if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 413 sizeof(NVPortPrivRec) + 414 sizeof(DevUnion)))) 415 { 416 return NULL; 417 } 418 419 adapt->type = XvWindowMask | XvInputMask | XvImageMask; 420 adapt->flags = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT; 421 adapt->name = "NV Video Overlay"; 422 adapt->nEncodings = 1; 423 adapt->pEncodings = &DummyEncoding; 424 adapt->nFormats = NUM_FORMATS_ALL; 425 adapt->pFormats = NVFormats; 426 adapt->nPorts = 1; 427 adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 428 pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]); 429 adapt->pPortPrivates[0].ptr = (pointer)(pPriv); 430 adapt->pAttributes = NVOverlayAttributes; 431 adapt->nAttributes = NUM_OVERLAY_ATTRIBUTES; 432 adapt->pImages = NVImages; 433 adapt->nImages = NUM_IMAGES_YUV; 434 adapt->PutVideo = NULL; 435 adapt->PutStill = NULL; 436 adapt->GetVideo = NULL; 437 adapt->GetStill = NULL; 438 adapt->StopVideo = NVStopOverlayVideo; 439 adapt->SetPortAttribute = NVSetOverlayPortAttribute; 440 adapt->GetPortAttribute = NVGetOverlayPortAttribute; 441 adapt->QueryBestSize = NVQueryBestSize; 442 adapt->PutImage = NVPutImage; 443 adapt->QueryImageAttributes = NVQueryImageAttributes; 444 445 pPriv->videoStatus = 0; 446 pPriv->currentBuffer = 0; 447 pPriv->grabbedByV4L = FALSE; 448 pPriv->blitter = FALSE; 449 450 NVSetPortDefaults (pScrnInfo, pPriv); 451 452 /* gotta uninit this someplace */ 453 REGION_NULL(pScreen, &pPriv->clip); 454 455 pNv->overlayAdaptor = adapt; 456 457 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 458 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER"); 459 xvContrast = MAKE_ATOM("XV_CONTRAST"); 460 xvColorKey = MAKE_ATOM("XV_COLORKEY"); 461 xvSaturation = MAKE_ATOM("XV_SATURATION"); 462 xvHue = MAKE_ATOM("XV_HUE"); 463 xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); 464 xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS"); 465 xvITURBT709 = MAKE_ATOM("XV_ITURBT_709"); 466 467 NVResetVideo(pScrnInfo); 468 469 return adapt; 470} 471 472static void 473NVPutOverlayImage ( 474 ScrnInfoPtr pScrnInfo, 475 int offset, 476 int id, 477 int dstPitch, 478 BoxPtr dstBox, 479 int x1, 480 int y1, 481 int x2, 482 int y2, 483 short width, 484 short height, 485 short src_w, 486 short src_h, 487 short drw_w, 488 short drw_h, 489 RegionPtr clipBoxes 490) 491{ 492 NVPtr pNv = NVPTR(pScrnInfo); 493 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 494 int buffer = pPriv->currentBuffer; 495 496 /* paint the color key */ 497 if(pPriv->autopaintColorKey && 498 (pPriv->grabbedByV4L || 499 !REGION_EQUAL(pScrnInfo->pScreen, &pPriv->clip, clipBoxes))) 500 { 501 /* we always paint V4L's color key */ 502 if(!pPriv->grabbedByV4L) 503 REGION_COPY(pScrnInfo->pScreen, &pPriv->clip, clipBoxes); 504 xf86XVFillKeyHelper(pScrnInfo->pScreen, pPriv->colorKey, clipBoxes); 505 } 506 507 if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) { 508 dstBox->y1 <<= 1; 509 dstBox->y2 <<= 1; 510 drw_h <<= 1; 511 } 512 513 pNv->PMC[(0x8900/4) + buffer] = offset; 514 pNv->PMC[(0x8928/4) + buffer] = (height << 16) | width; 515 pNv->PMC[(0x8930/4) + buffer] = ((y1 << 4) & 0xffff0000) | (x1 >> 12); 516 pNv->PMC[(0x8938/4) + buffer] = (src_w << 20) / drw_w; 517 pNv->PMC[(0x8940/4) + buffer] = (src_h << 20) / drw_h; 518 pNv->PMC[(0x8948/4) + buffer] = (dstBox->y1 << 16) | dstBox->x1; 519 pNv->PMC[(0x8950/4) + buffer] = ((dstBox->y2 - dstBox->y1) << 16) | 520 (dstBox->x2 - dstBox->x1); 521 522 dstPitch |= 1 << 20; /* use color key */ 523 524 if(id != FOURCC_UYVY) 525 dstPitch |= 1 << 16; 526 if(pPriv->iturbt_709) 527 dstPitch |= 1 << 24; 528 529 pNv->PMC[(0x8958/4) + buffer] = dstPitch; 530 pNv->PMC[0x00008704/4] = 0; 531 pNv->PMC[0x8700/4] = 1 << (buffer << 2); 532 533 pPriv->videoStatus = CLIENT_VIDEO_ON; 534} 535 536 537 538static void 539NVPutBlitImage ( 540 ScrnInfoPtr pScrnInfo, 541 int offset, 542 int id, 543 int dstPitch, 544 BoxPtr dstBox, 545 int x1, 546 int y1, 547 int x2, 548 int y2, 549 short width, 550 short height, 551 short src_w, 552 short src_h, 553 short drw_w, 554 short drw_h, 555 RegionPtr clipBoxes 556) 557{ 558 NVPtr pNv = NVPTR(pScrnInfo); 559 NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv); 560 BoxPtr pbox = REGION_RECTS(clipBoxes); 561 int nbox = REGION_NUM_RECTS(clipBoxes); 562 CARD32 dsdx, dtdy, size, point, srcpoint, format; 563 564 dsdx = (src_w << 20) / drw_w; 565 dtdy = (src_h << 20) / drw_h; 566 567 size = ((dstBox->y2 - dstBox->y1) << 16) | (dstBox->x2 - dstBox->x1); 568 point = (dstBox->y1 << 16) | dstBox->x1; 569 570 dstPitch |= (STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER << 16) | 571 (STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR << 24); 572 573 srcpoint = ((y1 << 4) & 0xffff0000) | (x1 >> 12); 574 575 switch(id) { 576 case FOURCC_RGB: 577 format = STRETCH_BLIT_FORMAT_X8R8G8B8; 578 break; 579 case FOURCC_UYVY: 580 format = STRETCH_BLIT_FORMAT_UYVY; 581 break; 582 default: 583 format = STRETCH_BLIT_FORMAT_YUYV; 584 break; 585 } 586 587 if(pNv->CurrentLayout.depth == 15) { 588 NVDmaStart(pNv, SURFACE_FORMAT, 1); 589 NVDmaNext (pNv, SURFACE_FORMAT_DEPTH15); 590 } 591 592 if(pPriv->SyncToVBlank) { 593 NVDmaKickoff(pNv); 594 NVWaitVSync(pNv); 595 } 596 597 if(pNv->BlendingPossible) { 598 NVDmaStart(pNv, STRETCH_BLIT_FORMAT, 2); 599 NVDmaNext (pNv, format); 600 NVDmaNext (pNv, STRETCH_BLIT_OPERATION_COPY); 601 } else { 602 NVDmaStart(pNv, STRETCH_BLIT_FORMAT, 1); 603 NVDmaNext (pNv, format); 604 } 605 606 while(nbox--) { 607 NVDmaStart(pNv, RECT_SOLID_COLOR, 1); 608 NVDmaNext (pNv, 0); 609 610 NVDmaStart(pNv, STRETCH_BLIT_CLIP_POINT, 6); 611 NVDmaNext (pNv, (pbox->y1 << 16) | pbox->x1); 612 NVDmaNext (pNv, ((pbox->y2 - pbox->y1) << 16) | (pbox->x2 - pbox->x1)); 613 NVDmaNext (pNv, point); 614 NVDmaNext (pNv, size); 615 NVDmaNext (pNv, dsdx); 616 NVDmaNext (pNv, dtdy); 617 618 NVDmaStart(pNv, STRETCH_BLIT_SRC_SIZE, 4); 619 NVDmaNext (pNv, (height << 16) | width); 620 NVDmaNext (pNv, dstPitch); 621 NVDmaNext (pNv, offset); 622 NVDmaNext (pNv, srcpoint); 623 pbox++; 624 } 625 626 if(pNv->CurrentLayout.depth == 15) { 627 NVDmaStart(pNv, SURFACE_FORMAT, 1); 628 NVDmaNext (pNv, SURFACE_FORMAT_DEPTH16); 629 } 630 631 NVDmaKickoff(pNv); 632#ifdef HAVE_XAA_H 633 SET_SYNC_FLAG(pNv->AccelInfoRec); 634#endif 635 pPriv->videoStatus = FREE_TIMER; 636 pPriv->videoTime = currentTime.milliseconds + FREE_DELAY; 637 pNv->VideoTimerCallback = NVVideoTimerCallback; 638} 639 640/* 641 * StopVideo 642 */ 643static void NVStopOverlayVideo 644( 645 ScrnInfoPtr pScrnInfo, 646 pointer data, 647 Bool Exit 648) 649{ 650 NVPtr pNv = NVPTR(pScrnInfo); 651 NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 652 653 if(pPriv->grabbedByV4L) return; 654 655 REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip); 656 657 if(Exit) { 658 if(pPriv->videoStatus & CLIENT_VIDEO_ON) 659 NVStopOverlay(pScrnInfo); 660 NVFreeOverlayMemory(pScrnInfo); 661 pPriv->videoStatus = 0; 662 } else { 663 if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 664 pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON; 665 pPriv->videoTime = currentTime.milliseconds + OFF_DELAY; 666 pNv->VideoTimerCallback = NVVideoTimerCallback; 667 } 668 } 669} 670 671static void NVStopBlitVideo 672( 673 ScrnInfoPtr pScrnInfo, 674 pointer data, 675 Bool Exit 676) 677{ 678} 679 680static int NVSetOverlayPortAttribute 681( 682 ScrnInfoPtr pScrnInfo, 683 Atom attribute, 684 INT32 value, 685 pointer data 686) 687{ 688 NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 689 690 if (attribute == xvBrightness) 691 { 692 if ((value < -512) || (value > 512)) 693 return BadValue; 694 pPriv->brightness = value; 695 } 696 else if (attribute == xvDoubleBuffer) 697 { 698 if ((value < 0) || (value > 1)) 699 return BadValue; 700 pPriv->doubleBuffer = value; 701 } 702 else if (attribute == xvContrast) 703 { 704 if ((value < 0) || (value > 8191)) 705 return BadValue; 706 pPriv->contrast = value; 707 } 708 else if (attribute == xvHue) 709 { 710 value %= 360; 711 if (value < 0) 712 value += 360; 713 pPriv->hue = value; 714 } 715 else if (attribute == xvSaturation) 716 { 717 if ((value < 0) || (value > 8191)) 718 return BadValue; 719 pPriv->saturation = value; 720 } 721 else if (attribute == xvColorKey) 722 { 723 pPriv->colorKey = value; 724 REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip); 725 } 726 else if (attribute == xvAutopaintColorKey) 727 { 728 if ((value < 0) || (value > 1)) 729 return BadValue; 730 pPriv->autopaintColorKey = value; 731 } 732 else if (attribute == xvITURBT709) 733 { 734 if ((value < 0) || (value > 1)) 735 return BadValue; 736 pPriv->iturbt_709 = value; 737 } 738 else if (attribute == xvSetDefaults) 739 { 740 NVSetPortDefaults(pScrnInfo, pPriv); 741 } 742 else 743 return BadMatch; 744 745 NVResetVideo(pScrnInfo); 746 return Success; 747} 748 749 750static int NVGetOverlayPortAttribute 751( 752 ScrnInfoPtr pScrnInfo, 753 Atom attribute, 754 INT32 *value, 755 pointer data 756) 757{ 758 NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 759 760 if (attribute == xvBrightness) 761 *value = pPriv->brightness; 762 else if (attribute == xvDoubleBuffer) 763 *value = (pPriv->doubleBuffer) ? 1 : 0; 764 else if (attribute == xvContrast) 765 *value = pPriv->contrast; 766 else if (attribute == xvSaturation) 767 *value = pPriv->saturation; 768 else if (attribute == xvHue) 769 *value = pPriv->hue; 770 else if (attribute == xvColorKey) 771 *value = pPriv->colorKey; 772 else if (attribute == xvAutopaintColorKey) 773 *value = (pPriv->autopaintColorKey) ? 1 : 0; 774 else if (attribute == xvITURBT709) 775 *value = (pPriv->iturbt_709) ? 1 : 0; 776 else 777 return BadMatch; 778 779 return Success; 780} 781 782static int NVSetBlitPortAttribute 783( 784 ScrnInfoPtr pScrnInfo, 785 Atom attribute, 786 INT32 value, 787 pointer data 788) 789{ 790 NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 791 NVPtr pNv = NVPTR(pScrnInfo); 792 793 if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) { 794 if ((value < 0) || (value > 1)) 795 return BadValue; 796 pPriv->SyncToVBlank = value; 797 } else 798 if (attribute == xvSetDefaults) { 799 pPriv->SyncToVBlank = pNv->WaitVSyncPossible; 800 } else 801 return BadMatch; 802 803 return Success; 804} 805 806static int NVGetBlitPortAttribute 807( 808 ScrnInfoPtr pScrnInfo, 809 Atom attribute, 810 INT32 *value, 811 pointer data 812) 813{ 814 NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 815 816 if(attribute == xvSyncToVBlank) 817 *value = (pPriv->SyncToVBlank) ? 1 : 0; 818 else 819 return BadMatch; 820 821 return Success; 822} 823 824 825/* 826 * QueryBestSize 827 */ 828static void NVQueryBestSize 829( 830 ScrnInfoPtr pScrnInfo, 831 Bool motion, 832 short vid_w, 833 short vid_h, 834 short drw_w, 835 short drw_h, 836 unsigned int *p_w, 837 unsigned int *p_h, 838 pointer data 839) 840{ 841 if(vid_w > (drw_w << 3)) 842 drw_w = vid_w >> 3; 843 if(vid_h > (drw_h << 3)) 844 drw_h = vid_h >> 3; 845 846 *p_w = drw_w; 847 *p_h = drw_h; 848} 849 850static void NVCopyData420 851( 852 unsigned char *src1, 853 unsigned char *src2, 854 unsigned char *src3, 855 unsigned char *dst1, 856 int srcPitch, 857 int srcPitch2, 858 int dstPitch, 859 int h, 860 int w 861) 862{ 863 CARD32 *dst; 864 CARD8 *s1, *s2, *s3; 865 int i, j; 866 867 w >>= 1; 868 869 for(j = 0; j < h; j++) { 870 dst = (CARD32*)dst1; 871 s1 = src1; s2 = src2; s3 = src3; 872 i = w; 873 while(i > 4) { 874#if X_BYTE_ORDER == X_BIG_ENDIAN 875 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0]; 876 dst[1] = (s1[2] << 24) | (s1[3] << 8) | (s3[1] << 16) | s2[1]; 877 dst[2] = (s1[4] << 24) | (s1[5] << 8) | (s3[2] << 16) | s2[2]; 878 dst[3] = (s1[6] << 24) | (s1[7] << 8) | (s3[3] << 16) | s2[3]; 879#else 880 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24); 881 dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24); 882 dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24); 883 dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24); 884#endif 885 dst += 4; s2 += 4; s3 += 4; s1 += 8; 886 i -= 4; 887 } 888 889 while(i--) { 890#if X_BYTE_ORDER == X_BIG_ENDIAN 891 dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0]; 892#else 893 dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24); 894#endif 895 dst++; s2++; s3++; 896 s1 += 2; 897 } 898 899 dst1 += dstPitch; 900 src1 += srcPitch; 901 if(j & 1) { 902 src2 += srcPitch2; 903 src3 += srcPitch2; 904 } 905 } 906} 907 908 909static void NVMoveDWORDS( 910 CARD32* dest, 911 CARD32* src, 912 int dwords ) 913{ 914 while(dwords & ~0x03) { 915 *dest = *src; 916 *(dest + 1) = *(src + 1); 917 *(dest + 2) = *(src + 2); 918 *(dest + 3) = *(src + 3); 919 src += 4; 920 dest += 4; 921 dwords -= 4; 922 } 923 if(!dwords) return; 924 *dest = *src; 925 if(dwords == 1) return; 926 *(dest + 1) = *(src + 1); 927 if(dwords == 2) return; 928 *(dest + 2) = *(src + 2); 929} 930 931#if X_BYTE_ORDER == X_BIG_ENDIAN 932static void NVMoveDWORDSSwapped( 933 CARD32* dest, 934 CARD8* src, 935 int dwords ) 936{ 937 while(dwords--) { 938 *dest++ = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0]; 939 src += 4; 940 } 941} 942#endif 943 944static void NVCopyData422 945( 946 unsigned char *src, 947 unsigned char *dst, 948 int srcPitch, 949 int dstPitch, 950 int h, 951 int w 952) 953{ 954 w >>= 1; /* pixels to DWORDS */ 955 while(h--) { 956 NVMoveDWORDS((CARD32*)dst, (CARD32*)src, w); 957 src += srcPitch; 958 dst += dstPitch; 959 } 960} 961 962static void NVCopyDataRGB 963( 964 unsigned char *src, 965 unsigned char *dst, 966 int srcPitch, 967 int dstPitch, 968 int h, 969 int w 970) 971{ 972 while(h--) { 973#if X_BYTE_ORDER == X_BIG_ENDIAN 974 NVMoveDWORDSSwapped((CARD32*)dst, (CARD8*)src, w); 975#else 976 NVMoveDWORDS((CARD32*)dst, (CARD32*)src, w); 977#endif 978 src += srcPitch; 979 dst += dstPitch; 980 } 981} 982 983 984/* 985 * PutImage 986 */ 987static int NVPutImage 988( 989 ScrnInfoPtr pScrnInfo, 990 short src_x, 991 short src_y, 992 short drw_x, 993 short drw_y, 994 short src_w, 995 short src_h, 996 short drw_w, 997 short drw_h, 998 int id, 999 unsigned char *buf, 1000 short width, 1001 short height, 1002 Bool Sync, 1003 RegionPtr clipBoxes, 1004 pointer data, 1005 DrawablePtr pDraw 1006) 1007{ 1008 NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 1009 NVPtr pNv = NVPTR(pScrnInfo); 1010 INT32 xa, xb, ya, yb; 1011 unsigned char *dst_start; 1012 int newSize, offset, s2offset, s3offset; 1013 int srcPitch, srcPitch2, dstPitch; 1014 int top, left, right, bottom, npixels, nlines, bpp; 1015 Bool skip = FALSE; 1016 BoxRec dstBox; 1017 CARD32 tmp; 1018 1019 /* 1020 * s2offset, s3offset - byte offsets into U and V plane of the 1021 * source where copying starts. Y plane is 1022 * done by editing "buf". 1023 * 1024 * offset - byte offset to the first line of the destination. 1025 * 1026 * dst_start - byte address to the first displayed pel. 1027 * 1028 */ 1029 1030 if(pPriv->grabbedByV4L) return Success; 1031 1032 /* make the compiler happy */ 1033 s2offset = s3offset = srcPitch2 = 0; 1034 1035 if(!pPriv->blitter) { 1036 if(src_w > (drw_w << 3)) 1037 drw_w = src_w >> 3; 1038 if(src_h > (drw_h << 3)) 1039 drw_h = src_h >> 3; 1040 } 1041 1042 /* Clip */ 1043 xa = src_x; 1044 xb = src_x + src_w; 1045 ya = src_y; 1046 yb = src_y + src_h; 1047 1048 dstBox.x1 = drw_x; 1049 dstBox.x2 = drw_x + drw_w; 1050 dstBox.y1 = drw_y; 1051 dstBox.y2 = drw_y + drw_h; 1052 1053 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, 1054 width, height)) 1055 return Success; 1056 1057 if(!pPriv->blitter) { 1058 dstBox.x1 -= pScrnInfo->frameX0; 1059 dstBox.x2 -= pScrnInfo->frameX0; 1060 dstBox.y1 -= pScrnInfo->frameY0; 1061 dstBox.y2 -= pScrnInfo->frameY0; 1062 } 1063 1064 bpp = pScrnInfo->bitsPerPixel >> 3; 1065 1066 switch(id) { 1067 case FOURCC_YV12: 1068 case FOURCC_I420: 1069 srcPitch = (width + 3) & ~3; /* of luma */ 1070 s2offset = srcPitch * height; 1071 srcPitch2 = ((width >> 1) + 3) & ~3; 1072 s3offset = (srcPitch2 * (height >> 1)) + s2offset; 1073 dstPitch = ((width << 1) + 63) & ~63; 1074 break; 1075 case FOURCC_UYVY: 1076 case FOURCC_YUY2: 1077 srcPitch = width << 1; 1078 dstPitch = ((width << 1) + 63) & ~63; 1079 break; 1080 case FOURCC_RGB: 1081 srcPitch = width << 2; 1082 dstPitch = ((width << 2) + 63) & ~63; 1083 break; 1084 default: 1085 return BadImplementation; 1086 } 1087 1088 newSize = height * dstPitch / bpp; 1089 1090 if(pPriv->doubleBuffer) 1091 newSize <<= 1; 1092 1093 pPriv->linear = NVAllocateOverlayMemory(pScrnInfo, 1094 pPriv->linear, 1095 newSize); 1096 1097 if(!pPriv->linear) return BadAlloc; 1098 1099 offset = pPriv->linear->offset * bpp; 1100 1101 if(pPriv->doubleBuffer) { 1102 int mask = 1 << (pPriv->currentBuffer << 2); 1103 1104#if 0 1105 /* burn the CPU until the next buffer is available */ 1106 while(pNv->PMC[0x00008700/4] & mask); 1107#else 1108 /* overwrite the newest buffer if there's not one free */ 1109 if(pNv->PMC[0x00008700/4] & mask) { 1110 if(!pPriv->currentBuffer) 1111 offset += (newSize * bpp) >> 1; 1112 skip = TRUE; 1113 } else 1114#endif 1115 if(pPriv->currentBuffer) 1116 offset += (newSize * bpp) >> 1; 1117 } 1118 1119 dst_start = pNv->FbStart + offset; 1120 1121 /* We need to enlarge the copied rectangle by a pixel so the HW 1122 filtering doesn't pick up junk laying outside of the source */ 1123 1124 left = (xa - 0x00010000) >> 16; 1125 if(left < 0) left = 0; 1126 top = (ya - 0x00010000) >> 16; 1127 if(top < 0) top = 0; 1128 right = (xb + 0x0001ffff) >> 16; 1129 if(right > width) right = width; 1130 bottom = (yb + 0x0001ffff) >> 16; 1131 if(bottom > height) bottom = height; 1132 1133 if(pPriv->blitter) NVSync(pScrnInfo); 1134 1135 switch(id) { 1136 case FOURCC_YV12: 1137 case FOURCC_I420: 1138 left &= ~1; 1139 npixels = ((right + 1) & ~1) - left; 1140 top &= ~1; 1141 nlines = ((bottom + 1) & ~1) - top; 1142 1143 dst_start += (left << 1) + (top * dstPitch); 1144 tmp = ((top >> 1) * srcPitch2) + (left >> 1); 1145 s2offset += tmp; 1146 s3offset += tmp; 1147 if(id == FOURCC_I420) { 1148 tmp = s2offset; 1149 s2offset = s3offset; 1150 s3offset = tmp; 1151 } 1152 NVCopyData420(buf + (top * srcPitch) + left, 1153 buf + s2offset, buf + s3offset, 1154 dst_start, srcPitch, srcPitch2, 1155 dstPitch, nlines, npixels); 1156 break; 1157 case FOURCC_UYVY: 1158 case FOURCC_YUY2: 1159 left &= ~1; 1160 npixels = ((right + 1) & ~1) - left; 1161 nlines = bottom - top; 1162 1163 left <<= 1; 1164 buf += (top * srcPitch) + left; 1165 dst_start += left + (top * dstPitch); 1166 1167 NVCopyData422(buf, dst_start, srcPitch, dstPitch, nlines, npixels); 1168 break; 1169 case FOURCC_RGB: 1170 npixels = right - left; 1171 nlines = bottom - top; 1172 1173 left <<= 2; 1174 buf += (top * srcPitch) + left; 1175 dst_start += left + (top * dstPitch); 1176 1177 NVCopyDataRGB(buf, dst_start, srcPitch, dstPitch, nlines, npixels); 1178 break; 1179 default: 1180 return BadImplementation; 1181 } 1182 1183 if(!skip) { 1184 if(pPriv->blitter) { 1185 NVPutBlitImage(pScrnInfo, offset, id, dstPitch, &dstBox, 1186 xa, ya, xb, yb, 1187 width, height, src_w, src_h, drw_w, drw_h, 1188 clipBoxes); 1189 } else { 1190 NVPutOverlayImage(pScrnInfo, offset, id, dstPitch, &dstBox, 1191 xa, ya, xb, yb, 1192 width, height, src_w, src_h, drw_w, drw_h, 1193 clipBoxes); 1194 pPriv->currentBuffer ^= 1; 1195 } 1196 } 1197 1198 return Success; 1199} 1200/* 1201 * QueryImageAttributes 1202 */ 1203static int NVQueryImageAttributes 1204( 1205 ScrnInfoPtr pScrnInfo, 1206 int id, 1207 unsigned short *w, 1208 unsigned short *h, 1209 int *pitches, 1210 int *offsets 1211) 1212{ 1213 int size, tmp; 1214 1215 if(*w > 2046) 1216 *w = 2046; 1217 if(*h > 2046) 1218 *h = 2046; 1219 1220 *w = (*w + 1) & ~1; 1221 if (offsets) 1222 offsets[0] = 0; 1223 1224 switch (id) 1225 { 1226 case FOURCC_YV12: 1227 case FOURCC_I420: 1228 *h = (*h + 1) & ~1; 1229 size = (*w + 3) & ~3; 1230 if (pitches) 1231 pitches[0] = size; 1232 size *= *h; 1233 if (offsets) 1234 offsets[1] = size; 1235 tmp = ((*w >> 1) + 3) & ~3; 1236 if (pitches) 1237 pitches[1] = pitches[2] = tmp; 1238 tmp *= (*h >> 1); 1239 size += tmp; 1240 if (offsets) 1241 offsets[2] = size; 1242 size += tmp; 1243 break; 1244 case FOURCC_UYVY: 1245 case FOURCC_YUY2: 1246 size = *w << 1; 1247 if (pitches) 1248 pitches[0] = size; 1249 size *= *h; 1250 break; 1251 case FOURCC_RGB: 1252 size = *w << 2; 1253 if(pitches) 1254 pitches[0] = size; 1255 size *= *h; 1256 break; 1257 default: 1258 *w = *h = size = 0; 1259 break; 1260 } 1261 return size; 1262} 1263 1264static void NVVideoTimerCallback 1265( 1266 ScrnInfoPtr pScrnInfo, 1267 Time currentTime 1268) 1269{ 1270 NVPtr pNv = NVPTR(pScrnInfo); 1271 NVPortPrivPtr pOverPriv = NULL; 1272 NVPortPrivPtr pBlitPriv = NULL; 1273 Bool needCallback = FALSE; 1274 1275 if(!pScrnInfo->vtSema) return; 1276 1277 if(pNv->overlayAdaptor) { 1278 pOverPriv = GET_OVERLAY_PRIVATE(pNv); 1279 if(!pOverPriv->videoStatus) 1280 pOverPriv = NULL; 1281 } 1282 1283 if(pNv->blitAdaptor) { 1284 pBlitPriv = GET_BLIT_PRIVATE(pNv); 1285 if(!pBlitPriv->videoStatus) 1286 pBlitPriv = NULL; 1287 } 1288 1289 if(pOverPriv) { 1290 if(pOverPriv->videoTime < currentTime) { 1291 if(pOverPriv->videoStatus & OFF_TIMER) { 1292 NVStopOverlay(pScrnInfo); 1293 pOverPriv->videoStatus = FREE_TIMER; 1294 pOverPriv->videoTime = currentTime + FREE_DELAY; 1295 needCallback = TRUE; 1296 } else 1297 if(pOverPriv->videoStatus & FREE_TIMER) { 1298 NVFreeOverlayMemory(pScrnInfo); 1299 pOverPriv->videoStatus = 0; 1300 } 1301 } else { 1302 needCallback = TRUE; 1303 } 1304 } 1305 1306 if(pBlitPriv) { 1307 if(pBlitPriv->videoTime < currentTime) { 1308 NVFreeBlitMemory(pScrnInfo); 1309 pBlitPriv->videoStatus = 0; 1310 } else { 1311 needCallback = TRUE; 1312 } 1313 } 1314 1315 pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL; 1316} 1317 1318 1319/***** Exported offscreen surface stuff ****/ 1320 1321 1322static int 1323NVAllocSurface ( 1324 ScrnInfoPtr pScrnInfo, 1325 int id, 1326 unsigned short w, 1327 unsigned short h, 1328 XF86SurfacePtr surface 1329) 1330{ 1331 NVPtr pNv = NVPTR(pScrnInfo); 1332 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 1333 int size, bpp; 1334 1335 bpp = pScrnInfo->bitsPerPixel >> 3; 1336 1337 if(pPriv->grabbedByV4L) return BadAlloc; 1338 1339 if((w > 2046) || (h > 2046)) return BadValue; 1340 1341 w = (w + 1) & ~1; 1342 pPriv->pitch = ((w << 1) + 63) & ~63; 1343 size = h * pPriv->pitch / bpp; 1344 1345 pPriv->linear = NVAllocateOverlayMemory(pScrnInfo, pPriv->linear, 1346 size); 1347 1348 if(!pPriv->linear) return BadAlloc; 1349 1350 pPriv->offset = pPriv->linear->offset * bpp; 1351 1352 surface->width = w; 1353 surface->height = h; 1354 surface->pScrn = pScrnInfo; 1355 surface->pitches = &pPriv->pitch; 1356 surface->offsets = &pPriv->offset; 1357 surface->devPrivate.ptr = (pointer)pPriv; 1358 surface->id = id; 1359 1360 /* grab the video */ 1361 NVStopOverlay(pScrnInfo); 1362 pPriv->videoStatus = 0; 1363 REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip); 1364 pPriv->grabbedByV4L = TRUE; 1365 1366 return Success; 1367} 1368 1369static int 1370NVStopSurface (XF86SurfacePtr surface) 1371{ 1372 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr); 1373 1374 if(pPriv->grabbedByV4L && pPriv->videoStatus) { 1375 NVStopOverlay(surface->pScrn); 1376 pPriv->videoStatus = 0; 1377 } 1378 1379 return Success; 1380} 1381 1382static int 1383NVFreeSurface (XF86SurfacePtr surface) 1384{ 1385 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr); 1386 1387 if(pPriv->grabbedByV4L) { 1388 NVStopSurface(surface); 1389 NVFreeOverlayMemory(surface->pScrn); 1390 pPriv->grabbedByV4L = FALSE; 1391 } 1392 1393 return Success; 1394} 1395 1396static int 1397NVGetSurfaceAttribute ( 1398 ScrnInfoPtr pScrnInfo, 1399 Atom attribute, 1400 INT32 *value 1401) 1402{ 1403 NVPtr pNv = NVPTR(pScrnInfo); 1404 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 1405 1406 return NVGetOverlayPortAttribute(pScrnInfo, attribute, value, (pointer)pPriv); 1407} 1408 1409static int 1410NVSetSurfaceAttribute( 1411 ScrnInfoPtr pScrnInfo, 1412 Atom attribute, 1413 INT32 value 1414) 1415{ 1416 NVPtr pNv = NVPTR(pScrnInfo); 1417 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 1418 1419 return NVSetOverlayPortAttribute(pScrnInfo, attribute, value, (pointer)pPriv); 1420} 1421 1422static int 1423NVDisplaySurface ( 1424 XF86SurfacePtr surface, 1425 short src_x, short src_y, 1426 short drw_x, short drw_y, 1427 short src_w, short src_h, 1428 short drw_w, short drw_h, 1429 RegionPtr clipBoxes 1430) 1431{ 1432 ScrnInfoPtr pScrnInfo = surface->pScrn; 1433 NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr); 1434 INT32 xa, xb, ya, yb; 1435 BoxRec dstBox; 1436 1437 if(!pPriv->grabbedByV4L) return Success; 1438 1439 if(src_w > (drw_w << 3)) 1440 drw_w = src_w >> 3; 1441 if(src_h > (drw_h << 3)) 1442 drw_h = src_h >> 3; 1443 1444 /* Clip */ 1445 xa = src_x; 1446 xb = src_x + src_w; 1447 ya = src_y; 1448 yb = src_y + src_h; 1449 1450 dstBox.x1 = drw_x; 1451 dstBox.x2 = drw_x + drw_w; 1452 dstBox.y1 = drw_y; 1453 dstBox.y2 = drw_y + drw_h; 1454 1455 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, 1456 surface->width, surface->height)) 1457 { 1458 return Success; 1459 } 1460 1461 dstBox.x1 -= pScrnInfo->frameX0; 1462 dstBox.x2 -= pScrnInfo->frameX0; 1463 dstBox.y1 -= pScrnInfo->frameY0; 1464 dstBox.y2 -= pScrnInfo->frameY0; 1465 1466 pPriv->currentBuffer = 0; 1467 1468 NVPutOverlayImage (pScrnInfo, surface->offsets[0], surface->id, 1469 surface->pitches[0], &dstBox, xa, ya, xb, yb, 1470 surface->width, surface->height, src_w, src_h, 1471 drw_w, drw_h, clipBoxes); 1472 1473 return Success; 1474} 1475 1476XF86OffscreenImageRec NVOffscreenImages[2] = 1477{ 1478 { 1479 &NVImages[0], 1480 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 1481 NVAllocSurface, 1482 NVFreeSurface, 1483 NVDisplaySurface, 1484 NVStopSurface, 1485 NVGetSurfaceAttribute, 1486 NVSetSurfaceAttribute, 1487 2046, 2046, 1488 NUM_OVERLAY_ATTRIBUTES - 1, 1489 &NVOverlayAttributes[1] 1490 }, 1491 { 1492 &NVImages[2], 1493 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 1494 NVAllocSurface, 1495 NVFreeSurface, 1496 NVDisplaySurface, 1497 NVStopSurface, 1498 NVGetSurfaceAttribute, 1499 NVSetSurfaceAttribute, 1500 2046, 2046, 1501 NUM_OVERLAY_ATTRIBUTES - 1, 1502 &NVOverlayAttributes[1] 1503 }, 1504}; 1505 1506static void 1507NVInitOffscreenImages (ScreenPtr pScreen) 1508{ 1509 xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2); 1510} 1511