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