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