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