savage_video.c revision 8697ee19
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 + dstPitch * 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 memcpy(dstCopy, srcY, srcPitch * h); 1193 1194 /* copy V planar */ 1195 dstCopy = dstCopy + srcPitch * h; 1196 memcpy(dstCopy, srcV, srcPitch2 * (h>>1)); 1197 1198 /* copy U planar */ 1199 dstCopy = dstCopy + srcPitch2 * (h>>1); 1200 memcpy(dstCopy, srcU, srcPitch2 * (h>>1)); 1201 1202 /* 1203 * Transfer pixel data from one memory location to another location 1204 * and reformat the data during the transfer 1205 * a. program BCI51 to specify the source information 1206 * b. program BCI52 to specify the destination information 1207 * c. program BCI53 to specify the source dimensions 1208 * d. program BCI54 to specify the destination dimensions 1209 * e. (if the data is in YCbCr420 format)program BCI55,BCI56,BCI57 to 1210 * locations of the Y,Cb,and Cr data 1211 * f. program BCI50(command=011) to specify the formatting options and 1212 * kick off the transfer 1213 * this command can be used for color space conversion(YCbCr to RGB) 1214 * or for oversampling, but not for both simultaneously. it can also be 1215 * used to do mastered image transfer when the source is tiled 1216 */ 1217 1218 w = (w+0xf)&0xff0; 1219 psav->WaitQueue(psav,11); 1220 BCI_SEND(0x96070051); 1221 BCI_SEND(offsetY); 1222 1223 BCI_SEND(dstOffset); 1224 1225 BCI_SEND(((h-1)<<16)|((w-1)>>3)); 1226 1227 BCI_SEND(dstPitch >> 3); 1228 1229 1230 BCI_SEND(offsetU); 1231 BCI_SEND(offsetV); 1232 1233 BCI_SEND((srcPitch2 << 16)| srcPitch2); 1234 1235 BCI_SEND(0x96010050); 1236 BCI_SEND(0x00200003 | srcPitch); 1237 BCI_SEND(0xC0170000); 1238} 1239 1240static void 1241SavageCopyData( 1242 unsigned char *src, 1243 unsigned char *dst, 1244 int srcPitch, 1245 int dstPitch, 1246 int h, 1247 int w 1248){ 1249 w <<= 1; 1250 if (w == srcPitch && w == dstPitch) { 1251 memcpy(dst, src, w * h); 1252 } else 1253 while(h--) { 1254 memcpy(dst, src, w); 1255 src += srcPitch; 1256 dst += dstPitch; 1257 } 1258} 1259 1260static void 1261SavageCopyPlanarData( 1262 unsigned char *src1, /* Y */ 1263 unsigned char *src2, /* V */ 1264 unsigned char *src3, /* U */ 1265 unsigned char *dst1, 1266 int srcPitch, 1267 int srcPitch2, 1268 int dstPitch, 1269 int h, 1270 int w 1271){ 1272 CARD32 *dst = (CARD32*)dst1; 1273 int i, j; 1274 1275 dstPitch >>= 2; 1276 w >>= 1; 1277 1278 for(j = 0; j < h; j++) { 1279 for(i = 0; i < w; i++) { 1280/* Shouldn't this be 'if LITTLEENDIAN'? */ 1281#if 1 1282 dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) | 1283 (src3[i] << 8) | (src2[i] << 24); 1284#else 1285 dst[i] = (src1[i << 1] << 24) | (src1[(i << 1) + 1] << 8) | 1286 (src3[i] << 0) | (src2[i] << 16); 1287#endif 1288 } 1289 dst += dstPitch; 1290 src1 += srcPitch; 1291 if(j & 1) { 1292 src2 += srcPitch2; 1293 src3 += srcPitch2; 1294 } 1295 } 1296} 1297 1298static void 1299SavageVideoSave(ScreenPtr pScreen, ExaOffscreenArea *area) 1300{ 1301 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1302 SavagePtr psav = SAVPTR(pScrn); 1303 SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr; 1304 1305 if (pPriv->video_memory == area) 1306 pPriv->video_memory = NULL; 1307} 1308 1309static CARD32 1310SavageAllocateMemory( 1311 ScrnInfoPtr pScrn, 1312 void **mem_struct, 1313 int size 1314){ 1315 ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; 1316 SavagePtr psav = SAVPTR(pScrn); 1317 int offset = 0; 1318 1319 if (psav->useEXA) { 1320 ExaOffscreenArea *area = *mem_struct; 1321 1322 if (area != NULL) { 1323 if (area->size >= size) 1324 return area->offset; 1325 1326 exaOffscreenFree(pScrn->pScreen, area); 1327 } 1328 1329 area = exaOffscreenAlloc(pScrn->pScreen, size, 64, TRUE, SavageVideoSave, 1330 NULL); 1331 *mem_struct = area; 1332 if (area == NULL) 1333 return 0; 1334 offset = area->offset; 1335 } 1336 1337 if (!psav->useEXA) { 1338 FBLinearPtr linear = *mem_struct; 1339 int cpp = pScrn->bitsPerPixel / 8; 1340 1341 /* XAA allocates in units of pixels at the screen bpp, so adjust size 1342 * appropriately. 1343 */ 1344 size = (size + cpp - 1) / cpp; 1345 1346 if (linear) { 1347 if(linear->size >= size) 1348 return linear->offset * cpp; 1349 1350 if(xf86ResizeOffscreenLinear(linear, size)) 1351 return linear->offset * cpp; 1352 1353 xf86FreeOffscreenLinear(linear); 1354 } 1355 1356 linear = xf86AllocateOffscreenLinear(pScreen, size, 16, 1357 NULL, NULL, NULL); 1358 *mem_struct = linear; 1359 1360 if (!linear) { 1361 int max_size; 1362 1363 xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, 1364 PRIORITY_EXTREME); 1365 1366 if(max_size < size) 1367 return 0; 1368 1369 xf86PurgeUnlockedOffscreenAreas(pScreen); 1370 linear = xf86AllocateOffscreenLinear(pScreen, size, 16, 1371 NULL, NULL, NULL); 1372 *mem_struct = linear; 1373 if (!linear) 1374 return 0; 1375 } 1376 offset = linear->offset * cpp; 1377 } 1378 1379 return offset; 1380} 1381 1382static void 1383SavageFreeMemory( 1384 ScrnInfoPtr pScrn, 1385 void *mem_struct 1386){ 1387 SavagePtr psav = SAVPTR(pScrn); 1388 1389 if (psav->useEXA) { 1390 ExaOffscreenArea *area = mem_struct; 1391 1392 if (area != NULL) 1393 exaOffscreenFree(pScrn->pScreen, area); 1394 } 1395 if (!psav->useEXA) { 1396 FBLinearPtr linear = mem_struct; 1397 1398 if (linear != NULL) 1399 xf86FreeOffscreenLinear(linear); 1400 } 1401} 1402 1403static void 1404SavageSetBlend(ScrnInfoPtr pScrn, int id) 1405{ 1406 SavagePtr psav = SAVPTR(pScrn); 1407 1408 if ( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) 1409 { 1410 psav->blendBase = GetBlendForFourCC( id ); 1411 xf86ErrorFVerb(XVTRACE+1,"Format %4.4s, blend is %08x\n", (char*)&id, psav->blendBase ); 1412 if (psav->IsSecondary) { 1413 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) )); 1414 } else if (psav->IsPrimary) { 1415 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 )); 1416 } else { 1417 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 )); 1418#if 0 1419 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) )); 1420#endif 1421 } 1422 } else if (psav->Chipset == S3_SAVAGE2000) { 1423 psav->blendBase = GetBlendForFourCC2000( id ); 1424 xf86ErrorFVerb(XVTRACE+1,"Format %4.4s, blend is %08x\n", (char*)&id, psav->blendBase ); 1425 if (id != FOURCC_YV12) 1426 OUTREG( BLEND_CONTROL, 1427 ((psav->blendBase << 24) | (8 << 2) /*| 0x20000000*/)); 1428 else 1429 OUTREG( BLEND_CONTROL, 1430 ((psav->blendBase << 24) | (8 << 2) /*| 0x10000000*/)); 1431 } 1432 1433 psav->videoFourCC = id; 1434} 1435 1436static void 1437SavageDisplayVideoOld( 1438 ScrnInfoPtr pScrn, 1439 int id, 1440 int offset, 1441 short width, short height, 1442 int pitch, 1443 int x1, int y1, int x2, int y2, 1444 BoxPtr dstBox, 1445 short src_w, short src_h, 1446 short drw_w, short drw_h 1447){ 1448 SavagePtr psav = SAVPTR(pScrn); 1449 vgaHWPtr hwp = VGAHWPTR(pScrn); 1450 SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr; 1451 /*DisplayModePtr mode = pScrn->currentMode;*/ 1452 int vgaCRIndex, vgaCRReg, vgaIOBase; 1453 CARD32 ssControl; 1454 int scalratio; 1455 1456 1457 vgaIOBase = hwp->IOBase; 1458 vgaCRIndex = vgaIOBase + 4; 1459 vgaCRReg = vgaIOBase + 5; 1460#if 0 1461 if ( psav->videoFourCC != id ) { 1462 SavageSetBlend(pScrn,id); 1463 SavageResetVideo(pScrn); 1464 } 1465#endif 1466 if( psav->videoFourCC != id ) 1467 SavageStreamsOff(pScrn); 1468 1469 if( !(psav->videoFlags & VF_STREAMS_ON) ) 1470 { 1471 SavageSetBlend(pScrn,id); 1472 SavageStreamsOn(pScrn); 1473 SavageResetVideo(pScrn); 1474 pPriv->lastKnownPitch = 0; 1475 } 1476 1477 if (S3_MOBILE_TWISTER_SERIES(psav->Chipset) 1478 && psav->FPExpansion) { 1479 drw_w = (((float)(drw_w * psav->XExp1)/(float)psav->XExp2)+1); 1480 drw_h = (float)(drw_h * psav->YExp1)/(float)psav->YExp2+1; 1481 dstBox->x1 = (float)(dstBox->x1 * psav->XExp1)/(float)psav->XExp2; 1482 dstBox->y1 = (float)(dstBox->y1 * psav->YExp1)/(float)psav->YExp2; 1483 1484 dstBox->x1 += psav->displayXoffset; 1485 dstBox->y1 += psav->displayYoffset; 1486 } 1487 1488 /* 1489 * Process horizontal scaling 1490 * upscaling and downscaling smaller than 2:1 controled by MM8198 1491 * MM8190 controls downscaling mode larger than 2:1 1492 * Together MM8190 and MM8198 can set arbitrary downscale up to 64:1 1493 */ 1494 scalratio = 0; 1495 ssControl = 0; 1496 1497 if (src_w >= (drw_w * 2)) { 1498 if (src_w < (drw_w * 4)) { 1499 ssControl |= HDSCALE_4; 1500 scalratio = HSCALING(src_w,(drw_w*4)); 1501 } else if (src_w < (drw_w * 8)) { 1502 ssControl |= HDSCALE_8; 1503 scalratio = HSCALING(src_w,(drw_w*8)); 1504 } else if (src_w < (drw_w * 16)) { 1505 ssControl |= HDSCALE_16; 1506 scalratio = HSCALING(src_w,(drw_w*16)); 1507 } else if (src_w < (drw_w * 32)) { 1508 ssControl |= HDSCALE_32; 1509 scalratio = HSCALING(src_w,(drw_w*32)); 1510 } else if (src_w < (drw_w * 64)) { 1511 ssControl |= HDSCALE_64; 1512 scalratio = HSCALING(src_w,(drw_w*64)); 1513 } else { 1514 /* Request beyond maximum downscale! */ 1515 ssControl |= HDSCALE_64; 1516 scalratio = HSCALING(2,1); 1517 } 1518 } else 1519 scalratio = HSCALING(src_w,drw_w); 1520 1521 ssControl |= src_w; 1522 /*ssControl |= (1 << 24);*/ 1523 ssControl |= (GetBlendForFourCC(psav->videoFourCC) << 24); 1524#if 0 1525 /* Wait for VBLANK. */ 1526 VerticalRetraceWait(); 1527#endif 1528 OUTREG(SSTREAM_CONTROL_REG, ssControl); 1529 if (scalratio) 1530 OUTREG(SSTREAM_STRETCH_REG,scalratio); 1531 1532 /* Calculate vertical scale factor. */ 1533 OUTREG(SSTREAM_VINITIAL_REG, 0 ); 1534 /*OUTREG(SSTREAM_VSCALE_REG, (src_h << 15) / drw_h );*/ 1535 OUTREG(SSTREAM_VSCALE_REG, VSCALING(src_h,drw_h)); 1536 1537 /* Set surface location and stride. */ 1538 OUTREG(SSTREAM_FBADDR0_REG, (offset + (x1>>15)) & (0x1ffffff & ~BASE_PAD) ); 1539 OUTREG(SSTREAM_FBADDR1_REG, 0); 1540 OUTREG(SSTREAM_STRIDE_REG, pitch & 0xfff ); 1541 1542 OUTREG(SSTREAM_WINDOW_START_REG, OS_XY(dstBox->x1, dstBox->y1) ); 1543 OUTREG(SSTREAM_WINDOW_SIZE_REG, OS_WH(dstBox->x2-dstBox->x1, 1544 dstBox->y2-dstBox->y1)); 1545 1546 /* 1547 * MM81E8:Secondary Stream Source Line Count 1548 * bit_0~10: # of lines in the source image (before scaling) 1549 * bit_15 = 1: Enable vertical interpolation 1550 * 0: Line duplicaion 1551 */ 1552 /* 1553 * Vertical Interpolation is very bandwidth intensive. Some savages can't 1554 * seem to handle it. Default is line doubling. --AGD 1555 */ 1556 if (pPriv->interpolation) { 1557 if (src_w * 16 <= 0x3300) { 1558 OUTREG(SSTREAM_LINES_REG, 0x8000 | src_h ); 1559 OUTREG(FIFO_CONTROL, (INREG(FIFO_CONTROL) + 1)); 1560 } else { 1561 OUTREG(SSTREAM_LINES_REG, src_h ); 1562 } 1563 } else { 1564 OUTREG(SSTREAM_LINES_REG, src_h ); 1565 } 1566 1567#if 0 1568 /* Set color key on primary. */ 1569 1570 SavageSetColorKey( pScrn ); 1571#endif 1572 1573 /* Set FIFO L2 on second stream. */ 1574 1575 if( pPriv->lastKnownPitch != pitch ) 1576 { 1577 unsigned char cr92; 1578 1579 pPriv->lastKnownPitch = pitch; 1580 1581 pitch = (pitch + 7) / 8; 1582 VGAOUT8(vgaCRIndex, 0x92); 1583 cr92 = VGAIN8(vgaCRReg); 1584 VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80); 1585 VGAOUT8(vgaCRIndex, 0x93); 1586 if (psav->bTiled && (( drw_h > src_h) || (drw_w > src_w))) 1587 VGAOUT8(vgaCRReg, pitch | 0xf); 1588 else 1589 VGAOUT8(vgaCRReg, pitch); 1590 } 1591} 1592 1593static void 1594SavageDisplayVideoNew( 1595 ScrnInfoPtr pScrn, 1596 int id, 1597 int offset, 1598 short width, short height, 1599 int pitch, 1600 int x1, int y1, int x2, int y2, 1601 BoxPtr dstBox, 1602 short src_w, short src_h, 1603 short drw_w, short drw_h 1604){ 1605 SavagePtr psav = SAVPTR(pScrn); 1606 vgaHWPtr hwp = VGAHWPTR(pScrn); 1607 /*DisplayModePtr mode = pScrn->currentMode;*/ 1608 SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr; 1609 int vgaCRIndex, vgaCRReg, vgaIOBase; 1610 1611 1612 vgaIOBase = hwp->IOBase; 1613 vgaCRIndex = vgaIOBase + 4; 1614 vgaCRReg = vgaIOBase + 5; 1615#if 0 1616 if ( psav->videoFourCC != id ) { 1617 SavageSetBlend(pScrn,id); 1618 SavageResetVideo(pScrn); 1619 } 1620#endif 1621 if( psav->videoFourCC != id ) 1622 SavageStreamsOff(pScrn); 1623 1624 if( !(psav->videoFlags & VF_STREAMS_ON) ) 1625 { 1626 SavageSetBlend(pScrn,id); 1627 SavageStreamsOn(pScrn); 1628 SavageResetVideo(pScrn); 1629 pPriv->lastKnownPitch = 0; 1630 } 1631 1632 /* Calculate horizontal and vertical scale factors. */ 1633 1634 if ( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) && 1635 (psav->DisplayType == MT_LCD) && 1636 !psav->CrtOnly && 1637 !psav->TvOn) 1638 { 1639 drw_w = (drw_w * psav->XExp1)/psav->XExp2 + 1; 1640 drw_h = (drw_h * psav->YExp1)/psav->YExp2 + 1; 1641 dstBox->x1 = (dstBox->x1 * psav->XExp1)/psav->XExp2; 1642 dstBox->y1 = (dstBox->y1 * psav->YExp1)/psav->YExp2; 1643 dstBox->x1 += psav->displayXoffset; 1644 dstBox->y1 += psav->displayYoffset; 1645 } 1646 1647 if (psav->IsSecondary) { 1648 OUTREG(SEC_STREAM2_HSCALING, 1649 ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF )); 1650 /* BUGBUG need to add 00040000 if src stride > 2048 */ 1651 OUTREG(SEC_STREAM2_VSCALING, 1652 ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF )); 1653 } else if (psav->IsPrimary) { 1654 OUTREG(SEC_STREAM_HSCALING, 1655 ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF )); 1656 /* BUGBUG need to add 00040000 if src stride > 2048 */ 1657 OUTREG(SEC_STREAM_VSCALING, 1658 ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF )); 1659 } else { 1660 OUTREG(SEC_STREAM_HSCALING, 1661 ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF )); 1662 /* BUGBUG need to add 00040000 if src stride > 2048 */ 1663 OUTREG(SEC_STREAM_VSCALING, 1664 ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF )); 1665#if 0 1666 OUTREG(SEC_STREAM2_HSCALING, 1667 ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF )); 1668 /* BUGBUG need to add 00040000 if src stride > 2048 */ 1669 OUTREG(SEC_STREAM2_VSCALING, 1670 ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF )); 1671#endif 1672 } 1673 1674 /* 1675 * Set surface location and stride. We use x1>>15 because all surfaces 1676 * are 2 bytes/pixel. 1677 */ 1678 1679 if (psav->IsSecondary) { 1680 OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15)) 1681 & (0x7ffffff & ~BASE_PAD)); 1682 OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff ); 1683 OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) ); 1684 OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16) 1685 | (dstBox->x2-dstBox->x1) ); 1686 } else if (psav->IsPrimary) { 1687 OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15)) 1688 & (0x7ffffff & ~BASE_PAD)); 1689 OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff ); 1690 OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) ); 1691 OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16) 1692 | (dstBox->x2-dstBox->x1) ); 1693 } else { 1694 OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15)) 1695 & (0x7ffffff & ~BASE_PAD)); 1696 OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff ); 1697 OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) ); 1698 OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16) 1699 | (dstBox->x2-dstBox->x1) ); 1700#if 0 1701 OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15)) 1702 & (0x7ffffff & ~BASE_PAD)); 1703 OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff ); 1704 OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) ); 1705 OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16) 1706 | (dstBox->x2-dstBox->x1) ); 1707#endif 1708 } 1709 1710#if 0 1711 /* Set color key on primary. */ 1712 1713 SavageSetColorKey( pScrn ); 1714#endif 1715 1716 /* Set FIFO L2 on second stream. */ 1717 /* Is CR92 shadowed for crtc2? -- AGD */ 1718 if( pPriv->lastKnownPitch != pitch ) 1719 { 1720 unsigned char cr92; 1721 1722 pPriv->lastKnownPitch = pitch; 1723 pitch = (pitch + 7) / 8 - 4; 1724 VGAOUT8(vgaCRIndex, 0x92); 1725 cr92 = VGAIN8(vgaCRReg); 1726 VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80); 1727 VGAOUT8(vgaCRIndex, 0x93); 1728 VGAOUT8(vgaCRReg, pitch); 1729 } 1730} 1731 1732static void 1733SavageDisplayVideo2000( 1734 ScrnInfoPtr pScrn, 1735 int id, 1736 int offset, 1737 short width, short height, 1738 int pitch, 1739 int x1, int y1, int x2, int y2, 1740 BoxPtr dstBox, 1741 short src_w, short src_h, 1742 short drw_w, short drw_h 1743){ 1744 SavagePtr psav = SAVPTR(pScrn); 1745 vgaHWPtr hwp = VGAHWPTR(pScrn); 1746 /*DisplayModePtr mode = pScrn->currentMode;*/ 1747 SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr; 1748 int vgaCRIndex, vgaCRReg, vgaIOBase; 1749 CARD32 addr0, addr1, addr2; 1750 1751 vgaIOBase = hwp->IOBase; 1752 vgaCRIndex = vgaIOBase + 4; 1753 vgaCRReg = vgaIOBase + 5; 1754 1755 1756 if( psav->videoFourCC != id ) 1757 SavageStreamsOff(pScrn); 1758 1759 if( !(psav->videoFlags & VF_STREAMS_ON) ) 1760 { 1761 SavageSetBlend(pScrn,id); 1762 SavageStreamsOn(pScrn); 1763 SavageResetVideo(pScrn); 1764 pPriv->lastKnownPitch = 0; 1765 } 1766 1767 if (src_w > drw_w) 1768 OUTREG(SEC_STREAM_SRC_START_2000, 0); 1769 else 1770 OUTREG(SEC_STREAM_SRC_START_2000, SRCSTART(x1, y1)); 1771 1772 /*OUTREG(SEC_STREAM_SRC_SIZE_2000, SRCSIZE(src_w, src_h));*/ 1773 OUTREG(SEC_STREAM_SRC_SIZE_2000, 1774 SRCSIZE((dstBox->x2-dstBox->x1), (dstBox->y2-dstBox->y1))); 1775 /* 1776 buffersize = (src_w * src_h * 2) / 4096; 1777 OUTREG(SEC_STREAM_BUFFERSIZE_2000, (buffersize & 0xffffff) << 12); 1778 */ 1779 1780 /*SavageResetVideo(pScrn);*/ 1781 1782 if( src_w > drw_w ) 1783 OUTREG(SEC_STREAM_HSCALE_NORMALIZE, HSCALING_NORMALIZE(drw_w,src_w)); 1784 else 1785 OUTREG(SEC_STREAM_HSCALE_NORMALIZE, (2048 << 16)); 1786 1787 /* Calculate horizontal and vertical scale factors. */ 1788 if ((src_w > drw_w) || (src_h > drw_h)) 1789 OUTREG(SEC_STREAM_HSCALING, (HSCALING_2000(src_w,drw_w)) | 0x01000000); 1790 else 1791 OUTREG(SEC_STREAM_HSCALING, HSCALING_2000(src_w,drw_w)); 1792 1793 OUTREG(SEC_STREAM_VSCALING, VSCALING_2000(src_h,drw_h)); 1794 1795 /* 1796 * Set surface location and stride. We use x1>>15 because all surfaces 1797 * are 2 bytes/pixel. 1798 */ 1799 1800 addr0 = offset + (x1>>15); /* Y in YCbCr420 */ 1801 addr1 = addr0 + (width * height); /* Cb in in YCbCr420 */ 1802 addr2 = addr1 + ((width * height) / 4); /* Cr in in YCbCr420 */ 1803 OUTREG(SEC_STREAM_FBUF_ADDR0, (addr0) & (0x3fffff & ~BASE_PAD)); 1804#if 0 1805 OUTREG(SEC_STREAM_FBUF_ADDR1, (addr1) & (0x3fffff & ~BASE_PAD)); 1806 OUTREG(SEC_STREAM_FBUF_ADDR2, (addr2) & (0x3fffff & ~BASE_PAD)); 1807#endif 1808 1809 OUTREG(SEC_STREAM_WINDOW_START, XY_2000(dstBox->x1,dstBox->y1)); 1810 OUTREG(SEC_STREAM_WINDOW_SZ, 1811 WH_2000((dstBox->x2-dstBox->x1),(dstBox->y2-dstBox->y1))); 1812 1813 /*pitch = width * 2;*/ 1814 OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff); 1815#if 0 1816 /* Y stride + CbCr stride in YCbCr420 */ 1817 OUTREG(SEC_STREAM_STRIDE, (pitch & 0xfff) + ((pitch & 0xfff) << 15)); 1818#endif 1819 1820#if 0 1821 /* Set color key on primary. */ 1822 1823 SavageSetColorKey2000( pScrn ); 1824#endif 1825 1826#if 0 1827 /* Set FIFO L2 on second stream. */ 1828 if( pPriv->lastKnownPitch != pitch ) 1829 { 1830 unsigned char cr92; 1831 1832 pPriv->lastKnownPitch = pitch; 1833 pitch = (pitch + 7) / 8 - 4; 1834 VGAOUT8(vgaCRIndex, 0x92); 1835 cr92 = VGAIN8(vgaCRReg); 1836 VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80); 1837 VGAOUT8(vgaCRIndex, 0x93); 1838 VGAOUT8(vgaCRReg, pitch); 1839 } 1840#endif 1841} 1842 1843static int 1844SavagePutImage( 1845 ScrnInfoPtr pScrn, 1846 short src_x, short src_y, 1847 short drw_x, short drw_y, 1848 short src_w, short src_h, 1849 short drw_w, short drw_h, 1850 int id, unsigned char* buf, 1851 short width, short height, 1852 Bool sync, 1853 RegionPtr clipBoxes, pointer data, 1854 DrawablePtr pDraw 1855){ 1856 SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data; 1857 SavagePtr psav = SAVPTR(pScrn); 1858 ScreenPtr pScreen = pScrn->pScreen; 1859 INT32 x1, x2, y1, y2; 1860 unsigned char *dst_start; 1861 int pitch, new_size, offset, offsetV=0, offsetU=0; 1862 int srcPitch, srcPitch2=0, dstPitch; 1863 int top, left, npixels, nlines; 1864 BoxRec dstBox; 1865 CARD32 tmp; 1866/* xf86ErrorFVerb(XVTRACE,"SavagePutImage\n"); */ 1867 if(drw_w > 16384) drw_w = 16384; 1868 1869 /* Clip */ 1870 x1 = src_x; 1871 x2 = src_x + src_w; 1872 y1 = src_y; 1873 y2 = src_y + src_h; 1874 1875 dstBox.x1 = drw_x; 1876 dstBox.x2 = drw_x + drw_w; 1877 dstBox.y1 = drw_y; 1878 dstBox.y2 = drw_y + drw_h; 1879 1880 SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2, 1881 REGION_EXTENTS(pScreen, clipBoxes), width, height); 1882 1883 drw_w = dstBox.x2 - dstBox.x1; 1884 drw_h = dstBox.y2 - dstBox.y1; 1885 src_w = ( x2 - x1 ) >> 16; 1886 src_h = ( y2 - y1 ) >> 16; 1887 1888 if((x1 >= x2) || (y1 >= y2)) 1889 return Success; 1890 1891 dstBox.x1 -= pScrn->frameX0; 1892 dstBox.x2 -= pScrn->frameX0; 1893 dstBox.y1 -= pScrn->frameY0; 1894 dstBox.y2 -= pScrn->frameY0; 1895 1896 pitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3; 1897 1898 dstPitch = ((width << 1) + 15) & ~15; 1899 /*new_h = ((dstPitch * height) + pitch - 1) / pitch;*/ 1900 new_size = dstPitch * height; 1901 1902 switch(id) { 1903 case FOURCC_Y211: /* Y211 */ 1904 srcPitch = width; 1905 break; 1906 case FOURCC_YV12: /* YV12 */ 1907 srcPitch = (width + 3) & ~3; 1908 offsetV = srcPitch * height; 1909 srcPitch2 = ((width >> 1) + 3) & ~3; 1910 offsetU = (srcPitch2 * (height >> 1)) + offsetV; 1911 break; 1912 case FOURCC_I420: 1913 srcPitch = (width + 3) & ~3; 1914 offsetU = srcPitch * height; 1915 srcPitch2 = ((width >> 1) + 3) & ~3; 1916 offsetV = (srcPitch2 * (height >> 1)) + offsetU; 1917 break; 1918 case FOURCC_RV15: /* RGB15 */ 1919 case FOURCC_RV16: /* RGB16 */ 1920 case FOURCC_YUY2: /* YUY2 */ 1921 default: 1922 srcPitch = (width << 1); 1923 break; 1924 } 1925 1926 if (srcPitch2 != 0 && S3_SAVAGE4_SERIES(psav->Chipset) && psav->BCIforXv) { 1927 new_size = ((new_size + 0xF) & ~0xF) + srcPitch * height + srcPitch2 * height; 1928 } 1929 1930/* if(!(pPriv->area = SavageAllocateMemory(pScrn, pPriv->area, new_h))) 1931 return BadAlloc;*/ 1932 pPriv->video_offset = SavageAllocateMemory(pScrn, &pPriv->video_memory, 1933 new_size); 1934 if (pPriv->video_offset == 0) 1935 return BadAlloc; 1936 1937 /* copy data */ 1938 top = y1 >> 16; 1939 left = (x1 >> 16) & ~1; 1940 npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; 1941 left <<= 1; 1942 1943 offset = (pPriv->video_offset) + (top * dstPitch); 1944 /*offset = pPriv->area->box.y1 * psav->lDelta;*/ 1945 dst_start = (psav->FBBase + ((offset + left) & ~BASE_PAD)); 1946 1947 switch(id) { 1948 case FOURCC_YV12: /* YV12 */ 1949 case FOURCC_I420: 1950 top &= ~1; 1951 tmp = ((top >> 1) * srcPitch2) + (left >> 2); 1952 offsetU += tmp; 1953 offsetV += tmp; 1954 nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; 1955 if (S3_SAVAGE4_SERIES(psav->Chipset) && psav->BCIforXv && (npixels & 0xF) == 0) { 1956 SavageCopyPlanarDataBCI( 1957 pScrn, 1958 buf + (top * srcPitch) + (left >> 1), 1959 buf + offsetV, 1960 buf + offsetU, 1961 dst_start, srcPitch, srcPitch2, dstPitch, nlines, npixels); 1962 } else { 1963 SavageCopyPlanarData( 1964 buf + (top * srcPitch) + (left >> 1), 1965 buf + offsetV, 1966 buf + offsetU, 1967 dst_start, srcPitch, srcPitch2, dstPitch, nlines, npixels); 1968 } 1969 break; 1970 case FOURCC_Y211: /* Y211 */ 1971 case FOURCC_RV15: /* RGB15 */ 1972 case FOURCC_RV16: /* RGB16 */ 1973 case FOURCC_YUY2: /* YUY2 */ 1974 default: 1975 buf += (top * srcPitch) + left; 1976 nlines = ((y2 + 0xffff) >> 16) - top; 1977 SavageCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels); 1978 break; 1979 } 1980 1981 /* We need to enable the video before we draw the chroma color. 1982 Otherwise, we get blue flashes. */ 1983 1984 SavageDisplayVideo(pScrn, id, offset, width, height, dstPitch, 1985 x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 1986 1987 /* update cliplist */ 1988 if(!REGION_EQUAL(pScreen, &pPriv->clip, clipBoxes)) { 1989 REGION_COPY(pScreen, &pPriv->clip, clipBoxes); 1990 /* draw these */ 1991 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 1992 1993 } 1994 1995 pPriv->videoStatus = CLIENT_VIDEO_ON; 1996 1997 return Success; 1998} 1999 2000static int 2001SavageQueryImageAttributes( 2002 ScrnInfoPtr pScrn, 2003 int id, 2004 unsigned short *w, unsigned short *h, 2005 int *pitches, int *offsets 2006){ 2007 int size, tmp; 2008 2009 if(*w > 1024) *w = 1024; 2010 if(*h > 1024) *h = 1024; 2011 2012 *w = (*w + 1) & ~1; 2013 if(offsets) offsets[0] = 0; 2014 2015 switch(id) { 2016 case FOURCC_IA44: 2017 if (pitches) pitches[0]=*w; 2018 size=(*w)*(*h); 2019 break; 2020 case FOURCC_Y211: 2021 size = *w << 2; 2022 if(pitches) pitches[0] = size; 2023 size *= *h; 2024 break; 2025 case FOURCC_YV12: 2026 case FOURCC_I420: 2027 *h = (*h + 1) & ~1; 2028 size = (*w + 3) & ~3; 2029 if(pitches) pitches[0] = size; 2030 size *= *h; 2031 if(offsets) offsets[1] = size; 2032 tmp = ((*w >> 1) + 3) & ~3; 2033 if(pitches) pitches[1] = pitches[2] = tmp; 2034 tmp *= (*h >> 1); 2035 size += tmp; 2036 if(offsets) offsets[2] = size; 2037 size += tmp; 2038 break; 2039 case FOURCC_RV15: /* RGB15 */ 2040 case FOURCC_RV16: /* RGB16 */ 2041 case FOURCC_YUY2: 2042 default: 2043 size = *w << 1; 2044 if(pitches) pitches[0] = size; 2045 size *= *h; 2046 break; 2047 } 2048 2049 return size; 2050} 2051 2052/****************** Offscreen stuff ***************/ 2053 2054typedef struct { 2055 void *surface_memory; 2056 Bool isOn; 2057} OffscreenPrivRec, * OffscreenPrivPtr; 2058 2059static int 2060SavageAllocateSurface( 2061 ScrnInfoPtr pScrn, 2062 int id, 2063 unsigned short w, 2064 unsigned short h, 2065 XF86SurfacePtr surface 2066){ 2067 int offset, size; 2068 int pitch, fbpitch, numlines; 2069 void *surface_memory = NULL; 2070 OffscreenPrivPtr pPriv; 2071 2072 if((w > 1024) || (h > 1024)) 2073 return BadAlloc; 2074 2075 w = (w + 1) & ~1; 2076 pitch = ((w << 1) + 15) & ~15; 2077 fbpitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3; 2078 numlines = ((pitch * h) + fbpitch - 1) / fbpitch; 2079 size = pitch * h; 2080 2081 offset = SavageAllocateMemory(pScrn, &surface_memory, size); 2082 if (offset == 0) 2083 return BadAlloc; 2084 2085 surface->width = w; 2086 surface->height = h; 2087 2088 if(!(surface->pitches = xalloc(sizeof(int)))) { 2089 SavageFreeMemory(pScrn, surface_memory); 2090 return BadAlloc; 2091 } 2092 if(!(surface->offsets = xalloc(sizeof(int)))) { 2093 xfree(surface->pitches); 2094 SavageFreeMemory(pScrn, surface_memory); 2095 return BadAlloc; 2096 } 2097 if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) { 2098 xfree(surface->pitches); 2099 xfree(surface->offsets); 2100 SavageFreeMemory(pScrn, surface_memory); 2101 return BadAlloc; 2102 } 2103 2104 pPriv->surface_memory = surface_memory; 2105 pPriv->isOn = FALSE; 2106 2107 surface->pScrn = pScrn; 2108 surface->id = id; 2109 surface->pitches[0] = pitch; 2110 surface->offsets[0] = offset; /*area->box.y1 * fbpitch;*/ 2111 surface->devPrivate.ptr = (pointer)pPriv; 2112 2113 return Success; 2114} 2115 2116static int 2117SavageStopSurface( 2118 XF86SurfacePtr surface 2119){ 2120 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 2121 xf86ErrorFVerb(XVTRACE,"SavageStopSurface\n"); 2122 2123 if(pPriv->isOn) { 2124 /*SavagePtr psav = SAVPTR(surface->pScrn);*/ 2125 /*SavageClipVWindow(surface->pScrn);*/ 2126 SavageStreamsOff( surface->pScrn ); 2127 pPriv->isOn = FALSE; 2128 } 2129 2130 return Success; 2131} 2132 2133 2134static int 2135SavageFreeSurface( 2136 XF86SurfacePtr surface 2137){ 2138 ScrnInfoPtr pScrn = surface->pScrn; 2139 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 2140 2141 if(pPriv->isOn) 2142 SavageStopSurface(surface); 2143 SavageFreeMemory(pScrn, pPriv->surface_memory); 2144 xfree(surface->pitches); 2145 xfree(surface->offsets); 2146 xfree(surface->devPrivate.ptr); 2147 2148 return Success; 2149} 2150 2151static int 2152SavageGetSurfaceAttribute( 2153 ScrnInfoPtr pScrn, 2154 Atom attribute, 2155 INT32 *value 2156){ 2157 return SavageGetPortAttribute(pScrn, attribute, value, 2158 (pointer)(GET_PORT_PRIVATE(pScrn))); 2159} 2160 2161static int 2162SavageSetSurfaceAttribute( 2163 ScrnInfoPtr pScrn, 2164 Atom attribute, 2165 INT32 value 2166){ 2167 return SavageSetPortAttribute(pScrn, attribute, value, 2168 (pointer)(GET_PORT_PRIVATE(pScrn))); 2169} 2170 2171 2172static int 2173SavageDisplaySurface( 2174 XF86SurfacePtr surface, 2175 short src_x, short src_y, 2176 short drw_x, short drw_y, 2177 short src_w, short src_h, 2178 short drw_w, short drw_h, 2179 RegionPtr clipBoxes 2180){ 2181 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 2182 ScrnInfoPtr pScrn = surface->pScrn; 2183 ScreenPtr pScreen = pScrn->pScreen; 2184 SavagePortPrivPtr portPriv = GET_PORT_PRIVATE(pScrn); 2185 INT32 x1, y1, x2, y2; 2186 BoxRec dstBox; 2187 xf86ErrorFVerb(XVTRACE,"SavageDisplaySurface\n"); 2188 2189 x1 = src_x; 2190 x2 = src_x + src_w; 2191 y1 = src_y; 2192 y2 = src_y + src_h; 2193 2194 dstBox.x1 = drw_x; 2195 dstBox.x2 = drw_x + drw_w; 2196 dstBox.y1 = drw_y; 2197 dstBox.y2 = drw_y + drw_h; 2198 2199 SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2, 2200 REGION_EXTENTS(pScreen, clipBoxes), 2201 surface->width, surface->height); 2202 2203 if((x1 >= x2) || (y1 >= y2)) 2204 return Success; 2205 2206 dstBox.x1 -= pScrn->frameX0; 2207 dstBox.x2 -= pScrn->frameX0; 2208 dstBox.y1 -= pScrn->frameY0; 2209 dstBox.y2 -= pScrn->frameY0; 2210 2211 SavageDisplayVideo(pScrn, surface->id, surface->offsets[0], 2212 surface->width, surface->height, surface->pitches[0], 2213 x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 2214 2215 xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes); 2216 2217 pPriv->isOn = TRUE; 2218#if 0 2219 if(portPriv->videoStatus & CLIENT_VIDEO_ON) { 2220 REGION_EMPTY(pScreen, &portPriv->clip); 2221 UpdateCurrentTime(); 2222 portPriv->videoStatus = FREE_TIMER; 2223 portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 2224 } 2225#endif 2226 2227 return Success; 2228} 2229 2230 2231static void 2232SavageInitOffscreenImages(ScreenPtr pScreen) 2233{ 2234 XF86OffscreenImagePtr offscreenImages; 2235 SavagePtr psav = SAVPTR(xf86Screens[pScreen->myNum]); 2236 2237 /* need to free this someplace */ 2238 if (!psav->offscreenImages) { 2239 if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) 2240 return; 2241 psav->offscreenImages = offscreenImages; 2242 } else { 2243 offscreenImages = psav->offscreenImages; 2244 } 2245 2246 offscreenImages[0].image = &Images[0]; 2247 offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | 2248 VIDEO_CLIP_TO_VIEWPORT; 2249 offscreenImages[0].alloc_surface = SavageAllocateSurface; 2250 offscreenImages[0].free_surface = SavageFreeSurface; 2251 offscreenImages[0].display = SavageDisplaySurface; 2252 offscreenImages[0].stop = SavageStopSurface; 2253 offscreenImages[0].setAttribute = SavageSetSurfaceAttribute; 2254 offscreenImages[0].getAttribute = SavageGetSurfaceAttribute; 2255 offscreenImages[0].max_width = 1024; 2256 offscreenImages[0].max_height = 1024; 2257 offscreenImages[0].num_attributes = NUM_ATTRIBUTES; 2258 offscreenImages[0].attributes = Attributes; 2259 2260 xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); 2261} 2262 2263