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