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 "xf86.h" 43#include "xf86_OSproc.h" 44#include "compiler.h" 45#include "xf86PciInfo.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 "xaa.h" 54#include "xaalocal.h" 55#include "dixstruct.h" 56#include "fourcc.h" 57 58#define OFF_DELAY 250 /* milliseconds */ 59#define FREE_DELAY 15000 60 61#define OFF_TIMER 0x01 62#define FREE_TIMER 0x02 63#define CLIENT_VIDEO_ON 0x04 64 65#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 66 67static void I810InitOffscreenImages(ScreenPtr); 68 69static XF86VideoAdaptorPtr I810SetupImageVideo(ScreenPtr); 70static void I810StopVideo(ScrnInfoPtr, pointer, Bool); 71static int I810SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 72static int I810GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); 73static void I810QueryBestSize(ScrnInfoPtr, Bool, 74 short, short, short, short, unsigned int *, unsigned int *, pointer); 75static int I810PutImage( ScrnInfoPtr, 76 short, short, short, short, short, short, short, short, 77 int, unsigned char*, short, short, Bool, RegionPtr, pointer, 78 DrawablePtr); 79static int I810QueryImageAttributes(ScrnInfoPtr, 80 int, unsigned short *, unsigned short *, int *, int *); 81 82static void I810BlockHandler(int, pointer, pointer, pointer); 83 84#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 85 86static Atom xvBrightness, xvContrast, xvColorKey; 87 88#define IMAGE_MAX_WIDTH 1440 89#define IMAGE_FAST_WIDTH 720 90#define IMAGE_MAX_HEIGHT 1080 91#define Y_BUF_SIZE (IMAGE_MAX_WIDTH * IMAGE_MAX_HEIGHT) 92 93#define OVERLAY_UPDATE(p) OUTREG(0x30000, p | 0x80000000); 94 95/* 96 * OV0CMD - Overlay Command Register 97 */ 98#define VERTICAL_CHROMINANCE_FILTER 0x70000000 99#define VC_SCALING_OFF 0x00000000 100#define VC_LINE_REPLICATION 0x10000000 101#define VC_UP_INTERPOLATION 0x20000000 102#define VC_PIXEL_DROPPING 0x50000000 103#define VC_DOWN_INTERPOLATION 0x60000000 104#define VERTICAL_LUMINANCE_FILTER 0x0E000000 105#define VL_SCALING_OFF 0x00000000 106#define VL_LINE_REPLICATION 0x02000000 107#define VL_UP_INTERPOLATION 0x04000000 108#define VL_PIXEL_DROPPING 0x0A000000 109#define VL_DOWN_INTERPOLATION 0x0C000000 110#define HORIZONTAL_CHROMINANCE_FILTER 0x01C00000 111#define HC_SCALING_OFF 0x00000000 112#define HC_LINE_REPLICATION 0x00400000 113#define HC_UP_INTERPOLATION 0x00800000 114#define HC_PIXEL_DROPPING 0x01400000 115#define HC_DOWN_INTERPOLATION 0x01800000 116#define HORIZONTAL_LUMINANCE_FILTER 0x00380000 117#define HL_SCALING_OFF 0x00000000 118#define HL_LINE_REPLICATION 0x00080000 119#define HL_UP_INTERPOLATION 0x00100000 120#define HL_PIXEL_DROPPING 0x00280000 121#define HL_DOWN_INTERPOLATION 0x00300000 122 123#define Y_ADJUST 0x00010000 124#define OV_BYTE_ORDER 0x0000C000 125#define UV_SWAP 0x00004000 126#define Y_SWAP 0x00008000 127#define Y_AND_UV_SWAP 0x0000C000 128#define SOURCE_FORMAT 0x00003C00 129#define RGB_555 0x00000800 130#define RGB_565 0x00000C00 131#define YUV_422 0x00002000 132#define YUV_411 0x00002400 133#define YUV_420 0x00003000 134#define YUV_410 0x00003800 135#define BUFFER_AND_FIELD 0x00000006 136#define BUFFER0_FIELD0 0x00000000 137#define BUFFER1_FIELD0 0x00000004 138#define OVERLAY_ENABLE 0x00000001 139 140#define UV_VERT_BUF1 0x02 141#define UV_VERT_BUF0 0x04 142 143/* 144 * DOV0STA - Display/Overlay 0 Status Register 145 */ 146#define DOV0STA 0x30008 147 148#define MINUV_SCALE 0x1 149 150#define RGB16ToColorKey(c) \ 151 (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3)) 152 153#define RGB15ToColorKey(c) \ 154 (((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3)) 155 156void I810InitVideo(ScreenPtr pScreen) 157{ 158 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 159 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 160 XF86VideoAdaptorPtr newAdaptor = NULL; 161 int num_adaptors; 162 163 if (pScrn->bitsPerPixel != 8) 164 { 165 newAdaptor = I810SetupImageVideo(pScreen); 166 I810InitOffscreenImages(pScreen); 167 } 168 169 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 170 171 if(newAdaptor) { 172 if(!num_adaptors) { 173 num_adaptors = 1; 174 adaptors = &newAdaptor; 175 } else { 176 newAdaptors = /* need to free this someplace */ 177 xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); 178 if(newAdaptors) { 179 memcpy(newAdaptors, adaptors, num_adaptors * 180 sizeof(XF86VideoAdaptorPtr)); 181 newAdaptors[num_adaptors] = newAdaptor; 182 adaptors = newAdaptors; 183 num_adaptors++; 184 } 185 } 186 } 187 188 if(num_adaptors) 189 xf86XVScreenInit(pScreen, adaptors, num_adaptors); 190 191 if(newAdaptors) 192 xfree(newAdaptors); 193} 194 195/* *INDENT-OFF* */ 196/* client libraries expect an encoding */ 197static XF86VideoEncodingRec DummyEncoding[1] = 198{ 199 { 200 0, 201 "XV_IMAGE", 202 IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, 203 {1, 1} 204 } 205}; 206 207#define NUM_FORMATS 3 208 209static XF86VideoFormatRec Formats[NUM_FORMATS] = 210{ 211 {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 212}; 213 214#define NUM_ATTRIBUTES 3 215 216static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = 217{ 218 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 219 {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, 220 {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"} 221}; 222 223#define NUM_IMAGES 6 224 225#define I810_RV15 0x35315652 226#define I810_RV16 0x36315652 227 228static XF86ImageRec Images[NUM_IMAGES] = 229{ 230 { 231 I810_RV15, 232 XvRGB, 233 LSBFirst, 234 {'R','V','1','5', 235 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 236 16, 237 XvPacked, 238 1, 239 15, 0x7C00, 0x03E0, 0x001F, 240 0, 0, 0, 241 0, 0, 0, 242 0, 0, 0, 243 {'R','V','B',0, 244 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}, 245 XvTopToBottom 246 }, 247 { 248 I810_RV16, 249 XvRGB, 250 LSBFirst, 251 {'R','V','1','6', 252 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 253 16, 254 XvPacked, 255 1, 256 16, 0xF800, 0x07E0, 0x001F, 257 0, 0, 0, 258 0, 0, 0, 259 0, 0, 0, 260 {'R','V','B',0, 261 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}, 262 XvTopToBottom 263 }, 264 XVIMAGE_YUY2, 265 XVIMAGE_YV12, 266 XVIMAGE_I420, 267 XVIMAGE_UYVY 268}; 269/* *INDENT-ON* */ 270 271typedef struct { 272 uint32_t OBUF_0Y; 273 uint32_t OBUF_1Y; 274 uint32_t OBUF_0U; 275 uint32_t OBUF_0V; 276 uint32_t OBUF_1U; 277 uint32_t OBUF_1V; 278 uint32_t OV0STRIDE; 279 uint32_t YRGB_VPH; 280 uint32_t UV_VPH; 281 uint32_t HORZ_PH; 282 uint32_t INIT_PH; 283 uint32_t DWINPOS; 284 uint32_t DWINSZ; 285 uint32_t SWID; 286 uint32_t SWIDQW; 287 uint32_t SHEIGHT; 288 uint32_t YRGBSCALE; 289 uint32_t UVSCALE; 290 uint32_t OV0CLRC0; 291 uint32_t OV0CLRC1; 292 uint32_t DCLRKV; 293 uint32_t DCLRKM; 294 uint32_t SCLRKVH; 295 uint32_t SCLRKVL; 296 uint32_t SCLRKM; 297 uint32_t OV0CONF; 298 uint32_t OV0CMD; 299} I810OverlayRegRec, *I810OverlayRegPtr; 300 301typedef struct { 302 uint32_t YBuf0offset; 303 uint32_t UBuf0offset; 304 uint32_t VBuf0offset; 305 306 uint32_t YBuf1offset; 307 uint32_t UBuf1offset; 308 uint32_t VBuf1offset; 309 310 unsigned char currentBuf; 311 312 int brightness; 313 int contrast; 314 315 RegionRec clip; 316 uint32_t colorKey; 317 318 uint32_t videoStatus; 319 Time offTime; 320 Time freeTime; 321 FBLinearPtr linear; 322} I810PortPrivRec, *I810PortPrivPtr; 323 324#define GET_PORT_PRIVATE(pScrn) \ 325 (I810PortPrivPtr)((I810PTR(pScrn))->adaptor->pPortPrivates[0].ptr) 326 327static void I810ResetVideo(ScrnInfoPtr pScrn) 328{ 329 I810Ptr pI810 = I810PTR(pScrn); 330 I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr; 331 I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 332 333 /* 334 * Default to maximum image size in YV12 335 */ 336 337 overlay->YRGB_VPH = 0; 338 overlay->UV_VPH = 0; 339 overlay->HORZ_PH = 0; 340 overlay->INIT_PH = 0; 341 overlay->DWINPOS = 0; 342 overlay->DWINSZ = (IMAGE_MAX_HEIGHT << 16) | IMAGE_MAX_WIDTH; 343 overlay->SWID = IMAGE_MAX_WIDTH | (IMAGE_MAX_WIDTH << 15); 344 overlay->SWIDQW = (IMAGE_MAX_WIDTH >> 3) | (IMAGE_MAX_WIDTH << 12); 345 overlay->SHEIGHT = IMAGE_MAX_HEIGHT | (IMAGE_MAX_HEIGHT << 15); 346 overlay->YRGBSCALE = 0x80004000; /* scale factor 1 */ 347 overlay->UVSCALE = 0x80004000; /* scale factor 1 */ 348 overlay->OV0CLRC0 = 0x4000; /* brightness: 0 contrast: 1.0 */ 349 overlay->OV0CLRC1 = 0x80; /* saturation: bypass */ 350 351 /* 352 * Enable destination color keying 353 */ 354 switch(pScrn->depth) { 355 case 16: overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey); 356 overlay->DCLRKM = 0x80070307; 357 break; 358 case 15: overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey); 359 overlay->DCLRKM = 0x80070707; 360 break; 361 default: overlay->DCLRKV = pPriv->colorKey; 362 overlay->DCLRKM = 0x80000000; 363 break; 364 } 365 366 overlay->SCLRKVH = 0; 367 overlay->SCLRKVL = 0; 368 overlay->SCLRKM = 0; /* source color key disable */ 369 overlay->OV0CONF = 0; /* two 720 pixel line buffers */ 370 371 overlay->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | Y_ADJUST | 372 YUV_420; 373 374 OVERLAY_UPDATE(pI810->OverlayPhysical); 375} 376 377 378static XF86VideoAdaptorPtr 379I810SetupImageVideo(ScreenPtr pScreen) 380{ 381 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 382 I810Ptr pI810 = I810PTR(pScrn); 383 XF86VideoAdaptorPtr adapt; 384 I810PortPrivPtr pPriv; 385 386 if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + 387 sizeof(I810PortPrivRec) + 388 sizeof(DevUnion)))) 389 return NULL; 390 391 adapt->type = XvWindowMask | XvInputMask | XvImageMask; 392 adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 393 adapt->name = "I810 Video Overlay"; 394 adapt->nEncodings = 1; 395 adapt->pEncodings = DummyEncoding; 396 adapt->nFormats = NUM_FORMATS; 397 adapt->pFormats = Formats; 398 adapt->nPorts = 1; 399 adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 400 401 pPriv = (I810PortPrivPtr)(&adapt->pPortPrivates[1]); 402 403 adapt->pPortPrivates[0].ptr = (pointer)(pPriv); 404 adapt->pAttributes = Attributes; 405 adapt->nImages = NUM_IMAGES; 406 adapt->nAttributes = NUM_ATTRIBUTES; 407 adapt->pImages = Images; 408 adapt->PutVideo = NULL; 409 adapt->PutStill = NULL; 410 adapt->GetVideo = NULL; 411 adapt->GetStill = NULL; 412 adapt->StopVideo = I810StopVideo; 413 adapt->SetPortAttribute = I810SetPortAttribute; 414 adapt->GetPortAttribute = I810GetPortAttribute; 415 adapt->QueryBestSize = I810QueryBestSize; 416 adapt->PutImage = I810PutImage; 417 adapt->QueryImageAttributes = I810QueryImageAttributes; 418 419 pPriv->colorKey = pI810->colorKey & ((1 << pScrn->depth) - 1); 420 pPriv->videoStatus = 0; 421 pPriv->brightness = 0; 422 pPriv->contrast = 64; 423 pPriv->linear = NULL; 424 pPriv->currentBuf = 0; 425 426 /* gotta uninit this someplace */ 427 REGION_NULL(pScreen, &pPriv->clip); 428 429 pI810->adaptor = adapt; 430 431 pI810->BlockHandler = pScreen->BlockHandler; 432 pScreen->BlockHandler = I810BlockHandler; 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->pScreen, &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->pScreen, &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 = (width + 7) & ~7; 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 = ((width + 3) & ~3) << 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 pScreen; 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 pScreen = screenInfo.screens[pScrn->scrnIndex]; 946 947 new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, 948 NULL, NULL, NULL); 949 950 if(!new_linear) { 951 int max_size; 952 953 xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4, 954 PRIORITY_EXTREME); 955 956 if(max_size < size) return NULL; 957 958 xf86PurgeUnlockedOffscreenAreas(pScreen); 959 new_linear = xf86AllocateOffscreenLinear(pScreen, 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->pScreen, 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 = (width + 3) & ~3; 1017 dstPitch = ((width >> 1) + 7) & ~7; /* 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 = (srcPitch + 7) & ~7; 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 = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; 1066 1067 switch(id) { 1068 case FOURCC_YV12: 1069 case FOURCC_I420: 1070 top &= ~1; 1071 nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - 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->pScreen, &pPriv->clip, clipBoxes)) { 1086 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 1087 /* draw these */ 1088 xf86XVFillKeyHelper(pScrn->pScreen, 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 1148static void 1149I810BlockHandler ( 1150 int i, 1151 pointer blockData, 1152 pointer pTimeout, 1153 pointer pReadmask 1154){ 1155 ScreenPtr pScreen = screenInfo.screens[i]; 1156 ScrnInfoPtr pScrn = xf86Screens[i]; 1157 I810Ptr pI810 = I810PTR(pScrn); 1158 I810PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 1159 I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 1160 1161 pScreen->BlockHandler = pI810->BlockHandler; 1162 1163 (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); 1164 1165 pScreen->BlockHandler = I810BlockHandler; 1166 1167 if(pPriv->videoStatus & TIMER_MASK) { 1168 UpdateCurrentTime(); 1169 if(pPriv->videoStatus & OFF_TIMER) { 1170 if(pPriv->offTime < currentTime.milliseconds) { 1171 /* Turn off the overlay */ 1172 overlay->OV0CMD &= 0xFFFFFFFE; 1173 OVERLAY_UPDATE(pI810->OverlayPhysical); 1174 1175 pPriv->videoStatus = FREE_TIMER; 1176 pPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 1177 } 1178 } else { /* FREE_TIMER */ 1179 if(pPriv->freeTime < currentTime.milliseconds) { 1180 if(pPriv->linear) { 1181 xf86FreeOffscreenLinear(pPriv->linear); 1182 pPriv->linear = NULL; 1183 } 1184 pPriv->videoStatus = 0; 1185 } 1186 } 1187 } 1188} 1189 1190 1191/*************************************************************************** 1192 * Offscreen Images 1193 ***************************************************************************/ 1194 1195typedef struct { 1196 FBLinearPtr linear; 1197 Bool isOn; 1198} OffscreenPrivRec, * OffscreenPrivPtr; 1199 1200static int 1201I810AllocateSurface( 1202 ScrnInfoPtr pScrn, 1203 int id, 1204 unsigned short w, 1205 unsigned short h, 1206 XF86SurfacePtr surface 1207){ 1208 FBLinearPtr linear; 1209 int pitch, fbpitch, size, bpp; 1210 OffscreenPrivPtr pPriv; 1211 I810Ptr pI810 = I810PTR(pScrn); 1212 1213 if((w > 1024) || (h > 1024)) 1214 return BadAlloc; 1215 1216 w = (w + 1) & ~1; 1217 pitch = ((w << 1) + 15) & ~15; 1218 bpp = pScrn->bitsPerPixel >> 3; 1219 fbpitch = bpp * pScrn->displayWidth; 1220 size = ((pitch * h) + bpp - 1) / bpp; 1221 1222 if(!(linear = I810AllocateMemory(pScrn, NULL, size))) 1223 return BadAlloc; 1224 1225 surface->width = w; 1226 surface->height = h; 1227 1228 if(!(surface->pitches = xalloc(sizeof(int)))) { 1229 xf86FreeOffscreenLinear(linear); 1230 return BadAlloc; 1231 } 1232 if(!(surface->offsets = xalloc(sizeof(int)))) { 1233 xfree(surface->pitches); 1234 xf86FreeOffscreenLinear(linear); 1235 return BadAlloc; 1236 } 1237 if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) { 1238 xfree(surface->pitches); 1239 xfree(surface->offsets); 1240 xf86FreeOffscreenLinear(linear); 1241 return BadAlloc; 1242 } 1243 1244 pPriv->linear = linear; 1245 pPriv->isOn = FALSE; 1246 1247 surface->pScrn = pScrn; 1248 surface->id = id; 1249 surface->pitches[0] = pitch; 1250 surface->offsets[0] = linear->offset * bpp; 1251 surface->devPrivate.ptr = (pointer)pPriv; 1252 1253 memset(pI810->FbBase + surface->offsets[0],0,size); 1254 1255 return Success; 1256} 1257 1258static int 1259I810StopSurface( 1260 XF86SurfacePtr surface 1261){ 1262 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 1263 1264 if(pPriv->isOn) { 1265 I810Ptr pI810 = I810PTR(surface->pScrn); 1266 1267 I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 1268 1269 overlay->OV0CMD &= 0xFFFFFFFE; 1270 OVERLAY_UPDATE(pI810->OverlayPhysical); 1271 1272 pPriv->isOn = FALSE; 1273 } 1274 1275 return Success; 1276} 1277 1278 1279static int 1280I810FreeSurface( 1281 XF86SurfacePtr surface 1282){ 1283 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 1284 1285 if(pPriv->isOn) { 1286 I810StopSurface(surface); 1287 } 1288 xf86FreeOffscreenLinear(pPriv->linear); 1289 xfree(surface->pitches); 1290 xfree(surface->offsets); 1291 xfree(surface->devPrivate.ptr); 1292 1293 return Success; 1294} 1295 1296static int 1297I810GetSurfaceAttribute( 1298 ScrnInfoPtr pScrn, 1299 Atom attribute, 1300 INT32 *value 1301){ 1302 return I810GetPortAttribute(pScrn, attribute, value, NULL); 1303} 1304 1305static int 1306I810SetSurfaceAttribute( 1307 ScrnInfoPtr pScrn, 1308 Atom attribute, 1309 INT32 value 1310){ 1311 return I810SetPortAttribute(pScrn, attribute, value, NULL); 1312} 1313 1314 1315static int 1316I810DisplaySurface( 1317 XF86SurfacePtr surface, 1318 short src_x, short src_y, 1319 short drw_x, short drw_y, 1320 short src_w, short src_h, 1321 short drw_w, short drw_h, 1322 RegionPtr clipBoxes 1323){ 1324 OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 1325 ScrnInfoPtr pScrn = surface->pScrn; 1326 I810Ptr pI810 = I810PTR(pScrn); 1327 I810PortPrivPtr pI810Priv = GET_PORT_PRIVATE(pScrn); 1328 1329 INT32 x1, y1, x2, y2; 1330 INT32 loops = 0; 1331 BoxRec dstBox; 1332 1333 x1 = src_x; 1334 x2 = src_x + src_w; 1335 y1 = src_y; 1336 y2 = src_y + src_h; 1337 1338 dstBox.x1 = drw_x; 1339 dstBox.x2 = drw_x + drw_w; 1340 dstBox.y1 = drw_y; 1341 dstBox.y2 = drw_y + drw_h; 1342 1343 I810ClipVideo(&dstBox, &x1, &x2, &y1, &y2, 1344 REGION_EXTENTS(screenInfo.screens[0], clipBoxes), 1345 surface->width, surface->height); 1346 1347 /* 1348 * Fix for 4 pixel granularity of AdjustFrame 1349 * unless boarder is clipped by frame 1350 */ 1351 dstBox.x1 -= (pScrn->frameX0 & 1352 ((dstBox.x1 == pScrn->frameX0) ? ~0x0UL : ~0x3UL)); 1353 dstBox.x2 -= (pScrn->frameX0 & ~0x3); 1354 dstBox.y1 -= pScrn->frameY0; 1355 dstBox.y2 -= pScrn->frameY0; 1356 1357 /* fixup pointers */ 1358 pI810Priv->YBuf0offset = surface->offsets[0]; 1359 pI810Priv->YBuf1offset = pI810Priv->YBuf0offset; 1360 1361 /* wait for the last rendered buffer to be flipped in */ 1362 while (((INREG(DOV0STA)&0x00100000)>>20) != pI810Priv->currentBuf) { 1363 if(loops == 200000) { 1364 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Overlay Lockup\n"); 1365 break; 1366 } 1367 loops++; 1368 } 1369 1370 /* buffer swap */ 1371 if (pI810Priv->currentBuf == 0) 1372 pI810Priv->currentBuf = 1; 1373 else 1374 pI810Priv->currentBuf = 0; 1375 1376 I810ResetVideo(pScrn); 1377 1378 I810DisplayVideo(pScrn, surface->id, surface->width, surface->height, 1379 surface->pitches[0], x1, y1, x2, y2, &dstBox, 1380 src_w, src_h, drw_w, drw_h); 1381 1382 xf86XVFillKeyHelper(pScrn->pScreen, pI810Priv->colorKey, clipBoxes); 1383 1384 pPriv->isOn = TRUE; 1385 /* we've prempted the XvImage stream so set its free timer */ 1386 if(pI810Priv->videoStatus & CLIENT_VIDEO_ON) { 1387 REGION_EMPTY(pScrn->pScreen, & pI810Priv->clip); 1388 UpdateCurrentTime(); 1389 pI810Priv->videoStatus = FREE_TIMER; 1390 pI810Priv->freeTime = currentTime.milliseconds + FREE_DELAY; 1391 pScrn->pScreen->BlockHandler = I810BlockHandler; 1392 } 1393 1394 return Success; 1395} 1396 1397 1398static void 1399I810InitOffscreenImages(ScreenPtr pScreen) 1400{ 1401 XF86OffscreenImagePtr offscreenImages; 1402 1403 /* need to free this someplace */ 1404 if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) { 1405 return; 1406 } 1407 1408 offscreenImages[0].image = &Images[0]; 1409 offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | 1410 VIDEO_CLIP_TO_VIEWPORT; 1411 offscreenImages[0].alloc_surface = I810AllocateSurface; 1412 offscreenImages[0].free_surface = I810FreeSurface; 1413 offscreenImages[0].display = I810DisplaySurface; 1414 offscreenImages[0].stop = I810StopSurface; 1415 offscreenImages[0].setAttribute = I810SetSurfaceAttribute; 1416 offscreenImages[0].getAttribute = I810GetSurfaceAttribute; 1417 offscreenImages[0].max_width = 1024; 1418 offscreenImages[0].max_height = 1024; 1419 offscreenImages[0].num_attributes = 1; 1420 offscreenImages[0].attributes = Attributes; 1421 1422 xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); 1423} 1424 1425