1/*************************************************************************** 2 3Copyright 2000 Intel Corporation. All Rights Reserved. 4 5Permission is hereby granted, free of charge, to any person obtaining a 6copy of this software and associated documentation files (the 7"Software"), to deal in the Software without restriction, including 8without limitation the rights to use, copy, modify, merge, publish, 9distribute, sub license, and/or sell copies of the Software, and to 10permit persons to whom the Software is furnished to do so, subject to 11the following conditions: 12 13The above copyright notice and this permission notice (including the 14next paragraph) shall be included in all copies or substantial portions 15of the Software. 16 17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 21DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 23THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25**************************************************************************/ 26 27/* 28 * i810_video.c: i810 Xv driver. Based on the mga Xv driver by Mark Vojkovich. 29 * 30 * Authors: 31 * Jonathan Bian <jonathan.bian@intel.com> 32 * Offscreen Images: 33 * Matt Sottek <matthew.j.sottek@intel.com> 34 */ 35 36#ifdef HAVE_CONFIG_H 37#include "config.h" 38#endif 39 40#include <string.h> 41 42#include "xorg-server.h" 43#include "xf86.h" 44#include "xf86_OSproc.h" 45#include "compiler.h" 46#include "xf86Pci.h" 47#include "xf86fbman.h" 48#include "regionstr.h" 49 50#include "i810.h" 51#include "xf86xv.h" 52#include <X11/extensions/Xv.h> 53#include "dixstruct.h" 54#include "fourcc.h" 55 56#define OFF_DELAY 250 /* milliseconds */ 57#define FREE_DELAY 15000 58 59#define OFF_TIMER 0x01 60#define FREE_TIMER 0x02 61#define CLIENT_VIDEO_ON 0x04 62 63#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 64 65static void I810InitOffscreenImages(ScreenPtr); 66 67static XF86VideoAdaptorPtr I810SetupImageVideo(ScreenPtr); 68static void I810StopVideo(ScrnInfoPtr, pointer, Bool); 69static int I810SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 70static int I810GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); 71static void I810QueryBestSize(ScrnInfoPtr, Bool, 72 short, short, short, short, unsigned int *, unsigned int *, pointer); 73static int I810PutImage( ScrnInfoPtr, 74 short, short, short, short, short, short, short, short, 75 int, unsigned char*, short, short, Bool, RegionPtr, pointer, 76 DrawablePtr); 77static int I810QueryImageAttributes(ScrnInfoPtr, 78 int, unsigned short *, unsigned short *, int *, int *); 79 80#if !HAVE_NOTIFY_FD 81static void I810BlockHandler(BLOCKHANDLER_ARGS_DECL); 82#else 83static void I810BlockHandler(void *data, void *_timeout); 84#endif 85 86#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 87 88static Atom xvBrightness, xvContrast, xvColorKey; 89 90#define IMAGE_MAX_WIDTH 1440 91#define IMAGE_FAST_WIDTH 720 92#define IMAGE_MAX_HEIGHT 1080 93#define Y_BUF_SIZE (IMAGE_MAX_WIDTH * IMAGE_MAX_HEIGHT) 94 95#define OVERLAY_UPDATE(p) OUTREG(0x30000, p | 0x80000000); 96 97/* 98 * OV0CMD - Overlay Command Register 99 */ 100#define VERTICAL_CHROMINANCE_FILTER 0x70000000 101#define VC_SCALING_OFF 0x00000000 102#define VC_LINE_REPLICATION 0x10000000 103#define VC_UP_INTERPOLATION 0x20000000 104#define VC_PIXEL_DROPPING 0x50000000 105#define VC_DOWN_INTERPOLATION 0x60000000 106#define VERTICAL_LUMINANCE_FILTER 0x0E000000 107#define VL_SCALING_OFF 0x00000000 108#define VL_LINE_REPLICATION 0x02000000 109#define VL_UP_INTERPOLATION 0x04000000 110#define VL_PIXEL_DROPPING 0x0A000000 111#define VL_DOWN_INTERPOLATION 0x0C000000 112#define HORIZONTAL_CHROMINANCE_FILTER 0x01C00000 113#define HC_SCALING_OFF 0x00000000 114#define HC_LINE_REPLICATION 0x00400000 115#define HC_UP_INTERPOLATION 0x00800000 116#define HC_PIXEL_DROPPING 0x01400000 117#define HC_DOWN_INTERPOLATION 0x01800000 118#define HORIZONTAL_LUMINANCE_FILTER 0x00380000 119#define HL_SCALING_OFF 0x00000000 120#define HL_LINE_REPLICATION 0x00080000 121#define HL_UP_INTERPOLATION 0x00100000 122#define HL_PIXEL_DROPPING 0x00280000 123#define HL_DOWN_INTERPOLATION 0x00300000 124 125#define Y_ADJUST 0x00010000 126#define OV_BYTE_ORDER 0x0000C000 127#define UV_SWAP 0x00004000 128#define Y_SWAP 0x00008000 129#define Y_AND_UV_SWAP 0x0000C000 130#define SOURCE_FORMAT 0x00003C00 131#define RGB_555 0x00000800 132#define RGB_565 0x00000C00 133#define YUV_422 0x00002000 134#define YUV_411 0x00002400 135#define YUV_420 0x00003000 136#define YUV_410 0x00003800 137#define BUFFER_AND_FIELD 0x00000006 138#define BUFFER0_FIELD0 0x00000000 139#define BUFFER1_FIELD0 0x00000004 140#define OVERLAY_ENABLE 0x00000001 141 142#define UV_VERT_BUF1 0x02 143#define UV_VERT_BUF0 0x04 144 145/* 146 * DOV0STA - Display/Overlay 0 Status Register 147 */ 148#define DOV0STA 0x30008 149 150#define MINUV_SCALE 0x1 151 152#define RGB16ToColorKey(c) \ 153 (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3)) 154 155#define RGB15ToColorKey(c) \ 156 (((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3)) 157 158void I810InitVideo(ScreenPtr screen) 159{ 160 ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 161 XF86VideoAdaptorPtr *adaptors = NULL; 162 int num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 163 164 if (pScrn->bitsPerPixel != 8) { 165 XF86VideoAdaptorPtr newAdaptor; 166 167 newAdaptor = I810SetupImageVideo(screen); 168 I810InitOffscreenImages(screen); 169 170 if (newAdaptor) { 171 XF86VideoAdaptorPtr *newAdaptors; 172 173 newAdaptors = 174 realloc(adaptors, 175 (num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr)); 176 if (newAdaptors != NULL) { 177 newAdaptors[num_adaptors++] = newAdaptor; 178 adaptors = newAdaptors; 179 } 180 } 181 } 182 183 if (num_adaptors) 184 xf86XVScreenInit(screen, adaptors, num_adaptors); 185 186 free(adaptors); 187} 188 189/* *INDENT-OFF* */ 190/* client libraries expect an encoding */ 191static XF86VideoEncodingRec DummyEncoding[1] = 192{ 193 { 194 0, 195 "XV_IMAGE", 196 IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, 197 {1, 1} 198 } 199}; 200 201#define NUM_FORMATS 3 202 203static XF86VideoFormatRec Formats[NUM_FORMATS] = 204{ 205 {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 206}; 207 208#define NUM_ATTRIBUTES 3 209 210static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = 211{ 212 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 213 {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, 214 {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"} 215}; 216 217#define NUM_IMAGES 6 218 219#define I810_RV15 0x35315652 220#define I810_RV16 0x36315652 221 222static XF86ImageRec Images[NUM_IMAGES] = 223{ 224 { 225 I810_RV15, 226 XvRGB, 227 LSBFirst, 228 {'R','V','1','5', 229 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 230 16, 231 XvPacked, 232 1, 233 15, 0x7C00, 0x03E0, 0x001F, 234 0, 0, 0, 235 0, 0, 0, 236 0, 0, 0, 237 {'R','V','B',0, 238 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 239 XvTopToBottom 240 }, 241 { 242 I810_RV16, 243 XvRGB, 244 LSBFirst, 245 {'R','V','1','6', 246 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 247 16, 248 XvPacked, 249 1, 250 16, 0xF800, 0x07E0, 0x001F, 251 0, 0, 0, 252 0, 0, 0, 253 0, 0, 0, 254 {'R','V','B',0, 255 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 256 XvTopToBottom 257 }, 258 XVIMAGE_YUY2, 259 XVIMAGE_YV12, 260 XVIMAGE_I420, 261 XVIMAGE_UYVY 262}; 263/* *INDENT-ON* */ 264 265typedef struct { 266 uint32_t OBUF_0Y; 267 uint32_t OBUF_1Y; 268 uint32_t OBUF_0U; 269 uint32_t OBUF_0V; 270 uint32_t OBUF_1U; 271 uint32_t OBUF_1V; 272 uint32_t OV0STRIDE; 273 uint32_t YRGB_VPH; 274 uint32_t UV_VPH; 275 uint32_t HORZ_PH; 276 uint32_t INIT_PH; 277 uint32_t DWINPOS; 278 uint32_t DWINSZ; 279 uint32_t SWID; 280 uint32_t SWIDQW; 281 uint32_t SHEIGHT; 282 uint32_t YRGBSCALE; 283 uint32_t UVSCALE; 284 uint32_t OV0CLRC0; 285 uint32_t OV0CLRC1; 286 uint32_t DCLRKV; 287 uint32_t DCLRKM; 288 uint32_t SCLRKVH; 289 uint32_t SCLRKVL; 290 uint32_t SCLRKM; 291 uint32_t OV0CONF; 292 uint32_t OV0CMD; 293} I810OverlayRegRec, *I810OverlayRegPtr; 294 295typedef struct { 296 uint32_t YBuf0offset; 297 uint32_t UBuf0offset; 298 uint32_t VBuf0offset; 299 300 uint32_t YBuf1offset; 301 uint32_t UBuf1offset; 302 uint32_t VBuf1offset; 303 304 unsigned char currentBuf; 305 306 int brightness; 307 int contrast; 308 309 RegionRec clip; 310 uint32_t colorKey; 311 312 uint32_t videoStatus; 313 Time offTime; 314 Time freeTime; 315 FBLinearPtr linear; 316} I810PortPrivRec, *I810PortPrivPtr; 317 318#define GET_PORT_PRIVATE(pScrn) \ 319 (I810PortPrivPtr)((I810PTR(pScrn))->adaptor->pPortPrivates[0].ptr) 320 321static void I810ResetVideo(ScrnInfoPtr pScrn) 322{ 323 I810Ptr pI810 = I810PTR(pScrn); 324 I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr; 325 I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 326 327 /* 328 * Default to maximum image size in YV12 329 */ 330 331 overlay->YRGB_VPH = 0; 332 overlay->UV_VPH = 0; 333 overlay->HORZ_PH = 0; 334 overlay->INIT_PH = 0; 335 overlay->DWINPOS = 0; 336 overlay->DWINSZ = (IMAGE_MAX_HEIGHT << 16) | IMAGE_MAX_WIDTH; 337 overlay->SWID = IMAGE_MAX_WIDTH | (IMAGE_MAX_WIDTH << 15); 338 overlay->SWIDQW = (IMAGE_MAX_WIDTH >> 3) | (IMAGE_MAX_WIDTH << 12); 339 overlay->SHEIGHT = IMAGE_MAX_HEIGHT | (IMAGE_MAX_HEIGHT << 15); 340 overlay->YRGBSCALE = 0x80004000; /* scale factor 1 */ 341 overlay->UVSCALE = 0x80004000; /* scale factor 1 */ 342 overlay->OV0CLRC0 = 0x4000; /* brightness: 0 contrast: 1.0 */ 343 overlay->OV0CLRC1 = 0x80; /* saturation: bypass */ 344 345 /* 346 * Enable destination color keying 347 */ 348 switch(pScrn->depth) { 349 case 16: overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey); 350 overlay->DCLRKM = 0x80070307; 351 break; 352 case 15: overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey); 353 overlay->DCLRKM = 0x80070707; 354 break; 355 default: overlay->DCLRKV = pPriv->colorKey; 356 overlay->DCLRKM = 0x80000000; 357 break; 358 } 359 360 overlay->SCLRKVH = 0; 361 overlay->SCLRKVL = 0; 362 overlay->SCLRKM = 0; /* source color key disable */ 363 overlay->OV0CONF = 0; /* two 720 pixel line buffers */ 364 365 overlay->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | Y_ADJUST | 366 YUV_420; 367 368 OVERLAY_UPDATE(pI810->OverlayPhysical); 369} 370 371 372static XF86VideoAdaptorPtr 373I810SetupImageVideo(ScreenPtr screen) 374{ 375 ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 376 I810Ptr pI810 = I810PTR(pScrn); 377 XF86VideoAdaptorPtr adapt; 378 I810PortPrivPtr pPriv; 379 380 if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 381 sizeof(I810PortPrivRec) + 382 sizeof(DevUnion)))) 383 return NULL; 384 385 adapt->type = XvWindowMask | XvInputMask | XvImageMask; 386 adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 387 adapt->name = "I810 Video Overlay"; 388 adapt->nEncodings = 1; 389 adapt->pEncodings = DummyEncoding; 390 adapt->nFormats = NUM_FORMATS; 391 adapt->pFormats = Formats; 392 adapt->nPorts = 1; 393 adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 394 395 pPriv = (I810PortPrivPtr)(&adapt->pPortPrivates[1]); 396 397 adapt->pPortPrivates[0].ptr = (pointer)(pPriv); 398 adapt->pAttributes = Attributes; 399 adapt->nImages = NUM_IMAGES; 400 adapt->nAttributes = NUM_ATTRIBUTES; 401 adapt->pImages = Images; 402 adapt->PutVideo = NULL; 403 adapt->PutStill = NULL; 404 adapt->GetVideo = NULL; 405 adapt->GetStill = NULL; 406 adapt->StopVideo = I810StopVideo; 407 adapt->SetPortAttribute = I810SetPortAttribute; 408 adapt->GetPortAttribute = I810GetPortAttribute; 409 adapt->QueryBestSize = I810QueryBestSize; 410 adapt->PutImage = I810PutImage; 411 adapt->QueryImageAttributes = I810QueryImageAttributes; 412 413 pPriv->colorKey = pI810->colorKey & ((1 << pScrn->depth) - 1); 414 pPriv->videoStatus = 0; 415 pPriv->brightness = 0; 416 pPriv->contrast = 64; 417 pPriv->linear = NULL; 418 pPriv->currentBuf = 0; 419 420 /* gotta uninit this someplace */ 421 REGION_NULL(screen, &pPriv->clip); 422 423 pI810->adaptor = adapt; 424 425#if !HAVE_NOTIFY_FD 426 pI810->BlockHandler = screen->BlockHandler; 427 screen->BlockHandler = I810BlockHandler; 428#else 429 RegisterBlockAndWakeupHandlers(I810BlockHandler, 430 (ServerWakeupHandlerProcPtr)NoopDDA, 431 pScrn); 432#endif 433 434 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 435 xvContrast = MAKE_ATOM("XV_CONTRAST"); 436 xvColorKey = MAKE_ATOM("XV_COLORKEY"); 437 438 I810ResetVideo(pScrn); 439 440 return adapt; 441} 442 443 444/* I810ClipVideo - 445 446 Takes the dst box in standard X BoxRec form (top and left 447 edges inclusive, bottom and right exclusive). The new dst 448 box is returned. The source boundaries are given (x1, y1 449 inclusive, x2, y2 exclusive) and returned are the new source 450 boundaries in 16.16 fixed point. 451*/ 452 453static void 454I810ClipVideo( 455 BoxPtr dst, 456 INT32 *x1, 457 INT32 *x2, 458 INT32 *y1, 459 INT32 *y2, 460 BoxPtr extents, /* extents of the clip region */ 461 INT32 width, 462 INT32 height 463){ 464 INT32 vscale, hscale, delta; 465 int diff; 466 467 hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1); 468 vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1); 469 470 *x1 <<= 16; *x2 <<= 16; 471 *y1 <<= 16; *y2 <<= 16; 472 473 diff = extents->x1 - dst->x1; 474 if(diff > 0) { 475 dst->x1 = extents->x1; 476 *x1 += diff * hscale; 477 } 478 diff = dst->x2 - extents->x2; 479 if(diff > 0) { 480 dst->x2 = extents->x2; 481 *x2 -= diff * hscale; 482 } 483 diff = extents->y1 - dst->y1; 484 if(diff > 0) { 485 dst->y1 = extents->y1; 486 *y1 += diff * vscale; 487 } 488 diff = dst->y2 - extents->y2; 489 if(diff > 0) { 490 dst->y2 = extents->y2; 491 *y2 -= diff * vscale; 492 } 493 494 if(*x1 < 0) { 495 diff = (- *x1 + hscale - 1)/ hscale; 496 dst->x1 += diff; 497 *x1 += diff * hscale; 498 } 499 delta = *x2 - (width << 16); 500 if(delta > 0) { 501 diff = (delta + hscale - 1)/ hscale; 502 dst->x2 -= diff; 503 *x2 -= diff * hscale; 504 } 505 if(*y1 < 0) { 506 diff = (- *y1 + vscale - 1)/ vscale; 507 dst->y1 += diff; 508 *y1 += diff * vscale; 509 } 510 delta = *y2 - (height << 16); 511 if(delta > 0) { 512 diff = (delta + vscale - 1)/ vscale; 513 dst->y2 -= diff; 514 *y2 -= diff * vscale; 515 } 516} 517 518static void 519I810StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) 520{ 521 I810PortPrivPtr pPriv = (I810PortPrivPtr)data; 522 I810Ptr pI810 = I810PTR(pScrn); 523 524 I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 525 526 REGION_EMPTY(pScrn->screen, &pPriv->clip); 527 528 if(shutdown) { 529 if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 530 overlay->OV0CMD &= 0xFFFFFFFE; 531 OVERLAY_UPDATE(pI810->OverlayPhysical); 532 } 533 if(pPriv->linear) { 534 xf86FreeOffscreenLinear(pPriv->linear); 535 pPriv->linear = NULL; 536 } 537 pPriv->videoStatus = 0; 538 } else { 539 if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 540 pPriv->videoStatus |= OFF_TIMER; 541 pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 542 } 543 } 544 545} 546 547static int 548I810SetPortAttribute( 549 ScrnInfoPtr pScrn, 550 Atom attribute, 551 INT32 value, 552 pointer data 553){ 554 I810PortPrivPtr pPriv = (I810PortPrivPtr)data; 555 I810Ptr pI810 = I810PTR(pScrn); 556 I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 557 558 if(attribute == xvBrightness) { 559 if((value < -128) || (value > 127)) 560 return BadValue; 561 pPriv->brightness = value; 562 overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff); 563 OVERLAY_UPDATE(pI810->OverlayPhysical); 564 } else 565 if(attribute == xvContrast) { 566 if((value < 0) || (value > 255)) 567 return BadValue; 568 pPriv->contrast = value; 569 overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff); 570 OVERLAY_UPDATE(pI810->OverlayPhysical); 571 } else 572 if(attribute == xvColorKey) { 573 pPriv->colorKey = value; 574 switch(pScrn->depth) { 575 case 16: overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey); 576 break; 577 case 15: overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey); 578 break; 579 default: overlay->DCLRKV = pPriv->colorKey; 580 break; 581 } 582 OVERLAY_UPDATE(pI810->OverlayPhysical); 583 REGION_EMPTY(pScrn->screen, &pPriv->clip); 584 } else return BadMatch; 585 586 return Success; 587} 588 589static int 590I810GetPortAttribute( 591 ScrnInfoPtr pScrn, 592 Atom attribute, 593 INT32 *value, 594 pointer data 595){ 596 I810PortPrivPtr pPriv = (I810PortPrivPtr)data; 597 598 if(attribute == xvBrightness) { 599 *value = pPriv->brightness; 600 } else 601 if(attribute == xvContrast) { 602 *value = pPriv->contrast; 603 } else 604 if(attribute == xvColorKey) { 605 *value = pPriv->colorKey; 606 } else return BadMatch; 607 608 return Success; 609} 610 611static void 612I810QueryBestSize( 613 ScrnInfoPtr pScrn, 614 Bool motion, 615 short vid_w, short vid_h, 616 short drw_w, short drw_h, 617 unsigned int *p_w, unsigned int *p_h, 618 pointer data 619){ 620 if(vid_w > (drw_w << 1)) drw_w = vid_w >> 1; 621 if(vid_h > (drw_h << 1)) drw_h = vid_h >> 1; 622 623 *p_w = drw_w; 624 *p_h = drw_h; 625} 626 627 628static void 629I810CopyPackedData( 630 ScrnInfoPtr pScrn, 631 unsigned char *buf, 632 int srcPitch, 633 int dstPitch, 634 int top, 635 int left, 636 int h, 637 int w 638 ) 639{ 640 I810Ptr pI810 = I810PTR(pScrn); 641 I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr; 642 unsigned char *src, *dst; 643 644 src = buf + (top*srcPitch) + (left<<1); 645 646 if (pPriv->currentBuf == 0) 647 dst = pI810->FbBase + pPriv->YBuf0offset; 648 else 649 dst = pI810->FbBase + pPriv->YBuf1offset; 650 651 w <<= 1; 652 while(h--) { 653 memcpy(dst, src, w); 654 src += srcPitch; 655 dst += dstPitch; 656 } 657} 658 659static void 660I810CopyPlanarData( 661 ScrnInfoPtr pScrn, 662 unsigned char *buf, 663 int srcPitch, 664 int dstPitch, /* of chroma */ 665 int srcH, 666 int top, 667 int left, 668 int h, 669 int w, 670 int id 671 ) 672{ 673 I810Ptr pI810 = I810PTR(pScrn); 674 I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr; 675 int i; 676 unsigned char *src1, *src2, *src3, *dst1, *dst2, *dst3; 677 678 /* Copy Y data */ 679 src1 = buf + (top*srcPitch) + left; 680 if (pPriv->currentBuf == 0) 681 dst1 = pI810->FbBase + pPriv->YBuf0offset; 682 else 683 dst1 = pI810->FbBase + pPriv->YBuf1offset; 684 685 for (i = 0; i < h; i++) { 686 memcpy(dst1, src1, w); 687 src1 += srcPitch; 688 dst1 += dstPitch << 1; 689 } 690 691 /* Copy V data for YV12, or U data for I420 */ 692 src2 = buf + (srcH*srcPitch) + ((top*srcPitch)>>2) + (left>>1); 693 if (pPriv->currentBuf == 0) { 694 if (id == FOURCC_I420) 695 dst2 = pI810->FbBase + pPriv->UBuf0offset; 696 else 697 dst2 = pI810->FbBase + pPriv->VBuf0offset; 698 } else { 699 if (id == FOURCC_I420) 700 dst2 = pI810->FbBase + pPriv->UBuf1offset; 701 else 702 dst2 = pI810->FbBase + pPriv->VBuf1offset; 703 } 704 705 for (i = 0; i < h/2; i++) { 706 memcpy(dst2, src2, w/2); 707 src2 += srcPitch>>1; 708 dst2 += dstPitch; 709 } 710 711 /* Copy U data for YV12, or V data for I420 */ 712 src3 = buf + (srcH*srcPitch) + ((srcH*srcPitch)>>2) + ((top*srcPitch)>>2) + (left>>1); 713 if (pPriv->currentBuf == 0) { 714 if (id == FOURCC_I420) 715 dst3 = pI810->FbBase + pPriv->VBuf0offset; 716 else 717 dst3 = pI810->FbBase + pPriv->UBuf0offset; 718 } else { 719 if (id == FOURCC_I420) 720 dst3 = pI810->FbBase + pPriv->VBuf1offset; 721 else 722 dst3 = pI810->FbBase + pPriv->UBuf1offset; 723 } 724 725 for (i = 0; i < h/2; i++) { 726 memcpy(dst3, src3, w/2); 727 src3 += srcPitch>>1; 728 dst3 += dstPitch; 729 } 730} 731 732static void 733I810DisplayVideo( 734 ScrnInfoPtr pScrn, 735 int id, 736 short width, short height, 737 int dstPitch, /* of chroma for 4:2:0 */ 738 int x1, int y1, int x2, int y2, 739 BoxPtr dstBox, 740 short src_w, short src_h, 741 short drw_w, short drw_h 742){ 743 I810Ptr pI810 = I810PTR(pScrn); 744 I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr; 745 I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 746 int xscaleInt, xscaleFract, yscaleInt, yscaleFract; 747 int xscaleIntUV = 0, xscaleFractUV = 0, yscaleIntUV = 0, yscaleFractUV = 0; 748 unsigned int swidth; 749 750 switch(id) { 751 case FOURCC_YV12: 752 case FOURCC_I420: 753 swidth = ALIGN(width, 8); 754 overlay->SWID = (swidth << 15) | swidth; 755 overlay->SWIDQW = (swidth << 12) | (swidth >> 3); 756 break; 757 case FOURCC_UYVY: 758 case FOURCC_YUY2: 759 default: 760 swidth = ALIGN(width, 4) << 1; 761 overlay->SWID = swidth; 762 overlay->SWIDQW = swidth >> 3; 763 break; 764 } 765 766 /* wide video formats (>720 pixels) are special */ 767 if( swidth > IMAGE_FAST_WIDTH ) { 768 overlay->OV0CONF = 1; /* one 1440 pixel line buffer */ 769 } else { 770 overlay->OV0CONF = 0; /* two 720 pixel line buffers */ 771 } 772 773 overlay->SHEIGHT = height | (height << 15); 774 overlay->DWINPOS = (dstBox->y1 << 16) | (dstBox->x1); 775 overlay->DWINSZ = ((dstBox->y2 - dstBox->y1) << 16) | 776 (dstBox->x2 - dstBox->x1); 777 778 /* buffer locations */ 779 overlay->OBUF_0Y = pPriv->YBuf0offset; 780 overlay->OBUF_1Y = pPriv->YBuf1offset; 781 overlay->OBUF_0U = pPriv->UBuf0offset; 782 overlay->OBUF_0V = pPriv->VBuf0offset; 783 overlay->OBUF_1U = pPriv->UBuf1offset; 784 overlay->OBUF_1V = pPriv->VBuf1offset; 785 786 /* 787 * Calculate horizontal and vertical scaling factors, default to 1:1 788 */ 789 overlay->YRGBSCALE = 0x80004000; 790 overlay->UVSCALE = 0x80004000; 791 792 /* 793 * Initially, YCbCr and Overlay Enable and 794 * vertical chrominance up interpolation and horozontal chrominance 795 * up interpolation 796 */ 797 overlay->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | Y_ADJUST | 798 OVERLAY_ENABLE; 799 800 if ((drw_w != src_w) || (drw_h != src_h)) 801 { 802 xscaleInt = (src_w / drw_w) & 0x3; 803 xscaleFract = (src_w << 12) / drw_w; 804 yscaleInt = (src_h / drw_h) & 0x3; 805 yscaleFract = (src_h << 12) / drw_h; 806 807 overlay->YRGBSCALE = (xscaleInt << 15) | 808 ((xscaleFract & 0xFFF) << 3) | 809 (yscaleInt) | 810 ((yscaleFract & 0xFFF) << 20); 811 812 if (drw_w > src_w) 813 { 814 /* horizontal up-scaling */ 815 overlay->OV0CMD &= ~HORIZONTAL_CHROMINANCE_FILTER; 816 overlay->OV0CMD &= ~HORIZONTAL_LUMINANCE_FILTER; 817 overlay->OV0CMD |= (HC_UP_INTERPOLATION | HL_UP_INTERPOLATION); 818 } 819 820 if (drw_h > src_h) 821 { 822 /* vertical up-scaling */ 823 overlay->OV0CMD &= ~VERTICAL_CHROMINANCE_FILTER; 824 overlay->OV0CMD &= ~VERTICAL_LUMINANCE_FILTER; 825 overlay->OV0CMD |= (VC_UP_INTERPOLATION | VL_UP_INTERPOLATION); 826 } 827 828 if (drw_w < src_w) 829 { 830 /* horizontal down-scaling */ 831 overlay->OV0CMD &= ~HORIZONTAL_CHROMINANCE_FILTER; 832 overlay->OV0CMD &= ~HORIZONTAL_LUMINANCE_FILTER; 833 overlay->OV0CMD |= (HC_DOWN_INTERPOLATION | HL_DOWN_INTERPOLATION); 834 } 835 836 if (drw_h < src_h) 837 { 838 /* vertical down-scaling */ 839 overlay->OV0CMD &= ~VERTICAL_CHROMINANCE_FILTER; 840 overlay->OV0CMD &= ~VERTICAL_LUMINANCE_FILTER; 841 overlay->OV0CMD |= (VC_DOWN_INTERPOLATION | VL_DOWN_INTERPOLATION); 842 } 843 844 /* now calculate the UV scaling factor */ 845 846 if (xscaleFract) 847 { 848 xscaleFractUV = xscaleFract >> MINUV_SCALE; 849 overlay->OV0CMD &= ~HC_DOWN_INTERPOLATION; 850 overlay->OV0CMD |= HC_UP_INTERPOLATION; 851 } 852 853 if (xscaleInt) 854 { 855 xscaleIntUV = xscaleInt >> MINUV_SCALE; 856 if (xscaleIntUV) 857 { 858 overlay->OV0CMD &= ~HC_UP_INTERPOLATION; 859 } 860 } 861 862 if (yscaleFract) 863 { 864 yscaleFractUV = yscaleFract >> MINUV_SCALE; 865 overlay->OV0CMD &= ~VC_DOWN_INTERPOLATION; 866 overlay->OV0CMD |= VC_UP_INTERPOLATION; 867 } 868 869 if (yscaleInt) 870 { 871 yscaleIntUV = yscaleInt >> MINUV_SCALE; 872 if (yscaleIntUV) 873 { 874 overlay->OV0CMD &= ~VC_UP_INTERPOLATION; 875 overlay->OV0CMD |= VC_DOWN_INTERPOLATION; 876 } 877 } 878 879 overlay->UVSCALE = yscaleIntUV | ((xscaleFractUV & 0xFFF) << 3) | 880 ((yscaleFractUV & 0xFFF) << 20); 881 } 882 883 switch(id) { 884 case FOURCC_YV12: 885 case FOURCC_I420: 886 /* set UV vertical phase to -0.25 */ 887 overlay->UV_VPH = 0x30003000; 888 overlay->INIT_PH = UV_VERT_BUF0 | UV_VERT_BUF1; 889 overlay->OV0STRIDE = (dstPitch << 1) | (dstPitch << 16); 890 overlay->OV0CMD &= ~SOURCE_FORMAT; 891 overlay->OV0CMD |= YUV_420; 892 break; 893 case I810_RV15: 894 case I810_RV16: 895 overlay->UV_VPH = 0; 896 overlay->INIT_PH = 0; 897 overlay->OV0STRIDE = dstPitch; 898 overlay->OV0CMD &= ~SOURCE_FORMAT; 899 overlay->OV0CMD |= (id==I810_RV15 ? RGB_555 : RGB_565); 900 overlay->OV0CMD &= ~OV_BYTE_ORDER; 901 break; 902 case FOURCC_UYVY: 903 case FOURCC_YUY2: 904 default: 905 overlay->UV_VPH = 0; 906 overlay->INIT_PH = 0; 907 overlay->OV0STRIDE = dstPitch; 908 overlay->OV0CMD &= ~SOURCE_FORMAT; 909 overlay->OV0CMD |= YUV_422; 910 overlay->OV0CMD &= ~OV_BYTE_ORDER; 911 if (id == FOURCC_UYVY) 912 overlay->OV0CMD |= Y_SWAP; 913 break; 914 } 915 916 overlay->OV0CMD &= ~BUFFER_AND_FIELD; 917 if (pPriv->currentBuf == 0) 918 overlay->OV0CMD |= BUFFER0_FIELD0; 919 else 920 overlay->OV0CMD |= BUFFER1_FIELD0; 921 922 OVERLAY_UPDATE(pI810->OverlayPhysical); 923 924} 925 926static FBLinearPtr 927I810AllocateMemory( 928 ScrnInfoPtr pScrn, 929 FBLinearPtr linear, 930 int size 931){ 932 ScreenPtr screen; 933 FBLinearPtr new_linear; 934 935 if(linear) { 936 if(linear->size >= size) 937 return linear; 938 939 if(xf86ResizeOffscreenLinear(linear, size)) 940 return linear; 941 942 xf86FreeOffscreenLinear(linear); 943 } 944 945 screen = xf86ScrnToScreen(pScrn); 946 947 new_linear = xf86AllocateOffscreenLinear(screen, size, 4, 948 NULL, NULL, NULL); 949 950 if(!new_linear) { 951 int max_size; 952 953 xf86QueryLargestOffscreenLinear(screen, &max_size, 4, 954 PRIORITY_EXTREME); 955 956 if(max_size < size) return NULL; 957 958 xf86PurgeUnlockedOffscreenAreas(screen); 959 new_linear = xf86AllocateOffscreenLinear(screen, size, 4, 960 NULL, NULL, NULL); 961 } 962 963 return new_linear; 964} 965 966static int 967I810PutImage( 968 ScrnInfoPtr pScrn, 969 short src_x, short src_y, 970 short drw_x, short drw_y, 971 short src_w, short src_h, 972 short drw_w, short drw_h, 973 int id, unsigned char* buf, 974 short width, short height, 975 Bool sync, 976 RegionPtr clipBoxes, pointer data, 977 DrawablePtr pDraw 978){ 979 I810Ptr pI810 = I810PTR(pScrn); 980 I810PortPrivPtr pPriv = (I810PortPrivPtr)data; 981 INT32 x1, x2, y1, y2; 982 int srcPitch, dstPitch; 983 int top, left, npixels, nlines, size, loops; 984 BoxRec dstBox; 985 986 987 /* Clip */ 988 x1 = src_x; 989 x2 = src_x + src_w; 990 y1 = src_y; 991 y2 = src_y + src_h; 992 993 dstBox.x1 = drw_x; 994 dstBox.x2 = drw_x + drw_w; 995 dstBox.y1 = drw_y; 996 dstBox.y2 = drw_y + drw_h; 997 998 I810ClipVideo(&dstBox, &x1, &x2, &y1, &y2, 999 REGION_EXTENTS(pScrn->screen, clipBoxes), width, height); 1000 1001 if((x1 >= x2) || (y1 >= y2)) 1002 return Success; 1003 /* 1004 * Fix for 4 pixel granularity of AdjustFrame 1005 * unless boarder is clipped by frame 1006 */ 1007 dstBox.x1 -= (pScrn->frameX0 & 1008 ((dstBox.x1 == pScrn->frameX0) ? ~0x0UL : ~0x3UL)); 1009 dstBox.x2 -= (pScrn->frameX0 & ~0x3); 1010 dstBox.y1 -= pScrn->frameY0; 1011 dstBox.y2 -= pScrn->frameY0; 1012 1013 switch(id) { 1014 case FOURCC_YV12: 1015 case FOURCC_I420: 1016 srcPitch = ALIGN(width, 4); 1017 dstPitch = ALIGN((width >> 1), 8); /* of chroma */ 1018 size = dstPitch * height * 3; 1019 break; 1020 case FOURCC_UYVY: 1021 case FOURCC_YUY2: 1022 default: 1023 srcPitch = (width << 1); 1024 dstPitch = ALIGN(srcPitch, 8); 1025 size = dstPitch * height; 1026 break; 1027 } 1028 1029 if(!(pPriv->linear = I810AllocateMemory(pScrn, pPriv->linear, 1030 (pScrn->bitsPerPixel == 16) ? size : (size >> 1)))) 1031 return BadAlloc; 1032 1033 /* fixup pointers */ 1034 pPriv->YBuf0offset = pPriv->linear->offset * pI810->cpp; 1035 pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height); 1036 pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height >> 1); 1037 1038 pPriv->YBuf1offset = (pPriv->linear->offset * pI810->cpp) + size; 1039 pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height); 1040 pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height >> 1); 1041 1042 1043 /* Make sure this buffer isn't in use */ 1044 loops = 0; 1045 while (loops < 1000000) { 1046 if(((INREG(DOV0STA)&0x00100000)>>20) == pPriv->currentBuf) { 1047 break; 1048 } 1049 loops++; 1050 } 1051 if(loops >= 1000000) { 1052 pPriv->currentBuf = !pPriv->currentBuf; 1053 } 1054 1055 1056 /* buffer swap */ 1057 if (pPriv->currentBuf == 0) 1058 pPriv->currentBuf = 1; 1059 else 1060 pPriv->currentBuf = 0; 1061 1062 /* copy data */ 1063 top = y1 >> 16; 1064 left = (x1 >> 16) & ~1; 1065 npixels = ALIGN(((x2 + 0xffff) >> 16), 2) - left; 1066 1067 switch(id) { 1068 case FOURCC_YV12: 1069 case FOURCC_I420: 1070 top &= ~1; 1071 nlines = ALIGN(((y2 + 0xffff) >> 16), 2) - top; 1072 I810CopyPlanarData(pScrn, buf, srcPitch, dstPitch, height, top, left, 1073 nlines, npixels, id); 1074 break; 1075 case FOURCC_UYVY: 1076 case FOURCC_YUY2: 1077 default: 1078 nlines = ((y2 + 0xffff) >> 16) - top; 1079 I810CopyPackedData(pScrn, buf, srcPitch, dstPitch, top, left, nlines, 1080 npixels); 1081 break; 1082 } 1083 1084 /* update cliplist */ 1085 if(!REGION_EQUAL(pScrn->screen, &pPriv->clip, clipBoxes)) { 1086 REGION_COPY(pScrn->screen, &pPriv->clip, clipBoxes); 1087 /* draw these */ 1088 xf86XVFillKeyHelperDrawable(pDraw, pPriv->colorKey, clipBoxes); 1089 } 1090 1091 I810DisplayVideo(pScrn, id, width, height, dstPitch, 1092 x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 1093 1094 pPriv->videoStatus = CLIENT_VIDEO_ON; 1095 1096 return Success; 1097} 1098 1099 1100static int 1101I810QueryImageAttributes( 1102 ScrnInfoPtr pScrn, 1103 int id, 1104 unsigned short *w, unsigned short *h, 1105 int *pitches, int *offsets 1106){ 1107 int size, tmp; 1108 1109 if(*w > IMAGE_MAX_WIDTH) *w = IMAGE_MAX_WIDTH; 1110 if(*h > IMAGE_MAX_HEIGHT) *h = IMAGE_MAX_HEIGHT; 1111 1112 *w = (*w + 1) & ~1; 1113 if(offsets) offsets[0] = 0; 1114 1115 switch(id) { 1116 /* IA44 is for XvMC only */ 1117 case FOURCC_IA44: 1118 case FOURCC_AI44: 1119 if(pitches) pitches[0] = *w; 1120 size = *w * *h; 1121 break; 1122 case FOURCC_YV12: 1123 case FOURCC_I420: 1124 *h = (*h + 1) & ~1; 1125 size = (*w + 3) & ~3; 1126 if(pitches) pitches[0] = size; 1127 size *= *h; 1128 if(offsets) offsets[1] = size; 1129 tmp = ((*w >> 1) + 3) & ~3; 1130 if(pitches) pitches[1] = pitches[2] = tmp; 1131 tmp *= (*h >> 1); 1132 size += tmp; 1133 if(offsets) offsets[2] = size; 1134 size += tmp; 1135 break; 1136 case FOURCC_UYVY: 1137 case FOURCC_YUY2: 1138 default: 1139 size = *w << 1; 1140 if(pitches) pitches[0] = size; 1141 size *= *h; 1142 break; 1143 } 1144 1145 return size; 1146} 1147 1148#if !HAVE_NOTIFY_FD 1149static void 1150I810BlockHandler (BLOCKHANDLER_ARGS_DECL) 1151{ 1152 SCREEN_PTR(arg); 1153 ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 1154 I810Ptr pI810 = I810PTR(pScrn); 1155 I810PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 1156 I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 1157 1158 screen->BlockHandler = pI810->BlockHandler; 1159 1160 (*screen->BlockHandler) (BLOCKHANDLER_ARGS); 1161 1162 screen->BlockHandler = I810BlockHandler; 1163 1164 if(pPriv->videoStatus & TIMER_MASK) { 1165 UpdateCurrentTime(); 1166 if(pPriv->videoStatus & OFF_TIMER) { 1167 if(pPriv->offTime < currentTime.milliseconds) { 1168 /* Turn off the overlay */ 1169 overlay->OV0CMD &= 0xFFFFFFFE; 1170 OVERLAY_UPDATE(pI810->OverlayPhysical); 1171 1172 pPriv->videoStatus = FREE_TIMER; 1173 pPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 1174 } 1175 } else { /* FREE_TIMER */ 1176 if(pPriv->freeTime < currentTime.milliseconds) { 1177 if(pPriv->linear) { 1178 xf86FreeOffscreenLinear(pPriv->linear); 1179 pPriv->linear = NULL; 1180 } 1181 pPriv->videoStatus = 0; 1182 } 1183 } 1184 } 1185} 1186#else 1187static void 1188I810BlockHandler(void *data, void *_timeout) 1189{ 1190 ScrnInfoPtr pScrn = data; 1191 I810Ptr pI810 = I810PTR(pScrn); 1192 I810PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 1193 I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 1194 1195 if(pPriv->videoStatus & TIMER_MASK) { 1196 UpdateCurrentTime(); 1197 if(pPriv->videoStatus & OFF_TIMER) { 1198 if(pPriv->offTime < currentTime.milliseconds) { 1199 /* Turn off the overlay */ 1200 overlay->OV0CMD &= 0xFFFFFFFE; 1201 OVERLAY_UPDATE(pI810->OverlayPhysical); 1202 1203 pPriv->videoStatus = FREE_TIMER; 1204 pPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 1205 } 1206 } else { /* FREE_TIMER */ 1207 if(pPriv->freeTime < currentTime.milliseconds) { 1208 if(pPriv->linear) { 1209 xf86FreeOffscreenLinear(pPriv->linear); 1210 pPriv->linear = NULL; 1211 } 1212 pPriv->videoStatus = 0; 1213 } 1214 } 1215 } 1216} 1217#endif 1218 1219 1220/*************************************************************************** 1221 * Offscreen Images 1222 ***************************************************************************/ 1223 1224typedef struct { 1225 FBLinearPtr linear; 1226 Bool isOn; 1227} OffscreenPrivRec, * OffscreenPrivPtr; 1228 1229static int 1230I810AllocateSurface( 1231 ScrnInfoPtr pScrn, 1232 int id, 1233 unsigned short w, 1234 unsigned short h, 1235 XF86SurfacePtr surface 1236){ 1237 FBLinearPtr linear; 1238 int pitch, size, bpp; 1239 OffscreenPrivPtr pPriv; 1240 I810Ptr pI810 = I810PTR(pScrn); 1241 1242 if((w > 1024) || (h > 1024)) 1243 return BadAlloc; 1244 1245 w = ALIGN(w, 2); 1246 pitch = ALIGN((w << 1), 16); 1247 bpp = pScrn->bitsPerPixel >> 3; 1248 size = ((pitch * h) + bpp - 1) / bpp; 1249 1250 if(!(linear = I810AllocateMemory(pScrn, NULL, size))) 1251 return BadAlloc; 1252 1253 surface->width = w; 1254 surface->height = h; 1255 1256 if(!(surface->pitches = malloc(sizeof(int)))) { 1257 xf86FreeOffscreenLinear(linear); 1258 return BadAlloc; 1259 } 1260 if(!(surface->offsets = malloc(sizeof(int)))) { 1261 free(surface->pitches); 1262 xf86FreeOffscreenLinear(linear); 1263 return BadAlloc; 1264 } 1265 if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) { 1266 free(surface->pitches); 1267 free(surface->offsets); 1268 xf86FreeOffscreenLinear(linear); 1269 return BadAlloc; 1270 } 1271 1272 pPriv->linear = linear; 1273 pPriv->isOn = FALSE; 1274 1275 surface->pScrn = pScrn; 1276 surface->id = id; 1277 surface->pitches[0] = pitch; 1278 surface->offsets[0] = linear->offset * bpp; 1279 surface->devPrivate.ptr = (pointer)pPriv; 1280 1281 memset(pI810->FbBase + surface->offsets[0],0,size); 1282 1283 return Success; 1284} 1285 1286static int 1287I810StopSurface( 1288 XF86SurfacePtr surface 1289){ 1290 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 1291 1292 if(pPriv->isOn) { 1293 I810Ptr pI810 = I810PTR(surface->pScrn); 1294 1295 I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 1296 1297 overlay->OV0CMD &= 0xFFFFFFFE; 1298 OVERLAY_UPDATE(pI810->OverlayPhysical); 1299 1300 pPriv->isOn = FALSE; 1301 } 1302 1303 return Success; 1304} 1305 1306 1307static int 1308I810FreeSurface( 1309 XF86SurfacePtr surface 1310){ 1311 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 1312 1313 if(pPriv->isOn) { 1314 I810StopSurface(surface); 1315 } 1316 xf86FreeOffscreenLinear(pPriv->linear); 1317 free(surface->pitches); 1318 free(surface->offsets); 1319 free(surface->devPrivate.ptr); 1320 1321 return Success; 1322} 1323 1324static int 1325I810GetSurfaceAttribute( 1326 ScrnInfoPtr pScrn, 1327 Atom attribute, 1328 INT32 *value 1329){ 1330 return I810GetPortAttribute(pScrn, attribute, value, GET_PORT_PRIVATE(pScrn)); 1331} 1332 1333static int 1334I810SetSurfaceAttribute( 1335 ScrnInfoPtr pScrn, 1336 Atom attribute, 1337 INT32 value 1338){ 1339 return I810SetPortAttribute(pScrn, attribute, value, GET_PORT_PRIVATE(pScrn)); 1340} 1341 1342 1343static int 1344I810DisplaySurface( 1345 XF86SurfacePtr surface, 1346 short src_x, short src_y, 1347 short drw_x, short drw_y, 1348 short src_w, short src_h, 1349 short drw_w, short drw_h, 1350 RegionPtr clipBoxes 1351){ 1352 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 1353 ScrnInfoPtr pScrn = surface->pScrn; 1354 I810Ptr pI810 = I810PTR(pScrn); 1355 I810PortPrivPtr pI810Priv = GET_PORT_PRIVATE(pScrn); 1356 1357 INT32 x1, y1, x2, y2; 1358 INT32 loops = 0; 1359 BoxRec dstBox; 1360 1361 x1 = src_x; 1362 x2 = src_x + src_w; 1363 y1 = src_y; 1364 y2 = src_y + src_h; 1365 1366 dstBox.x1 = drw_x; 1367 dstBox.x2 = drw_x + drw_w; 1368 dstBox.y1 = drw_y; 1369 dstBox.y2 = drw_y + drw_h; 1370 1371 I810ClipVideo(&dstBox, &x1, &x2, &y1, &y2, 1372 REGION_EXTENTS(screenInfo.screens[0], clipBoxes), 1373 surface->width, surface->height); 1374 1375 /* 1376 * Fix for 4 pixel granularity of AdjustFrame 1377 * unless boarder is clipped by frame 1378 */ 1379 dstBox.x1 -= (pScrn->frameX0 & 1380 ((dstBox.x1 == pScrn->frameX0) ? ~0x0UL : ~0x3UL)); 1381 dstBox.x2 -= (pScrn->frameX0 & ~0x3); 1382 dstBox.y1 -= pScrn->frameY0; 1383 dstBox.y2 -= pScrn->frameY0; 1384 1385 /* fixup pointers */ 1386 pI810Priv->YBuf0offset = surface->offsets[0]; 1387 pI810Priv->YBuf1offset = pI810Priv->YBuf0offset; 1388 1389 /* wait for the last rendered buffer to be flipped in */ 1390 while (((INREG(DOV0STA)&0x00100000)>>20) != pI810Priv->currentBuf) { 1391 if(loops == 200000) { 1392 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Overlay Lockup\n"); 1393 break; 1394 } 1395 loops++; 1396 } 1397 1398 /* buffer swap */ 1399 if (pI810Priv->currentBuf == 0) 1400 pI810Priv->currentBuf = 1; 1401 else 1402 pI810Priv->currentBuf = 0; 1403 1404 I810ResetVideo(pScrn); 1405 1406 I810DisplayVideo(pScrn, surface->id, surface->width, surface->height, 1407 surface->pitches[0], x1, y1, x2, y2, &dstBox, 1408 src_w, src_h, drw_w, drw_h); 1409 1410 xf86XVFillKeyHelper(pScrn->pScreen, pI810Priv->colorKey, clipBoxes); 1411 1412 pPriv->isOn = TRUE; 1413 /* we've prempted the XvImage stream so set its free timer */ 1414 if(pI810Priv->videoStatus & CLIENT_VIDEO_ON) { 1415 REGION_EMPTY(pScrn->screen, & pI810Priv->clip); 1416 UpdateCurrentTime(); 1417 pI810Priv->videoStatus = FREE_TIMER; 1418 pI810Priv->freeTime = currentTime.milliseconds + FREE_DELAY; 1419 } 1420 1421 return Success; 1422} 1423 1424 1425static void 1426I810InitOffscreenImages(ScreenPtr screen) 1427{ 1428 XF86OffscreenImagePtr offscreenImages; 1429 1430 /* need to free this someplace */ 1431 if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec)))) { 1432 return; 1433 } 1434 1435 offscreenImages[0].image = &Images[0]; 1436 offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | 1437 VIDEO_CLIP_TO_VIEWPORT; 1438 offscreenImages[0].alloc_surface = I810AllocateSurface; 1439 offscreenImages[0].free_surface = I810FreeSurface; 1440 offscreenImages[0].display = I810DisplaySurface; 1441 offscreenImages[0].stop = I810StopSurface; 1442 offscreenImages[0].setAttribute = I810SetSurfaceAttribute; 1443 offscreenImages[0].getAttribute = I810GetSurfaceAttribute; 1444 offscreenImages[0].max_width = 1024; 1445 offscreenImages[0].max_height = 1024; 1446 offscreenImages[0].num_attributes = 1; 1447 offscreenImages[0].attributes = Attributes; 1448 1449 if (!xf86XVRegisterOffscreenImages(screen, offscreenImages, 1)) 1450 free(offscreenImages); 1451} 1452 1453