savage_video.c revision 38770048
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, (CARD32)MMIO_IN32( psav->MapBase, offset ), value ); 308 MMIO_OUT32( psav->MapBase, offset, value ); 309 ErrorF( " now %08lx\n", (CARD32)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 SavagePtr psav = SAVPTR(pScrn); 1041 1042 xf86ErrorFVerb(XVTRACE,"SavageStopVideo\n"); 1043 1044 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 1045 1046 if(shutdown) { 1047 /*SavageClipVWindow(pScrn);*/ 1048 SavageStreamsOff( pScrn ); 1049 1050#ifdef SAVAGEDRI 1051 if (pPriv->agpBufferMap != NULL) { 1052 SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo; 1053 1054 /* agpXVideo is reused to implement UploadToScreen in EXA */ 1055 if (!psav->useEXA) { 1056 drmUnmap(pPriv->agpBufferMap, pSAVAGEDRIServer->agpXVideo.size); 1057 pSAVAGEDRIServer->agpXVideo.map = NULL; 1058 } 1059 pPriv->agpBufferMap = NULL; 1060 pPriv->agpBufferOffset = 0; 1061 } 1062 pPriv->tried_agp = FALSE; 1063#endif 1064 1065 if (pPriv->video_memory != NULL) { 1066 SavageFreeMemory(pScrn, pPriv->video_memory); 1067 pPriv->video_memory = NULL; 1068 } 1069 if (pPriv->video_planarmem != NULL) { 1070 SavageFreeMemory(pScrn, pPriv->video_planarmem); 1071 pPriv->video_planarmem = NULL; 1072 } 1073 pPriv->videoStatus = 0; 1074 } else { 1075 if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 1076 pPriv->videoStatus |= OFF_TIMER; 1077 pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 1078 } 1079 } 1080} 1081 1082 1083static int 1084SavageSetPortAttribute( 1085 ScrnInfoPtr pScrn, 1086 Atom attribute, 1087 INT32 value, 1088 pointer data 1089){ 1090 SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data; 1091 SavagePtr psav = SAVPTR(pScrn); 1092 1093 if(attribute == xvColorKey) { 1094 pPriv->colorKey = value; 1095 if( psav->videoFlags & VF_STREAMS_ON) 1096 SavageSetColorKey( pScrn ); 1097 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 1098 } 1099 else if( attribute == xvBrightness) { 1100 if((value < -128) || (value > 127)) 1101 return BadValue; 1102 pPriv->brightness = value; 1103 if( psav->videoFlags & VF_STREAMS_ON) 1104 SavageSetColor( pScrn ); 1105 } 1106 else if( attribute == xvContrast) { 1107 if((value < 0) || (value > 255)) 1108 return BadValue; 1109 pPriv->contrast = value; 1110 if( psav->videoFlags & VF_STREAMS_ON) 1111 SavageSetColor( pScrn ); 1112 } 1113 else if( attribute == xvSaturation) { 1114 if((value < 0) || (value > 255)) 1115 return BadValue; 1116 pPriv->saturation = value; 1117 if( psav->videoFlags & VF_STREAMS_ON) 1118 SavageSetColor( pScrn ); 1119 } 1120 else if( attribute == xvHue) { 1121 if((value < -180) || (value > 180)) 1122 return BadValue; 1123 pPriv->hue = value; 1124 if( psav->videoFlags & VF_STREAMS_ON) 1125 SavageSetColor( pScrn ); 1126 } 1127 else if( attribute == xvInterpolation) { 1128 if((value < 0) || (value > 1)) 1129 return BadValue; 1130 if (value == 1) 1131 pPriv->interpolation = TRUE; 1132 else 1133 pPriv->interpolation = FALSE; 1134 } 1135 else 1136 return BadMatch; 1137 1138 return Success; 1139} 1140 1141 1142static int 1143SavageGetPortAttribute( 1144 ScrnInfoPtr pScrn, 1145 Atom attribute, 1146 INT32 *value, 1147 pointer data 1148){ 1149 SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data; 1150 1151 if(attribute == xvColorKey) { 1152 *value = pPriv->colorKey; 1153 } 1154 else if( attribute == xvBrightness ) { 1155 *value = pPriv->brightness; 1156 } 1157 else if( attribute == xvContrast ) { 1158 *value = pPriv->contrast; 1159 } 1160 else if( attribute == xvHue ) { 1161 *value = pPriv->hue; 1162 } 1163 else if( attribute == xvSaturation ) { 1164 *value = pPriv->saturation; 1165 } 1166 else if( attribute == xvInterpolation ) { 1167 *value = pPriv->interpolation; 1168 } 1169 else return BadMatch; 1170 1171 return Success; 1172} 1173 1174static void 1175SavageQueryBestSize( 1176 ScrnInfoPtr pScrn, 1177 Bool motion, 1178 short vid_w, short vid_h, 1179 short drw_w, short drw_h, 1180 unsigned int *p_w, unsigned int *p_h, 1181 pointer data 1182){ 1183 /* What are the real limits for the Savage? */ 1184 1185 *p_w = drw_w; 1186 *p_h = drw_h; 1187 1188 if(*p_w > 16384) *p_w = 16384; 1189} 1190 1191/* SavageCopyPlanarDataBCI() causes artifacts on the screen when used on savage4. 1192 * It's probably something with the BCI. Maybe we need a waitforidle() or 1193 * something... 1194 */ 1195static void 1196SavageCopyPlanarDataBCI( 1197 ScrnInfoPtr pScrn, 1198 unsigned char *srcY, /* Y */ 1199 unsigned char *srcV, /* V */ 1200 unsigned char *srcU, /* U */ 1201 unsigned char *dst, 1202 unsigned char * planarPtr, 1203 unsigned long planarOffset, 1204 int srcPitch, int srcPitch2, 1205 int dstPitch, 1206 int h,int w, 1207 Bool isAGP) 1208{ 1209 SavagePtr psav = SAVPTR(pScrn); 1210 1211 /* for pixel transfer */ 1212 unsigned long offsetY = planarOffset; 1213 unsigned long offsetV = offsetY + srcPitch * h; 1214 unsigned long offsetU = offsetV + srcPitch2 * (h>>1); 1215 unsigned long dstOffset = (unsigned long)dst - (unsigned long)psav->FBBase; 1216 unsigned char memType; 1217 1218 BCI_GET_PTR; 1219 1220 /* copy Y planar */ 1221 memcpy(planarPtr, srcY, srcPitch * h); 1222 1223 /* copy V planar */ 1224 planarPtr = planarPtr + srcPitch * h; 1225 memcpy(planarPtr, srcV, srcPitch2 * (h>>1)); 1226 1227 /* copy U planar */ 1228 planarPtr = planarPtr + srcPitch2 * (h>>1); 1229 memcpy(planarPtr, srcU, srcPitch2 * (h>>1)); 1230 1231 memType = isAGP ? 3 : 0; 1232 1233 /* 1234 * Transfer pixel data from one memory location to another location 1235 * and reformat the data during the transfer 1236 * a. program BCI51 to specify the source information 1237 * b. program BCI52 to specify the destination information 1238 * c. program BCI53 to specify the source dimensions 1239 * d. program BCI54 to specify the destination dimensions 1240 * e. (if the data is in YCbCr420 format)program BCI55,BCI56,BCI57 to 1241 * locations of the Y,Cb,and Cr data 1242 * f. program BCI50(command=011) to specify the formatting options and 1243 * kick off the transfer 1244 * this command can be used for color space conversion(YCbCr to RGB) 1245 * or for oversampling, but not for both simultaneously. it can also be 1246 * used to do mastered image transfer when the source is tiled 1247 */ 1248 1249 w = (w+0xf)&0xff0; 1250 psav->WaitQueue(psav,11); 1251 BCI_SEND(BCI_SET_REGISTER | BCI_SET_REGISTER_COUNT(7) | 0x51); 1252 BCI_SEND(offsetY | memType); 1253 BCI_SEND(dstOffset); 1254 BCI_SEND(((h-1)<<16)|((w-1)>>3)); 1255 BCI_SEND(dstPitch >> 3); 1256 BCI_SEND(offsetU | memType); 1257 BCI_SEND(offsetV | memType); 1258 BCI_SEND((srcPitch2 << 16)| srcPitch2); 1259 1260 BCI_SEND(BCI_SET_REGISTER | BCI_SET_REGISTER_COUNT(1) | 0x50); 1261 BCI_SEND(0x00200003 | srcPitch); 1262 1263 BCI_SEND(0xC0170000); 1264} 1265 1266static void 1267SavageCopyData( 1268 unsigned char *src, 1269 unsigned char *dst, 1270 int srcPitch, 1271 int dstPitch, 1272 int h, 1273 int w 1274){ 1275 w <<= 1; 1276 if (w == srcPitch && w == dstPitch) { 1277 memcpy(dst, src, w * h); 1278 } else 1279 while(h--) { 1280 memcpy(dst, src, w); 1281 src += srcPitch; 1282 dst += dstPitch; 1283 } 1284} 1285 1286static void 1287SavageCopyPlanarData( 1288 unsigned char *src1, /* Y */ 1289 unsigned char *src2, /* V */ 1290 unsigned char *src3, /* U */ 1291 unsigned char *dst1, 1292 int srcPitch, 1293 int srcPitch2, 1294 int dstPitch, 1295 int h, 1296 int w 1297){ 1298 CARD32 *dst = (CARD32*)dst1; 1299 int i, j; 1300 1301 dstPitch >>= 2; 1302 w >>= 1; 1303 1304 for(j = 0; j < h; j++) { 1305 for(i = 0; i < w; i++) { 1306/* Shouldn't this be 'if LITTLEENDIAN'? */ 1307#if 1 1308 dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) | 1309 (src3[i] << 8) | (src2[i] << 24); 1310#else 1311 dst[i] = (src1[i << 1] << 24) | (src1[(i << 1) + 1] << 8) | 1312 (src3[i] << 0) | (src2[i] << 16); 1313#endif 1314 } 1315 dst += dstPitch; 1316 src1 += srcPitch; 1317 if(j & 1) { 1318 src2 += srcPitch2; 1319 src3 += srcPitch2; 1320 } 1321 } 1322} 1323 1324static void 1325SavageVideoSave(ScreenPtr pScreen, ExaOffscreenArea *area) 1326{ 1327 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1328 SavagePtr psav = SAVPTR(pScrn); 1329 SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr; 1330 1331 if (pPriv->video_memory == area) 1332 pPriv->video_memory = NULL; 1333 if (pPriv->video_planarmem == area) 1334 pPriv->video_planarmem = NULL; 1335} 1336 1337static CARD32 1338SavageAllocateMemory( 1339 ScrnInfoPtr pScrn, 1340 void **mem_struct, 1341 int size 1342){ 1343 ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 1344 SavagePtr psav = SAVPTR(pScrn); 1345 int offset = 0; 1346 1347 if (psav->useEXA) { 1348 ExaOffscreenArea *area = *mem_struct; 1349 1350 if (area != NULL) { 1351 if (area->size >= size) 1352 return area->offset; 1353 1354 exaOffscreenFree(pScrn->pScreen, area); 1355 } 1356 1357 area = exaOffscreenAlloc(pScrn->pScreen, size, 64, TRUE, SavageVideoSave, 1358 NULL); 1359 *mem_struct = area; 1360 if (area == NULL) 1361 return 0; 1362 offset = area->offset; 1363 } 1364 1365 if (!psav->useEXA) { 1366 FBLinearPtr linear = *mem_struct; 1367 int cpp = pScrn->bitsPerPixel / 8; 1368 1369 /* XAA allocates in units of pixels at the screen bpp, so adjust size 1370 * appropriately. 1371 */ 1372 size = (size + cpp - 1) / cpp; 1373 1374 if (linear) { 1375 if(linear->size >= size) 1376 return linear->offset * cpp; 1377 1378 if(xf86ResizeOffscreenLinear(linear, size)) 1379 return linear->offset * cpp; 1380 1381 xf86FreeOffscreenLinear(linear); 1382 } 1383 1384 linear = xf86AllocateOffscreenLinear(pScreen, size, 16, 1385 NULL, NULL, NULL); 1386 *mem_struct = linear; 1387 1388 if (!linear) { 1389 int max_size; 1390 1391 xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, 1392 PRIORITY_EXTREME); 1393 1394 if(max_size < size) 1395 return 0; 1396 1397 xf86PurgeUnlockedOffscreenAreas(pScreen); 1398 linear = xf86AllocateOffscreenLinear(pScreen, size, 16, 1399 NULL, NULL, NULL); 1400 *mem_struct = linear; 1401 if (!linear) 1402 return 0; 1403 } 1404 offset = linear->offset * cpp; 1405 } 1406 1407 return offset; 1408} 1409 1410static void 1411SavageFreeMemory( 1412 ScrnInfoPtr pScrn, 1413 void *mem_struct 1414){ 1415 SavagePtr psav = SAVPTR(pScrn); 1416 1417 if (psav->useEXA) { 1418 ExaOffscreenArea *area = mem_struct; 1419 1420 if (area != NULL) 1421 exaOffscreenFree(pScrn->pScreen, area); 1422 } 1423 if (!psav->useEXA) { 1424 FBLinearPtr linear = mem_struct; 1425 1426 if (linear != NULL) 1427 xf86FreeOffscreenLinear(linear); 1428 } 1429} 1430 1431static void 1432SavageSetBlend(ScrnInfoPtr pScrn, int id) 1433{ 1434 SavagePtr psav = SAVPTR(pScrn); 1435 1436 if ( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) 1437 { 1438 psav->blendBase = GetBlendForFourCC( id ); 1439 xf86ErrorFVerb(XVTRACE+1,"Format %4.4s, blend is %08x\n", (char*)&id, psav->blendBase ); 1440 if (psav->IsSecondary) { 1441 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) )); 1442 } else if (psav->IsPrimary) { 1443 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 )); 1444 } else { 1445 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 9) | 0x08 )); 1446#if 0 1447 OUTREG( BLEND_CONTROL, (INREG32(BLEND_CONTROL) | (psav->blendBase << 17) | (8 << 12) )); 1448#endif 1449 } 1450 } else if (psav->Chipset == S3_SAVAGE2000) { 1451 psav->blendBase = GetBlendForFourCC2000( id ); 1452 xf86ErrorFVerb(XVTRACE+1,"Format %4.4s, blend is %08x\n", (char*)&id, psav->blendBase ); 1453 if (id != FOURCC_YV12) 1454 OUTREG( BLEND_CONTROL, 1455 ((psav->blendBase << 24) | (8 << 2) /*| 0x20000000*/)); 1456 else 1457 OUTREG( BLEND_CONTROL, 1458 ((psav->blendBase << 24) | (8 << 2) /*| 0x10000000*/)); 1459 } 1460 1461 psav->videoFourCC = id; 1462} 1463 1464static void 1465SavageDisplayVideoOld( 1466 ScrnInfoPtr pScrn, 1467 int id, 1468 int offset, 1469 short width, short height, 1470 int pitch, 1471 int x1, int y1, int x2, int y2, 1472 BoxPtr dstBox, 1473 short src_w, short src_h, 1474 short drw_w, short drw_h 1475){ 1476 SavagePtr psav = SAVPTR(pScrn); 1477 vgaHWPtr hwp = VGAHWPTR(pScrn); 1478 SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr; 1479 /*DisplayModePtr mode = pScrn->currentMode;*/ 1480 int vgaCRIndex, vgaCRReg, vgaIOBase; 1481 CARD32 ssControl; 1482 int scalratio; 1483 1484 1485 vgaIOBase = hwp->IOBase; 1486 vgaCRIndex = vgaIOBase + 4; 1487 vgaCRReg = vgaIOBase + 5; 1488#if 0 1489 if ( psav->videoFourCC != id ) { 1490 SavageSetBlend(pScrn,id); 1491 SavageResetVideo(pScrn); 1492 } 1493#endif 1494 if( psav->videoFourCC != id ) 1495 SavageStreamsOff(pScrn); 1496 1497 if( !(psav->videoFlags & VF_STREAMS_ON) ) 1498 { 1499 SavageSetBlend(pScrn,id); 1500 SavageStreamsOn(pScrn); 1501 SavageResetVideo(pScrn); 1502 pPriv->lastKnownPitch = 0; 1503 } 1504 1505 if (S3_MOBILE_TWISTER_SERIES(psav->Chipset) 1506 && psav->FPExpansion) { 1507 drw_w = (drw_w * psav->XExp1) / psav->XExp2 + 1; 1508 drw_h = (drw_h * psav->YExp1) / psav->YExp2 + 1; 1509 dstBox->x1 = (dstBox->x1 * psav->XExp1) / psav->XExp2; 1510 dstBox->y1 = (dstBox->y1 * psav->YExp1) / psav->YExp2; 1511 dstBox->x2 = (dstBox->x2 * psav->XExp1) / psav->XExp2; 1512 dstBox->y2 = (dstBox->y2 * psav->YExp1) / psav->YExp2; 1513 dstBox->x1 += psav->displayXoffset; 1514 dstBox->y1 += psav->displayYoffset; 1515 dstBox->x2 += psav->displayXoffset; 1516 dstBox->y2 += psav->displayYoffset; 1517 } 1518 1519 /* 1520 * Process horizontal scaling 1521 * upscaling and downscaling smaller than 2:1 controled by MM8198 1522 * MM8190 controls downscaling mode larger than 2:1 1523 * Together MM8190 and MM8198 can set arbitrary downscale up to 64:1 1524 */ 1525 scalratio = 0; 1526 ssControl = 0; 1527 1528 if (src_w >= (drw_w * 2)) { 1529 if (src_w < (drw_w * 4)) { 1530 ssControl |= HDSCALE_4; 1531 scalratio = HSCALING(src_w,(drw_w*4)); 1532 } else if (src_w < (drw_w * 8)) { 1533 ssControl |= HDSCALE_8; 1534 scalratio = HSCALING(src_w,(drw_w*8)); 1535 } else if (src_w < (drw_w * 16)) { 1536 ssControl |= HDSCALE_16; 1537 scalratio = HSCALING(src_w,(drw_w*16)); 1538 } else if (src_w < (drw_w * 32)) { 1539 ssControl |= HDSCALE_32; 1540 scalratio = HSCALING(src_w,(drw_w*32)); 1541 } else if (src_w < (drw_w * 64)) { 1542 ssControl |= HDSCALE_64; 1543 scalratio = HSCALING(src_w,(drw_w*64)); 1544 } else { 1545 /* Request beyond maximum downscale! */ 1546 ssControl |= HDSCALE_64; 1547 scalratio = HSCALING(2,1); 1548 } 1549 } else 1550 scalratio = HSCALING(src_w,drw_w); 1551 1552 ssControl |= src_w; 1553 /*ssControl |= (1 << 24);*/ 1554 ssControl |= (GetBlendForFourCC(psav->videoFourCC) << 24); 1555#if 0 1556 /* Wait for VBLANK. */ 1557 VerticalRetraceWait(); 1558#endif 1559 OUTREG(SSTREAM_CONTROL_REG, ssControl); 1560 if (scalratio) 1561 OUTREG(SSTREAM_STRETCH_REG,scalratio); 1562 1563 /* Calculate vertical scale factor. */ 1564 OUTREG(SSTREAM_VINITIAL_REG, 0 ); 1565 /*OUTREG(SSTREAM_VSCALE_REG, (src_h << 15) / drw_h );*/ 1566 OUTREG(SSTREAM_VSCALE_REG, VSCALING(src_h,drw_h)); 1567 1568 /* Set surface location and stride. */ 1569 OUTREG(SSTREAM_FBADDR0_REG, (offset + (x1>>15)) & (0x1ffffff & ~BASE_PAD) ); 1570 OUTREG(SSTREAM_FBADDR1_REG, 0); 1571 OUTREG(SSTREAM_STRIDE_REG, pitch & 0xfff ); 1572 1573 OUTREG(SSTREAM_WINDOW_START_REG, OS_XY(dstBox->x1, dstBox->y1) ); 1574 OUTREG(SSTREAM_WINDOW_SIZE_REG, OS_WH(dstBox->x2-dstBox->x1, 1575 dstBox->y2-dstBox->y1)); 1576 1577 /* 1578 * MM81E8:Secondary Stream Source Line Count 1579 * bit_0~10: # of lines in the source image (before scaling) 1580 * bit_15 = 1: Enable vertical interpolation 1581 * 0: Line duplicaion 1582 */ 1583 /* 1584 * Vertical Interpolation is very bandwidth intensive. Some savages can't 1585 * seem to handle it. Default is line doubling. --AGD 1586 */ 1587 if (pPriv->interpolation) { 1588 if (src_w * 16 <= 0x3300) { 1589 OUTREG(SSTREAM_LINES_REG, 0x8000 | src_h ); 1590 OUTREG(FIFO_CONTROL, (INREG(FIFO_CONTROL) + 1)); 1591 } else { 1592 OUTREG(SSTREAM_LINES_REG, src_h ); 1593 } 1594 } else { 1595 OUTREG(SSTREAM_LINES_REG, src_h ); 1596 } 1597 1598#if 0 1599 /* Set color key on primary. */ 1600 1601 SavageSetColorKey( pScrn ); 1602#endif 1603 1604 /* Set FIFO L2 on second stream. */ 1605 1606 if( pPriv->lastKnownPitch != pitch ) 1607 { 1608 unsigned char cr92; 1609 1610 pPriv->lastKnownPitch = pitch; 1611 1612 pitch = (pitch + 7) / 8; 1613 VGAOUT8(vgaCRIndex, 0x92); 1614 cr92 = VGAIN8(vgaCRReg); 1615 VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80); 1616 VGAOUT8(vgaCRIndex, 0x93); 1617 if (psav->bTiled && (( drw_h > src_h) || (drw_w > src_w))) 1618 VGAOUT8(vgaCRReg, pitch | 0xf); 1619 else 1620 VGAOUT8(vgaCRReg, pitch); 1621 } 1622} 1623 1624static void 1625SavageDisplayVideoNew( 1626 ScrnInfoPtr pScrn, 1627 int id, 1628 int offset, 1629 short width, short height, 1630 int pitch, 1631 int x1, int y1, int x2, int y2, 1632 BoxPtr dstBox, 1633 short src_w, short src_h, 1634 short drw_w, short drw_h 1635){ 1636 SavagePtr psav = SAVPTR(pScrn); 1637 vgaHWPtr hwp = VGAHWPTR(pScrn); 1638 /*DisplayModePtr mode = pScrn->currentMode;*/ 1639 SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr; 1640 int vgaCRIndex, vgaCRReg, vgaIOBase; 1641 1642 1643 vgaIOBase = hwp->IOBase; 1644 vgaCRIndex = vgaIOBase + 4; 1645 vgaCRReg = vgaIOBase + 5; 1646#if 0 1647 if ( psav->videoFourCC != id ) { 1648 SavageSetBlend(pScrn,id); 1649 SavageResetVideo(pScrn); 1650 } 1651#endif 1652 if( psav->videoFourCC != id ) 1653 SavageStreamsOff(pScrn); 1654 1655 if( !(psav->videoFlags & VF_STREAMS_ON) ) 1656 { 1657 SavageSetBlend(pScrn,id); 1658 SavageStreamsOn(pScrn); 1659 SavageResetVideo(pScrn); 1660 pPriv->lastKnownPitch = 0; 1661 } 1662 1663 /* Calculate horizontal and vertical scale factors. */ 1664 1665 if ( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) && 1666 (psav->DisplayType == MT_LCD) && 1667 !psav->CrtOnly && 1668 !psav->TvOn) 1669 { 1670 drw_w = (drw_w * psav->XExp1) / psav->XExp2 + 1; 1671 drw_h = (drw_h * psav->YExp1) / psav->YExp2 + 1; 1672 dstBox->x1 = (dstBox->x1 * psav->XExp1) / psav->XExp2; 1673 dstBox->y1 = (dstBox->y1 * psav->YExp1) / psav->YExp2; 1674 dstBox->x2 = (dstBox->x2 * psav->XExp1) / psav->XExp2; 1675 dstBox->y2 = (dstBox->y2 * psav->YExp1) / psav->YExp2; 1676 dstBox->x1 += psav->displayXoffset; 1677 dstBox->y1 += psav->displayYoffset; 1678 dstBox->x2 += psav->displayXoffset; 1679 dstBox->y2 += psav->displayYoffset; 1680 } 1681 1682 if (psav->IsSecondary) { 1683 OUTREG(SEC_STREAM2_HSCALING, 1684 ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF )); 1685 /* BUGBUG need to add 00040000 if src stride > 2048 */ 1686 OUTREG(SEC_STREAM2_VSCALING, 1687 ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF )); 1688 } else if (psav->IsPrimary) { 1689 OUTREG(SEC_STREAM_HSCALING, 1690 ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF )); 1691 /* BUGBUG need to add 00040000 if src stride > 2048 */ 1692 OUTREG(SEC_STREAM_VSCALING, 1693 ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF )); 1694 } else { 1695 OUTREG(SEC_STREAM_HSCALING, 1696 ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF )); 1697 /* BUGBUG need to add 00040000 if src stride > 2048 */ 1698 OUTREG(SEC_STREAM_VSCALING, 1699 ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF )); 1700#if 0 1701 OUTREG(SEC_STREAM2_HSCALING, 1702 ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF )); 1703 /* BUGBUG need to add 00040000 if src stride > 2048 */ 1704 OUTREG(SEC_STREAM2_VSCALING, 1705 ((src_h&0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF )); 1706#endif 1707 } 1708 1709 /* 1710 * Set surface location and stride. We use x1>>15 because all surfaces 1711 * are 2 bytes/pixel. 1712 */ 1713 1714 if (psav->IsSecondary) { 1715 OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15)) 1716 & (0x7ffffff & ~BASE_PAD)); 1717 OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff ); 1718 OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) ); 1719 OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16) 1720 | (dstBox->y2 - dstBox->y1) ); 1721 } else if (psav->IsPrimary) { 1722 OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15)) 1723 & (0x7ffffff & ~BASE_PAD)); 1724 OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff ); 1725 OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) ); 1726 OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16) 1727 | (dstBox->y2 - dstBox->y1) ); 1728 } else { 1729 OUTREG(SEC_STREAM_FBUF_ADDR0, (offset + (x1>>15)) 1730 & (0x7ffffff & ~BASE_PAD)); 1731 OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff ); 1732 OUTREG(SEC_STREAM_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) ); 1733 OUTREG(SEC_STREAM_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16) 1734 | (dstBox->y2 - dstBox->y1) ); 1735#if 0 1736 OUTREG(SEC_STREAM2_FBUF_ADDR0, (offset + (x1>>15)) 1737 & (0x7ffffff & ~BASE_PAD)); 1738 OUTREG(SEC_STREAM2_STRIDE_LPB, pitch & 0xfff ); 1739 OUTREG(SEC_STREAM2_WINDOW_START, ((dstBox->x1+1) << 16) | (dstBox->y1+1) ); 1740 OUTREG(SEC_STREAM2_WINDOW_SZ, ((dstBox->x2-dstBox->x1) << 16) 1741 | (dstBox->y2 - dstBox->y1) ); 1742#endif 1743 } 1744 1745#if 0 1746 /* Set color key on primary. */ 1747 1748 SavageSetColorKey( pScrn ); 1749#endif 1750 1751 /* Set FIFO L2 on second stream. */ 1752 /* Is CR92 shadowed for crtc2? -- AGD */ 1753 if( pPriv->lastKnownPitch != pitch ) 1754 { 1755 unsigned char cr92; 1756 1757 pPriv->lastKnownPitch = pitch; 1758 pitch = (pitch + 7) / 8 - 4; 1759 VGAOUT8(vgaCRIndex, 0x92); 1760 cr92 = VGAIN8(vgaCRReg); 1761 VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80); 1762 VGAOUT8(vgaCRIndex, 0x93); 1763 VGAOUT8(vgaCRReg, pitch); 1764 } 1765} 1766 1767static void 1768SavageDisplayVideo2000( 1769 ScrnInfoPtr pScrn, 1770 int id, 1771 int offset, 1772 short width, short height, 1773 int pitch, 1774 int x1, int y1, int x2, int y2, 1775 BoxPtr dstBox, 1776 short src_w, short src_h, 1777 short drw_w, short drw_h 1778){ 1779 SavagePtr psav = SAVPTR(pScrn); 1780 vgaHWPtr hwp = VGAHWPTR(pScrn); 1781 /*DisplayModePtr mode = pScrn->currentMode;*/ 1782 SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr; 1783 int vgaCRIndex, vgaCRReg, vgaIOBase; 1784 CARD32 addr0, addr1, addr2; 1785 1786 vgaIOBase = hwp->IOBase; 1787 vgaCRIndex = vgaIOBase + 4; 1788 vgaCRReg = vgaIOBase + 5; 1789 1790 1791 if( psav->videoFourCC != id ) 1792 SavageStreamsOff(pScrn); 1793 1794 if( !(psav->videoFlags & VF_STREAMS_ON) ) 1795 { 1796 SavageSetBlend(pScrn,id); 1797 SavageStreamsOn(pScrn); 1798 SavageResetVideo(pScrn); 1799 pPriv->lastKnownPitch = 0; 1800 } 1801 1802 if (src_w > drw_w) 1803 OUTREG(SEC_STREAM_SRC_START_2000, 0); 1804 else 1805 OUTREG(SEC_STREAM_SRC_START_2000, SRCSTART(x1, y1)); 1806 1807 /*OUTREG(SEC_STREAM_SRC_SIZE_2000, SRCSIZE(src_w, src_h));*/ 1808 OUTREG(SEC_STREAM_SRC_SIZE_2000, 1809 SRCSIZE((dstBox->x2-dstBox->x1), (dstBox->y2-dstBox->y1))); 1810 /* 1811 buffersize = (src_w * src_h * 2) / 4096; 1812 OUTREG(SEC_STREAM_BUFFERSIZE_2000, (buffersize & 0xffffff) << 12); 1813 */ 1814 1815 /*SavageResetVideo(pScrn);*/ 1816 1817 if( src_w > drw_w ) 1818 OUTREG(SEC_STREAM_HSCALE_NORMALIZE, HSCALING_NORMALIZE(drw_w,src_w)); 1819 else 1820 OUTREG(SEC_STREAM_HSCALE_NORMALIZE, (2048 << 16)); 1821 1822 /* Calculate horizontal and vertical scale factors. */ 1823 if ((src_w > drw_w) || (src_h > drw_h)) 1824 OUTREG(SEC_STREAM_HSCALING, (HSCALING_2000(src_w,drw_w)) | 0x01000000); 1825 else 1826 OUTREG(SEC_STREAM_HSCALING, HSCALING_2000(src_w,drw_w)); 1827 1828 OUTREG(SEC_STREAM_VSCALING, VSCALING_2000(src_h,drw_h)); 1829 1830 /* 1831 * Set surface location and stride. We use x1>>15 because all surfaces 1832 * are 2 bytes/pixel. 1833 */ 1834 1835 addr0 = offset + (x1>>15); /* Y in YCbCr420 */ 1836 addr1 = addr0 + (width * height); /* Cb in in YCbCr420 */ 1837 addr2 = addr1 + ((width * height) / 4); /* Cr in in YCbCr420 */ 1838 OUTREG(SEC_STREAM_FBUF_ADDR0, (addr0) & (0x3fffff & ~BASE_PAD)); 1839#if 0 1840 OUTREG(SEC_STREAM_FBUF_ADDR1, (addr1) & (0x3fffff & ~BASE_PAD)); 1841 OUTREG(SEC_STREAM_FBUF_ADDR2, (addr2) & (0x3fffff & ~BASE_PAD)); 1842#endif 1843 1844 OUTREG(SEC_STREAM_WINDOW_START, XY_2000(dstBox->x1,dstBox->y1)); 1845 OUTREG(SEC_STREAM_WINDOW_SZ, 1846 WH_2000((dstBox->x2-dstBox->x1),(dstBox->y2-dstBox->y1))); 1847 1848 /*pitch = width * 2;*/ 1849 OUTREG(SEC_STREAM_STRIDE, pitch & 0xfff); 1850#if 0 1851 /* Y stride + CbCr stride in YCbCr420 */ 1852 OUTREG(SEC_STREAM_STRIDE, (pitch & 0xfff) + ((pitch & 0xfff) << 15)); 1853#endif 1854 1855#if 0 1856 /* Set color key on primary. */ 1857 1858 SavageSetColorKey2000( pScrn ); 1859#endif 1860 1861#if 0 1862 /* Set FIFO L2 on second stream. */ 1863 if( pPriv->lastKnownPitch != pitch ) 1864 { 1865 unsigned char cr92; 1866 1867 pPriv->lastKnownPitch = pitch; 1868 pitch = (pitch + 7) / 8 - 4; 1869 VGAOUT8(vgaCRIndex, 0x92); 1870 cr92 = VGAIN8(vgaCRReg); 1871 VGAOUT8(vgaCRReg, (cr92 & 0x40) | (pitch >> 8) | 0x80); 1872 VGAOUT8(vgaCRIndex, 0x93); 1873 VGAOUT8(vgaCRReg, pitch); 1874 } 1875#endif 1876} 1877 1878static void 1879SavageFillKeyHelper(DrawablePtr pDraw, uint32_t colorKey, RegionPtr clipBoxes) 1880{ 1881#if HAVE_XV_DRAWABLE_HELPER 1882 xf86XVFillKeyHelperDrawable(pDraw, colorKey, clipBoxes); 1883#else 1884 xf86XVFillKeyHelper(pDraw->pScreen, colorKey, clipBoxes); 1885#endif 1886} 1887 1888static int 1889SavagePutImage( 1890 ScrnInfoPtr pScrn, 1891 short src_x, short src_y, 1892 short drw_x, short drw_y, 1893 short src_w, short src_h, 1894 short drw_w, short drw_h, 1895 int id, unsigned char* buf, 1896 short width, short height, 1897 Bool sync, 1898 RegionPtr clipBoxes, pointer data, 1899 DrawablePtr pDraw 1900){ 1901 SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data; 1902 SavagePtr psav = SAVPTR(pScrn); 1903 ScreenPtr pScreen = pScrn->pScreen; 1904 INT32 x1, x2, y1, y2; 1905 unsigned char *dst_start; 1906 int pitch, new_size, offset, offsetV=0, offsetU=0; 1907 int srcPitch, srcPitch2=0, dstPitch; 1908 int planarFrameSize; 1909 int top, left, npixels, nlines; 1910 BoxRec dstBox; 1911 CARD32 tmp; 1912/* xf86ErrorFVerb(XVTRACE,"SavagePutImage\n"); */ 1913 if(drw_w > 16384) drw_w = 16384; 1914 1915 /* Clip */ 1916 x1 = src_x; 1917 x2 = src_x + src_w; 1918 y1 = src_y; 1919 y2 = src_y + src_h; 1920 1921 dstBox.x1 = drw_x; 1922 dstBox.x2 = drw_x + drw_w; 1923 dstBox.y1 = drw_y; 1924 dstBox.y2 = drw_y + drw_h; 1925 1926 SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2, 1927 REGION_EXTENTS(pScreen, clipBoxes), width, height); 1928 1929 drw_w = dstBox.x2 - dstBox.x1; 1930 drw_h = dstBox.y2 - dstBox.y1; 1931 src_w = ( x2 - x1 ) >> 16; 1932 src_h = ( y2 - y1 ) >> 16; 1933 1934 if((x1 >= x2) || (y1 >= y2)) 1935 return Success; 1936 1937 dstBox.x1 -= pScrn->frameX0; 1938 dstBox.x2 -= pScrn->frameX0; 1939 dstBox.y1 -= pScrn->frameY0; 1940 dstBox.y2 -= pScrn->frameY0; 1941 1942 pitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3; 1943 1944 /* All formats directly displayable by Savage are packed and 2 bytes per pixel */ 1945 dstPitch = ((width << 1) + 15) & ~15; 1946 new_size = dstPitch * height; 1947 1948 switch(id) { 1949 case FOURCC_Y211: /* Y211 */ 1950 srcPitch = width; 1951 break; 1952 case FOURCC_YV12: /* YV12 */ 1953 srcPitch = (width + 3) & ~3; 1954 offsetV = srcPitch * height; 1955 srcPitch2 = ((width >> 1) + 3) & ~3; 1956 offsetU = (srcPitch2 * (height >> 1)) + offsetV; 1957 break; 1958 case FOURCC_I420: 1959 srcPitch = (width + 3) & ~3; 1960 offsetU = srcPitch * height; 1961 srcPitch2 = ((width >> 1) + 3) & ~3; 1962 offsetV = (srcPitch2 * (height >> 1)) + offsetU; 1963 break; 1964 case FOURCC_RV15: /* RGB15 */ 1965 case FOURCC_RV16: /* RGB16 */ 1966 case FOURCC_YUY2: /* YUY2 */ 1967 default: 1968 srcPitch = (width << 1); 1969 break; 1970 } 1971 1972 /* Calculate required memory for all planar frames */ 1973 planarFrameSize = 0; 1974 if (srcPitch2 != 0 && S3_SAVAGE4_SERIES(psav->Chipset) && psav->BCIforXv) { 1975 new_size = ((new_size + 0xF) & ~0xF); 1976 planarFrameSize = srcPitch * height + srcPitch2 * height; 1977 } 1978 1979 /* Check whether AGP buffers can be allocated. If not, fall back to ordinary 1980 upload to framebuffer (slower) */ 1981#ifdef SAVAGEDRI 1982 if (!pPriv->tried_agp && !psav->IsPCI && psav->drmFD > 0 && psav->DRIServerInfo != NULL) { 1983 SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo; 1984 1985 pPriv->tried_agp = TRUE; 1986 if (pSAVAGEDRIServer->agpXVideo.size >= max(new_size, planarFrameSize)) { 1987 if (pSAVAGEDRIServer->agpXVideo.map == NULL && 1988 drmMap( psav->drmFD, 1989 pSAVAGEDRIServer->agpXVideo.handle, 1990 pSAVAGEDRIServer->agpXVideo.size, 1991 &pSAVAGEDRIServer->agpXVideo.map ) < 0 ) { 1992 1993 xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] XVideo: Could not map agpXVideo \n" ); 1994 pPriv->agpBufferOffset = 0; 1995 pPriv->agpBufferMap = NULL; 1996 } else { 1997 pPriv->agpBufferMap = pSAVAGEDRIServer->agpXVideo.map; 1998 pPriv->agpBufferOffset = pSAVAGEDRIServer->agpXVideo.offset; 1999 pPriv->agpBase = drmAgpBase(psav->drmFD); 2000#if 0 2001 xf86DrvMsg( pScreen->myNum, X_INFO, 2002 "[agp] agpXVideo mapped at 0x%08lx aperture=0x%08x offset=0x%08lx\n", 2003 (unsigned long)pPriv->agpBufferMap, pPriv->agpBase, pPriv->agpBufferOffset); 2004#endif 2005 } 2006 } else { 2007 /* This situation is expected if AGPforXv is disabled, otherwise report. */ 2008 if (pSAVAGEDRIServer->agpXVideo.size > 0) { 2009 xf86DrvMsg( pScreen->myNum, X_ERROR, 2010 "[agp] XVideo: not enough space in buffer (got %ld bytes, required %d bytes).\n", 2011 (long int)pSAVAGEDRIServer->agpXVideo.size, max(new_size, planarFrameSize)); 2012 } 2013 pPriv->agpBufferMap = NULL; 2014 pPriv->agpBufferOffset = 0; 2015 } 2016 } 2017#endif /* SAVAGEDRI */ 2018 2019 2020 /* Buffer for final packed frame */ 2021 pPriv->video_offset = SavageAllocateMemory( 2022 pScrn, &pPriv->video_memory, 2023 new_size); 2024 if (pPriv->video_offset == 0) 2025 return BadAlloc; 2026 2027 /* Packed format cases */ 2028 if (planarFrameSize == 0) { 2029 pPriv->video_planarbuf = 0; 2030 2031 /* Planar format cases */ 2032 } else { 2033 /* Hardware-assisted planar conversion only works on 16-byte aligned addresses */ 2034 pPriv->video_planarbuf = SavageAllocateMemory( 2035 pScrn, &pPriv->video_planarmem, 2036 ((planarFrameSize + 0xF) & ~0xF)); 2037 if (pPriv->video_planarbuf != 0) { 2038 /* TODO: stop any pending conversions when buffers change... */ 2039 pPriv->video_planarbuf = ((pPriv->video_planarbuf + 0xF) & ~0xF); 2040 } else { 2041 /* Fallback using software conversion */ 2042 } 2043 } 2044 2045 /* copy data */ 2046 top = y1 >> 16; 2047 left = (x1 >> 16) & ~1; 2048 npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; 2049 left <<= 1; 2050 2051 offset = (pPriv->video_offset) + (top * dstPitch); 2052 dst_start = (psav->FBBase + ((offset + left) & ~BASE_PAD)); 2053 2054 switch(id) { 2055 case FOURCC_YV12: /* YV12 */ 2056 case FOURCC_I420: 2057 top &= ~1; 2058 tmp = ((top >> 1) * srcPitch2) + (left >> 2); 2059 offsetU += tmp; 2060 offsetV += tmp; 2061 nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; 2062 if (S3_SAVAGE4_SERIES(psav->Chipset) && psav->BCIforXv && (npixels & 0xF) == 0 && pPriv->video_planarbuf != 0) { 2063#ifdef SAVAGEDRI 2064 if (pPriv->agpBufferMap != NULL) { 2065 /* Using copy to AGP memory */ 2066 SavageCopyPlanarDataBCI( 2067 pScrn, 2068 buf + (top * srcPitch) + (left >> 1), 2069 buf + offsetV, 2070 buf + offsetU, 2071 dst_start, 2072 pPriv->agpBufferMap, 2073 pPriv->agpBase + pPriv->agpBufferOffset, 2074 srcPitch, srcPitch2, dstPitch, nlines, npixels, TRUE); 2075 } else 2076#endif /* SAVAGEDRI */ 2077 { 2078 /* Using ordinary copy to framebuffer */ 2079 SavageCopyPlanarDataBCI( 2080 pScrn, 2081 buf + (top * srcPitch) + (left >> 1), 2082 buf + offsetV, 2083 buf + offsetU, 2084 dst_start, 2085 (unsigned char *)psav->FBBase + pPriv->video_planarbuf, 2086 pPriv->video_planarbuf, 2087 srcPitch, srcPitch2, dstPitch, nlines, npixels, FALSE); 2088 } 2089 } else { 2090 SavageCopyPlanarData( 2091 buf + (top * srcPitch) + (left >> 1), 2092 buf + offsetV, 2093 buf + offsetU, 2094 dst_start, srcPitch, srcPitch2, dstPitch, nlines, npixels); 2095 } 2096 break; 2097 case FOURCC_Y211: /* Y211 */ 2098 case FOURCC_RV15: /* RGB15 */ 2099 case FOURCC_RV16: /* RGB16 */ 2100 case FOURCC_YUY2: /* YUY2 */ 2101 default: 2102 buf += (top * srcPitch) + left; 2103 nlines = ((y2 + 0xffff) >> 16) - top; 2104 SavageCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels); 2105 break; 2106 } 2107 2108 /* We need to enable the video before we draw the chroma color. 2109 Otherwise, we get blue flashes. */ 2110 2111 SavageDisplayVideo(pScrn, id, offset, width, height, dstPitch, 2112 x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 2113 2114 /* update cliplist */ 2115 if(!REGION_EQUAL(pScreen, &pPriv->clip, clipBoxes)) { 2116 REGION_COPY(pScreen, &pPriv->clip, clipBoxes); 2117 /* draw these */ 2118 SavageFillKeyHelper(pDraw, pPriv->colorKey, clipBoxes); 2119 2120 } 2121 2122 pPriv->videoStatus = CLIENT_VIDEO_ON; 2123 2124 return Success; 2125} 2126 2127static int 2128SavageQueryImageAttributes( 2129 ScrnInfoPtr pScrn, 2130 int id, 2131 unsigned short *w, unsigned short *h, 2132 int *pitches, int *offsets 2133){ 2134 int size, tmp; 2135 2136 if(*w > 1024) *w = 1024; 2137 if(*h > 1024) *h = 1024; 2138 2139 *w = (*w + 1) & ~1; 2140 if(offsets) offsets[0] = 0; 2141 2142 switch(id) { 2143 case FOURCC_IA44: 2144 if (pitches) pitches[0]=*w; 2145 size=(*w)*(*h); 2146 break; 2147 case FOURCC_Y211: 2148 size = *w << 2; 2149 if(pitches) pitches[0] = size; 2150 size *= *h; 2151 break; 2152 case FOURCC_YV12: 2153 case FOURCC_I420: 2154 *h = (*h + 1) & ~1; 2155 size = (*w + 3) & ~3; 2156 if(pitches) pitches[0] = size; 2157 size *= *h; 2158 if(offsets) offsets[1] = size; 2159 tmp = ((*w >> 1) + 3) & ~3; 2160 if(pitches) pitches[1] = pitches[2] = tmp; 2161 tmp *= (*h >> 1); 2162 size += tmp; 2163 if(offsets) offsets[2] = size; 2164 size += tmp; 2165 break; 2166 case FOURCC_RV15: /* RGB15 */ 2167 case FOURCC_RV16: /* RGB16 */ 2168 case FOURCC_YUY2: 2169 default: 2170 size = *w << 1; 2171 if(pitches) pitches[0] = size; 2172 size *= *h; 2173 break; 2174 } 2175 2176 return size; 2177} 2178 2179/****************** Offscreen stuff ***************/ 2180 2181typedef struct { 2182 void *surface_memory; 2183 Bool isOn; 2184} OffscreenPrivRec, * OffscreenPrivPtr; 2185 2186static int 2187SavageAllocateSurface( 2188 ScrnInfoPtr pScrn, 2189 int id, 2190 unsigned short w, 2191 unsigned short h, 2192 XF86SurfacePtr surface 2193){ 2194 int offset, size; 2195 int pitch, fbpitch, numlines; 2196 void *surface_memory = NULL; 2197 OffscreenPrivPtr pPriv; 2198 2199 if((w > 1024) || (h > 1024)) 2200 return BadAlloc; 2201 2202 w = (w + 1) & ~1; 2203 pitch = ((w << 1) + 15) & ~15; 2204 fbpitch = pScrn->bitsPerPixel * pScrn->displayWidth >> 3; 2205 numlines = ((pitch * h) + fbpitch - 1) / fbpitch; 2206 size = pitch * h; 2207 2208 offset = SavageAllocateMemory(pScrn, &surface_memory, size); 2209 if (offset == 0) 2210 return BadAlloc; 2211 2212 surface->width = w; 2213 surface->height = h; 2214 2215 if(!(surface->pitches = malloc(sizeof(int)))) { 2216 SavageFreeMemory(pScrn, surface_memory); 2217 return BadAlloc; 2218 } 2219 if(!(surface->offsets = malloc(sizeof(int)))) { 2220 free(surface->pitches); 2221 SavageFreeMemory(pScrn, surface_memory); 2222 return BadAlloc; 2223 } 2224 if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) { 2225 free(surface->pitches); 2226 free(surface->offsets); 2227 SavageFreeMemory(pScrn, surface_memory); 2228 return BadAlloc; 2229 } 2230 2231 pPriv->surface_memory = surface_memory; 2232 pPriv->isOn = FALSE; 2233 2234 surface->pScrn = pScrn; 2235 surface->id = id; 2236 surface->pitches[0] = pitch; 2237 surface->offsets[0] = offset; /*area->box.y1 * fbpitch;*/ 2238 surface->devPrivate.ptr = (pointer)pPriv; 2239 2240 return Success; 2241} 2242 2243static int 2244SavageStopSurface( 2245 XF86SurfacePtr surface 2246){ 2247 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 2248 xf86ErrorFVerb(XVTRACE,"SavageStopSurface\n"); 2249 2250 if(pPriv->isOn) { 2251 /*SavagePtr psav = SAVPTR(surface->pScrn);*/ 2252 /*SavageClipVWindow(surface->pScrn);*/ 2253 SavageStreamsOff( surface->pScrn ); 2254 pPriv->isOn = FALSE; 2255 } 2256 2257 return Success; 2258} 2259 2260 2261static int 2262SavageFreeSurface( 2263 XF86SurfacePtr surface 2264){ 2265 ScrnInfoPtr pScrn = surface->pScrn; 2266 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 2267 2268 if(pPriv->isOn) 2269 SavageStopSurface(surface); 2270 SavageFreeMemory(pScrn, pPriv->surface_memory); 2271 free(surface->pitches); 2272 free(surface->offsets); 2273 free(surface->devPrivate.ptr); 2274 2275 return Success; 2276} 2277 2278static int 2279SavageGetSurfaceAttribute( 2280 ScrnInfoPtr pScrn, 2281 Atom attribute, 2282 INT32 *value 2283){ 2284 return SavageGetPortAttribute(pScrn, attribute, value, 2285 (pointer)(GET_PORT_PRIVATE(pScrn))); 2286} 2287 2288static int 2289SavageSetSurfaceAttribute( 2290 ScrnInfoPtr pScrn, 2291 Atom attribute, 2292 INT32 value 2293){ 2294 return SavageSetPortAttribute(pScrn, attribute, value, 2295 (pointer)(GET_PORT_PRIVATE(pScrn))); 2296} 2297 2298 2299static int 2300SavageDisplaySurface( 2301 XF86SurfacePtr surface, 2302 short src_x, short src_y, 2303 short drw_x, short drw_y, 2304 short src_w, short src_h, 2305 short drw_w, short drw_h, 2306 RegionPtr clipBoxes 2307){ 2308 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 2309 ScrnInfoPtr pScrn = surface->pScrn; 2310 ScreenPtr pScreen = pScrn->pScreen; 2311 SavagePortPrivPtr portPriv = GET_PORT_PRIVATE(pScrn); 2312 INT32 x1, y1, x2, y2; 2313 BoxRec dstBox; 2314 xf86ErrorFVerb(XVTRACE,"SavageDisplaySurface\n"); 2315 2316 x1 = src_x; 2317 x2 = src_x + src_w; 2318 y1 = src_y; 2319 y2 = src_y + src_h; 2320 2321 dstBox.x1 = drw_x; 2322 dstBox.x2 = drw_x + drw_w; 2323 dstBox.y1 = drw_y; 2324 dstBox.y2 = drw_y + drw_h; 2325 2326 SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2, 2327 REGION_EXTENTS(pScreen, clipBoxes), 2328 surface->width, surface->height); 2329 2330 if((x1 >= x2) || (y1 >= y2)) 2331 return Success; 2332 2333 dstBox.x1 -= pScrn->frameX0; 2334 dstBox.x2 -= pScrn->frameX0; 2335 dstBox.y1 -= pScrn->frameY0; 2336 dstBox.y2 -= pScrn->frameY0; 2337 2338 SavageDisplayVideo(pScrn, surface->id, surface->offsets[0], 2339 surface->width, surface->height, surface->pitches[0], 2340 x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 2341 2342 xf86XVFillKeyHelper(pScreen, portPriv->colorKey, clipBoxes); 2343 2344 pPriv->isOn = TRUE; 2345#if 0 2346 if(portPriv->videoStatus & CLIENT_VIDEO_ON) { 2347 REGION_EMPTY(pScreen, &portPriv->clip); 2348 UpdateCurrentTime(); 2349 portPriv->videoStatus = FREE_TIMER; 2350 portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 2351 } 2352#endif 2353 2354 return Success; 2355} 2356 2357 2358static void 2359SavageInitOffscreenImages(ScreenPtr pScreen) 2360{ 2361 XF86OffscreenImagePtr offscreenImages; 2362 SavagePtr psav = SAVPTR(xf86ScreenToScrn(pScreen)); 2363 2364 /* need to free this someplace */ 2365 if (!psav->offscreenImages) { 2366 if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec)))) 2367 return; 2368 psav->offscreenImages = offscreenImages; 2369 } else { 2370 offscreenImages = psav->offscreenImages; 2371 } 2372 2373 offscreenImages[0].image = &Images[0]; 2374 offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | 2375 VIDEO_CLIP_TO_VIEWPORT; 2376 offscreenImages[0].alloc_surface = SavageAllocateSurface; 2377 offscreenImages[0].free_surface = SavageFreeSurface; 2378 offscreenImages[0].display = SavageDisplaySurface; 2379 offscreenImages[0].stop = SavageStopSurface; 2380 offscreenImages[0].setAttribute = SavageSetSurfaceAttribute; 2381 offscreenImages[0].getAttribute = SavageGetSurfaceAttribute; 2382 offscreenImages[0].max_width = 1024; 2383 offscreenImages[0].max_height = 1024; 2384 offscreenImages[0].num_attributes = NUM_ATTRIBUTES; 2385 offscreenImages[0].attributes = Attributes; 2386 2387 xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); 2388} 2389 2390