1 2#ifdef HAVE_CONFIG_H 3#include "config.h" 4#endif 5 6#include "xf86.h" 7#include "tdfx.h" 8#include "dixstruct.h" 9 10#include <X11/extensions/Xv.h> 11#include "fourcc.h" 12 13static Atom xvColorKey, xvFilterQuality; 14 15/* These should move into tdfxdefs.h with better names */ 16#define YUV_Y_BASE 0xC00000 17#define YUV_U_BASE 0xD00000 18#define YUV_V_BASE 0xE00000 19 20#define SST_2D_FORMAT_YUYV 0x8 21#define SST_2D_FORMAT_UYVY 0x9 22 23#define YUVBASEADDR 0x80100 24#define YUVSTRIDE 0x80104 25#define VIDPROCCFGMASK 0xa2e3eb6c 26 27#define OFF_DELAY 250 /* milliseconds */ 28#define FREE_DELAY 15000 29 30#define OFF_TIMER 0x01 31#define FREE_TIMER 0x02 32#define CLIENT_VIDEO_ON 0x04 33#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 34 35#define TDFX_MAX_OVERLAY_PORTS 1 36#define TDFX_MAX_TEXTURE_PORTS 32 37 38#define GET_PORT_PRIVATE(pScrn) \ 39 (TDFXPortPrivPtr)((TDFXPTR(pScrn))->overlayAdaptor->pPortPrivates[0].ptr) 40 41/* Needed for attribute atoms */ 42#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 43 44/* 45 * PROTOTYPES 46 */ 47 48static FBAreaPtr TDFXAllocateMemoryArea (ScrnInfoPtr pScrn, FBAreaPtr area, int width, int height); 49static FBLinearPtr TDFXAllocateMemoryLinear (ScrnInfoPtr pScrn, FBLinearPtr linear, int size); 50static void TDFXVideoTimerCallback(ScrnInfoPtr pScrn, Time time); 51 52static XF86VideoAdaptorPtr TDFXSetupImageVideoTexture(ScreenPtr); 53static int TDFXSetPortAttributeTexture(ScrnInfoPtr, Atom, INT32, pointer); 54static int TDFXGetPortAttributeTexture(ScrnInfoPtr, Atom ,INT32 *, pointer); 55static int TDFXPutImageTexture(ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer, DrawablePtr); 56static void TDFXStopVideoTexture(ScrnInfoPtr, pointer, Bool); 57 58static XF86VideoAdaptorPtr TDFXSetupImageVideoOverlay(ScreenPtr); 59static int TDFXSetPortAttributeOverlay(ScrnInfoPtr, Atom, INT32, pointer); 60static int TDFXGetPortAttributeOverlay(ScrnInfoPtr, Atom ,INT32 *, pointer); 61static int TDFXPutImageOverlay(ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer, DrawablePtr); 62static void TDFXStopVideoOverlay(ScrnInfoPtr, pointer, Bool); 63static void TDFXResetVideoOverlay(ScrnInfoPtr); 64 65static void TDFXQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, unsigned int *, unsigned int *, pointer); 66static int TDFXQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *, int *, int *); 67 68static void TDFXInitOffscreenImages(ScreenPtr); 69 70/* 71 * ADAPTOR INFORMATION 72 */ 73 74static XF86VideoEncodingRec OverlayEncoding[] = 75{ 76 { 0, "XV_IMAGE", 2048, 2048, {1, 1} } 77}; 78 79static XF86VideoEncodingRec TextureEncoding[] = 80{ 81 { 0, "XV_IMAGE", 1024, 1024, {1, 1} } 82}; 83 84static XF86VideoFormatRec OverlayFormats[] = 85{ 86 {8, TrueColor}, {8, DirectColor}, {8, PseudoColor}, 87 {8, GrayScale}, {8, StaticGray}, {8, StaticColor}, 88 {15, TrueColor}, {16, TrueColor}, {24, TrueColor}, 89 {15, DirectColor}, {16, DirectColor}, {24, DirectColor} 90}; 91 92static XF86VideoFormatRec TextureFormats[] = 93{ 94 {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 95}; 96 97static XF86AttributeRec OverlayAttributes[] = 98{ 99 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 100 {XvSettable | XvGettable, 0, 1, "XV_FILTER_QUALITY"} 101}; 102 103static XF86AttributeRec TextureAttributes[] = 104{ 105 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 106 {XvSettable | XvGettable, 0, 1, "XV_FILTER_QUALITY"} 107}; 108 109static XF86ImageRec OverlayImages[] = 110{ 111 XVIMAGE_YUY2, XVIMAGE_UYVY, XVIMAGE_YV12, XVIMAGE_I420 112}; 113 114static XF86ImageRec TextureImages[] = 115{ 116 XVIMAGE_YV12, XVIMAGE_I420 117}; 118 119/* 120 * COMMON SETUP FUNCTIONS 121 */ 122 123void TDFXInitVideo(ScreenPtr pScreen) 124{ 125 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 126 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 127 XF86VideoAdaptorPtr newAdaptor = NULL; 128 TDFXPtr pTDFX = TDFXPTR(pScrn); 129 int num_adaptors; 130 131 /* The hardware can't convert YUV->8 bit color */ 132 if(pTDFX->cpp == 1) 133 return; 134 135 if (!pTDFX->TextureXvideo) { 136 /* Offscreen support for Overlay only */ 137 TDFXInitOffscreenImages(pScreen); 138 139 /* Overlay adaptor */ 140 newAdaptor = TDFXSetupImageVideoOverlay(pScreen); 141 } else { 142 /* Texture adaptor */ 143 newAdaptor = TDFXSetupImageVideoTexture(pScreen); 144 } 145 146 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 147 148 if(newAdaptor) { 149 if (!num_adaptors) { 150 num_adaptors = 1; 151 adaptors = &newAdaptor; 152 } else { 153 newAdaptors = 154 malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); 155 if(newAdaptors) { 156 memcpy(newAdaptors, adaptors, num_adaptors * 157 sizeof(XF86VideoAdaptorPtr)); 158 newAdaptors[num_adaptors] = newAdaptor; 159 adaptors = newAdaptors; 160 num_adaptors++; 161 } 162 } 163 } 164 165 if(num_adaptors) 166 xf86XVScreenInit(pScreen, adaptors, num_adaptors); 167 168 if(newAdaptors) 169 free(newAdaptors); 170} 171 172 173void TDFXCloseVideo (ScreenPtr pScreen) 174{ 175} 176 177 178static XF86VideoAdaptorPtr 179TDFXAllocAdaptor(ScrnInfoPtr pScrn, int numberPorts) 180{ 181 XF86VideoAdaptorPtr adapt; 182 TDFXPtr pTDFX = TDFXPTR(pScrn); 183 TDFXPortPrivPtr pPriv; 184 185 if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn))) 186 return NULL; 187 188 if(!(pPriv = calloc(1, sizeof(TDFXPortPrivRec) + (numberPorts * sizeof(DevUnion))))) 189 { 190 free(adapt); 191 return NULL; 192 } 193 194 adapt->pPortPrivates = (DevUnion*)(&pPriv[1]); 195 adapt->pPortPrivates[0].ptr = (pointer)pPriv; 196 197 xvColorKey = MAKE_ATOM("XV_COLORKEY"); 198 xvFilterQuality = MAKE_ATOM("XV_FILTER_QUALITY"); 199 200 pPriv->colorKey = pTDFX->videoKey; 201 pPriv->videoStatus = 0; 202 pPriv->filterQuality = 1; 203 204 return adapt; 205} 206 207 208static XF86VideoAdaptorPtr 209TDFXSetupImageVideoOverlay(ScreenPtr pScreen) 210{ 211 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 212 TDFXPtr pTDFX = TDFXPTR(pScrn); 213 TDFXPortPrivPtr pPriv; 214 XF86VideoAdaptorPtr adapt; 215 216 if(!(adapt = TDFXAllocAdaptor(pScrn, TDFX_MAX_OVERLAY_PORTS))) 217 return NULL; 218 219 adapt->type = XvWindowMask | XvInputMask | XvImageMask; 220 adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 221 adapt->name = "3dfx Video Overlay"; 222 adapt->nPorts = TDFX_MAX_OVERLAY_PORTS; 223 adapt->nEncodings = sizeof(OverlayEncoding) / sizeof(XF86VideoEncodingRec); 224 adapt->pEncodings = OverlayEncoding; 225 adapt->nFormats = sizeof(OverlayFormats) / sizeof(XF86VideoFormatRec); 226 adapt->pFormats = OverlayFormats; 227 adapt->nAttributes = sizeof(OverlayAttributes) / sizeof(XF86AttributeRec); 228 adapt->pAttributes = OverlayAttributes; 229 adapt->nImages = sizeof(OverlayImages) / sizeof(XF86ImageRec); 230 adapt->pImages = OverlayImages; 231 adapt->PutVideo = NULL; 232 adapt->PutStill = NULL; 233 adapt->GetVideo = NULL; 234 adapt->GetStill = NULL; 235 adapt->StopVideo = TDFXStopVideoOverlay; 236 adapt->SetPortAttribute = TDFXSetPortAttributeOverlay; 237 adapt->GetPortAttribute = TDFXGetPortAttributeOverlay; 238 adapt->QueryBestSize = TDFXQueryBestSize; 239 adapt->PutImage = TDFXPutImageOverlay; 240 adapt->QueryImageAttributes = TDFXQueryImageAttributes; 241 242 pTDFX->overlayAdaptor = adapt; 243 244 pPriv = (TDFXPortPrivPtr)(adapt->pPortPrivates[0].ptr); 245 REGION_NULL(pScreen, &(pPriv->clip)); 246 247 TDFXResetVideoOverlay(pScrn); 248 249 return adapt; 250} 251 252static XF86VideoAdaptorPtr 253TDFXSetupImageVideoTexture(ScreenPtr pScreen) 254{ 255 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 256 TDFXPtr pTDFX = TDFXPTR(pScrn); 257 XF86VideoAdaptorPtr adapt; 258 int i; 259 260 if(!(adapt = TDFXAllocAdaptor(pScrn, TDFX_MAX_TEXTURE_PORTS))) 261 return NULL; 262 263 adapt->type = XvWindowMask | XvInputMask | XvImageMask; 264 adapt->flags = VIDEO_OVERLAID_IMAGES; 265 adapt->name = "3dfx Video Texture"; 266 adapt->nPorts = TDFX_MAX_TEXTURE_PORTS; 267 adapt->nEncodings = sizeof(TextureEncoding) / sizeof(XF86VideoEncodingRec); 268 adapt->pEncodings = TextureEncoding; 269 adapt->nFormats = sizeof(TextureFormats) / sizeof(XF86VideoFormatRec); 270 adapt->pFormats = TextureFormats; 271 adapt->nAttributes = sizeof(TextureAttributes) / sizeof(XF86AttributeRec); 272 adapt->pAttributes = TextureAttributes; 273 adapt->nImages = sizeof(TextureImages) / sizeof(XF86ImageRec); 274 adapt->pImages = TextureImages; 275 adapt->PutVideo = NULL; 276 adapt->PutStill = NULL; 277 adapt->GetVideo = NULL; 278 adapt->GetStill = NULL; 279 adapt->StopVideo = TDFXStopVideoTexture; 280 adapt->SetPortAttribute = TDFXSetPortAttributeTexture; 281 adapt->GetPortAttribute = TDFXGetPortAttributeTexture; 282 adapt->QueryBestSize = TDFXQueryBestSize; 283 adapt->PutImage = TDFXPutImageTexture; 284 adapt->QueryImageAttributes = TDFXQueryImageAttributes; 285 286 for(i = 0; i < TDFX_MAX_TEXTURE_PORTS; i++) 287 adapt->pPortPrivates[i].val = i; 288 289 pTDFX->textureAdaptor = adapt; 290 291 return adapt; 292} 293 294 295/* 296 * MISCELLANEOUS ROUTINES 297 */ 298 299static int 300TDFXQueryImageAttributes( 301 ScrnInfoPtr pScrn, 302 int id, 303 unsigned short *w, unsigned short *h, 304 int *pitches, int *offsets 305){ 306 int size, tmp; 307 308 if(*w > 1024) *w = 1024; 309 if(*h > 1024) *h = 1024; 310 311 *w = (*w + 1) & ~1; 312 if(offsets) offsets[0] = 0; 313 314 switch(id) { 315 case FOURCC_YV12: 316 case FOURCC_I420: 317 *h = (*h + 1) & ~1; 318 size = (*w + 3) & ~3; 319 if(pitches) pitches[0] = size; 320 size *= *h; 321 if(offsets) offsets[1] = size; 322 tmp = ((*w >> 1) + 3) & ~3; 323 if(pitches) pitches[1] = pitches[2] = tmp; 324 tmp *= (*h >> 1); 325 size += tmp; 326 if(offsets) offsets[2] = size; 327 size += tmp; 328 break; 329 case FOURCC_UYVY: 330 case FOURCC_YUY2: 331 default: 332 size = *w << 1; 333 if(pitches) pitches[0] = size; 334 size *= *h; 335 break; 336 } 337 338 return size; 339} 340 341 342static int 343TDFXSetPortAttributeOverlay( 344 ScrnInfoPtr pScrn, 345 Atom attribute, 346 INT32 value, 347 pointer data 348){ 349 350 TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data; 351 TDFXPtr pTDFX = TDFXPTR(pScrn); 352 353 if(attribute == xvColorKey) { 354 pPriv->colorKey = value; 355 pTDFX->writeLong(pTDFX, VIDCHROMAMIN, pPriv->colorKey); 356 pTDFX->writeLong(pTDFX, VIDCHROMAMAX, pPriv->colorKey); 357 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 358 } else if(attribute == xvFilterQuality) { 359 if((value < 0) || (value > 1)) 360 return BadValue; 361 pPriv->filterQuality = value; 362 } else return BadMatch; 363 364 return Success; 365} 366 367static int 368TDFXGetPortAttributeOverlay( 369 ScrnInfoPtr pScrn, 370 Atom attribute, 371 INT32 *value, 372 pointer data 373){ 374 TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data; 375 376 if(attribute == xvColorKey) { 377 *value = pPriv->colorKey; 378 } else if(attribute == xvFilterQuality) { 379 *value = pPriv->filterQuality; 380 } else return BadMatch; 381 382 return Success; 383} 384 385 386static int 387TDFXSetPortAttributeTexture( 388 ScrnInfoPtr pScrn, 389 Atom attribute, 390 INT32 value, 391 pointer data 392) { 393 return Success; 394} 395 396 397static int 398TDFXGetPortAttributeTexture( 399 ScrnInfoPtr pScrn, 400 Atom attribute, 401 INT32 *value, 402 pointer data 403){ 404 return Success; 405} 406 407 408static void 409TDFXQueryBestSize( 410 ScrnInfoPtr pScrn, 411 Bool motion, 412 short vid_w, short vid_h, 413 short drw_w, short drw_h, 414 unsigned int *p_w, unsigned int *p_h, 415 pointer data 416){ 417 if(vid_w > drw_w) drw_w = vid_w; 418 if(vid_h > drw_h) drw_h = vid_h; 419 420 *p_w = drw_w; 421 *p_h = drw_h; 422} 423 424 425static void 426TDFXCopyData( 427 unsigned char *src, 428 unsigned char *dst, 429 int srcPitch, 430 int dstPitch, 431 int h, 432 int w 433){ 434#if X_BYTE_ORDER == X_BIG_ENDIAN 435 w >>= 1; 436 while(h--) { 437 int i; 438 for (i=0; i<w; i++) 439 ((unsigned long *)dst)[i]=BE_WSWAP32(((unsigned long *)src)[i]); 440 src += srcPitch; 441 dst += dstPitch; 442 } 443#else 444 w <<= 1; 445 while(h--) { 446 memcpy(dst, src, w); 447 src += srcPitch; 448 dst += dstPitch; 449 } 450#endif 451} 452 453static void 454TDFXCopyMungedData( 455 unsigned char *src1, 456 unsigned char *src2, 457 unsigned char *src3, 458 unsigned char *dst1, 459 int srcPitch, 460 int srcPitch2, 461 int dstPitch, 462 int h, 463 int w 464){ 465 CARD32 *dst; 466 CARD8 *s1, *s2, *s3; 467 int i, j; 468 469 w >>= 1; 470 471 for(j = 0; j < h; j++) { 472 dst = (CARD32*)dst1; 473 s1 = src1; s2 = src2; s3 = src3; 474 i = w; 475 while(i > 4) { 476 dst[0] = BE_WSWAP32(s1[0] | (s1[1] << 16) | (s3[0] << 8) | 477 (s2[0] << 24)); 478 dst[1] = BE_WSWAP32(s1[2] | (s1[3] << 16) | (s3[1] << 8) | 479 (s2[1] << 24)); 480 dst[2] = BE_WSWAP32(s1[4] | (s1[5] << 16) | (s3[2] << 8) | 481 (s2[2] << 24)); 482 dst[3] = BE_WSWAP32(s1[6] | (s1[7] << 16) | (s3[3] << 8) | 483 (s2[3] << 24)); 484 dst += 4; s2 += 4; s3 += 4; s1 += 8; 485 i -= 4; 486 } 487 while(i--) { 488 dst[0] = BE_WSWAP32(s1[0] | (s1[1] << 16) | (s3[0] << 8) | 489 (s2[0] << 24)); 490 dst++; s2++; s3++; 491 s1 += 2; 492 } 493 494 dst1 += dstPitch; 495 src1 += srcPitch; 496 if(j & 1) { 497 src2 += srcPitch2; 498 src3 += srcPitch2; 499 } 500 } 501} 502 503 504/* 505 * TEXTURE DRAWING FUNCTIONS 506 */ 507 508 509static void 510TDFXStopVideoTexture(ScrnInfoPtr pScrn, pointer data, Bool cleanup) 511{ 512 TDFXPtr pTDFX = TDFXPTR(pScrn); 513 514 if (cleanup) { 515 if(pTDFX->textureBuffer) { 516 xf86FreeOffscreenArea(pTDFX->textureBuffer); 517 pTDFX->textureBuffer = NULL; 518 } 519 } 520} 521 522 523static void 524TDFXScreenToScreenYUVStretchBlit (ScrnInfoPtr pScrn, 525 short src_x1, short src_y1, 526 short src_x2, short src_y2, 527 short dst_x1, short dst_y1, 528 short dst_x2, short dst_y2) 529{ 530 TDFXPtr pTDFX = TDFXPTR(pScrn); 531 /* reformulate the paramaters the way the hardware wants them */ 532 INT32 src_x = src_x1 & 0x1FFF; 533 INT32 src_y = src_y1 & 0x1FFF; 534 INT32 dst_x = dst_x1 & 0x1FFF; 535 INT32 dst_y = dst_y1 & 0x1FFF; 536 INT32 src_w = (src_x2 - src_x1) & 0x1FFF; 537 INT32 src_h = (src_y2 - src_y1) & 0x1FFF; 538 INT32 dst_w = (dst_x2 - dst_x1) & 0x1FFF; 539 INT32 dst_h = (dst_y2 - dst_y1) & 0x1FFF; 540 541 /* Setup for blit src and dest */ 542 TDFXMakeRoom(pTDFX, 4); 543 DECLARE(SSTCP_DSTSIZE|SSTCP_SRCSIZE|SSTCP_DSTXY|SSTCP_COMMAND/*|SSTCP_COMMANDEXTRA*/); 544 /* TDFXWriteLong(pTDFX, SST_2D_COMMANDEXTRA, SST_COMMANDEXTRA_VSYNC);*/ 545 TDFXWriteLong(pTDFX, SST_2D_SRCSIZE, src_w | (src_h<<16)); 546 TDFXWriteLong(pTDFX, SST_2D_DSTSIZE, dst_w | (dst_h<<16)); 547 TDFXWriteLong(pTDFX, SST_2D_DSTXY, dst_x | (dst_y<<16)); 548 TDFXWriteLong(pTDFX, SST_2D_COMMAND, SST_2D_SCRNTOSCRNSTRETCH | 0xCC000000); 549 /* Write to the launch area to start the blit */ 550 TDFXMakeRoom(pTDFX, 1); 551 DECLARE_LAUNCH(1, 0); 552 TDFXWriteLong(pTDFX, SST_2D_LAUNCH, (src_x<<1) | (src_y<<16)); 553 /* Wait for it to happen */ 554 TDFXSendNOPFifo2D(pScrn); 555} 556 557 558static void 559YUVPlanarToPacked (ScrnInfoPtr pScrn, 560 short src_x, short src_y, 561 short src_h, short src_w, 562 int id, unsigned char *buf, 563 short width, short height, 564 FBAreaPtr fbarea) 565{ 566 TDFXPtr pTDFX = TDFXPTR(pScrn); 567 unsigned char *psrc, *pdst; 568 int count; 569 int baseaddr; 570 INT32 yuvBaseAddr, yuvStride; 571 572 /* Save these registers so I can restore them when we are done. */ 573 yuvBaseAddr = TDFXReadLongMMIO(pTDFX, YUVBASEADDR); 574 yuvStride = TDFXReadLongMMIO(pTDFX, YUVSTRIDE); 575 576 /* Set yuvBaseAddress and yuvStride. */ 577 baseaddr = pTDFX->fbOffset + pTDFX->cpp * fbarea->box.x1 + pTDFX->stride * fbarea->box.y1; 578 TDFXWriteLongMMIO(pTDFX, YUVSTRIDE, pTDFX->stride); 579 TDFXWriteLongMMIO(pTDFX, YUVBASEADDR, baseaddr); 580 581 /* Copy Y plane (twice as much Y as U or V) */ 582 psrc = buf; 583 psrc += (src_x & ~0x1) + src_y * width; 584 pdst = pTDFX->MMIOBase[0] + YUV_Y_BASE; 585 TDFXCopyData(psrc, pdst, width, 1024, src_h, src_w + (src_x & 0x1)); 586 587 /* Copy V plane */ 588 psrc = buf + width * height; 589 psrc += (src_x >> 1) + (src_y >> 1) * (width >> 1); 590 pdst = pTDFX->MMIOBase[0] + YUV_V_BASE; 591 TDFXCopyData(psrc, pdst, width >> 1, 1024, src_h >> 1, src_w >> 1); 592 593 /* Copy U plane */ 594 psrc = buf + width * height + (width >> 1) * (height >> 1); 595 psrc += (src_x >> 1) + (src_y >> 1) * (width >> 1); 596 pdst = pTDFX->MMIOBase[0] + YUV_U_BASE; 597 TDFXCopyData(psrc, pdst, width >> 1, 1024, src_h >> 1, src_w >> 1); 598 599 /* IDLE until the copy finished, timeout for safety */ 600 for (count = 0; count < 1000; count++) 601 if (!((TDFXReadLongMMIO(pTDFX, STATUS) & SST_BUSY))) 602 break; 603 604 /* Restore trashed registers */ 605 TDFXWriteLongMMIO(pTDFX, YUVBASEADDR, yuvBaseAddr); 606 TDFXWriteLongMMIO(pTDFX, YUVSTRIDE, yuvStride); 607 608 /* Wait for it to happen */ 609 TDFXSendNOPFifo2D(pScrn); 610} 611 612 613static int 614TDFXPutImageTexture( 615 ScrnInfoPtr pScrn, 616 short src_x, short src_y, 617 short drw_x, short drw_y, 618 short src_w, short src_h, 619 short drw_w, short drw_h, 620 int id, unsigned char* buf, 621 short width, short height, 622 Bool sync, 623 RegionPtr clipBoxes, pointer data, 624 DrawablePtr pDraw 625 ) 626{ 627 TDFXPtr pTDFX = TDFXPTR(pScrn); 628 BoxPtr pbox; 629 int nbox; 630 int format; 631 632 TDFXTRACE("TDFXPutImageTexture(src_x=%d, src_y=%d, drw_x=%d, drw_y=%d, .. sync=%d\n", 633 src_x, src_y, drw_x, drw_y, sync); 634 635 /* Check the source format */ 636 if (id == FOURCC_YV12) format = SST_2D_FORMAT_YUYV; 637 else if (id == FOURCC_UYVY) format = SST_2D_FORMAT_UYVY; 638 else return BadAlloc; 639 640 /* Get a buffer to store the packed YUV data */ 641 if (!(pTDFX->textureBuffer = TDFXAllocateMemoryArea(pScrn, pTDFX->textureBuffer, src_w, src_h))) 642 return BadAlloc; 643 644 /* Pack the YUV data in offscreen memory using YUV framebuffer (0x[CDE]0000) */ 645 YUVPlanarToPacked (pScrn, src_x, src_y, src_h, src_w, 646 id, buf, width, height, 647 pTDFX->textureBuffer); 648 649 /* Setup source and destination pixel formats (yuv -> rgb) */ 650 TDFXMakeRoom(pTDFX, 2); 651 DECLARE(SSTCP_SRCFORMAT|SSTCP_DSTFORMAT); 652 TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, pTDFX->stride|((pTDFX->cpp+1)<<16)); 653 TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, pTDFX->stride|((format)<<16)); 654 655 /* Blit packed YUV data from offscreen memory, respecting clips */ 656#define SRC_X1 (pTDFX->textureBuffer->box.x1) 657#define SRC_Y1 (pTDFX->textureBuffer->box.y1) 658#define SCALEX(dx) ((int)(((dx) * src_w) / drw_w)) 659#define SCALEY(dy) ((int)(((dy) * src_h) / drw_h)) 660 for (nbox = REGION_NUM_RECTS(clipBoxes), 661 pbox = REGION_RECTS(clipBoxes); nbox > 0; nbox--, pbox++) 662 { 663 TDFXScreenToScreenYUVStretchBlit (pScrn, 664 SRC_X1 + SCALEX(pbox->x1 - drw_x), 665 SRC_Y1 + SCALEY(pbox->y1 - drw_y), 666 SRC_X1 + SCALEX(pbox->x2 - drw_x), 667 SRC_Y1 + SCALEY(pbox->y2 - drw_y), 668 pbox->x1, pbox->y1, 669 pbox->x2, pbox->y2); 670 } 671 672 /* Restore the WAX registers we trashed */ 673 TDFXMakeRoom(pTDFX, 2); 674 DECLARE(SSTCP_SRCFORMAT|SSTCP_DSTFORMAT); 675 TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, pTDFX->sst2DDstFmtShadow); 676 TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, pTDFX->sst2DSrcFmtShadow); 677 678 /* Wait for it to happen */ 679 TDFXSendNOPFifo2D(pScrn); 680 681 return Success; 682} 683 684 685/* 686 * OVERLAY DRAWING FUNCTIONS 687 */ 688 689 690static void 691TDFXResetVideoOverlay(ScrnInfoPtr pScrn) 692{ 693 TDFXPtr pTDFX = TDFXPTR(pScrn); 694 TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr; 695 696 /* reset the video */ 697 pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK; 698 pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg); 699 pTDFX->writeLong(pTDFX, RGBMAXDELTA, 0x0080808); 700 pTDFX->writeLong(pTDFX, VIDCHROMAMIN, pPriv->colorKey); 701 pTDFX->writeLong(pTDFX, VIDCHROMAMAX, pPriv->colorKey); 702} 703 704 705static void 706TDFXStopVideoOverlay(ScrnInfoPtr pScrn, pointer data, Bool cleanup) 707{ 708 TDFXPtr pTDFX = TDFXPTR(pScrn); 709 TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data; 710 711 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 712 713 if(cleanup) { 714 if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 715 pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK; 716 pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg); 717 } 718 if(pTDFX->overlayBuffer) { 719 xf86FreeOffscreenLinear(pTDFX->overlayBuffer); 720 pTDFX->overlayBuffer = NULL; 721 } 722 if(pTDFX->overlayBuffer2) { 723 xf86FreeOffscreenLinear(pTDFX->overlayBuffer2); 724 pTDFX->overlayBuffer2 = NULL; 725 } 726 pPriv->videoStatus = 0; 727 } else { 728 if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 729 pPriv->videoStatus |= OFF_TIMER; 730 pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 731 } 732 } 733} 734 735 736/* * * * * * 737 738Decoder... 739 740VIDPROCCFG: 0x5c: Video Processor Configuration register 741 742#define VIDPROCCFGMASK 0xa2e3eb6c 743 3 2 1 0 744 10987654321098765432109876543210 745 10100010111000111110101101101100 746 747The "1" bits are the bits cleared to 0 in pTDFX->ModeReg.vidcfg 748 749 750Then we or in 0x320: 751 752 11 753 109876543210 754320 = 001100100000 755 756bit 11=0: Do not bypass clut (colour lookup) for overlay 757bit 10=0: Do not bypass clut for desktop 758bit 9=1: use video-in buffer address as overlay start 759 address (auto-flipping) 760bit 8=1: fetch overlay surface 761bit 7=0: do not fetch the desktop surface (?) 762bit 6=0: chromakey not inverted 763bit 5=1: chromakey enabled 764bit 4=0: half-mode disabled 765bit 3=0: not interlaced (interlace doesn't work on Avenger) 766bit 2=0: overlay stereo disabled 767bit 1=0: Windows cursor mode 768bit 0=0: Video processor off, VGA mode on 769 770SST_VIDEO_2X_MODE_EN: bit26: means 2 pixels per screen clock mode is on 771 772VIDOVERLAYSTARTCOORDS: x&y coords of overlay on the screen 773VIDOVERLAYENDSCREENCOORDS: x&y coorder of bot-right of overlay on the screen 774VIDOVERLAYDUDX: step size in source per hoz step in screen space (x-mag) 775VIDOVERLAYDUDXOFFSETSRCWIDTH: 776VIDOVERLAYDVDY: step size in sourcxe per vertical step in screen (y-mag) 777VIDOVERLAYDVDYOFFSET: initial offset of DVDY 778VIDDESKTOPOVERLAYSTRIDE: desktop surface stride 779 780SST_3D_LEFTOVERLAYBUF: starting physical address of the overlay surface buffer 781VIDINADDR0: starting address of video-in buffer-0 782 [this is set, but this is for video _input_ as I understand docs...?] 783 784* * * * * */ 785 786static void 787TDFXDisplayVideoOverlay( 788 ScrnInfoPtr pScrn, 789 int id, 790 int offset, 791 short width, short height, 792 int pitch, 793 int left, int right, int top, 794 BoxPtr dstBox, 795 short src_w, short src_h, 796 short drw_w, short drw_h 797){ 798 TDFXPtr pTDFX = TDFXPTR(pScrn); 799 TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr; 800 int dudx, dvdy; 801 802 dudx = (src_w << 20) / drw_w; 803 /* subtract 1 to eliminate garbage on last line */ 804 dvdy = (( src_h - 1 )<< 20) / drw_h; 805 806 offset += ((left >> 16) & ~1) << 1; 807 left = (left & 0x0001ffff) << 3; 808 809 pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK; 810 pTDFX->ModeReg.vidcfg |= 0x00000320; 811 812 if(drw_w != src_w) pTDFX->ModeReg.vidcfg |= (1 << 14); 813 if(drw_h != src_h) pTDFX->ModeReg.vidcfg |= (1 << 15); 814 if(id == FOURCC_UYVY) pTDFX->ModeReg.vidcfg |= (6 << 21); 815 else pTDFX->ModeReg.vidcfg |= (5 << 21); 816 if(pScrn->depth == 8) pTDFX->ModeReg.vidcfg |= (1 << 11); 817 /* can't do bilinear filtering when in 2X mode */ 818 if(pPriv->filterQuality && !(pTDFX->ModeReg.vidcfg & SST_VIDEO_2X_MODE_EN)) 819 pTDFX->ModeReg.vidcfg |= (3 << 16); 820 pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg); 821 822 pTDFX->writeLong(pTDFX, VIDOVERLAYSTARTCOORDS, dstBox->x1 | (dstBox->y1 << 12)); 823 pTDFX->writeLong(pTDFX, VIDOVERLAYENDSCREENCOORDS, (dstBox->x2 - 1) | ((dstBox->y2 - 1) << 12)); 824 pTDFX->writeLong(pTDFX, VIDOVERLAYDUDX, dudx); 825 pTDFX->writeLong(pTDFX, VIDOVERLAYDUDXOFFSETSRCWIDTH, left | (src_w << 20)); 826 pTDFX->writeLong(pTDFX, VIDOVERLAYDVDY, dvdy); 827 pTDFX->writeLong(pTDFX, VIDOVERLAYDVDYOFFSET, (top & 0x0000ffff) << 3); 828 829 pTDFX->ModeReg.stride &= 0x0000ffff; 830 pTDFX->ModeReg.stride |= pitch << 16; 831 pTDFX->writeLong(pTDFX, VIDDESKTOPOVERLAYSTRIDE, pTDFX->ModeReg.stride); 832 pTDFX->writeLong(pTDFX, SST_3D_LEFTOVERLAYBUF, offset & ~3); 833 pTDFX->writeLong(pTDFX, VIDINADDR0, offset & ~3); 834 TDFXTRACE("TDFXDisplayVideoOverlay: done, offset=0x%x\n", offset); 835} 836 837 838#if 0 839 840/* * * * * 841 842TDFXSwapVideoOverlayBuffer tries to use the Avenger SWAPBUFFER 843capability to change frames without tearing. 844 845Use this in preference to TDFXDisplayVideoOverlay where all image 846parameters are the same as the previous frame - ie where only the 847SST_3D_LEFTOVERLAYBUF register would have been changed. 848 849NOTE: Work in progress - doesn't seem to sync to VSYNC, and only every 850other frame gets displayed... 851 852Seeing that the buffer swap initiated by DisplayVideoOverlay gets 853synced to VSYNC anyway, just adding double-buffering to PutImageOverlay 854appears to do the job. Still - I leave this code in in case we can 855get it working later 856 857 -- Steve Davies 2002-10-04 858 -- <steve@daviesfam.org> 859 860* * * * * */ 861 862static void 863TDFXSwapVideoOverlayBuffer( 864 ScrnInfoPtr pScrn, 865 int offset, 866 int left 867){ 868 TDFXPtr pTDFX = TDFXPTR(pScrn); 869 offset += ((left >> 16) & ~1) << 1; 870 /* Write mew buffer address */ 871 pTDFX->writeLong(pTDFX, SST_3D_LEFTOVERLAYBUF, offset & ~3); 872 /* Incremement the swap-pending counter */ 873 pTDFX->writeLong(pTDFX, SST_3D_SWAPPENDING, 0); 874 /* write the swapbuffer command - triggered by (next) VSYNC */ 875 pTDFX->writeLong(pTDFX, SST_3D_SWAPBUFFERCMD, 1); 876} 877 878#endif 879 880static int 881TDFXPutImageOverlay( 882 ScrnInfoPtr pScrn, 883 short src_x, short src_y, 884 short drw_x, short drw_y, 885 short src_w, short src_h, 886 short drw_w, short drw_h, 887 int id, unsigned char* buf, 888 short width, short height, 889 Bool Sync, 890 RegionPtr clipBoxes, pointer data, 891 DrawablePtr pDraw 892){ 893 TDFXPtr pTDFX = TDFXPTR(pScrn); 894 TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data; 895 INT32 xa, xb, ya, yb; 896 unsigned char *dst_start; 897 int new_size, offset; 898 int s2offset = 0, s3offset = 0; 899 int srcPitch = 0, srcPitch2 = 0; 900 int dstPitch; 901 int top, left, npixels, nlines, bpp; 902 BoxRec dstBox; 903 CARD32 tmp; 904 905 TDFXTRACE("TDFXPutImageOverlay: src_x=%d, src_y=%d, drw_x=%d, drw_y=%d, src_w=%d, src_h=%d, drw_w=%d, drw_h=%d, id=%d, width=%d, height=%d, sync=%d\n", 906 src_x, src_y, drw_x, drw_y, src_w, src_h, drw_w, drw_h, id, width, height, Sync); 907 908 /* 909 * s2offset, s3offset - byte offsets into U and V plane of the 910 * source where copying starts. Y plane is 911 * done by editing "buf". 912 * 913 * offset - byte offset to the first line of the destination. 914 * 915 * dst_start - byte address to the first displayed pel. 916 * 917 */ 918 919 if(src_w > drw_w) drw_w = src_w; 920 if(src_h > drw_h) drw_h = src_h; 921 922 /* Clip */ 923 xa = src_x; 924 xb = src_x + src_w; 925 ya = src_y; 926 yb = src_y + src_h; 927 928 dstBox.x1 = drw_x; 929 dstBox.x2 = drw_x + drw_w; 930 dstBox.y1 = drw_y; 931 dstBox.y2 = drw_y + drw_h; 932 933 if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, 934 clipBoxes, width, height)) 935 return Success; 936 937 dstBox.x1 -= pScrn->frameX0; 938 dstBox.x2 -= pScrn->frameX0; 939 dstBox.y1 -= pScrn->frameY0; 940 dstBox.y2 -= pScrn->frameY0; 941 942 bpp = pScrn->bitsPerPixel >> 3; 943 944 switch(id) { 945 case FOURCC_YV12: 946 case FOURCC_I420: 947 dstPitch = ((width << 1) + 3) & ~3; 948 new_size = ((dstPitch * height) + bpp - 1) / bpp; 949 srcPitch = (width + 3) & ~3; 950 s2offset = srcPitch * height; 951 srcPitch2 = ((width >> 1) + 3) & ~3; 952 s3offset = (srcPitch2 * (height >> 1)) + s2offset; 953 break; 954 case FOURCC_UYVY: 955 case FOURCC_YUY2: 956 default: 957 dstPitch = ((width << 1) + 3) & ~3; 958 new_size = ((dstPitch * height) + bpp - 1) / bpp; 959 srcPitch = (width << 1); 960 break; 961 } 962 963 if(!(pTDFX->overlayBuffer = TDFXAllocateMemoryLinear(pScrn, pTDFX->overlayBuffer, new_size))) 964 return BadAlloc; 965 /* Second buffer for double-buffering (If we can't get the memory then we just don't double-buffer) */ 966 if (!(pTDFX->overlayBuffer2 = TDFXAllocateMemoryLinear(pScrn, pTDFX->overlayBuffer2, new_size))) 967 pTDFX->whichOverlayBuffer = 0; 968 TDFXTRACE("TDFXPutImageOverlay: %s have a second overlay buffer for double-buffering\n", 969 pTDFX->overlayBuffer2 ? "Do" : "Do not"); 970 971 /* copy data */ 972 top = ya >> 16; 973 left = (xa >> 16) & ~1; 974 npixels = ((((xb + 0xffff) >> 16) + 1) & ~1) - left; 975 976 /* Get buffer offset */ 977 if (pTDFX->whichOverlayBuffer == 0) 978 offset = (pTDFX->overlayBuffer->offset * bpp) + (top * dstPitch) + pTDFX->fbOffset; 979 else 980 offset = (pTDFX->overlayBuffer2->offset * bpp) + (top * dstPitch) + pTDFX->fbOffset; 981 982 /* Flip to other buffer for next time */ 983 pTDFX->whichOverlayBuffer ^= 1; 984 985 dst_start = pTDFX->FbBase + offset; 986 987 switch(id) { 988 case FOURCC_YV12: 989 case FOURCC_I420: 990 top &= ~1; 991 dst_start += left << 1; 992 tmp = ((top >> 1) * srcPitch2) + (left >> 1); 993 s2offset += tmp; 994 s3offset += tmp; 995 if(id == FOURCC_I420) { 996 tmp = s2offset; 997 s2offset = s3offset; 998 s3offset = tmp; 999 } 1000 nlines = ((((yb + 0xffff) >> 16) + 1) & ~1) - top; 1001 TDFXTRACE("TDFXPutImageOverlay: using copymungeddata\n"); 1002 TDFXCopyMungedData(buf + (top * srcPitch) + left, buf + s2offset, 1003 buf + s3offset, dst_start, srcPitch, srcPitch2, 1004 dstPitch, nlines, npixels); 1005 break; 1006 case FOURCC_UYVY: 1007 case FOURCC_YUY2: 1008 default: 1009 left <<= 1; 1010 buf += (top * srcPitch) + left; 1011 nlines = ((yb + 0xffff) >> 16) - top; 1012 dst_start += left; 1013 TDFXTRACE("TDFXPutImageOverlay: using copydata\n"); 1014 TDFXCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels); 1015 break; 1016 } 1017 1018 if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { 1019 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 1020 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 1021 } 1022 1023 TDFXDisplayVideoOverlay(pScrn, id, offset, width, height, dstPitch, xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h); 1024 1025 pPriv->videoStatus = CLIENT_VIDEO_ON; 1026 1027 pTDFX->VideoTimerCallback = TDFXVideoTimerCallback; 1028 1029 /* Display some swap-buffer related info...: vidCurrOverlayStartAddr, fbiSwapHistory */ 1030 /* To give us some insight into workings or otherwise of swapbuffer stuff */ 1031 TDFXTRACE("TDFXPutImageOverlay: vidCurrOverlayStrtAdr=%x, fbiSwpHist=%x, whchBuf=%d, 3Dstus=%x\n", 1032 pTDFX->readLong(pTDFX, VIDCUROVERLAYSTARTADDR), 1033 pTDFX->readLong(pTDFX, SST_3D_FBISWAPHISTORY), 1034 pTDFX->whichOverlayBuffer, 1035 pTDFX->readLong(pTDFX, SST_3D_STATUS) 1036 ); 1037 1038 return Success; 1039} 1040 1041 1042static void 1043TDFXVideoTimerCallback(ScrnInfoPtr pScrn, Time time) 1044{ 1045 TDFXPtr pTDFX = TDFXPTR(pScrn); 1046 TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr; 1047 1048 if(pPriv->videoStatus & TIMER_MASK) { 1049 if(pPriv->videoStatus & OFF_TIMER) { 1050 if(pPriv->offTime < time) { 1051 pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK; 1052 pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg); 1053 pPriv->videoStatus = FREE_TIMER; 1054 pPriv->freeTime = time + FREE_DELAY; 1055 } 1056 } else 1057 if(pPriv->videoStatus & FREE_TIMER) { 1058 if(pPriv->freeTime < time) { 1059 if(pTDFX->overlayBuffer) { 1060 xf86FreeOffscreenLinear(pTDFX->overlayBuffer); 1061 pTDFX->overlayBuffer = NULL; 1062 } 1063 if(pTDFX->overlayBuffer2) { 1064 xf86FreeOffscreenLinear(pTDFX->overlayBuffer2); 1065 pTDFX->overlayBuffer2 = NULL; 1066 } 1067 pPriv->videoStatus = 0; 1068 pTDFX->VideoTimerCallback = NULL; 1069 } 1070 } 1071 } else /* shouldn't get here */ 1072 pTDFX->VideoTimerCallback = NULL; 1073} 1074 1075 1076/* 1077 * MEMORY MANAGEMENT 1078 */ 1079 1080 1081static FBAreaPtr 1082TDFXAllocateMemoryArea (ScrnInfoPtr pScrn, FBAreaPtr area, int width, int height) 1083{ 1084 TDFXPtr pTDFX = TDFXPTR(pScrn); 1085 ScreenPtr pScreen; 1086 FBAreaPtr new_area; 1087 1088 if (area) { 1089 if ((area->box.x2 - area->box.x1 >= width) && 1090 (area->box.y2 - area->box.y1 >= height)) 1091 return area; 1092 1093 if (xf86ResizeOffscreenArea(area, width, height)) 1094 return area; 1095 1096 xf86FreeOffscreenArea(area); 1097 } 1098 1099 pScreen = xf86ScrnToScreen(pScrn); 1100 1101 new_area = xf86AllocateOffscreenArea(pScreen, width, height, pTDFX->cpp, NULL, NULL, NULL); 1102 1103 if (!new_area) { 1104 int max_width, max_height; 1105 1106 xf86QueryLargestOffscreenArea(pScreen, &max_width, &max_height, pTDFX->cpp, 0, PRIORITY_EXTREME); 1107 1108 if (max_width < width || max_height < height) 1109 return NULL; 1110 1111 xf86PurgeUnlockedOffscreenAreas(pScreen); 1112 new_area = xf86AllocateOffscreenArea(pScreen, width, height, pTDFX->cpp, NULL, NULL, NULL); 1113 } 1114 1115 return new_area; 1116} 1117 1118 1119static FBLinearPtr 1120TDFXAllocateMemoryLinear (ScrnInfoPtr pScrn, FBLinearPtr linear, int size) 1121{ 1122 ScreenPtr pScreen; 1123 FBLinearPtr new_linear; 1124 1125 if(linear) { 1126 if(linear->size >= size) 1127 return linear; 1128 1129 if(xf86ResizeOffscreenLinear(linear, size)) 1130 return linear; 1131 1132 xf86FreeOffscreenLinear(linear); 1133 } 1134 1135 pScreen = xf86ScrnToScreen(pScrn); 1136 1137 new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, NULL, NULL, NULL); 1138 1139 if(!new_linear) { 1140 int max_size; 1141 1142 xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4, PRIORITY_EXTREME); 1143 1144 if(max_size < size) 1145 return NULL; 1146 1147 xf86PurgeUnlockedOffscreenAreas(pScreen); 1148 new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, NULL, NULL, NULL); 1149 } 1150 1151 return new_linear; 1152} 1153 1154/****************** Offscreen stuff ***************/ 1155 1156typedef struct { 1157 FBLinearPtr linear; 1158 Bool isOn; 1159} OffscreenPrivRec, * OffscreenPrivPtr; 1160 1161static int 1162TDFXAllocateSurface( 1163 ScrnInfoPtr pScrn, 1164 int id, 1165 unsigned short w, 1166 unsigned short h, 1167 XF86SurfacePtr surface 1168){ 1169 TDFXPtr pTDFX = TDFXPTR(pScrn); 1170 FBLinearPtr linear; 1171 int pitch, size, bpp; 1172 OffscreenPrivPtr pPriv; 1173 1174 if((w > 2048) || (h > 2048)) 1175 return BadAlloc; 1176 1177 w = (w + 1) & ~1; 1178 pitch = ((w << 1) + 15) & ~15; 1179 bpp = pScrn->bitsPerPixel >> 3; 1180 size = ((pitch * h) + bpp - 1) / bpp; 1181 1182 if(!(linear = TDFXAllocateMemoryLinear(pScrn, NULL, size))) 1183 return BadAlloc; 1184 1185 surface->width = w; 1186 surface->height = h; 1187 1188 if(!(surface->pitches = malloc(sizeof(int)))) { 1189 xf86FreeOffscreenLinear(linear); 1190 return BadAlloc; 1191 } 1192 if(!(surface->offsets = malloc(sizeof(int)))) { 1193 free(surface->pitches); 1194 xf86FreeOffscreenLinear(linear); 1195 return BadAlloc; 1196 } 1197 if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) { 1198 free(surface->pitches); 1199 free(surface->offsets); 1200 xf86FreeOffscreenLinear(linear); 1201 return BadAlloc; 1202 } 1203 1204 pPriv->linear = linear; 1205 pPriv->isOn = FALSE; 1206 1207 surface->pScrn = pScrn; 1208 surface->id = id; 1209 surface->pitches[0] = pitch; 1210 surface->offsets[0] = pTDFX->fbOffset + (linear->offset * bpp); 1211 surface->devPrivate.ptr = (pointer)pPriv; 1212 1213 return Success; 1214} 1215 1216static int 1217TDFXStopSurface( 1218 XF86SurfacePtr surface 1219){ 1220 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 1221 1222 if(pPriv->isOn) { 1223 TDFXPtr pTDFX = TDFXPTR(surface->pScrn); 1224 pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK; 1225 pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg); 1226 pPriv->isOn = FALSE; 1227 } 1228 1229 return Success; 1230} 1231 1232 1233static int 1234TDFXFreeSurface( 1235 XF86SurfacePtr surface 1236){ 1237 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 1238 1239 if(pPriv->isOn) 1240 TDFXStopSurface(surface); 1241 xf86FreeOffscreenLinear(pPriv->linear); 1242 free(surface->pitches); 1243 free(surface->offsets); 1244 free(surface->devPrivate.ptr); 1245 1246 return Success; 1247} 1248 1249static int 1250TDFXGetSurfaceAttribute( 1251 ScrnInfoPtr pScrn, 1252 Atom attribute, 1253 INT32 *value 1254){ 1255 return TDFXGetPortAttributeOverlay(pScrn, attribute, value, 1256 (pointer)(GET_PORT_PRIVATE(pScrn))); 1257} 1258 1259static int 1260TDFXSetSurfaceAttribute( 1261 ScrnInfoPtr pScrn, 1262 Atom attribute, 1263 INT32 value 1264){ 1265 return TDFXSetPortAttributeOverlay(pScrn, attribute, value, 1266 (pointer)(GET_PORT_PRIVATE(pScrn))); 1267} 1268 1269static int 1270TDFXDisplaySurface( 1271 XF86SurfacePtr surface, 1272 short src_x, short src_y, 1273 short drw_x, short drw_y, 1274 short src_w, short src_h, 1275 short drw_w, short drw_h, 1276 RegionPtr clipBoxes 1277){ 1278 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 1279 ScrnInfoPtr pScrn = surface->pScrn; 1280 TDFXPtr pTDFX = TDFXPTR(pScrn); 1281 TDFXPortPrivPtr portPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr; 1282 INT32 x1, y1, x2, y2; 1283 BoxRec dstBox; 1284 1285 x1 = src_x; 1286 x2 = src_x + src_w; 1287 y1 = src_y; 1288 y2 = src_y + src_h; 1289 1290 dstBox.x1 = drw_x; 1291 dstBox.x2 = drw_x + drw_w; 1292 dstBox.y1 = drw_y; 1293 dstBox.y2 = drw_y + drw_h; 1294 1295 if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, 1296 surface->width, surface->height)) 1297 { 1298 return Success; 1299 } 1300 1301 dstBox.x1 -= pScrn->frameX0; 1302 dstBox.x2 -= pScrn->frameX0; 1303 dstBox.y1 -= pScrn->frameY0; 1304 dstBox.y2 -= pScrn->frameY0; 1305 1306#if 0 1307 TDFXResetVideoOverlay(pScrn); 1308#endif 1309 1310 TDFXDisplayVideoOverlay(pScrn, surface->id, surface->offsets[0], 1311 surface->width, surface->height, surface->pitches[0], 1312 x1, y1, x2, &dstBox, src_w, src_h, drw_w, drw_h); 1313 1314 xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes); 1315 1316 pPriv->isOn = TRUE; 1317 /* we've prempted the XvImage stream so set its free timer */ 1318 if(portPriv->videoStatus & CLIENT_VIDEO_ON) { 1319 REGION_EMPTY(pScrn->pScreen, &portPriv->clip); 1320 UpdateCurrentTime(); 1321 portPriv->videoStatus = FREE_TIMER; 1322 portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 1323 pTDFX->VideoTimerCallback = TDFXVideoTimerCallback; 1324 } 1325 1326 return Success; 1327} 1328 1329static void 1330TDFXInitOffscreenImages(ScreenPtr pScreen) 1331{ 1332 XF86OffscreenImagePtr offscreenImages; 1333 1334 /* need to free this someplace */ 1335 if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec)))) 1336 return; 1337 1338 offscreenImages[0].image = &OverlayImages[0]; 1339 offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | 1340 VIDEO_CLIP_TO_VIEWPORT; 1341 offscreenImages[0].alloc_surface = TDFXAllocateSurface; 1342 offscreenImages[0].free_surface = TDFXFreeSurface; 1343 offscreenImages[0].display = TDFXDisplaySurface; 1344 offscreenImages[0].stop = TDFXStopSurface; 1345 offscreenImages[0].setAttribute = TDFXSetSurfaceAttribute; 1346 offscreenImages[0].getAttribute = TDFXGetSurfaceAttribute; 1347 offscreenImages[0].max_width = 2048; 1348 offscreenImages[0].max_height = 2048; 1349 offscreenImages[0].num_attributes = 2; 1350 offscreenImages[0].attributes = OverlayAttributes; 1351 1352 xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); 1353} 1354