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