103b705cfSriastradh/*************************************************************************** 203b705cfSriastradh 303b705cfSriastradhCopyright 2000 Intel Corporation. All Rights Reserved. 403b705cfSriastradh 503b705cfSriastradhPermission is hereby granted, free of charge, to any person obtaining a 603b705cfSriastradhcopy of this software and associated documentation files (the 703b705cfSriastradh"Software"), to deal in the Software without restriction, including 803b705cfSriastradhwithout limitation the rights to use, copy, modify, merge, publish, 903b705cfSriastradhdistribute, sub license, and/or sell copies of the Software, and to 1003b705cfSriastradhpermit persons to whom the Software is furnished to do so, subject to 1103b705cfSriastradhthe following conditions: 1203b705cfSriastradh 1303b705cfSriastradhThe above copyright notice and this permission notice (including the 1403b705cfSriastradhnext paragraph) shall be included in all copies or substantial portions 1503b705cfSriastradhof the Software. 1603b705cfSriastradh 1703b705cfSriastradhTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1803b705cfSriastradhOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1903b705cfSriastradhMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 2003b705cfSriastradhIN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 2103b705cfSriastradhDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 2203b705cfSriastradhOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 2303b705cfSriastradhTHE USE OR OTHER DEALINGS IN THE SOFTWARE. 2403b705cfSriastradh 2503b705cfSriastradh**************************************************************************/ 2603b705cfSriastradh 2703b705cfSriastradh/* 2803b705cfSriastradh * i810_video.c: i810 Xv driver. Based on the mga Xv driver by Mark Vojkovich. 2903b705cfSriastradh * 3003b705cfSriastradh * Authors: 3103b705cfSriastradh * Jonathan Bian <jonathan.bian@intel.com> 3203b705cfSriastradh * Offscreen Images: 3303b705cfSriastradh * Matt Sottek <matthew.j.sottek@intel.com> 3403b705cfSriastradh */ 3503b705cfSriastradh 3603b705cfSriastradh#ifdef HAVE_CONFIG_H 3703b705cfSriastradh#include "config.h" 3803b705cfSriastradh#endif 3903b705cfSriastradh 4003b705cfSriastradh#include <string.h> 4103b705cfSriastradh 4242542f5fSchristos#include "xorg-server.h" 4303b705cfSriastradh#include "xf86.h" 4403b705cfSriastradh#include "xf86_OSproc.h" 4503b705cfSriastradh#include "compiler.h" 4603b705cfSriastradh#include "xf86Pci.h" 4703b705cfSriastradh#include "xf86fbman.h" 4803b705cfSriastradh#include "regionstr.h" 4903b705cfSriastradh 5003b705cfSriastradh#include "i810.h" 5103b705cfSriastradh#include "xf86xv.h" 5203b705cfSriastradh#include <X11/extensions/Xv.h> 5303b705cfSriastradh#include "dixstruct.h" 5403b705cfSriastradh#include "fourcc.h" 5503b705cfSriastradh 5603b705cfSriastradh#define OFF_DELAY 250 /* milliseconds */ 5703b705cfSriastradh#define FREE_DELAY 15000 5803b705cfSriastradh 5903b705cfSriastradh#define OFF_TIMER 0x01 6003b705cfSriastradh#define FREE_TIMER 0x02 6103b705cfSriastradh#define CLIENT_VIDEO_ON 0x04 6203b705cfSriastradh 6303b705cfSriastradh#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 6403b705cfSriastradh 6503b705cfSriastradhstatic void I810InitOffscreenImages(ScreenPtr); 6603b705cfSriastradh 6703b705cfSriastradhstatic XF86VideoAdaptorPtr I810SetupImageVideo(ScreenPtr); 6803b705cfSriastradhstatic void I810StopVideo(ScrnInfoPtr, pointer, Bool); 6903b705cfSriastradhstatic int I810SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 7003b705cfSriastradhstatic int I810GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); 7103b705cfSriastradhstatic void I810QueryBestSize(ScrnInfoPtr, Bool, 7203b705cfSriastradh short, short, short, short, unsigned int *, unsigned int *, pointer); 7303b705cfSriastradhstatic int I810PutImage( ScrnInfoPtr, 7403b705cfSriastradh short, short, short, short, short, short, short, short, 7503b705cfSriastradh int, unsigned char*, short, short, Bool, RegionPtr, pointer, 7603b705cfSriastradh DrawablePtr); 7703b705cfSriastradhstatic int I810QueryImageAttributes(ScrnInfoPtr, 7803b705cfSriastradh int, unsigned short *, unsigned short *, int *, int *); 7903b705cfSriastradh 80fe8aea9eSmrg#if !HAVE_NOTIFY_FD 8103b705cfSriastradhstatic void I810BlockHandler(BLOCKHANDLER_ARGS_DECL); 82fe8aea9eSmrg#else 83fe8aea9eSmrgstatic void I810BlockHandler(void *data, void *_timeout); 84fe8aea9eSmrg#endif 8503b705cfSriastradh 8603b705cfSriastradh#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 8703b705cfSriastradh 8803b705cfSriastradhstatic Atom xvBrightness, xvContrast, xvColorKey; 8903b705cfSriastradh 9003b705cfSriastradh#define IMAGE_MAX_WIDTH 1440 9103b705cfSriastradh#define IMAGE_FAST_WIDTH 720 9203b705cfSriastradh#define IMAGE_MAX_HEIGHT 1080 9303b705cfSriastradh#define Y_BUF_SIZE (IMAGE_MAX_WIDTH * IMAGE_MAX_HEIGHT) 9403b705cfSriastradh 9503b705cfSriastradh#define OVERLAY_UPDATE(p) OUTREG(0x30000, p | 0x80000000); 9603b705cfSriastradh 9703b705cfSriastradh/* 9803b705cfSriastradh * OV0CMD - Overlay Command Register 9903b705cfSriastradh */ 10003b705cfSriastradh#define VERTICAL_CHROMINANCE_FILTER 0x70000000 10103b705cfSriastradh#define VC_SCALING_OFF 0x00000000 10203b705cfSriastradh#define VC_LINE_REPLICATION 0x10000000 10303b705cfSriastradh#define VC_UP_INTERPOLATION 0x20000000 10403b705cfSriastradh#define VC_PIXEL_DROPPING 0x50000000 10503b705cfSriastradh#define VC_DOWN_INTERPOLATION 0x60000000 10603b705cfSriastradh#define VERTICAL_LUMINANCE_FILTER 0x0E000000 10703b705cfSriastradh#define VL_SCALING_OFF 0x00000000 10803b705cfSriastradh#define VL_LINE_REPLICATION 0x02000000 10903b705cfSriastradh#define VL_UP_INTERPOLATION 0x04000000 11003b705cfSriastradh#define VL_PIXEL_DROPPING 0x0A000000 11103b705cfSriastradh#define VL_DOWN_INTERPOLATION 0x0C000000 11203b705cfSriastradh#define HORIZONTAL_CHROMINANCE_FILTER 0x01C00000 11303b705cfSriastradh#define HC_SCALING_OFF 0x00000000 11403b705cfSriastradh#define HC_LINE_REPLICATION 0x00400000 11503b705cfSriastradh#define HC_UP_INTERPOLATION 0x00800000 11603b705cfSriastradh#define HC_PIXEL_DROPPING 0x01400000 11703b705cfSriastradh#define HC_DOWN_INTERPOLATION 0x01800000 11803b705cfSriastradh#define HORIZONTAL_LUMINANCE_FILTER 0x00380000 11903b705cfSriastradh#define HL_SCALING_OFF 0x00000000 12003b705cfSriastradh#define HL_LINE_REPLICATION 0x00080000 12103b705cfSriastradh#define HL_UP_INTERPOLATION 0x00100000 12203b705cfSriastradh#define HL_PIXEL_DROPPING 0x00280000 12303b705cfSriastradh#define HL_DOWN_INTERPOLATION 0x00300000 12403b705cfSriastradh 12503b705cfSriastradh#define Y_ADJUST 0x00010000 12603b705cfSriastradh#define OV_BYTE_ORDER 0x0000C000 12703b705cfSriastradh#define UV_SWAP 0x00004000 12803b705cfSriastradh#define Y_SWAP 0x00008000 12903b705cfSriastradh#define Y_AND_UV_SWAP 0x0000C000 13003b705cfSriastradh#define SOURCE_FORMAT 0x00003C00 13103b705cfSriastradh#define RGB_555 0x00000800 13203b705cfSriastradh#define RGB_565 0x00000C00 13303b705cfSriastradh#define YUV_422 0x00002000 13403b705cfSriastradh#define YUV_411 0x00002400 13503b705cfSriastradh#define YUV_420 0x00003000 13603b705cfSriastradh#define YUV_410 0x00003800 13703b705cfSriastradh#define BUFFER_AND_FIELD 0x00000006 13803b705cfSriastradh#define BUFFER0_FIELD0 0x00000000 13903b705cfSriastradh#define BUFFER1_FIELD0 0x00000004 14003b705cfSriastradh#define OVERLAY_ENABLE 0x00000001 14103b705cfSriastradh 14203b705cfSriastradh#define UV_VERT_BUF1 0x02 14303b705cfSriastradh#define UV_VERT_BUF0 0x04 14403b705cfSriastradh 14503b705cfSriastradh/* 14603b705cfSriastradh * DOV0STA - Display/Overlay 0 Status Register 14703b705cfSriastradh */ 14803b705cfSriastradh#define DOV0STA 0x30008 14903b705cfSriastradh 15003b705cfSriastradh#define MINUV_SCALE 0x1 15103b705cfSriastradh 15203b705cfSriastradh#define RGB16ToColorKey(c) \ 15303b705cfSriastradh (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3)) 15403b705cfSriastradh 15503b705cfSriastradh#define RGB15ToColorKey(c) \ 15603b705cfSriastradh (((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3)) 15703b705cfSriastradh 15803b705cfSriastradhvoid I810InitVideo(ScreenPtr screen) 15903b705cfSriastradh{ 16003b705cfSriastradh ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 16103b705cfSriastradh XF86VideoAdaptorPtr *adaptors = NULL; 16203b705cfSriastradh int num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 16303b705cfSriastradh 16403b705cfSriastradh if (pScrn->bitsPerPixel != 8) { 16503b705cfSriastradh XF86VideoAdaptorPtr newAdaptor; 16603b705cfSriastradh 16703b705cfSriastradh newAdaptor = I810SetupImageVideo(screen); 16803b705cfSriastradh I810InitOffscreenImages(screen); 16903b705cfSriastradh 17003b705cfSriastradh if (newAdaptor) { 17103b705cfSriastradh XF86VideoAdaptorPtr *newAdaptors; 17203b705cfSriastradh 17303b705cfSriastradh newAdaptors = 17403b705cfSriastradh realloc(adaptors, 17503b705cfSriastradh (num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr)); 17603b705cfSriastradh if (newAdaptors != NULL) { 17703b705cfSriastradh newAdaptors[num_adaptors++] = newAdaptor; 17803b705cfSriastradh adaptors = newAdaptors; 17903b705cfSriastradh } 18003b705cfSriastradh } 18103b705cfSriastradh } 18203b705cfSriastradh 18303b705cfSriastradh if (num_adaptors) 18403b705cfSriastradh xf86XVScreenInit(screen, adaptors, num_adaptors); 18503b705cfSriastradh 18603b705cfSriastradh free(adaptors); 18703b705cfSriastradh} 18803b705cfSriastradh 18903b705cfSriastradh/* *INDENT-OFF* */ 19003b705cfSriastradh/* client libraries expect an encoding */ 19103b705cfSriastradhstatic XF86VideoEncodingRec DummyEncoding[1] = 19203b705cfSriastradh{ 19303b705cfSriastradh { 19403b705cfSriastradh 0, 19503b705cfSriastradh "XV_IMAGE", 19603b705cfSriastradh IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, 19703b705cfSriastradh {1, 1} 19803b705cfSriastradh } 19903b705cfSriastradh}; 20003b705cfSriastradh 20103b705cfSriastradh#define NUM_FORMATS 3 20203b705cfSriastradh 20303b705cfSriastradhstatic XF86VideoFormatRec Formats[NUM_FORMATS] = 20403b705cfSriastradh{ 20503b705cfSriastradh {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 20603b705cfSriastradh}; 20703b705cfSriastradh 20803b705cfSriastradh#define NUM_ATTRIBUTES 3 20903b705cfSriastradh 21003b705cfSriastradhstatic XF86AttributeRec Attributes[NUM_ATTRIBUTES] = 21103b705cfSriastradh{ 21203b705cfSriastradh {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 21303b705cfSriastradh {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, 21403b705cfSriastradh {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"} 21503b705cfSriastradh}; 21603b705cfSriastradh 21703b705cfSriastradh#define NUM_IMAGES 6 21803b705cfSriastradh 21903b705cfSriastradh#define I810_RV15 0x35315652 22003b705cfSriastradh#define I810_RV16 0x36315652 22103b705cfSriastradh 22203b705cfSriastradhstatic XF86ImageRec Images[NUM_IMAGES] = 22303b705cfSriastradh{ 22403b705cfSriastradh { 22503b705cfSriastradh I810_RV15, 22603b705cfSriastradh XvRGB, 22703b705cfSriastradh LSBFirst, 22803b705cfSriastradh {'R','V','1','5', 22903b705cfSriastradh 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 23003b705cfSriastradh 16, 23103b705cfSriastradh XvPacked, 23203b705cfSriastradh 1, 23303b705cfSriastradh 15, 0x7C00, 0x03E0, 0x001F, 23403b705cfSriastradh 0, 0, 0, 23503b705cfSriastradh 0, 0, 0, 23603b705cfSriastradh 0, 0, 0, 23703b705cfSriastradh {'R','V','B',0, 23803b705cfSriastradh 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}, 23903b705cfSriastradh XvTopToBottom 24003b705cfSriastradh }, 24103b705cfSriastradh { 24203b705cfSriastradh I810_RV16, 24303b705cfSriastradh XvRGB, 24403b705cfSriastradh LSBFirst, 24503b705cfSriastradh {'R','V','1','6', 24603b705cfSriastradh 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 24703b705cfSriastradh 16, 24803b705cfSriastradh XvPacked, 24903b705cfSriastradh 1, 25003b705cfSriastradh 16, 0xF800, 0x07E0, 0x001F, 25103b705cfSriastradh 0, 0, 0, 25203b705cfSriastradh 0, 0, 0, 25303b705cfSriastradh 0, 0, 0, 25403b705cfSriastradh {'R','V','B',0, 25503b705cfSriastradh 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}, 25603b705cfSriastradh XvTopToBottom 25703b705cfSriastradh }, 25803b705cfSriastradh XVIMAGE_YUY2, 25903b705cfSriastradh XVIMAGE_YV12, 26003b705cfSriastradh XVIMAGE_I420, 26103b705cfSriastradh XVIMAGE_UYVY 26203b705cfSriastradh}; 26303b705cfSriastradh/* *INDENT-ON* */ 26403b705cfSriastradh 26503b705cfSriastradhtypedef struct { 26603b705cfSriastradh uint32_t OBUF_0Y; 26703b705cfSriastradh uint32_t OBUF_1Y; 26803b705cfSriastradh uint32_t OBUF_0U; 26903b705cfSriastradh uint32_t OBUF_0V; 27003b705cfSriastradh uint32_t OBUF_1U; 27103b705cfSriastradh uint32_t OBUF_1V; 27203b705cfSriastradh uint32_t OV0STRIDE; 27303b705cfSriastradh uint32_t YRGB_VPH; 27403b705cfSriastradh uint32_t UV_VPH; 27503b705cfSriastradh uint32_t HORZ_PH; 27603b705cfSriastradh uint32_t INIT_PH; 27703b705cfSriastradh uint32_t DWINPOS; 27803b705cfSriastradh uint32_t DWINSZ; 27903b705cfSriastradh uint32_t SWID; 28003b705cfSriastradh uint32_t SWIDQW; 28103b705cfSriastradh uint32_t SHEIGHT; 28203b705cfSriastradh uint32_t YRGBSCALE; 28303b705cfSriastradh uint32_t UVSCALE; 28403b705cfSriastradh uint32_t OV0CLRC0; 28503b705cfSriastradh uint32_t OV0CLRC1; 28603b705cfSriastradh uint32_t DCLRKV; 28703b705cfSriastradh uint32_t DCLRKM; 28803b705cfSriastradh uint32_t SCLRKVH; 28903b705cfSriastradh uint32_t SCLRKVL; 29003b705cfSriastradh uint32_t SCLRKM; 29103b705cfSriastradh uint32_t OV0CONF; 29203b705cfSriastradh uint32_t OV0CMD; 29303b705cfSriastradh} I810OverlayRegRec, *I810OverlayRegPtr; 29403b705cfSriastradh 29503b705cfSriastradhtypedef struct { 29603b705cfSriastradh uint32_t YBuf0offset; 29703b705cfSriastradh uint32_t UBuf0offset; 29803b705cfSriastradh uint32_t VBuf0offset; 29903b705cfSriastradh 30003b705cfSriastradh uint32_t YBuf1offset; 30103b705cfSriastradh uint32_t UBuf1offset; 30203b705cfSriastradh uint32_t VBuf1offset; 30303b705cfSriastradh 30403b705cfSriastradh unsigned char currentBuf; 30503b705cfSriastradh 30603b705cfSriastradh int brightness; 30703b705cfSriastradh int contrast; 30803b705cfSriastradh 30903b705cfSriastradh RegionRec clip; 31003b705cfSriastradh uint32_t colorKey; 31103b705cfSriastradh 31203b705cfSriastradh uint32_t videoStatus; 31303b705cfSriastradh Time offTime; 31403b705cfSriastradh Time freeTime; 31503b705cfSriastradh FBLinearPtr linear; 31603b705cfSriastradh} I810PortPrivRec, *I810PortPrivPtr; 31703b705cfSriastradh 31803b705cfSriastradh#define GET_PORT_PRIVATE(pScrn) \ 31903b705cfSriastradh (I810PortPrivPtr)((I810PTR(pScrn))->adaptor->pPortPrivates[0].ptr) 32003b705cfSriastradh 32103b705cfSriastradhstatic void I810ResetVideo(ScrnInfoPtr pScrn) 32203b705cfSriastradh{ 32303b705cfSriastradh I810Ptr pI810 = I810PTR(pScrn); 32403b705cfSriastradh I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr; 32503b705cfSriastradh I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 32603b705cfSriastradh 32703b705cfSriastradh /* 32803b705cfSriastradh * Default to maximum image size in YV12 32903b705cfSriastradh */ 33003b705cfSriastradh 33103b705cfSriastradh overlay->YRGB_VPH = 0; 33203b705cfSriastradh overlay->UV_VPH = 0; 33303b705cfSriastradh overlay->HORZ_PH = 0; 33403b705cfSriastradh overlay->INIT_PH = 0; 33503b705cfSriastradh overlay->DWINPOS = 0; 33603b705cfSriastradh overlay->DWINSZ = (IMAGE_MAX_HEIGHT << 16) | IMAGE_MAX_WIDTH; 33703b705cfSriastradh overlay->SWID = IMAGE_MAX_WIDTH | (IMAGE_MAX_WIDTH << 15); 33803b705cfSriastradh overlay->SWIDQW = (IMAGE_MAX_WIDTH >> 3) | (IMAGE_MAX_WIDTH << 12); 33903b705cfSriastradh overlay->SHEIGHT = IMAGE_MAX_HEIGHT | (IMAGE_MAX_HEIGHT << 15); 34003b705cfSriastradh overlay->YRGBSCALE = 0x80004000; /* scale factor 1 */ 34103b705cfSriastradh overlay->UVSCALE = 0x80004000; /* scale factor 1 */ 34203b705cfSriastradh overlay->OV0CLRC0 = 0x4000; /* brightness: 0 contrast: 1.0 */ 34303b705cfSriastradh overlay->OV0CLRC1 = 0x80; /* saturation: bypass */ 34403b705cfSriastradh 34503b705cfSriastradh /* 34603b705cfSriastradh * Enable destination color keying 34703b705cfSriastradh */ 34803b705cfSriastradh switch(pScrn->depth) { 34903b705cfSriastradh case 16: overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey); 35003b705cfSriastradh overlay->DCLRKM = 0x80070307; 35103b705cfSriastradh break; 35203b705cfSriastradh case 15: overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey); 35303b705cfSriastradh overlay->DCLRKM = 0x80070707; 35403b705cfSriastradh break; 35503b705cfSriastradh default: overlay->DCLRKV = pPriv->colorKey; 35603b705cfSriastradh overlay->DCLRKM = 0x80000000; 35703b705cfSriastradh break; 35803b705cfSriastradh } 35903b705cfSriastradh 36003b705cfSriastradh overlay->SCLRKVH = 0; 36103b705cfSriastradh overlay->SCLRKVL = 0; 36203b705cfSriastradh overlay->SCLRKM = 0; /* source color key disable */ 36303b705cfSriastradh overlay->OV0CONF = 0; /* two 720 pixel line buffers */ 36403b705cfSriastradh 36503b705cfSriastradh overlay->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | Y_ADJUST | 36603b705cfSriastradh YUV_420; 36703b705cfSriastradh 36803b705cfSriastradh OVERLAY_UPDATE(pI810->OverlayPhysical); 36903b705cfSriastradh} 37003b705cfSriastradh 37103b705cfSriastradh 37203b705cfSriastradhstatic XF86VideoAdaptorPtr 37303b705cfSriastradhI810SetupImageVideo(ScreenPtr screen) 37403b705cfSriastradh{ 37503b705cfSriastradh ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 37603b705cfSriastradh I810Ptr pI810 = I810PTR(pScrn); 37703b705cfSriastradh XF86VideoAdaptorPtr adapt; 37803b705cfSriastradh I810PortPrivPtr pPriv; 37903b705cfSriastradh 38003b705cfSriastradh if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 38103b705cfSriastradh sizeof(I810PortPrivRec) + 38203b705cfSriastradh sizeof(DevUnion)))) 38303b705cfSriastradh return NULL; 38403b705cfSriastradh 38503b705cfSriastradh adapt->type = XvWindowMask | XvInputMask | XvImageMask; 38603b705cfSriastradh adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 38703b705cfSriastradh adapt->name = "I810 Video Overlay"; 38803b705cfSriastradh adapt->nEncodings = 1; 38903b705cfSriastradh adapt->pEncodings = DummyEncoding; 39003b705cfSriastradh adapt->nFormats = NUM_FORMATS; 39103b705cfSriastradh adapt->pFormats = Formats; 39203b705cfSriastradh adapt->nPorts = 1; 39303b705cfSriastradh adapt->pPortPrivates = (DevUnion*)(&adapt[1]); 39403b705cfSriastradh 39503b705cfSriastradh pPriv = (I810PortPrivPtr)(&adapt->pPortPrivates[1]); 39603b705cfSriastradh 39703b705cfSriastradh adapt->pPortPrivates[0].ptr = (pointer)(pPriv); 39803b705cfSriastradh adapt->pAttributes = Attributes; 39903b705cfSriastradh adapt->nImages = NUM_IMAGES; 40003b705cfSriastradh adapt->nAttributes = NUM_ATTRIBUTES; 40103b705cfSriastradh adapt->pImages = Images; 40203b705cfSriastradh adapt->PutVideo = NULL; 40303b705cfSriastradh adapt->PutStill = NULL; 40403b705cfSriastradh adapt->GetVideo = NULL; 40503b705cfSriastradh adapt->GetStill = NULL; 40603b705cfSriastradh adapt->StopVideo = I810StopVideo; 40703b705cfSriastradh adapt->SetPortAttribute = I810SetPortAttribute; 40803b705cfSriastradh adapt->GetPortAttribute = I810GetPortAttribute; 40903b705cfSriastradh adapt->QueryBestSize = I810QueryBestSize; 41003b705cfSriastradh adapt->PutImage = I810PutImage; 41103b705cfSriastradh adapt->QueryImageAttributes = I810QueryImageAttributes; 41203b705cfSriastradh 41303b705cfSriastradh pPriv->colorKey = pI810->colorKey & ((1 << pScrn->depth) - 1); 41403b705cfSriastradh pPriv->videoStatus = 0; 41503b705cfSriastradh pPriv->brightness = 0; 41603b705cfSriastradh pPriv->contrast = 64; 41703b705cfSriastradh pPriv->linear = NULL; 41803b705cfSriastradh pPriv->currentBuf = 0; 41903b705cfSriastradh 42003b705cfSriastradh /* gotta uninit this someplace */ 42103b705cfSriastradh REGION_NULL(screen, &pPriv->clip); 42203b705cfSriastradh 42303b705cfSriastradh pI810->adaptor = adapt; 42403b705cfSriastradh 425fe8aea9eSmrg#if !HAVE_NOTIFY_FD 42603b705cfSriastradh pI810->BlockHandler = screen->BlockHandler; 42703b705cfSriastradh screen->BlockHandler = I810BlockHandler; 428fe8aea9eSmrg#else 429fe8aea9eSmrg RegisterBlockAndWakeupHandlers(I810BlockHandler, 430fe8aea9eSmrg (ServerWakeupHandlerProcPtr)NoopDDA, 431fe8aea9eSmrg pScrn); 432fe8aea9eSmrg#endif 43303b705cfSriastradh 43403b705cfSriastradh xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 43503b705cfSriastradh xvContrast = MAKE_ATOM("XV_CONTRAST"); 43603b705cfSriastradh xvColorKey = MAKE_ATOM("XV_COLORKEY"); 43703b705cfSriastradh 43803b705cfSriastradh I810ResetVideo(pScrn); 43903b705cfSriastradh 44003b705cfSriastradh return adapt; 44103b705cfSriastradh} 44203b705cfSriastradh 44303b705cfSriastradh 44403b705cfSriastradh/* I810ClipVideo - 44503b705cfSriastradh 44603b705cfSriastradh Takes the dst box in standard X BoxRec form (top and left 44703b705cfSriastradh edges inclusive, bottom and right exclusive). The new dst 44803b705cfSriastradh box is returned. The source boundaries are given (x1, y1 44903b705cfSriastradh inclusive, x2, y2 exclusive) and returned are the new source 45003b705cfSriastradh boundaries in 16.16 fixed point. 45103b705cfSriastradh*/ 45203b705cfSriastradh 45303b705cfSriastradhstatic void 45403b705cfSriastradhI810ClipVideo( 45503b705cfSriastradh BoxPtr dst, 45603b705cfSriastradh INT32 *x1, 45703b705cfSriastradh INT32 *x2, 45803b705cfSriastradh INT32 *y1, 45903b705cfSriastradh INT32 *y2, 46003b705cfSriastradh BoxPtr extents, /* extents of the clip region */ 46103b705cfSriastradh INT32 width, 46203b705cfSriastradh INT32 height 46303b705cfSriastradh){ 46403b705cfSriastradh INT32 vscale, hscale, delta; 46503b705cfSriastradh int diff; 46603b705cfSriastradh 46703b705cfSriastradh hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1); 46803b705cfSriastradh vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1); 46903b705cfSriastradh 47003b705cfSriastradh *x1 <<= 16; *x2 <<= 16; 47103b705cfSriastradh *y1 <<= 16; *y2 <<= 16; 47203b705cfSriastradh 47303b705cfSriastradh diff = extents->x1 - dst->x1; 47403b705cfSriastradh if(diff > 0) { 47503b705cfSriastradh dst->x1 = extents->x1; 47603b705cfSriastradh *x1 += diff * hscale; 47703b705cfSriastradh } 47803b705cfSriastradh diff = dst->x2 - extents->x2; 47903b705cfSriastradh if(diff > 0) { 48003b705cfSriastradh dst->x2 = extents->x2; 48103b705cfSriastradh *x2 -= diff * hscale; 48203b705cfSriastradh } 48303b705cfSriastradh diff = extents->y1 - dst->y1; 48403b705cfSriastradh if(diff > 0) { 48503b705cfSriastradh dst->y1 = extents->y1; 48603b705cfSriastradh *y1 += diff * vscale; 48703b705cfSriastradh } 48803b705cfSriastradh diff = dst->y2 - extents->y2; 48903b705cfSriastradh if(diff > 0) { 49003b705cfSriastradh dst->y2 = extents->y2; 49103b705cfSriastradh *y2 -= diff * vscale; 49203b705cfSriastradh } 49303b705cfSriastradh 49403b705cfSriastradh if(*x1 < 0) { 49503b705cfSriastradh diff = (- *x1 + hscale - 1)/ hscale; 49603b705cfSriastradh dst->x1 += diff; 49703b705cfSriastradh *x1 += diff * hscale; 49803b705cfSriastradh } 49903b705cfSriastradh delta = *x2 - (width << 16); 50003b705cfSriastradh if(delta > 0) { 50103b705cfSriastradh diff = (delta + hscale - 1)/ hscale; 50203b705cfSriastradh dst->x2 -= diff; 50303b705cfSriastradh *x2 -= diff * hscale; 50403b705cfSriastradh } 50503b705cfSriastradh if(*y1 < 0) { 50603b705cfSriastradh diff = (- *y1 + vscale - 1)/ vscale; 50703b705cfSriastradh dst->y1 += diff; 50803b705cfSriastradh *y1 += diff * vscale; 50903b705cfSriastradh } 51003b705cfSriastradh delta = *y2 - (height << 16); 51103b705cfSriastradh if(delta > 0) { 51203b705cfSriastradh diff = (delta + vscale - 1)/ vscale; 51303b705cfSriastradh dst->y2 -= diff; 51403b705cfSriastradh *y2 -= diff * vscale; 51503b705cfSriastradh } 51603b705cfSriastradh} 51703b705cfSriastradh 51803b705cfSriastradhstatic void 51903b705cfSriastradhI810StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) 52003b705cfSriastradh{ 52103b705cfSriastradh I810PortPrivPtr pPriv = (I810PortPrivPtr)data; 52203b705cfSriastradh I810Ptr pI810 = I810PTR(pScrn); 52303b705cfSriastradh 52403b705cfSriastradh I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 52503b705cfSriastradh 52603b705cfSriastradh REGION_EMPTY(pScrn->screen, &pPriv->clip); 52703b705cfSriastradh 52803b705cfSriastradh if(shutdown) { 52903b705cfSriastradh if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 53003b705cfSriastradh overlay->OV0CMD &= 0xFFFFFFFE; 53103b705cfSriastradh OVERLAY_UPDATE(pI810->OverlayPhysical); 53203b705cfSriastradh } 53303b705cfSriastradh if(pPriv->linear) { 53403b705cfSriastradh xf86FreeOffscreenLinear(pPriv->linear); 53503b705cfSriastradh pPriv->linear = NULL; 53603b705cfSriastradh } 53703b705cfSriastradh pPriv->videoStatus = 0; 53803b705cfSriastradh } else { 53903b705cfSriastradh if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 54003b705cfSriastradh pPriv->videoStatus |= OFF_TIMER; 54103b705cfSriastradh pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 54203b705cfSriastradh } 54303b705cfSriastradh } 54403b705cfSriastradh 54503b705cfSriastradh} 54603b705cfSriastradh 54703b705cfSriastradhstatic int 54803b705cfSriastradhI810SetPortAttribute( 54903b705cfSriastradh ScrnInfoPtr pScrn, 55003b705cfSriastradh Atom attribute, 55103b705cfSriastradh INT32 value, 55203b705cfSriastradh pointer data 55303b705cfSriastradh){ 55403b705cfSriastradh I810PortPrivPtr pPriv = (I810PortPrivPtr)data; 55503b705cfSriastradh I810Ptr pI810 = I810PTR(pScrn); 55603b705cfSriastradh I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 55703b705cfSriastradh 55803b705cfSriastradh if(attribute == xvBrightness) { 55903b705cfSriastradh if((value < -128) || (value > 127)) 56003b705cfSriastradh return BadValue; 56103b705cfSriastradh pPriv->brightness = value; 56203b705cfSriastradh overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff); 56303b705cfSriastradh OVERLAY_UPDATE(pI810->OverlayPhysical); 56403b705cfSriastradh } else 56503b705cfSriastradh if(attribute == xvContrast) { 56603b705cfSriastradh if((value < 0) || (value > 255)) 56703b705cfSriastradh return BadValue; 56803b705cfSriastradh pPriv->contrast = value; 56903b705cfSriastradh overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff); 57003b705cfSriastradh OVERLAY_UPDATE(pI810->OverlayPhysical); 57103b705cfSriastradh } else 57203b705cfSriastradh if(attribute == xvColorKey) { 57303b705cfSriastradh pPriv->colorKey = value; 57403b705cfSriastradh switch(pScrn->depth) { 57503b705cfSriastradh case 16: overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey); 57603b705cfSriastradh break; 57703b705cfSriastradh case 15: overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey); 57803b705cfSriastradh break; 57903b705cfSriastradh default: overlay->DCLRKV = pPriv->colorKey; 58003b705cfSriastradh break; 58103b705cfSriastradh } 58203b705cfSriastradh OVERLAY_UPDATE(pI810->OverlayPhysical); 58303b705cfSriastradh REGION_EMPTY(pScrn->screen, &pPriv->clip); 58403b705cfSriastradh } else return BadMatch; 58503b705cfSriastradh 58603b705cfSriastradh return Success; 58703b705cfSriastradh} 58803b705cfSriastradh 58903b705cfSriastradhstatic int 59003b705cfSriastradhI810GetPortAttribute( 59103b705cfSriastradh ScrnInfoPtr pScrn, 59203b705cfSriastradh Atom attribute, 59303b705cfSriastradh INT32 *value, 59403b705cfSriastradh pointer data 59503b705cfSriastradh){ 59603b705cfSriastradh I810PortPrivPtr pPriv = (I810PortPrivPtr)data; 59703b705cfSriastradh 59803b705cfSriastradh if(attribute == xvBrightness) { 59903b705cfSriastradh *value = pPriv->brightness; 60003b705cfSriastradh } else 60103b705cfSriastradh if(attribute == xvContrast) { 60203b705cfSriastradh *value = pPriv->contrast; 60303b705cfSriastradh } else 60403b705cfSriastradh if(attribute == xvColorKey) { 60503b705cfSriastradh *value = pPriv->colorKey; 60603b705cfSriastradh } else return BadMatch; 60703b705cfSriastradh 60803b705cfSriastradh return Success; 60903b705cfSriastradh} 61003b705cfSriastradh 61103b705cfSriastradhstatic void 61203b705cfSriastradhI810QueryBestSize( 61303b705cfSriastradh ScrnInfoPtr pScrn, 61403b705cfSriastradh Bool motion, 61503b705cfSriastradh short vid_w, short vid_h, 61603b705cfSriastradh short drw_w, short drw_h, 61703b705cfSriastradh unsigned int *p_w, unsigned int *p_h, 61803b705cfSriastradh pointer data 61903b705cfSriastradh){ 62003b705cfSriastradh if(vid_w > (drw_w << 1)) drw_w = vid_w >> 1; 62103b705cfSriastradh if(vid_h > (drw_h << 1)) drw_h = vid_h >> 1; 62203b705cfSriastradh 62303b705cfSriastradh *p_w = drw_w; 62403b705cfSriastradh *p_h = drw_h; 62503b705cfSriastradh} 62603b705cfSriastradh 62703b705cfSriastradh 62803b705cfSriastradhstatic void 62903b705cfSriastradhI810CopyPackedData( 63003b705cfSriastradh ScrnInfoPtr pScrn, 63103b705cfSriastradh unsigned char *buf, 63203b705cfSriastradh int srcPitch, 63303b705cfSriastradh int dstPitch, 63403b705cfSriastradh int top, 63503b705cfSriastradh int left, 63603b705cfSriastradh int h, 63703b705cfSriastradh int w 63803b705cfSriastradh ) 63903b705cfSriastradh{ 64003b705cfSriastradh I810Ptr pI810 = I810PTR(pScrn); 64103b705cfSriastradh I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr; 64203b705cfSriastradh unsigned char *src, *dst; 64303b705cfSriastradh 64403b705cfSriastradh src = buf + (top*srcPitch) + (left<<1); 64503b705cfSriastradh 64603b705cfSriastradh if (pPriv->currentBuf == 0) 64703b705cfSriastradh dst = pI810->FbBase + pPriv->YBuf0offset; 64803b705cfSriastradh else 64903b705cfSriastradh dst = pI810->FbBase + pPriv->YBuf1offset; 65003b705cfSriastradh 65103b705cfSriastradh w <<= 1; 65203b705cfSriastradh while(h--) { 65303b705cfSriastradh memcpy(dst, src, w); 65403b705cfSriastradh src += srcPitch; 65503b705cfSriastradh dst += dstPitch; 65603b705cfSriastradh } 65703b705cfSriastradh} 65803b705cfSriastradh 65903b705cfSriastradhstatic void 66003b705cfSriastradhI810CopyPlanarData( 66103b705cfSriastradh ScrnInfoPtr pScrn, 66203b705cfSriastradh unsigned char *buf, 66303b705cfSriastradh int srcPitch, 66403b705cfSriastradh int dstPitch, /* of chroma */ 66503b705cfSriastradh int srcH, 66603b705cfSriastradh int top, 66703b705cfSriastradh int left, 66803b705cfSriastradh int h, 66903b705cfSriastradh int w, 67003b705cfSriastradh int id 67103b705cfSriastradh ) 67203b705cfSriastradh{ 67303b705cfSriastradh I810Ptr pI810 = I810PTR(pScrn); 67403b705cfSriastradh I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr; 67503b705cfSriastradh int i; 67603b705cfSriastradh unsigned char *src1, *src2, *src3, *dst1, *dst2, *dst3; 67703b705cfSriastradh 67803b705cfSriastradh /* Copy Y data */ 67903b705cfSriastradh src1 = buf + (top*srcPitch) + left; 68003b705cfSriastradh if (pPriv->currentBuf == 0) 68103b705cfSriastradh dst1 = pI810->FbBase + pPriv->YBuf0offset; 68203b705cfSriastradh else 68303b705cfSriastradh dst1 = pI810->FbBase + pPriv->YBuf1offset; 68403b705cfSriastradh 68503b705cfSriastradh for (i = 0; i < h; i++) { 68603b705cfSriastradh memcpy(dst1, src1, w); 68703b705cfSriastradh src1 += srcPitch; 68803b705cfSriastradh dst1 += dstPitch << 1; 68903b705cfSriastradh } 69003b705cfSriastradh 69103b705cfSriastradh /* Copy V data for YV12, or U data for I420 */ 69203b705cfSriastradh src2 = buf + (srcH*srcPitch) + ((top*srcPitch)>>2) + (left>>1); 69303b705cfSriastradh if (pPriv->currentBuf == 0) { 69403b705cfSriastradh if (id == FOURCC_I420) 69503b705cfSriastradh dst2 = pI810->FbBase + pPriv->UBuf0offset; 69603b705cfSriastradh else 69703b705cfSriastradh dst2 = pI810->FbBase + pPriv->VBuf0offset; 69803b705cfSriastradh } else { 69903b705cfSriastradh if (id == FOURCC_I420) 70003b705cfSriastradh dst2 = pI810->FbBase + pPriv->UBuf1offset; 70103b705cfSriastradh else 70203b705cfSriastradh dst2 = pI810->FbBase + pPriv->VBuf1offset; 70303b705cfSriastradh } 70403b705cfSriastradh 70503b705cfSriastradh for (i = 0; i < h/2; i++) { 70603b705cfSriastradh memcpy(dst2, src2, w/2); 70703b705cfSriastradh src2 += srcPitch>>1; 70803b705cfSriastradh dst2 += dstPitch; 70903b705cfSriastradh } 71003b705cfSriastradh 71103b705cfSriastradh /* Copy U data for YV12, or V data for I420 */ 71203b705cfSriastradh src3 = buf + (srcH*srcPitch) + ((srcH*srcPitch)>>2) + ((top*srcPitch)>>2) + (left>>1); 71303b705cfSriastradh if (pPriv->currentBuf == 0) { 71403b705cfSriastradh if (id == FOURCC_I420) 71503b705cfSriastradh dst3 = pI810->FbBase + pPriv->VBuf0offset; 71603b705cfSriastradh else 71703b705cfSriastradh dst3 = pI810->FbBase + pPriv->UBuf0offset; 71803b705cfSriastradh } else { 71903b705cfSriastradh if (id == FOURCC_I420) 72003b705cfSriastradh dst3 = pI810->FbBase + pPriv->VBuf1offset; 72103b705cfSriastradh else 72203b705cfSriastradh dst3 = pI810->FbBase + pPriv->UBuf1offset; 72303b705cfSriastradh } 72403b705cfSriastradh 72503b705cfSriastradh for (i = 0; i < h/2; i++) { 72603b705cfSriastradh memcpy(dst3, src3, w/2); 72703b705cfSriastradh src3 += srcPitch>>1; 72803b705cfSriastradh dst3 += dstPitch; 72903b705cfSriastradh } 73003b705cfSriastradh} 73103b705cfSriastradh 73203b705cfSriastradhstatic void 73303b705cfSriastradhI810DisplayVideo( 73403b705cfSriastradh ScrnInfoPtr pScrn, 73503b705cfSriastradh int id, 73603b705cfSriastradh short width, short height, 73703b705cfSriastradh int dstPitch, /* of chroma for 4:2:0 */ 73803b705cfSriastradh int x1, int y1, int x2, int y2, 73903b705cfSriastradh BoxPtr dstBox, 74003b705cfSriastradh short src_w, short src_h, 74103b705cfSriastradh short drw_w, short drw_h 74203b705cfSriastradh){ 74303b705cfSriastradh I810Ptr pI810 = I810PTR(pScrn); 74403b705cfSriastradh I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr; 74503b705cfSriastradh I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 74603b705cfSriastradh int xscaleInt, xscaleFract, yscaleInt, yscaleFract; 74703b705cfSriastradh int xscaleIntUV = 0, xscaleFractUV = 0, yscaleIntUV = 0, yscaleFractUV = 0; 74803b705cfSriastradh unsigned int swidth; 74903b705cfSriastradh 75003b705cfSriastradh switch(id) { 75103b705cfSriastradh case FOURCC_YV12: 75203b705cfSriastradh case FOURCC_I420: 75303b705cfSriastradh swidth = ALIGN(width, 8); 75403b705cfSriastradh overlay->SWID = (swidth << 15) | swidth; 75503b705cfSriastradh overlay->SWIDQW = (swidth << 12) | (swidth >> 3); 75603b705cfSriastradh break; 75703b705cfSriastradh case FOURCC_UYVY: 75803b705cfSriastradh case FOURCC_YUY2: 75903b705cfSriastradh default: 76003b705cfSriastradh swidth = ALIGN(width, 4) << 1; 76103b705cfSriastradh overlay->SWID = swidth; 76203b705cfSriastradh overlay->SWIDQW = swidth >> 3; 76303b705cfSriastradh break; 76403b705cfSriastradh } 76503b705cfSriastradh 76603b705cfSriastradh /* wide video formats (>720 pixels) are special */ 76703b705cfSriastradh if( swidth > IMAGE_FAST_WIDTH ) { 76803b705cfSriastradh overlay->OV0CONF = 1; /* one 1440 pixel line buffer */ 76903b705cfSriastradh } else { 77003b705cfSriastradh overlay->OV0CONF = 0; /* two 720 pixel line buffers */ 77103b705cfSriastradh } 77203b705cfSriastradh 77303b705cfSriastradh overlay->SHEIGHT = height | (height << 15); 77403b705cfSriastradh overlay->DWINPOS = (dstBox->y1 << 16) | (dstBox->x1); 77503b705cfSriastradh overlay->DWINSZ = ((dstBox->y2 - dstBox->y1) << 16) | 77603b705cfSriastradh (dstBox->x2 - dstBox->x1); 77703b705cfSriastradh 77803b705cfSriastradh /* buffer locations */ 77903b705cfSriastradh overlay->OBUF_0Y = pPriv->YBuf0offset; 78003b705cfSriastradh overlay->OBUF_1Y = pPriv->YBuf1offset; 78103b705cfSriastradh overlay->OBUF_0U = pPriv->UBuf0offset; 78203b705cfSriastradh overlay->OBUF_0V = pPriv->VBuf0offset; 78303b705cfSriastradh overlay->OBUF_1U = pPriv->UBuf1offset; 78403b705cfSriastradh overlay->OBUF_1V = pPriv->VBuf1offset; 78503b705cfSriastradh 78603b705cfSriastradh /* 78703b705cfSriastradh * Calculate horizontal and vertical scaling factors, default to 1:1 78803b705cfSriastradh */ 78903b705cfSriastradh overlay->YRGBSCALE = 0x80004000; 79003b705cfSriastradh overlay->UVSCALE = 0x80004000; 79103b705cfSriastradh 79203b705cfSriastradh /* 79303b705cfSriastradh * Initially, YCbCr and Overlay Enable and 79403b705cfSriastradh * vertical chrominance up interpolation and horozontal chrominance 79503b705cfSriastradh * up interpolation 79603b705cfSriastradh */ 79703b705cfSriastradh overlay->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | Y_ADJUST | 79803b705cfSriastradh OVERLAY_ENABLE; 79903b705cfSriastradh 80003b705cfSriastradh if ((drw_w != src_w) || (drw_h != src_h)) 80103b705cfSriastradh { 80203b705cfSriastradh xscaleInt = (src_w / drw_w) & 0x3; 80303b705cfSriastradh xscaleFract = (src_w << 12) / drw_w; 80403b705cfSriastradh yscaleInt = (src_h / drw_h) & 0x3; 80503b705cfSriastradh yscaleFract = (src_h << 12) / drw_h; 80603b705cfSriastradh 80703b705cfSriastradh overlay->YRGBSCALE = (xscaleInt << 15) | 80803b705cfSriastradh ((xscaleFract & 0xFFF) << 3) | 80903b705cfSriastradh (yscaleInt) | 81003b705cfSriastradh ((yscaleFract & 0xFFF) << 20); 81103b705cfSriastradh 81203b705cfSriastradh if (drw_w > src_w) 81303b705cfSriastradh { 81403b705cfSriastradh /* horizontal up-scaling */ 81503b705cfSriastradh overlay->OV0CMD &= ~HORIZONTAL_CHROMINANCE_FILTER; 81603b705cfSriastradh overlay->OV0CMD &= ~HORIZONTAL_LUMINANCE_FILTER; 81703b705cfSriastradh overlay->OV0CMD |= (HC_UP_INTERPOLATION | HL_UP_INTERPOLATION); 81803b705cfSriastradh } 81903b705cfSriastradh 82003b705cfSriastradh if (drw_h > src_h) 82103b705cfSriastradh { 82203b705cfSriastradh /* vertical up-scaling */ 82303b705cfSriastradh overlay->OV0CMD &= ~VERTICAL_CHROMINANCE_FILTER; 82403b705cfSriastradh overlay->OV0CMD &= ~VERTICAL_LUMINANCE_FILTER; 82503b705cfSriastradh overlay->OV0CMD |= (VC_UP_INTERPOLATION | VL_UP_INTERPOLATION); 82603b705cfSriastradh } 82703b705cfSriastradh 82803b705cfSriastradh if (drw_w < src_w) 82903b705cfSriastradh { 83003b705cfSriastradh /* horizontal down-scaling */ 83103b705cfSriastradh overlay->OV0CMD &= ~HORIZONTAL_CHROMINANCE_FILTER; 83203b705cfSriastradh overlay->OV0CMD &= ~HORIZONTAL_LUMINANCE_FILTER; 83303b705cfSriastradh overlay->OV0CMD |= (HC_DOWN_INTERPOLATION | HL_DOWN_INTERPOLATION); 83403b705cfSriastradh } 83503b705cfSriastradh 83603b705cfSriastradh if (drw_h < src_h) 83703b705cfSriastradh { 83803b705cfSriastradh /* vertical down-scaling */ 83903b705cfSriastradh overlay->OV0CMD &= ~VERTICAL_CHROMINANCE_FILTER; 84003b705cfSriastradh overlay->OV0CMD &= ~VERTICAL_LUMINANCE_FILTER; 84103b705cfSriastradh overlay->OV0CMD |= (VC_DOWN_INTERPOLATION | VL_DOWN_INTERPOLATION); 84203b705cfSriastradh } 84303b705cfSriastradh 84403b705cfSriastradh /* now calculate the UV scaling factor */ 84503b705cfSriastradh 84603b705cfSriastradh if (xscaleFract) 84703b705cfSriastradh { 84803b705cfSriastradh xscaleFractUV = xscaleFract >> MINUV_SCALE; 84903b705cfSriastradh overlay->OV0CMD &= ~HC_DOWN_INTERPOLATION; 85003b705cfSriastradh overlay->OV0CMD |= HC_UP_INTERPOLATION; 85103b705cfSriastradh } 85203b705cfSriastradh 85303b705cfSriastradh if (xscaleInt) 85403b705cfSriastradh { 85503b705cfSriastradh xscaleIntUV = xscaleInt >> MINUV_SCALE; 85603b705cfSriastradh if (xscaleIntUV) 85703b705cfSriastradh { 85803b705cfSriastradh overlay->OV0CMD &= ~HC_UP_INTERPOLATION; 85903b705cfSriastradh } 86003b705cfSriastradh } 86103b705cfSriastradh 86203b705cfSriastradh if (yscaleFract) 86303b705cfSriastradh { 86403b705cfSriastradh yscaleFractUV = yscaleFract >> MINUV_SCALE; 86503b705cfSriastradh overlay->OV0CMD &= ~VC_DOWN_INTERPOLATION; 86603b705cfSriastradh overlay->OV0CMD |= VC_UP_INTERPOLATION; 86703b705cfSriastradh } 86803b705cfSriastradh 86903b705cfSriastradh if (yscaleInt) 87003b705cfSriastradh { 87103b705cfSriastradh yscaleIntUV = yscaleInt >> MINUV_SCALE; 87203b705cfSriastradh if (yscaleIntUV) 87303b705cfSriastradh { 87403b705cfSriastradh overlay->OV0CMD &= ~VC_UP_INTERPOLATION; 87503b705cfSriastradh overlay->OV0CMD |= VC_DOWN_INTERPOLATION; 87603b705cfSriastradh } 87703b705cfSriastradh } 87803b705cfSriastradh 87903b705cfSriastradh overlay->UVSCALE = yscaleIntUV | ((xscaleFractUV & 0xFFF) << 3) | 88003b705cfSriastradh ((yscaleFractUV & 0xFFF) << 20); 88103b705cfSriastradh } 88203b705cfSriastradh 88303b705cfSriastradh switch(id) { 88403b705cfSriastradh case FOURCC_YV12: 88503b705cfSriastradh case FOURCC_I420: 88603b705cfSriastradh /* set UV vertical phase to -0.25 */ 88703b705cfSriastradh overlay->UV_VPH = 0x30003000; 88803b705cfSriastradh overlay->INIT_PH = UV_VERT_BUF0 | UV_VERT_BUF1; 88903b705cfSriastradh overlay->OV0STRIDE = (dstPitch << 1) | (dstPitch << 16); 89003b705cfSriastradh overlay->OV0CMD &= ~SOURCE_FORMAT; 89103b705cfSriastradh overlay->OV0CMD |= YUV_420; 89203b705cfSriastradh break; 89303b705cfSriastradh case I810_RV15: 89403b705cfSriastradh case I810_RV16: 89503b705cfSriastradh overlay->UV_VPH = 0; 89603b705cfSriastradh overlay->INIT_PH = 0; 89703b705cfSriastradh overlay->OV0STRIDE = dstPitch; 89803b705cfSriastradh overlay->OV0CMD &= ~SOURCE_FORMAT; 89903b705cfSriastradh overlay->OV0CMD |= (id==I810_RV15 ? RGB_555 : RGB_565); 90003b705cfSriastradh overlay->OV0CMD &= ~OV_BYTE_ORDER; 90103b705cfSriastradh break; 90203b705cfSriastradh case FOURCC_UYVY: 90303b705cfSriastradh case FOURCC_YUY2: 90403b705cfSriastradh default: 90503b705cfSriastradh overlay->UV_VPH = 0; 90603b705cfSriastradh overlay->INIT_PH = 0; 90703b705cfSriastradh overlay->OV0STRIDE = dstPitch; 90803b705cfSriastradh overlay->OV0CMD &= ~SOURCE_FORMAT; 90903b705cfSriastradh overlay->OV0CMD |= YUV_422; 91003b705cfSriastradh overlay->OV0CMD &= ~OV_BYTE_ORDER; 91103b705cfSriastradh if (id == FOURCC_UYVY) 91203b705cfSriastradh overlay->OV0CMD |= Y_SWAP; 91303b705cfSriastradh break; 91403b705cfSriastradh } 91503b705cfSriastradh 91603b705cfSriastradh overlay->OV0CMD &= ~BUFFER_AND_FIELD; 91703b705cfSriastradh if (pPriv->currentBuf == 0) 91803b705cfSriastradh overlay->OV0CMD |= BUFFER0_FIELD0; 91903b705cfSriastradh else 92003b705cfSriastradh overlay->OV0CMD |= BUFFER1_FIELD0; 92103b705cfSriastradh 92203b705cfSriastradh OVERLAY_UPDATE(pI810->OverlayPhysical); 92303b705cfSriastradh 92403b705cfSriastradh} 92503b705cfSriastradh 92603b705cfSriastradhstatic FBLinearPtr 92703b705cfSriastradhI810AllocateMemory( 92803b705cfSriastradh ScrnInfoPtr pScrn, 92903b705cfSriastradh FBLinearPtr linear, 93003b705cfSriastradh int size 93103b705cfSriastradh){ 93203b705cfSriastradh ScreenPtr screen; 93303b705cfSriastradh FBLinearPtr new_linear; 93403b705cfSriastradh 93503b705cfSriastradh if(linear) { 93603b705cfSriastradh if(linear->size >= size) 93703b705cfSriastradh return linear; 93803b705cfSriastradh 93903b705cfSriastradh if(xf86ResizeOffscreenLinear(linear, size)) 94003b705cfSriastradh return linear; 94103b705cfSriastradh 94203b705cfSriastradh xf86FreeOffscreenLinear(linear); 94303b705cfSriastradh } 94403b705cfSriastradh 94503b705cfSriastradh screen = xf86ScrnToScreen(pScrn); 94603b705cfSriastradh 94703b705cfSriastradh new_linear = xf86AllocateOffscreenLinear(screen, size, 4, 94803b705cfSriastradh NULL, NULL, NULL); 94903b705cfSriastradh 95003b705cfSriastradh if(!new_linear) { 95103b705cfSriastradh int max_size; 95203b705cfSriastradh 95303b705cfSriastradh xf86QueryLargestOffscreenLinear(screen, &max_size, 4, 95403b705cfSriastradh PRIORITY_EXTREME); 95503b705cfSriastradh 95603b705cfSriastradh if(max_size < size) return NULL; 95703b705cfSriastradh 95803b705cfSriastradh xf86PurgeUnlockedOffscreenAreas(screen); 95903b705cfSriastradh new_linear = xf86AllocateOffscreenLinear(screen, size, 4, 96003b705cfSriastradh NULL, NULL, NULL); 96103b705cfSriastradh } 96203b705cfSriastradh 96303b705cfSriastradh return new_linear; 96403b705cfSriastradh} 96503b705cfSriastradh 96603b705cfSriastradhstatic int 96703b705cfSriastradhI810PutImage( 96803b705cfSriastradh ScrnInfoPtr pScrn, 96903b705cfSriastradh short src_x, short src_y, 97003b705cfSriastradh short drw_x, short drw_y, 97103b705cfSriastradh short src_w, short src_h, 97203b705cfSriastradh short drw_w, short drw_h, 97303b705cfSriastradh int id, unsigned char* buf, 97403b705cfSriastradh short width, short height, 97503b705cfSriastradh Bool sync, 97603b705cfSriastradh RegionPtr clipBoxes, pointer data, 97703b705cfSriastradh DrawablePtr pDraw 97803b705cfSriastradh){ 97903b705cfSriastradh I810Ptr pI810 = I810PTR(pScrn); 98003b705cfSriastradh I810PortPrivPtr pPriv = (I810PortPrivPtr)data; 98103b705cfSriastradh INT32 x1, x2, y1, y2; 98203b705cfSriastradh int srcPitch, dstPitch; 98303b705cfSriastradh int top, left, npixels, nlines, size, loops; 98403b705cfSriastradh BoxRec dstBox; 98503b705cfSriastradh 98603b705cfSriastradh 98703b705cfSriastradh /* Clip */ 98803b705cfSriastradh x1 = src_x; 98903b705cfSriastradh x2 = src_x + src_w; 99003b705cfSriastradh y1 = src_y; 99103b705cfSriastradh y2 = src_y + src_h; 99203b705cfSriastradh 99303b705cfSriastradh dstBox.x1 = drw_x; 99403b705cfSriastradh dstBox.x2 = drw_x + drw_w; 99503b705cfSriastradh dstBox.y1 = drw_y; 99603b705cfSriastradh dstBox.y2 = drw_y + drw_h; 99703b705cfSriastradh 99803b705cfSriastradh I810ClipVideo(&dstBox, &x1, &x2, &y1, &y2, 99903b705cfSriastradh REGION_EXTENTS(pScrn->screen, clipBoxes), width, height); 100003b705cfSriastradh 100103b705cfSriastradh if((x1 >= x2) || (y1 >= y2)) 100203b705cfSriastradh return Success; 100303b705cfSriastradh /* 100403b705cfSriastradh * Fix for 4 pixel granularity of AdjustFrame 100503b705cfSriastradh * unless boarder is clipped by frame 100603b705cfSriastradh */ 100703b705cfSriastradh dstBox.x1 -= (pScrn->frameX0 & 100803b705cfSriastradh ((dstBox.x1 == pScrn->frameX0) ? ~0x0UL : ~0x3UL)); 100903b705cfSriastradh dstBox.x2 -= (pScrn->frameX0 & ~0x3); 101003b705cfSriastradh dstBox.y1 -= pScrn->frameY0; 101103b705cfSriastradh dstBox.y2 -= pScrn->frameY0; 101203b705cfSriastradh 101303b705cfSriastradh switch(id) { 101403b705cfSriastradh case FOURCC_YV12: 101503b705cfSriastradh case FOURCC_I420: 101603b705cfSriastradh srcPitch = ALIGN(width, 4); 101703b705cfSriastradh dstPitch = ALIGN((width >> 1), 8); /* of chroma */ 101803b705cfSriastradh size = dstPitch * height * 3; 101903b705cfSriastradh break; 102003b705cfSriastradh case FOURCC_UYVY: 102103b705cfSriastradh case FOURCC_YUY2: 102203b705cfSriastradh default: 102303b705cfSriastradh srcPitch = (width << 1); 102403b705cfSriastradh dstPitch = ALIGN(srcPitch, 8); 102503b705cfSriastradh size = dstPitch * height; 102603b705cfSriastradh break; 102703b705cfSriastradh } 102803b705cfSriastradh 102903b705cfSriastradh if(!(pPriv->linear = I810AllocateMemory(pScrn, pPriv->linear, 103003b705cfSriastradh (pScrn->bitsPerPixel == 16) ? size : (size >> 1)))) 103103b705cfSriastradh return BadAlloc; 103203b705cfSriastradh 103303b705cfSriastradh /* fixup pointers */ 103403b705cfSriastradh pPriv->YBuf0offset = pPriv->linear->offset * pI810->cpp; 103503b705cfSriastradh pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height); 103603b705cfSriastradh pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height >> 1); 103703b705cfSriastradh 103803b705cfSriastradh pPriv->YBuf1offset = (pPriv->linear->offset * pI810->cpp) + size; 103903b705cfSriastradh pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height); 104003b705cfSriastradh pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height >> 1); 104103b705cfSriastradh 104203b705cfSriastradh 104303b705cfSriastradh /* Make sure this buffer isn't in use */ 104403b705cfSriastradh loops = 0; 104503b705cfSriastradh while (loops < 1000000) { 104603b705cfSriastradh if(((INREG(DOV0STA)&0x00100000)>>20) == pPriv->currentBuf) { 104703b705cfSriastradh break; 104803b705cfSriastradh } 104903b705cfSriastradh loops++; 105003b705cfSriastradh } 105103b705cfSriastradh if(loops >= 1000000) { 105203b705cfSriastradh pPriv->currentBuf = !pPriv->currentBuf; 105303b705cfSriastradh } 105403b705cfSriastradh 105503b705cfSriastradh 105603b705cfSriastradh /* buffer swap */ 105703b705cfSriastradh if (pPriv->currentBuf == 0) 105803b705cfSriastradh pPriv->currentBuf = 1; 105903b705cfSriastradh else 106003b705cfSriastradh pPriv->currentBuf = 0; 106103b705cfSriastradh 106203b705cfSriastradh /* copy data */ 106303b705cfSriastradh top = y1 >> 16; 106403b705cfSriastradh left = (x1 >> 16) & ~1; 106503b705cfSriastradh npixels = ALIGN(((x2 + 0xffff) >> 16), 2) - left; 106603b705cfSriastradh 106703b705cfSriastradh switch(id) { 106803b705cfSriastradh case FOURCC_YV12: 106903b705cfSriastradh case FOURCC_I420: 107003b705cfSriastradh top &= ~1; 107103b705cfSriastradh nlines = ALIGN(((y2 + 0xffff) >> 16), 2) - top; 107203b705cfSriastradh I810CopyPlanarData(pScrn, buf, srcPitch, dstPitch, height, top, left, 107303b705cfSriastradh nlines, npixels, id); 107403b705cfSriastradh break; 107503b705cfSriastradh case FOURCC_UYVY: 107603b705cfSriastradh case FOURCC_YUY2: 107703b705cfSriastradh default: 107803b705cfSriastradh nlines = ((y2 + 0xffff) >> 16) - top; 107903b705cfSriastradh I810CopyPackedData(pScrn, buf, srcPitch, dstPitch, top, left, nlines, 108003b705cfSriastradh npixels); 108103b705cfSriastradh break; 108203b705cfSriastradh } 108303b705cfSriastradh 108403b705cfSriastradh /* update cliplist */ 108503b705cfSriastradh if(!REGION_EQUAL(pScrn->screen, &pPriv->clip, clipBoxes)) { 108603b705cfSriastradh REGION_COPY(pScrn->screen, &pPriv->clip, clipBoxes); 108703b705cfSriastradh /* draw these */ 108803b705cfSriastradh xf86XVFillKeyHelperDrawable(pDraw, pPriv->colorKey, clipBoxes); 108903b705cfSriastradh } 109003b705cfSriastradh 109103b705cfSriastradh I810DisplayVideo(pScrn, id, width, height, dstPitch, 109203b705cfSriastradh x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 109303b705cfSriastradh 109403b705cfSriastradh pPriv->videoStatus = CLIENT_VIDEO_ON; 109503b705cfSriastradh 109603b705cfSriastradh return Success; 109703b705cfSriastradh} 109803b705cfSriastradh 109903b705cfSriastradh 110003b705cfSriastradhstatic int 110103b705cfSriastradhI810QueryImageAttributes( 110203b705cfSriastradh ScrnInfoPtr pScrn, 110303b705cfSriastradh int id, 110403b705cfSriastradh unsigned short *w, unsigned short *h, 110503b705cfSriastradh int *pitches, int *offsets 110603b705cfSriastradh){ 110703b705cfSriastradh int size, tmp; 110803b705cfSriastradh 110903b705cfSriastradh if(*w > IMAGE_MAX_WIDTH) *w = IMAGE_MAX_WIDTH; 111003b705cfSriastradh if(*h > IMAGE_MAX_HEIGHT) *h = IMAGE_MAX_HEIGHT; 111103b705cfSriastradh 111203b705cfSriastradh *w = (*w + 1) & ~1; 111303b705cfSriastradh if(offsets) offsets[0] = 0; 111403b705cfSriastradh 111503b705cfSriastradh switch(id) { 111603b705cfSriastradh /* IA44 is for XvMC only */ 111703b705cfSriastradh case FOURCC_IA44: 111803b705cfSriastradh case FOURCC_AI44: 111903b705cfSriastradh if(pitches) pitches[0] = *w; 112003b705cfSriastradh size = *w * *h; 112103b705cfSriastradh break; 112203b705cfSriastradh case FOURCC_YV12: 112303b705cfSriastradh case FOURCC_I420: 112403b705cfSriastradh *h = (*h + 1) & ~1; 112503b705cfSriastradh size = (*w + 3) & ~3; 112603b705cfSriastradh if(pitches) pitches[0] = size; 112703b705cfSriastradh size *= *h; 112803b705cfSriastradh if(offsets) offsets[1] = size; 112903b705cfSriastradh tmp = ((*w >> 1) + 3) & ~3; 113003b705cfSriastradh if(pitches) pitches[1] = pitches[2] = tmp; 113103b705cfSriastradh tmp *= (*h >> 1); 113203b705cfSriastradh size += tmp; 113303b705cfSriastradh if(offsets) offsets[2] = size; 113403b705cfSriastradh size += tmp; 113503b705cfSriastradh break; 113603b705cfSriastradh case FOURCC_UYVY: 113703b705cfSriastradh case FOURCC_YUY2: 113803b705cfSriastradh default: 113903b705cfSriastradh size = *w << 1; 114003b705cfSriastradh if(pitches) pitches[0] = size; 114103b705cfSriastradh size *= *h; 114203b705cfSriastradh break; 114303b705cfSriastradh } 114403b705cfSriastradh 114503b705cfSriastradh return size; 114603b705cfSriastradh} 114703b705cfSriastradh 1148fe8aea9eSmrg#if !HAVE_NOTIFY_FD 114903b705cfSriastradhstatic void 115003b705cfSriastradhI810BlockHandler (BLOCKHANDLER_ARGS_DECL) 115103b705cfSriastradh{ 115203b705cfSriastradh SCREEN_PTR(arg); 115303b705cfSriastradh ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 115403b705cfSriastradh I810Ptr pI810 = I810PTR(pScrn); 115503b705cfSriastradh I810PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 115603b705cfSriastradh I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 115703b705cfSriastradh 115803b705cfSriastradh screen->BlockHandler = pI810->BlockHandler; 115903b705cfSriastradh 116003b705cfSriastradh (*screen->BlockHandler) (BLOCKHANDLER_ARGS); 116103b705cfSriastradh 116203b705cfSriastradh screen->BlockHandler = I810BlockHandler; 116303b705cfSriastradh 116403b705cfSriastradh if(pPriv->videoStatus & TIMER_MASK) { 116503b705cfSriastradh UpdateCurrentTime(); 116603b705cfSriastradh if(pPriv->videoStatus & OFF_TIMER) { 116703b705cfSriastradh if(pPriv->offTime < currentTime.milliseconds) { 116803b705cfSriastradh /* Turn off the overlay */ 116903b705cfSriastradh overlay->OV0CMD &= 0xFFFFFFFE; 117003b705cfSriastradh OVERLAY_UPDATE(pI810->OverlayPhysical); 117103b705cfSriastradh 117203b705cfSriastradh pPriv->videoStatus = FREE_TIMER; 117303b705cfSriastradh pPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 117403b705cfSriastradh } 117503b705cfSriastradh } else { /* FREE_TIMER */ 117603b705cfSriastradh if(pPriv->freeTime < currentTime.milliseconds) { 117703b705cfSriastradh if(pPriv->linear) { 117803b705cfSriastradh xf86FreeOffscreenLinear(pPriv->linear); 117903b705cfSriastradh pPriv->linear = NULL; 118003b705cfSriastradh } 118103b705cfSriastradh pPriv->videoStatus = 0; 118203b705cfSriastradh } 118303b705cfSriastradh } 118403b705cfSriastradh } 118503b705cfSriastradh} 1186fe8aea9eSmrg#else 1187fe8aea9eSmrgstatic void 1188fe8aea9eSmrgI810BlockHandler(void *data, void *_timeout) 1189fe8aea9eSmrg{ 1190fe8aea9eSmrg ScrnInfoPtr pScrn = data; 1191fe8aea9eSmrg I810Ptr pI810 = I810PTR(pScrn); 1192fe8aea9eSmrg I810PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); 1193fe8aea9eSmrg I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 1194fe8aea9eSmrg 1195fe8aea9eSmrg if(pPriv->videoStatus & TIMER_MASK) { 1196fe8aea9eSmrg UpdateCurrentTime(); 1197fe8aea9eSmrg if(pPriv->videoStatus & OFF_TIMER) { 1198fe8aea9eSmrg if(pPriv->offTime < currentTime.milliseconds) { 1199fe8aea9eSmrg /* Turn off the overlay */ 1200fe8aea9eSmrg overlay->OV0CMD &= 0xFFFFFFFE; 1201fe8aea9eSmrg OVERLAY_UPDATE(pI810->OverlayPhysical); 1202fe8aea9eSmrg 1203fe8aea9eSmrg pPriv->videoStatus = FREE_TIMER; 1204fe8aea9eSmrg pPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 1205fe8aea9eSmrg } 1206fe8aea9eSmrg } else { /* FREE_TIMER */ 1207fe8aea9eSmrg if(pPriv->freeTime < currentTime.milliseconds) { 1208fe8aea9eSmrg if(pPriv->linear) { 1209fe8aea9eSmrg xf86FreeOffscreenLinear(pPriv->linear); 1210fe8aea9eSmrg pPriv->linear = NULL; 1211fe8aea9eSmrg } 1212fe8aea9eSmrg pPriv->videoStatus = 0; 1213fe8aea9eSmrg } 1214fe8aea9eSmrg } 1215fe8aea9eSmrg } 1216fe8aea9eSmrg} 1217fe8aea9eSmrg#endif 121803b705cfSriastradh 121903b705cfSriastradh 122003b705cfSriastradh/*************************************************************************** 122103b705cfSriastradh * Offscreen Images 122203b705cfSriastradh ***************************************************************************/ 122303b705cfSriastradh 122403b705cfSriastradhtypedef struct { 122503b705cfSriastradh FBLinearPtr linear; 122603b705cfSriastradh Bool isOn; 122703b705cfSriastradh} OffscreenPrivRec, * OffscreenPrivPtr; 122803b705cfSriastradh 122903b705cfSriastradhstatic int 123003b705cfSriastradhI810AllocateSurface( 123103b705cfSriastradh ScrnInfoPtr pScrn, 123203b705cfSriastradh int id, 123303b705cfSriastradh unsigned short w, 123403b705cfSriastradh unsigned short h, 123503b705cfSriastradh XF86SurfacePtr surface 123603b705cfSriastradh){ 123703b705cfSriastradh FBLinearPtr linear; 123803b705cfSriastradh int pitch, size, bpp; 123903b705cfSriastradh OffscreenPrivPtr pPriv; 124003b705cfSriastradh I810Ptr pI810 = I810PTR(pScrn); 124103b705cfSriastradh 124203b705cfSriastradh if((w > 1024) || (h > 1024)) 124303b705cfSriastradh return BadAlloc; 124403b705cfSriastradh 124503b705cfSriastradh w = ALIGN(w, 2); 124603b705cfSriastradh pitch = ALIGN((w << 1), 16); 124703b705cfSriastradh bpp = pScrn->bitsPerPixel >> 3; 124803b705cfSriastradh size = ((pitch * h) + bpp - 1) / bpp; 124903b705cfSriastradh 125003b705cfSriastradh if(!(linear = I810AllocateMemory(pScrn, NULL, size))) 125103b705cfSriastradh return BadAlloc; 125203b705cfSriastradh 125303b705cfSriastradh surface->width = w; 125403b705cfSriastradh surface->height = h; 125503b705cfSriastradh 125603b705cfSriastradh if(!(surface->pitches = malloc(sizeof(int)))) { 125703b705cfSriastradh xf86FreeOffscreenLinear(linear); 125803b705cfSriastradh return BadAlloc; 125903b705cfSriastradh } 126003b705cfSriastradh if(!(surface->offsets = malloc(sizeof(int)))) { 126103b705cfSriastradh free(surface->pitches); 126203b705cfSriastradh xf86FreeOffscreenLinear(linear); 126303b705cfSriastradh return BadAlloc; 126403b705cfSriastradh } 126503b705cfSriastradh if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) { 126603b705cfSriastradh free(surface->pitches); 126703b705cfSriastradh free(surface->offsets); 126803b705cfSriastradh xf86FreeOffscreenLinear(linear); 126903b705cfSriastradh return BadAlloc; 127003b705cfSriastradh } 127103b705cfSriastradh 127203b705cfSriastradh pPriv->linear = linear; 127303b705cfSriastradh pPriv->isOn = FALSE; 127403b705cfSriastradh 127503b705cfSriastradh surface->pScrn = pScrn; 127603b705cfSriastradh surface->id = id; 127703b705cfSriastradh surface->pitches[0] = pitch; 127803b705cfSriastradh surface->offsets[0] = linear->offset * bpp; 127903b705cfSriastradh surface->devPrivate.ptr = (pointer)pPriv; 128003b705cfSriastradh 128103b705cfSriastradh memset(pI810->FbBase + surface->offsets[0],0,size); 128203b705cfSriastradh 128303b705cfSriastradh return Success; 128403b705cfSriastradh} 128503b705cfSriastradh 128603b705cfSriastradhstatic int 128703b705cfSriastradhI810StopSurface( 128803b705cfSriastradh XF86SurfacePtr surface 128903b705cfSriastradh){ 129003b705cfSriastradh OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 129103b705cfSriastradh 129203b705cfSriastradh if(pPriv->isOn) { 129303b705cfSriastradh I810Ptr pI810 = I810PTR(surface->pScrn); 129403b705cfSriastradh 129503b705cfSriastradh I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); 129603b705cfSriastradh 129703b705cfSriastradh overlay->OV0CMD &= 0xFFFFFFFE; 129803b705cfSriastradh OVERLAY_UPDATE(pI810->OverlayPhysical); 129903b705cfSriastradh 130003b705cfSriastradh pPriv->isOn = FALSE; 130103b705cfSriastradh } 130203b705cfSriastradh 130303b705cfSriastradh return Success; 130403b705cfSriastradh} 130503b705cfSriastradh 130603b705cfSriastradh 130703b705cfSriastradhstatic int 130803b705cfSriastradhI810FreeSurface( 130903b705cfSriastradh XF86SurfacePtr surface 131003b705cfSriastradh){ 131103b705cfSriastradh OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 131203b705cfSriastradh 131303b705cfSriastradh if(pPriv->isOn) { 131403b705cfSriastradh I810StopSurface(surface); 131503b705cfSriastradh } 131603b705cfSriastradh xf86FreeOffscreenLinear(pPriv->linear); 131703b705cfSriastradh free(surface->pitches); 131803b705cfSriastradh free(surface->offsets); 131903b705cfSriastradh free(surface->devPrivate.ptr); 132003b705cfSriastradh 132103b705cfSriastradh return Success; 132203b705cfSriastradh} 132303b705cfSriastradh 132403b705cfSriastradhstatic int 132503b705cfSriastradhI810GetSurfaceAttribute( 132603b705cfSriastradh ScrnInfoPtr pScrn, 132703b705cfSriastradh Atom attribute, 132803b705cfSriastradh INT32 *value 132903b705cfSriastradh){ 133003b705cfSriastradh return I810GetPortAttribute(pScrn, attribute, value, GET_PORT_PRIVATE(pScrn)); 133103b705cfSriastradh} 133203b705cfSriastradh 133303b705cfSriastradhstatic int 133403b705cfSriastradhI810SetSurfaceAttribute( 133503b705cfSriastradh ScrnInfoPtr pScrn, 133603b705cfSriastradh Atom attribute, 133703b705cfSriastradh INT32 value 133803b705cfSriastradh){ 133903b705cfSriastradh return I810SetPortAttribute(pScrn, attribute, value, GET_PORT_PRIVATE(pScrn)); 134003b705cfSriastradh} 134103b705cfSriastradh 134203b705cfSriastradh 134303b705cfSriastradhstatic int 134403b705cfSriastradhI810DisplaySurface( 134503b705cfSriastradh XF86SurfacePtr surface, 134603b705cfSriastradh short src_x, short src_y, 134703b705cfSriastradh short drw_x, short drw_y, 134803b705cfSriastradh short src_w, short src_h, 134903b705cfSriastradh short drw_w, short drw_h, 135003b705cfSriastradh RegionPtr clipBoxes 135103b705cfSriastradh){ 135203b705cfSriastradh OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; 135303b705cfSriastradh ScrnInfoPtr pScrn = surface->pScrn; 135403b705cfSriastradh I810Ptr pI810 = I810PTR(pScrn); 135503b705cfSriastradh I810PortPrivPtr pI810Priv = GET_PORT_PRIVATE(pScrn); 135603b705cfSriastradh 135703b705cfSriastradh INT32 x1, y1, x2, y2; 135803b705cfSriastradh INT32 loops = 0; 135903b705cfSriastradh BoxRec dstBox; 136003b705cfSriastradh 136103b705cfSriastradh x1 = src_x; 136203b705cfSriastradh x2 = src_x + src_w; 136303b705cfSriastradh y1 = src_y; 136403b705cfSriastradh y2 = src_y + src_h; 136503b705cfSriastradh 136603b705cfSriastradh dstBox.x1 = drw_x; 136703b705cfSriastradh dstBox.x2 = drw_x + drw_w; 136803b705cfSriastradh dstBox.y1 = drw_y; 136903b705cfSriastradh dstBox.y2 = drw_y + drw_h; 137003b705cfSriastradh 137103b705cfSriastradh I810ClipVideo(&dstBox, &x1, &x2, &y1, &y2, 137203b705cfSriastradh REGION_EXTENTS(screenInfo.screens[0], clipBoxes), 137303b705cfSriastradh surface->width, surface->height); 137403b705cfSriastradh 137503b705cfSriastradh /* 137603b705cfSriastradh * Fix for 4 pixel granularity of AdjustFrame 137703b705cfSriastradh * unless boarder is clipped by frame 137803b705cfSriastradh */ 137903b705cfSriastradh dstBox.x1 -= (pScrn->frameX0 & 138003b705cfSriastradh ((dstBox.x1 == pScrn->frameX0) ? ~0x0UL : ~0x3UL)); 138103b705cfSriastradh dstBox.x2 -= (pScrn->frameX0 & ~0x3); 138203b705cfSriastradh dstBox.y1 -= pScrn->frameY0; 138303b705cfSriastradh dstBox.y2 -= pScrn->frameY0; 138403b705cfSriastradh 138503b705cfSriastradh /* fixup pointers */ 138603b705cfSriastradh pI810Priv->YBuf0offset = surface->offsets[0]; 138703b705cfSriastradh pI810Priv->YBuf1offset = pI810Priv->YBuf0offset; 138803b705cfSriastradh 138903b705cfSriastradh /* wait for the last rendered buffer to be flipped in */ 139003b705cfSriastradh while (((INREG(DOV0STA)&0x00100000)>>20) != pI810Priv->currentBuf) { 139103b705cfSriastradh if(loops == 200000) { 139203b705cfSriastradh xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Overlay Lockup\n"); 139303b705cfSriastradh break; 139403b705cfSriastradh } 139503b705cfSriastradh loops++; 139603b705cfSriastradh } 139703b705cfSriastradh 139803b705cfSriastradh /* buffer swap */ 139903b705cfSriastradh if (pI810Priv->currentBuf == 0) 140003b705cfSriastradh pI810Priv->currentBuf = 1; 140103b705cfSriastradh else 140203b705cfSriastradh pI810Priv->currentBuf = 0; 140303b705cfSriastradh 140403b705cfSriastradh I810ResetVideo(pScrn); 140503b705cfSriastradh 140603b705cfSriastradh I810DisplayVideo(pScrn, surface->id, surface->width, surface->height, 140703b705cfSriastradh surface->pitches[0], x1, y1, x2, y2, &dstBox, 140803b705cfSriastradh src_w, src_h, drw_w, drw_h); 140903b705cfSriastradh 141003b705cfSriastradh xf86XVFillKeyHelper(pScrn->pScreen, pI810Priv->colorKey, clipBoxes); 141103b705cfSriastradh 141203b705cfSriastradh pPriv->isOn = TRUE; 141303b705cfSriastradh /* we've prempted the XvImage stream so set its free timer */ 141403b705cfSriastradh if(pI810Priv->videoStatus & CLIENT_VIDEO_ON) { 141503b705cfSriastradh REGION_EMPTY(pScrn->screen, & pI810Priv->clip); 141603b705cfSriastradh UpdateCurrentTime(); 141703b705cfSriastradh pI810Priv->videoStatus = FREE_TIMER; 141803b705cfSriastradh pI810Priv->freeTime = currentTime.milliseconds + FREE_DELAY; 141903b705cfSriastradh } 142003b705cfSriastradh 142103b705cfSriastradh return Success; 142203b705cfSriastradh} 142303b705cfSriastradh 142403b705cfSriastradh 142503b705cfSriastradhstatic void 142603b705cfSriastradhI810InitOffscreenImages(ScreenPtr screen) 142703b705cfSriastradh{ 142803b705cfSriastradh XF86OffscreenImagePtr offscreenImages; 142903b705cfSriastradh 143003b705cfSriastradh /* need to free this someplace */ 143103b705cfSriastradh if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec)))) { 143203b705cfSriastradh return; 143303b705cfSriastradh } 143403b705cfSriastradh 143503b705cfSriastradh offscreenImages[0].image = &Images[0]; 143603b705cfSriastradh offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | 143703b705cfSriastradh VIDEO_CLIP_TO_VIEWPORT; 143803b705cfSriastradh offscreenImages[0].alloc_surface = I810AllocateSurface; 143903b705cfSriastradh offscreenImages[0].free_surface = I810FreeSurface; 144003b705cfSriastradh offscreenImages[0].display = I810DisplaySurface; 144103b705cfSriastradh offscreenImages[0].stop = I810StopSurface; 144203b705cfSriastradh offscreenImages[0].setAttribute = I810SetSurfaceAttribute; 144303b705cfSriastradh offscreenImages[0].getAttribute = I810GetSurfaceAttribute; 144403b705cfSriastradh offscreenImages[0].max_width = 1024; 144503b705cfSriastradh offscreenImages[0].max_height = 1024; 144603b705cfSriastradh offscreenImages[0].num_attributes = 1; 144703b705cfSriastradh offscreenImages[0].attributes = Attributes; 144803b705cfSriastradh 144903b705cfSriastradh if (!xf86XVRegisterOffscreenImages(screen, offscreenImages, 1)) 145003b705cfSriastradh free(offscreenImages); 145103b705cfSriastradh} 145203b705cfSriastradh 1453