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