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