s3v_xv.c revision ba85709e
1/* 2Copyright (C) 2000 The XFree86 Project, Inc. All Rights Reserved. 3 4Permission is hereby granted, free of charge, to any person obtaining a copy of 5this software and associated documentation files (the "Software"), to deal in 6the Software without restriction, including without limitation the rights to 7use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 8of the Software, and to permit persons to whom the Software is furnished to do 9so, subject to the following conditions: 10 11The above copyright notice and this permission notice shall be included in all 12copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- 16NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 19WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of the XFree86 Project shall not 22be used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from the XFree86 Project. 24*/ 25 26/* 27 * s3v_xv.c 28 * X Video Extension support 29 * 30 * S3 ViRGE driver 31 * 32 * 7/2000 Kevin Brosius 33 * 34 * Useful references: 35 * X Video extension support -> xc/programs/hw/xfree86/common/xf86xv.c 36 * 37 */ 38 39#ifdef HAVE_CONFIG_H 40#include "config.h" 41#endif 42 43 /* Most xf86 commons are already in s3v.h */ 44#include "s3v.h" 45 46#if 0 47#define OFF_DELAY 250 /* milliseconds */ 48#define FREE_DELAY 15000 49 50#define OFF_TIMER 0x01 51#define FREE_TIMER 0x02 52#endif 53#define CLIENT_VIDEO_ON 0x04 54 55#define S3V_MAX_PORTS 1 56 57#if 0 58static void S3VInitOffscreenImages(ScreenPtr); 59#endif 60 61static XF86VideoAdaptorPtr S3VAllocAdaptor(ScrnInfoPtr pScrn); 62static XF86VideoAdaptorPtr S3VSetupImageVideoOverlay(ScreenPtr); 63static int S3VSetPortAttributeOverlay(ScrnInfoPtr, Atom, INT32, pointer); 64static int S3VGetPortAttributeOverlay(ScrnInfoPtr, Atom ,INT32 *, pointer); 65 66 67static void S3VStopVideo(ScrnInfoPtr, pointer, Bool); 68static void S3VQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, 69 unsigned int *, unsigned int *, pointer); 70static int S3VPutImage(ScrnInfoPtr, short, short, short, short, short, 71 short, short, short, int, unsigned char*, short, 72 short, Bool, RegionPtr, pointer, DrawablePtr); 73static int S3VQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, 74 unsigned short *, int *, int *); 75 76 77static void S3VResetVideoOverlay(ScrnInfoPtr); 78 79#if 0 80#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 81 82static Atom xvBrightness, xvContrast, xvColorKey; 83 84#endif /* 0 */ 85 86int S3VQueryXvCapable(ScrnInfoPtr pScrn) 87{ 88 S3VPtr ps3v = S3VPTR(pScrn); 89 90 if( 91 ((pScrn->bitsPerPixel == 24) || 92 (pScrn->bitsPerPixel == 16) 93 ) 94 && 95 ((ps3v->Chipset == S3_ViRGE_DXGX) || 96 S3_ViRGE_MX_SERIES(ps3v->Chipset) || 97 S3_ViRGE_GX2_SERIES(ps3v->Chipset) 98 )) 99 return TRUE; 100 else 101 return FALSE; 102} 103 104 105void S3VInitVideo(ScreenPtr pScreen) 106{ 107 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 108 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 109 XF86VideoAdaptorPtr newAdaptor = NULL; 110 S3VPtr ps3v = S3VPTR(pScrn); 111 int num_adaptors; 112 113 if( 114 ((pScrn->bitsPerPixel == 24) || 115 (pScrn->bitsPerPixel == 16) 116 ) 117 && 118 ((ps3v->Chipset == S3_ViRGE_DXGX) || 119 S3_ViRGE_MX_SERIES(ps3v->Chipset) || 120 S3_ViRGE_GX2_SERIES(ps3v->Chipset) /* || */ 121 /* (ps3v->Chipset == S3_ViRGE) */ 122 ) 123 && !ps3v->NoAccel 124 && ps3v->XVideo 125 ) 126 { 127 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using overlay video\n"); 128 newAdaptor = S3VSetupImageVideoOverlay(pScreen); 129 } 130 131 132 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 133 134 if(newAdaptor) { 135 if(!num_adaptors) { 136 num_adaptors = 1; 137 adaptors = &newAdaptor; 138 } else { 139 newAdaptors = /* need to free this someplace */ 140 xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); 141 if(newAdaptors) { 142 memcpy(newAdaptors, adaptors, num_adaptors * 143 sizeof(XF86VideoAdaptorPtr)); 144 newAdaptors[num_adaptors] = newAdaptor; 145 adaptors = newAdaptors; 146 num_adaptors++; 147 } 148 } 149 } 150 151 if(num_adaptors) 152 xf86XVScreenInit(pScreen, adaptors, num_adaptors); 153 154 if(newAdaptors) 155 xfree(newAdaptors); 156} 157 158/* client libraries expect an encoding */ 159static XF86VideoEncodingRec DummyEncoding[2] = 160{ 161 { /* overlay limit */ 162 0, 163 "XV_IMAGE", 164 1024, 1024, 165 {1, 1} 166 }, 167 { /* texture limit */ 168 0, 169 "XV_IMAGE", 170 2046, 2046, 171 {1, 1} 172 } 173}; 174 175#define NUM_FORMATS_OVERLAY 4 176#define NUM_FORMATS_TEXTURE 4 177 178static XF86VideoFormatRec Formats[NUM_FORMATS_TEXTURE] = 179{ 180 /*{15, TrueColor},*/ {16, TrueColor}, {24, TrueColor} /* , 181 {15, DirectColor}*/, {16, DirectColor}, {24, DirectColor} 182}; 183 184#if 0 185#define NUM_ATTRIBUTES_OVERLAY 3 186 187static XF86AttributeRec Attributes[NUM_ATTRIBUTES_OVERLAY] = 188{ 189 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 190 {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, 191 {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"} 192}; 193#endif 194 195#define NUM_IMAGES 3 196 197static XF86ImageRec Images[NUM_IMAGES] = 198{ 199 XVIMAGE_YUY2, 200 /* As in mga, YV12 & I420 are converted to YUY2 on the fly by */ 201 /* copy over conversion. */ 202 XVIMAGE_YV12, 203 XVIMAGE_I420 204 /* XVIMAGE_UYVY */ 205}; 206 207 208 209static int 210S3VSetPortAttributeOverlay( 211 ScrnInfoPtr pScrn, 212 Atom attribute, 213 INT32 value, 214 pointer data 215){ 216 217return BadMatch; 218 219} 220 221static int 222S3VGetPortAttributeOverlay( 223 ScrnInfoPtr pScrn, 224 Atom attribute, 225 INT32 *value, 226 pointer data 227){ 228 229 230return BadMatch; 231 232} 233 234 235 236static void 237S3VQueryBestSize( 238 ScrnInfoPtr pScrn, 239 Bool motion, 240 short vid_w, short vid_h, 241 short drw_w, short drw_h, 242 unsigned int *p_w, unsigned int *p_h, 243 pointer data 244){ 245 *p_w = drw_w; 246 *p_h = drw_h; 247 248#if 0 249 /* Only support scaling up, no down scaling. */ 250 /* This doesn't seem to work (at least for XMovie) */ 251 /* and the DESIGN doc says this is illegal anyway... */ 252 if( drw_w < vid_w ) *p_w = vid_w; 253 if( drw_h < vid_h ) *p_h = vid_h; 254#endif 255} 256 257 258 259static void 260S3VResetVideoOverlay(ScrnInfoPtr pScrn) 261{ 262 /* empty for ViRGE at the moment... */ 263#if 0 264 S3VPtr ps3v = S3VPTR(pScrn); 265 S3VPortPrivPtr pPriv = ps3v->portPrivate; 266 267 MGAPtr pMga = MGAPTR(pScrn); 268 MGAPortPrivPtr pPriv = pMga->portPrivate; 269 270 CHECK_DMA_QUIESCENT(pMga, pScrn); 271 272 outMGAdac(0x51, 0x01); /* keying on */ 273 outMGAdac(0x52, 0xff); /* full mask */ 274 outMGAdac(0x53, 0xff); 275 outMGAdac(0x54, 0xff); 276 277 outMGAdac(0x55, (pPriv->colorKey & pScrn->mask.red) >> 278 pScrn->offset.red); 279 outMGAdac(0x56, (pPriv->colorKey & pScrn->mask.green) >> 280 pScrn->offset.green); 281 outMGAdac(0x57, (pPriv->colorKey & pScrn->mask.blue) >> 282 pScrn->offset.blue); 283#endif 284 285#if 0 286 OUTREG(MGAREG_BESLUMACTL, ((pPriv->brightness & 0xff) << 16) | 287 (pPriv->contrast & 0xff)); 288#endif /*0*/ 289} 290 291 292 293static XF86VideoAdaptorPtr 294S3VAllocAdaptor(ScrnInfoPtr pScrn) 295{ 296 XF86VideoAdaptorPtr adapt; 297 S3VPtr ps3v = S3VPTR(pScrn); 298 S3VPortPrivPtr pPriv; 299 int i; 300 301 if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn))) 302 return NULL; 303 304 if(!(pPriv = xcalloc(1, sizeof(S3VPortPrivRec) + 305 (sizeof(DevUnion) * S3V_MAX_PORTS)))) 306 { 307 xfree(adapt); 308 return NULL; 309 } 310 311 adapt->pPortPrivates = (DevUnion*)(&pPriv[1]); 312 313 for(i = 0; i < S3V_MAX_PORTS; i++) 314 adapt->pPortPrivates[i].val = i; 315 316#if 0 317 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 318 xvContrast = MAKE_ATOM("XV_CONTRAST"); 319 xvColorKey = MAKE_ATOM("XV_COLORKEY"); 320#endif 321 322 pPriv->colorKey = 323 (1 << pScrn->offset.red) | 324 (1 << pScrn->offset.green) | 325 (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue); 326 327#if 0 328 pPriv->brightness = 0; 329 pPriv->contrast = 128; 330#endif 331 332 pPriv->videoStatus = 0; 333 pPriv->lastPort = -1; 334 335 ps3v->adaptor = adapt; 336 ps3v->portPrivate = pPriv; 337 338 return adapt; 339} 340 341 342 343 344 345static XF86VideoAdaptorPtr 346S3VSetupImageVideoOverlay(ScreenPtr pScreen) 347{ 348 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 349 S3VPtr ps3v = S3VPTR(pScrn); 350 XF86VideoAdaptorPtr adapt; 351 352 adapt = S3VAllocAdaptor(pScrn); 353 354 adapt->type = XvWindowMask | XvInputMask | XvImageMask; 355 adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 356 adapt->name = "S3 ViRGE Backend Scaler"; 357 adapt->nEncodings = 1; 358 adapt->pEncodings = &DummyEncoding[0]; 359 adapt->nFormats = NUM_FORMATS_OVERLAY; 360 adapt->pFormats = Formats; 361 adapt->nPorts = 1; 362 adapt->pAttributes = NULL /*Attributes*/; 363 adapt->nImages = 3; 364 adapt->nAttributes = 0; 365 adapt->pImages = Images; 366 adapt->PutVideo = NULL; 367 adapt->PutStill = NULL; 368 adapt->GetVideo = NULL; 369 adapt->GetStill = NULL; 370 adapt->StopVideo = S3VStopVideo; 371 /* Empty Attrib functions - required anyway */ 372 adapt->SetPortAttribute = S3VSetPortAttributeOverlay; 373 adapt->GetPortAttribute = S3VGetPortAttributeOverlay; 374 adapt->QueryBestSize = S3VQueryBestSize; 375 adapt->PutImage = S3VPutImage; 376 adapt->QueryImageAttributes = S3VQueryImageAttributes; 377 378 /* gotta uninit this someplace */ 379 REGION_NULL(pScreen, &(ps3v->portPrivate->clip)); 380 381 S3VResetVideoOverlay(pScrn); 382 383 return adapt; 384} 385 386 387static void 388S3VStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) 389{ 390 S3VPtr ps3v = S3VPTR(pScrn); 391 S3VPortPrivPtr pPriv = ps3v->portPrivate; 392 393 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 394 395 if(shutdown) { 396 if(pPriv->videoStatus & CLIENT_VIDEO_ON) 397 { 398 if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 399 S3_ViRGE_MX_SERIES(ps3v->Chipset) 400 ) 401 { 402 /* Aaarg... It .. won't.. go .. away! */ 403 /* So let's be creative, make the overlay really */ 404 /* small and near an edge. */ 405 /* Size of 0 leaves a window sized vertical stripe */ 406 /* Size of 1 leaves a single pixel.. */ 407 OUTREG(SSTREAM_WINDOW_SIZE_REG, 1); 408 /* And hide it at 0,0 */ 409 OUTREG(SSTREAM_START_REG, 0 ); 410 } 411 else 412 { 413 /* Primary over secondary */ 414 OUTREG(BLEND_CONTROL_REG, 0x01000000); 415 } 416 } 417 418 if(pPriv->area) { 419 xf86FreeOffscreenArea(pPriv->area); 420 pPriv->area = NULL; 421 } 422 pPriv->videoStatus = 0; 423#if 0 424 } else { 425 if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 426 pPriv->videoStatus |= OFF_TIMER; 427 pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 428 } 429#endif 430 } 431} 432 433 434 435static FBAreaPtr 436S3VAllocateMemory( 437 ScrnInfoPtr pScrn, 438 FBAreaPtr area, 439 int numlines 440){ 441 ScreenPtr pScreen; 442 FBAreaPtr new_area; 443 444 if(area) { 445 if((area->box.y2 - area->box.y1) >= numlines) 446 return area; 447 448 if(xf86ResizeOffscreenArea(area, pScrn->displayWidth, numlines)) 449 return area; 450 451 xf86FreeOffscreenArea(area); 452 } 453 454 pScreen = screenInfo.screens[pScrn->scrnIndex]; 455 456 new_area = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, 457 numlines, 0, NULL, NULL, NULL); 458 459 if(!new_area) { 460 int max_w, max_h; 461 462 xf86QueryLargestOffscreenArea(pScreen, &max_w, &max_h, 0, 463 FAVOR_WIDTH_THEN_AREA, PRIORITY_EXTREME); 464 465 if((max_w < pScrn->displayWidth) || (max_h < numlines)) 466 return NULL; 467 468 xf86PurgeUnlockedOffscreenAreas(pScreen); 469 new_area = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, 470 numlines, 0, NULL, NULL, NULL); 471 } 472 473 return new_area; 474} 475 476 477 478static void 479S3VDisplayVideoOverlay( 480 ScrnInfoPtr pScrn, 481 int id, 482 int offset, 483 short width, short height, 484 int pitch, 485 /* x,y src co-ordinates */ 486 int x1, int y1, int x2, int y2, 487 /* dst in BoxPtr format */ 488 BoxPtr dstBox, 489 /* src width and height */ 490 short src_w, short src_h, 491 /* dst width and height */ 492 short drw_w, short drw_h 493){ 494 int tmp; 495 496#if 0 497 CHECK_DMA_QUIESCENT(pMga, pScrn); 498#endif 499 S3VPtr ps3v = S3VPTR(pScrn); 500 S3VPortPrivPtr pPriv = ps3v->portPrivate; 501 502 vgaHWPtr hwp = VGAHWPTR(pScrn); 503 /* S3VPtr ps3v = S3VPTR(pScrn);*/ 504 int vgaCRIndex, vgaCRReg, vgaIOBase; 505 vgaIOBase = hwp->IOBase; 506 vgaCRIndex = vgaIOBase + 4; 507 vgaCRReg = vgaIOBase + 5; 508 509 /* If streams aren't enabled, do nothing */ 510 if(!ps3v->NeedSTREAMS) 511 return; 512 513 514 /* Reference at http://www.webartz.com/fourcc/ */ 515 /* Looks like ViRGE only supports YUY2 and Y211?, */ 516 /* listed as YUV-16 (4.2.2) and YUV (2.1.1) in manual. */ 517 518#if 0 519 /* Only supporting modes we listed for the time being, */ 520 /* No, switching required... #if 0'd this out */ 521 522 switch(id) { 523 case FOURCC_UYVY: 524 /* 525 FOURCC=0x59565955 526 bpp=16 527 YUV 4:2:2 (Y sample at every 528 pixel, U and V sampled at 529 every second pixel 530 horizontally on each line). A 531 macropixel contains 2 pixels 532 in 1 u_int32. 533 */ 534 535 /* OUTREG(MGAREG_BESGLOBCTL, 0x000000c3 | (tmp << 16));*/ 536 break; 537 case FOURCC_YUY2: 538 /* 539 FOURCC=0x32595559 540 bpp=16 541 YUV 4:2:2 as for UYVY but 542 with different component 543 ordering within the u_int32 544 macropixel. 545 546 Supports YV12 & I420 by copy over conversion of formats to YUY2, 547 copied from mga driver. Thanks Mark! 548 */ 549 default: 550 /*OUTREG(MGAREG_BESGLOBCTL, 0x00000083 | (tmp << 16));*/ 551 /* YUV-16 (4.2.2) Secondary stream */ 552 /* temp ... add DDA Horiz Accum. */ 553 /*OUTREG(SSTREAM_CONTROL_REG, 0x02000000); / YUV-16 */ 554 /* works for xvtest and suzi */ 555 /* OUTREG(SSTREAM_CONTROL_REG, 0x01000000); * YCbCr-16 * no scaling */ 556 557 /* calc horizontal scale factor */ 558 tmp = drw_w / src_w; 559 if (drw_w == src_w) tmp = 0; 560 else if (tmp>=4) tmp =3; 561 else if (tmp>=2) tmp =2; 562 else tmp =1; 563 564 /* YCbCr-16 */ 565 OUTREG(SSTREAM_CONTROL_REG, 566 tmp << 28 | 0x01000000 | 567 ((((src_w-1)<<1)-(drw_w-1)) & 0xfff) 568 ); 569 break; 570 } 571#endif 572 573 /* calc horizontal scale factor */ 574 if (drw_w == src_w) 575 tmp = 0; 576 else 577 tmp =2; 578 /* YCbCr-16 */ 579 OUTREG(SSTREAM_CONTROL_REG, 580 tmp << 28 | 0x01000000 | 581 ((((src_w-1)<<1)-(drw_w-1)) & 0xfff) 582 ); 583 584 OUTREG(SSTREAM_STRETCH_REG, 585 ((src_w - 1) & 0x7ff) | (((src_w-drw_w-1) & 0x7ff) << 16) 586 ); 587 588 /* Color key on primary */ 589 if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 590 S3_ViRGE_MX_SERIES(ps3v->Chipset) 591 ) 592 { 593 /* 100% of secondary, no primary */ 594 /* gx2/mx can both blend while keying, need to */ 595 /* select secondary here, otherwise all you'll get */ 596 /* from the primary is the color key. (And setting */ 597 /* 0 here gives you black... no primary or secondary. */ 598 /* Discovered that the hard way!) */ 599 OUTREG(BLEND_CONTROL_REG, 0x20 ); 600 } 601 else 602 { 603 OUTREG(BLEND_CONTROL_REG, 0x05000000); 604 } 605 606 OUTREG(SSTREAM_FBADDR0_REG, offset & 0x3fffff ); 607 OUTREG(SSTREAM_STRIDE_REG, pitch & 0xfff ); 608 609 OUTREG(K1_VSCALE_REG, src_h-1 ); 610 OUTREG(K2_VSCALE_REG, (src_h - drw_h) & 0x7ff ); 611 612 if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 613 S3_ViRGE_MX_SERIES(ps3v->Chipset) ) 614 { 615 /* enable vert interp. & bandwidth saving - gx2 */ 616 OUTREG(DDA_VERT_REG, (((~drw_h)-1) & 0xfff ) | 617 /* bw & vert interp */ 618 0xc000 619 /* no bw save 0x8000*/ 620 ); 621 } 622 else 623 { 624 OUTREG(DDA_VERT_REG, (((~drw_h)-1)) & 0xfff ); 625 } 626 627 OUTREG(SSTREAM_START_REG, ((dstBox->x1 +1) << 16) | (dstBox->y1 +1)); 628 OUTREG(SSTREAM_WINDOW_SIZE_REG, 629 ( ((drw_w-1) << 16) | (drw_h ) ) & 0x7ff07ff 630 ); 631 632 if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 633 S3_ViRGE_MX_SERIES(ps3v->Chipset) 634 ) 635 { 636 OUTREG(COL_CHROMA_KEY_CONTROL_REG, 637 /* color key ON - keying on primary */ 638 0x40000000 | 639 /* # bits to compare */ 640 ((pScrn->weight.red-1) << 24) | 641 642 ((pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red) << 643 (16 + 8-pScrn->weight.red) | 644 645 ((pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green) << 646 (8 + 8-pScrn->weight.green) | 647 648 ((pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue) << 649 (8-pScrn->weight.blue) 650 ); 651 } 652 else 653 { 654 OUTREG(COL_CHROMA_KEY_CONTROL_REG, 655 /* color key ON */ 656 0x10000000 | 657 /* # bits to compare */ 658 ((pScrn->weight.red-1) << 24) | 659 660 ((pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red) << 661 (16 + 8-pScrn->weight.red) | 662 663 ((pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green) << 664 (8 + 8-pScrn->weight.green) | 665 666 ((pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue) << 667 (8-pScrn->weight.blue) 668 ); 669 } 670 671 if ( S3_ViRGE_GX2_SERIES(ps3v->Chipset) || 672 S3_ViRGE_MX_SERIES(ps3v->Chipset) ) 673 { 674 VGAOUT8(vgaCRIndex, 0x92); 675 VGAOUT8(vgaCRReg, (((pitch + 7) / 8) >> 8) | 0x80); 676 VGAOUT8(vgaCRIndex, 0x93); 677 VGAOUT8(vgaCRReg, (pitch + 7) / 8); 678 } 679 680} 681 682 683static int 684S3VPutImage( 685 ScrnInfoPtr pScrn, 686 short src_x, short src_y, 687 short drw_x, short drw_y, 688 short src_w, short src_h, 689 short drw_w, short drw_h, 690 int id, unsigned char* buf, 691 short width, short height, 692 Bool sync, 693 RegionPtr clipBoxes, pointer data, 694 DrawablePtr pDraw 695){ 696 S3VPtr ps3v = S3VPTR(pScrn); 697 S3VPortPrivPtr pPriv = ps3v->portPrivate; 698 INT32 x1, x2, y1, y2; 699 unsigned char *dst_start; 700 int pitch, new_h, offset, offset2=0, offset3=0; 701 int srcPitch, srcPitch2=0, dstPitch; 702 int top, left, npixels, nlines; 703 BoxRec dstBox; 704 CARD32 tmp; 705 706 /* If streams aren't enabled, do nothing */ 707 if(!ps3v->NeedSTREAMS) 708 return Success; 709 710 /* Clip */ 711 x1 = src_x; 712 x2 = src_x + src_w; 713 y1 = src_y; 714 y2 = src_y + src_h; 715 716 dstBox.x1 = drw_x; 717 dstBox.x2 = drw_x + drw_w; 718 dstBox.y1 = drw_y; 719 dstBox.y2 = drw_y + drw_h; 720 721 if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, 722 clipBoxes, width, height)) 723 return Success; 724 725 /*if(!pMga->TexturedVideo) {*/ 726 dstBox.x1 -= pScrn->frameX0; 727 dstBox.x2 -= pScrn->frameX0; 728 dstBox.y1 -= pScrn->frameY0; 729 dstBox.y2 -= pScrn->frameY0; 730 /*}*/ 731 732 pitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3; 733 734 dstPitch = ((width << 1) + 15) & ~15; 735 new_h = ((dstPitch * height) + pitch - 1) / pitch; 736 737 switch(id) { 738 case FOURCC_YV12: 739 case FOURCC_I420: 740 srcPitch = (width + 3) & ~3; 741 offset2 = srcPitch * height; 742 srcPitch2 = ((width >> 1) + 3) & ~3; 743 offset3 = (srcPitch2 * (height >> 1)) + offset2; 744 break; 745 case FOURCC_UYVY: 746 case FOURCC_YUY2: 747 default: 748 srcPitch = (width << 1); 749 break; 750 } 751 752 if(!(pPriv->area = S3VAllocateMemory(pScrn, pPriv->area, new_h))) 753 return BadAlloc; 754 755 /* copy data */ 756 top = y1 >> 16; 757 left = (x1 >> 16) & ~1; 758 npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; 759 left <<= 1; 760 761 offset = pPriv->area->box.y1 * pitch; 762 dst_start = ps3v->FBStart + offset + left + (top * dstPitch); 763 /*dst_start = pMga->FbStart + offset + left + (top * dstPitch);*/ 764 765 766 switch(id) { 767 case FOURCC_YV12: 768 case FOURCC_I420: 769 top &= ~1; 770 tmp = ((top >> 1) * srcPitch2) + (left >> 2); 771 offset2 += tmp; 772 offset3 += tmp; 773 if(id == FOURCC_I420) { 774 tmp = offset2; 775 offset2 = offset3; 776 offset3 = tmp; 777 } 778 nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; 779 xf86XVCopyYUV12ToPacked(buf + (top * srcPitch) + (left >> 1), 780 buf + offset2, buf + offset3, dst_start, 781 srcPitch, srcPitch2, dstPitch, nlines, npixels); 782 break; 783 case FOURCC_UYVY: 784 case FOURCC_YUY2: 785 default: 786 buf += (top * srcPitch) + left; 787 nlines = ((y2 + 0xffff) >> 16) - top; 788 xf86XVCopyPacked(buf, dst_start, srcPitch, dstPitch, nlines, npixels); 789 break; 790 } 791 792 793 /* update cliplist */ 794 if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { 795 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 796 /* draw these */ 797 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 798 } 799 800 offset += left + (top * dstPitch); 801 S3VDisplayVideoOverlay(pScrn, id, offset, width, height, dstPitch, 802 x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 803 804 pPriv->videoStatus = CLIENT_VIDEO_ON; 805 806 807 return Success; 808} 809 810 811static int 812S3VQueryImageAttributes( 813 ScrnInfoPtr pScrn, 814 int id, 815 unsigned short *w, unsigned short *h, 816 int *pitches, int *offsets 817){ 818 819 int size, tmp; 820 821 if(*w > 1024) *w = 1024; 822 if(*h > 1024) *h = 1024; 823 824 *w = (*w + 1) & ~1; 825 if(offsets) offsets[0] = 0; 826 827 switch(id) { 828 case FOURCC_YV12: 829 case FOURCC_I420: 830 *h = (*h + 1) & ~1; 831 size = (*w + 3) & ~3; 832 if(pitches) pitches[0] = size; 833 size *= *h; 834 if(offsets) offsets[1] = size; 835 tmp = ((*w >> 1) + 3) & ~3; 836 if(pitches) pitches[1] = pitches[2] = tmp; 837 tmp *= (*h >> 1); 838 size += tmp; 839 if(offsets) offsets[2] = size; 840 size += tmp; 841 break; 842 case FOURCC_UYVY: 843 case FOURCC_YUY2: 844 default: 845 size = *w << 1; 846 if(pitches) pitches[0] = size; 847 size *= *h; 848 break; 849 } 850 851 return size; 852} 853