apm_video.c revision 17a48c7c
1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm_video.c,v 1.11tsi Exp $ */ 2 3#ifdef HAVE_CONFIG_H 4#include "config.h" 5#endif 6 7#if PSZ != 24 8#include "dixstruct.h" 9#include "fourcc.h" 10 11/* 12 * Ported from mga_video.c by Loïc Grenié 13 */ 14 15#ifndef OFF_DELAY 16#define OFF_DELAY 200 17#endif 18 19static XF86VideoAdaptorPtr A(SetupImageVideo)(ScreenPtr); 20 21static void A(StopVideo)(ScrnInfoPtr, pointer, Bool); 22static int A(SetPortAttribute)(ScrnInfoPtr, Atom, INT32, pointer); 23#ifndef IOP_ACCESS 24static int ApmGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); 25static void ApmQueryBestSize(ScrnInfoPtr, Bool, short, short, short, 26 short, unsigned int *, unsigned int *, 27 pointer); 28static int ApmQueryImageAttributes(ScrnInfoPtr, int, 29 unsigned short *, unsigned short *, 30 int *, int *); 31#endif 32static int A(ReputImage)(ScrnInfoPtr, short, short, RegionPtr, pointer, 33 DrawablePtr); 34static int A(PutImage)(ScrnInfoPtr, short, short, short, short, short, 35 short, short, short, int, unsigned char*, 36 short, short, Bool, RegionPtr, pointer, 37 DrawablePtr); 38 39static void A(ResetVideo)(ScrnInfoPtr); 40static void A(XvMoveCB)(FBAreaPtr, FBAreaPtr); 41static void A(XvRemoveCB)(FBAreaPtr); 42 43#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 44 45void A(InitVideo)(ScreenPtr pScreen) 46{ 47 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 48 XF86VideoAdaptorPtr *adaptors, *newAdaptors; 49 XF86VideoAdaptorPtr newAdaptor; 50 APMDECL(pScrn); 51 int num_adaptors; 52 Bool freeAdaptors = FALSE; 53 54 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 55 56 if (pApm->Chipset >= AT24) { 57 if ((newAdaptor = A(SetupImageVideo)(pScreen))) { 58 59 newAdaptors = xalloc((num_adaptors + 1) * 60 sizeof(XF86VideoAdaptorPtr*)); 61 if(newAdaptors) { 62 if(num_adaptors) 63 memcpy(newAdaptors, adaptors, num_adaptors * 64 sizeof(XF86VideoAdaptorPtr)); 65 newAdaptors[num_adaptors] = newAdaptor; 66 adaptors = newAdaptors; 67 num_adaptors++; 68 freeAdaptors = TRUE; 69 } 70 } 71 } 72 73 if(num_adaptors) 74 xf86XVScreenInit(pScreen, adaptors, num_adaptors); 75 76 if(freeAdaptors) 77 xfree(adaptors); 78} 79 80#ifndef APM_VIDEO_DEFINES 81#define APM_VIDEO_DEFINES 82 83static Atom xvBrightness, xvContrast; 84 85/* client libraries expect an encoding */ 86static XF86VideoEncodingRec DummyEncoding[1] = 87{ 88 { 89 0, 90 "XV_IMAGE", 91 1024, 1024, 92 {1, 1} 93 } 94}; 95 96#define NUM_FORMATS 24 97 98static XF86VideoFormatRec Formats[NUM_FORMATS] = 99{ 100 { 8, PseudoColor}, 101 {15, PseudoColor}, 102 {16, PseudoColor}, 103 {24, PseudoColor}, 104 {32, PseudoColor}, 105 { 8, DirectColor}, 106 {15, DirectColor}, 107 {16, DirectColor}, 108 {24, DirectColor}, 109 {32, DirectColor}, 110 { 8, TrueColor}, 111 {15, TrueColor}, 112 {16, TrueColor}, 113 {24, TrueColor}, 114 {32, TrueColor} 115}; 116 117#define NUM_ATTRIBUTES 2 118 119static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = 120{ 121 {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, 122 {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"} 123}; 124 125#define NUM_IMAGES 9 126typedef char c8; 127 128static XF86ImageRec Images[NUM_IMAGES] = 129{ 130 { 131 0x35315652, 132 XvRGB, 133 LSBFirst, 134 {'R','V','1','5', 135 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 136 16, 137 XvPacked, 138 1, 139 15, 0x001F, 0x03E0, 0x7C00, 140 0, 0, 0, 141 0, 0, 0, 142 0, 0, 0, 143 {'R','V','B',0, 144 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}, 145 XvTopToBottom 146 }, 147 { 148 0x36315652, 149 XvRGB, 150 LSBFirst, 151 {'R','V','1','6', 152 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 153 16, 154 XvPacked, 155 1, 156 16, 0x001F, 0x07E0, 0xF800, 157 0, 0, 0, 158 0, 0, 0, 159 0, 0, 0, 160 {'R','V','B',0, 161 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}, 162 XvTopToBottom 163 }, 164 { 165 0x32335652, 166 XvRGB, 167 LSBFirst, 168 {'R','V','3','2', 169 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 170 32, 171 XvPacked, 172 1, 173 24, 0x0000FF, 0x00FF00, 0xFF0000, 174 0, 0, 0, 175 0, 0, 0, 176 0, 0, 0, 177 {'R','V','B',0, 178 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}, 179 XvTopToBottom 180 }, 181 XVIMAGE_YUY2, 182 { 183 0x59595959, 184 XvYUV, 185 LSBFirst, 186 {0x00,0x00,0x00,0x00, 187 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 188 8, 189 XvPacked, 190 1, 191 0, 0, 0, 0, 192 8, 0, 0, 193 1, 1, 1, 194 1, 1, 1, 195 {'Y','Y','Y','Y', 196 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}, 197 XvTopToBottom 198 }, 199 { 200 0x32315659, 201 XvYUV, 202 LSBFirst, 203 {'Y','V','1','2', 204 0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71}, 205 12, 206 XvPlanar, 207 3, 208 0, 0, 0, 0 , 209 8, 8, 8, 210 1, 2, 2, 211 1, 2, 2, 212 {'Y','V','U', 213 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,0}, 214 XvTopToBottom 215 }, 216 { 217 0x59565955, 218 XvYUV, 219 LSBFirst, 220 {'U','Y','V','Y', 221 0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71}, 222 16, 223 XvPlanar, 224 1, 225 0, 0, 0, 0, 226 8, 8, 8, 227 1, 2, 2, 228 1, 1, 1, 229 {'U','Y','V','Y', 230 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}, 231 XvTopToBottom 232 }, 233 { 234 0x55595659, 235 XvYUV, 236 LSBFirst, 237 {'Y','V','Y','U', 238 0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71}, 239 16, 240 XvPlanar, 241 1, 242 0, 0, 0, 0, 243 8, 8, 8, 244 1, 2, 2, 245 1, 1, 1, 246 {'Y','V','Y','U', 247 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}, 248 XvTopToBottom 249 }, 250 { 251 0x59555956, 252 XvYUV, 253 LSBFirst, 254 {'V','Y','U','Y', 255 0x00,0x00,0x00,0x10,(c8)0x80,0x00,0x00,(c8)0xAA,0x00,0x38,(c8)0x9B,0x71}, 256 16, 257 XvPlanar, 258 1, 259 0, 0, 0, 0, 260 8, 8, 8, 261 1, 2, 2, 262 1, 1, 1, 263 {'V','Y','U','Y', 264 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}, 265 XvTopToBottom 266 } 267}; 268 269typedef struct { 270 Bool on; 271 unsigned char brightness; 272 unsigned char contrast; 273 unsigned short reg, val; 274 ApmPtr pApm; 275 int x1, x10, y1, drw_x, drw_y, Bpp, Bps; 276 FBAreaPtr area; 277 RegionRec clip; 278 int xnum, xden, ynum, yden; 279 CARD32 scalex, scaley; 280 CARD32 data; 281} ApmPortPrivRec, *ApmPortPrivPtr; 282#endif 283 284 285static void 286A(ResetVideo)(ScrnInfoPtr pScrn) 287{ 288 APMDECL(pScrn); 289 290 A(WaitForFifo)(pApm, 2); 291 ((ApmPortPrivPtr)pApm->adaptor->pPortPrivates[0].ptr)->on = 0; 292 ((ApmPortPrivPtr)pApm->adaptor->pPortPrivates[1].ptr)->on = 0; 293 WRXW(0x82, 0); 294 WRXW(0x92, 0); 295} 296 297 298static XF86VideoAdaptorPtr 299A(SetupImageVideo)(ScreenPtr pScreen) 300{ 301 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 302 APMDECL(pScrn); 303 XF86VideoAdaptorPtr adapt; 304 ApmPortPrivPtr pPriv; 305 306 if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + 307 2 * sizeof(ApmPortPrivRec) + 308 2 * sizeof(DevUnion)))) 309 return NULL; 310 311 adapt->type = XvWindowMask | XvInputMask | XvImageMask; 312 adapt->flags = VIDEO_OVERLAID_IMAGES; 313 adapt->name = "Alliance Pro Motion video engine"; 314 adapt->nEncodings = 1; 315 adapt->pEncodings = DummyEncoding; 316 adapt->nFormats = NUM_FORMATS; 317 adapt->pFormats = Formats; 318 adapt->nPorts = 2; 319 adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 320 pPriv = (ApmPortPrivPtr)(&adapt->pPortPrivates[2]); 321 pPriv->pApm = pApm; 322 pPriv[1].pApm = pApm; 323 pPriv->reg = 0x82; 324 pPriv[1].reg = 0x92; 325 adapt->pPortPrivates[0].ptr = (pointer)(pPriv); 326 adapt->pPortPrivates[1].ptr = (pointer)(pPriv + 1); 327 adapt->nAttributes = NUM_ATTRIBUTES; 328 adapt->pAttributes = Attributes; 329 adapt->nImages = NUM_IMAGES; 330 adapt->pImages = Images; 331 adapt->PutVideo = NULL; 332 adapt->PutStill = NULL; 333 adapt->GetVideo = NULL; 334 adapt->GetStill = NULL; 335 adapt->StopVideo = A(StopVideo); 336 adapt->SetPortAttribute = A(SetPortAttribute); 337 adapt->GetPortAttribute = ApmGetPortAttribute; 338 adapt->QueryBestSize = ApmQueryBestSize; 339 adapt->PutImage = A(PutImage); 340 adapt->ReputImage = A(ReputImage); 341 adapt->QueryImageAttributes = ApmQueryImageAttributes; 342 343 pPriv->brightness = 0; 344 pPriv->contrast = 128; 345 pPriv[1].brightness = 0; 346 pPriv[1].contrast = 128; 347 348 /* gotta uninit this someplace */ 349 REGION_NULL(pScreen, &pPriv->clip); 350 REGION_NULL(pScreen, &(pPriv + 1)->clip); 351 352 pApm->adaptor = adapt; 353 354 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 355 xvContrast = MAKE_ATOM("XV_CONTRAST"); 356 357 A(ResetVideo)(pScrn); 358 359 return adapt; 360} 361 362#ifndef IOP_ACCESS 363/* ApmClipVideo - 364 365 Takes the dst box in standard X BoxRec form (top and left 366 edges inclusive, bottom and right exclusive). The new dst 367 box is returned. The source boundaries are given (x1, y1 368 inclusive, x2, y2 exclusive) and returned are the new source 369 boundaries in 16.16 fixed point. 370 371 extents is the extents of the clip region 372*/ 373 374static void 375ApmClipVideo(BoxPtr dst, INT32 *x1, INT32 *x2, INT32 *y1, INT32 *y2, 376 BoxPtr extents, INT32 width, INT32 height, 377 CARD32 *scalex, CARD32 *scaley, INT32 mask) 378{ 379 INT32 vscale, hscale; 380 int diff; 381 382 if (dst->x2 - dst->x1 < *x2 - *x1) 383 dst->x2 = dst->x1 + *x2 - *x1; 384 385 if (dst->y2 - dst->y1 < *y2 - *y1) 386 dst->y2 = dst->y1 + *y2 - *y1; 387 388 *x1 <<= 12; *x2 <<= 16; 389 *y1 <<= 12; *y2 <<= 16; 390 391 hscale = (*x2 - *x1) / (dst->x2 - dst->x1); 392 vscale = (*y2 - *y1) / (dst->y2 - dst->y1); 393 394 diff = extents->x1 - dst->x1; 395 if(diff > 0) { 396 dst->x1 = extents->x1; 397 *x1 += diff * hscale; 398 } 399 diff = dst->x2 - extents->x2; 400 if(diff > 0) { 401 dst->x2 = extents->x2; 402 *x2 -= diff * hscale; 403 } 404 diff = extents->y1 - dst->y1; 405 if(diff > 0) { 406 dst->y1 = extents->y1; 407 *y1 += diff * vscale; 408 } 409 diff = dst->y2 - extents->y2; 410 if(diff > 0) { 411 dst->y2 = extents->y2; 412 *y2 -= diff * vscale; 413 } 414 415 if (*x2 - *x1 == 0x10000 * (dst->x2 - dst->x1)) /* Shrinking */ 416 *scalex = 0; 417 else 418 *scalex = ((*x2 - *x1) / (dst->x2 - dst->x1)) >> 4; 419 if (*y2 - *y1 == 0x10000 * (dst->y2 - dst->y1)) /* Shrinking */ 420 *scaley = 0; 421 else 422 *scaley = ((*y2 - *y1) / (dst->y2 - dst->y1)) >> 4; 423} 424#endif 425 426static void 427A(StopVideo)(ScrnInfoPtr pScrn, pointer data, Bool shutdown) 428{ 429 ApmPortPrivPtr pPriv = (ApmPortPrivPtr)data; 430 APMDECL(pScrn); 431 432 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 433 434 pPriv->on = 0; 435 A(WaitForFifo)(pApm, 1); 436 WRXB(pPriv->reg, 0); 437} 438 439static int 440A(SetPortAttribute)(ScrnInfoPtr pScrn, Atom attribute, INT32 value, 441 pointer data) 442{ 443 ApmPortPrivPtr pPriv = (ApmPortPrivPtr)data; 444 /*APMDECL(pScrn);*/ 445 446 if(attribute == xvBrightness) { 447 if((value < -128) || (value > 127)) 448 return BadValue; 449 pPriv->brightness = value; 450 /* TODO : enable */ 451 } else if(attribute == xvContrast) { 452 if((value < 0) || (value > 255)) 453 return BadValue; 454 pPriv->contrast = value; 455 /* TODO : enable */ 456 } 457 458 return Success; 459} 460 461#ifndef IOP_ACCESS 462static int 463ApmGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value, 464 pointer data) 465{ 466 ApmPortPrivPtr pPriv = (ApmPortPrivPtr)data; 467 468 if(attribute == xvBrightness) { 469 *value = pPriv->brightness; 470 } else 471 if(attribute == xvContrast) { 472 *value = pPriv->contrast; 473 } 474 475 return Success; 476} 477 478static void 479ApmQueryBestSize(ScrnInfoPtr pScrn, Bool motion, short vid_w, short vid_h, 480 short drw_w, short drw_h, 481 unsigned int *p_w, unsigned int *p_h, pointer data) 482{ 483 APMDECL(pScrn); 484 unsigned short round = ~pApm->CurrentLayout.mask32; 485 486 *p_w = drw_w & round; 487 *p_h = drw_h & round; 488} 489#endif 490 491static void A(XvMoveCB)(FBAreaPtr area1, FBAreaPtr area2) 492{ 493 ApmPortPrivPtr pPriv = (ApmPortPrivPtr)area1->devPrivate.ptr; 494 ApmPtr pApm = pPriv->pApm; 495 496 pPriv->on = 0; 497 A(WaitForFifo)(pApm, 1); 498 WRXB(pPriv->reg, 0); /* Stop video for this port */ 499 pPriv->area = area2; 500} 501 502static void A(XvRemoveCB)(FBAreaPtr area) 503{ 504 ApmPortPrivPtr pPriv = (ApmPortPrivPtr)area->devPrivate.ptr; 505 ApmPtr pApm = pPriv->pApm; 506 507 pPriv->on = 0; 508 A(WaitForFifo)(pApm, 1); 509 WRXB(pPriv->reg, 0); /* Stop video for this port */ 510 pPriv->area = NULL; 511} 512 513static int 514A(ReputImage)(ScrnInfoPtr pScrn, short drw_x, short drw_y, 515 RegionPtr clipBoxes, pointer pdata, DrawablePtr pDraw) 516{ 517 ScreenPtr pScreen = pScrn->pScreen; 518 APMDECL(pScrn); 519 ApmPortPrivPtr pPriv = pdata, pPriv0, pPriv1; 520 register int fx, fy; 521 CARD32 mask; 522 RegionRec Union; 523 RegionPtr reg0; 524 int nrects, CurrY, tile; 525 int X1, X2, Y1, y2, xmax, ymax; 526 BoxPtr rects; 527 Bool didit = 0; 528 529 mask = pApm->CurrentLayout.mask32; 530 fx = pScrn->frameX0 & ~mask; 531 fy = pScrn->frameY0 + 1; 532 REGION_COPY(pScreen, &pPriv->clip, clipBoxes); 533 pPriv->x1 += drw_x - pPriv->drw_x; 534 pPriv->x10 = ((pPriv->x1 + mask) & ~mask) - fx; 535 pPriv->y1 += drw_y - pPriv->drw_y; 536 pPriv->drw_x = drw_x; 537 pPriv->drw_y = drw_y; 538 A(WaitForFifo)(pApm, 2); 539 WRXW(pPriv->reg + 0x06, 0xFFF - ((pPriv->scalex * pPriv->x10) & 0xFFF)); 540 WRXW(pPriv->reg + 0x0A, 0xFFF - ((pPriv->scaley * pPriv->y1) & 0xFFF)); 541 pPriv0 = (ApmPortPrivPtr)pApm->adaptor->pPortPrivates[0].ptr; 542 pPriv1 = (ApmPortPrivPtr)pApm->adaptor->pPortPrivates[1].ptr; 543 reg0 = &pPriv0->clip; 544 bzero(&Union, sizeof Union); 545 REGION_EMPTY(pScreen, &Union); 546 REGION_NULL(pScreen, &Union); 547 REGION_UNION(pScreen, &Union, reg0, &pPriv1->clip); 548 nrects = REGION_NUM_RECTS(&Union); 549 rects = REGION_RECTS(&Union); 550 tile = 0x200; 551 xmax = pScrn->frameX1 - pScrn->frameX0 + 1; 552 ymax = pScrn->frameY1 - pScrn->frameY0; 553 CurrY = -1; 554 goto BEGIN_LOOP_1; 555 do { 556 rects++; 557BEGIN_LOOP_1: 558 X1 = ((rects->x1 + mask) & ~mask) - fx; 559 if (X1 < 0) 560 X1 = 0; 561 X2 = (rects->x2 & ~mask) - fx; 562 if (X2 > xmax) 563 X2 = xmax; 564 y2 = rects->y2 - fy; 565 } while ((X2 <= X1 || y2 < -1) && --nrects > 0); 566 Y1 = rects->y1 - fy; 567 568 while (!(STATUS() & 0x800)); 569 while (STATUS() & 0x800); 570 while (nrects-- > 0) { 571 CARD32 reg, data; 572 int x1, x2, y1; 573 574 x1 = X1; 575 x2 = X2; 576 y1 = Y1; 577 if (y1 < -1) y1 = -1; 578 if (y1 > ymax) 579 break; 580 didit = 1; 581 if (y1 > CurrY) { 582 A(WaitForFifo)(pApm, 3); 583 WRXL(tile + 0x00, 0xFFF0011); 584 WRXL(tile + 0x04, y1 << 16); 585 WRXL(tile + 0x08, 0); 586 tile += 16; 587 } 588 if (RECT_IN_REGION(pScreen, reg0, rects)) { 589 pPriv = pPriv0; 590 reg = (x1 << 16) | 1; 591 } 592 else { 593 pPriv = pPriv1; 594 reg = (x1 << 16) | 2; 595 } 596 CurrY = y2; 597 if (nrects <= 0) 598 goto BEGIN_LOOP_2; 599 do { 600 rects++; 601BEGIN_LOOP_2: 602 X1 = ((rects->x1 + mask) & ~mask) - fx; 603 if (X1 < 0) 604 X1 = 0; 605 X2 = (rects->x2 & ~mask) - fx; 606 if (X2 > xmax) 607 X2 = xmax; 608 } while (X2 <= X1 && --nrects > 0); 609 Y1 = rects->y1 - fy; 610 y2 = rects->y2 - fy; 611 data = pPriv->data + (((x1 - pPriv->x10) 612 * pPriv->xden) / pPriv->xnum) * pPriv->Bpp + 613 (((y1 - pPriv->y1 + fy) * pPriv->yden) / pPriv->ynum) * pPriv->Bps; 614 A(WaitForFifo)(pApm, 4); 615 if (!nrects || tile == 0x2B0 || y1 < Y1) { 616 WRXL(tile , 0x10 | reg); 617 } 618 else { 619 WRXL(tile , reg); 620 } 621 WRXL(tile + 0x04, x2 | (CurrY << 16)); 622 WRXL(tile + 0x08, (((x2-x1)*pPriv->xden+pPriv->xnum-1) / pPriv->xnum) | 623 (data << 16)); 624 WRXB(tile + 0x0C, data >> 16); 625 tile += 16; 626 if (tile == 0x2C0) { 627 tile = 0x200; 628 break; 629 } 630 } 631 REGION_UNINIT(pScreen, &Union); 632 633 if (didit) { 634 A(WaitForFifo)(pApm, 1); 635 WRXW(0x8E, tile - 0x200); 636 } 637 638 if (didit ^ ((pPriv0->val | pPriv1->val) & 1)) { 639 if (didit) { 640 pPriv0->val |= 1; 641 pPriv1->val |= 1; 642 } 643 else { 644 pPriv0->val &= 0xFFFE; 645 pPriv1->val &= 0xFFFE; 646 } 647 if (pPriv0->on) { 648 A(WaitForFifo)(pApm, 1); 649 WRXW(0x82, pPriv0->val); 650 } 651 if (pPriv1->on) { 652 A(WaitForFifo)(pApm, 1); 653 WRXW(0x92, pPriv1->val); 654 } 655 } 656 657 return Success; 658} 659 660static int 661A(PutImage)(ScrnInfoPtr pScrn, short src_x, short src_y, 662 short drw_x, short drw_y, short src_w, short src_h, 663 short drw_w, short drw_h, int id, unsigned char* buf, 664 short width, short height, Bool sync, RegionPtr clipBoxes, 665 pointer data, DrawablePtr pDraw) 666{ 667 ApmPortPrivPtr pPriv = (ApmPortPrivPtr)data; 668 ScreenPtr pScreen = pScrn->pScreen; 669 APMDECL(pScrn); 670 INT32 x1, x2, y1, y2; 671 unsigned char *dst_start; 672 int pitch, Bpp, new_h, offset = 0, offset2 = 0, offset3 = 0; 673 CARD32 mask; 674 FBAreaPtr area; 675 int srcPitch, dstPitch, srcPitch2 = 0; 676 int top, left, npixels, nlines; 677 BoxRec dstBox; 678 CARD32 scalex, scaley, scale; 679 CARD32 tmp; 680 Bool offscreen; 681 682 offscreen = (buf < (unsigned char *)pApm->FbBase || 683 buf > (unsigned char *)pApm->FbBase + 0x400000); 684 685 if(drw_w > 16384) drw_w = 16384; 686 687 /* Clip */ 688 x1 = src_x; 689 x2 = src_x + src_w; 690 y1 = src_y; 691 y2 = src_y + src_h; 692 693 dstBox.x1 = drw_x; 694 dstBox.x2 = drw_x + drw_w; 695 dstBox.y1 = drw_y; 696 dstBox.y2 = drw_y + drw_h; 697 698 mask = pApm->CurrentLayout.mask32; 699 700 ApmClipVideo(&dstBox, &x1, &x2, &y1, &y2, 701 REGION_EXTENTS(pScreen, clipBoxes), width, height, 702 &scalex, &scaley, mask); 703 704 pPriv->drw_x = drw_x; 705 pPriv->drw_y = drw_y; 706 pPriv->xnum = drw_w; 707 if (scalex) 708 pPriv->xden = src_w; 709 else 710 pPriv->xden = drw_w; /* If image is larger than window */ 711 pPriv->ynum = drw_h; 712 if (scaley) 713 pPriv->yden = src_h; 714 else 715 pPriv->yden = drw_h; 716 if((x1 - x2 >= 0xFFFF) || (y1 - y2 >= 0xFFFF)) 717 return Success; 718 719 Bpp = pScrn->bitsPerPixel >> 3; 720 pitch = Bpp * pScrn->displayWidth; 721 722 switch(id) { 723 case 0x32315659: 724 dstPitch = ((width << 1) + 3) & ~3; 725 srcPitch = (width + 3) & ~3; 726 offset2 = srcPitch * height; 727 srcPitch2 = ((width >> 1) + 3) & ~3; 728 offset = srcPitch2 * (height >> 1); 729 offset3 = offset + offset2; 730 new_h = (2 * offset2 + pitch - 1) / pitch; 731 break; 732 case 0x59595959: 733 srcPitch = width; 734 dstPitch = (srcPitch + 3) & ~3; 735 offset = dstPitch * height; 736 new_h = (offset + pitch - 1) / pitch; 737 break; 738 case 0x32335652: 739 srcPitch = (width << 2); 740 dstPitch = (srcPitch + 3) & ~3; 741 offset = dstPitch * height; 742 new_h = (offset + pitch - 1) / pitch; 743 break; 744 default: 745 if (pApm->PutImageStride) 746 srcPitch = pApm->PutImageStride; 747 else 748 srcPitch = (width << 1); 749 dstPitch = (srcPitch + 3) & ~3; 750 offset = dstPitch * height; 751 new_h = (offset + pitch - 1) / pitch; 752 break; 753 } 754 755 area = pPriv->area; 756 757 /* Allocate offscreen memory */ 758 if (offscreen && (!area || ((area->box.y2 - area->box.y1) < new_h))) { 759 Bool nukeMem = FALSE; 760 int max_w, max_h; 761 762 xf86QueryLargestOffscreenArea(pScreen, &max_w, &max_h, 0, 763 FAVOR_WIDTH_THEN_AREA, PRIORITY_LOW); 764 if (max_w == pScrn->displayWidth && max_h >= new_h) { 765 area = xf86AllocateOffscreenArea(pScreen, 766 pScrn->displayWidth, new_h, 767 4, A(XvMoveCB), A(XvRemoveCB), pPriv); 768 if (area) { 769 if (pPriv->area) 770 xf86FreeOffscreenArea(pPriv->area); 771 } 772 else 773 area = pPriv->area; /* Should not happen */ 774 } 775 if(!area) { 776 if(!(area = xf86AllocateOffscreenArea(pScreen, 777 pScrn->displayWidth, new_h, 4, 778 A(XvMoveCB), A(XvRemoveCB), pPriv))) 779 { 780 nukeMem = TRUE; 781 } 782 } else { 783 if(!xf86ResizeOffscreenArea(area, pScrn->displayWidth, new_h)) { 784 xf86FreeOffscreenArea(area); 785 pPriv->area = area = NULL; 786 nukeMem = TRUE; 787 } 788 } 789 if(nukeMem) { 790 xf86QueryLargestOffscreenArea(pScreen, &max_w, &max_h, 0, 791 FAVOR_WIDTH_THEN_AREA, PRIORITY_EXTREME); 792 793 if((max_w < pScrn->displayWidth) || (max_h < new_h)) 794 return BadAlloc; 795 796 xf86PurgeUnlockedOffscreenAreas(pScreen); 797 798 area = xf86AllocateOffscreenArea(pScreen, 799 pScrn->displayWidth, new_h, 4, 800 A(XvMoveCB), A(XvRemoveCB), pPriv); 801 } 802 803 pPriv->area = area; 804 } 805 806 /* copy data */ 807 pPriv->x1 = dstBox.x1 /*drw_x*/; 808 pPriv->y1 = dstBox.y1 /*drw_y*/; 809 top = y1 >> 16; 810 left = (x1 >> 16) & ~1; 811 npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; 812 813 switch(id) { 814 case 0x59595959: 815 pPriv->Bpp = 1; 816 break; 817 default: 818 pPriv->Bpp = 2; 819 left <<= 1; 820 break; 821 case 0x32335652: 822 pPriv->Bpp = 4; 823 left <<= 2; 824 break; 825 } 826 pPriv->Bps = pPriv->Bpp * pPriv->xden; 827 if (offscreen) { 828 offset = (area->box.y1 * pitch) + (top * dstPitch); 829 dst_start = ((unsigned char *)pApm->FbBase) + 830 (pPriv->data = offset + left); 831 switch(id) { 832 case 0x32315659: 833 top &= ~1; 834 tmp = ((top >> 1) * srcPitch2) + (left >> 2); 835 offset2 += tmp; 836 offset3 += tmp; 837 nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; 838 xf86XVCopyYUV12ToPacked(buf + (top * srcPitch) + (left >> 1), 839 buf + offset2, buf + offset3, dst_start, 840 srcPitch, srcPitch2, dstPitch, 841 nlines, npixels); 842 break; 843 default: 844 if (id == 0x32335652) 845 npixels <<= 1; 846 else if (id == 0x59595959) 847 npixels >>= 1; 848 buf += (top * srcPitch) + left; 849 nlines = ((y2 + 0xffff) >> 16) - top; 850 if (offscreen) 851 xf86XVCopyPacked(buf, dst_start, srcPitch, dstPitch, 852 nlines, npixels); 853 break; 854 } 855 } 856 else 857 pPriv->data = buf - (unsigned char *)pApm->FbBase; 858 pPriv->on = 1; 859 A(WaitForFifo)(pApm, 3); 860 WRXW(pPriv->reg + 0x02, dstPitch >> 2); 861 WRXW(pPriv->reg + 0x04, scalex); 862 WRXW(pPriv->reg + 0x08, scaley); 863 pPriv->scalex = scalex; 864 pPriv->scaley = scaley; 865 if (scalex && scaley) 866 scale = 0x0E00; 867 else if (scalex) 868 scale = 0x0600; 869 else if (scaley) 870 scale = 0x0A00; 871 else 872 scale = 0; 873 switch(id) { 874 case 0x59595959: 875 pPriv->val = 0x017B | scale; 876 break; 877 case 0x32335652: 878 pPriv->val = 0x002F | (scale & 0xF7FF);/*Smoothing filter doesn't work*/ 879 break; 880 case 0x36315652: 881 pPriv->val = 0x002B | (scale & 0xF7FF); 882 break; 883 case 0x35315652: 884 pPriv->val = 0x0029 | (scale & 0xF7FF); 885 break; 886 case 0x59555956: 887 pPriv->val = 0x013B | scale; 888 break; 889 case 0x55595659: 890 pPriv->val = 0x014B | scale; 891 break; 892 case 0x32315659: 893 case 0x59565955: 894 default: 895 pPriv->val = 0x016B | scale; 896 break; 897 } 898 899 (void) A(ReputImage)(pScrn, drw_x, drw_y, clipBoxes, data, pDraw); 900 901 A(WaitForFifo)(pApm, 1); 902 WRXW(pPriv->reg, pPriv->val); 903 904 return Success; 905} 906 907#ifndef IOP_ACCESS 908static int 909ApmQueryImageAttributes(ScrnInfoPtr pScrn, int id, 910 unsigned short *w, unsigned short *h, 911 int *pitches, int *offsets) 912{ 913 int size, tmp; 914 915 if(*w > 1024) *w = 1024; 916 if(*h > 1024) *h = 1024; 917 918 *w = (*w + 1) & ~1; 919 if(offsets) offsets[0] = 0; 920 921 switch(id) { 922 case 0x32315659: 923 *h = (*h + 1) & ~1; 924 size = (*w + 3) & ~3; 925 if(pitches) pitches[0] = size; 926 size *= *h; 927 if(offsets) offsets[1] = size; 928 tmp = ((*w >> 1) + 3) & ~3; 929 if(pitches) pitches[1] = pitches[2] = tmp; 930 tmp *= (*h >> 1); 931 size += tmp; 932 if(offsets) offsets[2] = size; 933 size += tmp; 934 break; 935 case 0x59565955: 936 case 0x55595659: 937 case 0x59555956: 938 case 0x32595559: 939 size = *w << 1; 940 goto common; 941 case 0x59595959: 942 default: 943 size = *w; 944common: 945 if (pitches) 946 pitches[0] = size; 947 size *= *h; 948 break; 949 } 950 951 return size; 952} 953#endif 954#endif 955