1428d7b3dSmrg/*************************************************************************** 2428d7b3dSmrg 3428d7b3dSmrgCopyright 2000 Intel Corporation. All Rights Reserved. 4428d7b3dSmrg 5428d7b3dSmrgPermission is hereby granted, free of charge, to any person obtaining a 6428d7b3dSmrgcopy of this software and associated documentation files (the 7428d7b3dSmrg"Software"), to deal in the Software without restriction, including 8428d7b3dSmrgwithout limitation the rights to use, copy, modify, merge, publish, 9428d7b3dSmrgdistribute, sub license, and/or sell copies of the Software, and to 10428d7b3dSmrgpermit persons to whom the Software is furnished to do so, subject to 11428d7b3dSmrgthe following conditions: 12428d7b3dSmrg 13428d7b3dSmrgThe above copyright notice and this permission notice (including the 14428d7b3dSmrgnext paragraph) shall be included in all copies or substantial portions 15428d7b3dSmrgof the Software. 16428d7b3dSmrg 17428d7b3dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18428d7b3dSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19428d7b3dSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20428d7b3dSmrgIN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 21428d7b3dSmrgDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22428d7b3dSmrgOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 23428d7b3dSmrgTHE USE OR OTHER DEALINGS IN THE SOFTWARE. 24428d7b3dSmrg 25428d7b3dSmrg**************************************************************************/ 26428d7b3dSmrg 27428d7b3dSmrg/* 28428d7b3dSmrg * i810_video.c: i810 Xv driver. Based on the mga Xv driver by Mark Vojkovich. 29428d7b3dSmrg * 30428d7b3dSmrg * Authors: 31428d7b3dSmrg * Jonathan Bian <jonathan.bian@intel.com> 32428d7b3dSmrg * Offscreen Images: 33428d7b3dSmrg * Matt Sottek <matthew.j.sottek@intel.com> 34428d7b3dSmrg */ 35428d7b3dSmrg 36428d7b3dSmrg#ifdef HAVE_CONFIG_H 37428d7b3dSmrg#include "config.h" 38428d7b3dSmrg#endif 39428d7b3dSmrg 40428d7b3dSmrg#include <string.h> 41428d7b3dSmrg 42428d7b3dSmrg#include "xorg-server.h" 43428d7b3dSmrg#include "xf86.h" 44428d7b3dSmrg#include "xf86_OSproc.h" 45428d7b3dSmrg#include "compiler.h" 46428d7b3dSmrg#include "xf86Pci.h" 47428d7b3dSmrg#include "xf86fbman.h" 48428d7b3dSmrg#include "regionstr.h" 49428d7b3dSmrg 50428d7b3dSmrg#include "i810.h" 51428d7b3dSmrg#include "xf86xv.h" 52428d7b3dSmrg#include <X11/extensions/Xv.h> 53428d7b3dSmrg#include "dixstruct.h" 54428d7b3dSmrg#include "fourcc.h" 55428d7b3dSmrg 56428d7b3dSmrg#define OFF_DELAY 250 /* milliseconds */ 57428d7b3dSmrg#define FREE_DELAY 15000 58428d7b3dSmrg 59428d7b3dSmrg#define OFF_TIMER 0x01 60428d7b3dSmrg#define FREE_TIMER 0x02 61428d7b3dSmrg#define CLIENT_VIDEO_ON 0x04 62428d7b3dSmrg 63428d7b3dSmrg#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 64428d7b3dSmrg 65428d7b3dSmrgstatic void I810InitOffscreenImages(ScreenPtr); 66428d7b3dSmrg 67428d7b3dSmrgstatic XF86VideoAdaptorPtr I810SetupImageVideo(ScreenPtr); 68428d7b3dSmrgstatic void I810StopVideo(ScrnInfoPtr, pointer, Bool); 69428d7b3dSmrgstatic int I810SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 70428d7b3dSmrgstatic int I810GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); 71428d7b3dSmrgstatic void I810QueryBestSize(ScrnInfoPtr, Bool, 72428d7b3dSmrg short, short, short, short, unsigned int *, unsigned int *, pointer); 73428d7b3dSmrgstatic int I810PutImage( ScrnInfoPtr, 74428d7b3dSmrg short, short, short, short, short, short, short, short, 75428d7b3dSmrg int, unsigned char*, short, short, Bool, RegionPtr, pointer, 76428d7b3dSmrg DrawablePtr); 77428d7b3dSmrgstatic int I810QueryImageAttributes(ScrnInfoPtr, 78428d7b3dSmrg int, unsigned short *, unsigned short *, int *, int *); 79428d7b3dSmrg 80428d7b3dSmrgstatic void I810BlockHandler(BLOCKHANDLER_ARGS_DECL); 81428d7b3dSmrg 82428d7b3dSmrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 83428d7b3dSmrg 84428d7b3dSmrgstatic Atom xvBrightness, xvContrast, xvColorKey; 85428d7b3dSmrg 86428d7b3dSmrg#define IMAGE_MAX_WIDTH 1440 87428d7b3dSmrg#define IMAGE_FAST_WIDTH 720 88428d7b3dSmrg#define IMAGE_MAX_HEIGHT 1080 89428d7b3dSmrg#define Y_BUF_SIZE (IMAGE_MAX_WIDTH * IMAGE_MAX_HEIGHT) 90428d7b3dSmrg 91428d7b3dSmrg#define OVERLAY_UPDATE(p) OUTREG(0x30000, p | 0x80000000); 92428d7b3dSmrg 93428d7b3dSmrg/* 94428d7b3dSmrg * OV0CMD - Overlay Command Register 95428d7b3dSmrg */ 96428d7b3dSmrg#define VERTICAL_CHROMINANCE_FILTER 0x70000000 97428d7b3dSmrg#define VC_SCALING_OFF 0x00000000 98428d7b3dSmrg#define VC_LINE_REPLICATION 0x10000000 99428d7b3dSmrg#define VC_UP_INTERPOLATION 0x20000000 100428d7b3dSmrg#define VC_PIXEL_DROPPING 0x50000000 101428d7b3dSmrg#define VC_DOWN_INTERPOLATION 0x60000000 102428d7b3dSmrg#define VERTICAL_LUMINANCE_FILTER 0x0E000000 103428d7b3dSmrg#define VL_SCALING_OFF 0x00000000 104428d7b3dSmrg#define VL_LINE_REPLICATION 0x02000000 105428d7b3dSmrg#define VL_UP_INTERPOLATION 0x04000000 106428d7b3dSmrg#define VL_PIXEL_DROPPING 0x0A000000 107428d7b3dSmrg#define VL_DOWN_INTERPOLATION 0x0C000000 108428d7b3dSmrg#define HORIZONTAL_CHROMINANCE_FILTER 0x01C00000 109428d7b3dSmrg#define HC_SCALING_OFF 0x00000000 110428d7b3dSmrg#define HC_LINE_REPLICATION 0x00400000 111428d7b3dSmrg#define HC_UP_INTERPOLATION 0x00800000 112428d7b3dSmrg#define HC_PIXEL_DROPPING 0x01400000 113428d7b3dSmrg#define HC_DOWN_INTERPOLATION 0x01800000 114428d7b3dSmrg#define HORIZONTAL_LUMINANCE_FILTER 0x00380000 115428d7b3dSmrg#define HL_SCALING_OFF 0x00000000 116428d7b3dSmrg#define HL_LINE_REPLICATION 0x00080000 117428d7b3dSmrg#define HL_UP_INTERPOLATION 0x00100000 118428d7b3dSmrg#define HL_PIXEL_DROPPING 0x00280000 119428d7b3dSmrg#define HL_DOWN_INTERPOLATION 0x00300000 120428d7b3dSmrg 121428d7b3dSmrg#define Y_ADJUST 0x00010000 122428d7b3dSmrg#define OV_BYTE_ORDER 0x0000C000 123428d7b3dSmrg#define UV_SWAP 0x00004000 124428d7b3dSmrg#define Y_SWAP 0x00008000 125428d7b3dSmrg#define Y_AND_UV_SWAP 0x0000C000 126428d7b3dSmrg#define SOURCE_FORMAT 0x00003C00 127428d7b3dSmrg#define RGB_555 0x00000800 128428d7b3dSmrg#define RGB_565 0x00000C00 129428d7b3dSmrg#define YUV_422 0x00002000 130428d7b3dSmrg#define YUV_411 0x00002400 131428d7b3dSmrg#define YUV_420 0x00003000 132428d7b3dSmrg#define YUV_410 0x00003800 133428d7b3dSmrg#define BUFFER_AND_FIELD 0x00000006 134428d7b3dSmrg#define BUFFER0_FIELD0 0x00000000 135428d7b3dSmrg#define BUFFER1_FIELD0 0x00000004 136428d7b3dSmrg#define OVERLAY_ENABLE 0x00000001 137428d7b3dSmrg 138428d7b3dSmrg#define UV_VERT_BUF1 0x02 139428d7b3dSmrg#define UV_VERT_BUF0 0x04 140428d7b3dSmrg 141428d7b3dSmrg/* 142428d7b3dSmrg * DOV0STA - Display/Overlay 0 Status Register 143428d7b3dSmrg */ 144428d7b3dSmrg#define DOV0STA 0x30008 145428d7b3dSmrg 146428d7b3dSmrg#define MINUV_SCALE 0x1 147428d7b3dSmrg 148428d7b3dSmrg#define RGB16ToColorKey(c) \ 149428d7b3dSmrg (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3)) 150428d7b3dSmrg 151428d7b3dSmrg#define RGB15ToColorKey(c) \ 152428d7b3dSmrg (((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3)) 153428d7b3dSmrg 154428d7b3dSmrgvoid I810InitVideo(ScreenPtr screen) 155428d7b3dSmrg{ 156428d7b3dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 157428d7b3dSmrg XF86VideoAdaptorPtr *adaptors = NULL; 158428d7b3dSmrg int num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 159428d7b3dSmrg 160428d7b3dSmrg if (pScrn->bitsPerPixel != 8) { 161428d7b3dSmrg XF86VideoAdaptorPtr newAdaptor; 162428d7b3dSmrg 163428d7b3dSmrg newAdaptor = I810SetupImageVideo(screen); 164428d7b3dSmrg I810InitOffscreenImages(screen); 165428d7b3dSmrg 166428d7b3dSmrg if (newAdaptor) { 167428d7b3dSmrg XF86VideoAdaptorPtr *newAdaptors; 168428d7b3dSmrg 169428d7b3dSmrg newAdaptors = 170428d7b3dSmrg realloc(adaptors, 171428d7b3dSmrg (num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr)); 172428d7b3dSmrg if (newAdaptors != NULL) { 173428d7b3dSmrg newAdaptors[num_adaptors++] = newAdaptor; 174428d7b3dSmrg adaptors = newAdaptors; 175428d7b3dSmrg } 176428d7b3dSmrg } 177428d7b3dSmrg } 178428d7b3dSmrg 179428d7b3dSmrg if (num_adaptors) 180428d7b3dSmrg xf86XVScreenInit(screen, adaptors, num_adaptors); 181428d7b3dSmrg 182428d7b3dSmrg free(adaptors); 183428d7b3dSmrg} 184428d7b3dSmrg 185428d7b3dSmrg/* *INDENT-OFF* */ 186428d7b3dSmrg/* client libraries expect an encoding */ 187428d7b3dSmrgstatic XF86VideoEncodingRec DummyEncoding[1] = 188428d7b3dSmrg{ 189428d7b3dSmrg { 190428d7b3dSmrg 0, 191428d7b3dSmrg "XV_IMAGE", 192428d7b3dSmrg IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, 193428d7b3dSmrg {1, 1} 194428d7b3dSmrg } 195428d7b3dSmrg}; 196428d7b3dSmrg 197428d7b3dSmrg#define NUM_FORMATS 3 198428d7b3dSmrg 199428d7b3dSmrgstatic XF86VideoFormatRec Formats[NUM_FORMATS] = 200428d7b3dSmrg{ 201428d7b3dSmrg {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 202428d7b3dSmrg}; 203428d7b3dSmrg 204428d7b3dSmrg#define NUM_ATTRIBUTES 3 205428d7b3dSmrg 206428d7b3dSmrgstatic XF86AttributeRec Attributes[NUM_ATTRIBUTES] = 207428d7b3dSmrg{ 208428d7b3dSmrg {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 209428d7b3dSmrg {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, 210428d7b3dSmrg {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"} 211428d7b3dSmrg}; 212428d7b3dSmrg 213428d7b3dSmrg#define NUM_IMAGES 6 214428d7b3dSmrg 215428d7b3dSmrg#define I810_RV15 0x35315652 216428d7b3dSmrg#define I810_RV16 0x36315652 217428d7b3dSmrg 218428d7b3dSmrgstatic XF86ImageRec Images[NUM_IMAGES] = 219428d7b3dSmrg{ 220428d7b3dSmrg { 221428d7b3dSmrg I810_RV15, 222428d7b3dSmrg XvRGB, 223428d7b3dSmrg LSBFirst, 224428d7b3dSmrg {'R','V','1','5', 225428d7b3dSmrg 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 226428d7b3dSmrg 16, 227428d7b3dSmrg XvPacked, 228428d7b3dSmrg 1, 229428d7b3dSmrg 15, 0x7C00, 0x03E0, 0x001F, 230428d7b3dSmrg 0, 0, 0, 231428d7b3dSmrg 0, 0, 0, 232428d7b3dSmrg 0, 0, 0, 233428d7b3dSmrg {'R','V','B',0, 234428d7b3dSmrg 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}, 235428d7b3dSmrg XvTopToBottom 236428d7b3dSmrg }, 237428d7b3dSmrg { 238428d7b3dSmrg I810_RV16, 239428d7b3dSmrg XvRGB, 240428d7b3dSmrg LSBFirst, 241428d7b3dSmrg {'R','V','1','6', 242428d7b3dSmrg 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 243428d7b3dSmrg 16, 244428d7b3dSmrg XvPacked, 245428d7b3dSmrg 1, 246428d7b3dSmrg 16, 0xF800, 0x07E0, 0x001F, 247428d7b3dSmrg 0, 0, 0, 248428d7b3dSmrg 0, 0, 0, 249428d7b3dSmrg 0, 0, 0, 250428d7b3dSmrg {'R','V','B',0, 251428d7b3dSmrg 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}, 252428d7b3dSmrg XvTopToBottom 253428d7b3dSmrg }, 254428d7b3dSmrg XVIMAGE_YUY2, 255428d7b3dSmrg XVIMAGE_YV12, 256428d7b3dSmrg XVIMAGE_I420, 257428d7b3dSmrg XVIMAGE_UYVY 258428d7b3dSmrg}; 259428d7b3dSmrg/* *INDENT-ON* */ 260428d7b3dSmrg 261428d7b3dSmrgtypedef struct { 262428d7b3dSmrg uint32_t OBUF_0Y; 263428d7b3dSmrg uint32_t OBUF_1Y; 264428d7b3dSmrg uint32_t OBUF_0U; 265428d7b3dSmrg uint32_t OBUF_0V; 266428d7b3dSmrg uint32_t OBUF_1U; 267428d7b3dSmrg uint32_t OBUF_1V; 268428d7b3dSmrg uint32_t OV0STRIDE; 269428d7b3dSmrg uint32_t YRGB_VPH; 270428d7b3dSmrg uint32_t UV_VPH; 271428d7b3dSmrg uint32_t HORZ_PH; 272428d7b3dSmrg uint32_t INIT_PH; 273428d7b3dSmrg uint32_t DWINPOS; 274428d7b3dSmrg uint32_t DWINSZ; 275428d7b3dSmrg uint32_t SWID; 276428d7b3dSmrg uint32_t SWIDQW; 277428d7b3dSmrg uint32_t SHEIGHT; 278428d7b3dSmrg uint32_t YRGBSCALE; 279428d7b3dSmrg uint32_t UVSCALE; 280428d7b3dSmrg uint32_t OV0CLRC0; 281428d7b3dSmrg uint32_t OV0CLRC1; 282428d7b3dSmrg uint32_t DCLRKV; 283428d7b3dSmrg uint32_t DCLRKM; 284428d7b3dSmrg uint32_t SCLRKVH; 285428d7b3dSmrg uint32_t SCLRKVL; 286428d7b3dSmrg uint32_t SCLRKM; 287428d7b3dSmrg uint32_t OV0CONF; 288428d7b3dSmrg uint32_t OV0CMD; 289428d7b3dSmrg} I810OverlayRegRec, *I810OverlayRegPtr; 290428d7b3dSmrg 291428d7b3dSmrgtypedef struct { 292428d7b3dSmrg uint32_t YBuf0offset; 293428d7b3dSmrg uint32_t UBuf0offset; 294428d7b3dSmrg uint32_t VBuf0offset; 295428d7b3dSmrg 296428d7b3dSmrg uint32_t YBuf1offset; 297428d7b3dSmrg uint32_t UBuf1offset; 298428d7b3dSmrg uint32_t VBuf1offset; 299428d7b3dSmrg 300428d7b3dSmrg unsigned char currentBuf; 301428d7b3dSmrg 302428d7b3dSmrg int brightness; 303428d7b3dSmrg int contrast; 304428d7b3dSmrg 305428d7b3dSmrg RegionRec clip; 306428d7b3dSmrg uint32_t colorKey; 307428d7b3dSmrg 308428d7b3dSmrg uint32_t videoStatus; 309428d7b3dSmrg Time offTime; 310428d7b3dSmrg Time freeTime; 311428d7b3dSmrg FBLinearPtr linear; 312428d7b3dSmrg} I810PortPrivRec, *I810PortPrivPtr; 313428d7b3dSmrg 314428d7b3dSmrg#define GET_PORT_PRIVATE(pScrn) \ 315428d7b3dSmrg (I810PortPrivPtr)((I810PTR(pScrn))->adaptor->pPortPrivates[0].ptr) 316428d7b3dSmrg 317428d7b3dSmrgstatic void I810ResetVideo(ScrnInfoPtr pScrn) 318428d7b3dSmrg{ 319428d7b3dSmrg I810Ptr pI810 = I810PTR(pScrn); 320428d7b3dSmrg I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr; 321428d7b3dSmrg I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 322428d7b3dSmrg 323428d7b3dSmrg /* 324428d7b3dSmrg * Default to maximum image size in YV12 325428d7b3dSmrg */ 326428d7b3dSmrg 327428d7b3dSmrg overlay->YRGB_VPH = 0; 328428d7b3dSmrg overlay->UV_VPH = 0; 329428d7b3dSmrg overlay->HORZ_PH = 0; 330428d7b3dSmrg overlay->INIT_PH = 0; 331428d7b3dSmrg overlay->DWINPOS = 0; 332428d7b3dSmrg overlay->DWINSZ = (IMAGE_MAX_HEIGHT << 16) | IMAGE_MAX_WIDTH; 333428d7b3dSmrg overlay->SWID = IMAGE_MAX_WIDTH | (IMAGE_MAX_WIDTH << 15); 334428d7b3dSmrg overlay->SWIDQW = (IMAGE_MAX_WIDTH >> 3) | (IMAGE_MAX_WIDTH << 12); 335428d7b3dSmrg overlay->SHEIGHT = IMAGE_MAX_HEIGHT | (IMAGE_MAX_HEIGHT << 15); 336428d7b3dSmrg overlay->YRGBSCALE = 0x80004000; /* scale factor 1 */ 337428d7b3dSmrg overlay->UVSCALE = 0x80004000; /* scale factor 1 */ 338428d7b3dSmrg overlay->OV0CLRC0 = 0x4000; /* brightness: 0 contrast: 1.0 */ 339428d7b3dSmrg overlay->OV0CLRC1 = 0x80; /* saturation: bypass */ 340428d7b3dSmrg 341428d7b3dSmrg /* 342428d7b3dSmrg * Enable destination color keying 343428d7b3dSmrg */ 344428d7b3dSmrg switch(pScrn->depth) { 345428d7b3dSmrg case 16: overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey); 346428d7b3dSmrg overlay->DCLRKM = 0x80070307; 347428d7b3dSmrg break; 348428d7b3dSmrg case 15: overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey); 349428d7b3dSmrg overlay->DCLRKM = 0x80070707; 350428d7b3dSmrg break; 351428d7b3dSmrg default: overlay->DCLRKV = pPriv->colorKey; 352428d7b3dSmrg overlay->DCLRKM = 0x80000000; 353428d7b3dSmrg break; 354428d7b3dSmrg } 355428d7b3dSmrg 356428d7b3dSmrg overlay->SCLRKVH = 0; 357428d7b3dSmrg overlay->SCLRKVL = 0; 358428d7b3dSmrg overlay->SCLRKM = 0; /* source color key disable */ 359428d7b3dSmrg overlay->OV0CONF = 0; /* two 720 pixel line buffers */ 360428d7b3dSmrg 361428d7b3dSmrg overlay->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | Y_ADJUST | 362428d7b3dSmrg YUV_420; 363428d7b3dSmrg 364428d7b3dSmrg OVERLAY_UPDATE(pI810->OverlayPhysical); 365428d7b3dSmrg} 366428d7b3dSmrg 367428d7b3dSmrg 368428d7b3dSmrgstatic XF86VideoAdaptorPtr 369428d7b3dSmrgI810SetupImageVideo(ScreenPtr screen) 370428d7b3dSmrg{ 371428d7b3dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 372428d7b3dSmrg I810Ptr pI810 = I810PTR(pScrn); 373428d7b3dSmrg XF86VideoAdaptorPtr adapt; 374428d7b3dSmrg I810PortPrivPtr pPriv; 375428d7b3dSmrg 376428d7b3dSmrg if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 377428d7b3dSmrg sizeof(I810PortPrivRec) + 378428d7b3dSmrg sizeof(DevUnion)))) 379428d7b3dSmrg return NULL; 380428d7b3dSmrg 381428d7b3dSmrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 382428d7b3dSmrg adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 383428d7b3dSmrg adapt->name = "I810 Video Overlay"; 384428d7b3dSmrg adapt->nEncodings = 1; 385428d7b3dSmrg adapt->pEncodings = DummyEncoding; 386428d7b3dSmrg adapt->nFormats = NUM_FORMATS; 387428d7b3dSmrg adapt->pFormats = Formats; 388428d7b3dSmrg adapt->nPorts = 1; 389428d7b3dSmrg adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 390428d7b3dSmrg 391428d7b3dSmrg pPriv = (I810PortPrivPtr)(&adapt->pPortPrivates[1]); 392428d7b3dSmrg 393428d7b3dSmrg adapt->pPortPrivates[0].ptr = (pointer)(pPriv); 394428d7b3dSmrg adapt->pAttributes = Attributes; 395428d7b3dSmrg adapt->nImages = NUM_IMAGES; 396428d7b3dSmrg adapt->nAttributes = NUM_ATTRIBUTES; 397428d7b3dSmrg adapt->pImages = Images; 398428d7b3dSmrg adapt->PutVideo = NULL; 399428d7b3dSmrg adapt->PutStill = NULL; 400428d7b3dSmrg adapt->GetVideo = NULL; 401428d7b3dSmrg adapt->GetStill = NULL; 402428d7b3dSmrg adapt->StopVideo = I810StopVideo; 403428d7b3dSmrg adapt->SetPortAttribute = I810SetPortAttribute; 404428d7b3dSmrg adapt->GetPortAttribute = I810GetPortAttribute; 405428d7b3dSmrg adapt->QueryBestSize = I810QueryBestSize; 406428d7b3dSmrg adapt->PutImage = I810PutImage; 407428d7b3dSmrg adapt->QueryImageAttributes = I810QueryImageAttributes; 408428d7b3dSmrg 409428d7b3dSmrg pPriv->colorKey = pI810->colorKey & ((1 << pScrn->depth) - 1); 410428d7b3dSmrg pPriv->videoStatus = 0; 411428d7b3dSmrg pPriv->brightness = 0; 412428d7b3dSmrg pPriv->contrast = 64; 413428d7b3dSmrg pPriv->linear = NULL; 414428d7b3dSmrg pPriv->currentBuf = 0; 415428d7b3dSmrg 416428d7b3dSmrg /* gotta uninit this someplace */ 417428d7b3dSmrg REGION_NULL(screen, &pPriv->clip); 418428d7b3dSmrg 419428d7b3dSmrg pI810->adaptor = adapt; 420428d7b3dSmrg 421428d7b3dSmrg pI810->BlockHandler = screen->BlockHandler; 422428d7b3dSmrg screen->BlockHandler = I810BlockHandler; 423428d7b3dSmrg 424428d7b3dSmrg xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 425428d7b3dSmrg xvContrast = MAKE_ATOM("XV_CONTRAST"); 426428d7b3dSmrg xvColorKey = MAKE_ATOM("XV_COLORKEY"); 427428d7b3dSmrg 428428d7b3dSmrg I810ResetVideo(pScrn); 429428d7b3dSmrg 430428d7b3dSmrg return adapt; 431428d7b3dSmrg} 432428d7b3dSmrg 433428d7b3dSmrg 434428d7b3dSmrg/* I810ClipVideo - 435428d7b3dSmrg 436428d7b3dSmrg Takes the dst box in standard X BoxRec form (top and left 437428d7b3dSmrg edges inclusive, bottom and right exclusive). The new dst 438428d7b3dSmrg box is returned. The source boundaries are given (x1, y1 439428d7b3dSmrg inclusive, x2, y2 exclusive) and returned are the new source 440428d7b3dSmrg boundaries in 16.16 fixed point. 441428d7b3dSmrg*/ 442428d7b3dSmrg 443428d7b3dSmrgstatic void 444428d7b3dSmrgI810ClipVideo( 445428d7b3dSmrg BoxPtr dst, 446428d7b3dSmrg INT32 *x1, 447428d7b3dSmrg INT32 *x2, 448428d7b3dSmrg INT32 *y1, 449428d7b3dSmrg INT32 *y2, 450428d7b3dSmrg BoxPtr extents, /* extents of the clip region */ 451428d7b3dSmrg INT32 width, 452428d7b3dSmrg INT32 height 453428d7b3dSmrg){ 454428d7b3dSmrg INT32 vscale, hscale, delta; 455428d7b3dSmrg int diff; 456428d7b3dSmrg 457428d7b3dSmrg hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1); 458428d7b3dSmrg vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1); 459428d7b3dSmrg 460428d7b3dSmrg *x1 <<= 16; *x2 <<= 16; 461428d7b3dSmrg *y1 <<= 16; *y2 <<= 16; 462428d7b3dSmrg 463428d7b3dSmrg diff = extents->x1 - dst->x1; 464428d7b3dSmrg if(diff > 0) { 465428d7b3dSmrg dst->x1 = extents->x1; 466428d7b3dSmrg *x1 += diff * hscale; 467428d7b3dSmrg } 468428d7b3dSmrg diff = dst->x2 - extents->x2; 469428d7b3dSmrg if(diff > 0) { 470428d7b3dSmrg dst->x2 = extents->x2; 471428d7b3dSmrg *x2 -= diff * hscale; 472428d7b3dSmrg } 473428d7b3dSmrg diff = extents->y1 - dst->y1; 474428d7b3dSmrg if(diff > 0) { 475428d7b3dSmrg dst->y1 = extents->y1; 476428d7b3dSmrg *y1 += diff * vscale; 477428d7b3dSmrg } 478428d7b3dSmrg diff = dst->y2 - extents->y2; 479428d7b3dSmrg if(diff > 0) { 480428d7b3dSmrg dst->y2 = extents->y2; 481428d7b3dSmrg *y2 -= diff * vscale; 482428d7b3dSmrg } 483428d7b3dSmrg 484428d7b3dSmrg if(*x1 < 0) { 485428d7b3dSmrg diff = (- *x1 + hscale - 1)/ hscale; 486428d7b3dSmrg dst->x1 += diff; 487428d7b3dSmrg *x1 += diff * hscale; 488428d7b3dSmrg } 489428d7b3dSmrg delta = *x2 - (width << 16); 490428d7b3dSmrg if(delta > 0) { 491428d7b3dSmrg diff = (delta + hscale - 1)/ hscale; 492428d7b3dSmrg dst->x2 -= diff; 493428d7b3dSmrg *x2 -= diff * hscale; 494428d7b3dSmrg } 495428d7b3dSmrg if(*y1 < 0) { 496428d7b3dSmrg diff = (- *y1 + vscale - 1)/ vscale; 497428d7b3dSmrg dst->y1 += diff; 498428d7b3dSmrg *y1 += diff * vscale; 499428d7b3dSmrg } 500428d7b3dSmrg delta = *y2 - (height << 16); 501428d7b3dSmrg if(delta > 0) { 502428d7b3dSmrg diff = (delta + vscale - 1)/ vscale; 503428d7b3dSmrg dst->y2 -= diff; 504428d7b3dSmrg *y2 -= diff * vscale; 505428d7b3dSmrg } 506428d7b3dSmrg} 507428d7b3dSmrg 508428d7b3dSmrgstatic void 509428d7b3dSmrgI810StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) 510428d7b3dSmrg{ 511428d7b3dSmrg I810PortPrivPtr pPriv = (I810PortPrivPtr)data; 512428d7b3dSmrg I810Ptr pI810 = I810PTR(pScrn); 513428d7b3dSmrg 514428d7b3dSmrg I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 515428d7b3dSmrg 516428d7b3dSmrg REGION_EMPTY(pScrn->screen, &pPriv->clip); 517428d7b3dSmrg 518428d7b3dSmrg if(shutdown) { 519428d7b3dSmrg if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 520428d7b3dSmrg overlay->OV0CMD &= 0xFFFFFFFE; 521428d7b3dSmrg OVERLAY_UPDATE(pI810->OverlayPhysical); 522428d7b3dSmrg } 523428d7b3dSmrg if(pPriv->linear) { 524428d7b3dSmrg xf86FreeOffscreenLinear(pPriv->linear); 525428d7b3dSmrg pPriv->linear = NULL; 526428d7b3dSmrg } 527428d7b3dSmrg pPriv->videoStatus = 0; 528428d7b3dSmrg } else { 529428d7b3dSmrg if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 530428d7b3dSmrg pPriv->videoStatus |= OFF_TIMER; 531428d7b3dSmrg pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 532428d7b3dSmrg } 533428d7b3dSmrg } 534428d7b3dSmrg 535428d7b3dSmrg} 536428d7b3dSmrg 537428d7b3dSmrgstatic int 538428d7b3dSmrgI810SetPortAttribute( 539428d7b3dSmrg ScrnInfoPtr pScrn, 540428d7b3dSmrg Atom attribute, 541428d7b3dSmrg INT32 value, 542428d7b3dSmrg pointer data 543428d7b3dSmrg){ 544428d7b3dSmrg I810PortPrivPtr pPriv = (I810PortPrivPtr)data; 545428d7b3dSmrg I810Ptr pI810 = I810PTR(pScrn); 546428d7b3dSmrg I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 547428d7b3dSmrg 548428d7b3dSmrg if(attribute == xvBrightness) { 549428d7b3dSmrg if((value < -128) || (value > 127)) 550428d7b3dSmrg return BadValue; 551428d7b3dSmrg pPriv->brightness = value; 552428d7b3dSmrg overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff); 553428d7b3dSmrg OVERLAY_UPDATE(pI810->OverlayPhysical); 554428d7b3dSmrg } else 555428d7b3dSmrg if(attribute == xvContrast) { 556428d7b3dSmrg if((value < 0) || (value > 255)) 557428d7b3dSmrg return BadValue; 558428d7b3dSmrg pPriv->contrast = value; 559428d7b3dSmrg overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff); 560428d7b3dSmrg OVERLAY_UPDATE(pI810->OverlayPhysical); 561428d7b3dSmrg } else 562428d7b3dSmrg if(attribute == xvColorKey) { 563428d7b3dSmrg pPriv->colorKey = value; 564428d7b3dSmrg switch(pScrn->depth) { 565428d7b3dSmrg case 16: overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey); 566428d7b3dSmrg break; 567428d7b3dSmrg case 15: overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey); 568428d7b3dSmrg break; 569428d7b3dSmrg default: overlay->DCLRKV = pPriv->colorKey; 570428d7b3dSmrg break; 571428d7b3dSmrg } 572428d7b3dSmrg OVERLAY_UPDATE(pI810->OverlayPhysical); 573428d7b3dSmrg REGION_EMPTY(pScrn->screen, &pPriv->clip); 574428d7b3dSmrg } else return BadMatch; 575428d7b3dSmrg 576428d7b3dSmrg return Success; 577428d7b3dSmrg} 578428d7b3dSmrg 579428d7b3dSmrgstatic int 580428d7b3dSmrgI810GetPortAttribute( 581428d7b3dSmrg ScrnInfoPtr pScrn, 582428d7b3dSmrg Atom attribute, 583428d7b3dSmrg INT32 *value, 584428d7b3dSmrg pointer data 585428d7b3dSmrg){ 586428d7b3dSmrg I810PortPrivPtr pPriv = (I810PortPrivPtr)data; 587428d7b3dSmrg 588428d7b3dSmrg if(attribute == xvBrightness) { 589428d7b3dSmrg *value = pPriv->brightness; 590428d7b3dSmrg } else 591428d7b3dSmrg if(attribute == xvContrast) { 592428d7b3dSmrg *value = pPriv->contrast; 593428d7b3dSmrg } else 594428d7b3dSmrg if(attribute == xvColorKey) { 595428d7b3dSmrg *value = pPriv->colorKey; 596428d7b3dSmrg } else return BadMatch; 597428d7b3dSmrg 598428d7b3dSmrg return Success; 599428d7b3dSmrg} 600428d7b3dSmrg 601428d7b3dSmrgstatic void 602428d7b3dSmrgI810QueryBestSize( 603428d7b3dSmrg ScrnInfoPtr pScrn, 604428d7b3dSmrg Bool motion, 605428d7b3dSmrg short vid_w, short vid_h, 606428d7b3dSmrg short drw_w, short drw_h, 607428d7b3dSmrg unsigned int *p_w, unsigned int *p_h, 608428d7b3dSmrg pointer data 609428d7b3dSmrg){ 610428d7b3dSmrg if(vid_w > (drw_w << 1)) drw_w = vid_w >> 1; 611428d7b3dSmrg if(vid_h > (drw_h << 1)) drw_h = vid_h >> 1; 612428d7b3dSmrg 613428d7b3dSmrg *p_w = drw_w; 614428d7b3dSmrg *p_h = drw_h; 615428d7b3dSmrg} 616428d7b3dSmrg 617428d7b3dSmrg 618428d7b3dSmrgstatic void 619428d7b3dSmrgI810CopyPackedData( 620428d7b3dSmrg ScrnInfoPtr pScrn, 621428d7b3dSmrg unsigned char *buf, 622428d7b3dSmrg int srcPitch, 623428d7b3dSmrg int dstPitch, 624428d7b3dSmrg int top, 625428d7b3dSmrg int left, 626428d7b3dSmrg int h, 627428d7b3dSmrg int w 628428d7b3dSmrg ) 629428d7b3dSmrg{ 630428d7b3dSmrg I810Ptr pI810 = I810PTR(pScrn); 631428d7b3dSmrg I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr; 632428d7b3dSmrg unsigned char *src, *dst; 633428d7b3dSmrg 634428d7b3dSmrg src = buf + (top*srcPitch) + (left<<1); 635428d7b3dSmrg 636428d7b3dSmrg if (pPriv->currentBuf == 0) 637428d7b3dSmrg dst = pI810->FbBase + pPriv->YBuf0offset; 638428d7b3dSmrg else 639428d7b3dSmrg dst = pI810->FbBase + pPriv->YBuf1offset; 640428d7b3dSmrg 641428d7b3dSmrg w <<= 1; 642428d7b3dSmrg while(h--) { 643428d7b3dSmrg memcpy(dst, src, w); 644428d7b3dSmrg src += srcPitch; 645428d7b3dSmrg dst += dstPitch; 646428d7b3dSmrg } 647428d7b3dSmrg} 648428d7b3dSmrg 649428d7b3dSmrgstatic void 650428d7b3dSmrgI810CopyPlanarData( 651428d7b3dSmrg ScrnInfoPtr pScrn, 652428d7b3dSmrg unsigned char *buf, 653428d7b3dSmrg int srcPitch, 654428d7b3dSmrg int dstPitch, /* of chroma */ 655428d7b3dSmrg int srcH, 656428d7b3dSmrg int top, 657428d7b3dSmrg int left, 658428d7b3dSmrg int h, 659428d7b3dSmrg int w, 660428d7b3dSmrg int id 661428d7b3dSmrg ) 662428d7b3dSmrg{ 663428d7b3dSmrg I810Ptr pI810 = I810PTR(pScrn); 664428d7b3dSmrg I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr; 665428d7b3dSmrg int i; 666428d7b3dSmrg unsigned char *src1, *src2, *src3, *dst1, *dst2, *dst3; 667428d7b3dSmrg 668428d7b3dSmrg /* Copy Y data */ 669428d7b3dSmrg src1 = buf + (top*srcPitch) + left; 670428d7b3dSmrg if (pPriv->currentBuf == 0) 671428d7b3dSmrg dst1 = pI810->FbBase + pPriv->YBuf0offset; 672428d7b3dSmrg else 673428d7b3dSmrg dst1 = pI810->FbBase + pPriv->YBuf1offset; 674428d7b3dSmrg 675428d7b3dSmrg for (i = 0; i < h; i++) { 676428d7b3dSmrg memcpy(dst1, src1, w); 677428d7b3dSmrg src1 += srcPitch; 678428d7b3dSmrg dst1 += dstPitch << 1; 679428d7b3dSmrg } 680428d7b3dSmrg 681428d7b3dSmrg /* Copy V data for YV12, or U data for I420 */ 682428d7b3dSmrg src2 = buf + (srcH*srcPitch) + ((top*srcPitch)>>2) + (left>>1); 683428d7b3dSmrg if (pPriv->currentBuf == 0) { 684428d7b3dSmrg if (id == FOURCC_I420) 685428d7b3dSmrg dst2 = pI810->FbBase + pPriv->UBuf0offset; 686428d7b3dSmrg else 687428d7b3dSmrg dst2 = pI810->FbBase + pPriv->VBuf0offset; 688428d7b3dSmrg } else { 689428d7b3dSmrg if (id == FOURCC_I420) 690428d7b3dSmrg dst2 = pI810->FbBase + pPriv->UBuf1offset; 691428d7b3dSmrg else 692428d7b3dSmrg dst2 = pI810->FbBase + pPriv->VBuf1offset; 693428d7b3dSmrg } 694428d7b3dSmrg 695428d7b3dSmrg for (i = 0; i < h/2; i++) { 696428d7b3dSmrg memcpy(dst2, src2, w/2); 697428d7b3dSmrg src2 += srcPitch>>1; 698428d7b3dSmrg dst2 += dstPitch; 699428d7b3dSmrg } 700428d7b3dSmrg 701428d7b3dSmrg /* Copy U data for YV12, or V data for I420 */ 702428d7b3dSmrg src3 = buf + (srcH*srcPitch) + ((srcH*srcPitch)>>2) + ((top*srcPitch)>>2) + (left>>1); 703428d7b3dSmrg if (pPriv->currentBuf == 0) { 704428d7b3dSmrg if (id == FOURCC_I420) 705428d7b3dSmrg dst3 = pI810->FbBase + pPriv->VBuf0offset; 706428d7b3dSmrg else 707428d7b3dSmrg dst3 = pI810->FbBase + pPriv->UBuf0offset; 708428d7b3dSmrg } else { 709428d7b3dSmrg if (id == FOURCC_I420) 710428d7b3dSmrg dst3 = pI810->FbBase + pPriv->VBuf1offset; 711428d7b3dSmrg else 712428d7b3dSmrg dst3 = pI810->FbBase + pPriv->UBuf1offset; 713428d7b3dSmrg } 714428d7b3dSmrg 715428d7b3dSmrg for (i = 0; i < h/2; i++) { 716428d7b3dSmrg memcpy(dst3, src3, w/2); 717428d7b3dSmrg src3 += srcPitch>>1; 718428d7b3dSmrg dst3 += dstPitch; 719428d7b3dSmrg } 720428d7b3dSmrg} 721428d7b3dSmrg 722428d7b3dSmrgstatic void 723428d7b3dSmrgI810DisplayVideo( 724428d7b3dSmrg ScrnInfoPtr pScrn, 725428d7b3dSmrg int id, 726428d7b3dSmrg short width, short height, 727428d7b3dSmrg int dstPitch, /* of chroma for 4:2:0 */ 728428d7b3dSmrg int x1, int y1, int x2, int y2, 729428d7b3dSmrg BoxPtr dstBox, 730428d7b3dSmrg short src_w, short src_h, 731428d7b3dSmrg short drw_w, short drw_h 732428d7b3dSmrg){ 733428d7b3dSmrg I810Ptr pI810 = I810PTR(pScrn); 734428d7b3dSmrg I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr; 735428d7b3dSmrg I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 736428d7b3dSmrg int xscaleInt, xscaleFract, yscaleInt, yscaleFract; 737428d7b3dSmrg int xscaleIntUV = 0, xscaleFractUV = 0, yscaleIntUV = 0, yscaleFractUV = 0; 738428d7b3dSmrg unsigned int swidth; 739428d7b3dSmrg 740428d7b3dSmrg switch(id) { 741428d7b3dSmrg case FOURCC_YV12: 742428d7b3dSmrg case FOURCC_I420: 743428d7b3dSmrg swidth = ALIGN(width, 8); 744428d7b3dSmrg overlay->SWID = (swidth << 15) | swidth; 745428d7b3dSmrg overlay->SWIDQW = (swidth << 12) | (swidth >> 3); 746428d7b3dSmrg break; 747428d7b3dSmrg case FOURCC_UYVY: 748428d7b3dSmrg case FOURCC_YUY2: 749428d7b3dSmrg default: 750428d7b3dSmrg swidth = ALIGN(width, 4) << 1; 751428d7b3dSmrg overlay->SWID = swidth; 752428d7b3dSmrg overlay->SWIDQW = swidth >> 3; 753428d7b3dSmrg break; 754428d7b3dSmrg } 755428d7b3dSmrg 756428d7b3dSmrg /* wide video formats (>720 pixels) are special */ 757428d7b3dSmrg if( swidth > IMAGE_FAST_WIDTH ) { 758428d7b3dSmrg overlay->OV0CONF = 1; /* one 1440 pixel line buffer */ 759428d7b3dSmrg } else { 760428d7b3dSmrg overlay->OV0CONF = 0; /* two 720 pixel line buffers */ 761428d7b3dSmrg } 762428d7b3dSmrg 763428d7b3dSmrg overlay->SHEIGHT = height | (height << 15); 764428d7b3dSmrg overlay->DWINPOS = (dstBox->y1 << 16) | (dstBox->x1); 765428d7b3dSmrg overlay->DWINSZ = ((dstBox->y2 - dstBox->y1) << 16) | 766428d7b3dSmrg (dstBox->x2 - dstBox->x1); 767428d7b3dSmrg 768428d7b3dSmrg /* buffer locations */ 769428d7b3dSmrg overlay->OBUF_0Y = pPriv->YBuf0offset; 770428d7b3dSmrg overlay->OBUF_1Y = pPriv->YBuf1offset; 771428d7b3dSmrg overlay->OBUF_0U = pPriv->UBuf0offset; 772428d7b3dSmrg overlay->OBUF_0V = pPriv->VBuf0offset; 773428d7b3dSmrg overlay->OBUF_1U = pPriv->UBuf1offset; 774428d7b3dSmrg overlay->OBUF_1V = pPriv->VBuf1offset; 775428d7b3dSmrg 776428d7b3dSmrg /* 777428d7b3dSmrg * Calculate horizontal and vertical scaling factors, default to 1:1 778428d7b3dSmrg */ 779428d7b3dSmrg overlay->YRGBSCALE = 0x80004000; 780428d7b3dSmrg overlay->UVSCALE = 0x80004000; 781428d7b3dSmrg 782428d7b3dSmrg /* 783428d7b3dSmrg * Initially, YCbCr and Overlay Enable and 784428d7b3dSmrg * vertical chrominance up interpolation and horozontal chrominance 785428d7b3dSmrg * up interpolation 786428d7b3dSmrg */ 787428d7b3dSmrg overlay->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | Y_ADJUST | 788428d7b3dSmrg OVERLAY_ENABLE; 789428d7b3dSmrg 790428d7b3dSmrg if ((drw_w != src_w) || (drw_h != src_h)) 791428d7b3dSmrg { 792428d7b3dSmrg xscaleInt = (src_w / drw_w) & 0x3; 793428d7b3dSmrg xscaleFract = (src_w << 12) / drw_w; 794428d7b3dSmrg yscaleInt = (src_h / drw_h) & 0x3; 795428d7b3dSmrg yscaleFract = (src_h << 12) / drw_h; 796428d7b3dSmrg 797428d7b3dSmrg overlay->YRGBSCALE = (xscaleInt << 15) | 798428d7b3dSmrg ((xscaleFract & 0xFFF) << 3) | 799428d7b3dSmrg (yscaleInt) | 800428d7b3dSmrg ((yscaleFract & 0xFFF) << 20); 801428d7b3dSmrg 802428d7b3dSmrg if (drw_w > src_w) 803428d7b3dSmrg { 804428d7b3dSmrg /* horizontal up-scaling */ 805428d7b3dSmrg overlay->OV0CMD &= ~HORIZONTAL_CHROMINANCE_FILTER; 806428d7b3dSmrg overlay->OV0CMD &= ~HORIZONTAL_LUMINANCE_FILTER; 807428d7b3dSmrg overlay->OV0CMD |= (HC_UP_INTERPOLATION | HL_UP_INTERPOLATION); 808428d7b3dSmrg } 809428d7b3dSmrg 810428d7b3dSmrg if (drw_h > src_h) 811428d7b3dSmrg { 812428d7b3dSmrg /* vertical up-scaling */ 813428d7b3dSmrg overlay->OV0CMD &= ~VERTICAL_CHROMINANCE_FILTER; 814428d7b3dSmrg overlay->OV0CMD &= ~VERTICAL_LUMINANCE_FILTER; 815428d7b3dSmrg overlay->OV0CMD |= (VC_UP_INTERPOLATION | VL_UP_INTERPOLATION); 816428d7b3dSmrg } 817428d7b3dSmrg 818428d7b3dSmrg if (drw_w < src_w) 819428d7b3dSmrg { 820428d7b3dSmrg /* horizontal down-scaling */ 821428d7b3dSmrg overlay->OV0CMD &= ~HORIZONTAL_CHROMINANCE_FILTER; 822428d7b3dSmrg overlay->OV0CMD &= ~HORIZONTAL_LUMINANCE_FILTER; 823428d7b3dSmrg overlay->OV0CMD |= (HC_DOWN_INTERPOLATION | HL_DOWN_INTERPOLATION); 824428d7b3dSmrg } 825428d7b3dSmrg 826428d7b3dSmrg if (drw_h < src_h) 827428d7b3dSmrg { 828428d7b3dSmrg /* vertical down-scaling */ 829428d7b3dSmrg overlay->OV0CMD &= ~VERTICAL_CHROMINANCE_FILTER; 830428d7b3dSmrg overlay->OV0CMD &= ~VERTICAL_LUMINANCE_FILTER; 831428d7b3dSmrg overlay->OV0CMD |= (VC_DOWN_INTERPOLATION | VL_DOWN_INTERPOLATION); 832428d7b3dSmrg } 833428d7b3dSmrg 834428d7b3dSmrg /* now calculate the UV scaling factor */ 835428d7b3dSmrg 836428d7b3dSmrg if (xscaleFract) 837428d7b3dSmrg { 838428d7b3dSmrg xscaleFractUV = xscaleFract >> MINUV_SCALE; 839428d7b3dSmrg overlay->OV0CMD &= ~HC_DOWN_INTERPOLATION; 840428d7b3dSmrg overlay->OV0CMD |= HC_UP_INTERPOLATION; 841428d7b3dSmrg } 842428d7b3dSmrg 843428d7b3dSmrg if (xscaleInt) 844428d7b3dSmrg { 845428d7b3dSmrg xscaleIntUV = xscaleInt >> MINUV_SCALE; 846428d7b3dSmrg if (xscaleIntUV) 847428d7b3dSmrg { 848428d7b3dSmrg overlay->OV0CMD &= ~HC_UP_INTERPOLATION; 849428d7b3dSmrg } 850428d7b3dSmrg } 851428d7b3dSmrg 852428d7b3dSmrg if (yscaleFract) 853428d7b3dSmrg { 854428d7b3dSmrg yscaleFractUV = yscaleFract >> MINUV_SCALE; 855428d7b3dSmrg overlay->OV0CMD &= ~VC_DOWN_INTERPOLATION; 856428d7b3dSmrg overlay->OV0CMD |= VC_UP_INTERPOLATION; 857428d7b3dSmrg } 858428d7b3dSmrg 859428d7b3dSmrg if (yscaleInt) 860428d7b3dSmrg { 861428d7b3dSmrg yscaleIntUV = yscaleInt >> MINUV_SCALE; 862428d7b3dSmrg if (yscaleIntUV) 863428d7b3dSmrg { 864428d7b3dSmrg overlay->OV0CMD &= ~VC_UP_INTERPOLATION; 865428d7b3dSmrg overlay->OV0CMD |= VC_DOWN_INTERPOLATION; 866428d7b3dSmrg } 867428d7b3dSmrg } 868428d7b3dSmrg 869428d7b3dSmrg overlay->UVSCALE = yscaleIntUV | ((xscaleFractUV & 0xFFF) << 3) | 870428d7b3dSmrg ((yscaleFractUV & 0xFFF) << 20); 871428d7b3dSmrg } 872428d7b3dSmrg 873428d7b3dSmrg switch(id) { 874428d7b3dSmrg case FOURCC_YV12: 875428d7b3dSmrg case FOURCC_I420: 876428d7b3dSmrg /* set UV vertical phase to -0.25 */ 877428d7b3dSmrg overlay->UV_VPH = 0x30003000; 878428d7b3dSmrg overlay->INIT_PH = UV_VERT_BUF0 | UV_VERT_BUF1; 879428d7b3dSmrg overlay->OV0STRIDE = (dstPitch << 1) | (dstPitch << 16); 880428d7b3dSmrg overlay->OV0CMD &= ~SOURCE_FORMAT; 881428d7b3dSmrg overlay->OV0CMD |= YUV_420; 882428d7b3dSmrg break; 883428d7b3dSmrg case I810_RV15: 884428d7b3dSmrg case I810_RV16: 885428d7b3dSmrg overlay->UV_VPH = 0; 886428d7b3dSmrg overlay->INIT_PH = 0; 887428d7b3dSmrg overlay->OV0STRIDE = dstPitch; 888428d7b3dSmrg overlay->OV0CMD &= ~SOURCE_FORMAT; 889428d7b3dSmrg overlay->OV0CMD |= (id==I810_RV15 ? RGB_555 : RGB_565); 890428d7b3dSmrg overlay->OV0CMD &= ~OV_BYTE_ORDER; 891428d7b3dSmrg break; 892428d7b3dSmrg case FOURCC_UYVY: 893428d7b3dSmrg case FOURCC_YUY2: 894428d7b3dSmrg default: 895428d7b3dSmrg overlay->UV_VPH = 0; 896428d7b3dSmrg overlay->INIT_PH = 0; 897428d7b3dSmrg overlay->OV0STRIDE = dstPitch; 898428d7b3dSmrg overlay->OV0CMD &= ~SOURCE_FORMAT; 899428d7b3dSmrg overlay->OV0CMD |= YUV_422; 900428d7b3dSmrg overlay->OV0CMD &= ~OV_BYTE_ORDER; 901428d7b3dSmrg if (id == FOURCC_UYVY) 902428d7b3dSmrg overlay->OV0CMD |= Y_SWAP; 903428d7b3dSmrg break; 904428d7b3dSmrg } 905428d7b3dSmrg 906428d7b3dSmrg overlay->OV0CMD &= ~BUFFER_AND_FIELD; 907428d7b3dSmrg if (pPriv->currentBuf == 0) 908428d7b3dSmrg overlay->OV0CMD |= BUFFER0_FIELD0; 909428d7b3dSmrg else 910428d7b3dSmrg overlay->OV0CMD |= BUFFER1_FIELD0; 911428d7b3dSmrg 912428d7b3dSmrg OVERLAY_UPDATE(pI810->OverlayPhysical); 913428d7b3dSmrg 914428d7b3dSmrg} 915428d7b3dSmrg 916428d7b3dSmrgstatic FBLinearPtr 917428d7b3dSmrgI810AllocateMemory( 918428d7b3dSmrg ScrnInfoPtr pScrn, 919428d7b3dSmrg FBLinearPtr linear, 920428d7b3dSmrg int size 921428d7b3dSmrg){ 922428d7b3dSmrg ScreenPtr screen; 923428d7b3dSmrg FBLinearPtr new_linear; 924428d7b3dSmrg 925428d7b3dSmrg if(linear) { 926428d7b3dSmrg if(linear->size >= size) 927428d7b3dSmrg return linear; 928428d7b3dSmrg 929428d7b3dSmrg if(xf86ResizeOffscreenLinear(linear, size)) 930428d7b3dSmrg return linear; 931428d7b3dSmrg 932428d7b3dSmrg xf86FreeOffscreenLinear(linear); 933428d7b3dSmrg } 934428d7b3dSmrg 935428d7b3dSmrg screen = xf86ScrnToScreen(pScrn); 936428d7b3dSmrg 937428d7b3dSmrg new_linear = xf86AllocateOffscreenLinear(screen, size, 4, 938428d7b3dSmrg NULL, NULL, NULL); 939428d7b3dSmrg 940428d7b3dSmrg if(!new_linear) { 941428d7b3dSmrg int max_size; 942428d7b3dSmrg 943428d7b3dSmrg xf86QueryLargestOffscreenLinear(screen, &max_size, 4, 944428d7b3dSmrg PRIORITY_EXTREME); 945428d7b3dSmrg 946428d7b3dSmrg if(max_size < size) return NULL; 947428d7b3dSmrg 948428d7b3dSmrg xf86PurgeUnlockedOffscreenAreas(screen); 949428d7b3dSmrg new_linear = xf86AllocateOffscreenLinear(screen, size, 4, 950428d7b3dSmrg NULL, NULL, NULL); 951428d7b3dSmrg } 952428d7b3dSmrg 953428d7b3dSmrg return new_linear; 954428d7b3dSmrg} 955428d7b3dSmrg 956428d7b3dSmrgstatic int 957428d7b3dSmrgI810PutImage( 958428d7b3dSmrg ScrnInfoPtr pScrn, 959428d7b3dSmrg short src_x, short src_y, 960428d7b3dSmrg short drw_x, short drw_y, 961428d7b3dSmrg short src_w, short src_h, 962428d7b3dSmrg short drw_w, short drw_h, 963428d7b3dSmrg int id, unsigned char* buf, 964428d7b3dSmrg short width, short height, 965428d7b3dSmrg Bool sync, 966428d7b3dSmrg RegionPtr clipBoxes, pointer data, 967428d7b3dSmrg DrawablePtr pDraw 968428d7b3dSmrg){ 969428d7b3dSmrg I810Ptr pI810 = I810PTR(pScrn); 970428d7b3dSmrg I810PortPrivPtr pPriv = (I810PortPrivPtr)data; 971428d7b3dSmrg INT32 x1, x2, y1, y2; 972428d7b3dSmrg int srcPitch, dstPitch; 973428d7b3dSmrg int top, left, npixels, nlines, size, loops; 974428d7b3dSmrg BoxRec dstBox; 975428d7b3dSmrg 976428d7b3dSmrg 977428d7b3dSmrg /* Clip */ 978428d7b3dSmrg x1 = src_x; 979428d7b3dSmrg x2 = src_x + src_w; 980428d7b3dSmrg y1 = src_y; 981428d7b3dSmrg y2 = src_y + src_h; 982428d7b3dSmrg 983428d7b3dSmrg dstBox.x1 = drw_x; 984428d7b3dSmrg dstBox.x2 = drw_x + drw_w; 985428d7b3dSmrg dstBox.y1 = drw_y; 986428d7b3dSmrg dstBox.y2 = drw_y + drw_h; 987428d7b3dSmrg 988428d7b3dSmrg I810ClipVideo(&dstBox, &x1, &x2, &y1, &y2, 989428d7b3dSmrg REGION_EXTENTS(pScrn->screen, clipBoxes), width, height); 990428d7b3dSmrg 991428d7b3dSmrg if((x1 >= x2) || (y1 >= y2)) 992428d7b3dSmrg return Success; 993428d7b3dSmrg /* 994428d7b3dSmrg * Fix for 4 pixel granularity of AdjustFrame 995428d7b3dSmrg * unless boarder is clipped by frame 996428d7b3dSmrg */ 997428d7b3dSmrg dstBox.x1 -= (pScrn->frameX0 & 998428d7b3dSmrg ((dstBox.x1 == pScrn->frameX0) ? ~0x0UL : ~0x3UL)); 999428d7b3dSmrg dstBox.x2 -= (pScrn->frameX0 & ~0x3); 1000428d7b3dSmrg dstBox.y1 -= pScrn->frameY0; 1001428d7b3dSmrg dstBox.y2 -= pScrn->frameY0; 1002428d7b3dSmrg 1003428d7b3dSmrg switch(id) { 1004428d7b3dSmrg case FOURCC_YV12: 1005428d7b3dSmrg case FOURCC_I420: 1006428d7b3dSmrg srcPitch = ALIGN(width, 4); 1007428d7b3dSmrg dstPitch = ALIGN((width >> 1), 8); /* of chroma */ 1008428d7b3dSmrg size = dstPitch * height * 3; 1009428d7b3dSmrg break; 1010428d7b3dSmrg case FOURCC_UYVY: 1011428d7b3dSmrg case FOURCC_YUY2: 1012428d7b3dSmrg default: 1013428d7b3dSmrg srcPitch = (width << 1); 1014428d7b3dSmrg dstPitch = ALIGN(srcPitch, 8); 1015428d7b3dSmrg size = dstPitch * height; 1016428d7b3dSmrg break; 1017428d7b3dSmrg } 1018428d7b3dSmrg 1019428d7b3dSmrg if(!(pPriv->linear = I810AllocateMemory(pScrn, pPriv->linear, 1020428d7b3dSmrg (pScrn->bitsPerPixel == 16) ? size : (size >> 1)))) 1021428d7b3dSmrg return BadAlloc; 1022428d7b3dSmrg 1023428d7b3dSmrg /* fixup pointers */ 1024428d7b3dSmrg pPriv->YBuf0offset = pPriv->linear->offset * pI810->cpp; 1025428d7b3dSmrg pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height); 1026428d7b3dSmrg pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height >> 1); 1027428d7b3dSmrg 1028428d7b3dSmrg pPriv->YBuf1offset = (pPriv->linear->offset * pI810->cpp) + size; 1029428d7b3dSmrg pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height); 1030428d7b3dSmrg pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height >> 1); 1031428d7b3dSmrg 1032428d7b3dSmrg 1033428d7b3dSmrg /* Make sure this buffer isn't in use */ 1034428d7b3dSmrg loops = 0; 1035428d7b3dSmrg while (loops < 1000000) { 1036428d7b3dSmrg if(((INREG(DOV0STA)&0x00100000)>>20) == pPriv->currentBuf) { 1037428d7b3dSmrg break; 1038428d7b3dSmrg } 1039428d7b3dSmrg loops++; 1040428d7b3dSmrg } 1041428d7b3dSmrg if(loops >= 1000000) { 1042428d7b3dSmrg pPriv->currentBuf = !pPriv->currentBuf; 1043428d7b3dSmrg } 1044428d7b3dSmrg 1045428d7b3dSmrg 1046428d7b3dSmrg /* buffer swap */ 1047428d7b3dSmrg if (pPriv->currentBuf == 0) 1048428d7b3dSmrg pPriv->currentBuf = 1; 1049428d7b3dSmrg else 1050428d7b3dSmrg pPriv->currentBuf = 0; 1051428d7b3dSmrg 1052428d7b3dSmrg /* copy data */ 1053428d7b3dSmrg top = y1 >> 16; 1054428d7b3dSmrg left = (x1 >> 16) & ~1; 1055428d7b3dSmrg npixels = ALIGN(((x2 + 0xffff) >> 16), 2) - left; 1056428d7b3dSmrg 1057428d7b3dSmrg switch(id) { 1058428d7b3dSmrg case FOURCC_YV12: 1059428d7b3dSmrg case FOURCC_I420: 1060428d7b3dSmrg top &= ~1; 1061428d7b3dSmrg nlines = ALIGN(((y2 + 0xffff) >> 16), 2) - top; 1062428d7b3dSmrg I810CopyPlanarData(pScrn, buf, srcPitch, dstPitch, height, top, left, 1063428d7b3dSmrg nlines, npixels, id); 1064428d7b3dSmrg break; 1065428d7b3dSmrg case FOURCC_UYVY: 1066428d7b3dSmrg case FOURCC_YUY2: 1067428d7b3dSmrg default: 1068428d7b3dSmrg nlines = ((y2 + 0xffff) >> 16) - top; 1069428d7b3dSmrg I810CopyPackedData(pScrn, buf, srcPitch, dstPitch, top, left, nlines, 1070428d7b3dSmrg npixels); 1071428d7b3dSmrg break; 1072428d7b3dSmrg } 1073428d7b3dSmrg 1074428d7b3dSmrg /* update cliplist */ 1075428d7b3dSmrg if(!REGION_EQUAL(pScrn->screen, &pPriv->clip, clipBoxes)) { 1076428d7b3dSmrg REGION_COPY(pScrn->screen, &pPriv->clip, clipBoxes); 1077428d7b3dSmrg /* draw these */ 1078428d7b3dSmrg xf86XVFillKeyHelperDrawable(pDraw, pPriv->colorKey, clipBoxes); 1079428d7b3dSmrg } 1080428d7b3dSmrg 1081428d7b3dSmrg I810DisplayVideo(pScrn, id, width, height, dstPitch, 1082428d7b3dSmrg x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 1083428d7b3dSmrg 1084428d7b3dSmrg pPriv->videoStatus = CLIENT_VIDEO_ON; 1085428d7b3dSmrg 1086428d7b3dSmrg return Success; 1087428d7b3dSmrg} 1088428d7b3dSmrg 1089428d7b3dSmrg 1090428d7b3dSmrgstatic int 1091428d7b3dSmrgI810QueryImageAttributes( 1092428d7b3dSmrg ScrnInfoPtr pScrn, 1093428d7b3dSmrg int id, 1094428d7b3dSmrg unsigned short *w, unsigned short *h, 1095428d7b3dSmrg int *pitches, int *offsets 1096428d7b3dSmrg){ 1097428d7b3dSmrg int size, tmp; 1098428d7b3dSmrg 1099428d7b3dSmrg if(*w > IMAGE_MAX_WIDTH) *w = IMAGE_MAX_WIDTH; 1100428d7b3dSmrg if(*h > IMAGE_MAX_HEIGHT) *h = IMAGE_MAX_HEIGHT; 1101428d7b3dSmrg 1102428d7b3dSmrg *w = (*w + 1) & ~1; 1103428d7b3dSmrg if(offsets) offsets[0] = 0; 1104428d7b3dSmrg 1105428d7b3dSmrg switch(id) { 1106428d7b3dSmrg /* IA44 is for XvMC only */ 1107428d7b3dSmrg case FOURCC_IA44: 1108428d7b3dSmrg case FOURCC_AI44: 1109428d7b3dSmrg if(pitches) pitches[0] = *w; 1110428d7b3dSmrg size = *w * *h; 1111428d7b3dSmrg break; 1112428d7b3dSmrg case FOURCC_YV12: 1113428d7b3dSmrg case FOURCC_I420: 1114428d7b3dSmrg *h = (*h + 1) & ~1; 1115428d7b3dSmrg size = (*w + 3) & ~3; 1116428d7b3dSmrg if(pitches) pitches[0] = size; 1117428d7b3dSmrg size *= *h; 1118428d7b3dSmrg if(offsets) offsets[1] = size; 1119428d7b3dSmrg tmp = ((*w >> 1) + 3) & ~3; 1120428d7b3dSmrg if(pitches) pitches[1] = pitches[2] = tmp; 1121428d7b3dSmrg tmp *= (*h >> 1); 1122428d7b3dSmrg size += tmp; 1123428d7b3dSmrg if(offsets) offsets[2] = size; 1124428d7b3dSmrg size += tmp; 1125428d7b3dSmrg break; 1126428d7b3dSmrg case FOURCC_UYVY: 1127428d7b3dSmrg case FOURCC_YUY2: 1128428d7b3dSmrg default: 1129428d7b3dSmrg size = *w << 1; 1130428d7b3dSmrg if(pitches) pitches[0] = size; 1131428d7b3dSmrg size *= *h; 1132428d7b3dSmrg break; 1133428d7b3dSmrg } 1134428d7b3dSmrg 1135428d7b3dSmrg return size; 1136428d7b3dSmrg} 1137428d7b3dSmrg 1138428d7b3dSmrgstatic void 1139428d7b3dSmrgI810BlockHandler (BLOCKHANDLER_ARGS_DECL) 1140428d7b3dSmrg{ 1141428d7b3dSmrg SCREEN_PTR(arg); 1142428d7b3dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 1143428d7b3dSmrg I810Ptr pI810 = I810PTR(pScrn); 1144428d7b3dSmrg I810PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 1145428d7b3dSmrg I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 1146428d7b3dSmrg 1147428d7b3dSmrg screen->BlockHandler = pI810->BlockHandler; 1148428d7b3dSmrg 1149428d7b3dSmrg (*screen->BlockHandler) (BLOCKHANDLER_ARGS); 1150428d7b3dSmrg 1151428d7b3dSmrg screen->BlockHandler = I810BlockHandler; 1152428d7b3dSmrg 1153428d7b3dSmrg if(pPriv->videoStatus & TIMER_MASK) { 1154428d7b3dSmrg UpdateCurrentTime(); 1155428d7b3dSmrg if(pPriv->videoStatus & OFF_TIMER) { 1156428d7b3dSmrg if(pPriv->offTime < currentTime.milliseconds) { 1157428d7b3dSmrg /* Turn off the overlay */ 1158428d7b3dSmrg overlay->OV0CMD &= 0xFFFFFFFE; 1159428d7b3dSmrg OVERLAY_UPDATE(pI810->OverlayPhysical); 1160428d7b3dSmrg 1161428d7b3dSmrg pPriv->videoStatus = FREE_TIMER; 1162428d7b3dSmrg pPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 1163428d7b3dSmrg } 1164428d7b3dSmrg } else { /* FREE_TIMER */ 1165428d7b3dSmrg if(pPriv->freeTime < currentTime.milliseconds) { 1166428d7b3dSmrg if(pPriv->linear) { 1167428d7b3dSmrg xf86FreeOffscreenLinear(pPriv->linear); 1168428d7b3dSmrg pPriv->linear = NULL; 1169428d7b3dSmrg } 1170428d7b3dSmrg pPriv->videoStatus = 0; 1171428d7b3dSmrg } 1172428d7b3dSmrg } 1173428d7b3dSmrg } 1174428d7b3dSmrg} 1175428d7b3dSmrg 1176428d7b3dSmrg 1177428d7b3dSmrg/*************************************************************************** 1178428d7b3dSmrg * Offscreen Images 1179428d7b3dSmrg ***************************************************************************/ 1180428d7b3dSmrg 1181428d7b3dSmrgtypedef struct { 1182428d7b3dSmrg FBLinearPtr linear; 1183428d7b3dSmrg Bool isOn; 1184428d7b3dSmrg} OffscreenPrivRec, * OffscreenPrivPtr; 1185428d7b3dSmrg 1186428d7b3dSmrgstatic int 1187428d7b3dSmrgI810AllocateSurface( 1188428d7b3dSmrg ScrnInfoPtr pScrn, 1189428d7b3dSmrg int id, 1190428d7b3dSmrg unsigned short w, 1191428d7b3dSmrg unsigned short h, 1192428d7b3dSmrg XF86SurfacePtr surface 1193428d7b3dSmrg){ 1194428d7b3dSmrg FBLinearPtr linear; 1195428d7b3dSmrg int pitch, size, bpp; 1196428d7b3dSmrg OffscreenPrivPtr pPriv; 1197428d7b3dSmrg I810Ptr pI810 = I810PTR(pScrn); 1198428d7b3dSmrg 1199428d7b3dSmrg if((w > 1024) || (h > 1024)) 1200428d7b3dSmrg return BadAlloc; 1201428d7b3dSmrg 1202428d7b3dSmrg w = ALIGN(w, 2); 1203428d7b3dSmrg pitch = ALIGN((w << 1), 16); 1204428d7b3dSmrg bpp = pScrn->bitsPerPixel >> 3; 1205428d7b3dSmrg size = ((pitch * h) + bpp - 1) / bpp; 1206428d7b3dSmrg 1207428d7b3dSmrg if(!(linear = I810AllocateMemory(pScrn, NULL, size))) 1208428d7b3dSmrg return BadAlloc; 1209428d7b3dSmrg 1210428d7b3dSmrg surface->width = w; 1211428d7b3dSmrg surface->height = h; 1212428d7b3dSmrg 1213428d7b3dSmrg if(!(surface->pitches = malloc(sizeof(int)))) { 1214428d7b3dSmrg xf86FreeOffscreenLinear(linear); 1215428d7b3dSmrg return BadAlloc; 1216428d7b3dSmrg } 1217428d7b3dSmrg if(!(surface->offsets = malloc(sizeof(int)))) { 1218428d7b3dSmrg free(surface->pitches); 1219428d7b3dSmrg xf86FreeOffscreenLinear(linear); 1220428d7b3dSmrg return BadAlloc; 1221428d7b3dSmrg } 1222428d7b3dSmrg if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) { 1223428d7b3dSmrg free(surface->pitches); 1224428d7b3dSmrg free(surface->offsets); 1225428d7b3dSmrg xf86FreeOffscreenLinear(linear); 1226428d7b3dSmrg return BadAlloc; 1227428d7b3dSmrg } 1228428d7b3dSmrg 1229428d7b3dSmrg pPriv->linear = linear; 1230428d7b3dSmrg pPriv->isOn = FALSE; 1231428d7b3dSmrg 1232428d7b3dSmrg surface->pScrn = pScrn; 1233428d7b3dSmrg surface->id = id; 1234428d7b3dSmrg surface->pitches[0] = pitch; 1235428d7b3dSmrg surface->offsets[0] = linear->offset * bpp; 1236428d7b3dSmrg surface->devPrivate.ptr = (pointer)pPriv; 1237428d7b3dSmrg 1238428d7b3dSmrg memset(pI810->FbBase + surface->offsets[0],0,size); 1239428d7b3dSmrg 1240428d7b3dSmrg return Success; 1241428d7b3dSmrg} 1242428d7b3dSmrg 1243428d7b3dSmrgstatic int 1244428d7b3dSmrgI810StopSurface( 1245428d7b3dSmrg XF86SurfacePtr surface 1246428d7b3dSmrg){ 1247428d7b3dSmrg OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 1248428d7b3dSmrg 1249428d7b3dSmrg if(pPriv->isOn) { 1250428d7b3dSmrg I810Ptr pI810 = I810PTR(surface->pScrn); 1251428d7b3dSmrg 1252428d7b3dSmrg I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 1253428d7b3dSmrg 1254428d7b3dSmrg overlay->OV0CMD &= 0xFFFFFFFE; 1255428d7b3dSmrg OVERLAY_UPDATE(pI810->OverlayPhysical); 1256428d7b3dSmrg 1257428d7b3dSmrg pPriv->isOn = FALSE; 1258428d7b3dSmrg } 1259428d7b3dSmrg 1260428d7b3dSmrg return Success; 1261428d7b3dSmrg} 1262428d7b3dSmrg 1263428d7b3dSmrg 1264428d7b3dSmrgstatic int 1265428d7b3dSmrgI810FreeSurface( 1266428d7b3dSmrg XF86SurfacePtr surface 1267428d7b3dSmrg){ 1268428d7b3dSmrg OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 1269428d7b3dSmrg 1270428d7b3dSmrg if(pPriv->isOn) { 1271428d7b3dSmrg I810StopSurface(surface); 1272428d7b3dSmrg } 1273428d7b3dSmrg xf86FreeOffscreenLinear(pPriv->linear); 1274428d7b3dSmrg free(surface->pitches); 1275428d7b3dSmrg free(surface->offsets); 1276428d7b3dSmrg free(surface->devPrivate.ptr); 1277428d7b3dSmrg 1278428d7b3dSmrg return Success; 1279428d7b3dSmrg} 1280428d7b3dSmrg 1281428d7b3dSmrgstatic int 1282428d7b3dSmrgI810GetSurfaceAttribute( 1283428d7b3dSmrg ScrnInfoPtr pScrn, 1284428d7b3dSmrg Atom attribute, 1285428d7b3dSmrg INT32 *value 1286428d7b3dSmrg){ 1287428d7b3dSmrg return I810GetPortAttribute(pScrn, attribute, value, GET_PORT_PRIVATE(pScrn)); 1288428d7b3dSmrg} 1289428d7b3dSmrg 1290428d7b3dSmrgstatic int 1291428d7b3dSmrgI810SetSurfaceAttribute( 1292428d7b3dSmrg ScrnInfoPtr pScrn, 1293428d7b3dSmrg Atom attribute, 1294428d7b3dSmrg INT32 value 1295428d7b3dSmrg){ 1296428d7b3dSmrg return I810SetPortAttribute(pScrn, attribute, value, GET_PORT_PRIVATE(pScrn)); 1297428d7b3dSmrg} 1298428d7b3dSmrg 1299428d7b3dSmrg 1300428d7b3dSmrgstatic int 1301428d7b3dSmrgI810DisplaySurface( 1302428d7b3dSmrg XF86SurfacePtr surface, 1303428d7b3dSmrg short src_x, short src_y, 1304428d7b3dSmrg short drw_x, short drw_y, 1305428d7b3dSmrg short src_w, short src_h, 1306428d7b3dSmrg short drw_w, short drw_h, 1307428d7b3dSmrg RegionPtr clipBoxes 1308428d7b3dSmrg){ 1309428d7b3dSmrg OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 1310428d7b3dSmrg ScrnInfoPtr pScrn = surface->pScrn; 1311428d7b3dSmrg I810Ptr pI810 = I810PTR(pScrn); 1312428d7b3dSmrg I810PortPrivPtr pI810Priv = GET_PORT_PRIVATE(pScrn); 1313428d7b3dSmrg 1314428d7b3dSmrg INT32 x1, y1, x2, y2; 1315428d7b3dSmrg INT32 loops = 0; 1316428d7b3dSmrg BoxRec dstBox; 1317428d7b3dSmrg 1318428d7b3dSmrg x1 = src_x; 1319428d7b3dSmrg x2 = src_x + src_w; 1320428d7b3dSmrg y1 = src_y; 1321428d7b3dSmrg y2 = src_y + src_h; 1322428d7b3dSmrg 1323428d7b3dSmrg dstBox.x1 = drw_x; 1324428d7b3dSmrg dstBox.x2 = drw_x + drw_w; 1325428d7b3dSmrg dstBox.y1 = drw_y; 1326428d7b3dSmrg dstBox.y2 = drw_y + drw_h; 1327428d7b3dSmrg 1328428d7b3dSmrg I810ClipVideo(&dstBox, &x1, &x2, &y1, &y2, 1329428d7b3dSmrg REGION_EXTENTS(screenInfo.screens[0], clipBoxes), 1330428d7b3dSmrg surface->width, surface->height); 1331428d7b3dSmrg 1332428d7b3dSmrg /* 1333428d7b3dSmrg * Fix for 4 pixel granularity of AdjustFrame 1334428d7b3dSmrg * unless boarder is clipped by frame 1335428d7b3dSmrg */ 1336428d7b3dSmrg dstBox.x1 -= (pScrn->frameX0 & 1337428d7b3dSmrg ((dstBox.x1 == pScrn->frameX0) ? ~0x0UL : ~0x3UL)); 1338428d7b3dSmrg dstBox.x2 -= (pScrn->frameX0 & ~0x3); 1339428d7b3dSmrg dstBox.y1 -= pScrn->frameY0; 1340428d7b3dSmrg dstBox.y2 -= pScrn->frameY0; 1341428d7b3dSmrg 1342428d7b3dSmrg /* fixup pointers */ 1343428d7b3dSmrg pI810Priv->YBuf0offset = surface->offsets[0]; 1344428d7b3dSmrg pI810Priv->YBuf1offset = pI810Priv->YBuf0offset; 1345428d7b3dSmrg 1346428d7b3dSmrg /* wait for the last rendered buffer to be flipped in */ 1347428d7b3dSmrg while (((INREG(DOV0STA)&0x00100000)>>20) != pI810Priv->currentBuf) { 1348428d7b3dSmrg if(loops == 200000) { 1349428d7b3dSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Overlay Lockup\n"); 1350428d7b3dSmrg break; 1351428d7b3dSmrg } 1352428d7b3dSmrg loops++; 1353428d7b3dSmrg } 1354428d7b3dSmrg 1355428d7b3dSmrg /* buffer swap */ 1356428d7b3dSmrg if (pI810Priv->currentBuf == 0) 1357428d7b3dSmrg pI810Priv->currentBuf = 1; 1358428d7b3dSmrg else 1359428d7b3dSmrg pI810Priv->currentBuf = 0; 1360428d7b3dSmrg 1361428d7b3dSmrg I810ResetVideo(pScrn); 1362428d7b3dSmrg 1363428d7b3dSmrg I810DisplayVideo(pScrn, surface->id, surface->width, surface->height, 1364428d7b3dSmrg surface->pitches[0], x1, y1, x2, y2, &dstBox, 1365428d7b3dSmrg src_w, src_h, drw_w, drw_h); 1366428d7b3dSmrg 1367428d7b3dSmrg xf86XVFillKeyHelper(pScrn->pScreen, pI810Priv->colorKey, clipBoxes); 1368428d7b3dSmrg 1369428d7b3dSmrg pPriv->isOn = TRUE; 1370428d7b3dSmrg /* we've prempted the XvImage stream so set its free timer */ 1371428d7b3dSmrg if(pI810Priv->videoStatus & CLIENT_VIDEO_ON) { 1372428d7b3dSmrg REGION_EMPTY(pScrn->screen, & pI810Priv->clip); 1373428d7b3dSmrg UpdateCurrentTime(); 1374428d7b3dSmrg pI810Priv->videoStatus = FREE_TIMER; 1375428d7b3dSmrg pI810Priv->freeTime = currentTime.milliseconds + FREE_DELAY; 1376428d7b3dSmrg pScrn->pScreen->BlockHandler = I810BlockHandler; 1377428d7b3dSmrg } 1378428d7b3dSmrg 1379428d7b3dSmrg return Success; 1380428d7b3dSmrg} 1381428d7b3dSmrg 1382428d7b3dSmrg 1383428d7b3dSmrgstatic void 1384428d7b3dSmrgI810InitOffscreenImages(ScreenPtr screen) 1385428d7b3dSmrg{ 1386428d7b3dSmrg XF86OffscreenImagePtr offscreenImages; 1387428d7b3dSmrg 1388428d7b3dSmrg /* need to free this someplace */ 1389428d7b3dSmrg if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec)))) { 1390428d7b3dSmrg return; 1391428d7b3dSmrg } 1392428d7b3dSmrg 1393428d7b3dSmrg offscreenImages[0].image = &Images[0]; 1394428d7b3dSmrg offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | 1395428d7b3dSmrg VIDEO_CLIP_TO_VIEWPORT; 1396428d7b3dSmrg offscreenImages[0].alloc_surface = I810AllocateSurface; 1397428d7b3dSmrg offscreenImages[0].free_surface = I810FreeSurface; 1398428d7b3dSmrg offscreenImages[0].display = I810DisplaySurface; 1399428d7b3dSmrg offscreenImages[0].stop = I810StopSurface; 1400428d7b3dSmrg offscreenImages[0].setAttribute = I810SetSurfaceAttribute; 1401428d7b3dSmrg offscreenImages[0].getAttribute = I810GetSurfaceAttribute; 1402428d7b3dSmrg offscreenImages[0].max_width = 1024; 1403428d7b3dSmrg offscreenImages[0].max_height = 1024; 1404428d7b3dSmrg offscreenImages[0].num_attributes = 1; 1405428d7b3dSmrg offscreenImages[0].attributes = Attributes; 1406428d7b3dSmrg 1407428d7b3dSmrg if (!xf86XVRegisterOffscreenImages(screen, offscreenImages, 1)) 1408428d7b3dSmrg free(offscreenImages); 1409428d7b3dSmrg} 1410428d7b3dSmrg 1411