savage_video.c revision ab47cfaa
1/* 2 * Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. 3 * Copyright (c) 2003-2006, X.Org Foundation 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 * COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 * Except as contained in this notice, the name of the copyright holder(s) 24 * and author(s) shall not be used in advertising or otherwise to promote 25 * the sale, use or other dealings in this Software without prior written 26 * authorization from the copyright holder(s) and author(s). 27 */ 28 29#ifdef HAVE_CONFIG_H 30#include "config.h" 31#endif 32 33#include <X11/extensions/Xv.h> 34#include "dix.h" 35#include "dixstruct.h" 36#include "fourcc.h" 37 38#include "savage_driver.h" 39#include "savage_streams.h" 40#include "savage_regs.h" 41#include "savage_bci.h" 42 43#define OFF_DELAY 200 /* milliseconds */ 44#define FREE_DELAY 60000 45 46#define OFF_TIMER 0x01 47#define FREE_TIMER 0x02 48#define CLIENT_VIDEO_ON 0x04 49 50#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 51 52void savageOUTREG( SavagePtr psav, unsigned long offset, unsigned long value ); 53 54static XF86VideoAdaptorPtr SavageSetupImageVideo(ScreenPtr); 55static void SavageInitOffscreenImages(ScreenPtr); 56static void SavageStopVideo(ScrnInfoPtr, pointer, Bool); 57static int SavageSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 58static int SavageGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); 59static void SavageQueryBestSize(ScrnInfoPtr, Bool, 60 short, short, short, short, unsigned int *, unsigned int *, pointer); 61static int SavagePutImage( ScrnInfoPtr, 62 short, short, short, short, short, short, short, short, 63 int, unsigned char*, short, short, Bool, RegionPtr, pointer, 64 DrawablePtr); 65static int SavageQueryImageAttributes(ScrnInfoPtr, 66 int, unsigned short *, unsigned short *, int *, int *); 67static void SavageFreeMemory(ScrnInfoPtr pScrn, void *mem_struct); 68 69void SavageResetVideo(ScrnInfoPtr pScrn); 70 71static void SavageSetColorKeyOld(ScrnInfoPtr pScrn); 72static void SavageSetColorKeyNew(ScrnInfoPtr pScrn); 73static void SavageSetColorKey2000(ScrnInfoPtr pScrn); 74static void (*SavageSetColorKey)(ScrnInfoPtr pScrn) = NULL; 75 76static void SavageSetColorOld(ScrnInfoPtr pScrn ); 77static void SavageSetColorNew(ScrnInfoPtr pScrn ); 78static void SavageSetColor2000(ScrnInfoPtr pScrn ); 79static void (*SavageSetColor)(ScrnInfoPtr pScrn ) = NULL; 80 81static void (*SavageInitStreams)(ScrnInfoPtr pScrn) = NULL; 82 83static void SavageDisplayVideoOld( 84 ScrnInfoPtr pScrn, int id, int offset, 85 short width, short height, int pitch, 86 int x1, int y1, int x2, int y2, 87 BoxPtr dstBox, 88 short src_w, short src_h, 89 short drw_w, short drw_h 90); 91static void SavageDisplayVideoNew( 92 ScrnInfoPtr pScrn, int id, int offset, 93 short width, short height, int pitch, 94 int x1, int y1, int x2, int y2, 95 BoxPtr dstBox, 96 short src_w, short src_h, 97 short drw_w, short drw_h 98); 99static void SavageDisplayVideo2000( 100 ScrnInfoPtr pScrn, int id, int offset, 101 short width, short height, int pitch, 102 int x1, int y1, int x2, int y2, 103 BoxPtr dstBox, 104 short src_w, short src_h, 105 short drw_w, short drw_h 106); 107static void (*SavageDisplayVideo)( 108 ScrnInfoPtr pScrn, int id, int offset, 109 short width, short height, int pitch, 110 int x1, int y1, int x2, int y2, 111 BoxPtr dstBox, 112 short src_w, short src_h, 113 short drw_w, short drw_h 114) = NULL; 115 116/*static void SavageBlockHandler(int, pointer, pointer, pointer);*/ 117 118#define XVTRACE 4 119 120#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 121 122static Atom xvColorKey, xvBrightness, xvContrast, xvSaturation, xvHue, xvInterpolation; 123 124/* client libraries expect an encoding */ 125static XF86VideoEncodingRec DummyEncoding[1] = 126{ 127 { 128 0, 129 "XV_IMAGE", 130 1024, 1024, 131 {1, 1} 132 } 133}; 134 135#define NUM_FORMATS 5 136 137static XF86VideoFormatRec Formats[NUM_FORMATS] = 138{ 139 {8, PseudoColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 140}; 141 142#define NUM_ATTRIBUTES 6 143 144static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = 145{ 146 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 147 {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, 148 {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}, 149 {XvSettable | XvGettable, 0, 255, "XV_SATURATION"}, 150 {XvSettable | XvGettable, -180, 180, "XV_HUE"}, 151 {XvSettable | XvGettable, 0, 1, "XV_VERTICAL_INTERPOLATION"} 152}; 153 154#define FOURCC_RV16 0x36315652 155#define FOURCC_RV15 0x35315652 156#define FOURCC_Y211 0x31313259 157 158/* 159 * For completeness sake, here is a cracking of the fourcc's I support. 160 * 161 * YUY2, packed 4:2:2, byte order: Y0 U0 Y1 V0 Y2 U2 Y3 V2 162 * Y211, packed 2:1:1, byte order: Y0 U0 Y2 V0 Y4 U2 Y6 V2 163 * YV12, planar 4:1:1, Y plane HxW, V plane H/2xW/2, U plane H/2xW/2 164 * I420, planar 4:1:1, Y plane HxW, U plane H/2xW/2, V plane H/2xW/2 165 * (I420 is also known as IYUV) 166 */ 167 168 169static XF86ImageRec Images[] = 170{ 171 XVIMAGE_YUY2, 172 XVIMAGE_YV12, 173 XVIMAGE_I420, 174 { 175 FOURCC_RV15, 176 XvRGB, 177 LSBFirst, 178 {'R','V','1','5', 179 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 180 16, 181 XvPacked, 182 1, 183 15, 0x001F, 0x03E0, 0x7C00, 184 0, 0, 0, 185 0, 0, 0, 186 0, 0, 0, 187 {'R','V','B',0, 188 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}, 189 XvTopToBottom 190 }, 191 { 192 FOURCC_RV16, 193 XvRGB, 194 LSBFirst, 195 {'R','V','1','6', 196 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 197 16, 198 XvPacked, 199 1, 200 16, 0x001F, 0x07E0, 0xF800, 201 0, 0, 0, 202 0, 0, 0, 203 0, 0, 0, 204 {'R','V','B',0, 205 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}, 206 XvTopToBottom 207 }, 208 { 209 FOURCC_Y211, 210 XvYUV, 211 LSBFirst, 212 {'Y','2','1','1', 213 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, 214 6, 215 XvPacked, 216 3, 217 0, 0, 0, 0 , 218 8, 8, 8, 219 2, 4, 4, 220 1, 1, 1, 221 {'Y','U','Y','V', 222 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}, 223 XvTopToBottom 224 } 225}; 226 227#define NUM_IMAGES (sizeof(Images)/sizeof(Images[0])) 228 229typedef struct { 230 int brightness; /* -128 .. 127 */ 231 CARD32 contrast; /* 0 .. 255 */ 232 CARD32 saturation; /* 0 .. 255 */ 233 int hue; /* -128 .. 127 */ 234 Bool interpolation; /* on/off */ 235 236 /*FBAreaPtr area;*/ 237 RegionRec clip; 238 CARD32 colorKey; 239 CARD32 videoStatus; 240 Time offTime; 241 Time freeTime; 242 int lastKnownPitch; 243 244 int size; 245 void *video_memory; 246 int video_offset; 247 248} SavagePortPrivRec, *SavagePortPrivPtr; 249 250 251#define GET_PORT_PRIVATE(pScrn) \ 252 (SavagePortPrivPtr)((SAVPTR(pScrn))->adaptor->pPortPrivates[0].ptr) 253 254static 255unsigned int GetBlendForFourCC( int id ) 256{ 257 switch( id ) { 258 case FOURCC_YUY2: 259 case FOURCC_YV12: /* shouldn't this be 4? */ 260 case FOURCC_I420: /* shouldn't this be 4? */ 261 return 1; 262 case FOURCC_Y211: 263 return 4; 264 case FOURCC_RV15: 265 return 3; 266 case FOURCC_RV16: 267 return 5; 268 default: 269 return 0; 270 } 271} 272 273static 274unsigned int GetBlendForFourCC2000( int id ) 275{ 276 switch( id ) { 277 case FOURCC_YUY2: 278 return 1; 279 case FOURCC_I420: 280 return 1; /* was 4 */ 281 case FOURCC_YV12: 282 return 1; /* was 4 */ 283 case FOURCC_Y211: 284 return 4; 285 case FOURCC_RV15: 286 return 3; 287 case FOURCC_RV16: 288 return 5; 289 default: 290 return 0; 291 } 292} 293 294 295void savageOUTREG( SavagePtr psav, unsigned long offset, unsigned long value ) 296{ 297 ErrorF( "MMIO %08lx, was %08lx, want %08lx,", 298 offset, (CARD32)MMIO_IN32( psav->MapBase, offset ), value ); 299 MMIO_OUT32( psav->MapBase, offset, value ); 300 ErrorF( " now %08lx\n", (CARD32)MMIO_IN32( psav->MapBase, offset ) ); 301} 302 303#if 0 304static void 305SavageClipVWindow(ScrnInfoPtr pScrn) 306{ 307 SavagePtr psav = SAVPTR(pScrn); 308 309 if( (psav->Chipset == S3_SAVAGE_MX) || 310 (psav->Chipset == S3_SUPERSAVAGE) ) { 311 if (psav->IsSecondary) { 312 OUTREG(SEC_STREAM2_WINDOW_SZ, 0); 313 } else if (psav->IsPrimary) { 314 OUTREG(SEC_STREAM_WINDOW_SZ, 0); 315 } else { 316 OUTREG(SEC_STREAM_WINDOW_SZ, 0); 317#if 0 318 OUTREG(SEC_STREAM2_WINDOW_SZ, 0); 319#endif 320 } 321 } else if (psav->Chipset == S3_SAVAGE2000) { 322 OUTREG(SEC_STREAM_WINDOW_SZ, 0); 323 } else { 324 OUTREG( SSTREAM_WINDOW_SIZE_REG, 1); 325 OUTREG( SSTREAM_WINDOW_START_REG, 0x03ff03ff); 326 } 327} 328#endif 329 330void SavageInitVideo(ScreenPtr pScreen) 331{ 332 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 333 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 334 XF86VideoAdaptorPtr newAdaptor = NULL; 335 SavagePtr psav = SAVPTR(pScrn); 336 int num_adaptors; 337 338 xf86ErrorFVerb(XVTRACE,"SavageInitVideo\n"); 339 if (S3_SAVAGE_MOBILE_SERIES(psav->Chipset)) 340 { 341 newAdaptor = SavageSetupImageVideo(pScreen); 342 SavageInitOffscreenImages(pScreen); 343 344 SavageInitStreams = SavageInitStreamsNew; 345 SavageSetColor = SavageSetColorNew; 346 SavageSetColorKey = SavageSetColorKeyNew; 347 SavageDisplayVideo = SavageDisplayVideoNew; 348 } 349 else if (psav->Chipset == S3_SAVAGE2000) 350 { 351 newAdaptor = SavageSetupImageVideo(pScreen); 352 SavageInitOffscreenImages(pScreen); 353 354 SavageInitStreams = SavageInitStreams2000; 355 SavageSetColor = SavageSetColor2000; 356 SavageSetColorKey = SavageSetColorKey2000; 357 SavageDisplayVideo = SavageDisplayVideo2000; 358 } 359 else 360 { 361 newAdaptor = SavageSetupImageVideo(pScreen); 362 SavageInitOffscreenImages(pScreen); 363 364 SavageInitStreams = SavageInitStreamsOld; 365 SavageSetColor = SavageSetColorOld; 366 SavageSetColorKey = SavageSetColorKeyOld; 367 SavageDisplayVideo = SavageDisplayVideoOld; 368 } 369 370 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 371 372 if(newAdaptor) { 373 if(!num_adaptors) { 374 num_adaptors = 1; 375 adaptors = &newAdaptor; 376 } else { 377 newAdaptors = /* need to free this someplace */ 378 xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); 379 if(newAdaptors) { 380 memcpy(newAdaptors, adaptors, num_adaptors * 381 sizeof(XF86VideoAdaptorPtr)); 382 newAdaptors[num_adaptors] = newAdaptor; 383 adaptors = newAdaptors; 384 num_adaptors++; 385 } 386 } 387 } 388 389 if(num_adaptors) 390 xf86XVScreenInit(pScreen, adaptors, num_adaptors); 391 392 if(newAdaptors) 393 xfree(newAdaptors); 394 395 if( newAdaptor ) 396 { 397 psav->videoFourCC = 0; 398 } 399} 400 401 402void SavageSetColorKeyOld(ScrnInfoPtr pScrn) 403{ 404 SavagePtr psav = SAVPTR(pScrn); 405 SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr; 406 int red, green, blue; 407 408 /* Here, we reset the colorkey and all the controls. */ 409 410 red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; 411 green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; 412 blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; 413 414 if( !pPriv->colorKey ) { 415 OUTREG( COL_CHROMA_KEY_CONTROL_REG, 0 ); 416 OUTREG( CHROMA_KEY_UPPER_BOUND_REG, 0 ); 417 OUTREG( BLEND_CONTROL_REG, 0 ); 418 } 419 else { 420 switch (pScrn->depth) { 421 case 8: 422 OUTREG( COL_CHROMA_KEY_CONTROL_REG, 423 0x37000000 | (pPriv->colorKey & 0xFF) ); 424 OUTREG( CHROMA_KEY_UPPER_BOUND_REG, 425 0x00000000 | (pPriv->colorKey & 0xFF) ); 426 break; 427 case 15: 428 OUTREG( COL_CHROMA_KEY_CONTROL_REG, 429 0x05000000 | (red<<19) | (green<<11) | (blue<<3) ); 430 OUTREG( CHROMA_KEY_UPPER_BOUND_REG, 431 0x00000000 | (red<<19) | (green<<11) | (blue<<3) ); 432 break; 433 case 16: 434 OUTREG( COL_CHROMA_KEY_CONTROL_REG, 435 0x16000000 | (red<<19) | (green<<10) | (blue<<3) ); 436 OUTREG( CHROMA_KEY_UPPER_BOUND_REG, 437 0x00020002 | (red<<19) | (green<<10) | (blue<<3) ); 438 break; 439 case 24: 440 OUTREG( COL_CHROMA_KEY_CONTROL_REG, 441 0x17000000 | (red<<16) | (green<<8) | (blue) ); 442 OUTREG( CHROMA_KEY_UPPER_BOUND_REG, 443 0x00000000 | (red<<16) | (green<<8) | (blue) ); 444 break; 445 } 446 447 /* We use destination colorkey */ 448 OUTREG( BLEND_CONTROL_REG, 0x05000000 ); 449 } 450} 451 452void SavageSetColorKeyNew(ScrnInfoPtr pScrn) 453{ 454 SavagePtr psav = SAVPTR(pScrn); 455 SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr; 456 int red, green, blue; 457 458 /* Here, we reset the colorkey and all the controls. */ 459 460 red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; 461 green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; 462 blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; 463 464 if( !pPriv->colorKey ) { 465 if (psav->IsSecondary) { 466 OUTREG( SEC_STREAM2_CKEY_LOW, 0 ); 467 OUTREG( SEC_STREAM2_CKEY_UPPER, 0 ); 468 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) )); 469 } else if (psav->IsPrimary) { 470 OUTREG( SEC_STREAM_CKEY_LOW, 0 ); 471 OUTREG( SEC_STREAM_CKEY_UPPER, 0 ); 472 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 )); 473 } else { 474 OUTREG( SEC_STREAM_CKEY_LOW, 0 ); 475 OUTREG( SEC_STREAM_CKEY_UPPER, 0 ); 476 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 )); 477#if 0 478 sleep(1); 479 OUTREG( SEC_STREAM2_CKEY_LOW, 0 ); 480 OUTREG( SEC_STREAM2_CKEY_UPPER, 0 ); 481 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) )); 482#endif 483 } 484 } 485 else { 486 switch (pScrn->depth) { 487 case 8: 488 if (psav->IsSecondary) { 489 OUTREG( SEC_STREAM2_CKEY_LOW, 490 0x47000000 | (pPriv->colorKey & 0xFF) ); 491 OUTREG( SEC_STREAM2_CKEY_UPPER, 492 0x47000000 | (pPriv->colorKey & 0xFF) ); 493 } else if (psav->IsPrimary) { 494 OUTREG( SEC_STREAM_CKEY_LOW, 495 0x47000000 | (pPriv->colorKey & 0xFF) ); 496 OUTREG( SEC_STREAM_CKEY_UPPER, 497 0x47000000 | (pPriv->colorKey & 0xFF) ); 498 } else { 499 OUTREG( SEC_STREAM_CKEY_LOW, 500 0x47000000 | (pPriv->colorKey & 0xFF) ); 501 OUTREG( SEC_STREAM_CKEY_UPPER, 502 0x47000000 | (pPriv->colorKey & 0xFF) ); 503#if 0 504 OUTREG( SEC_STREAM2_CKEY_LOW, 505 0x47000000 | (pPriv->colorKey & 0xFF) ); 506 OUTREG( SEC_STREAM2_CKEY_UPPER, 507 0x47000000 | (pPriv->colorKey & 0xFF) ); 508#endif 509 } 510 break; 511 case 15: 512 if (psav->IsSecondary) { 513 OUTREG( SEC_STREAM2_CKEY_LOW, 514 0x45000000 | (red<<19) | (green<<11) | (blue<<3) ); 515 OUTREG( SEC_STREAM2_CKEY_UPPER, 516 0x45000000 | (red<<19) | (green<<11) | (blue<<3) ); 517 } else if (psav->IsPrimary) { 518 OUTREG( SEC_STREAM_CKEY_LOW, 519 0x45000000 | (red<<19) | (green<<11) | (blue<<3) ); 520 OUTREG( SEC_STREAM_CKEY_UPPER, 521 0x45000000 | (red<<19) | (green<<11) | (blue<<3) ); 522 } else { 523 OUTREG( SEC_STREAM_CKEY_LOW, 524 0x45000000 | (red<<19) | (green<<11) | (blue<<3) ); 525 OUTREG( SEC_STREAM_CKEY_UPPER, 526 0x45000000 | (red<<19) | (green<<11) | (blue<<3) ); 527#if 0 528 OUTREG( SEC_STREAM2_CKEY_LOW, 529 0x45000000 | (red<<19) | (green<<11) | (blue<<3) ); 530 OUTREG( SEC_STREAM2_CKEY_UPPER, 531 0x45000000 | (red<<19) | (green<<11) | (blue<<3) ); 532#endif 533 } 534 break; 535 case 16: 536 if (psav->IsSecondary) { 537 OUTREG( SEC_STREAM2_CKEY_LOW, 538 0x46000000 | (red<<19) | (green<<10) | (blue<<3) ); 539 OUTREG( SEC_STREAM2_CKEY_UPPER, 540 0x46020002 | (red<<19) | (green<<10) | (blue<<3) ); 541 } else if (psav->IsPrimary) { 542 OUTREG( SEC_STREAM_CKEY_LOW, 543 0x46000000 | (red<<19) | (green<<10) | (blue<<3) ); 544 OUTREG( SEC_STREAM_CKEY_UPPER, 545 0x46020002 | (red<<19) | (green<<10) | (blue<<3) ); 546 } else { 547 OUTREG( SEC_STREAM_CKEY_LOW, 548 0x46000000 | (red<<19) | (green<<10) | (blue<<3) ); 549 OUTREG( SEC_STREAM_CKEY_UPPER, 550 0x46020002 | (red<<19) | (green<<10) | (blue<<3) ); 551#if 0 552 OUTREG( SEC_STREAM2_CKEY_LOW, 553 0x46000000 | (red<<19) | (green<<10) | (blue<<3) ); 554 OUTREG( SEC_STREAM2_CKEY_UPPER, 555 0x46020002 | (red<<19) | (green<<10) | (blue<<3) ); 556#endif 557 } 558 break; 559 case 24: 560 if (psav->IsSecondary) { 561 OUTREG( SEC_STREAM2_CKEY_LOW, 562 0x47000000 | (red<<16) | (green<<8) | (blue) ); 563 OUTREG( SEC_STREAM2_CKEY_UPPER, 564 0x47000000 | (red<<16) | (green<<8) | (blue) ); 565 } else if (psav->IsPrimary) { 566 OUTREG( SEC_STREAM_CKEY_LOW, 567 0x47000000 | (red<<16) | (green<<8) | (blue) ); 568 OUTREG( SEC_STREAM_CKEY_UPPER, 569 0x47000000 | (red<<16) | (green<<8) | (blue) ); 570 } else { 571 OUTREG( SEC_STREAM_CKEY_LOW, 572 0x47000000 | (red<<16) | (green<<8) | (blue) ); 573 OUTREG( SEC_STREAM_CKEY_UPPER, 574 0x47000000 | (red<<16) | (green<<8) | (blue) ); 575#if 0 576 OUTREG( SEC_STREAM2_CKEY_LOW, 577 0x47000000 | (red<<16) | (green<<8) | (blue) ); 578 OUTREG( SEC_STREAM2_CKEY_UPPER, 579 0x47000000 | (red<<16) | (green<<8) | (blue) ); 580#endif 581 } 582 break; 583 } 584 585 /* We assume destination colorkey */ 586 if (psav->IsSecondary) { 587 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) )); 588 } else if (psav->IsPrimary) { 589 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 )); 590 } else { 591 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 )); 592#if 0 593 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) )); 594#endif 595 } 596 } 597} 598 599void SavageSetColorKey2000(ScrnInfoPtr pScrn) 600{ 601 SavagePtr psav = SAVPTR(pScrn); 602 SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr; 603 int red, green, blue; 604 605 /* Here, we reset the colorkey and all the controls. */ 606 607 red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; 608 green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; 609 blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; 610 611 if( !pPriv->colorKey ) { 612 OUTREG( SEC_STREAM_CKEY_LOW, 0); 613 OUTREG( SEC_STREAM_CKEY_UPPER, 0); 614 OUTREG( BLEND_CONTROL, (8 << 2)); 615 } 616 else { 617 switch (pScrn->depth) { 618 case 8: 619 OUTREG( SEC_STREAM_CKEY_LOW, 620 0x47000000 | (pPriv->colorKey & 0xFF) ); 621 OUTREG( SEC_STREAM_CKEY_UPPER, 622 (pPriv->colorKey & 0xFF) ); 623 break; 624 case 15: 625 OUTREG( SEC_STREAM_CKEY_LOW, 626 0x45000000 | (red<<19) | (green<<11) | (blue<<3) ); 627 OUTREG( SEC_STREAM_CKEY_UPPER, 628 (red<<19) | (green<<11) | (blue<<3) ); 629 break; 630 case 16: 631 OUTREG( SEC_STREAM_CKEY_LOW, 632 0x46000000 | (red<<19) | (green<<10) | (blue<<3) ); 633 OUTREG( SEC_STREAM_CKEY_UPPER, 634 (red<<19) | (green<<10) | (blue<<3) ); 635 break; 636 case 24: 637 OUTREG( SEC_STREAM_CKEY_LOW, 638 0x47000000 | (red<<16) | (green<<8) | (blue) ); 639 OUTREG( SEC_STREAM_CKEY_UPPER, 640 (red<<16) | (green<<8) | (blue) ); 641 break; 642 } 643 644 /* We assume destination colorkey */ 645 OUTREG( BLEND_CONTROL, INREG(BLEND_CONTROL) | (8 << 2)); 646 } 647} 648 649void SavageSetColorOld( ScrnInfoPtr pScrn ) 650{ 651 SavagePtr psav = SAVPTR(pScrn); 652 SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr; 653 654 xf86ErrorFVerb(XVTRACE, "bright %d, contrast %d, saturation %d, hue %d\n", 655 pPriv->brightness, (int)pPriv->contrast, (int)pPriv->saturation, pPriv->hue ); 656 657 if( 658 (psav->videoFourCC == FOURCC_RV15) || 659 (psav->videoFourCC == FOURCC_RV16) 660 ) 661 { 662 OUTREG( COLOR_ADJUSTMENT_REG, 0 ); 663 } 664 else 665 { 666 /* Change 0..255 into 0..15 */ 667 long sat = pPriv->saturation * 16 / 256; 668 double hue = pPriv->hue * 0.017453292; 669 unsigned long hs1 = ((long)(sat * cos(hue))) & 0x1f; 670 unsigned long hs2 = ((long)(sat * sin(hue))) & 0x1f; 671 672 OUTREG( COLOR_ADJUSTMENT_REG, 673 0x80008000 | 674 (pPriv->brightness + 128) | 675 ((pPriv->contrast & 0xf8) << (12-7)) | 676 (hs1 << 16) | 677 (hs2 << 24) 678 ); 679 680 } 681} 682 683void SavageSetColorNew( ScrnInfoPtr pScrn ) 684{ 685 SavagePtr psav = SAVPTR(pScrn); 686 SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr; 687 688 /* Brightness/contrast/saturation/hue computations. */ 689 690 double k, dk1, dk2, dk3, dk4, dk5, dk6, dk7, dkb; 691 int k1, k2, k3, k4, k5, k6, k7, kb; 692 double s = pPriv->saturation / 128.0; 693 double h = pPriv->hue * 0.017453292; 694 unsigned long assembly1, assembly2, assembly3; 695 696 xf86ErrorFVerb(XVTRACE, "bright %d, contrast %d, saturation %d, hue %d\n", 697 pPriv->brightness, (int)pPriv->contrast, (int)pPriv->saturation, pPriv->hue ); 698 699 if( psav->videoFourCC == FOURCC_Y211 ) 700 k = 1.0; /* YUV */ 701 else 702 k = 1.14; /* YCrCb */ 703 704 /* 705 * The S3 documentation must be wrong for k4 and k5. Their default 706 * values, which they hardcode in their Windows driver, have the 707 * opposite sign from the results in the register spec. 708 */ 709 710 dk1 = k * pPriv->contrast; 711 dk2 = 64.0 * 1.371 * k * s * cos(h); 712 dk3 = -64.0 * 1.371 * k * s * sin(h); 713 dk4 = -128.0 * k * s * (0.698 * cos(h) - 0.336 * sin(h)); 714 dk5 = -128.0 * k * s * (0.698 * sin(h) + 0.336 * cos(h)); 715 dk6 = 64.0 * 1.732 * k * s * sin(h); /* == k3 / 1.26331, right? */ 716 dk7 = 64.0 * 1.732 * k * s * cos(h); /* == k2 / -1.26331, right? */ 717 dkb = 128.0 * pPriv->brightness + 64.0; 718 if( psav->videoFourCC != FOURCC_Y211 ) 719 dkb -= dk1 * 14.0; 720 721 k1 = (int)(dk1+0.5) & 0x1ff; 722 k2 = (int)(dk2+0.5) & 0x1ff; 723 k3 = (int)(dk3+0.5) & 0x1ff; 724 assembly1 = (k3<<18) | (k2<<9) | k1; 725 xf86ErrorFVerb(XVTRACE+1, "CC1 = %08lx ", assembly1 ); 726 727 k4 = (int)(dk4+0.5) & 0x1ff; 728 k5 = (int)(dk5+0.5) & 0x1ff; 729 k6 = (int)(dk6+0.5) & 0x1ff; 730 assembly2 = (k6<<18) | (k5<<9) | k4; 731 xf86ErrorFVerb(XVTRACE+1, "CC2 = %08lx ", assembly2 ); 732 733 k7 = (int)(dk7+0.5) & 0x1ff; 734 kb = (int)(dkb+0.5) & 0xffff; 735 assembly3 = (kb<<9) | k7; 736 xf86ErrorFVerb(XVTRACE+1, "CC3 = %08lx\n", assembly3 ); 737 738 if (psav->IsSecondary) { 739 OUTREG( SEC_STREAM2_COLOR_CONVERT1, assembly1 ); 740 OUTREG( SEC_STREAM2_COLOR_CONVERT2, assembly2 ); 741 OUTREG( SEC_STREAM2_COLOR_CONVERT3, assembly3 ); 742 } else if (psav->IsPrimary) { 743 OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly1 ); 744 OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly2 ); 745 OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly3 ); 746 } else { 747 OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly1 ); 748 OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly2 ); 749 OUTREG( SEC_STREAM_COLOR_CONVERT3, assembly3 ); 750#if 0 751 sleep(1); 752 OUTREG( SEC_STREAM2_COLOR_CONVERT1, assembly1 ); 753 OUTREG( SEC_STREAM2_COLOR_CONVERT2, assembly2 ); 754 OUTREG( SEC_STREAM2_COLOR_CONVERT3, assembly3 ); 755#endif 756 } 757} 758 759void SavageSetColor2000( ScrnInfoPtr pScrn ) 760{ 761 SavagePtr psav = SAVPTR(pScrn); 762 SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr; 763 764 /* Brightness/contrast/saturation/hue computations. */ 765 766 double k, yb, dk1, dk2, dk3, dk4, dk5, dk6, dk7, dkb; 767 int k1, k2, k3, k4, k5, k6, k7, kb; 768 double s = pPriv->saturation / 10000.0; 769 double h = pPriv->hue * 0.017453292; 770 unsigned long assembly1, assembly2, assembly3, assembly4; 771 unsigned long brightness = pPriv->brightness; 772 773 xf86ErrorFVerb(XVTRACE, "bright %d, contrast %d, saturation %d, hue %d\n", 774 pPriv->brightness, (int)pPriv->contrast, (int)pPriv->saturation, pPriv->hue ); 775 776 if( psav->videoFourCC == FOURCC_Y211 ) { 777 k = 1.0;/* YUV */ 778 yb = 0.0; 779 } else { 780 k = 1.1;/* YCrCb */ 781 yb = 14.0; 782 } 783 784 dk1 = 128 * k * (pPriv->contrast / 10000.0); 785 if (dk1 < 0) 786 dk1 -= 0.5; 787 else 788 dk1 += 0.5; 789 dk2 = 64.0 * 1.371 * k * s * cos(h); 790 if (dk2 < 0) 791 dk2 -= 0.5; 792 else 793 dk2 += 0.5; 794 dk3 = -64.0 * 1.371 * k * s * sin(h); 795 if (dk3 < 0) 796 dk3 -= 0.5; 797 else 798 dk3 += 0.5; 799 dk4 = -128.0 * k * s * (0.698 * cos(h) + 0.336 * sin(h)); 800 if (dk4 < 0) 801 dk4 -= 0.5; 802 else 803 dk4 += 0.5; 804 dk5 = 128.0 * k * s * (0.698 * sin(h) - 0.336 * cos(h)); 805 if (dk5 < 0) 806 dk5 -= 0.5; 807 else 808 dk5 += 0.5; 809 dk6 = 64.0 * 1.732 * k * s * sin(h); 810 if (dk6 < 0) 811 dk6 -= 0.5; 812 else 813 dk6 += 0.5; 814 dk7 = 64.0 * 1.732 * k * s * cos(h); 815 if (dk7 < 0) 816 dk7 -= 0.5; 817 else 818 dk7 += 0.5; 819 820 if (pPriv->brightness <= 0) 821 brightness = pPriv->brightness * 200 / 750 - 200; 822 else 823 brightness = (pPriv->brightness - 750) * 200 / (10000 - 750); 824 dkb = 128 * (brightness - (k * pPriv->contrast * yb / 10000.0) + 0.5); 825 if (dkb < 0) 826 dkb -= 0.5; 827 else 828 dkb += 0.5; 829 830 k1 = (int)(dk1 /*+0.5*/) & 0x1ff; 831 k2 = (int)(dk2 /*+0.5*/) & 0x1ff; 832 assembly1 = (k2<<16) | k1; 833 834 k3 = (int)(dk3 /*+0.5*/) & 0x1ff; 835 k4 = (int)(dk4 /*+0.5*/) & 0x1ff; 836 assembly2 = (k4<<16) | k3; 837 838 k5 = (int)(dk5 /*+0.5*/) & 0x1ff; 839 k6 = (int)(dk6 /*+0.5*/) & 0x1ff; 840 assembly3 = (k6<<16) | k5; 841 842 k7 = (int)(dk7 /*+0.5*/) & 0x1ff; 843 kb = (int)(dkb /*+0.5*/) & 0xffff; 844 assembly4 = (kb<<16) | k7; 845 846#if 0 847 assembly1 = 0x640092; 848 assembly2 = 0x19a0000; 849 assembly3 = 0x001cf; 850 assembly4 = 0xf8ca007e; 851#endif 852 853 OUTREG( SEC_STREAM_COLOR_CONVERT0_2000, assembly1 ); 854 OUTREG( SEC_STREAM_COLOR_CONVERT1_2000, assembly2 ); 855 OUTREG( SEC_STREAM_COLOR_CONVERT2_2000, assembly3 ); 856 OUTREG( SEC_STREAM_COLOR_CONVERT3_2000, assembly4 ); 857 858} 859 860void SavageResetVideo(ScrnInfoPtr pScrn) 861{ 862 xf86ErrorFVerb(XVTRACE,"SavageResetVideo\n"); 863 SavageSetColor( pScrn ); 864 SavageSetColorKey( pScrn ); 865} 866 867 868static XF86VideoAdaptorPtr 869SavageSetupImageVideo(ScreenPtr pScreen) 870{ 871 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 872 SavagePtr psav = SAVPTR(pScrn); 873 XF86VideoAdaptorPtr adapt; 874 SavagePortPrivPtr pPriv; 875 876 xf86ErrorFVerb(XVTRACE,"SavageSetupImageVideo\n"); 877 878 if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + 879 sizeof(SavagePortPrivRec) + 880 sizeof(DevUnion)))) 881 return NULL; 882 883 adapt->type = XvWindowMask | XvInputMask | XvImageMask; 884 adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 885 adapt->name = "Savage Streams Engine"; 886 adapt->nEncodings = 1; 887 adapt->pEncodings = DummyEncoding; 888 adapt->nFormats = NUM_FORMATS; 889 adapt->pFormats = Formats; 890 adapt->nPorts = 1; 891 adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 892 pPriv = (SavagePortPrivPtr)(&adapt->pPortPrivates[1]); 893 adapt->pPortPrivates[0].ptr = (pointer)(pPriv); 894 adapt->pAttributes = Attributes; 895 adapt->nImages = NUM_IMAGES; 896 adapt->nAttributes = NUM_ATTRIBUTES; 897 adapt->pImages = Images; 898 adapt->PutVideo = NULL; 899 adapt->PutStill = NULL; 900 adapt->GetVideo = NULL; 901 adapt->GetStill = NULL; 902 adapt->StopVideo = SavageStopVideo; 903 adapt->SetPortAttribute = SavageSetPortAttribute; 904 adapt->GetPortAttribute = SavageGetPortAttribute; 905 adapt->QueryBestSize = SavageQueryBestSize; 906 adapt->PutImage = SavagePutImage; 907 adapt->QueryImageAttributes = SavageQueryImageAttributes; 908 909 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 910 xvContrast = MAKE_ATOM("XV_CONTRAST"); 911 xvColorKey = MAKE_ATOM("XV_COLORKEY"); 912 xvHue = MAKE_ATOM("XV_HUE"); 913 xvSaturation = MAKE_ATOM("XV_SATURATION"); 914 /* interpolation option only available on "old" streams */ 915 xvInterpolation = MAKE_ATOM("XV_VERTICAL_INTERPOLATION"); 916 917 pPriv->colorKey = 918 (1 << pScrn->offset.red) | 919 (1 << pScrn->offset.green) | 920 (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue); 921 pPriv->videoStatus = 0; 922 pPriv->brightness = 0; 923 pPriv->contrast = 128; 924 pPriv->saturation = 128; 925#if 0 926 /* 927 * The S3 driver has these values for some of the chips. I have yet 928 * to find any Savage where these make sense. 929 */ 930 pPriv->brightness = 64; 931 pPriv->contrast = 16; 932 pPriv->saturation = 128; 933#endif 934 pPriv->hue = 0; 935 pPriv->lastKnownPitch = 0; 936 937 pPriv->interpolation = FALSE; 938 939 /* gotta uninit this someplace */ 940 REGION_NULL(pScreen, &pPriv->clip); 941 942 psav->adaptor = adapt; 943 944 #if 0 945 psav->BlockHandler = pScreen->BlockHandler; 946 pScreen->BlockHandler = SavageBlockHandler; 947 #endif 948 949 return adapt; 950} 951 952 953/* SavageClipVideo - 954 955 Takes the dst box in standard X BoxRec form (top and left 956 edges inclusive, bottom and right exclusive). The new dst 957 box is returned. The source boundaries are given (x1, y1 958 inclusive, x2, y2 exclusive) and returned are the new source 959 boundaries in 16.16 fixed point. 960*/ 961 962static void 963SavageClipVideo( 964 BoxPtr dst, 965 INT32 *x1, 966 INT32 *x2, 967 INT32 *y1, 968 INT32 *y2, 969 BoxPtr extents, /* extents of the clip region */ 970 INT32 width, 971 INT32 height 972){ 973 INT32 vscale, hscale, delta; 974 int diff; 975 976 hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1); 977 vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1); 978 979 *x1 <<= 16; *x2 <<= 16; 980 *y1 <<= 16; *y2 <<= 16; 981 982 diff = extents->x1 - dst->x1; 983 if(diff > 0) { 984 dst->x1 = extents->x1; 985 *x1 += diff * hscale; 986 } 987 diff = dst->x2 - extents->x2; 988 if(diff > 0) { 989 dst->x2 = extents->x2; 990 *x2 -= diff * hscale; 991 } 992 diff = extents->y1 - dst->y1; 993 if(diff > 0) { 994 dst->y1 = extents->y1; 995 *y1 += diff * vscale; 996 } 997 diff = dst->y2 - extents->y2; 998 if(diff > 0) { 999 dst->y2 = extents->y2; 1000 *y2 -= diff * vscale; 1001 } 1002 1003 if(*x1 < 0) { 1004 diff = (- *x1 + hscale - 1)/ hscale; 1005 dst->x1 += diff; 1006 *x1 += diff * hscale; 1007 } 1008 delta = *x2 - (width << 16); 1009 if(delta > 0) { 1010 diff = (delta + hscale - 1)/ hscale; 1011 dst->x2 -= diff; 1012 *x2 -= diff * hscale; 1013 } 1014 if(*y1 < 0) { 1015 diff = (- *y1 + vscale - 1)/ vscale; 1016 dst->y1 += diff; 1017 *y1 += diff * vscale; 1018 } 1019 delta = *y2 - (height << 16); 1020 if(delta > 0) { 1021 diff = (delta + vscale - 1)/ vscale; 1022 dst->y2 -= diff; 1023 *y2 -= diff * vscale; 1024 } 1025} 1026 1027static void 1028SavageStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) 1029{ 1030 SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data; 1031 /*SavagePtr psav = SAVPTR(pScrn); */ 1032 1033 xf86ErrorFVerb(XVTRACE,"SavageStopVideo\n"); 1034 1035 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 1036 1037 if(shutdown) { 1038 /*SavageClipVWindow(pScrn);*/ 1039 SavageStreamsOff( pScrn ); 1040 if (pPriv->video_memory != NULL) { 1041 SavageFreeMemory(pScrn, pPriv->video_memory); 1042 pPriv->video_memory = NULL; 1043 } 1044 pPriv->videoStatus = 0; 1045 } else { 1046 if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 1047 pPriv->videoStatus |= OFF_TIMER; 1048 pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 1049 } 1050 } 1051} 1052 1053 1054static int 1055SavageSetPortAttribute( 1056 ScrnInfoPtr pScrn, 1057 Atom attribute, 1058 INT32 value, 1059 pointer data 1060){ 1061 SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data; 1062 SavagePtr psav = SAVPTR(pScrn); 1063 1064 if(attribute == xvColorKey) { 1065 pPriv->colorKey = value; 1066 if( psav->videoFlags & VF_STREAMS_ON) 1067 SavageSetColorKey( pScrn ); 1068 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 1069 } 1070 else if( attribute == xvBrightness) { 1071 if((value < -128) || (value > 127)) 1072 return BadValue; 1073 pPriv->brightness = value; 1074 if( psav->videoFlags & VF_STREAMS_ON) 1075 SavageSetColor( pScrn ); 1076 } 1077 else if( attribute == xvContrast) { 1078 if((value < 0) || (value > 255)) 1079 return BadValue; 1080 pPriv->contrast = value; 1081 if( psav->videoFlags & VF_STREAMS_ON) 1082 SavageSetColor( pScrn ); 1083 } 1084 else if( attribute == xvSaturation) { 1085 if((value < 0) || (value > 255)) 1086 return BadValue; 1087 pPriv->saturation = value; 1088 if( psav->videoFlags & VF_STREAMS_ON) 1089 SavageSetColor( pScrn ); 1090 } 1091 else if( attribute == xvHue) { 1092 if((value < -180) || (value > 180)) 1093 return BadValue; 1094 pPriv->hue = value; 1095 if( psav->videoFlags & VF_STREAMS_ON) 1096 SavageSetColor( pScrn ); 1097 } 1098 else if( attribute == xvInterpolation) { 1099 if((value < 0) || (value > 1)) 1100 return BadValue; 1101 if (value == 1) 1102 pPriv->interpolation = TRUE; 1103 else 1104 pPriv->interpolation = FALSE; 1105 } 1106 else 1107 return BadMatch; 1108 1109 return Success; 1110} 1111 1112 1113static int 1114SavageGetPortAttribute( 1115 ScrnInfoPtr pScrn, 1116 Atom attribute, 1117 INT32 *value, 1118 pointer data 1119){ 1120 SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data; 1121 1122 if(attribute == xvColorKey) { 1123 *value = pPriv->colorKey; 1124 } 1125 else if( attribute == xvBrightness ) { 1126 *value = pPriv->brightness; 1127 } 1128 else if( attribute == xvContrast ) { 1129 *value = pPriv->contrast; 1130 } 1131 else if( attribute == xvHue ) { 1132 *value = pPriv->hue; 1133 } 1134 else if( attribute == xvSaturation ) { 1135 *value = pPriv->saturation; 1136 } 1137 else if( attribute == xvInterpolation ) { 1138 *value = pPriv->interpolation; 1139 } 1140 else return BadMatch; 1141 1142 return Success; 1143} 1144 1145static void 1146SavageQueryBestSize( 1147 ScrnInfoPtr pScrn, 1148 Bool motion, 1149 short vid_w, short vid_h, 1150 short drw_w, short drw_h, 1151 unsigned int *p_w, unsigned int *p_h, 1152 pointer data 1153){ 1154 /* What are the real limits for the Savage? */ 1155 1156 *p_w = drw_w; 1157 *p_h = drw_h; 1158 1159 if(*p_w > 16384) *p_w = 16384; 1160} 1161 1162/* SavageCopyPlanarDataBCI() causes artifacts on the screen when used on savage4. 1163 * It's probably something with the BCI. Maybe we need a waitforidle() or 1164 * something... 1165 */ 1166static void 1167SavageCopyPlanarDataBCI( 1168 ScrnInfoPtr pScrn, 1169 unsigned char *srcY, /* Y */ 1170 unsigned char *srcV, /* V */ 1171 unsigned char *srcU, /* U */ 1172 unsigned char *dst, 1173 int srcPitch, int srcPitch2, 1174 int dstPitch, 1175 int h,int w) 1176{ 1177 SavagePtr psav = SAVPTR(pScrn); 1178 /* half of the dest buffer for copying the YVU data to it ??? */ 1179 unsigned char *dstCopy = (unsigned char *)(((unsigned long)dst 1180 + 2 * srcPitch * h 1181 + 0x0f) & ~0x0f); 1182 /* for pixel transfer */ 1183 unsigned long offsetY = (unsigned long)dstCopy - (unsigned long)psav->FBBase; 1184 unsigned long offsetV = offsetY + srcPitch * h; 1185 unsigned long offsetU = offsetV + srcPitch2 * (h>>1); 1186 unsigned long dstOffset = (unsigned long)dst - (unsigned long)psav->FBBase; 1187 int i; 1188 1189 BCI_GET_PTR; 1190 1191 /* copy Y planar */ 1192 for (i=0;i<srcPitch * h;i++) { 1193 dstCopy[i] = srcY[i]; 1194 } 1195 1196 /* copy V planar */ 1197 dstCopy = dstCopy + srcPitch * h; 1198 for (i=0;i<srcPitch2 * (h>>1);i++) { 1199 dstCopy[i] = srcV[i]; 1200 } 1201 1202 /* copy U planar */ 1203 dstCopy = dstCopy + srcPitch2 * (h>>1); 1204 for (i=0;i<srcPitch2 * (h>>1);i++) { 1205 dstCopy[i] = srcU[i]; 1206 } 1207 1208 /* 1209 * Transfer pixel data from one memory location to another location 1210 * and reformat the data during the transfer 1211 * a. program BCI51 to specify the source information 1212 * b. program BCI52 to specify the destination information 1213 * c. program BCI53 to specify the source dimensions 1214 * d. program BCI54 to specify the destination dimensions 1215 * e. (if the data is in YCbCr420 format)program BCI55,BCI56,BCI57 to 1216 * locations of the Y,Cb,and Cr data 1217 * f. program BCI50(command=011) to specify the formatting options and 1218 * kick off the transfer 1219 * this command can be used for color space conversion(YCbCr to RGB) 1220 * or for oversampling, but not for both simultaneously. it can also be 1221 * used to do mastered image transfer when the source is tiled 1222 */ 1223 1224 w = (w+0xf)&0xff0; 1225 psav->WaitQueue(psav,11); 1226 BCI_SEND(0x96070051); 1227 BCI_SEND(offsetY); 1228 1229 BCI_SEND(dstOffset); 1230 1231 BCI_SEND(((h-1)<<16)|((w-1)>>3)); 1232 1233 BCI_SEND(dstPitch >> 3); 1234 1235 1236 BCI_SEND(offsetU); 1237 BCI_SEND(offsetV); 1238 1239 BCI_SEND((srcPitch2 << 16)| srcPitch2); 1240 1241 BCI_SEND(0x96010050); 1242 BCI_SEND(0x00200003 | srcPitch); 1243 BCI_SEND(0xC0170000); 1244} 1245 1246static void 1247SavageCopyData( 1248 unsigned char *src, 1249 unsigned char *dst, 1250 int srcPitch, 1251 int dstPitch, 1252 int h, 1253 int w 1254){ 1255 w <<= 1; 1256 while(h--) { 1257 memcpy(dst, src, w); 1258 src += srcPitch; 1259 dst += dstPitch; 1260 } 1261} 1262 1263static void 1264SavageCopyPlanarData( 1265 unsigned char *src1, /* Y */ 1266 unsigned char *src2, /* V */ 1267 unsigned char *src3, /* U */ 1268 unsigned char *dst1, 1269 int srcPitch, 1270 int srcPitch2, 1271 int dstPitch, 1272 int h, 1273 int w 1274){ 1275 CARD32 *dst = (CARD32*)dst1; 1276 int i, j; 1277 1278 dstPitch >>= 2; 1279 w >>= 1; 1280 1281 for(j = 0; j < h; j++) { 1282 for(i = 0; i < w; i++) { 1283/* Shouldn't this be 'if LITTLEENDIAN'? */ 1284#if 1 1285 dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) | 1286 (src3[i] << 8) | (src2[i] << 24); 1287#else 1288 dst[i] = (src1[i << 1] << 24) | (src1[(i << 1) + 1] << 8) | 1289 (src3[i] << 0) | (src2[i] << 16); 1290#endif 1291 } 1292 dst += dstPitch; 1293 src1 += srcPitch; 1294 if(j & 1) { 1295 src2 += srcPitch2; 1296 src3 += srcPitch2; 1297 } 1298 } 1299} 1300 1301static void 1302SavageVideoSave(ScreenPtr pScreen, ExaOffscreenArea *area) 1303{ 1304 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1305 SavagePtr psav = SAVPTR(pScrn); 1306 SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr; 1307 1308 if (pPriv->video_memory == area) 1309 pPriv->video_memory = NULL; 1310} 1311 1312static CARD32 1313SavageAllocateMemory( 1314 ScrnInfoPtr pScrn, 1315 void **mem_struct, 1316 int size 1317){ 1318 ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; 1319 SavagePtr psav = SAVPTR(pScrn); 1320 int offset = 0; 1321 1322 if (psav->useEXA) { 1323 ExaOffscreenArea *area = *mem_struct; 1324 1325 if (area != NULL) { 1326 if (area->size >= size) 1327 return area->offset; 1328 1329 exaOffscreenFree(pScrn->pScreen, area); 1330 } 1331 1332 area = exaOffscreenAlloc(pScrn->pScreen, size, 64, TRUE, SavageVideoSave, 1333 NULL); 1334 *mem_struct = area; 1335 if (area == NULL) 1336 return 0; 1337 offset = area->offset; 1338 } 1339 1340 if (!psav->useEXA) { 1341 FBLinearPtr linear = *mem_struct; 1342 int cpp = pScrn->bitsPerPixel / 8; 1343 1344 /* XAA allocates in units of pixels at the screen bpp, so adjust size 1345 * appropriately. 1346 */ 1347 size = (size + cpp - 1) / cpp; 1348 1349 if (linear) { 1350 if(linear->size >= size) 1351 return linear->offset * cpp; 1352 1353 if(xf86ResizeOffscreenLinear(linear, size)) 1354 return linear->offset * cpp; 1355 1356 xf86FreeOffscreenLinear(linear); 1357 } 1358 1359 linear = xf86AllocateOffscreenLinear(pScreen, size, 16, 1360 NULL, NULL, NULL); 1361 *mem_struct = linear; 1362 1363 if (!linear) { 1364 int max_size; 1365 1366 xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, 1367 PRIORITY_EXTREME); 1368 1369 if(max_size < size) 1370 return 0; 1371 1372 xf86PurgeUnlockedOffscreenAreas(pScreen); 1373 linear = xf86AllocateOffscreenLinear(pScreen, size, 16, 1374 NULL, NULL, NULL); 1375 *mem_struct = linear; 1376 if (!linear) 1377 return 0; 1378 } 1379 offset = linear->offset * cpp; 1380 } 1381 1382 return offset; 1383} 1384 1385static void 1386SavageFreeMemory( 1387 ScrnInfoPtr pScrn, 1388 void *mem_struct 1389){ 1390 SavagePtr psav = SAVPTR(pScrn); 1391 1392 if (psav->useEXA) { 1393 ExaOffscreenArea *area = mem_struct; 1394 1395 if (area != NULL) 1396 exaOffscreenFree(pScrn->pScreen, area); 1397 } 1398 if (!psav->useEXA) { 1399 FBLinearPtr linear = mem_struct; 1400 1401 if (linear != NULL) 1402 xf86FreeOffscreenLinear(linear); 1403 } 1404} 1405 1406static void 1407SavageSetBlend(ScrnInfoPtr pScrn, int id) 1408{ 1409 SavagePtr psav = SAVPTR(pScrn); 1410 1411 if ( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) 1412 { 1413 psav->blendBase = GetBlendForFourCC( id ); 1414 xf86ErrorFVerb(XVTRACE+1,"Format %4.4s, blend is %08x\n", (char*)&id, psav->blendBase ); 1415 if (psav->IsSecondary) { 1416 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) )); 1417 } else if (psav->IsPrimary) { 1418 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 )); 1419 } else { 1420 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 )); 1421#if 0 1422 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) )); 1423#endif 1424 } 1425 } else if (psav->Chipset == S3_SAVAGE2000) { 1426 psav->blendBase = GetBlendForFourCC2000( id ); 1427 xf86ErrorFVerb(XVTRACE+1,"Format %4.4s, blend is %08x\n", (char*)&id, psav->blendBase ); 1428 if (id != FOURCC_YV12) 1429 OUTREG( BLEND_CONTROL, 1430 ((psav->blendBase << 24) | (8 << 2) /*| 0x20000000*/)); 1431 else 1432 OUTREG( BLEND_CONTROL, 1433 ((psav->blendBase << 24) | (8 << 2) /*| 0x10000000*/)); 1434 } 1435 1436 psav->videoFourCC = id; 1437} 1438 1439static void 1440SavageDisplayVideoOld( 1441 ScrnInfoPtr pScrn, 1442 int id, 1443 int offset, 1444 short width, short height, 1445 int pitch, 1446 int x1, int y1, int x2, int y2, 1447 BoxPtr dstBox, 1448 short src_w, short src_h, 1449 short drw_w, short drw_h 1450){ 1451 SavagePtr psav = SAVPTR(pScrn); 1452 vgaHWPtr hwp = VGAHWPTR(pScrn); 1453 SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr; 1454 /*DisplayModePtr mode = pScrn->currentMode;*/ 1455 int vgaCRIndex, vgaCRReg, vgaIOBase; 1456 CARD32 ssControl; 1457 int scalratio; 1458 1459 1460 vgaIOBase = hwp->IOBase; 1461 vgaCRIndex = vgaIOBase + 4; 1462 vgaCRReg = vgaIOBase + 5; 1463#if 0 1464 if ( psav->videoFourCC != id ) { 1465 SavageSetBlend(pScrn,id); 1466 SavageResetVideo(pScrn); 1467 } 1468#endif 1469 if( psav->videoFourCC != id ) 1470 SavageStreamsOff(pScrn); 1471 1472 if( !psav->videoFlags & VF_STREAMS_ON ) 1473 { 1474 SavageSetBlend(pScrn,id); 1475 SavageStreamsOn(pScrn); 1476 SavageResetVideo(pScrn); 1477 } 1478 1479 if (S3_MOBILE_TWISTER_SERIES(psav->Chipset) 1480 && psav->FPExpansion) { 1481 drw_w = (((float)(drw_w * psav->XExp1)/(float)psav->XExp2)+1); 1482 drw_h = (float)(drw_h * psav->YExp1)/(float)psav->YExp2+1; 1483 dstBox->x1 = (float)(dstBox->x1 * psav->XExp1)/(float)psav->XExp2; 1484 dstBox->y1 = (float)(dstBox->y1 * psav->YExp1)/(float)psav->YExp2; 1485 1486 dstBox->x1 += psav->displayXoffset; 1487 dstBox->y1 += psav->displayYoffset; 1488 } 1489 1490 /* 1491 * Process horizontal scaling 1492 * upscaling and downscaling smaller than 2:1 controled by MM8198 1493 * MM8190 controls downscaling mode larger than 2:1 1494 */ 1495 scalratio = 0; 1496 ssControl = 0; 1497 1498 if (src_w >= (drw_w * 2)) { 1499 if (src_w < (drw_w * 4)) { 1500 scalratio = HSCALING(2,1); 1501 } else if (src_w < (drw_w * 8)) { 1502 ssControl |= HDSCALE_4; 1503 } else if (src_w < (drw_w * 16)) { 1504 ssControl |= HDSCALE_8; 1505 } else if (src_w < (drw_w * 32)) { 1506 ssControl |= HDSCALE_16; 1507 } else if (src_w < (drw_w * 64)) { 1508 ssControl |= HDSCALE_32; 1509 } else 1510 ssControl |= HDSCALE_64; 1511 } else 1512 scalratio = HSCALING(src_w,drw_w); 1513 1514 ssControl |= src_w; 1515 /*ssControl |= (1 << 24);*/ 1516 ssControl |= (GetBlendForFourCC(psav->videoFourCC) << 24); 1517 /* Wait for VBLANK. */ 1518 VerticalRetraceWait(); 1519 OUTREG(SSTREAM_CONTROL_REG, ssControl); 1520 if (scalratio) 1521 OUTREG(SSTREAM_STRETCH_REG,scalratio); 1522 1523 /* Calculate vertical scale factor. */ 1524 OUTREG(SSTREAM_VINITIAL_REG, 0 ); 1525 /*OUTREG(SSTREAM_VSCALE_REG, (src_h << 15) / drw_h );*/ 1526 OUTREG(SSTREAM_VSCALE_REG, VSCALING(src_h,drw_h)); 1527 1528 /* Set surface location and stride. */ 1529 OUTREG(SSTREAM_FBADDR0_REG, (offset + (x1>>15)) & (0x1ffffff & ~BASE_PAD) ); 1530 OUTREG(SSTREAM_FBADDR1_REG, 0); 1531 OUTREG(SSTREAM_STRIDE_REG, pitch & 0xfff ); 1532 1533 OUTREG(SSTREAM_WINDOW_START_REG, OS_XY(dstBox->x1, dstBox->y1) ); 1534 OUTREG(SSTREAM_WINDOW_SIZE_REG, OS_WH(dstBox->x2-dstBox->x1, 1535 dstBox->y2-dstBox->y1)); 1536 1537 /* 1538 * MM81E8:Secondary Stream Source Line Count 1539 * bit_0~10: # of lines in the source image (before scaling) 1540 * bit_15 = 1: Enable vertical interpolation 1541 * 0: Line duplicaion 1542 */ 1543 /* 1544 * Vertical Interpolation is very bandwidth intensive. Some savages can't 1545 * seem to handle it. Default is line doubling. --AGD 1546 */ 1547 if (pPriv->interpolation) { 1548 if (src_w * 16 <= 0x3300) { 1549 OUTREG(SSTREAM_LINES_REG, 0x8000 | src_h ); 1550 OUTREG(FIFO_CONTROL, (INREG(FIFO_CONTROL) + 1)); 1551 } else { 1552 OUTREG(SSTREAM_LINES_REG, src_h ); 1553 } 1554 } else { 1555 OUTREG(SSTREAM_LINES_REG, src_h ); 1556 } 1557 1558#if 0 1559 /* Set color key on primary. */ 1560 1561 SavageSetColorKey( pScrn ); 1562#endif 1563 1564 /* Set FIFO L2 on second stream. */ 1565 1566 if( pPriv->lastKnownPitch != pitch ) 1567 { 1568 unsigned char cr92; 1569 1570 pPriv->lastKnownPitch = pitch; 1571 1572 pitch = (pitch + 7) / 8; 1573 VGAOUT8(vgaCRIndex, 0x92); 1574 cr92 = VGAIN8(vgaCRReg); 1575 VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80); 1576 VGAOUT8(vgaCRIndex, 0x93); 1577 if (psav->bTiled && (( drw_h > src_h) || (drw_w > src_w))) 1578 VGAOUT8(vgaCRReg, pitch | 0xf); 1579 else 1580 VGAOUT8(vgaCRReg, pitch); 1581 } 1582} 1583 1584static void 1585SavageDisplayVideoNew( 1586 ScrnInfoPtr pScrn, 1587 int id, 1588 int offset, 1589 short width, short height, 1590 int pitch, 1591 int x1, int y1, int x2, int y2, 1592 BoxPtr dstBox, 1593 short src_w, short src_h, 1594 short drw_w, short drw_h 1595){ 1596 SavagePtr psav = SAVPTR(pScrn); 1597 vgaHWPtr hwp = VGAHWPTR(pScrn); 1598 /*DisplayModePtr mode = pScrn->currentMode;*/ 1599 SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr; 1600 int vgaCRIndex, vgaCRReg, vgaIOBase; 1601 1602 1603 vgaIOBase = hwp->IOBase; 1604 vgaCRIndex = vgaIOBase + 4; 1605 vgaCRReg = vgaIOBase + 5; 1606#if 0 1607 if ( psav->videoFourCC != id ) { 1608 SavageSetBlend(pScrn,id); 1609 SavageResetVideo(pScrn); 1610 } 1611#endif 1612 if( psav->videoFourCC != id ) 1613 SavageStreamsOff(pScrn); 1614 1615 if( !psav->videoFlags & VF_STREAMS_ON ) 1616 { 1617 SavageSetBlend(pScrn,id); 1618 SavageStreamsOn(pScrn); 1619 SavageResetVideo(pScrn); 1620 } 1621 1622 /* Calculate horizontal and vertical scale factors. */ 1623 1624 if ( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) && 1625 (psav->DisplayType == MT_LCD) && 1626 !psav->CrtOnly && 1627 !psav->TvOn) 1628 { 1629 drw_w = (drw_w * psav->XExp1)/psav->XExp2 + 1; 1630 drw_h = (drw_h * psav->YExp1)/psav->YExp2 + 1; 1631 dstBox->x1 = (dstBox->x1 * psav->XExp1)/psav->XExp2; 1632 dstBox->y1 = (dstBox->y1 * psav->YExp1)/psav->YExp2; 1633 dstBox->x1 += psav->displayXoffset; 1634 dstBox->y1 += psav->displayYoffset; 1635 } 1636 1637 if (psav->IsSecondary) { 1638 OUTREG(SEC_STREAM2_HSCALING, 1639 ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF )); 1640 /* BUGBUG need to add 00040000 if src stride > 2048 */ 1641 OUTREG(SEC_STREAM2_VSCALING, 1642 ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF )); 1643 } else if (psav->IsPrimary) { 1644 OUTREG(SEC_STREAM_HSCALING, 1645 ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF )); 1646 /* BUGBUG need to add 00040000 if src stride > 2048 */ 1647 OUTREG(SEC_STREAM_VSCALING, 1648 ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF )); 1649 } else { 1650 OUTREG(SEC_STREAM_HSCALING, 1651 ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF )); 1652 /* BUGBUG need to add 00040000 if src stride > 2048 */ 1653 OUTREG(SEC_STREAM_VSCALING, 1654 ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF )); 1655#if 0 1656 OUTREG(SEC_STREAM2_HSCALING, 1657 ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF )); 1658 /* BUGBUG need to add 00040000 if src stride > 2048 */ 1659 OUTREG(SEC_STREAM2_VSCALING, 1660 ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF )); 1661#endif 1662 } 1663 1664 /* 1665 * Set surface location and stride. We use x1>>15 because all surfaces 1666 * are 2 bytes/pixel. 1667 */ 1668 1669 if (psav->IsSecondary) { 1670 OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15)) 1671 & (0x7ffffff & ~BASE_PAD)); 1672 OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff ); 1673 OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) ); 1674 OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16) 1675 | (dstBox->x2-dstBox->x1) ); 1676 } else if (psav->IsPrimary) { 1677 OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15)) 1678 & (0x7ffffff & ~BASE_PAD)); 1679 OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff ); 1680 OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) ); 1681 OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16) 1682 | (dstBox->x2-dstBox->x1) ); 1683 } else { 1684 OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15)) 1685 & (0x7ffffff & ~BASE_PAD)); 1686 OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff ); 1687 OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) ); 1688 OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16) 1689 | (dstBox->x2-dstBox->x1) ); 1690#if 0 1691 OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15)) 1692 & (0x7ffffff & ~BASE_PAD)); 1693 OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff ); 1694 OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) ); 1695 OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16) 1696 | (dstBox->x2-dstBox->x1) ); 1697#endif 1698 } 1699 1700#if 0 1701 /* Set color key on primary. */ 1702 1703 SavageSetColorKey( pScrn ); 1704#endif 1705 1706 /* Set FIFO L2 on second stream. */ 1707 /* Is CR92 shadowed for crtc2? -- AGD */ 1708 if( pPriv->lastKnownPitch != pitch ) 1709 { 1710 unsigned char cr92; 1711 1712 pPriv->lastKnownPitch = pitch; 1713 pitch = (pitch + 7) / 8 - 4; 1714 VGAOUT8(vgaCRIndex, 0x92); 1715 cr92 = VGAIN8(vgaCRReg); 1716 VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80); 1717 VGAOUT8(vgaCRIndex, 0x93); 1718 VGAOUT8(vgaCRReg, pitch); 1719 } 1720} 1721 1722static void 1723SavageDisplayVideo2000( 1724 ScrnInfoPtr pScrn, 1725 int id, 1726 int offset, 1727 short width, short height, 1728 int pitch, 1729 int x1, int y1, int x2, int y2, 1730 BoxPtr dstBox, 1731 short src_w, short src_h, 1732 short drw_w, short drw_h 1733){ 1734 SavagePtr psav = SAVPTR(pScrn); 1735 vgaHWPtr hwp = VGAHWPTR(pScrn); 1736 /*DisplayModePtr mode = pScrn->currentMode;*/ 1737 SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr; 1738 int vgaCRIndex, vgaCRReg, vgaIOBase; 1739 CARD32 addr0, addr1, addr2; 1740 1741 vgaIOBase = hwp->IOBase; 1742 vgaCRIndex = vgaIOBase + 4; 1743 vgaCRReg = vgaIOBase + 5; 1744 1745 1746 if( psav->videoFourCC != id ) 1747 SavageStreamsOff(pScrn); 1748 1749 if( !psav->videoFlags & VF_STREAMS_ON ) 1750 { 1751 SavageSetBlend(pScrn,id); 1752 SavageStreamsOn(pScrn); 1753 SavageResetVideo(pScrn); 1754 } 1755 1756 if (src_w > drw_w) 1757 OUTREG(SEC_STREAM_SRC_START_2000, 0); 1758 else 1759 OUTREG(SEC_STREAM_SRC_START_2000, SRCSTART(x1, y1)); 1760 1761 /*OUTREG(SEC_STREAM_SRC_SIZE_2000, SRCSIZE(src_w, src_h));*/ 1762 OUTREG(SEC_STREAM_SRC_SIZE_2000, 1763 SRCSIZE((dstBox->x2-dstBox->x1), (dstBox->y2-dstBox->y1))); 1764 /* 1765 buffersize = (src_w * src_h * 2) / 4096; 1766 OUTREG(SEC_STREAM_BUFFERSIZE_2000, (buffersize & 0xffffff) << 12); 1767 */ 1768 1769 /*SavageResetVideo(pScrn);*/ 1770 1771 if( src_w > drw_w ) 1772 OUTREG(SEC_STREAM_HSCALE_NORMALIZE, HSCALING_NORMALIZE(drw_w,src_w)); 1773 else 1774 OUTREG(SEC_STREAM_HSCALE_NORMALIZE, (2048 << 16)); 1775 1776 /* Calculate horizontal and vertical scale factors. */ 1777 if ((src_w > drw_w) || (src_h > drw_h)) 1778 OUTREG(SEC_STREAM_HSCALING, (HSCALING_2000(src_w,drw_w)) | 0x01000000); 1779 else 1780 OUTREG(SEC_STREAM_HSCALING, HSCALING_2000(src_w,drw_w)); 1781 1782 OUTREG(SEC_STREAM_VSCALING, VSCALING_2000(src_h,drw_h)); 1783 1784 /* 1785 * Set surface location and stride. We use x1>>15 because all surfaces 1786 * are 2 bytes/pixel. 1787 */ 1788 1789 addr0 = offset + (x1>>15); /* Y in YCbCr420 */ 1790 addr1 = addr0 + (width * height); /* Cb in in YCbCr420 */ 1791 addr2 = addr1 + ((width * height) / 4); /* Cr in in YCbCr420 */ 1792 OUTREG(SEC_STREAM_FBUF_ADDR0, (addr0) & (0x3fffff & ~BASE_PAD)); 1793#if 0 1794 OUTREG(SEC_STREAM_FBUF_ADDR1, (addr1) & (0x3fffff & ~BASE_PAD)); 1795 OUTREG(SEC_STREAM_FBUF_ADDR2, (addr2) & (0x3fffff & ~BASE_PAD)); 1796#endif 1797 1798 OUTREG(SEC_STREAM_WINDOW_START, XY_2000(dstBox->x1,dstBox->y1)); 1799 OUTREG(SEC_STREAM_WINDOW_SZ, 1800 WH_2000((dstBox->x2-dstBox->x1),(dstBox->y2-dstBox->y1))); 1801 1802 /*pitch = width * 2;*/ 1803 OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff); 1804#if 0 1805 /* Y stride + CbCr stride in YCbCr420 */ 1806 OUTREG(SEC_STREAM_STRIDE, (pitch & 0xfff) + ((pitch & 0xfff) << 15)); 1807#endif 1808 1809#if 0 1810 /* Set color key on primary. */ 1811 1812 SavageSetColorKey2000( pScrn ); 1813#endif 1814 1815#if 0 1816 /* Set FIFO L2 on second stream. */ 1817 if( pPriv->lastKnownPitch != pitch ) 1818 { 1819 unsigned char cr92; 1820 1821 pPriv->lastKnownPitch = pitch; 1822 pitch = (pitch + 7) / 8 - 4; 1823 VGAOUT8(vgaCRIndex, 0x92); 1824 cr92 = VGAIN8(vgaCRReg); 1825 VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80); 1826 VGAOUT8(vgaCRIndex, 0x93); 1827 VGAOUT8(vgaCRReg, pitch); 1828 } 1829#endif 1830} 1831 1832static int 1833SavagePutImage( 1834 ScrnInfoPtr pScrn, 1835 short src_x, short src_y, 1836 short drw_x, short drw_y, 1837 short src_w, short src_h, 1838 short drw_w, short drw_h, 1839 int id, unsigned char* buf, 1840 short width, short height, 1841 Bool sync, 1842 RegionPtr clipBoxes, pointer data, 1843 DrawablePtr pDraw 1844){ 1845 SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data; 1846 SavagePtr psav = SAVPTR(pScrn); 1847 ScreenPtr pScreen = pScrn->pScreen; 1848 INT32 x1, x2, y1, y2; 1849 unsigned char *dst_start; 1850 int pitch, new_size, offset, offsetV=0, offsetU=0; 1851 int srcPitch, srcPitch2=0, dstPitch; 1852 int top, left, npixels, nlines; 1853 BoxRec dstBox; 1854 CARD32 tmp; 1855/* xf86ErrorFVerb(XVTRACE,"SavagePutImage\n"); */ 1856 if(drw_w > 16384) drw_w = 16384; 1857 1858 /* Clip */ 1859 x1 = src_x; 1860 x2 = src_x + src_w; 1861 y1 = src_y; 1862 y2 = src_y + src_h; 1863 1864 dstBox.x1 = drw_x; 1865 dstBox.x2 = drw_x + drw_w; 1866 dstBox.y1 = drw_y; 1867 dstBox.y2 = drw_y + drw_h; 1868 1869 SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2, 1870 REGION_EXTENTS(pScreen, clipBoxes), width, height); 1871 1872 drw_w = dstBox.x2 - dstBox.x1; 1873 drw_h = dstBox.y2 - dstBox.y1; 1874 src_w = ( x2 - x1 ) >> 16; 1875 src_h = ( y2 - y1 ) >> 16; 1876 1877 if((x1 >= x2) || (y1 >= y2)) 1878 return Success; 1879 1880 dstBox.x1 -= pScrn->frameX0; 1881 dstBox.x2 -= pScrn->frameX0; 1882 dstBox.y1 -= pScrn->frameY0; 1883 dstBox.y2 -= pScrn->frameY0; 1884 1885 pitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3; 1886 1887 dstPitch = ((width << 1) + 15) & ~15; 1888 /*new_h = ((dstPitch * height) + pitch - 1) / pitch;*/ 1889 new_size = dstPitch * height; 1890 1891 switch(id) { 1892 case FOURCC_Y211: /* Y211 */ 1893 srcPitch = width; 1894 break; 1895 case FOURCC_YV12: /* YV12 */ 1896 srcPitch = (width + 3) & ~3; 1897 offsetV = srcPitch * height; 1898 srcPitch2 = ((width >> 1) + 3) & ~3; 1899 offsetU = (srcPitch2 * (height >> 1)) + offsetV; 1900 break; 1901 case FOURCC_I420: 1902 srcPitch = (width + 3) & ~3; 1903 offsetU = srcPitch * height; 1904 srcPitch2 = ((width >> 1) + 3) & ~3; 1905 offsetV = (srcPitch2 * (height >> 1)) + offsetU; 1906 break; 1907 case FOURCC_RV15: /* RGB15 */ 1908 case FOURCC_RV16: /* RGB16 */ 1909 case FOURCC_YUY2: /* YUY2 */ 1910 default: 1911 srcPitch = (width << 1); 1912 break; 1913 } 1914 1915/* if(!(pPriv->area = SavageAllocateMemory(pScrn, pPriv->area, new_h))) 1916 return BadAlloc;*/ 1917 pPriv->video_offset = SavageAllocateMemory(pScrn, &pPriv->video_memory, 1918 new_size); 1919 if (pPriv->video_offset == 0) 1920 return BadAlloc; 1921 1922 /* copy data */ 1923 top = y1 >> 16; 1924 left = (x1 >> 16) & ~1; 1925 npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; 1926 left <<= 1; 1927 1928 offset = (pPriv->video_offset) + (top * dstPitch); 1929 /*offset = pPriv->area->box.y1 * psav->lDelta;*/ 1930 dst_start = (psav->FBBase + ((offset + left) & ~BASE_PAD)); 1931 1932 switch(id) { 1933 case FOURCC_YV12: /* YV12 */ 1934 case FOURCC_I420: 1935 top &= ~1; 1936 tmp = ((top >> 1) * srcPitch2) + (left >> 2); 1937 offsetU += tmp; 1938 offsetV += tmp; 1939 nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; 1940 if (S3_SAVAGE4_SERIES(psav->Chipset) && psav->BCIforXv) { 1941 SavageCopyPlanarDataBCI( 1942 pScrn, 1943 buf + (top * srcPitch) + (left >> 1), 1944 buf + offsetV, 1945 buf + offsetU, 1946 dst_start, srcPitch, srcPitch2, dstPitch, nlines, npixels); 1947 } else { 1948 SavageCopyPlanarData( 1949 buf + (top * srcPitch) + (left >> 1), 1950 buf + offsetV, 1951 buf + offsetU, 1952 dst_start, srcPitch, srcPitch2, dstPitch, nlines, npixels); 1953 } 1954 break; 1955 case FOURCC_Y211: /* Y211 */ 1956 case FOURCC_RV15: /* RGB15 */ 1957 case FOURCC_RV16: /* RGB16 */ 1958 case FOURCC_YUY2: /* YUY2 */ 1959 default: 1960 buf += (top * srcPitch) + left; 1961 nlines = ((y2 + 0xffff) >> 16) - top; 1962 SavageCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels); 1963 break; 1964 } 1965 1966 /* We need to enable the video before we draw the chroma color. 1967 Otherwise, we get blue flashes. */ 1968 1969 SavageDisplayVideo(pScrn, id, offset, width, height, dstPitch, 1970 x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 1971 1972 /* update cliplist */ 1973 if(!REGION_EQUAL(pScreen, &pPriv->clip, clipBoxes)) { 1974 REGION_COPY(pScreen, &pPriv->clip, clipBoxes); 1975 /* draw these */ 1976 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 1977 1978 } 1979 1980 pPriv->videoStatus = CLIENT_VIDEO_ON; 1981 1982 return Success; 1983} 1984 1985static int 1986SavageQueryImageAttributes( 1987 ScrnInfoPtr pScrn, 1988 int id, 1989 unsigned short *w, unsigned short *h, 1990 int *pitches, int *offsets 1991){ 1992 int size, tmp; 1993 1994 if(*w > 1024) *w = 1024; 1995 if(*h > 1024) *h = 1024; 1996 1997 *w = (*w + 1) & ~1; 1998 if(offsets) offsets[0] = 0; 1999 2000 switch(id) { 2001 case FOURCC_IA44: 2002 if (pitches) pitches[0]=*w; 2003 size=(*w)*(*h); 2004 break; 2005 case FOURCC_Y211: 2006 size = *w << 2; 2007 if(pitches) pitches[0] = size; 2008 size *= *h; 2009 break; 2010 case FOURCC_YV12: 2011 case FOURCC_I420: 2012 *h = (*h + 1) & ~1; 2013 size = (*w + 3) & ~3; 2014 if(pitches) pitches[0] = size; 2015 size *= *h; 2016 if(offsets) offsets[1] = size; 2017 tmp = ((*w >> 1) + 3) & ~3; 2018 if(pitches) pitches[1] = pitches[2] = tmp; 2019 tmp *= (*h >> 1); 2020 size += tmp; 2021 if(offsets) offsets[2] = size; 2022 size += tmp; 2023 break; 2024 case FOURCC_RV15: /* RGB15 */ 2025 case FOURCC_RV16: /* RGB16 */ 2026 case FOURCC_YUY2: 2027 default: 2028 size = *w << 1; 2029 if(pitches) pitches[0] = size; 2030 size *= *h; 2031 break; 2032 } 2033 2034 return size; 2035} 2036 2037/****************** Offscreen stuff ***************/ 2038 2039typedef struct { 2040 void *surface_memory; 2041 Bool isOn; 2042} OffscreenPrivRec, * OffscreenPrivPtr; 2043 2044static int 2045SavageAllocateSurface( 2046 ScrnInfoPtr pScrn, 2047 int id, 2048 unsigned short w, 2049 unsigned short h, 2050 XF86SurfacePtr surface 2051){ 2052 int offset, size; 2053 int pitch, fbpitch, numlines; 2054 void *surface_memory = NULL; 2055 OffscreenPrivPtr pPriv; 2056 2057 if((w > 1024) || (h > 1024)) 2058 return BadAlloc; 2059 2060 w = (w + 1) & ~1; 2061 pitch = ((w << 1) + 15) & ~15; 2062 fbpitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3; 2063 numlines = ((pitch * h) + fbpitch - 1) / fbpitch; 2064 size = pitch * h; 2065 2066 offset = SavageAllocateMemory(pScrn, &surface_memory, size); 2067 if (offset == 0) 2068 return BadAlloc; 2069 2070 surface->width = w; 2071 surface->height = h; 2072 2073 if(!(surface->pitches = xalloc(sizeof(int)))) { 2074 SavageFreeMemory(pScrn, surface_memory); 2075 return BadAlloc; 2076 } 2077 if(!(surface->offsets = xalloc(sizeof(int)))) { 2078 xfree(surface->pitches); 2079 SavageFreeMemory(pScrn, surface_memory); 2080 return BadAlloc; 2081 } 2082 if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) { 2083 xfree(surface->pitches); 2084 xfree(surface->offsets); 2085 SavageFreeMemory(pScrn, surface_memory); 2086 return BadAlloc; 2087 } 2088 2089 pPriv->surface_memory = surface_memory; 2090 pPriv->isOn = FALSE; 2091 2092 surface->pScrn = pScrn; 2093 surface->id = id; 2094 surface->pitches[0] = pitch; 2095 surface->offsets[0] = offset; /*area->box.y1 * fbpitch;*/ 2096 surface->devPrivate.ptr = (pointer)pPriv; 2097 2098 return Success; 2099} 2100 2101static int 2102SavageStopSurface( 2103 XF86SurfacePtr surface 2104){ 2105 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 2106 xf86ErrorFVerb(XVTRACE,"SavageStopSurface\n"); 2107 2108 if(pPriv->isOn) { 2109 /*SavagePtr psav = SAVPTR(surface->pScrn);*/ 2110 /*SavageClipVWindow(surface->pScrn);*/ 2111 SavageStreamsOff( surface->pScrn ); 2112 pPriv->isOn = FALSE; 2113 } 2114 2115 return Success; 2116} 2117 2118 2119static int 2120SavageFreeSurface( 2121 XF86SurfacePtr surface 2122){ 2123 ScrnInfoPtr pScrn = surface->pScrn; 2124 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 2125 2126 if(pPriv->isOn) 2127 SavageStopSurface(surface); 2128 SavageFreeMemory(pScrn, pPriv->surface_memory); 2129 xfree(surface->pitches); 2130 xfree(surface->offsets); 2131 xfree(surface->devPrivate.ptr); 2132 2133 return Success; 2134} 2135 2136static int 2137SavageGetSurfaceAttribute( 2138 ScrnInfoPtr pScrn, 2139 Atom attribute, 2140 INT32 *value 2141){ 2142 return SavageGetPortAttribute(pScrn, attribute, value, 2143 (pointer)(GET_PORT_PRIVATE(pScrn))); 2144} 2145 2146static int 2147SavageSetSurfaceAttribute( 2148 ScrnInfoPtr pScrn, 2149 Atom attribute, 2150 INT32 value 2151){ 2152 return SavageSetPortAttribute(pScrn, attribute, value, 2153 (pointer)(GET_PORT_PRIVATE(pScrn))); 2154} 2155 2156 2157static int 2158SavageDisplaySurface( 2159 XF86SurfacePtr surface, 2160 short src_x, short src_y, 2161 short drw_x, short drw_y, 2162 short src_w, short src_h, 2163 short drw_w, short drw_h, 2164 RegionPtr clipBoxes 2165){ 2166 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 2167 ScrnInfoPtr pScrn = surface->pScrn; 2168 ScreenPtr pScreen = pScrn->pScreen; 2169 SavagePortPrivPtr portPriv = GET_PORT_PRIVATE(pScrn); 2170 INT32 x1, y1, x2, y2; 2171 BoxRec dstBox; 2172 xf86ErrorFVerb(XVTRACE,"SavageDisplaySurface\n"); 2173 2174 x1 = src_x; 2175 x2 = src_x + src_w; 2176 y1 = src_y; 2177 y2 = src_y + src_h; 2178 2179 dstBox.x1 = drw_x; 2180 dstBox.x2 = drw_x + drw_w; 2181 dstBox.y1 = drw_y; 2182 dstBox.y2 = drw_y + drw_h; 2183 2184 SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2, 2185 REGION_EXTENTS(pScreen, clipBoxes), 2186 surface->width, surface->height); 2187 2188 if((x1 >= x2) || (y1 >= y2)) 2189 return Success; 2190 2191 dstBox.x1 -= pScrn->frameX0; 2192 dstBox.x2 -= pScrn->frameX0; 2193 dstBox.y1 -= pScrn->frameY0; 2194 dstBox.y2 -= pScrn->frameY0; 2195 2196 SavageDisplayVideo(pScrn, surface->id, surface->offsets[0], 2197 surface->width, surface->height, surface->pitches[0], 2198 x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 2199 2200 xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes); 2201 2202 pPriv->isOn = TRUE; 2203#if 0 2204 if(portPriv->videoStatus & CLIENT_VIDEO_ON) { 2205 REGION_EMPTY(pScreen, &portPriv->clip); 2206 UpdateCurrentTime(); 2207 portPriv->videoStatus = FREE_TIMER; 2208 portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 2209 } 2210#endif 2211 2212 return Success; 2213} 2214 2215 2216static void 2217SavageInitOffscreenImages(ScreenPtr pScreen) 2218{ 2219 XF86OffscreenImagePtr offscreenImages; 2220 SavagePtr psav = SAVPTR(xf86Screens[pScreen->myNum]); 2221 2222 /* need to free this someplace */ 2223 if (!psav->offscreenImages) { 2224 if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) 2225 return; 2226 psav->offscreenImages = offscreenImages; 2227 } else { 2228 offscreenImages = psav->offscreenImages; 2229 } 2230 2231 offscreenImages[0].image = &Images[0]; 2232 offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | 2233 VIDEO_CLIP_TO_VIEWPORT; 2234 offscreenImages[0].alloc_surface = SavageAllocateSurface; 2235 offscreenImages[0].free_surface = SavageFreeSurface; 2236 offscreenImages[0].display = SavageDisplaySurface; 2237 offscreenImages[0].stop = SavageStopSurface; 2238 offscreenImages[0].setAttribute = SavageSetSurfaceAttribute; 2239 offscreenImages[0].getAttribute = SavageGetSurfaceAttribute; 2240 offscreenImages[0].max_width = 1024; 2241 offscreenImages[0].max_height = 1024; 2242 offscreenImages[0].num_attributes = NUM_ATTRIBUTES; 2243 offscreenImages[0].attributes = Attributes; 2244 2245 xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); 2246} 2247 2248