pm3_video.c revision c35d236e
1/* 2 * Copyright 2001 by Alan Hourihane, Sychdyn, North Wales. 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of Alan Hourihane not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. Alan Hourihane makes no representations 11 * about the suitability of this software for any purpose. It is provided 12 * "as is" without express or implied warranty. 13 * 14 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 * 22 * Authors: Alan Hourihane, alanh@fairlite.demon.co.uk 23 * Sven Luther <luther@dpt-info.u-strasbg.fr> 24 */ 25/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/glint/pm3_video.c,v 1.14tsi Exp $ */ 26 27#ifdef HAVE_CONFIG_H 28#include "config.h" 29#endif 30 31#include "xf86.h" 32#include "xf86_OSproc.h" 33#include "xf86Resources.h" 34#include "compiler.h" 35#include "xf86PciInfo.h" 36#include "xf86Pci.h" 37#include "xf86fbman.h" 38#include "regionstr.h" 39 40#include "glint.h" 41#include "glint_regs.h" 42#include "pm3_regs.h" 43#include <X11/extensions/Xv.h> 44#include "xaa.h" 45#include "xaalocal.h" 46#include "dixstruct.h" 47#include "fourcc.h" 48 49#define OFF_DELAY 200 /* milliseconds */ 50#define FREE_DELAY 60000 51 52#define OFF_TIMER 0x01 53#define FREE_TIMER 0x02 54#define CLIENT_VIDEO_ON 0x04 55 56#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 57 58static XF86VideoAdaptorPtr Permedia3SetupImageVideo(ScreenPtr); 59static void Permedia3InitOffscreenImages(ScreenPtr); 60static void Permedia3StopVideo(ScrnInfoPtr, pointer, Bool); 61static int Permedia3SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 62static int Permedia3GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); 63static void Permedia3QueryBestSize(ScrnInfoPtr, Bool, 64 short, short, short, short, unsigned int *, unsigned int *, pointer); 65static int Permedia3PutImage( ScrnInfoPtr, 66 short, short, short, short, short, short, short, short, 67 int, unsigned char*, short, short, Bool, RegionPtr, pointer, 68 DrawablePtr); 69static int Permedia3QueryImageAttributes(ScrnInfoPtr, 70 int, unsigned short *, unsigned short *, int *, int *); 71static void Permedia3VideoTimerCallback(ScrnInfoPtr pScrn, Time time); 72 73#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 74 75static Atom xvColorKey, xvDoubleBuffer, xvAutopaintColorKey, xvFilter; 76 77void Permedia3InitVideo(ScreenPtr pScreen) 78{ 79 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 80 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 81 XF86VideoAdaptorPtr newAdaptor = NULL; 82 GLINTPtr pGlint = GLINTPTR(pScrn); 83 int num_adaptors; 84 85 /* Because of bugs in the PM3 when uploading images via the 86 * bypass to the framebuffer, we always have to use the accelerator. 87 */ 88 if (pGlint->NoAccel) 89 return; 90 91 newAdaptor = Permedia3SetupImageVideo(pScreen); 92 Permedia3InitOffscreenImages(pScreen); 93 94 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 95 96 if(newAdaptor) { 97 if(!num_adaptors) { 98 num_adaptors = 1; 99 adaptors = &newAdaptor; 100 } else { 101 newAdaptors = /* need to free this someplace */ 102 xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); 103 if(newAdaptors) { 104 memcpy(newAdaptors, adaptors, num_adaptors * 105 sizeof(XF86VideoAdaptorPtr)); 106 newAdaptors[num_adaptors] = newAdaptor; 107 adaptors = newAdaptors; 108 num_adaptors++; 109 } 110 } 111 } 112 113 if(num_adaptors) 114 xf86XVScreenInit(pScreen, adaptors, num_adaptors); 115 116 if(newAdaptors) 117 xfree(newAdaptors); 118} 119 120/* client libraries expect an encoding */ 121static XF86VideoEncodingRec DummyEncoding[1] = 122{ 123 { 124 0, 125 "XV_IMAGE", 126 2047, 2047, 127 {1, 1} 128 } 129}; 130 131#define NUM_FORMATS 4 132 133static XF86VideoFormatRec Formats[NUM_FORMATS] = 134{ 135 {8, PseudoColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 136}; 137 138#define NUM_ATTRIBUTES 4 139 140static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = 141{ 142 {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"}, 143 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 144 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}, 145 {XvSettable | XvGettable, 0, 2, "XV_FILTER"}, 146}; 147 148/* 149 * FOURCC from http://www.webartz.com/fourcc 150 * Generic GUID for legacy FOURCC XXXXXXXX-0000-0010-8000-00AA00389B71 151 */ 152#define LE4CC(a,b,c,d) (((CARD32)(a)&0xFF)|(((CARD32)(b)&0xFF)<<8)|(((CARD32)(c)&0xFF)<<16)|(((CARD32)(d)&0xFF)<<24)) 153#define GUID4CC(a,b,c,d) { a,b,c,d,0,0,0,0x10,0x80,0,0,0xAA,0,0x38,0x9B,0x71 } 154 155#define NoOrder LSBFirst 156 157#define NUM_IMAGES 15 158 159static XF86ImageRec Images[NUM_IMAGES] = 160{ 161 /* Planar YVU 4:2:0 (emulated) */ 162 { LE4CC('Y','V','1','2'), XvYUV, NoOrder, GUID4CC('Y','V','1','2'), 163 12, XvPlanar, 3, 0, 0, 0, 0, 164 8, 8, 8, 1, 2, 2, 1, 2, 2, "YVU", XvTopToBottom }, 165 166 /* Packed YUYV 4:2:2 */ 167 { LE4CC('Y','U','Y','2'), XvYUV, NoOrder, GUID4CC('Y','U','Y','2'), 168 16, XvPacked, 1, 0, 0, 0, 0, 169 8, 8, 8, 1, 2, 2, 1, 1, 1, "YUYV", XvTopToBottom }, 170 171 /* Packed UYVY 4:2:2 */ 172 { LE4CC('U','Y','V','Y'), XvYUV, NoOrder, GUID4CC('U','Y','V','Y'), 173 16, XvPacked, 1, 0, 0, 0, 0, 174 8, 8, 8, 1, 2, 2, 1, 1, 1, "UYVY", XvTopToBottom }, 175 176 /* Packed YUVA 4:4:4 */ 177 { LE4CC('Y','U','V','A') /* XXX not registered */, XvYUV, LSBFirst, { 0 }, 178 32, XvPacked, 1, 0, 0, 0, 0, 179 8, 8, 8, 1, 1, 1, 1, 1, 1, "YUVA", XvTopToBottom }, 180 181 /* Packed VUYA 4:4:4 */ 182 { LE4CC('V','U','Y','A') /* XXX not registered */, XvYUV, LSBFirst, { 0 }, 183 32, XvPacked, 1, 0, 0, 0, 0, 184 8, 8, 8, 1, 1, 1, 1, 1, 1, "VUYA", XvTopToBottom }, 185 186 /* RGBA 8:8:8:8 */ 187 { 0x41, XvRGB, LSBFirst, { 0 }, 188 32, XvPacked, 1, 24, 0x0000FF, 0x00FF00, 0xFF0000, 189 0, 0, 0, 0, 0, 0, 0, 0, 0, "RGBA", XvTopToBottom }, 190 191 /* RGB 5:6:5 */ 192 { 0x42, XvRGB, LSBFirst, { 0 }, 193 16, XvPacked, 1, 16, 0x001F, 0x07E0, 0xF800, 194 0, 0, 0, 0, 0, 0, 0, 0, 0, "RGB", XvTopToBottom }, 195 196 /* RGBA 5:5:5:1 */ 197 { 0x43, XvRGB, LSBFirst, { 0 }, 198 16, XvPacked, 1, 15, 0x001F, 0x03E0, 0x7C00, 199 0, 0, 0, 0, 0, 0, 0, 0, 0, "RGBA", XvTopToBottom }, 200 201 /* RGBA 4:4:4:4 */ 202 { 0x44, XvRGB, LSBFirst, { 0 }, 203 16, XvPacked, 1, 12, 0x000F, 0x00F0, 0x0F00, 204 0, 0, 0, 0, 0, 0, 0, 0, 0, "RGBA", XvTopToBottom }, 205 206 /* RGB 3:3:2 */ 207 { 0x46, XvRGB, NoOrder, { 0 }, 208 8, XvPacked, 1, 8, 0x07, 0x38, 0xC0, 209 0, 0, 0, 0, 0, 0, 0, 0, 0, "RGB", XvTopToBottom }, 210 211 /* BGRA 8:8:8:8 */ 212 { 0x47, XvRGB, LSBFirst, { 0 }, 213 32, XvPacked, 1, 24, 0xFF0000, 0x00FF00, 0x0000FF, 214 0, 0, 0, 0, 0, 0, 0, 0, 0, "BGRA", XvTopToBottom }, 215 216 /* BGR 5:6:5 */ 217 { 0x48, XvRGB, LSBFirst, { 0 }, 218 16, XvPacked, 1, 16, 0xF800, 0x07E0, 0x001F, 219 0, 0, 0, 0, 0, 0, 0, 0, 0, "BGR", XvTopToBottom }, 220 221 /* BGRA 5:5:5:1 */ 222 { 0x49, XvRGB, LSBFirst, { 0 }, 223 16, XvPacked, 1, 15, 0x7C00, 0x03E0, 0x001F, 224 0, 0, 0, 0, 0, 0, 0, 0, 0, "BGRA", XvTopToBottom }, 225 226 /* BGRA 4:4:4:4 */ 227 { 0x4A, XvRGB, LSBFirst, { 0 }, 228 16, XvPacked, 1, 12, 0x0F00, 0x00F0, 0x000F, 229 0, 0, 0, 0, 0, 0, 0, 0, 0, "BGRA", XvTopToBottom }, 230 231 /* BGR 2:3:3 */ 232 { 0x4C, XvRGB, NoOrder, { 0 }, 233 8, XvPacked, 1, 8, 0xC0, 0x38, 0x07, 234 0, 0, 0, 0, 0, 0, 0, 0, 0, "BGR", XvTopToBottom }, 235}; 236 237#define MAX_BUFFERS 2 238 239typedef struct { 240 FBAreaPtr area[MAX_BUFFERS]; 241 RegionRec clip; 242 CARD32 colorKey; 243 CARD32 videoStatus; 244 Time offTime; 245 Time freeTime; 246 int Video_Shift; 247 int Format; 248 Bool ramdacOn; 249 Bool doubleBuffer; 250 Bool autopaintColorKey; 251 int Filter; 252 int sx, sy; 253 int offset[MAX_BUFFERS]; 254 int buffer; 255} GLINTPortPrivRec, *GLINTPortPrivPtr; 256 257#define GET_PORT_PRIVATE(pScrn) \ 258 (GLINTPortPrivPtr)((GLINTPTR(pScrn))->adaptor->pPortPrivates[0].ptr) 259 260#define RAMDAC_WRITE(data,index) \ 261do{ \ 262 GLINT_WRITE_REG(((index)>>8)&0xff, PM3RD_IndexHigh); \ 263 GLINT_WRITE_REG((index)&0xff, PM3RD_IndexLow); \ 264 GLINT_WRITE_REG(data, PM3RD_IndexedData); \ 265}while(0) 266 267void Permedia3ResetVideo(ScrnInfoPtr pScrn) 268{ 269 GLINTPtr pGlint = GLINTPTR(pScrn); 270 GLINTPortPrivPtr pPriv = pGlint->adaptor->pPortPrivates[0].ptr; 271 272 GLINT_WAIT(15); 273 GLINT_WRITE_REG(0xfff0|(0xffff<<16), PM3VideoOverlayFifoControl); 274 GLINT_WRITE_REG(PM3VideoOverlayMode_DISABLE, PM3VideoOverlayMode); 275 pPriv->ramdacOn = FALSE; 276 RAMDAC_WRITE(PM3RD_VideoOverlayControl_DISABLE, PM3RD_VideoOverlayControl); 277 RAMDAC_WRITE((pPriv->colorKey&0xff0000)>>16, PM3RD_VideoOverlayKeyR); 278 RAMDAC_WRITE((pPriv->colorKey&0x00ff00)>>8, PM3RD_VideoOverlayKeyG); 279 RAMDAC_WRITE(pPriv->colorKey&0x0000ff, PM3RD_VideoOverlayKeyB); 280 GLINT_WRITE_REG(PM3VideoOverlayUpdate_ENABLE, PM3VideoOverlayUpdate); 281} 282 283 284static XF86VideoAdaptorPtr 285Permedia3SetupImageVideo(ScreenPtr pScreen) 286{ 287 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 288 GLINTPtr pGlint = GLINTPTR(pScrn); 289 XF86VideoAdaptorPtr adapt; 290 GLINTPortPrivPtr pPriv; 291 292 if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + 293 sizeof(GLINTPortPrivRec) + 294 sizeof(DevUnion)))) 295 return NULL; 296 297 adapt->type = XvWindowMask | XvInputMask | XvImageMask; 298 adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 299 adapt->name = "Permedia3 Backend Scaler"; 300 adapt->nEncodings = 1; 301 adapt->pEncodings = DummyEncoding; 302 adapt->nFormats = NUM_FORMATS; 303 adapt->pFormats = Formats; 304 adapt->nPorts = 1; 305 adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 306 pPriv = (GLINTPortPrivPtr)(&adapt->pPortPrivates[1]); 307 adapt->pPortPrivates[0].ptr = (pointer)(pPriv); 308 adapt->pAttributes = Attributes; 309 adapt->nImages = NUM_IMAGES; 310 adapt->nAttributes = NUM_ATTRIBUTES; 311 adapt->pImages = Images; 312 adapt->PutVideo = NULL; 313 adapt->PutStill = NULL; 314 adapt->GetVideo = NULL; 315 adapt->GetStill = NULL; 316 adapt->StopVideo = Permedia3StopVideo; 317 adapt->SetPortAttribute = Permedia3SetPortAttribute; 318 adapt->GetPortAttribute = Permedia3GetPortAttribute; 319 adapt->QueryBestSize = Permedia3QueryBestSize; 320 adapt->PutImage = Permedia3PutImage; 321 adapt->QueryImageAttributes = Permedia3QueryImageAttributes; 322 323 /* FIXME : depth 15 and 16 doesn't work here */ 324 pPriv->colorKey = pGlint->videoKey; 325 pPriv->videoStatus = 0; 326 pPriv->buffer = 0; /* double buffer (or maybe triple later) */ 327 pPriv->doubleBuffer = TRUE; 328 pPriv->autopaintColorKey = TRUE; 329 pPriv->Filter = PM3VideoOverlayMode_FILTER_FULL; 330 331 /* gotta uninit this someplace */ 332 REGION_NULL(pScreen, &pPriv->clip); 333 334 pGlint->adaptor = adapt; 335 336 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER"); 337 xvColorKey = MAKE_ATOM("XV_COLORKEY"); 338 xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); 339 xvFilter = MAKE_ATOM("XV_FILTER"); 340 341 Permedia3ResetVideo(pScrn); 342 343 return adapt; 344} 345 346 347static void 348Permedia3StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) 349{ 350 GLINTPtr pGlint = GLINTPTR(pScrn); 351 GLINTPortPrivPtr pPriv = (GLINTPortPrivPtr)data; 352 int i; 353 354 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 355 356 if(shutdown) { 357 if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 358 pPriv->ramdacOn = FALSE; 359 GLINT_WAIT(4); 360 RAMDAC_WRITE(PM3RD_VideoOverlayControl_DISABLE, 361 PM3RD_VideoOverlayControl); 362 GLINT_WRITE_REG(PM3VideoOverlayMode_DISABLE, 363 PM3VideoOverlayMode); 364 } 365 for (i = 0; i < (pPriv->doubleBuffer ? 2 : 1); i++) { 366 if(pPriv->area[i]) { 367 xf86FreeOffscreenArea(pPriv->area[i]); 368 pPriv->area[i] = NULL; 369 } 370 } 371 pPriv->videoStatus = 0; 372 } else { 373 if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 374 pPriv->videoStatus |= OFF_TIMER; 375 pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 376 } 377 } 378} 379 380static int 381Permedia3SetPortAttribute( 382 ScrnInfoPtr pScrn, 383 Atom attribute, 384 INT32 value, 385 pointer data 386){ 387 GLINTPortPrivPtr pPriv = (GLINTPortPrivPtr)data; 388 GLINTPtr pGlint = GLINTPTR(pScrn); 389 390 if (attribute == xvDoubleBuffer) 391 { 392 if ((value < 0) || (value > 1)) 393 return BadValue; 394 pPriv->doubleBuffer = value; 395 } 396 else if (attribute == xvColorKey) 397 { 398 pPriv->colorKey = value; 399 GLINT_WAIT(9); 400 RAMDAC_WRITE((value & 0xff0000)>>16, PM3RD_VideoOverlayKeyR); 401 RAMDAC_WRITE((value & 0x00ff00)>>8, PM3RD_VideoOverlayKeyG); 402 RAMDAC_WRITE((value & 0x0000ff), PM3RD_VideoOverlayKeyB); 403 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 404 } 405 else if (attribute == xvAutopaintColorKey) 406 { 407 if ((value < 0) || (value > 1)) 408 return BadValue; 409 pPriv->autopaintColorKey = value; 410 } 411 else if (attribute == xvFilter) 412 { 413 if ((value < 0) || (value > 2)) 414 return BadValue; 415 switch (value) { 416 case 0: 417 pPriv->Filter = PM3VideoOverlayMode_FILTER_OFF; 418 break; 419 case 1: 420 pPriv->Filter = PM3VideoOverlayMode_FILTER_FULL; 421 break; 422 case 2: 423 pPriv->Filter = PM3VideoOverlayMode_FILTER_PARTIAL; 424 break; 425 } 426 } 427 else 428 return BadMatch; 429 430 return Success; 431} 432 433static int 434Permedia3GetPortAttribute( 435 ScrnInfoPtr pScrn, 436 Atom attribute, 437 INT32 *value, 438 pointer data 439){ 440 GLINTPortPrivPtr pPriv = (GLINTPortPrivPtr)data; 441 442 if (attribute == xvDoubleBuffer) 443 *value = (pPriv->doubleBuffer) ? 1 : 0; 444 else if (attribute == xvColorKey) 445 *value = pPriv->colorKey; 446 else if (attribute == xvAutopaintColorKey) 447 *value = (pPriv->autopaintColorKey) ? 1 : 0; 448 else if (attribute == xvFilter) 449 *value = pPriv->Filter >> 14; 450 else 451 return BadMatch; 452 453 return Success; 454} 455 456static void 457Permedia3QueryBestSize( 458 ScrnInfoPtr pScrn, 459 Bool motion, 460 short vid_w, short vid_h, 461 short drw_w, short drw_h, 462 unsigned int *p_w, unsigned int *p_h, 463 pointer data 464){ 465 if(vid_w > (drw_w << 3)) 466 drw_w = vid_w >> 3; 467 if(vid_h > (drw_h << 3)) 468 drw_h = vid_h >> 3; 469 470 *p_w = drw_w; 471 *p_h = drw_h; 472} 473 474static void 475HWCopySetup(ScrnInfoPtr pScrn, int x, int y, int w, int h) 476{ 477 GLINTPtr pGlint = GLINTPTR(pScrn); 478 479 GLINT_WAIT(4); 480 GLINT_WRITE_REG(0xffffffff, FBHardwareWriteMask); 481 GLINT_WRITE_REG( 482 PM3Config2D_ForegroundROPEnable | 483 PM3Config2D_ForegroundROP(GXcopy) | 484 PM3Config2D_FBWriteEnable, 485 PM3Config2D); 486 GLINT_WRITE_REG( 487 PM3RectanglePosition_XOffset(x) | 488 PM3RectanglePosition_YOffset(y), 489 PM3RectanglePosition); 490 GLINT_WRITE_REG( 491 PM3Render2D_SpanOperation | 492 PM3Render2D_XPositive | 493 PM3Render2D_YPositive | 494 PM3Render2D_Operation_SyncOnHostData | 495 PM3Render2D_Width(w) | PM3Render2D_Height(h), 496 PM3Render2D); 497} 498 499static void 500HWCopyYV12(ScrnInfoPtr pScrn, CARD8 *Y, int w, int h) 501{ 502 GLINTPtr pGlint = GLINTPTR(pScrn); 503 int size = w * h; 504 CARD8 *V = Y + size; 505 CARD8 *U = V + (size >> 2); 506 CARD32 *dst; 507 int pass2 = 0; 508 int dwords, i, x = 0; 509 510 dwords = size >> 1; 511 512 w >>= 1; 513 514 while (dwords >= pGlint->FIFOSize) { 515 dst = (CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4); 516 GLINT_WAIT(pGlint->FIFOSize); 517 /* (0x15 << 4) | 0x05 is the TAG for FBSourceData */ 518 GLINT_WRITE_REG(((pGlint->FIFOSize - 2) << 16) | (0x15 << 4) | 519 0x05, OutputFIFO); 520 for (i = pGlint->FIFOSize - 1; i; i--, Y += 2, x++) { 521 if (x == w) { 522 x = 0; 523 if (pass2 == 0) 524 pass2 = 1; 525 else 526 if (pass2 == 1) { 527 pass2 = 0; 528 U += w; 529 V += w; 530 } 531 } 532 *dst++ = Y[0] + (U[x] << 8) + (Y[1] << 16) + (V[x] << 24); 533 } 534 dwords -= pGlint->FIFOSize - 1; 535 } 536 if (dwords) { 537 dst = (CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4); 538 GLINT_WAIT(dwords + 1); 539 /* (0x15 << 4) | 0x05 is the TAG for FBSourceData */ 540 GLINT_WRITE_REG(((dwords - 1) << 16) | (0x15 << 4) | 541 0x05, OutputFIFO); 542 for (i = dwords; i; i--, Y += 2, x++) { 543 if (x == w) { 544 x = 0; 545 if (pass2 == 0) 546 pass2 = 1; 547 else 548 if (pass2 == 1) { 549 pass2 = 0; 550 U += w; 551 V += w; 552 } 553 } 554 *dst++ = Y[0] + (U[x] << 8) + (Y[1] << 16) + (V[x] << 24); 555 } 556 } 557} 558 559static void 560HWCopyFlat(ScrnInfoPtr pScrn, CARD8 *src, int w, int h) 561{ 562 GLINTPtr pGlint = GLINTPTR(pScrn); 563 GLINTPortPrivPtr pPriv = pGlint->adaptor->pPortPrivates[0].ptr; 564 int pitch = pScrn->displayWidth; 565 CARD8 *tmp_src; 566 int dwords; 567 568 if (w == pitch) { 569 dwords = (w * h) >> (2 - pPriv->Video_Shift); 570 while(dwords >= pGlint->FIFOSize) { 571 GLINT_WAIT(pGlint->FIFOSize); 572 GLINT_WRITE_REG(((pGlint->FIFOSize - 2) << 16) | (0x15 << 4) | 573 0x05, OutputFIFO); 574 GLINT_MoveDWORDS( 575 (CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4), 576 (CARD32*)src, pGlint->FIFOSize - 1); 577 dwords -= (pGlint->FIFOSize - 1); 578 src += (pGlint->FIFOSize << 2) - 4; 579 } 580 if(dwords) { 581 GLINT_WAIT(dwords + 1); 582 GLINT_WRITE_REG(((dwords - 1) << 16)|(0x15 << 4) |0x05, OutputFIFO); 583 GLINT_MoveDWORDS( 584 (CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4), 585 (CARD32*)src, dwords); 586 } 587 } else { 588 while (h--) { 589 tmp_src = src; 590 dwords = w >> (2 - pPriv->Video_Shift); 591 while(dwords >= pGlint->FIFOSize) { 592 GLINT_WAIT(pGlint->FIFOSize); 593 GLINT_WRITE_REG(((pGlint->FIFOSize - 2) << 16) | (0x15 << 4) | 594 0x05, OutputFIFO); 595 GLINT_MoveDWORDS( 596 (CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4), 597 (CARD32*)src, pGlint->FIFOSize - 1); 598 dwords -= (pGlint->FIFOSize - 1); 599 src += (pGlint->FIFOSize << 2) - 4; 600 } 601 if(dwords) { 602 GLINT_WAIT(dwords + 1); 603 GLINT_WRITE_REG(((dwords-1)<<16)|(0x15<<4) | 0x05, OutputFIFO); 604 GLINT_MoveDWORDS( 605 (CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4), 606 (CARD32*)src, dwords); 607 } 608 src = tmp_src + (w << pPriv->Video_Shift); 609 } 610 } 611} 612 613static FBAreaPtr 614Permedia3AllocateMemory(ScrnInfoPtr pScrn, FBAreaPtr area, int width, int height) 615{ 616 ScreenPtr pScreen; 617 FBAreaPtr new_area; 618 619 if (area) { 620 if ((area->box.x2 - area->box.x1 >= width) && 621 (area->box.y2 - area->box.y1 >= height)) 622 return area; 623 624 if (xf86ResizeOffscreenArea(area, width, height)) 625 return area; 626 627 xf86FreeOffscreenArea(area); 628 } 629 630 pScreen = screenInfo.screens[pScrn->scrnIndex]; 631 632 new_area = xf86AllocateOffscreenArea(pScreen, width, height, pScrn->bitsPerPixel / 8, NULL, NULL, NULL); 633 634 if (!new_area) { 635 int max_width, max_height; 636 637 xf86QueryLargestOffscreenArea(pScreen, &max_width, &max_height, pScrn->bitsPerPixel / 8, 0, PRIORITY_EXTREME); 638 639 if (max_width < width || max_height < height) 640 return NULL; 641 642 xf86PurgeUnlockedOffscreenAreas(pScreen); 643 new_area = xf86AllocateOffscreenArea(pScreen, width, height, pScrn->bitsPerPixel / 8, NULL, NULL, NULL); 644 } 645 646 return new_area; 647} 648 649#define FORMAT_RGB8888 PM3VideoOverlayMode_COLORFORMAT_RGB8888 650#define FORMAT_RGB4444 PM3VideoOverlayMode_COLORFORMAT_RGB4444 651#define FORMAT_RGB5551 PM3VideoOverlayMode_COLORFORMAT_RGB5551 652#define FORMAT_RGB565 PM3VideoOverlayMode_COLORFORMAT_RGB565 653#define FORMAT_RGB332 PM3VideoOverlayMode_COLORFORMAT_RGB332 654#define FORMAT_BGR8888 PM3VideoOverlayMode_COLORFORMAT_BGR8888 655#define FORMAT_BGR4444 PM3VideoOverlayMode_COLORFORMAT_BGR4444 656#define FORMAT_BGR5551 PM3VideoOverlayMode_COLORFORMAT_BGR5551 657#define FORMAT_BGR565 PM3VideoOverlayMode_COLORFORMAT_BGR565 658#define FORMAT_BGR332 PM3VideoOverlayMode_COLORFORMAT_BGR332 659#define FORMAT_CI8 PM3VideoOverlayMode_COLORFORMAT_CI8 660#define FORMAT_VUY444 PM3VideoOverlayMode_COLORFORMAT_VUY444 661#define FORMAT_YUV444 PM3VideoOverlayMode_COLORFORMAT_YUV444 662#define FORMAT_VUY422 PM3VideoOverlayMode_COLORFORMAT_VUY422 663#define FORMAT_YUV422 PM3VideoOverlayMode_COLORFORMAT_YUV422 664 665/* Notice, have to check that we dont overflow the deltas here ... */ 666static void 667compute_scale_factor( 668 short* src_w, short* dst_w, 669 unsigned int* shrink_delta, unsigned int* zoom_delta) 670{ 671 /* NOTE: If we don't return reasonable values here then the video 672 * unit can potential shut off and won't display an image until re-enabled. 673 * Seems as though the zoom_delta is o.k, and I've not had the problem. 674 * The 'shrink_delta' is prone to this the most - FIXME ! */ 675 676 if (*src_w >= *dst_w) { 677 *src_w &= ~0x3; 678 *dst_w &= ~0x3; 679 *shrink_delta = (((*src_w << 16) / *dst_w) + 0x0f) & 0x0ffffff0; 680 *zoom_delta = 1<<16; 681 if ( ((*shrink_delta * *dst_w) >> 16) & 0x03 ) 682 *shrink_delta += 0x10; 683 } else { 684 *src_w &= ~0x3; 685 *dst_w &= ~0x3; 686 *zoom_delta = (((*src_w << 16) / *dst_w) + 0x0f) & 0x0001fff0; 687 *shrink_delta = 1<<16; 688 if ( ((*zoom_delta * *dst_w) >> 16) & 0x03 ) 689 *zoom_delta += 0x10; 690 } 691} 692 693static void 694Permedia3DisplayVideo( 695 ScrnInfoPtr pScrn, 696 int id, 697 int offset, 698 short width, short height, 699 int x1, int y1, int x2, int y2, 700 BoxPtr dstBox, 701 short src_w, short src_h, 702 short drw_w, short drw_h 703){ 704 GLINTPtr pGlint = GLINTPTR(pScrn); 705 GLINTPortPrivPtr portPriv = pGlint->adaptor->pPortPrivates[0].ptr; 706 unsigned int shrink, zoom; 707 unsigned int newx2; 708 709 /* Let's overlay only to visible parts of the screen */ 710 if (dstBox->x1 == 0) { 711 x1 = drw_w - dstBox->x2; 712 drw_w = dstBox->x2; 713 } 714 if (dstBox->x2 == pScrn->frameX1) { 715 x2 = drw_w - (dstBox->x2 - dstBox->x1); 716 drw_w = (dstBox->x2 - dstBox->x1); 717 } 718 719 /* Avoid divide by zero in compute_scale_factor. */ 720 if (drw_w < 8) 721 return; 722 723 /* Let's adjust the width of source and dest to be compliant with 724 * the Permedia3 overlay unit requirement, and compute the X deltas. */ 725 newx2 = drw_w; 726 compute_scale_factor(&src_w, &drw_w, &shrink, &zoom); 727 dstBox->x2 -= (newx2 - drw_w); 728 729 /* We do a long wait here - for everything that needs to be written */ 730 GLINT_WAIT(39); 731 GLINT_WRITE_REG(offset>>portPriv->Video_Shift, 732 portPriv->buffer ? PM3VideoOverlayBase1 : PM3VideoOverlayBase0); 733 /* Let's set the source pitch. */ 734 GLINT_WRITE_REG(PM3VideoOverlayStride_STRIDE(pScrn->displayWidth<< 735 (pScrn->bitsPerPixel>>4) >>portPriv->Video_Shift), 736 PM3VideoOverlayStride); 737 /* Let's set the position and size of the visible part of the source. */ 738 GLINT_WRITE_REG(PM3VideoOverlayWidth_WIDTH(src_w), 739 PM3VideoOverlayWidth); 740 GLINT_WRITE_REG(PM3VideoOverlayHeight_HEIGHT(src_h), 741 PM3VideoOverlayHeight); 742 GLINT_WRITE_REG( 743 PM3VideoOverlayOrigin_XORIGIN(x1) | 744 PM3VideoOverlayOrigin_YORIGIN(y1), 745 PM3VideoOverlayOrigin); 746 /* Scale the source to the destinationsize */ 747 if (src_h == drw_h) { 748 GLINT_WRITE_REG( 749 PM3VideoOverlayYDelta_NONE, 750 PM3VideoOverlayYDelta); 751 } else { 752 GLINT_WRITE_REG( 753 PM3VideoOverlayYDelta_DELTA(src_h,drw_h), 754 PM3VideoOverlayYDelta); 755 } 756 if (src_w == drw_w) { 757 GLINT_WRITE_REG(1<<16, PM3VideoOverlayShrinkXDelta); 758 GLINT_WRITE_REG(1<<16, PM3VideoOverlayZoomXDelta); 759 } else { 760 GLINT_WRITE_REG(shrink, PM3VideoOverlayShrinkXDelta); 761 GLINT_WRITE_REG(zoom, PM3VideoOverlayZoomXDelta); 762 } 763 GLINT_WRITE_REG(portPriv->buffer, PM3VideoOverlayIndex); 764 765 /* Now set the ramdac video overlay region and mode */ 766 RAMDAC_WRITE((dstBox->x1&0xff), PM3RD_VideoOverlayXStartLow); 767 RAMDAC_WRITE((dstBox->x1&0xf00)>>8, PM3RD_VideoOverlayXStartHigh); 768 RAMDAC_WRITE((dstBox->x2&0xff), PM3RD_VideoOverlayXEndLow); 769 RAMDAC_WRITE((dstBox->x2&0xf00)>>8,PM3RD_VideoOverlayXEndHigh); 770 RAMDAC_WRITE((dstBox->y1&0xff), PM3RD_VideoOverlayYStartLow); 771 RAMDAC_WRITE((dstBox->y1&0xf00)>>8, PM3RD_VideoOverlayYStartHigh); 772 RAMDAC_WRITE((dstBox->y2&0xff), PM3RD_VideoOverlayYEndLow); 773 RAMDAC_WRITE((dstBox->y2&0xf00)>>8,PM3RD_VideoOverlayYEndHigh); 774 775 GLINT_WRITE_REG(portPriv->Video_Shift << 5 | 776 portPriv->Format | 777 portPriv->Filter | 778 PM3VideoOverlayMode_BUFFERSYNC_MANUAL | 779 PM3VideoOverlayMode_FLIP_VIDEO | 780 PM3VideoOverlayMode_ENABLE, 781 PM3VideoOverlayMode); 782 783 if (!portPriv->ramdacOn) { 784 RAMDAC_WRITE(PM3RD_VideoOverlayControl_ENABLE | 785 PM3RD_VideoOverlayControl_KEY_COLOR | 786 PM3RD_VideoOverlayControl_MODE_MAINKEY | 787 PM3RD_VideoOverlayControl_DIRECTCOLOR_ENABLED, 788 PM3RD_VideoOverlayControl); 789 portPriv->ramdacOn = TRUE; 790 } 791 GLINT_WRITE_REG(PM3VideoOverlayUpdate_ENABLE, 792 PM3VideoOverlayUpdate); 793} 794 795static int 796Permedia3PutImage( 797 ScrnInfoPtr pScrn, 798 short src_x, short src_y, 799 short drw_x, short drw_y, 800 short src_w, short src_h, 801 short drw_w, short drw_h, 802 int id, unsigned char* buf, 803 short width, short height, 804 Bool sync, 805 RegionPtr clipBoxes, pointer data, 806 DrawablePtr pDraw 807){ 808#if 0 809 GLINTPtr pGlint = GLINTPTR(pScrn); 810#endif 811 GLINTPortPrivPtr pPriv = (GLINTPortPrivPtr)data; 812 INT32 x1, x2, y1, y2; 813 int pitch; 814 int i; 815 int w_bpp, bpp; 816 Bool copy_flat = TRUE; 817 BoxRec dstBox; 818 819 /* Let's find the image format and Video_Shift values */ 820 switch (id) { 821 case LE4CC('Y','V','1','2'): 822 pPriv->Format = FORMAT_YUV422; 823 pPriv->Video_Shift = 1; 824 copy_flat = FALSE; 825 break; 826 case LE4CC('Y','U','Y','2'): 827 pPriv->Format = FORMAT_YUV422; 828 pPriv->Video_Shift = 1; 829 break; 830 case LE4CC('U','Y','V','Y'): 831 pPriv->Format = FORMAT_VUY422; 832 pPriv->Video_Shift = 1; 833 break; 834 case LE4CC('Y','U','V','A'): 835 pPriv->Format = FORMAT_YUV444; 836 pPriv->Video_Shift = 2; 837 break; 838 case LE4CC('V','U','Y','A'): 839 pPriv->Format = FORMAT_VUY444; 840 pPriv->Video_Shift = 2; 841 break; 842 case 0x41: /* RGBA 8:8:8:8 */ 843 pPriv->Format = FORMAT_RGB8888; 844 pPriv->Video_Shift = 2; 845 break; 846 case 0x42: /* RGB 5:6:5 */ 847 pPriv->Format = FORMAT_RGB565; 848 pPriv->Video_Shift = 1; 849 break; 850 case 0x43: /* RGB 1:5:5:5 */ 851 pPriv->Format = FORMAT_RGB5551; 852 pPriv->Video_Shift = 1; 853 break; 854 case 0x44: /* RGB 4:4:4:4 */ 855 pPriv->Format = FORMAT_RGB4444; 856 pPriv->Video_Shift = 1; 857 break; 858 case 0x46: /* RGB 2:3:3 */ 859 pPriv->Format = FORMAT_RGB332; 860 pPriv->Video_Shift = 0; 861 break; 862 case 0x47: /* BGRA 8:8:8:8 */ 863 pPriv->Format = FORMAT_BGR8888; 864 pPriv->Video_Shift = 2; 865 break; 866 case 0x48: /* BGR 5:6:5 */ 867 pPriv->Format = FORMAT_BGR565; 868 pPriv->Video_Shift = 1; 869 break; 870 case 0x49: /* BGR 1:5:5:5 */ 871 pPriv->Format = FORMAT_BGR5551; 872 pPriv->Video_Shift = 1; 873 break; 874 case 0x4A: /* BGR 4:4:4:4 */ 875 pPriv->Format = FORMAT_BGR4444; 876 pPriv->Video_Shift = 1; 877 break; 878 case 0x4C: /* BGR 2:3:3 */ 879 pPriv->Format = FORMAT_BGR332; 880 pPriv->Video_Shift = 0; 881 break; 882 default: 883 return XvBadAlloc; 884 } 885 886 /* Clip */ 887 x1 = src_x; 888 x2 = src_x + src_w; 889 y1 = src_y; 890 y2 = src_y + src_h; 891 892 dstBox.x1 = drw_x; 893 dstBox.x2 = drw_x + drw_w; 894 dstBox.y1 = drw_y; 895 dstBox.y2 = drw_y + drw_h; 896 897 if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, 898 width, height)) 899 return Success; 900 901 dstBox.x1 -= pScrn->frameX0; 902 dstBox.x2 -= pScrn->frameX0; 903 dstBox.y1 -= pScrn->frameY0; 904 dstBox.y2 -= pScrn->frameY0; 905 906 bpp = pScrn->bitsPerPixel >> 3; 907 pitch = bpp * pScrn->displayWidth; 908 909 w_bpp = (width << pPriv->Video_Shift) >> (pScrn->bitsPerPixel >> 4); 910 911 for (i = 0; i < (pPriv->doubleBuffer ? 2 : 1); i++) { 912 if (!(pPriv->area[i] = 913 Permedia3AllocateMemory(pScrn,pPriv->area[i],w_bpp,src_h))) 914 return BadAlloc; 915 916 pPriv->offset[i] = (pPriv->area[i]->box.x1 * bpp) + 917 (pPriv->area[i]->box.y1 * pitch); 918 } 919 920 HWCopySetup(pScrn, pPriv->area[pPriv->buffer]->box.x1, 921 pPriv->area[pPriv->buffer]->box.y1, w_bpp, height); 922 923 if (copy_flat) 924 HWCopyFlat(pScrn, buf, width, height); 925 else 926 HWCopyYV12(pScrn, buf, width, height); 927 928 /* paint the color key */ 929 if(pPriv->autopaintColorKey && 930 !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { 931 /* update cliplist */ 932 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 933#if 0 934 GLINT_WAIT(1); 935 GLINT_WRITE_REG(PM3VideoOverlayMode_DISABLE, 936 PM3VideoOverlayMode); 937 pPriv->ramdacOn = FALSE; 938#endif 939 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 940 } 941 942 Permedia3Sync(pScrn); 943 944 Permedia3DisplayVideo(pScrn, id, pPriv->offset[pPriv->buffer], width,height, 945 x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 946 947 /* Switch buffer on next run - double buffer */ 948 if (pPriv->doubleBuffer) { 949 if (!pPriv->buffer) 950 pPriv->buffer = 1; 951 else 952 pPriv->buffer = 0; 953 } 954 955 pPriv->videoStatus = CLIENT_VIDEO_ON; 956 957 return Success; 958} 959 960static int 961Permedia3QueryImageAttributes( 962 ScrnInfoPtr pScrn, 963 int id, 964 unsigned short *w, unsigned short *h, 965 int *pitches, int *offsets 966){ 967 int size, tmp; 968 969 if(*w > 2047) *w = 2047; 970 if(*h > 2047) *h = 2047; 971 972 *w = (*w + 1) & ~1; 973 if(offsets) offsets[0] = 0; 974 975 switch(id) { 976 case FOURCC_YV12: /* YV12 */ 977 *h = (*h + 1) & ~1; 978 size = (*w + 3) & ~3; 979 if(pitches) pitches[0] = size; 980 size *= *h; 981 if(offsets) offsets[1] = size; 982 tmp = ((*w >> 1) + 3) & ~3; 983 if(pitches) pitches[1] = pitches[2] = tmp; 984 tmp *= (*h >> 1); 985 size += tmp; 986 if(offsets) offsets[2] = size; 987 size += tmp; 988 break; 989 default: /* RGB15, RGB16, YUY2 */ 990 size = *w << 1; 991 if(pitches) pitches[0] = size; 992 size *= *h; 993 break; 994 } 995 996 return size; 997} 998 999/****************** Offscreen stuff ***************/ 1000 1001typedef struct { 1002 FBAreaPtr area; 1003 Bool isOn; 1004 int Video_Shift; 1005 int Format; 1006 Bool ramdacOn; 1007} OffscreenPrivRec, * OffscreenPrivPtr; 1008 1009static int 1010Permedia3AllocateSurface( 1011 ScrnInfoPtr pScrn, 1012 int id, 1013 unsigned short w, 1014 unsigned short h, 1015 XF86SurfacePtr surface 1016){ 1017 FBAreaPtr area; 1018 int fbpitch, bpp; 1019 OffscreenPrivPtr pPriv; 1020 1021 if((w > 2047) || (h > 2047)) 1022 return BadAlloc; 1023 1024 w = (w + 1) & ~1; 1025 bpp = pScrn->bitsPerPixel >> 3; 1026 fbpitch = bpp * pScrn->displayWidth; 1027 1028 if(!(area = Permedia3AllocateMemory(pScrn, NULL, w, h))) 1029 return BadAlloc; 1030 1031 surface->width = w; 1032 surface->height = h; 1033 1034 if(!(surface->offsets = xalloc(sizeof(int)))) { 1035 xf86FreeOffscreenArea(area); 1036 return BadAlloc; 1037 } 1038 if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) { 1039 xfree(surface->offsets); 1040 xf86FreeOffscreenArea(area); 1041 return BadAlloc; 1042 } 1043 1044 pPriv->area = area; 1045 pPriv->isOn = FALSE; 1046 1047 surface->pScrn = pScrn; 1048 surface->id = id; 1049 surface->offsets[0] = (area->box.x1 * bpp) + (area->box.y1 * fbpitch); 1050 surface->devPrivate.ptr = (pointer)pPriv; 1051 1052 return Success; 1053} 1054 1055static int 1056Permedia3StopSurface( 1057 XF86SurfacePtr surface 1058){ 1059 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 1060 1061 if(pPriv->isOn) { 1062 GLINTPtr pGlint = GLINTPTR(surface->pScrn); 1063 pPriv->ramdacOn = FALSE; 1064 GLINT_WAIT(4); 1065 RAMDAC_WRITE(PM3RD_VideoOverlayControl_DISABLE, 1066 PM3RD_VideoOverlayControl); 1067 GLINT_WRITE_REG(PM3VideoOverlayMode_DISABLE, 1068 PM3VideoOverlayMode); 1069 pPriv->isOn = FALSE; 1070 } 1071 1072 return Success; 1073} 1074 1075static int 1076Permedia3FreeSurface( 1077 XF86SurfacePtr surface 1078){ 1079 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 1080 1081 if(pPriv->isOn) 1082 Permedia3StopSurface(surface); 1083 xf86FreeOffscreenArea(pPriv->area); 1084 xfree(surface->pitches); 1085 xfree(surface->offsets); 1086 xfree(surface->devPrivate.ptr); 1087 1088 return Success; 1089} 1090 1091static int 1092Permedia3GetSurfaceAttribute( 1093 ScrnInfoPtr pScrn, 1094 Atom attribute, 1095 INT32 *value 1096){ 1097 return Permedia3GetPortAttribute(pScrn, attribute, value, 1098 (pointer)(GET_PORT_PRIVATE(pScrn))); 1099} 1100 1101static int 1102Permedia3SetSurfaceAttribute( 1103 ScrnInfoPtr pScrn, 1104 Atom attribute, 1105 INT32 value 1106){ 1107 return Permedia3SetPortAttribute(pScrn, attribute, value, 1108 (pointer)(GET_PORT_PRIVATE(pScrn))); 1109} 1110 1111static int 1112Permedia3DisplaySurface( 1113 XF86SurfacePtr surface, 1114 short src_x, short src_y, 1115 short drw_x, short drw_y, 1116 short src_w, short src_h, 1117 short drw_w, short drw_h, 1118 RegionPtr clipBoxes 1119){ 1120 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 1121 ScrnInfoPtr pScrn = surface->pScrn; 1122 GLINTPtr pGlint = GLINTPTR(pScrn); 1123 GLINTPortPrivPtr portPriv = pGlint->adaptor->pPortPrivates[0].ptr; 1124 INT32 x1, y1, x2, y2; 1125 BoxRec dstBox; 1126 1127 x1 = src_x; 1128 x2 = src_x + src_w; 1129 y1 = src_y; 1130 y2 = src_y + src_h; 1131 1132 dstBox.x1 = drw_x; 1133 dstBox.x2 = drw_x + drw_w; 1134 dstBox.y1 = drw_y; 1135 dstBox.y2 = drw_y + drw_h; 1136 1137 if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, 1138 surface->width, surface->height)) 1139 { 1140 return Success; 1141 } 1142 1143 dstBox.x1 -= pScrn->frameX0; 1144 dstBox.x2 -= pScrn->frameX0; 1145 dstBox.y1 -= pScrn->frameY0; 1146 dstBox.y2 -= pScrn->frameY0; 1147 1148 /* Let's find the image format and Video_Shift values */ 1149 switch (surface->id) { 1150 case LE4CC('Y','V','1','2'): 1151 pPriv->Format = FORMAT_YUV422; 1152 pPriv->Video_Shift = 1; 1153 break; 1154 case LE4CC('Y','U','Y','2'): 1155 pPriv->Format = FORMAT_YUV422; 1156 pPriv->Video_Shift = 1; 1157 break; 1158 case LE4CC('U','Y','V','Y'): 1159 pPriv->Format = FORMAT_VUY422; 1160 pPriv->Video_Shift = 1; 1161 break; 1162 case LE4CC('Y','U','V','A'): 1163 pPriv->Format = FORMAT_YUV444; 1164 pPriv->Video_Shift = 2; 1165 break; 1166 case LE4CC('V','U','Y','A'): 1167 pPriv->Format = FORMAT_VUY444; 1168 pPriv->Video_Shift = 2; 1169 break; 1170 case 0x41: /* RGBA 8:8:8:8 */ 1171 pPriv->Format = FORMAT_RGB8888; 1172 pPriv->Video_Shift = 2; 1173 break; 1174 case 0x42: /* RGB 5:6:5 */ 1175 pPriv->Format = FORMAT_RGB565; 1176 pPriv->Video_Shift = 1; 1177 break; 1178 case 0x43: /* RGB 1:5:5:5 */ 1179 pPriv->Format = FORMAT_RGB5551; 1180 pPriv->Video_Shift = 1; 1181 break; 1182 case 0x44: /* RGB 4:4:4:4 */ 1183 pPriv->Format = FORMAT_RGB4444; 1184 pPriv->Video_Shift = 1; 1185 break; 1186 case 0x46: /* RGB 2:3:3 */ 1187 pPriv->Format = FORMAT_RGB332; 1188 pPriv->Video_Shift = 0; 1189 break; 1190 case 0x47: /* BGRA 8:8:8:8 */ 1191 pPriv->Format = FORMAT_BGR8888; 1192 pPriv->Video_Shift = 2; 1193 break; 1194 case 0x48: /* BGR 5:6:5 */ 1195 pPriv->Format = FORMAT_BGR565; 1196 pPriv->Video_Shift = 1; 1197 break; 1198 case 0x49: /* BGR 1:5:5:5 */ 1199 pPriv->Format = FORMAT_BGR5551; 1200 pPriv->Video_Shift = 1; 1201 break; 1202 case 0x4A: /* BGR 4:4:4:4 */ 1203 pPriv->Format = FORMAT_BGR4444; 1204 pPriv->Video_Shift = 1; 1205 break; 1206 case 0x4C: /* BGR 2:3:3 */ 1207 pPriv->Format = FORMAT_BGR332; 1208 pPriv->Video_Shift = 0; 1209 break; 1210 default: 1211 return XvBadAlloc; 1212 } 1213 1214 Permedia3DisplayVideo(pScrn, surface->id, surface->offsets[0], 1215 surface->width, surface->height, 1216 x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 1217 1218 xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes); 1219 1220 pPriv->isOn = TRUE; 1221 /* we've prempted the XvImage stream so set its free timer */ 1222 if(portPriv->videoStatus & CLIENT_VIDEO_ON) { 1223 REGION_EMPTY(pScrn->pScreen, &portPriv->clip); 1224 UpdateCurrentTime(); 1225 portPriv->videoStatus = FREE_TIMER; 1226 portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 1227 pGlint->VideoTimerCallback = Permedia3VideoTimerCallback; 1228 } 1229 1230 return Success; 1231} 1232 1233static void 1234Permedia3InitOffscreenImages(ScreenPtr pScreen) 1235{ 1236 XF86OffscreenImagePtr offscreenImages; 1237 1238 /* need to free this someplace */ 1239 if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) 1240 return; 1241 1242 offscreenImages[0].image = &Images[0]; 1243 offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | 1244 VIDEO_CLIP_TO_VIEWPORT; 1245 offscreenImages[0].alloc_surface = Permedia3AllocateSurface; 1246 offscreenImages[0].free_surface = Permedia3FreeSurface; 1247 offscreenImages[0].display = Permedia3DisplaySurface; 1248 offscreenImages[0].stop = Permedia3StopSurface; 1249 offscreenImages[0].setAttribute = Permedia3SetSurfaceAttribute; 1250 offscreenImages[0].getAttribute = Permedia3GetSurfaceAttribute; 1251 offscreenImages[0].max_width = 2047; 1252 offscreenImages[0].max_height = 2047; 1253 offscreenImages[0].num_attributes = NUM_ATTRIBUTES; 1254 offscreenImages[0].attributes = Attributes; 1255 1256 xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); 1257} 1258 1259static void 1260Permedia3VideoTimerCallback(ScrnInfoPtr pScrn, Time time) 1261{ 1262 GLINTPtr pGlint = GLINTPTR(pScrn); 1263 GLINTPortPrivPtr pPriv = pGlint->adaptor->pPortPrivates[0].ptr; 1264 int i; 1265 1266 if(pPriv->videoStatus & TIMER_MASK) { 1267 if(pPriv->videoStatus & OFF_TIMER) { 1268 if(pPriv->offTime < time) { 1269 pPriv->ramdacOn = FALSE; 1270 GLINT_WAIT(4); 1271 RAMDAC_WRITE(PM3RD_VideoOverlayControl_DISABLE, 1272 PM3RD_VideoOverlayControl); 1273 GLINT_WRITE_REG(PM3VideoOverlayMode_DISABLE, 1274 PM3VideoOverlayMode); 1275 pPriv->videoStatus = FREE_TIMER; 1276 pPriv->freeTime = time + FREE_DELAY; 1277 } 1278 } else { /* FREE_TIMER */ 1279 if(pPriv->freeTime < time) { 1280 for (i = 0; i < (pPriv->doubleBuffer ? 2 : 1); i++) { 1281 if(pPriv->area[i]) { 1282 xf86FreeOffscreenArea(pPriv->area[i]); 1283 pPriv->area[i] = NULL; 1284 } 1285 } 1286 pPriv->videoStatus = 0; 1287 pGlint->VideoTimerCallback = NULL; 1288 } 1289 } 1290 } else /* shouldn't get here */ 1291 pGlint->VideoTimerCallback = NULL; 1292} 1293