atimach64xv.c revision 0b0ce0bf
1/* 2 * Copyright 2003 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of Marc Aurele La France not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. Marc Aurele La France makes no representations 11 * about the suitability of this software for any purpose. It is provided 12 * "as-is" without express or implied warranty. 13 * 14 * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO 16 * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 */ 22 23#ifdef HAVE_CONFIG_H 24#include "config.h" 25#endif 26 27#include <string.h> 28 29#include "ati.h" 30#include "atichip.h" 31#include "atimach64accel.h" 32#include "atimach64io.h" 33#include "atixv.h" 34#include "atimach64version.h" 35 36#include <X11/extensions/Xv.h> 37#include "fourcc.h" 38#include "xf86xv.h" 39 40#define MAKE_ATOM(string) MakeAtom(string, strlen(string), TRUE) 41#define MaxScale (CARD32)(CARD16)(-1) 42 43static unsigned long ATIMach64XVAtomGeneration = (unsigned long)(-1); 44 45static XF86VideoEncodingRec ATIMach64VideoEncoding[] = 46{ 47 { 0, "XV_IMAGE", 720, 2048, {1, 1} } 48}; 49#define nATIMach64VideoEncoding NumberOf(ATIMach64VideoEncoding) 50 51static XF86VideoFormatRec ATIMach64VideoFormat[] = 52{ 53 { 8, TrueColor}, 54 { 8, DirectColor}, 55 { 8, PseudoColor}, 56 { 8, GrayScale}, 57 { 8, StaticGray}, 58 { 8, StaticColor}, 59 {15, TrueColor}, 60 {16, TrueColor}, 61 {24, TrueColor}, 62 {15, DirectColor}, 63 {16, DirectColor}, 64 {24, DirectColor} 65}; 66#define nATIMach64VideoFormat NumberOf(ATIMach64VideoFormat) 67 68static XF86AttributeRec ATIMach64Attribute[] = 69{ 70 /* These are only supported on the Rage Pro and later ... */ 71 { 72 XvSettable | XvGettable, 73 -1000, 1000, 74 "XV_SATURATION" 75 }, 76 { 77 XvSettable | XvGettable, 78 -1000, 1000, 79 "XV_BRIGHTNESS" 80 }, 81 { 82 XvSettable | XvGettable, 83 -1000, 1000, 84 "XV_COLOUR" 85 }, 86 { 87 XvSettable | XvGettable, 88 -1000, 1000, 89 "XV_COLOR" 90 }, 91 92 /* Local attributes, odds and ends for compatibility, etc... */ 93 { 94 XvSettable | XvGettable, 95 0, 1, 96 "XV_AUTOPAINT_COLOURKEY" 97 }, 98 { 99 XvSettable | XvGettable, 100 0, 1, 101 "XV_AUTOPAINT_COLORKEY" 102 }, 103 { 104 XvSettable | XvGettable, 105 0, (1 << 24) - 1, 106 "XV_COLOURKEY" 107 }, 108 { 109 XvSettable | XvGettable, 110 0, (1 << 24) - 1, 111 "XV_COLORKEY" 112 }, 113 { 114 XvSettable | XvGettable, 115 0, (1 << 24) - 1, 116 "XV_COLOURKEY_MASK" 117 }, 118 { 119 XvSettable | XvGettable, 120 0, (1 << 24) - 1, 121 "XV_COLORKEY_MASK" 122 }, 123 { 124 XvSettable, 125 0, 0, 126 "XV_SET_DEFAULTS" 127 }, 128 { /* Keep last */ 129 XvSettable | XvGettable, 130 0, 1, 131 "XV_DOUBLE_BUFFER" 132 } 133}; 134#define nATIMach64Attribute NumberOf(ATIMach64Attribute) 135 136static XF86ImageRec ATIMach64Image[] = 137{ 138 XVIMAGE_YUY2, 139 XVIMAGE_UYVY, 140 XVIMAGE_YV12, 141 XVIMAGE_I420 142}; 143#define nATIMach64Image NumberOf(ATIMach64Image) 144 145/* A local XVideo adaptor attribute record */ 146typedef struct _ATIMach64Attribute 147{ 148 Atom AttributeID; 149 INT32 MaxValue; /* ... for the hardware */ 150 void (*SetAttribute) (ATIPtr, INT32); 151 INT32 (*GetAttribute) (ATIPtr); 152} ATIMach64AttributeRec, *ATIMach64AttributePtr; 153 154/* Functions to get/set XVideo adaptor attributes */ 155 156static void 157ATIMach64SetSaturationAttribute 158( 159 ATIPtr pATI, 160 INT32 Value 161) 162{ 163 /* Set the register */ 164 pATI->NewHW.scaler_colour_cntl &= 165 ~(SCALE_SATURATION_U | SCALE_SATURATION_V); 166 pATI->NewHW.scaler_colour_cntl |= SetBits(Value, SCALE_SATURATION_U) | 167 SetBits(Value, SCALE_SATURATION_V); 168 outf(SCALER_COLOUR_CNTL, pATI->NewHW.scaler_colour_cntl); 169} 170 171static INT32 172ATIMach64GetSaturationAttribute 173( 174 ATIPtr pATI 175) 176{ 177 return (INT32)GetBits(pATI->NewHW.scaler_colour_cntl, SCALE_SATURATION_U); 178} 179 180static void 181ATIMach64SetBrightnessAttribute 182( 183 ATIPtr pATI, 184 INT32 Value 185) 186{ 187 /* Set the register */ 188 pATI->NewHW.scaler_colour_cntl &= ~SCALE_BRIGHTNESS; 189 pATI->NewHW.scaler_colour_cntl |= SetBits(Value, SCALE_BRIGHTNESS); 190 outf(SCALER_COLOUR_CNTL, pATI->NewHW.scaler_colour_cntl); 191} 192 193static INT32 194ATIMach64GetBrightnessAttribute 195( 196 ATIPtr pATI 197) 198{ 199 return (INT32)GetBits(pATI->NewHW.scaler_colour_cntl, SCALE_BRIGHTNESS); 200} 201 202static void 203ATIMach64SetDoubleBufferAttribute 204( 205 ATIPtr pATI, 206 INT32 Value 207) 208{ 209 pATI->DoubleBuffer = Value; 210} 211 212static INT32 213ATIMach64GetDoubleBufferAttribute 214( 215 ATIPtr pATI 216) 217{ 218 return (int)pATI->DoubleBuffer; 219} 220 221static void 222ATIMach64SetAutoPaintAttribute 223( 224 ATIPtr pATI, 225 INT32 Value 226) 227{ 228 pATI->AutoPaint = Value; 229} 230 231static INT32 232ATIMach64GetAutoPaintAttribute 233( 234 ATIPtr pATI 235) 236{ 237 return (int)pATI->AutoPaint; 238} 239 240static void 241ATIMach64SetColourKeyAttribute 242( 243 ATIPtr pATI, 244 INT32 Value 245) 246{ 247 pATI->NewHW.overlay_graphics_key_clr = 248 (CARD32)(Value & ((1 << pATI->depth) - 1)); 249 outf(OVERLAY_GRAPHICS_KEY_CLR, pATI->NewHW.overlay_graphics_key_clr); 250} 251 252static INT32 253ATIMach64GetColourKeyAttribute 254( 255 ATIPtr pATI 256) 257{ 258 return (INT32)pATI->NewHW.overlay_graphics_key_clr; 259} 260 261static void 262ATIMach64SetColourKeyMaskAttribute 263( 264 ATIPtr pATI, 265 INT32 Value 266) 267{ 268 pATI->NewHW.overlay_graphics_key_msk = 269 (CARD32)(Value & ((1 << pATI->depth) - 1)); 270 outf(OVERLAY_GRAPHICS_KEY_MSK, pATI->NewHW.overlay_graphics_key_msk); 271} 272 273static INT32 274ATIMach64GetColourKeyMaskAttribute 275( 276 ATIPtr pATI 277) 278{ 279 return (INT32)pATI->NewHW.overlay_graphics_key_msk; 280} 281 282/* 283 * ATIMach64SetDefaultAttributes -- 284 * 285 * This function calls other functions to set default values for the various 286 * attributes of an XVideo port. 287 */ 288static void 289ATIMach64SetDefaultAttributes 290( 291 ATIPtr pATI, 292 INT32 Value 293) 294{ 295 ATIMach64SetAutoPaintAttribute(pATI, TRUE); 296 ATIMach64SetDoubleBufferAttribute(pATI, FALSE); 297 ATIMach64SetColourKeyMaskAttribute(pATI, (1 << pATI->depth) - 1); 298 ATIMach64SetColourKeyAttribute(pATI, (3 << ((2 * pATI->depth) / 3)) | 299 (2 << ((1 * pATI->depth) / 3)) | 300 (1 << ((0 * pATI->depth) / 3))); 301 302 if (pATI->Chip < ATI_CHIP_264GTPRO) 303 return; 304 305 ATIMach64SetBrightnessAttribute(pATI, 32); 306 ATIMach64SetSaturationAttribute(pATI, 16); 307} 308 309/* 310 * There is a one-to-one correspondence between elements of the following array 311 * and those of ATIMach64Attribute. 312 */ 313static ATIMach64AttributeRec ATIMach64AttributeInfo[nATIMach64Attribute] = 314{ 315 { /* SATURATION */ 316 0, 23, 317 ATIMach64SetSaturationAttribute, 318 ATIMach64GetSaturationAttribute 319 }, 320 { /* BRIGHTNESS */ 321 0, 63, 322 ATIMach64SetBrightnessAttribute, 323 ATIMach64GetBrightnessAttribute 324 }, 325 { /* COLOUR */ 326 0, 23, 327 ATIMach64SetSaturationAttribute, 328 ATIMach64GetSaturationAttribute 329 }, 330 { /* COLOR */ 331 0, 23, 332 ATIMach64SetSaturationAttribute, 333 ATIMach64GetSaturationAttribute 334 }, 335 { /* AUTOPAINT_COLOURKEY */ 336 0, 1, 337 ATIMach64SetAutoPaintAttribute, 338 ATIMach64GetAutoPaintAttribute 339 }, 340 { /* AUTOPAINT_COLORKEY */ 341 0, 1, 342 ATIMach64SetAutoPaintAttribute, 343 ATIMach64GetAutoPaintAttribute 344 }, 345 { /* COLOURKEY */ 346 0, (1 << 24) - 1, 347 ATIMach64SetColourKeyAttribute, 348 ATIMach64GetColourKeyAttribute 349 }, 350 { /* COLORKEY */ 351 0, (1 << 24) - 1, 352 ATIMach64SetColourKeyAttribute, 353 ATIMach64GetColourKeyAttribute 354 }, 355 { /* COLOURKEY_MASK */ 356 0, (1 << 24) - 1, 357 ATIMach64SetColourKeyMaskAttribute, 358 ATIMach64GetColourKeyMaskAttribute 359 }, 360 { /* COLORKEY_MASK */ 361 0, (1 << 24) - 1, 362 ATIMach64SetColourKeyMaskAttribute, 363 ATIMach64GetColourKeyMaskAttribute 364 }, 365 { /* SET_DEFAULTS */ 366 0, 0, 367 ATIMach64SetDefaultAttributes, 368 NULL 369 }, 370 { /* DOUBLE_BUFFER */ 371 0, 1, 372 ATIMach64SetDoubleBufferAttribute, 373 ATIMach64GetDoubleBufferAttribute 374 } 375}; 376 377/* 378 * ATIMach64FindAttribute -- 379 * 380 * This function is called to locate an Xv attribute's table entry. 381 */ 382static int 383ATIMach64FindPortAttribute 384( 385 ATIPtr pATI, 386 Atom AttributeID 387) 388{ 389 int iAttribute; 390 391 if (pATI->Chip < ATI_CHIP_264GTPRO) 392 iAttribute = 4; 393 else 394 iAttribute = 0; 395 396 for (; iAttribute < nATIMach64Attribute; iAttribute++) 397 if (AttributeID == ATIMach64AttributeInfo[iAttribute].AttributeID) 398 return iAttribute; 399 400 return -1; 401} 402 403/* 404 * ATIMach64SetPortAttribute -- 405 * 406 * This function sets the value of a particular port's attribute. 407 */ 408static int 409ATIMach64SetPortAttribute 410( 411 ScrnInfoPtr pScreenInfo, 412 Atom AttributeID, 413 INT32 Value, 414 pointer pATI 415) 416{ 417 INT32 Range; 418 int iAttribute; 419 420 if (((iAttribute = ATIMach64FindPortAttribute(pATI, AttributeID)) < 0) || 421 !ATIMach64AttributeInfo[iAttribute].SetAttribute) 422 return BadMatch; 423 424 Range = ATIMach64Attribute[iAttribute].max_value - 425 ATIMach64Attribute[iAttribute].min_value; 426 427 if (Range >= 0) 428 { 429 /* Limit and scale the value */ 430 Value -= ATIMach64Attribute[iAttribute].min_value; 431 432 if (Value < 0) 433 Value = 0; 434 else if (Value > Range) 435 Value = Range; 436 437 if (Range != ATIMach64AttributeInfo[iAttribute].MaxValue) 438 { 439 if (ATIMach64AttributeInfo[iAttribute].MaxValue > 0) 440 Value *= ATIMach64AttributeInfo[iAttribute].MaxValue; 441 if (Range > 0) 442 Value /= Range; 443 } 444 } 445 446 (*ATIMach64AttributeInfo[iAttribute].SetAttribute)(pATI, Value); 447 448 return Success; 449} 450 451/* 452 * ATIMach64SetPortAttribute -- 453 * 454 * This function retrieves the value of a particular port's attribute. 455 */ 456static int 457ATIMach64GetPortAttribute 458( 459 ScrnInfoPtr pScreenInfo, 460 Atom AttributeID, 461 INT32 *Value, 462 pointer pATI 463) 464{ 465 INT32 Range; 466 int iAttribute; 467 468 if (!Value || 469 ((iAttribute = ATIMach64FindPortAttribute(pATI, AttributeID)) < 0) || 470 !ATIMach64AttributeInfo[iAttribute].GetAttribute) 471 return BadMatch; 472 473 *Value = (*ATIMach64AttributeInfo[iAttribute].GetAttribute)(pATI); 474 475 Range = ATIMach64Attribute[iAttribute].max_value - 476 ATIMach64Attribute[iAttribute].min_value; 477 478 if (Range >= 0) 479 { 480 if (Range != ATIMach64AttributeInfo[iAttribute].MaxValue) 481 { 482 /* (Un-)scale the value */ 483 if (Range > 0) 484 *Value *= Range; 485 if (ATIMach64AttributeInfo[iAttribute].MaxValue > 0) 486 *Value /= ATIMach64AttributeInfo[iAttribute].MaxValue; 487 } 488 489 *Value += ATIMach64Attribute[iAttribute].min_value; 490 } 491 492 return Success; 493} 494 495static pointer 496ATIMach64XVMemAlloc 497( 498 ScreenPtr pScreen, 499 pointer pVideo, 500 int size, 501 int *offset, 502 ATIPtr pATI 503); 504 505static void 506ATIMach64XVMemFree 507( 508 ScreenPtr pScreen, 509 pointer pVideo, 510 ATIPtr pATI 511); 512 513#ifdef USE_XAA 514/* 515 * ATIMach64RemoveLinearCallback -- 516 * 517 * This is called by the framebuffer manager to release the offscreen XVideo 518 * buffer after the video has been temporarily disabled due to its window being 519 * iconified or completely occluded. 520 */ 521static void 522ATIMach64RemoveLinearCallback 523( 524 FBLinearPtr pLinear 525) 526{ 527 ATIPtr pATI = ATIPTR(xf86ScreenToScrn(pLinear->pScreen)); 528 529 pATI->pXVBuffer = NULL; 530 outf(OVERLAY_SCALE_CNTL, SCALE_EN); 531} 532#endif /* USE_XAA */ 533 534/* 535 * ATIMach64StopVideo -- 536 * 537 * This is called to stop displaying a video. Note that, to prevent jittering 538 * this doesn't actually turn off the overlay unless 'Cleanup' is TRUE, i.e. 539 * when the video is to be actually stopped rather than temporarily disabled. 540 */ 541static void 542ATIMach64StopVideo 543( 544 ScrnInfoPtr pScreenInfo, 545 pointer Data, 546 Bool Cleanup 547) 548{ 549 ScreenPtr pScreen = pScreenInfo->pScreen; 550 ATIPtr pATI = Data; 551 552 if (pATI->ActiveSurface) 553 return; 554 555 REGION_EMPTY(pScreen, &pATI->VideoClip); 556 557#ifdef USE_XAA 558 if (!pATI->useEXA && !Cleanup) 559 { 560 /* 561 * Free offscreen buffer if/when its allocation is needed by XAA's 562 * pixmap cache. 563 */ 564 FBLinearPtr linear = (FBLinearPtr)pATI->pXVBuffer; 565 if (linear) 566 linear->RemoveLinearCallback = 567 ATIMach64RemoveLinearCallback; 568 return; 569 } 570#endif /* USE_XAA */ 571 572 ATIMach64XVMemFree(pScreen, pATI->pXVBuffer, pATI); 573 pATI->pXVBuffer = NULL; 574 outf(OVERLAY_SCALE_CNTL, SCALE_EN); 575} 576 577/* 578 * ATIMach64QueryBestSize -- 579 * 580 * Quoting XVideo docs: 581 * 582 * This function provides the client with a way to query what the destination 583 * dimensions would end up being if they were to request that an area 584 * VideoWidth by VideoHeight from the video stream be scaled to rectangle of 585 * DrawableWidth by DrawableHeight on the screen. Since it is not expected 586 * that all hardware will be able to get the target dimensions exactly, it is 587 * important that the driver provide this function. 588 */ 589static void 590ATIMach64QueryBestSize 591( 592 ScrnInfoPtr pScreenInfo, 593 Bool Motion, 594 short VideoWidth, 595 short VideoHeight, 596 short DrawableWidth, 597 short DrawableHeight, 598 unsigned int *Width, 599 unsigned int *Height, 600 pointer pATI 601) 602{ 603 *Width = DrawableWidth; 604 *Height = DrawableHeight; 605} 606 607/* 608 * ATIMach64QueryImageAttributes -- 609 * 610 * Quoting XVideo docs: 611 * 612 * This function is called to let the driver specify how data for a particular 613 * image of size Width by Height should be stored. Sometimes only the size and 614 * corrected width and height are needed. In that case pitches and offsets are 615 * NULL. The size of the memory required for the image is returned by this 616 * function. The width and height of the requested image can be altered by the 617 * driver to reflect format limitations (such as component sampling periods 618 * that are larger than one). If pPitch and pOffset are not NULL, these will 619 * be arrays with as many elements in them as there are planes in the image 620 * format. The driver should specify the pitch (in bytes) of each scanline in 621 * the particular plane as well as the offset to that plane (in bytes) from the 622 * beginning of the image. 623 */ 624static int 625ATIMach64QueryImageAttributes 626( 627 ScrnInfoPtr pScreenInfo, 628 int ImageID, 629 unsigned short *Width, 630 unsigned short *Height, 631 int *pPitch, 632 int *pOffset 633) 634{ 635 int Size, tmp; 636 637 if (!Width || !Height) 638 return 0; 639 640 if (*Width > 2048) 641 *Width = 2048; 642 else 643 *Width = (*Width + 1) & ~1; 644 645 if (*Height > 2048) 646 *Height = 2048; 647 648 if (pOffset) 649 pOffset[0] = 0; 650 651 switch (ImageID) 652 { 653 case FOURCC_YV12: 654 case FOURCC_I420: 655 *Height = (*Height + 1) & ~1; 656 Size = (*Width + 3) & ~3; 657 if (pPitch) 658 pPitch[0] = Size; 659 Size *= *Height; 660 if (pOffset) 661 pOffset[1] = Size; 662 tmp = ((*Width >> 1) + 3) & ~3; 663 if (pPitch) 664 pPitch[1] = pPitch[2] = tmp; 665 tmp *= (*Height >> 1); 666 Size += tmp; 667 if (pOffset) 668 pOffset[2] = Size; 669 Size += tmp; 670 break; 671 672 case FOURCC_UYVY: 673 case FOURCC_YUY2: 674 Size = *Width << 1; 675 if (pPitch) 676 pPitch[0] = Size; 677 Size *= *Height; 678 break; 679 680 default: 681 Size = 0; 682 break; 683 } 684 685 return Size; 686} 687 688/* 689 * ATIMach64ScaleVideo -- 690 * 691 * This function is called to calculate overlay scaling factors. 692 */ 693static void 694ATIMach64ScaleVideo 695( 696 ATIPtr pATI, 697 DisplayModePtr pMode, 698 int SrcW, 699 int SrcH, 700 int DstW, 701 int DstH, 702 CARD32 *pHScale, 703 CARD32 *pVScale 704) 705{ 706 int Shift; 707 708 *pHScale = ATIDivide(SrcW, DstW, 709 GetBits(pATI->NewHW.pll_vclk_cntl, PLL_ECP_DIV) + 12, 0); 710 711 Shift = 12; 712 if (pMode->Flags & V_INTERLACE) 713 Shift++; 714 715 if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0)) 716 { 717 if (pMode->VDisplay < pATI->LCDVertical) 718 { 719 SrcH *= pMode->VDisplay; 720 DstH *= pATI->LCDVertical; 721 } 722 } 723 else 724 { 725 if (pMode->Flags & V_DBLSCAN) 726 Shift--; 727 if (pMode->VScan > 1) 728 DstH *= pMode->VScan; 729 } 730 731 *pVScale = ATIDivide(SrcH, DstH, Shift, 0); 732} 733 734/* 735 * ATIMach64ClipVideo -- 736 * 737 * Clip the video (both source and destination) and make various other 738 * adjustments. 739 */ 740static Bool 741ATIMach64ClipVideo 742( 743 ScrnInfoPtr pScreenInfo, 744 ATIPtr pATI, 745 int ImageID, 746 short SrcX, 747 short SrcY, 748 short SrcW, 749 short SrcH, 750 short DstX, 751 short DstY, 752 short *DstW, 753 short *DstH, 754 short Width, 755 short Height, 756 RegionPtr pClip, 757 BoxPtr pDstBox, 758 INT32 *SrcX1, 759 INT32 *SrcX2, 760 INT32 *SrcY1, 761 INT32 *SrcY2, 762 int *SrcLeft, 763 int *SrcTop 764) 765{ 766 CARD32 HScale, VScale; 767 768 /* Check hardware limits */ 769 if ((Height <= 0) || (Height > 2048) || (Width <= 0) || (Width > 768) || 770 ((Width > 384) && (pATI->Chip < ATI_CHIP_264VTB)) || 771 ((Width > 720) && (pATI->Chip < ATI_CHIP_264GTPRO || 772 pATI->Chip > ATI_CHIP_264LTPRO))) 773 return FALSE; 774 775 ATIMach64ScaleVideo(pATI, pScreenInfo->currentMode, 776 SrcW, SrcH, *DstW, *DstH, &HScale, &VScale); 777 if (!HScale || !VScale) 778 return FALSE; 779 if (HScale > MaxScale) 780 *DstW = (*DstW * HScale) / MaxScale; 781 if (VScale > MaxScale) 782 *DstH = (*DstH * HScale) / MaxScale; 783 784 /* Clip both the source and the destination */ 785 *SrcX1 = SrcX; 786 *SrcX2 = SrcX + SrcW; 787 *SrcY1 = SrcY; 788 *SrcY2 = SrcY + SrcH; 789 790 pDstBox->x1 = DstX; 791 pDstBox->x2 = DstX + *DstW; 792 pDstBox->y1 = DstY; 793 pDstBox->y2 = DstY + *DstH; 794 795 if (!xf86XVClipVideoHelper(pDstBox, SrcX1, SrcX2, SrcY1, SrcY2, 796 pClip, Width, Height)) 797 return FALSE; 798 799 /* 800 * Reset overlay scaler origin. This prevents jittering during 801 * viewport panning or while the video is being moved or gradually 802 * obscured/unobscured. 803 */ 804 pDstBox->x1 = DstX; 805 pDstBox->y1 = DstY; 806 807 /* Translate to the current viewport */ 808 pDstBox->x1 -= pScreenInfo->frameX0; 809 pDstBox->x2 -= pScreenInfo->frameX0; 810 pDstBox->y1 -= pScreenInfo->frameY0; 811 pDstBox->y2 -= pScreenInfo->frameY0; 812 813 *SrcLeft = *SrcTop = 0; 814 815 /* 816 * If the overlay scaler origin ends up outside the current viewport, move 817 * it to the viewport's top left corner. This unavoidably causes a slight 818 * jittering in the image (even with double-buffering). 819 */ 820 if (pDstBox->x1 < 0) 821 { 822 *SrcLeft = ((-pDstBox->x1 * SrcW) / *DstW) & ~1; 823 pDstBox->x1 = 0; 824 } 825 826 if (pDstBox->y1 < 0) 827 { 828 *SrcTop = (-pDstBox->y1 * SrcH) / *DstH; 829 pDstBox->y1 = 0; 830 831 switch (ImageID) 832 { 833 case FOURCC_YV12: 834 case FOURCC_I420: 835 *SrcTop = (*SrcTop + 1) & ~1; 836 break; 837 838 default: 839 break; 840 } 841 } 842 843 return TRUE; 844} 845 846#ifdef ATIMove32 847 848/* A faster intercept */ 849#undef xf86XVCopyPacked 850#define xf86XVCopyPacked ATIMach64XVCopyPacked 851 852static void 853ATIMach64XVCopyPacked 854( 855 const CARD8 *pSrc, 856 CARD8 *pDst, 857 int SrcPitch, 858 int DstPitch, 859 int Height, 860 int Width 861) 862{ 863 Width >>= 1; 864 while (--Height >= 0) 865 { 866 ATIMove32(pDst, pSrc, Width); 867 pSrc += SrcPitch; 868 pDst += DstPitch; 869 } 870} 871 872#endif 873 874/* 875 * ATIMach64DisplayVideo -- 876 * 877 * This function programmes Mach64 registers needed to display a video. 878 */ 879static void 880ATIMach64DisplayVideo 881( 882 ScrnInfoPtr pScreenInfo, 883 ATIPtr pATI, 884 BoxPtr pDstBox, 885 int ImageID, 886 int Offset, 887 int Pitch, 888 short SrcW, 889 short SrcH, 890 short DstW, 891 short DstH, 892 short Width, 893 short Height 894) 895{ 896 DisplayModePtr pMode = pScreenInfo->currentMode; 897 CARD32 HScale, VScale; 898 899 if (pMode->VScan > 1) 900 { 901 pDstBox->y1 *= pMode->VScan; 902 pDstBox->y2 *= pMode->VScan; 903 } 904 if (pMode->Flags & V_DBLSCAN) 905 { 906 pDstBox->y1 <<= 1; 907 pDstBox->y2 <<= 1; 908 } 909 910 /* Recalculate overlay scale factors */ 911 ATIMach64ScaleVideo(pATI, pMode, SrcW, SrcH, DstW, DstH, &HScale, &VScale); 912 913 pATI->NewHW.video_format &= ~SCALER_IN; 914 if (ImageID == FOURCC_UYVY) 915 pATI->NewHW.video_format |= SCALER_IN_YVYU422; 916 else 917 pATI->NewHW.video_format |= SCALER_IN_VYUY422; 918 919 ATIMach64WaitForFIFO(pATI, 8); 920 outq(OVERLAY_Y_X_START, OVERLAY_Y_X_END, OVERLAY_LOCK_START | 921 SetWord(pDstBox->x1, 1) | SetWord(pDstBox->y1, 0), 922 SetWord(pDstBox->x2 - 1, 1) | SetWord(pDstBox->y2 - 1, 0)); 923 outf(OVERLAY_SCALE_INC, SetWord(HScale, 1) | SetWord(VScale, 0)); 924 outf(SCALER_HEIGHT_WIDTH, SetWord(Width, 1) | SetWord(Height, 0)); 925 outf(VIDEO_FORMAT, pATI->NewHW.video_format); 926 927 if (pATI->Chip < ATI_CHIP_264VTB) 928 { 929 outf(BUF0_OFFSET, Offset); 930 outf(BUF0_PITCH, Pitch); 931 } 932 else 933 { 934 outf(SCALER_BUF0_OFFSET, Offset); 935 outf(SCALER_BUF_PITCH, Pitch); 936 } 937 938 outf(OVERLAY_SCALE_CNTL, SCALE_PIX_EXPAND | OVERLAY_EN | SCALE_EN); 939} 940 941/* 942 * ATIMach64PutImage -- 943 * 944 * This function is called to put a video image on the screen. 945 */ 946static int 947ATIMach64PutImage 948( 949 ScrnInfoPtr pScreenInfo, 950 short SrcX, 951 short SrcY, 952 short DstX, 953 short DstY, 954 short SrcW, 955 short SrcH, 956 short DstW, 957 short DstH, 958 int ImageID, 959 unsigned char *Buffer, 960 short Width, 961 short Height, 962 Bool Synchronise, 963 RegionPtr pClip, 964 pointer Data, 965 DrawablePtr pDraw 966) 967{ 968 ATIPtr pATI = Data; 969 ScreenPtr pScreen; 970 INT32 SrcX1, SrcX2, SrcY1, SrcY2; 971 BoxRec DstBox; 972 int SrcPitch, SrcPitchUV, DstPitch, DstSize; 973 int SrcTop, SrcLeft, DstWidth, DstHeight; 974 int Top, Bottom, Left, Right, nLine, nPixel, Offset; 975 int OffsetV, OffsetU; 976 int XVOffset; 977 int tmp; 978 CARD8 *pDst; 979 980 if (pATI->ActiveSurface) 981 return Success; 982 983 if (DstH < 16) 984 return Success; 985 986 if (!ATIMach64ClipVideo(pScreenInfo, pATI, ImageID, 987 SrcX, SrcY, SrcW, SrcH, 988 DstX, DstY, &DstW, &DstH, 989 Width, Height, pClip, &DstBox, 990 &SrcX1, &SrcX2, &SrcY1, &SrcY2, 991 &SrcLeft, &SrcTop)) 992 return Success; 993 994 pScreen = pScreenInfo->pScreen; 995 996 DstWidth = Width - SrcLeft; 997 DstHeight = Height - SrcTop; 998 999 /* 1000 * Allocate an offscreen buffer for the entire source, even though only a 1001 * subset of the source will be copied into it. 1002 */ 1003 DstPitch = /* bytes */ 1004 (DstWidth + DstWidth + 15) & ~15; 1005 DstSize = /* bytes */ 1006 (DstPitch * DstHeight); 1007 1008 pATI->pXVBuffer = ATIMach64XVMemAlloc(pScreen, pATI->pXVBuffer, 1009 (pATI->DoubleBuffer + 1) * DstSize, &XVOffset, pATI); 1010 1011 if (!pATI->pXVBuffer) 1012 { 1013 if (!pATI->DoubleBuffer) 1014 return BadAlloc; 1015 1016 pATI->pXVBuffer = 1017 ATIMach64XVMemAlloc(pScreen, pATI->pXVBuffer, DstSize, &XVOffset, pATI); 1018 1019 if (!pATI->pXVBuffer) 1020 return BadAlloc; 1021 1022 xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, 1023 "Video image double-buffering downgraded to single-buffering\n due" 1024 " to insufficient video memory.\n"); 1025 pATI->DoubleBuffer = pATI->CurrentBuffer = 0; 1026 } 1027 else 1028 { 1029 /* Possibly switch buffers */ 1030 pATI->CurrentBuffer = pATI->DoubleBuffer - pATI->CurrentBuffer; 1031 } 1032 1033 /* Synchronise video memory accesses */ 1034 ATIMach64Sync(pScreenInfo); 1035 1036 Offset = XVOffset + pATI->CurrentBuffer * DstSize; 1037 pDst = pATI->pMemoryLE; 1038 pDst += Offset; 1039 1040 switch (ImageID) 1041 { 1042 case FOURCC_YV12: 1043 case FOURCC_I420: 1044 Left = (SrcX1 >> 16) & ~1; 1045 Right = ((SrcX2 + 0x1FFFF) >> 16) & ~1; 1046 Top = (SrcY1 >> 16) & ~1; 1047 Bottom = ((SrcY2 + 0x1FFFF) >> 16) & ~1; 1048 1049 if ((Right < Width) && ((SrcX1 & 0x1FFFF) <= (SrcX2 & 0x1FFFF))) 1050 Right += 2; 1051 if ((Bottom < Height) && ((SrcY1 & 0x1FFFF) <= (SrcY2 & 0x1FFFF))) 1052 Bottom += 2; 1053 1054 nPixel = Right - Left; 1055 nLine = Bottom - Top; 1056 1057 SrcPitch = (Width + 3) & ~3; 1058 OffsetV = SrcPitch * Height; 1059 SrcPitchUV = ((Width >> 1) + 3) & ~3; 1060 OffsetU = ((Height >> 1) * SrcPitchUV) + OffsetV; 1061 1062 tmp = ((Top >> 1) * SrcPitchUV) + (Left >> 1); 1063 OffsetV += tmp; 1064 OffsetU += tmp; 1065 1066 if (ImageID == FOURCC_I420) 1067 { 1068 tmp = OffsetV; 1069 OffsetV = OffsetU; 1070 OffsetU = tmp; 1071 } 1072 1073 pDst += ((Top - SrcTop) * DstPitch) + ((Left - SrcLeft) << 1); 1074 1075 xf86XVCopyYUV12ToPacked(Buffer + (Top * SrcPitch) + Left, 1076 Buffer + OffsetV, Buffer + OffsetU, pDst, SrcPitch, SrcPitchUV, 1077 DstPitch, nLine, nPixel); 1078 break; 1079 1080 case FOURCC_UYVY: 1081 case FOURCC_YUY2: 1082 default: 1083 Left = (SrcX1 >> 16) & ~1; 1084 Right = ((SrcX2 + 0x1FFFF) >> 16) & ~1; 1085 Top = SrcY1 >> 16; 1086 Bottom = (SrcY2 + 0x0FFFF) >> 16; 1087 1088 if ((Right < Width) && ((SrcX1 & 0x1FFFF) <= (SrcX2 & 0x1FFFF))) 1089 Right += 2; 1090 if ((Bottom < Height) && ((SrcY1 & 0x0FFFF) <= (SrcY2 & 0x0FFFF))) 1091 Bottom++; 1092 1093 nPixel = Right - Left; 1094 nLine = Bottom - Top; 1095 1096 SrcPitch = Width << 1; 1097 Buffer += (Top * SrcPitch) + (Left << 1); 1098 pDst += ((Top - SrcTop) * DstPitch) + ((Left - SrcLeft) << 1); 1099 1100 xf86XVCopyPacked(Buffer, pDst, SrcPitch, DstPitch, nLine, nPixel); 1101 break; 1102 } 1103 1104 if (!REGION_EQUAL(pScreen, &pATI->VideoClip, pClip)) 1105 { 1106 REGION_COPY(pScreen, &pATI->VideoClip, pClip); 1107 if (pATI->AutoPaint) 1108 xf86XVFillKeyHelper(pScreen, pATI->NewHW.overlay_graphics_key_clr, 1109 pClip); 1110 } 1111 1112 ATIMach64DisplayVideo(pScreenInfo, pATI, &DstBox, ImageID, 1113 Offset, DstPitch / 2, SrcW, SrcH, DstW, DstH, DstWidth, DstHeight); 1114 1115 return Success; 1116} 1117 1118/* 1119 * ATIMach64AllocateSurface -- 1120 * 1121 * This function allocates an offscreen buffer (called a "surface") for use by 1122 * an external driver such as 'v4l'. 1123 */ 1124static int 1125ATIMach64AllocateSurface 1126( 1127 ScrnInfoPtr pScreenInfo, 1128 int ImageID, 1129 unsigned short Width, 1130 unsigned short Height, 1131 XF86SurfacePtr pSurface 1132) 1133{ 1134 ScreenPtr pScreen; 1135 ATIPtr pATI = ATIPTR(pScreenInfo); 1136 int XVOffset; 1137 1138 if (pATI->ActiveSurface) 1139 return BadAlloc; 1140 1141 if ((Height <= 0) || (Height > 2048) || (Width <= 0) || (Width > 768) || 1142 ((Width > 384) && (pATI->Chip < ATI_CHIP_264VTB)) || 1143 ((Width > 720) && (pATI->Chip < ATI_CHIP_264GTPRO || 1144 pATI->Chip > ATI_CHIP_264LTPRO))) 1145 return BadValue; 1146 1147 Width = (Width + 1) & ~1; 1148 pATI->SurfacePitch = ((Width << 1) + 15) & ~15; 1149 1150 pScreen = pScreenInfo->pScreen; 1151 1152 pATI->pXVBuffer = ATIMach64XVMemAlloc(pScreen, pATI->pXVBuffer, 1153 Height * pATI->SurfacePitch, &XVOffset, pATI); 1154 if (!pATI->pXVBuffer) 1155 return BadAlloc; 1156 1157 pATI->SurfaceOffset = XVOffset; 1158 1159 pSurface->pScrn = pScreenInfo; 1160 pSurface->id = ImageID; 1161 pSurface->width = Width; 1162 pSurface->height = Height; 1163 pSurface->pitches = &pATI->SurfacePitch; 1164 pSurface->offsets = &pATI->SurfaceOffset; 1165 pSurface->devPrivate.ptr = pATI; 1166 1167 /* Stop the video */ 1168 outf(OVERLAY_SCALE_CNTL, SCALE_EN); 1169 REGION_EMPTY(pScreen, &pATI->VideoClip); 1170 pATI->ActiveSurface = TRUE; 1171 1172 return Success; 1173} 1174 1175/* 1176 * ATIMach64FreeSurface -- 1177 * 1178 * This function called to free a surface's offscreen buffer. 1179 */ 1180static int 1181ATIMach64FreeSurface 1182( 1183 XF86SurfacePtr pSurface 1184) 1185{ 1186 ATIPtr pATI = pSurface->devPrivate.ptr; 1187 1188 if (!pATI->ActiveSurface) 1189 return Success; 1190 1191 outf(OVERLAY_SCALE_CNTL, SCALE_EN); 1192 ATIMach64XVMemFree(pSurface->pScrn->pScreen, pATI->pXVBuffer, pATI); 1193 pATI->pXVBuffer = NULL; 1194 pATI->ActiveSurface = FALSE; 1195 1196 return Success; 1197} 1198 1199/* 1200 * ATIMach64DisplaySurface -- 1201 * 1202 * This function is called to display a video surface. 1203 */ 1204static int 1205ATIMach64DisplaySurface 1206( 1207 XF86SurfacePtr pSurface, 1208 short SrcX, 1209 short SrcY, 1210 short DstX, 1211 short DstY, 1212 short SrcW, 1213 short SrcH, 1214 short DstW, 1215 short DstH, 1216 RegionPtr pClip 1217) 1218{ 1219 ATIPtr pATI = pSurface->devPrivate.ptr; 1220 ScrnInfoPtr pScreenInfo; 1221 int ImageID; 1222 short Width, Height; 1223 BoxRec DstBox; 1224 INT32 SrcX1, SrcX2, SrcY1, SrcY2; 1225 int SrcLeft, SrcTop, SrcPitch, Offset; 1226 1227 if (!pATI->ActiveSurface) 1228 return Success; 1229 1230 pScreenInfo = pSurface->pScrn; 1231 ImageID = pSurface->id; 1232 Width = pSurface->width; 1233 Height = pSurface->height; 1234 1235 if (!ATIMach64ClipVideo(pScreenInfo, pATI, ImageID, 1236 SrcX, SrcY, SrcW, SrcH, 1237 DstX, DstY, &DstW, &DstH, 1238 Width, Height, pClip, &DstBox, 1239 &SrcX1, &SrcX2, &SrcY1, &SrcY2, 1240 &SrcLeft, &SrcTop)) 1241 return Success; 1242 1243 xf86XVFillKeyHelper(pScreenInfo->pScreen, 1244 pATI->NewHW.overlay_graphics_key_clr, pClip); 1245 1246 SrcPitch = pSurface->pitches[0]; 1247 Offset = pSurface->offsets[0] + (SrcTop * SrcPitch) + (SrcLeft << 1); 1248 ATIMach64DisplayVideo(pScreenInfo, pATI, &DstBox, ImageID, 1249 Offset, SrcPitch, SrcW, SrcH, DstW, DstH, Width, Height); 1250 1251 return Success; 1252} 1253 1254/* 1255 * ATIMach64StopSurface -- 1256 * 1257 * This function is called to stop the overlaid display of a video surface. 1258 */ 1259static int 1260ATIMach64StopSurface 1261( 1262 XF86SurfacePtr pSurface 1263) 1264{ 1265 ATIPtr pATI = pSurface->devPrivate.ptr; 1266 1267 if (pATI->ActiveSurface) 1268 outf(OVERLAY_SCALE_CNTL, SCALE_EN); 1269 1270 return Success; 1271} 1272 1273/* 1274 * ATIMach64GetSurfaceAttribute -- 1275 * 1276 * Retrieve the value of an XVideo attribute. 1277 */ 1278static int 1279ATIMach64GetSurfaceAttribute 1280( 1281 ScrnInfoPtr pScreenInfo, 1282 Atom AttributeID, 1283 INT32 *Value 1284) 1285{ 1286 return ATIMach64GetPortAttribute(pScreenInfo, AttributeID, Value, 1287 ATIPTR(pScreenInfo)); 1288} 1289 1290/* 1291 * ATIMach64SetSurfaceAttribute 1292 * 1293 * Set the value of an XVideo attribute. 1294 */ 1295static int 1296ATIMach64SetSurfaceAttribute 1297( 1298 ScrnInfoPtr pScreenInfo, 1299 Atom AttributeID, 1300 INT32 Value 1301) 1302{ 1303 return ATIMach64SetPortAttribute(pScreenInfo, AttributeID, Value, 1304 ATIPTR(pScreenInfo)); 1305} 1306 1307/* XVideo surface registration data */ 1308static XF86OffscreenImageRec ATIMach64Surface[] = 1309{ 1310 { 1311 &ATIMach64Image[0], /* YUY2 */ 1312 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 1313 ATIMach64AllocateSurface, 1314 ATIMach64FreeSurface, 1315 ATIMach64DisplaySurface, 1316 ATIMach64StopSurface, 1317 ATIMach64GetSurfaceAttribute, 1318 ATIMach64SetSurfaceAttribute, 1319 720, 2048, 1320 nATIMach64Attribute - 1, /* No double-buffering */ 1321 ATIMach64Attribute 1322 }, 1323 { 1324 &ATIMach64Image[1], /* UYVY */ 1325 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, 1326 ATIMach64AllocateSurface, 1327 ATIMach64FreeSurface, 1328 ATIMach64DisplaySurface, 1329 ATIMach64StopSurface, 1330 ATIMach64GetSurfaceAttribute, 1331 ATIMach64SetSurfaceAttribute, 1332 720, 2048, 1333 nATIMach64Attribute - 1, /* No double-buffering */ 1334 ATIMach64Attribute 1335 } 1336}; 1337#define nATIMach64Surface NumberOf(ATIMach64Surface) 1338 1339/* 1340 * ATIMach64XVInitialiseAdaptor -- 1341 * 1342 * This function is called to make a Mach64's hardware overlay support 1343 * available as an XVideo adaptor. 1344 */ 1345static int 1346ATIMach64XVInitialiseAdaptor 1347( 1348 ScrnInfoPtr pScreenInfo, 1349 XF86VideoAdaptorPtr **pppAdaptor 1350) 1351{ 1352 ScreenPtr pScreen = xf86ScrnToScreen(pScreenInfo); 1353 ATIPtr pATI = ATIPTR(pScreenInfo); 1354 XF86VideoAdaptorPtr *ppAdaptor = NULL; 1355 XF86VideoAdaptorPtr pAdaptor; 1356 int Index; 1357 1358 XF86VideoEncodingPtr enc = &(ATIMach64VideoEncoding[0]); 1359 XF86OffscreenImagePtr surf0 = &(ATIMach64Surface[0]); 1360 XF86OffscreenImagePtr surf1 = &(ATIMach64Surface[1]); 1361 1362 if (xf86NameCmp(pScreenInfo->driverName, MACH64_DRIVER_NAME) != 0) 1363 return 0; 1364 1365 if (pppAdaptor) 1366 *pppAdaptor = NULL; 1367 1368 if (!pATI->Block1Base) 1369 return 0; 1370 1371 if (!(pAdaptor = xf86XVAllocateVideoAdaptorRec(pScreenInfo))) 1372 return 0; 1373 1374 ppAdaptor = xnfalloc(sizeof(pAdaptor)); 1375 ppAdaptor[0] = pAdaptor; 1376 1377 pAdaptor->nPorts = 1; 1378 pAdaptor->pPortPrivates = pATI->XVPortPrivate; 1379 pATI->XVPortPrivate[0].ptr = pATI; 1380 1381 pAdaptor->type = XvInputMask | XvImageMask | XvWindowMask; 1382 pAdaptor->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 1383 pAdaptor->name = "ATI Mach64 Back-end Overlay Scaler"; 1384 1385 if (pATI->Chip < ATI_CHIP_264VTB) 1386 { 1387 enc->width = 384; 1388 } 1389 else if (pATI->Chip < ATI_CHIP_264GTPRO || 1390 pATI->Chip > ATI_CHIP_264LTPRO) 1391 { 1392 enc->width = 720; /* default */ 1393 } 1394 else 1395 { 1396 enc->width = 768; 1397 } 1398 pAdaptor->nEncodings = nATIMach64VideoEncoding; 1399 pAdaptor->pEncodings = ATIMach64VideoEncoding; 1400 1401 pAdaptor->nFormats = nATIMach64VideoFormat; 1402 pAdaptor->pFormats = ATIMach64VideoFormat; 1403 1404 pAdaptor->nAttributes = nATIMach64Attribute; 1405 pAdaptor->pAttributes = ATIMach64Attribute; 1406 1407 if (pATI->Chip < ATI_CHIP_264GTPRO) 1408 { 1409 /* Older controllers don't have brightness or saturation controls */ 1410 pAdaptor->nAttributes -= 4; 1411 pAdaptor->pAttributes += 4; 1412 } 1413 1414 pAdaptor->nImages = nATIMach64Image; 1415 pAdaptor->pImages = ATIMach64Image; 1416 1417 pAdaptor->StopVideo = ATIMach64StopVideo; 1418 pAdaptor->SetPortAttribute = ATIMach64SetPortAttribute; 1419 pAdaptor->GetPortAttribute = ATIMach64GetPortAttribute; 1420 pAdaptor->QueryBestSize = ATIMach64QueryBestSize; 1421 pAdaptor->PutImage = ATIMach64PutImage; 1422 pAdaptor->QueryImageAttributes = ATIMach64QueryImageAttributes; 1423 1424 REGION_NULL(pScreen, &pATI->VideoClip); 1425 pATI->ActiveSurface = FALSE; 1426 1427 if (ATIMach64XVAtomGeneration != serverGeneration) 1428 { 1429 /* Refresh static data */ 1430 ATIMach64XVAtomGeneration = serverGeneration; 1431 1432 Index = nATIMach64Attribute - pAdaptor->nAttributes; 1433 for (; Index < nATIMach64Attribute; Index++) 1434 ATIMach64AttributeInfo[Index].AttributeID = 1435 MAKE_ATOM(ATIMach64Attribute[Index].name); 1436 } 1437 1438 ATIMach64SetDefaultAttributes(pATI, 0); 1439 1440 if (pATI->Chip < ATI_CHIP_264VTB) 1441 { 1442 surf0->max_width = 384; 1443 surf1->max_width = 384; 1444 } 1445 else if (pATI->Chip < ATI_CHIP_264GTPRO || 1446 pATI->Chip > ATI_CHIP_264LTPRO) 1447 { 1448 surf0->max_width = 720; /* default */ 1449 surf1->max_width = 720; 1450 } 1451 else 1452 { 1453 surf0->max_width = 768; 1454 surf1->max_width = 768; 1455 } 1456 1457 if (pATI->Chip < ATI_CHIP_264GTPRO) 1458 { 1459 /* No saturation nor brightness */ 1460 surf0->num_attributes -= 4; 1461 surf1->num_attributes -= 4; 1462 surf0->attributes += 4; 1463 surf1->attributes += 4; 1464 } 1465 xf86XVRegisterOffscreenImages(pScreen, ATIMach64Surface, nATIMach64Surface); 1466 1467 if (pppAdaptor) 1468 *pppAdaptor = ppAdaptor; 1469 else { 1470 free(ppAdaptor[0]); 1471 free(ppAdaptor); 1472 } 1473 1474 return 1; 1475} 1476 1477/* 1478 * ATIXVPreInit -- 1479 * 1480 * This function is called by ATIPreInit() to set up the environment required 1481 * to support the XVideo extension. 1482 */ 1483void 1484ATIXVPreInit 1485( 1486 ATIPtr pATI 1487) 1488{ 1489 (void)xf86XVRegisterGenericAdaptorDriver(ATIMach64XVInitialiseAdaptor); 1490} 1491 1492/* 1493 * ATIXVFreeAdaptorInfo -- 1494 * 1495 * Free XVideo adaptor information. 1496 */ 1497static void 1498ATIXVFreeAdaptorInfo 1499( 1500 XF86VideoAdaptorPtr *ppAdaptor, 1501 int nAdaptor 1502) 1503{ 1504 if (!ppAdaptor) 1505 return; 1506 1507 while (nAdaptor > 0) 1508 free(ppAdaptor[--nAdaptor]); 1509 1510 free(ppAdaptor); 1511} 1512 1513/* 1514 * ATIInitializeXVideo -- 1515 * 1516 * This function is called to initialise XVideo extension support on a screen. 1517 */ 1518Bool 1519ATIInitializeXVideo 1520( 1521 ScreenPtr pScreen, 1522 ScrnInfoPtr pScreenInfo, 1523 ATIPtr pATI 1524) 1525{ 1526 XF86VideoAdaptorPtr *ppAdaptor; 1527 int nAdaptor; 1528 Bool result; 1529 1530 pScreenInfo->memPhysBase = pATI->LinearBase; 1531 pScreenInfo->fbOffset = 0; 1532 1533 nAdaptor = xf86XVListGenericAdaptors(pScreenInfo, &ppAdaptor); 1534 result = xf86XVScreenInit(pScreen, ppAdaptor, nAdaptor); 1535 1536 ATIXVFreeAdaptorInfo(ppAdaptor, nAdaptor); 1537 1538 return result; 1539} 1540 1541/* 1542 * ATIMach64CloseXVideo -- 1543 * 1544 * This function is called during screen termination to clean up after 1545 * initialisation of Mach64 XVideo support. 1546 */ 1547void 1548ATICloseXVideo 1549( 1550 ScreenPtr pScreen, 1551 ScrnInfoPtr pScreenInfo, 1552 ATIPtr pATI 1553) 1554{ 1555 if (!pATI->Block1Base) 1556 return; 1557 1558 ATIMach64StopVideo(pScreenInfo, pATI, TRUE); 1559 1560 REGION_UNINIT(pScreen, &pATI->VideoClip); 1561} 1562 1563/* Functions for offscreen memory management */ 1564 1565#ifdef USE_XAA 1566static FBLinearPtr 1567ATIResizeOffscreenLinear 1568( 1569 ScreenPtr pScreen, 1570 FBLinearPtr pLinear, 1571 int Size 1572) 1573{ 1574 if (Size <= 0) 1575 { 1576 xf86FreeOffscreenLinear(pLinear); 1577 return NULL; 1578 } 1579 1580 if (pLinear) 1581 { 1582 if ((pLinear->size >= Size) || 1583 xf86ResizeOffscreenLinear(pLinear, Size)) 1584 { 1585 pLinear->MoveLinearCallback = NULL; 1586 pLinear->RemoveLinearCallback = NULL; 1587 return pLinear; 1588 } 1589 1590 xf86FreeOffscreenLinear(pLinear); 1591 } 1592 1593 pLinear = xf86AllocateOffscreenLinear(pScreen, Size, 16, NULL, NULL, NULL); 1594 1595 if (!pLinear) 1596 { 1597 int maxSize; 1598 1599 xf86QueryLargestOffscreenLinear(pScreen, &maxSize, 16, 1600 PRIORITY_EXTREME); 1601 1602 if (maxSize < Size) 1603 return NULL; 1604 1605 xf86PurgeUnlockedOffscreenAreas(pScreen); 1606 pLinear = 1607 xf86AllocateOffscreenLinear(pScreen, Size, 16, NULL, NULL, NULL); 1608 } 1609 1610 return pLinear; 1611} 1612#endif /* USE_XAA */ 1613 1614static pointer 1615ATIMach64XVMemAlloc 1616( 1617 ScreenPtr pScreen, 1618 pointer pVideo, 1619 int size, 1620 int *offset, 1621 ATIPtr pATI 1622) 1623{ 1624#ifdef USE_EXA 1625 if (pATI->useEXA) { 1626 ExaOffscreenArea *area = (ExaOffscreenArea *)pVideo; 1627 1628 if (area != NULL) { 1629 if (area->size >= size) { 1630 *offset = area->offset; 1631 return area; 1632 } 1633 1634 exaOffscreenFree(pScreen, area); 1635 } 1636 1637 area = exaOffscreenAlloc(pScreen, size, 64, TRUE, NULL, NULL); 1638 if (area != NULL) { 1639 *offset = area->offset; 1640 return area; 1641 } 1642 } 1643#endif /* USE_EXA */ 1644 1645#ifdef USE_XAA 1646 if (!pATI->useEXA) { 1647 FBLinearPtr linear = (FBLinearPtr)pVideo; 1648 int cpp = pATI->AdjustDepth; 1649 1650 /* XAA allocates in units of pixels at the screen bpp, so adjust size 1651 * appropriately. 1652 */ 1653 size = (size + cpp - 1) / cpp; 1654 1655 linear = ATIResizeOffscreenLinear(pScreen, linear, size); 1656 if (linear != NULL) { 1657 *offset = linear->offset * cpp; 1658 return linear; 1659 } 1660 } 1661#endif /* USE_XAA */ 1662 1663 *offset = 0; 1664 return NULL; 1665} 1666 1667static void 1668ATIMach64XVMemFree 1669( 1670 ScreenPtr pScreen, 1671 pointer pVideo, 1672 ATIPtr pATI 1673) 1674{ 1675#ifdef USE_EXA 1676 if (pATI->useEXA) { 1677 ExaOffscreenArea *area = (ExaOffscreenArea *)pVideo; 1678 1679 if (area != NULL) 1680 exaOffscreenFree(pScreen, area); 1681 } 1682#endif /* USE_EXA */ 1683 1684#ifdef USE_XAA 1685 if (!pATI->useEXA) { 1686 FBLinearPtr linear = (FBLinearPtr)pVideo; 1687 1688 if (linear != NULL) 1689 ATIResizeOffscreenLinear(pScreen, linear, 0); 1690 } 1691#endif /* USE_XAA */ 1692} 1693 1694