1 2#ifdef HAVE_CONFIG_H 3#include "config.h" 4#endif 5 6#include "xf86.h" 7#include "xf86_OSproc.h" 8#include "compiler.h" 9#include "xf86Pci.h" 10#include "xf86fbman.h" 11#include "regionstr.h" 12 13#include "ct_driver.h" 14#include <X11/extensions/Xv.h> 15#include "dixstruct.h" 16#include "fourcc.h" 17 18#define OFF_DELAY 200 /* milliseconds */ 19#define FREE_DELAY 60000 20 21#define OFF_TIMER 0x01 22#define FREE_TIMER 0x02 23#define CLIENT_VIDEO_ON 0x04 24 25#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 26 27static XF86VideoAdaptorPtr CHIPSSetupImageVideo(ScreenPtr); 28static void CHIPSInitOffscreenImages(ScreenPtr); 29static void CHIPSStopVideo(ScrnInfoPtr, pointer, Bool); 30static int CHIPSSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 31static int CHIPSGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); 32static void CHIPSQueryBestSize(ScrnInfoPtr, Bool, 33 short, short, short, short, unsigned int *, unsigned int *, pointer); 34static int CHIPSPutImage( ScrnInfoPtr, 35 short, short, short, short, short, short, short, short, 36 int, unsigned char*, short, short, Bool, RegionPtr, pointer, 37 DrawablePtr); 38static int CHIPSQueryImageAttributes(ScrnInfoPtr, 39 int, unsigned short *, unsigned short *, int *, int *); 40static void CHIPSVideoTimerCallback(ScrnInfoPtr pScrn, Time time); 41 42 43#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 44 45static Atom xvColorKey; 46 47void 48CHIPSInitVideo(ScreenPtr pScreen) 49{ 50 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 51 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 52 XF86VideoAdaptorPtr newAdaptor = NULL; 53 CHIPSPtr cPtr = CHIPSPTR(pScrn); 54 int num_adaptors; 55 56 if ((cPtr->Flags & ChipsVideoSupport)) { 57 newAdaptor = CHIPSSetupImageVideo(pScreen); 58 CHIPSInitOffscreenImages(pScreen); 59 } 60 61 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 62 63 if(newAdaptor) { 64 if(!num_adaptors) { 65 num_adaptors = 1; 66 adaptors = &newAdaptor; 67 } else { 68 newAdaptors = /* need to free this someplace */ 69 malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); 70 if(newAdaptors) { 71 memcpy(newAdaptors, adaptors, num_adaptors * 72 sizeof(XF86VideoAdaptorPtr)); 73 newAdaptors[num_adaptors] = newAdaptor; 74 adaptors = newAdaptors; 75 num_adaptors++; 76 } 77 } 78 } 79 80 if(num_adaptors) 81 xf86XVScreenInit(pScreen, adaptors, num_adaptors); 82 83 free(newAdaptors); 84} 85 86/* client libraries expect an encoding */ 87static 88XF86VideoEncodingRec DummyEncoding[1] = 89{ 90 { 91 0, 92 "XV_IMAGE", 93 1024, 1024, 94 {1, 1} 95 } 96}; 97 98#define NUM_FORMATS 4 99 100static XF86VideoFormatRec Formats[NUM_FORMATS] = 101{ 102 {8, PseudoColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 103}; 104 105#define NUM_ATTRIBUTES 1 106 107static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = 108{ 109 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"} 110}; 111 112#define NUM_IMAGES 4 113 114static XF86ImageRec Images[NUM_IMAGES] = 115{ 116 { 117 0x35315652, 118 XvRGB, 119 LSBFirst, 120 {'R','V','1','5', 121 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 122 16, 123 XvPacked, 124 1, 125 15, 0x7C00, 0x03E0, 0x001F, 126 0, 0, 0, 127 0, 0, 0, 128 0, 0, 0, 129 {'R','V','B',0, 130 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}, 131 XvTopToBottom 132 }, 133 { 134 0x36315652, 135 XvRGB, 136 LSBFirst, 137 {'R','V','1','6', 138 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 139 16, 140 XvPacked, 141 1, 142 16, 0xF800, 0x07E0, 0x001F, 143 0, 0, 0, 144 0, 0, 0, 145 0, 0, 0, 146 {'R','V','B',0, 147 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}, 148 XvTopToBottom 149 }, 150 XVIMAGE_YV12, 151 XVIMAGE_YUY2 152}; 153 154typedef struct { 155 FBLinearPtr linear; 156 RegionRec clip; 157 CARD32 colorKey; 158 CARD32 videoStatus; 159 Time offTime; 160 Time freeTime; 161 Bool doubleBuffer; 162 Bool manualDoubleBuffer; 163 int currentBuffer; 164} CHIPSPortPrivRec, *CHIPSPortPrivPtr; 165 166 167#define GET_PORT_PRIVATE(pScrn) \ 168 (CHIPSPortPrivPtr)((CHIPSPTR(pScrn))->adaptor->pPortPrivates[0].ptr) 169 170void 171CHIPSResetVideo(ScrnInfoPtr pScrn) 172{ 173 CHIPSPtr cPtr = CHIPSPTR(pScrn); 174 CHIPSPortPrivPtr pPriv = cPtr->adaptor->pPortPrivates[0].ptr; 175 unsigned char mr3c; 176 int red, green, blue; 177 178#ifdef HAVE_XAA_H 179 if (cPtr->Flags & ChipsAccelSupport) 180 CHIPSHiQVSync(pScrn); 181#endif 182 183 mr3c = cPtr->readMR(cPtr, 0x3C); 184 cPtr->writeMR(cPtr, 0x3C, (mr3c | 0x6)); 185 switch (pScrn->depth) { 186 case 8: 187 cPtr->writeMR(cPtr, 0x3D, 0x00); 188 cPtr->writeMR(cPtr, 0x3E, 0x00); 189 cPtr->writeMR(cPtr, 0x3F, (pPriv->colorKey & 0xFF)); 190 cPtr->writeMR(cPtr, 0x40, 0xFF); 191 cPtr->writeMR(cPtr, 0x41, 0xFF); 192 cPtr->writeMR(cPtr, 0x42, 0x00); 193 break; 194 default: 195 red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; 196 green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; 197 blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; 198 switch (pScrn->depth) { 199 case 15: 200 cPtr->writeMR(cPtr, 0x3D, (red << 3)); 201 cPtr->writeMR(cPtr, 0x3E, (green << 3)); 202 cPtr->writeMR(cPtr, 0x3F, (blue << 3)); 203 cPtr->writeMR(cPtr, 0x40, 0x07); 204 cPtr->writeMR(cPtr, 0x41, 0x07); 205 cPtr->writeMR(cPtr, 0x42, 0x07); 206 break; 207 case 16: 208 cPtr->writeMR(cPtr, 0x3D, (red << 3)); 209 cPtr->writeMR(cPtr, 0x3E, (green << 2)); 210 cPtr->writeMR(cPtr, 0x3F, (blue << 3)); 211 cPtr->writeMR(cPtr, 0x40, 0x07); 212 cPtr->writeMR(cPtr, 0x41, 0x03); 213 cPtr->writeMR(cPtr, 0x42, 0x07); 214 break; 215 case 24: 216 cPtr->writeMR(cPtr, 0x3D, red); 217 cPtr->writeMR(cPtr, 0x3E, green); 218 cPtr->writeMR(cPtr, 0x3F, blue); 219 cPtr->writeMR(cPtr, 0x40, 0x00); 220 cPtr->writeMR(cPtr, 0x41, 0x00); 221 cPtr->writeMR(cPtr, 0x42, 0x00); 222 break; 223 } 224 } 225} 226 227 228static XF86VideoAdaptorPtr 229CHIPSSetupImageVideo(ScreenPtr pScreen) 230{ 231 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 232 CHIPSPtr cPtr = CHIPSPTR(pScrn); 233 XF86VideoAdaptorPtr adapt; 234 CHIPSPortPrivPtr pPriv; 235 236 if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 237 sizeof(CHIPSPortPrivRec) + 238 sizeof(DevUnion)))) 239 return NULL; 240 241 adapt->type = XvWindowMask | XvInputMask | XvImageMask; 242 adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 243 adapt->name = "Chips and Technologies Backend Scaler"; 244 adapt->nEncodings = 1; 245 adapt->pEncodings = DummyEncoding; 246 adapt->nFormats = NUM_FORMATS; 247 adapt->pFormats = Formats; 248 adapt->nPorts = 1; 249 adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 250 pPriv = (CHIPSPortPrivPtr)(&adapt->pPortPrivates[1]); 251 adapt->pPortPrivates[0].ptr = (pointer)(pPriv); 252 adapt->pAttributes = Attributes; 253 adapt->nImages = NUM_IMAGES; 254 adapt->nAttributes = NUM_ATTRIBUTES; 255 adapt->pImages = Images; 256 adapt->PutVideo = NULL; 257 adapt->PutStill = NULL; 258 adapt->GetVideo = NULL; 259 adapt->GetStill = NULL; 260 adapt->StopVideo = CHIPSStopVideo; 261 adapt->SetPortAttribute = CHIPSSetPortAttribute; 262 adapt->GetPortAttribute = CHIPSGetPortAttribute; 263 adapt->QueryBestSize = CHIPSQueryBestSize; 264 adapt->PutImage = CHIPSPutImage; 265 adapt->QueryImageAttributes = CHIPSQueryImageAttributes; 266 267 pPriv->colorKey = cPtr->videoKey; 268 pPriv->videoStatus = 0; 269 pPriv->manualDoubleBuffer = FALSE; 270 pPriv->currentBuffer = 0; 271 272 /* gotta uninit this someplace */ 273 REGION_NULL(pScreen, &pPriv->clip); 274 275 cPtr->adaptor = adapt; 276 277 xvColorKey = MAKE_ATOM("XV_COLORKEY"); 278 279 CHIPSResetVideo(pScrn); 280 281 return adapt; 282} 283 284 285static void 286CHIPSStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shadow) 287{ 288 CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data; 289 CHIPSPtr cPtr = CHIPSPTR(pScrn); 290 unsigned char mr3c, tmp; 291 292 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 293#ifdef HAVE_XAA_H 294 if (cPtr->Flags & ChipsAccelSupport) 295 CHIPSHiQVSync(pScrn); 296#endif 297 if(shadow) { 298 if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 299 mr3c = cPtr->readMR(cPtr, 0x3C); 300 cPtr->writeMR(cPtr, 0x3C, (mr3c & 0xFE)); 301 tmp = cPtr->readXR(cPtr, 0xD0); 302 cPtr->writeXR(cPtr, 0xD0, (tmp & 0xf)); 303 } 304 if(pPriv->linear) { 305 xf86FreeOffscreenLinear(pPriv->linear); 306 pPriv->linear = NULL; 307 } 308 pPriv->videoStatus = 0; 309 } else { 310 if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 311 pPriv->videoStatus |= OFF_TIMER; 312 pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 313 cPtr->VideoTimerCallback = CHIPSVideoTimerCallback; 314 } 315 } 316} 317 318static int 319CHIPSSetPortAttribute( 320 ScrnInfoPtr pScrn, 321 Atom attribute, 322 INT32 value, 323 pointer data 324){ 325 CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data; 326 CHIPSPtr cPtr = CHIPSPTR(pScrn); 327 328#ifdef HAVE_XAA_H 329 if (cPtr->Flags & ChipsAccelSupport) 330 CHIPSHiQVSync(pScrn); 331#endif 332 if(attribute == xvColorKey) { 333 int red, green, blue; 334 pPriv->colorKey = value; 335 switch (pScrn->depth) { 336 case 8: 337 cPtr->writeMR(cPtr, 0x3D, 0x00); 338 cPtr->writeMR(cPtr, 0x3E, 0x00); 339 cPtr->writeMR(cPtr, 0x3F, (pPriv->colorKey & 0xFF)); 340 break; 341 default: 342 red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; 343 green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; 344 blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; 345 switch (pScrn->depth) { 346 case 15: 347 cPtr->writeMR(cPtr, 0x3D, (red << 3)); 348 cPtr->writeMR(cPtr, 0x3E, (green << 3)); 349 cPtr->writeMR(cPtr, 0x3F, (blue << 3)); 350 break; 351 case 16: 352 cPtr->writeMR(cPtr, 0x3D, (red << 3)); 353 cPtr->writeMR(cPtr, 0x3E, (green << 2)); 354 cPtr->writeMR(cPtr, 0x3F, (blue << 3)); 355 break; 356 case 24: 357 cPtr->writeMR(cPtr, 0x3D, red); 358 cPtr->writeMR(cPtr, 0x3E, green); 359 cPtr->writeMR(cPtr, 0x3F, blue); 360 break; 361 } 362 } 363 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 364 } else return BadMatch; 365 366 return Success; 367} 368 369static int 370CHIPSGetPortAttribute( 371 ScrnInfoPtr pScrn, 372 Atom attribute, 373 INT32 *value, 374 pointer data 375){ 376 CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data; 377 378 if(attribute == xvColorKey) { 379 *value = pPriv->colorKey; 380 } else return BadMatch; 381 382 return Success; 383} 384 385static void 386CHIPSQueryBestSize( 387 ScrnInfoPtr pScrn, 388 Bool motion, 389 short vid_w, short vid_h, 390 short drw_w, short drw_h, 391 unsigned int *p_w, unsigned int *p_h, 392 pointer data 393){ 394 *p_w = drw_w; 395 *p_h = drw_h; 396 397 if(*p_w > 16384) *p_w = 16384; 398} 399 400 401static void 402CHIPSCopyData( 403 unsigned char *src, 404 unsigned char *dst, 405 int srcPitch, 406 int dstPitch, 407 int h, 408 int w 409){ 410 w <<= 1; 411 while(h--) { 412 memcpy(dst, src, w); 413 src += srcPitch; 414 dst += dstPitch; 415 } 416} 417 418static void 419CHIPSCopyMungedData( 420 unsigned char *src1, 421 unsigned char *src2, 422 unsigned char *src3, 423 unsigned char *dst1, 424 int srcPitch, 425 int srcPitch2, 426 int dstPitch, 427 int h, 428 int w 429){ 430 CARD32 *dst = (CARD32*)dst1; 431 int i, j; 432 433 dstPitch >>= 2; 434 w >>= 1; 435 436 for(j = 0; j < h; j++) { 437 for(i = 0; i < w; i++) { 438 dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) | 439 (src3[i] << 8) | (src2[i] << 24); 440 } 441 dst += dstPitch; 442 src1 += srcPitch; 443 if(j & 1) { 444 src2 += srcPitch2; 445 src3 += srcPitch2; 446 } 447 } 448} 449 450static FBLinearPtr 451CHIPSAllocateMemory( 452 ScrnInfoPtr pScrn, 453 FBLinearPtr linear, 454 int size 455){ 456 ScreenPtr pScreen; 457 FBLinearPtr new_linear; 458 459 if(linear) { 460 if(linear->size >= size) 461 return linear; 462 463 if(xf86ResizeOffscreenLinear(linear, size)) 464 return linear; 465 466 xf86FreeOffscreenLinear(linear); 467 } 468 469 pScreen = xf86ScrnToScreen(pScrn); 470 471 new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, 472 NULL, NULL, NULL); 473 474 if(!new_linear) { 475 int max_size; 476 477 xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8, 478 PRIORITY_EXTREME); 479 480 if(max_size < size) 481 return NULL; 482 483 xf86PurgeUnlockedOffscreenAreas(pScreen); 484 new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, 485 NULL, NULL, NULL); 486 } 487 488 return new_linear; 489} 490 491static int 492CHIPSSetCurrentPlaybackBuffer(CHIPSPtr cPtr, int n) 493{ 494 495 CARD8 mr20; 496 mr20 = cPtr->readMR(cPtr, 0x20); 497 mr20 &= ~0x1B; 498 if (!n) mr20 |= 0x10; 499 cPtr->writeMR(cPtr, 0x22, mr20); 500 return n; 501} 502 503static int 504CHIPSWaitGetNextFrame(CHIPSPtr cPtr) 505{ 506 volatile CARD8 mr20; 507 volatile CARD8 mr21; 508 509 mr20 = cPtr->readMR(cPtr, 0x20); 510 while (1) { 511 mr21 = cPtr->readMR(cPtr, 0x21); 512 if (!(mr20 & (1 << 5)) || !(mr21 & 1)) 513 break; 514 } 515 mr20 &= ~0x4; 516 mr20 = cPtr->readMR(cPtr, 0x20); 517 return (mr21 & 2)? 0 : 1; 518} 519 520static void 521CHIPSDisplayVideo( 522 ScrnInfoPtr pScrn, 523 int id, 524 int offset, 525 short width, short height, 526 int pitch, 527 int x1, int y1, int x2, int y2, 528 BoxPtr dstBox, 529 short src_w, short src_h, 530 short drw_w, short drw_h, 531 Bool triggerBufSwitch 532){ 533 CHIPSPtr cPtr = CHIPSPTR(pScrn); 534 CHIPSPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 535 DisplayModePtr mode = pScrn->currentMode; 536 unsigned char tmp, m1f, m1e; 537 int buffer = pPriv->currentBuffer; 538 Bool dblscan = (pScrn->currentMode->Flags & V_DBLSCAN) == V_DBLSCAN; 539 int val; 540 541#ifdef HAVE_XAA_H 542 if (cPtr->Flags & ChipsAccelSupport) 543 CHIPSHiQVSync(pScrn); 544#endif 545 tmp = cPtr->readXR(cPtr, 0xD0); 546 cPtr->writeXR(cPtr, 0xD0, (tmp | 0x10)); 547 548 m1e = cPtr->readMR(cPtr, 0x1E); 549 m1e &= 0xE0; /* Set Zoom and Direction */ 550 if ((!(cPtr->PanelType & ChipsLCD)) && (mode->Flags & V_INTERLACE)) 551 m1e |= 0x10; 552 553 m1f = cPtr->readMR(cPtr, 0x1F); 554 m1f = (m1f & 0x14); /* Mask reserved bits, unset interpolation */ 555 switch(id) { 556 case 0x35315652: /* RGB15 */ 557 m1f |= 0x09; 558 break; 559 case 0x36315652: /* RGB16 */ 560 m1f |= 0x08; 561 break; 562 case FOURCC_YV12: /* YV12 */ 563 /* m1f |= 0x03 */ 564 m1f |= 0x00; 565 break; 566 case FOURCC_YUY2: /* YUY2 */ 567 default: 568 m1f |= 0x00; /* Do nothing here */ 569 break; 570 } 571 572 offset += (x1 >> 15) & ~0x01; 573 /* Setup Pointer 1 */ 574 if (!buffer || pPriv->manualDoubleBuffer || !pPriv->doubleBuffer) { 575 cPtr->writeMR(cPtr, 0x22, (offset & 0xF8)); 576 cPtr->writeMR(cPtr, 0x23, ((offset >> 8) & 0xFF)); 577 cPtr->writeMR(cPtr, 0x24, ((offset >> 16) & 0xFF)); 578 } 579 580 /* Setup Pointer 2 */ 581 if ((buffer && !pPriv->manualDoubleBuffer) || !pPriv->doubleBuffer) { 582 cPtr->writeMR(cPtr, 0x25, (offset & 0xF8)); 583 cPtr->writeMR(cPtr, 0x26, ((offset >> 8) & 0xFF)); 584 cPtr->writeMR(cPtr, 0x27, ((offset >> 16) & 0xFF)); 585 } 586 587 tmp = cPtr->readMR(cPtr, 0x04); 588 if (pPriv->doubleBuffer && !pPriv->manualDoubleBuffer && triggerBufSwitch) 589 tmp |= 0x18; 590 cPtr->writeMR(cPtr, 0x04, tmp); 591 592 tmp = cPtr->readMR(cPtr, 0x20); 593 tmp &= 0xC3; 594 595 if (pPriv->doubleBuffer && !pPriv->manualDoubleBuffer && triggerBufSwitch) 596 tmp |= ((1 << 2 | 1 << 5) | ((buffer) ? (1 << 4) : 0)); 597 cPtr->writeMR(cPtr, 0x20, tmp); 598 599 cPtr->writeMR(cPtr, 0x28, ((width >> 2) - 1)); /* Width */ 600 cPtr->writeMR(cPtr, 0x34, ((width >> 2) - 1)); 601 602 /* Left Edge of Overlay */ 603 cPtr->writeMR(cPtr, 0x2A, ((cPtr->OverlaySkewX + dstBox->x1) & 0xFF)); 604 tmp = cPtr->readMR(cPtr, 0x2B); 605 tmp = (tmp & 0xF8) + (((cPtr->OverlaySkewX + dstBox->x1) >> 8) & 0x07); 606 cPtr->writeMR(cPtr, 0x2B, tmp); 607 /* Right Edge of Overlay */ 608 cPtr->writeMR(cPtr, 0x2C, ((cPtr->OverlaySkewX + dstBox->x2 -1) 609 & 0xFF)); 610 tmp = cPtr->readMR(cPtr, 0x2D); 611 tmp = (tmp & 0xF8) + (((cPtr->OverlaySkewX + dstBox->x2 - 1) >> 8) & 0x07); 612 cPtr->writeMR(cPtr, 0x2D, tmp); 613 /* Top Edge of Overlay */ 614 val = cPtr->OverlaySkewY + (dstBox->y1 << (dblscan ? 1 : 0)); 615 cPtr->writeMR(cPtr, 0x2E, ((val) & 0xFF)); 616 tmp = cPtr->readMR(cPtr, 0x2F); 617 tmp = (tmp & 0xF8) + (((val) >> 8) & 0x07); 618 cPtr->writeMR(cPtr, 0x2F, tmp); 619 /* Bottom Edge of Overlay*/ 620 val = cPtr->OverlaySkewY + (dstBox->y2 << (dblscan ? 1 : 0)); 621 cPtr->writeMR(cPtr, 0x30, ((val - 1) & 0xFF)); 622 tmp = cPtr->readMR(cPtr, 0x31); 623 tmp = (tmp & 0xF8) + (((val - 1) >> 8) & 0x07); 624 cPtr->writeMR(cPtr, 0x31, tmp); 625 626 /* Horizontal Zoom */ 627 if (drw_w > src_w) { 628 m1f = m1f | 0x20; /* set H-interpolation */ 629 m1e = m1e | 0x04; 630 tmp = cPtr->VideoZoomMax * src_w / drw_w; 631 cPtr->writeMR(cPtr, 0x32, tmp); 632 } 633 634 /* Vertical Zoom */ 635 if (drw_h > src_h || dblscan) { 636 m1f = m1f | 0x80; /* set V-interpolation */ 637 m1e = m1e | 0x08; 638 if (dblscan) 639 tmp = cPtr->VideoZoomMax >> 1; 640 if (drw_h > src_h) 641 tmp = 256 * src_h / drw_h; 642 cPtr->writeMR(cPtr, 0x33, tmp & 0xFC); 643 } 644 cPtr->writeMR(cPtr, 0x1F, m1f); 645 cPtr->writeMR(cPtr, 0x1E, m1e); 646 647 tmp = cPtr->readMR(cPtr, 0x3C); 648 cPtr->writeMR(cPtr, 0x3C, (tmp | 0x7)); 649#ifdef HAVE_XAA_H 650 if (cPtr->Flags & ChipsAccelSupport) 651 CHIPSHiQVSync(pScrn); 652#endif 653} 654 655static int 656CHIPSPutImage( 657 ScrnInfoPtr pScrn, 658 short src_x, short src_y, 659 short drw_x, short drw_y, 660 short src_w, short src_h, 661 short drw_w, short drw_h, 662 int id, unsigned char* buf, 663 short width, short height, 664 Bool sync, 665 RegionPtr clipBoxes, pointer data, 666 DrawablePtr pDraw 667){ 668 CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data; 669 CHIPSPtr cPtr = CHIPSPTR(pScrn); 670 INT32 x1, x2, y1, y2; 671 unsigned char *dst_start; 672 int new_size, offset, offset2 = 0, offset3 = 0; 673 int srcPitch, srcPitch2 = 0, dstPitch; 674 int top, left, npixels, nlines, bpp; 675 BoxRec dstBox; 676 CARD32 tmp; 677 678 if(drw_w > 16384) drw_w = 16384; 679 680 /* Clip */ 681 x1 = src_x; 682 x2 = src_x + src_w; 683 y1 = src_y; 684 y2 = src_y + src_h; 685 686 dstBox.x1 = drw_x; 687 dstBox.x2 = drw_x + drw_w; 688 dstBox.y1 = drw_y; 689 dstBox.y2 = drw_y + drw_h; 690 691 if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, 692 clipBoxes, width, height)) 693 return Success; 694 695 dstBox.x1 -= pScrn->frameX0 & cPtr->viewportMask; 696 dstBox.x2 -= pScrn->frameX0 & cPtr->viewportMask; 697 dstBox.y1 -= pScrn->frameY0; 698 dstBox.y2 -= pScrn->frameY0; 699 700 bpp = pScrn->bitsPerPixel >> 3; 701 702 dstPitch = ((width << 1) + 15) & ~15; 703 new_size = ((dstPitch * height) + bpp - 1) / bpp; 704 705 pPriv->doubleBuffer = (pScrn->currentMode->Flags & V_DBLSCAN) != V_DBLSCAN; 706 707 if (pPriv->doubleBuffer) 708 new_size <<= 1; 709 710 switch(id) { 711 case FOURCC_YV12: /* YV12 */ 712 srcPitch = (width + 3) & ~3; 713 offset2 = srcPitch * height; 714 srcPitch2 = ((width >> 1) + 3) & ~3; 715 offset3 = (srcPitch2 * (height >> 1)) + offset2; 716 break; 717 default: /* RGB15, RGB16, YUY2 */ 718 srcPitch = (width << 1); 719 break; 720 } 721 722 if(!(pPriv->linear = CHIPSAllocateMemory(pScrn, pPriv->linear, new_size))) { 723 if (pPriv->doubleBuffer 724 && (pPriv->linear = CHIPSAllocateMemory(pScrn, pPriv->linear, 725 new_size >> 1))) { 726 new_size >>= 1; 727 pPriv->doubleBuffer = FALSE; 728 } else 729 return BadAlloc; 730 } 731 732 /* copy data */ 733 top = y1 >> 16; 734 left = (x1 >> 16) & ~1; 735 npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; 736 left <<= 1; 737 738 offset = pPriv->linear->offset * bpp; 739 if (!pPriv->manualDoubleBuffer) 740 pPriv->currentBuffer = CHIPSWaitGetNextFrame(cPtr); 741 if(pPriv->doubleBuffer && pPriv->currentBuffer) 742 offset += (new_size * bpp) >> 1; 743 744 dst_start = cPtr->FbBase + offset + left + (top * dstPitch); 745 746 switch(id) { 747 case FOURCC_YV12: /* YV12 */ 748 top &= ~1; 749 tmp = ((top >> 1) * srcPitch2) + (left >> 2); 750 offset2 += tmp; 751 offset3 += tmp; 752 nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; 753 CHIPSCopyMungedData(buf + (top * srcPitch) + (left >> 1), 754 buf + offset2, buf + offset3, dst_start, 755 srcPitch, srcPitch2, dstPitch, nlines, npixels); 756 break; 757 default: /* RGB15, RGB16, YUY2 */ 758 buf += (top * srcPitch) + left; 759 nlines = ((y2 + 0xffff) >> 16) - top; 760 CHIPSCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels); 761 break; 762 } 763 764 /* update cliplist */ 765 if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { 766 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 767 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 768 } 769 770 offset += top * dstPitch; 771 CHIPSDisplayVideo(pScrn, id, offset, width, height, dstPitch, 772 x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h, TRUE); 773 774 pPriv->videoStatus = CLIENT_VIDEO_ON; 775 776 if (pPriv->manualDoubleBuffer) 777 pPriv->currentBuffer ^= 1; 778 779 return Success; 780} 781 782static int 783CHIPSQueryImageAttributes( 784 ScrnInfoPtr pScrn, 785 int id, 786 unsigned short *w, unsigned short *h, 787 int *pitches, int *offsets 788){ 789 int size, tmp; 790 791 if(*w > 1024) *w = 1024; 792 if(*h > 1024) *h = 1024; 793 794 *w = (*w + 1) & ~1; 795 if(offsets) offsets[0] = 0; 796 797 switch(id) { 798 case FOURCC_YV12: /* YV12 */ 799 *h = (*h + 1) & ~1; 800 size = (*w + 3) & ~3; 801 if(pitches) pitches[0] = size; 802 size *= *h; 803 if(offsets) offsets[1] = size; 804 tmp = ((*w >> 1) + 3) & ~3; 805 if(pitches) pitches[1] = pitches[2] = tmp; 806 tmp *= (*h >> 1); 807 size += tmp; 808 if(offsets) offsets[2] = size; 809 size += tmp; 810 break; 811 default: /* RGB15, RGB16, YUY2 */ 812 size = *w << 1; 813 if(pitches) pitches[0] = size; 814 size *= *h; 815 break; 816 } 817 818 return size; 819} 820 821 822static void 823CHIPSVideoTimerCallback(ScrnInfoPtr pScrn, Time time) 824{ 825 CHIPSPtr cPtr = CHIPSPTR(pScrn); 826 CHIPSPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 827 unsigned char mr3c; 828 829 if(pPriv->videoStatus & TIMER_MASK) { 830 if(pPriv->videoStatus & OFF_TIMER) { 831 if(pPriv->offTime < time) { 832#ifdef HAVE_XAA_H 833 if (cPtr->Flags & ChipsAccelSupport) 834 CHIPSHiQVSync(pScrn); 835#endif 836 mr3c = cPtr->readMR(cPtr, 0x3C); 837 cPtr->writeMR(cPtr, 0x3C, (mr3c & 0xFE)); 838 pPriv->videoStatus = FREE_TIMER; 839 pPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 840 } 841 } else { /* FREE_TIMER */ 842 if(pPriv->freeTime < time) { 843 if(pPriv->linear) { 844 xf86FreeOffscreenLinear(pPriv->linear); 845 pPriv->linear = NULL; 846 } 847 pPriv->videoStatus = 0; 848 cPtr->VideoTimerCallback = NULL; 849 } 850 } 851 } else /* shouldn't get here */ 852 cPtr->VideoTimerCallback = NULL; 853} 854 855 856/****************** Offscreen stuff ***************/ 857 858typedef struct { 859 FBLinearPtr linear; 860 Bool isOn; 861} OffscreenPrivRec, * OffscreenPrivPtr; 862 863static int 864CHIPSAllocateSurface( 865 ScrnInfoPtr pScrn, 866 int id, 867 unsigned short w, 868 unsigned short h, 869 XF86SurfacePtr surface 870){ 871 FBLinearPtr linear; 872 int pitch, size, bpp; 873 OffscreenPrivPtr pPriv; 874 875 if((w > 1024) || (h > 1024)) 876 return BadAlloc; 877 878 w = (w + 1) & ~1; 879 pitch = ((w << 1) + 15) & ~15; 880 bpp = pScrn->bitsPerPixel >> 3; 881 size = ((pitch * h) + bpp - 1) / bpp; 882 883 if(!(linear = CHIPSAllocateMemory(pScrn, NULL, size))) 884 return BadAlloc; 885 886 surface->width = w; 887 surface->height = h; 888 889 if(!(surface->pitches = malloc(sizeof(int)))) { 890 xf86FreeOffscreenLinear(linear); 891 return BadAlloc; 892 } 893 if(!(surface->offsets = malloc(sizeof(int)))) { 894 free(surface->pitches); 895 xf86FreeOffscreenLinear(linear); 896 return BadAlloc; 897 } 898 if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) { 899 free(surface->pitches); 900 free(surface->offsets); 901 xf86FreeOffscreenLinear(linear); 902 return BadAlloc; 903 } 904 905 pPriv->linear = linear; 906 pPriv->isOn = FALSE; 907 908 surface->pScrn = pScrn; 909 surface->id = id; 910 surface->pitches[0] = pitch; 911 surface->offsets[0] = linear->offset * bpp; 912 surface->devPrivate.ptr = (pointer)pPriv; 913 914 return Success; 915} 916 917static int 918CHIPSStopSurface( 919 XF86SurfacePtr surface 920){ 921 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 922 923 if(pPriv->isOn) { 924 CHIPSPtr cPtr = CHIPSPTR(surface->pScrn); 925 unsigned char mr3c, tmp; 926 tmp = cPtr->readXR(cPtr, 0xD0); 927 cPtr->writeXR(cPtr, 0xD0, (tmp & 0xf)); 928 mr3c = cPtr->readMR(cPtr, 0x3C); 929 cPtr->writeMR(cPtr, 0x3C, (mr3c & 0xFE)); 930 pPriv->isOn = FALSE; 931 } 932 933 return Success; 934} 935 936 937static int 938CHIPSFreeSurface( 939 XF86SurfacePtr surface 940){ 941 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 942 943 if(pPriv->isOn) 944 CHIPSStopSurface(surface); 945 xf86FreeOffscreenLinear(pPriv->linear); 946 free(surface->pitches); 947 free(surface->offsets); 948 free(surface->devPrivate.ptr); 949 950 return Success; 951} 952 953static int 954CHIPSGetSurfaceAttribute( 955 ScrnInfoPtr pScrn, 956 Atom attribute, 957 INT32 *value 958){ 959 return CHIPSGetPortAttribute(pScrn, attribute, value, 960 (pointer)(GET_PORT_PRIVATE(pScrn))); 961} 962 963static int 964CHIPSSetSurfaceAttribute( 965 ScrnInfoPtr pScrn, 966 Atom attribute, 967 INT32 value 968){ 969 return CHIPSSetPortAttribute(pScrn, attribute, value, 970 (pointer)(GET_PORT_PRIVATE(pScrn))); 971} 972 973 974static int 975CHIPSDisplaySurface( 976 XF86SurfacePtr surface, 977 short src_x, short src_y, 978 short drw_x, short drw_y, 979 short src_w, short src_h, 980 short drw_w, short drw_h, 981 RegionPtr clipBoxes 982){ 983 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 984 ScrnInfoPtr pScrn = surface->pScrn; 985 CHIPSPtr cPtr = CHIPSPTR(pScrn); 986 CHIPSPortPrivPtr portPriv = GET_PORT_PRIVATE(pScrn); 987 INT32 x1, y1, x2, y2; 988 BoxRec dstBox; 989 990 x1 = src_x; 991 x2 = src_x + src_w; 992 y1 = src_y; 993 y2 = src_y + src_h; 994 995 dstBox.x1 = drw_x; 996 dstBox.x2 = drw_x + drw_w; 997 dstBox.y1 = drw_y; 998 dstBox.y2 = drw_y + drw_h; 999 1000 if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, 1001 surface->width, surface->height)) 1002 return Success; 1003 1004 dstBox.x1 -= pScrn->frameX0; 1005 dstBox.x2 -= pScrn->frameX0; 1006 dstBox.y1 -= pScrn->frameY0; 1007 dstBox.y2 -= pScrn->frameY0; 1008 1009 if (portPriv->doubleBuffer) 1010 portPriv->currentBuffer = CHIPSSetCurrentPlaybackBuffer(cPtr,0); 1011 else 1012 portPriv->currentBuffer = 0; 1013 1014 CHIPSDisplayVideo(pScrn, surface->id, surface->offsets[0], 1015 surface->width, surface->height, surface->pitches[0], 1016 x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h, FALSE); 1017 xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes); 1018 1019 pPriv->isOn = TRUE; 1020 if(portPriv->videoStatus & CLIENT_VIDEO_ON) { 1021 REGION_EMPTY(pScrn->pScreen, &portPriv->clip); 1022 UpdateCurrentTime(); 1023 portPriv->videoStatus = FREE_TIMER; 1024 portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 1025 cPtr->VideoTimerCallback = CHIPSVideoTimerCallback; 1026 } 1027 1028 return Success; 1029} 1030 1031 1032static void 1033CHIPSInitOffscreenImages(ScreenPtr pScreen) 1034{ 1035 XF86OffscreenImagePtr offscreenImages; 1036 1037 /* need to free this someplace */ 1038 if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec)))) 1039 return; 1040 1041 offscreenImages[0].image = &Images[0]; 1042 offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | 1043 VIDEO_CLIP_TO_VIEWPORT; 1044 offscreenImages[0].alloc_surface = CHIPSAllocateSurface; 1045 offscreenImages[0].free_surface = CHIPSFreeSurface; 1046 offscreenImages[0].display = CHIPSDisplaySurface; 1047 offscreenImages[0].stop = CHIPSStopSurface; 1048 offscreenImages[0].setAttribute = CHIPSSetSurfaceAttribute; 1049 offscreenImages[0].getAttribute = CHIPSGetSurfaceAttribute; 1050 offscreenImages[0].max_width = 1024; 1051 offscreenImages[0].max_height = 1024; 1052 offscreenImages[0].num_attributes = NUM_ATTRIBUTES; 1053 offscreenImages[0].attributes = Attributes; 1054 1055 xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); 1056} 1057