intel_video.c revision 03b705cf
103b705cfSriastradh/*************************************************************************** 203b705cfSriastradh 303b705cfSriastradh Copyright 2000 Intel Corporation. All Rights Reserved. 403b705cfSriastradh 503b705cfSriastradh Permission is hereby granted, free of charge, to any person obtaining a 603b705cfSriastradh copy of this software and associated documentation files (the 703b705cfSriastradh "Software"), to deal in the Software without restriction, including 803b705cfSriastradh without limitation the rights to use, copy, modify, merge, publish, 903b705cfSriastradh distribute, sub license, and/or sell copies of the Software, and to 1003b705cfSriastradh permit persons to whom the Software is furnished to do so, subject to 1103b705cfSriastradh the following conditions: 1203b705cfSriastradh 1303b705cfSriastradh The above copyright notice and this permission notice (including the 1403b705cfSriastradh next paragraph) shall be included in all copies or substantial portions 1503b705cfSriastradh of the Software. 1603b705cfSriastradh 1703b705cfSriastradh THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1803b705cfSriastradh OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1903b705cfSriastradh MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 2003b705cfSriastradh IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 2103b705cfSriastradh DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 2203b705cfSriastradh OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 2303b705cfSriastradh THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2403b705cfSriastradh 2503b705cfSriastradh **************************************************************************/ 2603b705cfSriastradh 2703b705cfSriastradh/* 2803b705cfSriastradh * i830_video.c: i830/i845 Xv driver. 2903b705cfSriastradh * 3003b705cfSriastradh * Copyright © 2002 by Alan Hourihane and David Dawes 3103b705cfSriastradh * 3203b705cfSriastradh * Authors: 3303b705cfSriastradh * Alan Hourihane <alanh@tungstengraphics.com> 3403b705cfSriastradh * David Dawes <dawes@xfree86.org> 3503b705cfSriastradh * 3603b705cfSriastradh * Derived from i810 Xv driver: 3703b705cfSriastradh * 3803b705cfSriastradh * Authors of i810 code: 3903b705cfSriastradh * Jonathan Bian <jonathan.bian@intel.com> 4003b705cfSriastradh * Offscreen Images: 4103b705cfSriastradh * Matt Sottek <matthew.j.sottek@intel.com> 4203b705cfSriastradh */ 4303b705cfSriastradh 4403b705cfSriastradh/* 4503b705cfSriastradh * XXX Could support more formats. 4603b705cfSriastradh */ 4703b705cfSriastradh 4803b705cfSriastradh#ifdef HAVE_CONFIG_H 4903b705cfSriastradh#include "config.h" 5003b705cfSriastradh#endif 5103b705cfSriastradh 5203b705cfSriastradh#include <inttypes.h> 5303b705cfSriastradh#include <math.h> 5403b705cfSriastradh#include <string.h> 5503b705cfSriastradh#include <assert.h> 5603b705cfSriastradh#include <errno.h> 5703b705cfSriastradh 5803b705cfSriastradh#include "xf86.h" 5903b705cfSriastradh#include "xf86_OSproc.h" 6003b705cfSriastradh#include "compiler.h" 6103b705cfSriastradh#include "xf86Pci.h" 6203b705cfSriastradh#include "xf86fbman.h" 6303b705cfSriastradh#include "xf86drm.h" 6403b705cfSriastradh#include "regionstr.h" 6503b705cfSriastradh#include "randrstr.h" 6603b705cfSriastradh#include "windowstr.h" 6703b705cfSriastradh#include "damage.h" 6803b705cfSriastradh#include "intel.h" 6903b705cfSriastradh#include "intel_video.h" 7003b705cfSriastradh#include "i830_reg.h" 7103b705cfSriastradh#include "xf86xv.h" 7203b705cfSriastradh#include <X11/extensions/Xv.h> 7303b705cfSriastradh#include "dixstruct.h" 7403b705cfSriastradh#include "fourcc.h" 7503b705cfSriastradh 7603b705cfSriastradh#ifdef INTEL_XVMC 7703b705cfSriastradh#define _INTEL_XVMC_SERVER_ 7803b705cfSriastradh#include "intel_xvmc.h" 7903b705cfSriastradh#endif 8003b705cfSriastradh 8103b705cfSriastradh#define OFF_DELAY 250 /* milliseconds */ 8203b705cfSriastradh 8303b705cfSriastradh#define OFF_TIMER 0x01 8403b705cfSriastradh#define CLIENT_VIDEO_ON 0x02 8503b705cfSriastradh 8603b705cfSriastradhstatic XF86VideoAdaptorPtr I830SetupImageVideoOverlay(ScreenPtr); 8703b705cfSriastradhstatic XF86VideoAdaptorPtr I830SetupImageVideoTextured(ScreenPtr); 8803b705cfSriastradhstatic void I830StopVideo(ScrnInfoPtr, pointer, Bool); 8903b705cfSriastradhstatic int I830SetPortAttributeOverlay(ScrnInfoPtr, Atom, INT32, pointer); 9003b705cfSriastradhstatic int I830SetPortAttributeTextured(ScrnInfoPtr, Atom, INT32, pointer); 9103b705cfSriastradhstatic int I830GetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer); 9203b705cfSriastradhstatic void I830QueryBestSize(ScrnInfoPtr, Bool, 9303b705cfSriastradh short, short, short, short, unsigned int *, 9403b705cfSriastradh unsigned int *, pointer); 9503b705cfSriastradhstatic int I830PutImageTextured(ScrnInfoPtr, short, short, short, short, short, short, 9603b705cfSriastradh short, short, int, unsigned char *, short, short, 9703b705cfSriastradh Bool, RegionPtr, pointer, DrawablePtr); 9803b705cfSriastradhstatic int I830PutImageOverlay(ScrnInfoPtr, short, short, short, short, short, short, 9903b705cfSriastradh short, short, int, unsigned char *, short, short, 10003b705cfSriastradh Bool, RegionPtr, pointer, DrawablePtr); 10103b705cfSriastradhstatic int I830QueryImageAttributes(ScrnInfoPtr, int, unsigned short *, 10203b705cfSriastradh unsigned short *, int *, int *); 10303b705cfSriastradh 10403b705cfSriastradh#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 10503b705cfSriastradh 10603b705cfSriastradhstatic Atom xvBrightness, xvContrast, xvSaturation, xvColorKey, xvPipe; 10703b705cfSriastradhstatic Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5; 10803b705cfSriastradhstatic Atom xvSyncToVblank; 10903b705cfSriastradh 11003b705cfSriastradh/* Limits for the overlay/textured video source sizes. The documented hardware 11103b705cfSriastradh * limits are 2048x2048 or better for overlay and both of our textured video 11203b705cfSriastradh * implementations. Additionally, on the 830 and 845, larger sizes resulted in 11303b705cfSriastradh * the card hanging, so we keep the limits lower there. 11403b705cfSriastradh */ 11503b705cfSriastradh#define IMAGE_MAX_WIDTH 2048 11603b705cfSriastradh#define IMAGE_MAX_HEIGHT 2048 11703b705cfSriastradh#define IMAGE_MAX_WIDTH_LEGACY 1024 11803b705cfSriastradh#define IMAGE_MAX_HEIGHT_LEGACY 1088 11903b705cfSriastradh 12003b705cfSriastradh/* overlay debugging printf function */ 12103b705cfSriastradh#if 0 12203b705cfSriastradh#define OVERLAY_DEBUG ErrorF 12303b705cfSriastradh#else 12403b705cfSriastradh#define OVERLAY_DEBUG if (0) ErrorF 12503b705cfSriastradh#endif 12603b705cfSriastradh 12703b705cfSriastradh/* client libraries expect an encoding */ 12803b705cfSriastradhstatic const XF86VideoEncodingRec DummyEncoding[1] = { 12903b705cfSriastradh { 13003b705cfSriastradh 0, 13103b705cfSriastradh "XV_IMAGE", 13203b705cfSriastradh IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, 13303b705cfSriastradh {1, 1} 13403b705cfSriastradh } 13503b705cfSriastradh}; 13603b705cfSriastradh 13703b705cfSriastradh#define NUM_FORMATS 3 13803b705cfSriastradh 13903b705cfSriastradhstatic XF86VideoFormatRec Formats[NUM_FORMATS] = { 14003b705cfSriastradh {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 14103b705cfSriastradh}; 14203b705cfSriastradh 14303b705cfSriastradh#define NUM_ATTRIBUTES 5 14403b705cfSriastradhstatic XF86AttributeRec Attributes[NUM_ATTRIBUTES] = { 14503b705cfSriastradh {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 14603b705cfSriastradh {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, 14703b705cfSriastradh {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}, 14803b705cfSriastradh {XvSettable | XvGettable, 0, 1023, "XV_SATURATION"}, 14903b705cfSriastradh {XvSettable | XvGettable, -1, 1, "XV_PIPE"} 15003b705cfSriastradh}; 15103b705cfSriastradh 15203b705cfSriastradh#define GAMMA_ATTRIBUTES 6 15303b705cfSriastradhstatic XF86AttributeRec GammaAttributes[GAMMA_ATTRIBUTES] = { 15403b705cfSriastradh {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA0"}, 15503b705cfSriastradh {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA1"}, 15603b705cfSriastradh {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA2"}, 15703b705cfSriastradh {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA3"}, 15803b705cfSriastradh {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA4"}, 15903b705cfSriastradh {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA5"} 16003b705cfSriastradh}; 16103b705cfSriastradh 16203b705cfSriastradh#ifdef INTEL_XVMC 16303b705cfSriastradh#define NUM_IMAGES 5 16403b705cfSriastradh#define XVMC_IMAGE 1 16503b705cfSriastradh#else 16603b705cfSriastradh#define NUM_IMAGES 4 16703b705cfSriastradh#define XVMC_IMAGE 0 16803b705cfSriastradh#endif 16903b705cfSriastradh 17003b705cfSriastradhstatic XF86ImageRec Images[NUM_IMAGES] = { 17103b705cfSriastradh XVIMAGE_YUY2, 17203b705cfSriastradh XVIMAGE_YV12, 17303b705cfSriastradh XVIMAGE_I420, 17403b705cfSriastradh XVIMAGE_UYVY, 17503b705cfSriastradh#ifdef INTEL_XVMC 17603b705cfSriastradh { 17703b705cfSriastradh /* 17803b705cfSriastradh * Below, a dummy picture type that is used in XvPutImage only to do 17903b705cfSriastradh * an overlay update. Introduced for the XvMC client lib. 18003b705cfSriastradh * Defined to have a zero data size. 18103b705cfSriastradh */ 18203b705cfSriastradh FOURCC_XVMC, 18303b705cfSriastradh XvYUV, 18403b705cfSriastradh LSBFirst, 18503b705cfSriastradh {'X', 'V', 'M', 'C', 18603b705cfSriastradh 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0xAA, 0x00, 18703b705cfSriastradh 0x38, 0x9B, 0x71}, 18803b705cfSriastradh 12, 18903b705cfSriastradh XvPlanar, 19003b705cfSriastradh 3, 19103b705cfSriastradh 0, 0, 0, 0, 19203b705cfSriastradh 8, 8, 8, 19303b705cfSriastradh 1, 2, 2, 19403b705cfSriastradh 1, 2, 2, 19503b705cfSriastradh {'Y', 'V', 'U', 19603b705cfSriastradh 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19703b705cfSriastradh 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19803b705cfSriastradh XvTopToBottom}, 19903b705cfSriastradh#endif 20003b705cfSriastradh}; 20103b705cfSriastradh 20203b705cfSriastradh/* kernel modesetting overlay functions */ 20303b705cfSriastradhstatic Bool intel_has_overlay(intel_screen_private *intel) 20403b705cfSriastradh{ 20503b705cfSriastradh struct drm_i915_getparam gp; 20603b705cfSriastradh int has_overlay = 0; 20703b705cfSriastradh int ret; 20803b705cfSriastradh 20903b705cfSriastradh gp.param = I915_PARAM_HAS_OVERLAY; 21003b705cfSriastradh gp.value = &has_overlay; 21103b705cfSriastradh ret = drmCommandWriteRead(intel->drmSubFD, DRM_I915_GETPARAM, &gp, sizeof(gp)); 21203b705cfSriastradh 21303b705cfSriastradh return ret == 0 && !! has_overlay; 21403b705cfSriastradh} 21503b705cfSriastradh 21603b705cfSriastradhstatic Bool intel_overlay_update_attrs(intel_screen_private *intel) 21703b705cfSriastradh{ 21803b705cfSriastradh intel_adaptor_private *adaptor_priv = intel_get_adaptor_private(intel); 21903b705cfSriastradh struct drm_intel_overlay_attrs attrs; 22003b705cfSriastradh 22103b705cfSriastradh attrs.flags = I915_OVERLAY_UPDATE_ATTRS; 22203b705cfSriastradh attrs.brightness = adaptor_priv->brightness; 22303b705cfSriastradh attrs.contrast = adaptor_priv->contrast; 22403b705cfSriastradh attrs.saturation = adaptor_priv->saturation; 22503b705cfSriastradh attrs.color_key = adaptor_priv->colorKey; 22603b705cfSriastradh attrs.gamma0 = adaptor_priv->gamma0; 22703b705cfSriastradh attrs.gamma1 = adaptor_priv->gamma1; 22803b705cfSriastradh attrs.gamma2 = adaptor_priv->gamma2; 22903b705cfSriastradh attrs.gamma3 = adaptor_priv->gamma3; 23003b705cfSriastradh attrs.gamma4 = adaptor_priv->gamma4; 23103b705cfSriastradh attrs.gamma5 = adaptor_priv->gamma5; 23203b705cfSriastradh 23303b705cfSriastradh return drmCommandWriteRead(intel->drmSubFD, DRM_I915_OVERLAY_ATTRS, 23403b705cfSriastradh &attrs, sizeof(attrs)) == 0; 23503b705cfSriastradh} 23603b705cfSriastradh 23703b705cfSriastradhstatic void intel_overlay_off(intel_screen_private *intel) 23803b705cfSriastradh{ 23903b705cfSriastradh struct drm_intel_overlay_put_image request; 24003b705cfSriastradh int ret; 24103b705cfSriastradh 24203b705cfSriastradh request.flags = 0; 24303b705cfSriastradh 24403b705cfSriastradh ret = drmCommandWrite(intel->drmSubFD, DRM_I915_OVERLAY_PUT_IMAGE, 24503b705cfSriastradh &request, sizeof(request)); 24603b705cfSriastradh (void) ret; 24703b705cfSriastradh} 24803b705cfSriastradh 24903b705cfSriastradhstatic Bool 25003b705cfSriastradhintel_overlay_put_image(intel_screen_private *intel, 25103b705cfSriastradh xf86CrtcPtr crtc, 25203b705cfSriastradh int id, short width, short height, 25303b705cfSriastradh int dstPitch, int dstPitch2, 25403b705cfSriastradh BoxPtr dstBox, short src_w, short src_h, short drw_w, 25503b705cfSriastradh short drw_h) 25603b705cfSriastradh{ 25703b705cfSriastradh intel_adaptor_private *adaptor_priv = intel_get_adaptor_private(intel); 25803b705cfSriastradh struct drm_intel_overlay_put_image request; 25903b705cfSriastradh int ret; 26003b705cfSriastradh int planar = is_planar_fourcc(id); 26103b705cfSriastradh float scale; 26203b705cfSriastradh dri_bo *tmp; 26303b705cfSriastradh 26403b705cfSriastradh request.flags = I915_OVERLAY_ENABLE; 26503b705cfSriastradh 26603b705cfSriastradh request.bo_handle = adaptor_priv->buf->handle; 26703b705cfSriastradh if (planar) { 26803b705cfSriastradh request.stride_Y = dstPitch2; 26903b705cfSriastradh request.stride_UV = dstPitch; 27003b705cfSriastradh } else { 27103b705cfSriastradh request.stride_Y = dstPitch; 27203b705cfSriastradh request.stride_UV = 0; 27303b705cfSriastradh } 27403b705cfSriastradh request.offset_Y = adaptor_priv->YBufOffset; 27503b705cfSriastradh request.offset_U = adaptor_priv->UBufOffset; 27603b705cfSriastradh request.offset_V = adaptor_priv->VBufOffset; 27703b705cfSriastradh OVERLAY_DEBUG("off_Y: %i, off_U: %i, off_V: %i\n", request.offset_Y, 27803b705cfSriastradh request.offset_U, request.offset_V); 27903b705cfSriastradh 28003b705cfSriastradh request.crtc_id = intel_crtc_id(crtc); 28103b705cfSriastradh request.dst_x = dstBox->x1; 28203b705cfSriastradh request.dst_y = dstBox->y1; 28303b705cfSriastradh request.dst_width = dstBox->x2 - dstBox->x1; 28403b705cfSriastradh request.dst_height = dstBox->y2 - dstBox->y1; 28503b705cfSriastradh 28603b705cfSriastradh request.src_width = width; 28703b705cfSriastradh request.src_height = height; 28803b705cfSriastradh /* adjust src dimensions */ 28903b705cfSriastradh if (request.dst_height > 1) { 29003b705cfSriastradh scale = ((float)request.dst_height - 1) / ((float)drw_h - 1); 29103b705cfSriastradh request.src_scan_height = src_h * scale; 29203b705cfSriastradh } else 29303b705cfSriastradh request.src_scan_height = 1; 29403b705cfSriastradh 29503b705cfSriastradh if (request.dst_width > 1) { 29603b705cfSriastradh scale = ((float)request.dst_width - 1) / ((float)drw_w - 1); 29703b705cfSriastradh request.src_scan_width = src_w * scale; 29803b705cfSriastradh } else 29903b705cfSriastradh request.src_scan_width = 1; 30003b705cfSriastradh 30103b705cfSriastradh if (planar) { 30203b705cfSriastradh request.flags |= I915_OVERLAY_YUV_PLANAR | I915_OVERLAY_YUV420; 30303b705cfSriastradh } else { 30403b705cfSriastradh request.flags |= I915_OVERLAY_YUV_PACKED | I915_OVERLAY_YUV422; 30503b705cfSriastradh if (id == FOURCC_UYVY) 30603b705cfSriastradh request.flags |= I915_OVERLAY_Y_SWAP; 30703b705cfSriastradh } 30803b705cfSriastradh 30903b705cfSriastradh ret = drmCommandWrite(intel->drmSubFD, DRM_I915_OVERLAY_PUT_IMAGE, 31003b705cfSriastradh &request, sizeof(request)); 31103b705cfSriastradh if (ret) 31203b705cfSriastradh return FALSE; 31303b705cfSriastradh 31403b705cfSriastradh if (!adaptor_priv->reusable) { 31503b705cfSriastradh drm_intel_bo_unreference(adaptor_priv->buf); 31603b705cfSriastradh adaptor_priv->buf = NULL; 31703b705cfSriastradh adaptor_priv->reusable = TRUE; 31803b705cfSriastradh } 31903b705cfSriastradh 32003b705cfSriastradh tmp = adaptor_priv->old_buf[1]; 32103b705cfSriastradh adaptor_priv->old_buf[1] = adaptor_priv->old_buf[0]; 32203b705cfSriastradh adaptor_priv->old_buf[0] = adaptor_priv->buf; 32303b705cfSriastradh adaptor_priv->buf = tmp; 32403b705cfSriastradh 32503b705cfSriastradh return TRUE; 32603b705cfSriastradh} 32703b705cfSriastradh 32803b705cfSriastradhvoid I830InitVideo(ScreenPtr screen) 32903b705cfSriastradh{ 33003b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 33103b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 33203b705cfSriastradh XF86VideoAdaptorPtr *adaptors = NULL, *newAdaptors = NULL; 33303b705cfSriastradh XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL; 33403b705cfSriastradh int num_adaptors = xf86XVListGenericAdaptors(scrn, &adaptors); 33503b705cfSriastradh /* Give our adaptor list enough space for the overlay and/or texture video 33603b705cfSriastradh * adaptors. 33703b705cfSriastradh */ 33803b705cfSriastradh newAdaptors = realloc(adaptors, 33903b705cfSriastradh (num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr)); 34003b705cfSriastradh if (newAdaptors == NULL) { 34103b705cfSriastradh free(adaptors); 34203b705cfSriastradh return; 34303b705cfSriastradh } 34403b705cfSriastradh adaptors = newAdaptors; 34503b705cfSriastradh 34603b705cfSriastradh /* Add the adaptors supported by our hardware. First, set up the atoms 34703b705cfSriastradh * that will be used by both output adaptors. 34803b705cfSriastradh */ 34903b705cfSriastradh xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 35003b705cfSriastradh xvContrast = MAKE_ATOM("XV_CONTRAST"); 35103b705cfSriastradh 35203b705cfSriastradh /* Set up textured video if we can do it at this depth and we are on 35303b705cfSriastradh * supported hardware. 35403b705cfSriastradh */ 35503b705cfSriastradh if (scrn->bitsPerPixel >= 16 && 35603b705cfSriastradh INTEL_INFO(intel)->gen >= 030) { 35703b705cfSriastradh texturedAdaptor = I830SetupImageVideoTextured(screen); 35803b705cfSriastradh if (texturedAdaptor != NULL) { 35903b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, 36003b705cfSriastradh "Set up textured video\n"); 36103b705cfSriastradh } else { 36203b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 36303b705cfSriastradh "Failed to set up textured video\n"); 36403b705cfSriastradh } 36503b705cfSriastradh } 36603b705cfSriastradh 36703b705cfSriastradh /* Set up overlay video if it is available */ 36803b705cfSriastradh intel->use_overlay = intel_has_overlay(intel); 36903b705cfSriastradh if (intel->use_overlay) { 37003b705cfSriastradh overlayAdaptor = I830SetupImageVideoOverlay(screen); 37103b705cfSriastradh if (overlayAdaptor != NULL) { 37203b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, 37303b705cfSriastradh "Set up overlay video\n"); 37403b705cfSriastradh } else { 37503b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 37603b705cfSriastradh "Failed to set up overlay video\n"); 37703b705cfSriastradh } 37803b705cfSriastradh } 37903b705cfSriastradh 38003b705cfSriastradh if (overlayAdaptor && intel->XvPreferOverlay) 38103b705cfSriastradh adaptors[num_adaptors++] = overlayAdaptor; 38203b705cfSriastradh 38303b705cfSriastradh if (texturedAdaptor) 38403b705cfSriastradh adaptors[num_adaptors++] = texturedAdaptor; 38503b705cfSriastradh 38603b705cfSriastradh if (overlayAdaptor && !intel->XvPreferOverlay) 38703b705cfSriastradh adaptors[num_adaptors++] = overlayAdaptor; 38803b705cfSriastradh 38903b705cfSriastradh if (num_adaptors) { 39003b705cfSriastradh xf86XVScreenInit(screen, adaptors, num_adaptors); 39103b705cfSriastradh } else { 39203b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_WARNING, 39303b705cfSriastradh "Disabling Xv because no adaptors could be initialized.\n"); 39403b705cfSriastradh intel->XvEnabled = FALSE; 39503b705cfSriastradh } 39603b705cfSriastradh 39703b705cfSriastradh#ifdef INTEL_XVMC 39803b705cfSriastradh if (texturedAdaptor) 39903b705cfSriastradh intel_xvmc_adaptor_init(screen); 40003b705cfSriastradh#endif 40103b705cfSriastradh free(adaptors); 40203b705cfSriastradh} 40303b705cfSriastradh 40403b705cfSriastradhstatic XF86VideoAdaptorPtr I830SetupImageVideoOverlay(ScreenPtr screen) 40503b705cfSriastradh{ 40603b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 40703b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 40803b705cfSriastradh XF86VideoAdaptorPtr adapt; 40903b705cfSriastradh intel_adaptor_private *adaptor_priv; 41003b705cfSriastradh XF86AttributePtr att; 41103b705cfSriastradh 41203b705cfSriastradh OVERLAY_DEBUG("I830SetupImageVideoOverlay\n"); 41303b705cfSriastradh 41403b705cfSriastradh if (!(adapt = calloc(1, 41503b705cfSriastradh sizeof(XF86VideoAdaptorRec) + 41603b705cfSriastradh sizeof(intel_adaptor_private) + 41703b705cfSriastradh sizeof(DevUnion)))) 41803b705cfSriastradh return NULL; 41903b705cfSriastradh 42003b705cfSriastradh adapt->type = XvWindowMask | XvInputMask | XvImageMask; 42103b705cfSriastradh adapt->flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT */ ; 42203b705cfSriastradh adapt->name = "Intel(R) Video Overlay"; 42303b705cfSriastradh adapt->nEncodings = 1; 42403b705cfSriastradh adapt->pEncodings = xnfalloc(sizeof(DummyEncoding)); 42503b705cfSriastradh memcpy(adapt->pEncodings, DummyEncoding, sizeof(DummyEncoding)); 42603b705cfSriastradh if (IS_845G(intel) || IS_I830(intel)) { 42703b705cfSriastradh adapt->pEncodings->width = IMAGE_MAX_WIDTH_LEGACY; 42803b705cfSriastradh adapt->pEncodings->height = IMAGE_MAX_HEIGHT_LEGACY; 42903b705cfSriastradh } 43003b705cfSriastradh adapt->nFormats = NUM_FORMATS; 43103b705cfSriastradh adapt->pFormats = Formats; 43203b705cfSriastradh adapt->nPorts = 1; 43303b705cfSriastradh adapt->pPortPrivates = (DevUnion *) (&adapt[1]); 43403b705cfSriastradh 43503b705cfSriastradh adaptor_priv = (intel_adaptor_private *)&adapt->pPortPrivates[1]; 43603b705cfSriastradh 43703b705cfSriastradh adapt->pPortPrivates[0].ptr = (pointer) (adaptor_priv); 43803b705cfSriastradh adapt->nAttributes = NUM_ATTRIBUTES; 43903b705cfSriastradh if (INTEL_INFO(intel)->gen >= 030) 44003b705cfSriastradh adapt->nAttributes += GAMMA_ATTRIBUTES; /* has gamma */ 44103b705cfSriastradh adapt->pAttributes = 44203b705cfSriastradh xnfalloc(sizeof(XF86AttributeRec) * adapt->nAttributes); 44303b705cfSriastradh /* Now copy the attributes */ 44403b705cfSriastradh att = adapt->pAttributes; 44503b705cfSriastradh memcpy((char *)att, (char *)Attributes, 44603b705cfSriastradh sizeof(XF86AttributeRec) * NUM_ATTRIBUTES); 44703b705cfSriastradh att += NUM_ATTRIBUTES; 44803b705cfSriastradh if (INTEL_INFO(intel)->gen >= 030) { 44903b705cfSriastradh memcpy((char *)att, (char *)GammaAttributes, 45003b705cfSriastradh sizeof(XF86AttributeRec) * GAMMA_ATTRIBUTES); 45103b705cfSriastradh } 45203b705cfSriastradh adapt->nImages = NUM_IMAGES - XVMC_IMAGE; 45303b705cfSriastradh 45403b705cfSriastradh adapt->pImages = Images; 45503b705cfSriastradh adapt->PutVideo = NULL; 45603b705cfSriastradh adapt->PutStill = NULL; 45703b705cfSriastradh adapt->GetVideo = NULL; 45803b705cfSriastradh adapt->GetStill = NULL; 45903b705cfSriastradh adapt->StopVideo = I830StopVideo; 46003b705cfSriastradh adapt->SetPortAttribute = I830SetPortAttributeOverlay; 46103b705cfSriastradh adapt->GetPortAttribute = I830GetPortAttribute; 46203b705cfSriastradh adapt->QueryBestSize = I830QueryBestSize; 46303b705cfSriastradh adapt->PutImage = I830PutImageOverlay; 46403b705cfSriastradh adapt->QueryImageAttributes = I830QueryImageAttributes; 46503b705cfSriastradh 46603b705cfSriastradh adaptor_priv->textured = FALSE; 46703b705cfSriastradh adaptor_priv->colorKey = intel->colorKey & ((1 << scrn->depth) - 1); 46803b705cfSriastradh adaptor_priv->videoStatus = 0; 46903b705cfSriastradh adaptor_priv->brightness = -19; /* (255/219) * -16 */ 47003b705cfSriastradh adaptor_priv->contrast = 75; /* 255/219 * 64 */ 47103b705cfSriastradh adaptor_priv->saturation = 146; /* 128/112 * 128 */ 47203b705cfSriastradh adaptor_priv->desired_crtc = NULL; 47303b705cfSriastradh adaptor_priv->buf = NULL; 47403b705cfSriastradh adaptor_priv->old_buf[0] = NULL; 47503b705cfSriastradh adaptor_priv->old_buf[1] = NULL; 47603b705cfSriastradh adaptor_priv->gamma5 = 0xc0c0c0; 47703b705cfSriastradh adaptor_priv->gamma4 = 0x808080; 47803b705cfSriastradh adaptor_priv->gamma3 = 0x404040; 47903b705cfSriastradh adaptor_priv->gamma2 = 0x202020; 48003b705cfSriastradh adaptor_priv->gamma1 = 0x101010; 48103b705cfSriastradh adaptor_priv->gamma0 = 0x080808; 48203b705cfSriastradh 48303b705cfSriastradh adaptor_priv->rotation = RR_Rotate_0; 48403b705cfSriastradh 48503b705cfSriastradh /* gotta uninit this someplace */ 48603b705cfSriastradh REGION_NULL(screen, &adaptor_priv->clip); 48703b705cfSriastradh 48803b705cfSriastradh intel->adaptor = adapt; 48903b705cfSriastradh 49003b705cfSriastradh xvColorKey = MAKE_ATOM("XV_COLORKEY"); 49103b705cfSriastradh xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 49203b705cfSriastradh xvContrast = MAKE_ATOM("XV_CONTRAST"); 49303b705cfSriastradh xvSaturation = MAKE_ATOM("XV_SATURATION"); 49403b705cfSriastradh 49503b705cfSriastradh /* Allow the pipe to be switched from pipe A to B when in clone mode */ 49603b705cfSriastradh xvPipe = MAKE_ATOM("XV_PIPE"); 49703b705cfSriastradh 49803b705cfSriastradh if (INTEL_INFO(intel)->gen >= 030) { 49903b705cfSriastradh xvGamma0 = MAKE_ATOM("XV_GAMMA0"); 50003b705cfSriastradh xvGamma1 = MAKE_ATOM("XV_GAMMA1"); 50103b705cfSriastradh xvGamma2 = MAKE_ATOM("XV_GAMMA2"); 50203b705cfSriastradh xvGamma3 = MAKE_ATOM("XV_GAMMA3"); 50303b705cfSriastradh xvGamma4 = MAKE_ATOM("XV_GAMMA4"); 50403b705cfSriastradh xvGamma5 = MAKE_ATOM("XV_GAMMA5"); 50503b705cfSriastradh } 50603b705cfSriastradh 50703b705cfSriastradh intel_overlay_update_attrs(intel); 50803b705cfSriastradh 50903b705cfSriastradh return adapt; 51003b705cfSriastradh} 51103b705cfSriastradh 51203b705cfSriastradhstatic XF86VideoAdaptorPtr I830SetupImageVideoTextured(ScreenPtr screen) 51303b705cfSriastradh{ 51403b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 51503b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 51603b705cfSriastradh XF86VideoAdaptorPtr adapt; 51703b705cfSriastradh intel_adaptor_private *adaptor_privs; 51803b705cfSriastradh DevUnion *devUnions; 51903b705cfSriastradh int nports = 16, i; 52003b705cfSriastradh 52103b705cfSriastradh OVERLAY_DEBUG("I830SetupImageVideoOverlay\n"); 52203b705cfSriastradh 52303b705cfSriastradh adapt = calloc(1, sizeof(XF86VideoAdaptorRec)); 52403b705cfSriastradh adaptor_privs = calloc(nports, sizeof(intel_adaptor_private)); 52503b705cfSriastradh devUnions = calloc(nports, sizeof(DevUnion)); 52603b705cfSriastradh if (adapt == NULL || adaptor_privs == NULL || devUnions == NULL) { 52703b705cfSriastradh free(adapt); 52803b705cfSriastradh free(adaptor_privs); 52903b705cfSriastradh free(devUnions); 53003b705cfSriastradh return NULL; 53103b705cfSriastradh } 53203b705cfSriastradh 53303b705cfSriastradh adapt->type = XvWindowMask | XvInputMask | XvImageMask; 53403b705cfSriastradh adapt->flags = 0; 53503b705cfSriastradh adapt->name = "Intel(R) Textured Video"; 53603b705cfSriastradh adapt->nEncodings = 1; 53703b705cfSriastradh adapt->pEncodings = xnfalloc(sizeof(DummyEncoding)); 53803b705cfSriastradh memcpy(adapt->pEncodings, DummyEncoding, sizeof(DummyEncoding)); 53903b705cfSriastradh adapt->nFormats = NUM_FORMATS; 54003b705cfSriastradh adapt->pFormats = Formats; 54103b705cfSriastradh adapt->nPorts = nports; 54203b705cfSriastradh adapt->pPortPrivates = devUnions; 54303b705cfSriastradh adapt->nAttributes = 0; 54403b705cfSriastradh adapt->pAttributes = NULL; 54503b705cfSriastradh if (IS_I915G(intel) || IS_I915GM(intel)) 54603b705cfSriastradh adapt->nImages = NUM_IMAGES - XVMC_IMAGE; 54703b705cfSriastradh else 54803b705cfSriastradh adapt->nImages = NUM_IMAGES; 54903b705cfSriastradh 55003b705cfSriastradh adapt->pImages = Images; 55103b705cfSriastradh adapt->PutVideo = NULL; 55203b705cfSriastradh adapt->PutStill = NULL; 55303b705cfSriastradh adapt->GetVideo = NULL; 55403b705cfSriastradh adapt->GetStill = NULL; 55503b705cfSriastradh adapt->StopVideo = I830StopVideo; 55603b705cfSriastradh adapt->SetPortAttribute = I830SetPortAttributeTextured; 55703b705cfSriastradh adapt->GetPortAttribute = I830GetPortAttribute; 55803b705cfSriastradh adapt->QueryBestSize = I830QueryBestSize; 55903b705cfSriastradh adapt->PutImage = I830PutImageTextured; 56003b705cfSriastradh adapt->QueryImageAttributes = I830QueryImageAttributes; 56103b705cfSriastradh 56203b705cfSriastradh for (i = 0; i < nports; i++) { 56303b705cfSriastradh intel_adaptor_private *adaptor_priv = &adaptor_privs[i]; 56403b705cfSriastradh 56503b705cfSriastradh adaptor_priv->textured = TRUE; 56603b705cfSriastradh adaptor_priv->videoStatus = 0; 56703b705cfSriastradh adaptor_priv->buf = NULL; 56803b705cfSriastradh adaptor_priv->old_buf[0] = NULL; 56903b705cfSriastradh adaptor_priv->old_buf[1] = NULL; 57003b705cfSriastradh 57103b705cfSriastradh adaptor_priv->rotation = RR_Rotate_0; 57203b705cfSriastradh adaptor_priv->SyncToVblank = 1; 57303b705cfSriastradh 57403b705cfSriastradh /* gotta uninit this someplace, XXX: shouldn't be necessary for textured */ 57503b705cfSriastradh REGION_NULL(screen, &adaptor_priv->clip); 57603b705cfSriastradh 57703b705cfSriastradh adapt->pPortPrivates[i].ptr = (pointer) (adaptor_priv); 57803b705cfSriastradh } 57903b705cfSriastradh 58003b705cfSriastradh xvSyncToVblank = MAKE_ATOM("XV_SYNC_TO_VBLANK"); 58103b705cfSriastradh 58203b705cfSriastradh return adapt; 58303b705cfSriastradh} 58403b705cfSriastradh 58503b705cfSriastradhstatic void intel_free_video_buffers(intel_adaptor_private *adaptor_priv) 58603b705cfSriastradh{ 58703b705cfSriastradh int i; 58803b705cfSriastradh 58903b705cfSriastradh for (i = 0; i < 2; i++) { 59003b705cfSriastradh if (adaptor_priv->old_buf[i]) { 59103b705cfSriastradh drm_intel_bo_disable_reuse(adaptor_priv->old_buf[i]); 59203b705cfSriastradh drm_intel_bo_unreference(adaptor_priv->old_buf[i]); 59303b705cfSriastradh adaptor_priv->old_buf[i] = NULL; 59403b705cfSriastradh } 59503b705cfSriastradh } 59603b705cfSriastradh 59703b705cfSriastradh if (adaptor_priv->buf) { 59803b705cfSriastradh drm_intel_bo_unreference(adaptor_priv->buf); 59903b705cfSriastradh adaptor_priv->buf = NULL; 60003b705cfSriastradh } 60103b705cfSriastradh} 60203b705cfSriastradh 60303b705cfSriastradhstatic void I830StopVideo(ScrnInfoPtr scrn, pointer data, Bool shutdown) 60403b705cfSriastradh{ 60503b705cfSriastradh intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data; 60603b705cfSriastradh 60703b705cfSriastradh if (adaptor_priv->textured) 60803b705cfSriastradh return; 60903b705cfSriastradh 61003b705cfSriastradh OVERLAY_DEBUG("I830StopVideo\n"); 61103b705cfSriastradh 61203b705cfSriastradh REGION_EMPTY(scrn->pScreen, &adaptor_priv->clip); 61303b705cfSriastradh 61403b705cfSriastradh if (shutdown) { 61503b705cfSriastradh if (adaptor_priv->videoStatus & CLIENT_VIDEO_ON) 61603b705cfSriastradh intel_overlay_off(intel_get_screen_private(scrn)); 61703b705cfSriastradh 61803b705cfSriastradh intel_free_video_buffers(adaptor_priv); 61903b705cfSriastradh adaptor_priv->videoStatus = 0; 62003b705cfSriastradh } else { 62103b705cfSriastradh if (adaptor_priv->videoStatus & CLIENT_VIDEO_ON) { 62203b705cfSriastradh adaptor_priv->videoStatus |= OFF_TIMER; 62303b705cfSriastradh adaptor_priv->offTime = currentTime.milliseconds + OFF_DELAY; 62403b705cfSriastradh } 62503b705cfSriastradh } 62603b705cfSriastradh 62703b705cfSriastradh} 62803b705cfSriastradh 62903b705cfSriastradhstatic int 63003b705cfSriastradhI830SetPortAttributeTextured(ScrnInfoPtr scrn, 63103b705cfSriastradh Atom attribute, INT32 value, pointer data) 63203b705cfSriastradh{ 63303b705cfSriastradh intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data; 63403b705cfSriastradh 63503b705cfSriastradh if (attribute == xvBrightness) { 63603b705cfSriastradh if ((value < -128) || (value > 127)) 63703b705cfSriastradh return BadValue; 63803b705cfSriastradh adaptor_priv->brightness = value; 63903b705cfSriastradh return Success; 64003b705cfSriastradh } else if (attribute == xvContrast) { 64103b705cfSriastradh if ((value < 0) || (value > 255)) 64203b705cfSriastradh return BadValue; 64303b705cfSriastradh adaptor_priv->contrast = value; 64403b705cfSriastradh return Success; 64503b705cfSriastradh } else if (attribute == xvSyncToVblank) { 64603b705cfSriastradh if ((value < -1) || (value > 1)) 64703b705cfSriastradh return BadValue; 64803b705cfSriastradh adaptor_priv->SyncToVblank = value; 64903b705cfSriastradh return Success; 65003b705cfSriastradh } else { 65103b705cfSriastradh return BadMatch; 65203b705cfSriastradh } 65303b705cfSriastradh} 65403b705cfSriastradh 65503b705cfSriastradhstatic int 65603b705cfSriastradhI830SetPortAttributeOverlay(ScrnInfoPtr scrn, 65703b705cfSriastradh Atom attribute, INT32 value, pointer data) 65803b705cfSriastradh{ 65903b705cfSriastradh intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data; 66003b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 66103b705cfSriastradh 66203b705cfSriastradh if (attribute == xvBrightness) { 66303b705cfSriastradh if ((value < -128) || (value > 127)) 66403b705cfSriastradh return BadValue; 66503b705cfSriastradh adaptor_priv->brightness = value; 66603b705cfSriastradh OVERLAY_DEBUG("BRIGHTNESS\n"); 66703b705cfSriastradh } else if (attribute == xvContrast) { 66803b705cfSriastradh if ((value < 0) || (value > 255)) 66903b705cfSriastradh return BadValue; 67003b705cfSriastradh adaptor_priv->contrast = value; 67103b705cfSriastradh OVERLAY_DEBUG("CONTRAST\n"); 67203b705cfSriastradh } else if (attribute == xvSaturation) { 67303b705cfSriastradh if ((value < 0) || (value > 1023)) 67403b705cfSriastradh return BadValue; 67503b705cfSriastradh adaptor_priv->saturation = value; 67603b705cfSriastradh } else if (attribute == xvPipe) { 67703b705cfSriastradh xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 67803b705cfSriastradh if ((value < -1) || (value >= xf86_config->num_crtc)) 67903b705cfSriastradh return BadValue; 68003b705cfSriastradh if (value < 0) 68103b705cfSriastradh adaptor_priv->desired_crtc = NULL; 68203b705cfSriastradh else 68303b705cfSriastradh adaptor_priv->desired_crtc = xf86_config->crtc[value]; 68403b705cfSriastradh } else if (attribute == xvGamma0 && (INTEL_INFO(intel)->gen >= 030)) { 68503b705cfSriastradh adaptor_priv->gamma0 = value; 68603b705cfSriastradh } else if (attribute == xvGamma1 && (INTEL_INFO(intel)->gen >= 030)) { 68703b705cfSriastradh adaptor_priv->gamma1 = value; 68803b705cfSriastradh } else if (attribute == xvGamma2 && (INTEL_INFO(intel)->gen >= 030)) { 68903b705cfSriastradh adaptor_priv->gamma2 = value; 69003b705cfSriastradh } else if (attribute == xvGamma3 && (INTEL_INFO(intel)->gen >= 030)) { 69103b705cfSriastradh adaptor_priv->gamma3 = value; 69203b705cfSriastradh } else if (attribute == xvGamma4 && (INTEL_INFO(intel)->gen >= 030)) { 69303b705cfSriastradh adaptor_priv->gamma4 = value; 69403b705cfSriastradh } else if (attribute == xvGamma5 && (INTEL_INFO(intel)->gen >= 030)) { 69503b705cfSriastradh adaptor_priv->gamma5 = value; 69603b705cfSriastradh } else if (attribute == xvColorKey) { 69703b705cfSriastradh adaptor_priv->colorKey = value; 69803b705cfSriastradh OVERLAY_DEBUG("COLORKEY\n"); 69903b705cfSriastradh } else 70003b705cfSriastradh return BadMatch; 70103b705cfSriastradh 70203b705cfSriastradh if ((attribute == xvGamma0 || 70303b705cfSriastradh attribute == xvGamma1 || 70403b705cfSriastradh attribute == xvGamma2 || 70503b705cfSriastradh attribute == xvGamma3 || 70603b705cfSriastradh attribute == xvGamma4 || 70703b705cfSriastradh attribute == xvGamma5) && (INTEL_INFO(intel)->gen >= 030)) { 70803b705cfSriastradh OVERLAY_DEBUG("GAMMA\n"); 70903b705cfSriastradh } 71003b705cfSriastradh 71103b705cfSriastradh if (!intel_overlay_update_attrs(intel)) 71203b705cfSriastradh return BadValue; 71303b705cfSriastradh 71403b705cfSriastradh if (attribute == xvColorKey) 71503b705cfSriastradh REGION_EMPTY(scrn->pScreen, &adaptor_priv->clip); 71603b705cfSriastradh 71703b705cfSriastradh return Success; 71803b705cfSriastradh} 71903b705cfSriastradh 72003b705cfSriastradhstatic int 72103b705cfSriastradhI830GetPortAttribute(ScrnInfoPtr scrn, 72203b705cfSriastradh Atom attribute, INT32 * value, pointer data) 72303b705cfSriastradh{ 72403b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 72503b705cfSriastradh intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data; 72603b705cfSriastradh 72703b705cfSriastradh if (attribute == xvBrightness) { 72803b705cfSriastradh *value = adaptor_priv->brightness; 72903b705cfSriastradh } else if (attribute == xvContrast) { 73003b705cfSriastradh *value = adaptor_priv->contrast; 73103b705cfSriastradh } else if (attribute == xvSaturation) { 73203b705cfSriastradh *value = adaptor_priv->saturation; 73303b705cfSriastradh } else if (attribute == xvPipe) { 73403b705cfSriastradh int c; 73503b705cfSriastradh xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 73603b705cfSriastradh for (c = 0; c < xf86_config->num_crtc; c++) 73703b705cfSriastradh if (xf86_config->crtc[c] == adaptor_priv->desired_crtc) 73803b705cfSriastradh break; 73903b705cfSriastradh if (c == xf86_config->num_crtc) 74003b705cfSriastradh c = -1; 74103b705cfSriastradh *value = c; 74203b705cfSriastradh } else if (attribute == xvGamma0 && (INTEL_INFO(intel)->gen >= 030)) { 74303b705cfSriastradh *value = adaptor_priv->gamma0; 74403b705cfSriastradh } else if (attribute == xvGamma1 && (INTEL_INFO(intel)->gen >= 030)) { 74503b705cfSriastradh *value = adaptor_priv->gamma1; 74603b705cfSriastradh } else if (attribute == xvGamma2 && (INTEL_INFO(intel)->gen >= 030)) { 74703b705cfSriastradh *value = adaptor_priv->gamma2; 74803b705cfSriastradh } else if (attribute == xvGamma3 && (INTEL_INFO(intel)->gen >= 030)) { 74903b705cfSriastradh *value = adaptor_priv->gamma3; 75003b705cfSriastradh } else if (attribute == xvGamma4 && (INTEL_INFO(intel)->gen >= 030)) { 75103b705cfSriastradh *value = adaptor_priv->gamma4; 75203b705cfSriastradh } else if (attribute == xvGamma5 && (INTEL_INFO(intel)->gen >= 030)) { 75303b705cfSriastradh *value = adaptor_priv->gamma5; 75403b705cfSriastradh } else if (attribute == xvColorKey) { 75503b705cfSriastradh *value = adaptor_priv->colorKey; 75603b705cfSriastradh } else if (attribute == xvSyncToVblank) { 75703b705cfSriastradh *value = adaptor_priv->SyncToVblank; 75803b705cfSriastradh } else 75903b705cfSriastradh return BadMatch; 76003b705cfSriastradh 76103b705cfSriastradh return Success; 76203b705cfSriastradh} 76303b705cfSriastradh 76403b705cfSriastradhstatic void 76503b705cfSriastradhI830QueryBestSize(ScrnInfoPtr scrn, 76603b705cfSriastradh Bool motion, 76703b705cfSriastradh short vid_w, short vid_h, 76803b705cfSriastradh short drw_w, short drw_h, 76903b705cfSriastradh unsigned int *p_w, unsigned int *p_h, pointer data) 77003b705cfSriastradh{ 77103b705cfSriastradh if (vid_w > (drw_w << 1)) 77203b705cfSriastradh drw_w = vid_w >> 1; 77303b705cfSriastradh if (vid_h > (drw_h << 1)) 77403b705cfSriastradh drw_h = vid_h >> 1; 77503b705cfSriastradh 77603b705cfSriastradh *p_w = drw_w; 77703b705cfSriastradh *p_h = drw_h; 77803b705cfSriastradh} 77903b705cfSriastradh 78003b705cfSriastradhstatic Bool 78103b705cfSriastradhI830CopyPackedData(intel_adaptor_private *adaptor_priv, 78203b705cfSriastradh unsigned char *buf, 78303b705cfSriastradh int srcPitch, int dstPitch, int top, int left, int h, int w) 78403b705cfSriastradh{ 78503b705cfSriastradh unsigned char *src, *dst, *dst_base; 78603b705cfSriastradh int i, j; 78703b705cfSriastradh unsigned char *s; 78803b705cfSriastradh 78903b705cfSriastradh#if 0 79003b705cfSriastradh ErrorF("I830CopyPackedData: (%d,%d) (%d,%d)\n" 79103b705cfSriastradh "srcPitch: %d, dstPitch: %d\n", top, left, h, w, 79203b705cfSriastradh srcPitch, dstPitch); 79303b705cfSriastradh#endif 79403b705cfSriastradh 79503b705cfSriastradh src = buf + (top * srcPitch) + (left << 1); 79603b705cfSriastradh 79703b705cfSriastradh if (drm_intel_gem_bo_map_gtt(adaptor_priv->buf)) 79803b705cfSriastradh return FALSE; 79903b705cfSriastradh 80003b705cfSriastradh dst_base = adaptor_priv->buf->virtual; 80103b705cfSriastradh 80203b705cfSriastradh dst = dst_base + adaptor_priv->YBufOffset; 80303b705cfSriastradh 80403b705cfSriastradh switch (adaptor_priv->rotation) { 80503b705cfSriastradh case RR_Rotate_0: 80603b705cfSriastradh w <<= 1; 80703b705cfSriastradh for (i = 0; i < h; i++) { 80803b705cfSriastradh memcpy(dst, src, w); 80903b705cfSriastradh src += srcPitch; 81003b705cfSriastradh dst += dstPitch; 81103b705cfSriastradh } 81203b705cfSriastradh break; 81303b705cfSriastradh case RR_Rotate_90: 81403b705cfSriastradh h <<= 1; 81503b705cfSriastradh for (i = 0; i < h; i += 2) { 81603b705cfSriastradh s = src; 81703b705cfSriastradh for (j = 0; j < w; j++) { 81803b705cfSriastradh /* Copy Y */ 81903b705cfSriastradh dst[(i + 0) + ((w - j - 1) * dstPitch)] = *s++; 82003b705cfSriastradh (void)*s++; 82103b705cfSriastradh } 82203b705cfSriastradh src += srcPitch; 82303b705cfSriastradh } 82403b705cfSriastradh h >>= 1; 82503b705cfSriastradh src = buf + (top * srcPitch) + (left << 1); 82603b705cfSriastradh for (i = 0; i < h; i += 2) { 82703b705cfSriastradh for (j = 0; j < w; j += 2) { 82803b705cfSriastradh /* Copy U */ 82903b705cfSriastradh dst[((i * 2) + 1) + ((w - j - 1) * dstPitch)] = 83003b705cfSriastradh src[(j * 2) + 1 + (i * srcPitch)]; 83103b705cfSriastradh dst[((i * 2) + 1) + ((w - j - 2) * dstPitch)] = 83203b705cfSriastradh src[(j * 2) + 1 + ((i + 1) * srcPitch)]; 83303b705cfSriastradh /* Copy V */ 83403b705cfSriastradh dst[((i * 2) + 3) + ((w - j - 1) * dstPitch)] = 83503b705cfSriastradh src[(j * 2) + 3 + (i * srcPitch)]; 83603b705cfSriastradh dst[((i * 2) + 3) + ((w - j - 2) * dstPitch)] = 83703b705cfSriastradh src[(j * 2) + 3 + ((i + 1) * srcPitch)]; 83803b705cfSriastradh } 83903b705cfSriastradh } 84003b705cfSriastradh break; 84103b705cfSriastradh case RR_Rotate_180: 84203b705cfSriastradh w <<= 1; 84303b705cfSriastradh for (i = 0; i < h; i++) { 84403b705cfSriastradh s = src; 84503b705cfSriastradh for (j = 0; j < w; j += 4) { 84603b705cfSriastradh dst[(w - j - 4) + ((h - i - 1) * dstPitch)] = 84703b705cfSriastradh *s++; 84803b705cfSriastradh dst[(w - j - 3) + ((h - i - 1) * dstPitch)] = 84903b705cfSriastradh *s++; 85003b705cfSriastradh dst[(w - j - 2) + ((h - i - 1) * dstPitch)] = 85103b705cfSriastradh *s++; 85203b705cfSriastradh dst[(w - j - 1) + ((h - i - 1) * dstPitch)] = 85303b705cfSriastradh *s++; 85403b705cfSriastradh } 85503b705cfSriastradh src += srcPitch; 85603b705cfSriastradh } 85703b705cfSriastradh break; 85803b705cfSriastradh case RR_Rotate_270: 85903b705cfSriastradh h <<= 1; 86003b705cfSriastradh for (i = 0; i < h; i += 2) { 86103b705cfSriastradh s = src; 86203b705cfSriastradh for (j = 0; j < w; j++) { 86303b705cfSriastradh /* Copy Y */ 86403b705cfSriastradh dst[(h - i - 2) + (j * dstPitch)] = *s++; 86503b705cfSriastradh (void)*s++; 86603b705cfSriastradh } 86703b705cfSriastradh src += srcPitch; 86803b705cfSriastradh } 86903b705cfSriastradh h >>= 1; 87003b705cfSriastradh src = buf + (top * srcPitch) + (left << 1); 87103b705cfSriastradh for (i = 0; i < h; i += 2) { 87203b705cfSriastradh for (j = 0; j < w; j += 2) { 87303b705cfSriastradh /* Copy U */ 87403b705cfSriastradh dst[(((h - i) * 2) - 3) + (j * dstPitch)] = 87503b705cfSriastradh src[(j * 2) + 1 + (i * srcPitch)]; 87603b705cfSriastradh dst[(((h - i) * 2) - 3) + 87703b705cfSriastradh ((j + 1) * dstPitch)] = 87803b705cfSriastradh src[(j * 2) + 1 + ((i + 1) * srcPitch)]; 87903b705cfSriastradh /* Copy V */ 88003b705cfSriastradh dst[(((h - i) * 2) - 1) + (j * dstPitch)] = 88103b705cfSriastradh src[(j * 2) + 3 + (i * srcPitch)]; 88203b705cfSriastradh dst[(((h - i) * 2) - 1) + 88303b705cfSriastradh ((j + 1) * dstPitch)] = 88403b705cfSriastradh src[(j * 2) + 3 + ((i + 1) * srcPitch)]; 88503b705cfSriastradh } 88603b705cfSriastradh } 88703b705cfSriastradh break; 88803b705cfSriastradh } 88903b705cfSriastradh 89003b705cfSriastradh drm_intel_gem_bo_unmap_gtt(adaptor_priv->buf); 89103b705cfSriastradh return TRUE; 89203b705cfSriastradh} 89303b705cfSriastradh 89403b705cfSriastradhstatic void intel_memcpy_plane(unsigned char *dst, unsigned char *src, 89503b705cfSriastradh int height, int width, 89603b705cfSriastradh int dstPitch, int srcPitch, Rotation rotation) 89703b705cfSriastradh{ 89803b705cfSriastradh int i, j = 0; 89903b705cfSriastradh unsigned char *s; 90003b705cfSriastradh 90103b705cfSriastradh switch (rotation) { 90203b705cfSriastradh case RR_Rotate_0: 90303b705cfSriastradh /* optimise for the case of no clipping */ 90403b705cfSriastradh if (srcPitch == dstPitch && srcPitch == width) 90503b705cfSriastradh memcpy(dst, src, srcPitch * height); 90603b705cfSriastradh else 90703b705cfSriastradh for (i = 0; i < height; i++) { 90803b705cfSriastradh memcpy(dst, src, width); 90903b705cfSriastradh src += srcPitch; 91003b705cfSriastradh dst += dstPitch; 91103b705cfSriastradh } 91203b705cfSriastradh break; 91303b705cfSriastradh case RR_Rotate_90: 91403b705cfSriastradh for (i = 0; i < height; i++) { 91503b705cfSriastradh s = src; 91603b705cfSriastradh for (j = 0; j < width; j++) { 91703b705cfSriastradh dst[(i) + ((width - j - 1) * dstPitch)] = *s++; 91803b705cfSriastradh } 91903b705cfSriastradh src += srcPitch; 92003b705cfSriastradh } 92103b705cfSriastradh break; 92203b705cfSriastradh case RR_Rotate_180: 92303b705cfSriastradh for (i = 0; i < height; i++) { 92403b705cfSriastradh s = src; 92503b705cfSriastradh for (j = 0; j < width; j++) { 92603b705cfSriastradh dst[(width - j - 1) + 92703b705cfSriastradh ((height - i - 1) * dstPitch)] = *s++; 92803b705cfSriastradh } 92903b705cfSriastradh src += srcPitch; 93003b705cfSriastradh } 93103b705cfSriastradh break; 93203b705cfSriastradh case RR_Rotate_270: 93303b705cfSriastradh for (i = 0; i < height; i++) { 93403b705cfSriastradh s = src; 93503b705cfSriastradh for (j = 0; j < width; j++) { 93603b705cfSriastradh dst[(height - i - 1) + (j * dstPitch)] = *s++; 93703b705cfSriastradh } 93803b705cfSriastradh src += srcPitch; 93903b705cfSriastradh } 94003b705cfSriastradh break; 94103b705cfSriastradh } 94203b705cfSriastradh} 94303b705cfSriastradh 94403b705cfSriastradhstatic Bool 94503b705cfSriastradhI830CopyPlanarData(intel_adaptor_private *adaptor_priv, 94603b705cfSriastradh unsigned char *buf, int srcPitch, int srcPitch2, 94703b705cfSriastradh int dstPitch, int dstPitch2, 94803b705cfSriastradh int srcH, int top, int left, 94903b705cfSriastradh int h, int w, int id) 95003b705cfSriastradh{ 95103b705cfSriastradh unsigned char *src1, *src2, *src3, *dst_base, *dst1, *dst2, *dst3; 95203b705cfSriastradh 95303b705cfSriastradh#if 0 95403b705cfSriastradh ErrorF("I830CopyPlanarData: srcPitch %d, srcPitch %d, dstPitch %d\n" 95503b705cfSriastradh "nlines %d, npixels %d, top %d, left %d\n", 95603b705cfSriastradh srcPitch, srcPitch2, dstPitch, h, w, top, left); 95703b705cfSriastradh#endif 95803b705cfSriastradh 95903b705cfSriastradh /* Copy Y data */ 96003b705cfSriastradh src1 = buf + (top * srcPitch) + left; 96103b705cfSriastradh#if 0 96203b705cfSriastradh ErrorF("src1 is %p, offset is %ld\n", src1, 96303b705cfSriastradh (unsigned long)src1 - (unsigned long)buf); 96403b705cfSriastradh#endif 96503b705cfSriastradh 96603b705cfSriastradh if (drm_intel_gem_bo_map_gtt(adaptor_priv->buf)) 96703b705cfSriastradh return FALSE; 96803b705cfSriastradh 96903b705cfSriastradh dst_base = adaptor_priv->buf->virtual; 97003b705cfSriastradh 97103b705cfSriastradh dst1 = dst_base + adaptor_priv->YBufOffset; 97203b705cfSriastradh 97303b705cfSriastradh intel_memcpy_plane(dst1, src1, h, w, dstPitch2, srcPitch, 97403b705cfSriastradh adaptor_priv->rotation); 97503b705cfSriastradh 97603b705cfSriastradh /* Copy V data for YV12, or U data for I420 */ 97703b705cfSriastradh src2 = buf + /* start of YUV data */ 97803b705cfSriastradh (srcH * srcPitch) + /* move over Luma plane */ 97903b705cfSriastradh ((top >> 1) * srcPitch2) + /* move down from by top lines */ 98003b705cfSriastradh (left >> 1); /* move left by left pixels */ 98103b705cfSriastradh 98203b705cfSriastradh#if 0 98303b705cfSriastradh ErrorF("src2 is %p, offset is %ld\n", src2, 98403b705cfSriastradh (unsigned long)src2 - (unsigned long)buf); 98503b705cfSriastradh#endif 98603b705cfSriastradh if (id == FOURCC_I420) 98703b705cfSriastradh dst2 = dst_base + adaptor_priv->UBufOffset; 98803b705cfSriastradh else 98903b705cfSriastradh dst2 = dst_base + adaptor_priv->VBufOffset; 99003b705cfSriastradh 99103b705cfSriastradh intel_memcpy_plane(dst2, src2, h / 2, w / 2, 99203b705cfSriastradh dstPitch, srcPitch2, adaptor_priv->rotation); 99303b705cfSriastradh 99403b705cfSriastradh /* Copy U data for YV12, or V data for I420 */ 99503b705cfSriastradh src3 = buf + /* start of YUV data */ 99603b705cfSriastradh (srcH * srcPitch) + /* move over Luma plane */ 99703b705cfSriastradh ((srcH >> 1) * srcPitch2) + /* move over Chroma plane */ 99803b705cfSriastradh ((top >> 1) * srcPitch2) + /* move down from by top lines */ 99903b705cfSriastradh (left >> 1); /* move left by left pixels */ 100003b705cfSriastradh#if 0 100103b705cfSriastradh ErrorF("src3 is %p, offset is %ld\n", src3, 100203b705cfSriastradh (unsigned long)src3 - (unsigned long)buf); 100303b705cfSriastradh#endif 100403b705cfSriastradh if (id == FOURCC_I420) 100503b705cfSriastradh dst3 = dst_base + adaptor_priv->VBufOffset; 100603b705cfSriastradh else 100703b705cfSriastradh dst3 = dst_base + adaptor_priv->UBufOffset; 100803b705cfSriastradh 100903b705cfSriastradh intel_memcpy_plane(dst3, src3, h / 2, w / 2, 101003b705cfSriastradh dstPitch, srcPitch2, adaptor_priv->rotation); 101103b705cfSriastradh 101203b705cfSriastradh drm_intel_gem_bo_unmap_gtt(adaptor_priv->buf); 101303b705cfSriastradh return TRUE; 101403b705cfSriastradh} 101503b705cfSriastradh 101603b705cfSriastradhstatic void intel_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) 101703b705cfSriastradh{ 101803b705cfSriastradh dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; 101903b705cfSriastradh dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; 102003b705cfSriastradh if (dest->x1 >= dest->x2) { 102103b705cfSriastradh dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; 102203b705cfSriastradh return; 102303b705cfSriastradh } 102403b705cfSriastradh 102503b705cfSriastradh dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; 102603b705cfSriastradh dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; 102703b705cfSriastradh if (dest->y1 >= dest->y2) 102803b705cfSriastradh dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; 102903b705cfSriastradh} 103003b705cfSriastradh 103103b705cfSriastradhstatic void intel_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box) 103203b705cfSriastradh{ 103303b705cfSriastradh if (crtc->enabled) { 103403b705cfSriastradh crtc_box->x1 = crtc->x; 103503b705cfSriastradh crtc_box->x2 = 103603b705cfSriastradh crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation); 103703b705cfSriastradh crtc_box->y1 = crtc->y; 103803b705cfSriastradh crtc_box->y2 = 103903b705cfSriastradh crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation); 104003b705cfSriastradh } else 104103b705cfSriastradh crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; 104203b705cfSriastradh} 104303b705cfSriastradh 104403b705cfSriastradhstatic int intel_box_area(BoxPtr box) 104503b705cfSriastradh{ 104603b705cfSriastradh return (int)(box->x2 - box->x1) * (int)(box->y2 - box->y1); 104703b705cfSriastradh} 104803b705cfSriastradh 104903b705cfSriastradh/* 105003b705cfSriastradh * Return the crtc covering 'box'. If two crtcs cover a portion of 105103b705cfSriastradh * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc 105203b705cfSriastradh * with greater coverage 105303b705cfSriastradh */ 105403b705cfSriastradh 105503b705cfSriastradhxf86CrtcPtr 105603b705cfSriastradhintel_covering_crtc(ScrnInfoPtr scrn, 105703b705cfSriastradh BoxPtr box, xf86CrtcPtr desired, BoxPtr crtc_box_ret) 105803b705cfSriastradh{ 105903b705cfSriastradh xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 106003b705cfSriastradh xf86CrtcPtr crtc, best_crtc; 106103b705cfSriastradh int coverage, best_coverage; 106203b705cfSriastradh int c; 106303b705cfSriastradh BoxRec crtc_box, cover_box; 106403b705cfSriastradh 106503b705cfSriastradh best_crtc = NULL; 106603b705cfSriastradh best_coverage = 0; 106703b705cfSriastradh crtc_box_ret->x1 = 0; 106803b705cfSriastradh crtc_box_ret->x2 = 0; 106903b705cfSriastradh crtc_box_ret->y1 = 0; 107003b705cfSriastradh crtc_box_ret->y2 = 0; 107103b705cfSriastradh for (c = 0; c < xf86_config->num_crtc; c++) { 107203b705cfSriastradh crtc = xf86_config->crtc[c]; 107303b705cfSriastradh 107403b705cfSriastradh /* If the CRTC is off, treat it as not covering */ 107503b705cfSriastradh if (!intel_crtc_on(crtc)) 107603b705cfSriastradh continue; 107703b705cfSriastradh 107803b705cfSriastradh intel_crtc_box(crtc, &crtc_box); 107903b705cfSriastradh intel_box_intersect(&cover_box, &crtc_box, box); 108003b705cfSriastradh coverage = intel_box_area(&cover_box); 108103b705cfSriastradh if (coverage && crtc == desired) { 108203b705cfSriastradh *crtc_box_ret = crtc_box; 108303b705cfSriastradh return crtc; 108403b705cfSriastradh } 108503b705cfSriastradh if (coverage > best_coverage) { 108603b705cfSriastradh *crtc_box_ret = crtc_box; 108703b705cfSriastradh best_crtc = crtc; 108803b705cfSriastradh best_coverage = coverage; 108903b705cfSriastradh } 109003b705cfSriastradh } 109103b705cfSriastradh return best_crtc; 109203b705cfSriastradh} 109303b705cfSriastradh 109403b705cfSriastradhstatic void 109503b705cfSriastradhintel_update_dst_box_to_crtc_coords(ScrnInfoPtr scrn, xf86CrtcPtr crtc, 109603b705cfSriastradh BoxPtr dstBox) 109703b705cfSriastradh{ 109803b705cfSriastradh int tmp; 109903b705cfSriastradh 110003b705cfSriastradh /* for overlay, we should take it from crtc's screen 110103b705cfSriastradh * coordinate to current crtc's display mode. 110203b705cfSriastradh * yeah, a bit confusing. 110303b705cfSriastradh */ 110403b705cfSriastradh switch (crtc->rotation & 0xf) { 110503b705cfSriastradh case RR_Rotate_0: 110603b705cfSriastradh dstBox->x1 -= crtc->x; 110703b705cfSriastradh dstBox->x2 -= crtc->x; 110803b705cfSriastradh dstBox->y1 -= crtc->y; 110903b705cfSriastradh dstBox->y2 -= crtc->y; 111003b705cfSriastradh break; 111103b705cfSriastradh case RR_Rotate_90: 111203b705cfSriastradh tmp = dstBox->x1; 111303b705cfSriastradh dstBox->x1 = dstBox->y1 - crtc->x; 111403b705cfSriastradh dstBox->y1 = scrn->virtualX - tmp - crtc->y; 111503b705cfSriastradh tmp = dstBox->x2; 111603b705cfSriastradh dstBox->x2 = dstBox->y2 - crtc->x; 111703b705cfSriastradh dstBox->y2 = scrn->virtualX - tmp - crtc->y; 111803b705cfSriastradh tmp = dstBox->y1; 111903b705cfSriastradh dstBox->y1 = dstBox->y2; 112003b705cfSriastradh dstBox->y2 = tmp; 112103b705cfSriastradh break; 112203b705cfSriastradh case RR_Rotate_180: 112303b705cfSriastradh tmp = dstBox->x1; 112403b705cfSriastradh dstBox->x1 = scrn->virtualX - dstBox->x2 - crtc->x; 112503b705cfSriastradh dstBox->x2 = scrn->virtualX - tmp - crtc->x; 112603b705cfSriastradh tmp = dstBox->y1; 112703b705cfSriastradh dstBox->y1 = scrn->virtualY - dstBox->y2 - crtc->y; 112803b705cfSriastradh dstBox->y2 = scrn->virtualY - tmp - crtc->y; 112903b705cfSriastradh break; 113003b705cfSriastradh case RR_Rotate_270: 113103b705cfSriastradh tmp = dstBox->x1; 113203b705cfSriastradh dstBox->x1 = scrn->virtualY - dstBox->y1 - crtc->x; 113303b705cfSriastradh dstBox->y1 = tmp - crtc->y; 113403b705cfSriastradh tmp = dstBox->x2; 113503b705cfSriastradh dstBox->x2 = scrn->virtualY - dstBox->y2 - crtc->x; 113603b705cfSriastradh dstBox->y2 = tmp - crtc->y; 113703b705cfSriastradh tmp = dstBox->x1; 113803b705cfSriastradh dstBox->x1 = dstBox->x2; 113903b705cfSriastradh dstBox->x2 = tmp; 114003b705cfSriastradh break; 114103b705cfSriastradh } 114203b705cfSriastradh 114303b705cfSriastradh return; 114403b705cfSriastradh} 114503b705cfSriastradh 114603b705cfSriastradhint is_planar_fourcc(int id) 114703b705cfSriastradh{ 114803b705cfSriastradh switch (id) { 114903b705cfSriastradh case FOURCC_YV12: 115003b705cfSriastradh case FOURCC_I420: 115103b705cfSriastradh#ifdef INTEL_XVMC 115203b705cfSriastradh case FOURCC_XVMC: 115303b705cfSriastradh#endif 115403b705cfSriastradh return 1; 115503b705cfSriastradh case FOURCC_UYVY: 115603b705cfSriastradh case FOURCC_YUY2: 115703b705cfSriastradh return 0; 115803b705cfSriastradh default: 115903b705cfSriastradh ErrorF("Unknown format 0x%x\n", id); 116003b705cfSriastradh return 0; 116103b705cfSriastradh } 116203b705cfSriastradh} 116303b705cfSriastradh 116403b705cfSriastradhstatic int xvmc_passthrough(int id) 116503b705cfSriastradh{ 116603b705cfSriastradh#ifdef INTEL_XVMC 116703b705cfSriastradh return id == FOURCC_XVMC; 116803b705cfSriastradh#else 116903b705cfSriastradh return 0; 117003b705cfSriastradh#endif 117103b705cfSriastradh} 117203b705cfSriastradh 117303b705cfSriastradhstatic Bool 117403b705cfSriastradhintel_display_overlay(ScrnInfoPtr scrn, xf86CrtcPtr crtc, 117503b705cfSriastradh int id, short width, short height, 117603b705cfSriastradh int dstPitch, int dstPitch2, 117703b705cfSriastradh BoxPtr dstBox, short src_w, short src_h, short drw_w, 117803b705cfSriastradh short drw_h) 117903b705cfSriastradh{ 118003b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 118103b705cfSriastradh int tmp; 118203b705cfSriastradh 118303b705cfSriastradh OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height, 118403b705cfSriastradh dstPitch); 118503b705cfSriastradh 118603b705cfSriastradh /* 118703b705cfSriastradh * If the video isn't visible on any CRTC, turn it off 118803b705cfSriastradh */ 118903b705cfSriastradh if (!crtc) { 119003b705cfSriastradh intel_overlay_off(intel); 119103b705cfSriastradh return TRUE; 119203b705cfSriastradh } 119303b705cfSriastradh 119403b705cfSriastradh intel_update_dst_box_to_crtc_coords(scrn, crtc, dstBox); 119503b705cfSriastradh 119603b705cfSriastradh if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) { 119703b705cfSriastradh tmp = width; 119803b705cfSriastradh width = height; 119903b705cfSriastradh height = tmp; 120003b705cfSriastradh tmp = drw_w; 120103b705cfSriastradh drw_w = drw_h; 120203b705cfSriastradh drw_h = tmp; 120303b705cfSriastradh tmp = src_w; 120403b705cfSriastradh src_w = src_h; 120503b705cfSriastradh src_h = tmp; 120603b705cfSriastradh } 120703b705cfSriastradh 120803b705cfSriastradh return intel_overlay_put_image(intel, crtc, id, 120903b705cfSriastradh width, height, 121003b705cfSriastradh dstPitch, dstPitch2, dstBox, 121103b705cfSriastradh src_w, src_h, drw_w, drw_h); 121203b705cfSriastradh} 121303b705cfSriastradh 121403b705cfSriastradhstatic Bool 121503b705cfSriastradhintel_clip_video_helper(ScrnInfoPtr scrn, 121603b705cfSriastradh intel_adaptor_private *adaptor_priv, 121703b705cfSriastradh xf86CrtcPtr * crtc_ret, 121803b705cfSriastradh BoxPtr dst, 121903b705cfSriastradh short src_x, short src_y, 122003b705cfSriastradh short drw_x, short drw_y, 122103b705cfSriastradh short src_w, short src_h, 122203b705cfSriastradh short drw_w, short drw_h, 122303b705cfSriastradh int id, 122403b705cfSriastradh int *top, int* left, int* npixels, int *nlines, 122503b705cfSriastradh RegionPtr reg, INT32 width, INT32 height) 122603b705cfSriastradh{ 122703b705cfSriastradh Bool ret; 122803b705cfSriastradh RegionRec crtc_region_local; 122903b705cfSriastradh RegionPtr crtc_region = reg; 123003b705cfSriastradh BoxRec crtc_box; 123103b705cfSriastradh INT32 x1, x2, y1, y2; 123203b705cfSriastradh xf86CrtcPtr crtc; 123303b705cfSriastradh 123403b705cfSriastradh x1 = src_x; 123503b705cfSriastradh x2 = src_x + src_w; 123603b705cfSriastradh y1 = src_y; 123703b705cfSriastradh y2 = src_y + src_h; 123803b705cfSriastradh 123903b705cfSriastradh dst->x1 = drw_x; 124003b705cfSriastradh dst->x2 = drw_x + drw_w; 124103b705cfSriastradh dst->y1 = drw_y; 124203b705cfSriastradh dst->y2 = drw_y + drw_h; 124303b705cfSriastradh 124403b705cfSriastradh /* 124503b705cfSriastradh * For overlay video, compute the relevant CRTC and 124603b705cfSriastradh * clip video to that 124703b705cfSriastradh */ 124803b705cfSriastradh crtc = intel_covering_crtc(scrn, dst, adaptor_priv->desired_crtc, 124903b705cfSriastradh &crtc_box); 125003b705cfSriastradh 125103b705cfSriastradh /* For textured video, we don't actually want to clip at all. */ 125203b705cfSriastradh if (crtc && !adaptor_priv->textured) { 125303b705cfSriastradh REGION_INIT(screen, &crtc_region_local, &crtc_box, 1); 125403b705cfSriastradh crtc_region = &crtc_region_local; 125503b705cfSriastradh REGION_INTERSECT(screen, crtc_region, crtc_region, 125603b705cfSriastradh reg); 125703b705cfSriastradh } 125803b705cfSriastradh *crtc_ret = crtc; 125903b705cfSriastradh 126003b705cfSriastradh ret = xf86XVClipVideoHelper(dst, &x1, &x2, &y1, &y2, 126103b705cfSriastradh crtc_region, width, height); 126203b705cfSriastradh if (crtc_region != reg) 126303b705cfSriastradh REGION_UNINIT(screen, &crtc_region_local); 126403b705cfSriastradh 126503b705cfSriastradh *top = y1 >> 16; 126603b705cfSriastradh *left = (x1 >> 16) & ~1; 126703b705cfSriastradh *npixels = ALIGN(((x2 + 0xffff) >> 16), 2) - *left; 126803b705cfSriastradh if (is_planar_fourcc(id)) { 126903b705cfSriastradh *top &= ~1; 127003b705cfSriastradh *nlines = ALIGN(((y2 + 0xffff) >> 16), 2) - *top; 127103b705cfSriastradh } else 127203b705cfSriastradh *nlines = ((y2 + 0xffff) >> 16) - *top; 127303b705cfSriastradh 127403b705cfSriastradh return ret; 127503b705cfSriastradh} 127603b705cfSriastradh 127703b705cfSriastradhstatic void 127803b705cfSriastradhintel_wait_for_scanline(ScrnInfoPtr scrn, PixmapPtr pixmap, 127903b705cfSriastradh xf86CrtcPtr crtc, RegionPtr clipBoxes) 128003b705cfSriastradh{ 128103b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 128203b705cfSriastradh pixman_box16_t box, crtc_box; 128303b705cfSriastradh int pipe, event; 128403b705cfSriastradh Bool full_height; 128503b705cfSriastradh int y1, y2; 128603b705cfSriastradh 128703b705cfSriastradh pipe = -1; 128803b705cfSriastradh if (scrn->vtSema && pixmap_is_scanout(pixmap)) 128903b705cfSriastradh pipe = intel_crtc_to_pipe(crtc); 129003b705cfSriastradh if (pipe < 0) 129103b705cfSriastradh return; 129203b705cfSriastradh 129303b705cfSriastradh box = *REGION_EXTENTS(unused, clipBoxes); 129403b705cfSriastradh 129503b705cfSriastradh if (crtc->transform_in_use) 129603b705cfSriastradh pixman_f_transform_bounds(&crtc->f_framebuffer_to_crtc, &box); 129703b705cfSriastradh 129803b705cfSriastradh /* We could presume the clip was correctly computed... */ 129903b705cfSriastradh intel_crtc_box(crtc, &crtc_box); 130003b705cfSriastradh intel_box_intersect(&box, &crtc_box, &box); 130103b705cfSriastradh 130203b705cfSriastradh /* 130303b705cfSriastradh * Make sure we don't wait for a scanline that will 130403b705cfSriastradh * never occur 130503b705cfSriastradh */ 130603b705cfSriastradh y1 = (crtc_box.y1 <= box.y1) ? box.y1 - crtc_box.y1 : 0; 130703b705cfSriastradh y2 = (box.y2 <= crtc_box.y2) ? 130803b705cfSriastradh box.y2 - crtc_box.y1 : crtc_box.y2 - crtc_box.y1; 130903b705cfSriastradh if (y2 <= y1) 131003b705cfSriastradh return; 131103b705cfSriastradh 131203b705cfSriastradh full_height = FALSE; 131303b705cfSriastradh if (y1 == 0 && y2 == (crtc_box.y2 - crtc_box.y1)) 131403b705cfSriastradh full_height = TRUE; 131503b705cfSriastradh 131603b705cfSriastradh /* 131703b705cfSriastradh * Pre-965 doesn't have SVBLANK, so we need a bit 131803b705cfSriastradh * of extra time for the blitter to start up and 131903b705cfSriastradh * do its job for a full height blit 132003b705cfSriastradh */ 132103b705cfSriastradh if (full_height && INTEL_INFO(intel)->gen < 040) 132203b705cfSriastradh y2 -= 2; 132303b705cfSriastradh 132403b705cfSriastradh if (pipe == 0) { 132503b705cfSriastradh pipe = MI_LOAD_SCAN_LINES_DISPLAY_PIPEA; 132603b705cfSriastradh event = MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW; 132703b705cfSriastradh if (full_height && INTEL_INFO(intel)->gen >= 040) 132803b705cfSriastradh event = MI_WAIT_FOR_PIPEA_SVBLANK; 132903b705cfSriastradh } else { 133003b705cfSriastradh pipe = MI_LOAD_SCAN_LINES_DISPLAY_PIPEB; 133103b705cfSriastradh event = MI_WAIT_FOR_PIPEB_SCAN_LINE_WINDOW; 133203b705cfSriastradh if (full_height && INTEL_INFO(intel)->gen >= 040) 133303b705cfSriastradh event = MI_WAIT_FOR_PIPEB_SVBLANK; 133403b705cfSriastradh } 133503b705cfSriastradh 133603b705cfSriastradh if (crtc->mode.Flags & V_INTERLACE) { 133703b705cfSriastradh /* DSL count field lines */ 133803b705cfSriastradh y1 /= 2; 133903b705cfSriastradh y2 /= 2; 134003b705cfSriastradh } 134103b705cfSriastradh 134203b705cfSriastradh BEGIN_BATCH(5); 134303b705cfSriastradh /* The documentation says that the LOAD_SCAN_LINES command 134403b705cfSriastradh * always comes in pairs. Don't ask me why. */ 134503b705cfSriastradh OUT_BATCH(MI_LOAD_SCAN_LINES_INCL | pipe); 134603b705cfSriastradh OUT_BATCH((y1 << 16) | (y2-1)); 134703b705cfSriastradh OUT_BATCH(MI_LOAD_SCAN_LINES_INCL | pipe); 134803b705cfSriastradh OUT_BATCH((y1 << 16) | (y2-1)); 134903b705cfSriastradh OUT_BATCH(MI_WAIT_FOR_EVENT | event); 135003b705cfSriastradh ADVANCE_BATCH(); 135103b705cfSriastradh} 135203b705cfSriastradh 135303b705cfSriastradhstatic Bool 135403b705cfSriastradhintel_setup_video_buffer(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv, 135503b705cfSriastradh int alloc_size, int id, unsigned char *buf) 135603b705cfSriastradh{ 135703b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 135803b705cfSriastradh 135903b705cfSriastradh /* Free the current buffer if we're going to have to reallocate */ 136003b705cfSriastradh if (adaptor_priv->buf && adaptor_priv->buf->size < alloc_size) 136103b705cfSriastradh intel_free_video_buffers(adaptor_priv); 136203b705cfSriastradh 136303b705cfSriastradh if (adaptor_priv->buf == NULL) { 136403b705cfSriastradh adaptor_priv->buf = drm_intel_bo_alloc(intel->bufmgr, "xv buffer", 136503b705cfSriastradh alloc_size, 4096); 136603b705cfSriastradh if (adaptor_priv->buf == NULL) 136703b705cfSriastradh return FALSE; 136803b705cfSriastradh 136903b705cfSriastradh adaptor_priv->reusable = TRUE; 137003b705cfSriastradh } 137103b705cfSriastradh 137203b705cfSriastradh return TRUE; 137303b705cfSriastradh} 137403b705cfSriastradh 137503b705cfSriastradhstatic void 137603b705cfSriastradhintel_setup_dst_params(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv, short width, 137703b705cfSriastradh short height, int *dstPitch, int *dstPitch2, int *size, 137803b705cfSriastradh int id) 137903b705cfSriastradh{ 138003b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 138103b705cfSriastradh int pitchAlign; 138203b705cfSriastradh 138303b705cfSriastradh /* Only needs to be DWORD-aligned for textured on i915, but overlay has 138403b705cfSriastradh * stricter requirements. 138503b705cfSriastradh */ 138603b705cfSriastradh if (adaptor_priv->textured) { 138703b705cfSriastradh pitchAlign = 4; 138803b705cfSriastradh } else { 138903b705cfSriastradh if (INTEL_INFO(intel)->gen >= 040) 139003b705cfSriastradh /* Actually the alignment is 64 bytes, too. But the 139103b705cfSriastradh * stride must be at least 512 bytes. Take the easy fix 139203b705cfSriastradh * and align on 512 bytes unconditionally. */ 139303b705cfSriastradh pitchAlign = 512; 139403b705cfSriastradh else if (IS_I830(intel) || IS_845G(intel)) 139503b705cfSriastradh /* Harsh, errata on these chipsets limit the stride to be 139603b705cfSriastradh * a multiple of 256 bytes. 139703b705cfSriastradh */ 139803b705cfSriastradh pitchAlign = 256; 139903b705cfSriastradh else 140003b705cfSriastradh pitchAlign = 64; 140103b705cfSriastradh } 140203b705cfSriastradh 140303b705cfSriastradh#if INTEL_XVMC 140403b705cfSriastradh /* for i915 xvmc, hw requires 1kb aligned surfaces */ 140503b705cfSriastradh if ((id == FOURCC_XVMC) && IS_GEN3(intel)) 140603b705cfSriastradh pitchAlign = 1024; 140703b705cfSriastradh#endif 140803b705cfSriastradh 140903b705cfSriastradh /* Determine the desired destination pitch (representing the chroma's pitch, 141003b705cfSriastradh * in the planar case. 141103b705cfSriastradh */ 141203b705cfSriastradh if (is_planar_fourcc(id)) { 141303b705cfSriastradh if (adaptor_priv->rotation & (RR_Rotate_90 | RR_Rotate_270)) { 141403b705cfSriastradh *dstPitch = ALIGN((height / 2), pitchAlign); 141503b705cfSriastradh *dstPitch2 = ALIGN(height, pitchAlign); 141603b705cfSriastradh *size = *dstPitch * width * 3; 141703b705cfSriastradh } else { 141803b705cfSriastradh *dstPitch = ALIGN((width / 2), pitchAlign); 141903b705cfSriastradh *dstPitch2 = ALIGN(width, pitchAlign); 142003b705cfSriastradh *size = *dstPitch * height * 3; 142103b705cfSriastradh } 142203b705cfSriastradh } else { 142303b705cfSriastradh if (adaptor_priv->rotation & (RR_Rotate_90 | RR_Rotate_270)) { 142403b705cfSriastradh *dstPitch = ALIGN((height << 1), pitchAlign); 142503b705cfSriastradh *size = *dstPitch * width; 142603b705cfSriastradh } else { 142703b705cfSriastradh *dstPitch = ALIGN((width << 1), pitchAlign); 142803b705cfSriastradh *size = *dstPitch * height; 142903b705cfSriastradh } 143003b705cfSriastradh *dstPitch2 = 0; 143103b705cfSriastradh } 143203b705cfSriastradh#if 0 143303b705cfSriastradh ErrorF("srcPitch: %d, dstPitch: %d, size: %d\n", srcPitch, *dstPitch, 143403b705cfSriastradh size); 143503b705cfSriastradh#endif 143603b705cfSriastradh 143703b705cfSriastradh adaptor_priv->YBufOffset = 0; 143803b705cfSriastradh 143903b705cfSriastradh if (adaptor_priv->rotation & (RR_Rotate_90 | RR_Rotate_270)) { 144003b705cfSriastradh adaptor_priv->UBufOffset = 144103b705cfSriastradh adaptor_priv->YBufOffset + (*dstPitch2 * width); 144203b705cfSriastradh adaptor_priv->VBufOffset = 144303b705cfSriastradh adaptor_priv->UBufOffset + (*dstPitch * width / 2); 144403b705cfSriastradh } else { 144503b705cfSriastradh adaptor_priv->UBufOffset = 144603b705cfSriastradh adaptor_priv->YBufOffset + (*dstPitch2 * height); 144703b705cfSriastradh adaptor_priv->VBufOffset = 144803b705cfSriastradh adaptor_priv->UBufOffset + (*dstPitch * height / 2); 144903b705cfSriastradh } 145003b705cfSriastradh} 145103b705cfSriastradh 145203b705cfSriastradhstatic Bool 145303b705cfSriastradhintel_copy_video_data(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv, 145403b705cfSriastradh short width, short height, int *dstPitch, int *dstPitch2, 145503b705cfSriastradh int top, int left, int npixels, int nlines, 145603b705cfSriastradh int id, unsigned char *buf) 145703b705cfSriastradh{ 145803b705cfSriastradh int srcPitch = 0, srcPitch2 = 0; 145903b705cfSriastradh int size; 146003b705cfSriastradh 146103b705cfSriastradh if (is_planar_fourcc(id)) { 146203b705cfSriastradh srcPitch = ALIGN(width, 0x4); 146303b705cfSriastradh srcPitch2 = ALIGN((width >> 1), 0x4); 146403b705cfSriastradh } else { 146503b705cfSriastradh srcPitch = width << 1; 146603b705cfSriastradh } 146703b705cfSriastradh 146803b705cfSriastradh intel_setup_dst_params(scrn, adaptor_priv, width, height, dstPitch, 146903b705cfSriastradh dstPitch2, &size, id); 147003b705cfSriastradh 147103b705cfSriastradh if (!intel_setup_video_buffer(scrn, adaptor_priv, size, id, buf)) 147203b705cfSriastradh return FALSE; 147303b705cfSriastradh 147403b705cfSriastradh /* copy data */ 147503b705cfSriastradh if (is_planar_fourcc(id)) { 147603b705cfSriastradh return I830CopyPlanarData(adaptor_priv, buf, srcPitch, srcPitch2, 147703b705cfSriastradh *dstPitch, *dstPitch2, 147803b705cfSriastradh height, top, left, nlines, 147903b705cfSriastradh npixels, id); 148003b705cfSriastradh } else { 148103b705cfSriastradh return I830CopyPackedData(adaptor_priv, buf, srcPitch, *dstPitch, top, left, 148203b705cfSriastradh nlines, npixels); 148303b705cfSriastradh } 148403b705cfSriastradh} 148503b705cfSriastradh 148603b705cfSriastradh/* 148703b705cfSriastradh * The source rectangle of the video is defined by (src_x, src_y, src_w, src_h). 148803b705cfSriastradh * The dest rectangle of the video is defined by (drw_x, drw_y, drw_w, drw_h). 148903b705cfSriastradh * id is a fourcc code for the format of the video. 149003b705cfSriastradh * buf is the pointer to the source data in system memory. 149103b705cfSriastradh * width and height are the w/h of the source data. 149203b705cfSriastradh * If "sync" is TRUE, then we must be finished with *buf at the point of return 149303b705cfSriastradh * (which we always are). 149403b705cfSriastradh * clipBoxes is the clipping region in screen space. 149503b705cfSriastradh * data is a pointer to our port private. 149603b705cfSriastradh * drawable is some Drawable, which might not be the screen in the case of 149703b705cfSriastradh * compositing. It's a new argument to the function in the 1.1 server. 149803b705cfSriastradh */ 149903b705cfSriastradhstatic int 150003b705cfSriastradhI830PutImageTextured(ScrnInfoPtr scrn, 150103b705cfSriastradh short src_x, short src_y, 150203b705cfSriastradh short drw_x, short drw_y, 150303b705cfSriastradh short src_w, short src_h, 150403b705cfSriastradh short drw_w, short drw_h, 150503b705cfSriastradh int id, unsigned char *buf, 150603b705cfSriastradh short width, short height, 150703b705cfSriastradh Bool sync, RegionPtr clipBoxes, pointer data, 150803b705cfSriastradh DrawablePtr drawable) 150903b705cfSriastradh{ 151003b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 151103b705cfSriastradh intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data; 151203b705cfSriastradh PixmapPtr pixmap = get_drawable_pixmap(drawable); 151303b705cfSriastradh int dstPitch, dstPitch2; 151403b705cfSriastradh BoxRec dstBox; 151503b705cfSriastradh xf86CrtcPtr crtc; 151603b705cfSriastradh int top, left, npixels, nlines; 151703b705cfSriastradh 151803b705cfSriastradh if (!intel_pixmap_is_offscreen(pixmap)) 151903b705cfSriastradh return BadAlloc; 152003b705cfSriastradh 152103b705cfSriastradh#if 0 152203b705cfSriastradh ErrorF("I830PutImage: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d)\n" 152303b705cfSriastradh "width %d, height %d\n", src_x, src_y, src_w, src_h, drw_x, 152403b705cfSriastradh drw_y, drw_w, drw_h, width, height); 152503b705cfSriastradh#endif 152603b705cfSriastradh 152703b705cfSriastradh if (!intel_clip_video_helper(scrn, 152803b705cfSriastradh adaptor_priv, 152903b705cfSriastradh &crtc, 153003b705cfSriastradh &dstBox, 153103b705cfSriastradh src_x, src_y, drw_x, drw_y, 153203b705cfSriastradh src_w, src_h, drw_w, drw_h, 153303b705cfSriastradh id, 153403b705cfSriastradh &top, &left, &npixels, &nlines, clipBoxes, 153503b705cfSriastradh width, height)) 153603b705cfSriastradh return Success; 153703b705cfSriastradh 153803b705cfSriastradh if (xvmc_passthrough(id)) { 153903b705cfSriastradh uint32_t *gem_handle = (uint32_t *)buf; 154003b705cfSriastradh int size; 154103b705cfSriastradh 154203b705cfSriastradh intel_setup_dst_params(scrn, adaptor_priv, width, height, 154303b705cfSriastradh &dstPitch, &dstPitch2, &size, id); 154403b705cfSriastradh 154503b705cfSriastradh if (IS_I915G(intel) || IS_I915GM(intel)) { 154603b705cfSriastradh /* XXX: i915 is not support and needs some 154703b705cfSriastradh * serious care. grep for KMS in i915_hwmc.c */ 154803b705cfSriastradh return BadAlloc; 154903b705cfSriastradh } 155003b705cfSriastradh 155103b705cfSriastradh if (adaptor_priv->buf) 155203b705cfSriastradh drm_intel_bo_unreference(adaptor_priv->buf); 155303b705cfSriastradh 155403b705cfSriastradh adaptor_priv->buf = 155503b705cfSriastradh drm_intel_bo_gem_create_from_name(intel->bufmgr, 155603b705cfSriastradh "xvmc surface", 155703b705cfSriastradh *gem_handle); 155803b705cfSriastradh if (adaptor_priv->buf == NULL) 155903b705cfSriastradh return BadAlloc; 156003b705cfSriastradh 156103b705cfSriastradh adaptor_priv->reusable = FALSE; 156203b705cfSriastradh } else { 156303b705cfSriastradh if (!intel_copy_video_data(scrn, adaptor_priv, width, height, 156403b705cfSriastradh &dstPitch, &dstPitch2, 156503b705cfSriastradh top, left, npixels, nlines, id, buf)) 156603b705cfSriastradh return BadAlloc; 156703b705cfSriastradh } 156803b705cfSriastradh 156903b705cfSriastradh if (crtc && adaptor_priv->SyncToVblank != 0 && INTEL_INFO(intel)->gen < 060) { 157003b705cfSriastradh intel_wait_for_scanline(scrn, pixmap, crtc, clipBoxes); 157103b705cfSriastradh } 157203b705cfSriastradh 157303b705cfSriastradh if (INTEL_INFO(intel)->gen >= 060) { 157403b705cfSriastradh Gen6DisplayVideoTextured(scrn, adaptor_priv, id, clipBoxes, 157503b705cfSriastradh width, height, dstPitch, dstPitch2, 157603b705cfSriastradh src_w, src_h, 157703b705cfSriastradh drw_w, drw_h, pixmap); 157803b705cfSriastradh } else if (INTEL_INFO(intel)->gen >= 040) { 157903b705cfSriastradh I965DisplayVideoTextured(scrn, adaptor_priv, id, clipBoxes, 158003b705cfSriastradh width, height, dstPitch, dstPitch2, 158103b705cfSriastradh src_w, src_h, 158203b705cfSriastradh drw_w, drw_h, pixmap); 158303b705cfSriastradh } else { 158403b705cfSriastradh I915DisplayVideoTextured(scrn, adaptor_priv, id, clipBoxes, 158503b705cfSriastradh width, height, dstPitch, dstPitch2, 158603b705cfSriastradh src_w, src_h, drw_w, drw_h, 158703b705cfSriastradh pixmap); 158803b705cfSriastradh } 158903b705cfSriastradh 159003b705cfSriastradh intel_get_screen_private(scrn)->needs_flush = TRUE; 159103b705cfSriastradh DamageDamageRegion(drawable, clipBoxes); 159203b705cfSriastradh 159303b705cfSriastradh /* And make sure the WAIT_FOR_EVENT is queued before any 159403b705cfSriastradh * modesetting/dpms operations on the pipe. 159503b705cfSriastradh */ 159603b705cfSriastradh intel_batch_submit(scrn); 159703b705cfSriastradh 159803b705cfSriastradh return Success; 159903b705cfSriastradh} 160003b705cfSriastradh 160103b705cfSriastradhstatic int 160203b705cfSriastradhI830PutImageOverlay(ScrnInfoPtr scrn, 160303b705cfSriastradh short src_x, short src_y, 160403b705cfSriastradh short drw_x, short drw_y, 160503b705cfSriastradh short src_w, short src_h, 160603b705cfSriastradh short drw_w, short drw_h, 160703b705cfSriastradh int id, unsigned char *buf, 160803b705cfSriastradh short width, short height, 160903b705cfSriastradh Bool sync, RegionPtr clipBoxes, pointer data, 161003b705cfSriastradh DrawablePtr drawable) 161103b705cfSriastradh{ 161203b705cfSriastradh intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data; 161303b705cfSriastradh int dstPitch, dstPitch2; 161403b705cfSriastradh BoxRec dstBox; 161503b705cfSriastradh xf86CrtcPtr crtc; 161603b705cfSriastradh int top, left, npixels, nlines; 161703b705cfSriastradh 161803b705cfSriastradh#if 0 161903b705cfSriastradh ErrorF("I830PutImage: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d)\n" 162003b705cfSriastradh "width %d, height %d\n", src_x, src_y, src_w, src_h, drw_x, 162103b705cfSriastradh drw_y, drw_w, drw_h, width, height); 162203b705cfSriastradh#endif 162303b705cfSriastradh 162403b705cfSriastradh /* If dst width and height are less than 1/8th the src size, the 162503b705cfSriastradh * src/dst scale factor becomes larger than 8 and doesn't fit in 162603b705cfSriastradh * the scale register. */ 162703b705cfSriastradh if (src_w >= (drw_w * 8)) 162803b705cfSriastradh drw_w = src_w / 7; 162903b705cfSriastradh 163003b705cfSriastradh if (src_h >= (drw_h * 8)) 163103b705cfSriastradh drw_h = src_h / 7; 163203b705cfSriastradh 163303b705cfSriastradh if (!intel_clip_video_helper(scrn, 163403b705cfSriastradh adaptor_priv, 163503b705cfSriastradh &crtc, 163603b705cfSriastradh &dstBox, 163703b705cfSriastradh src_x, src_y, drw_x, drw_y, 163803b705cfSriastradh src_w, src_h, drw_w, drw_h, 163903b705cfSriastradh id, 164003b705cfSriastradh &top, &left, &npixels, &nlines, clipBoxes, 164103b705cfSriastradh width, height)) 164203b705cfSriastradh return Success; 164303b705cfSriastradh 164403b705cfSriastradh /* overlay can't handle rotation natively, store it for the copy func */ 164503b705cfSriastradh if (crtc) 164603b705cfSriastradh adaptor_priv->rotation = crtc->rotation; 164703b705cfSriastradh else { 164803b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_WARNING, 164903b705cfSriastradh "Fail to clip video to any crtc!\n"); 165003b705cfSriastradh return Success; 165103b705cfSriastradh } 165203b705cfSriastradh 165303b705cfSriastradh if (!intel_copy_video_data(scrn, adaptor_priv, width, height, 165403b705cfSriastradh &dstPitch, &dstPitch2, 165503b705cfSriastradh top, left, npixels, nlines, id, buf)) 165603b705cfSriastradh return BadAlloc; 165703b705cfSriastradh 165803b705cfSriastradh if (!intel_display_overlay 165903b705cfSriastradh (scrn, crtc, id, width, height, dstPitch, dstPitch2, 166003b705cfSriastradh &dstBox, src_w, src_h, drw_w, drw_h)) 166103b705cfSriastradh return BadAlloc; 166203b705cfSriastradh 166303b705cfSriastradh /* update cliplist */ 166403b705cfSriastradh if (!REGION_EQUAL(scrn->pScreen, &adaptor_priv->clip, clipBoxes)) { 166503b705cfSriastradh REGION_COPY(scrn->pScreen, &adaptor_priv->clip, clipBoxes); 166603b705cfSriastradh xf86XVFillKeyHelperDrawable(drawable, 166703b705cfSriastradh adaptor_priv->colorKey, 166803b705cfSriastradh clipBoxes); 166903b705cfSriastradh } 167003b705cfSriastradh 167103b705cfSriastradh adaptor_priv->videoStatus = CLIENT_VIDEO_ON; 167203b705cfSriastradh 167303b705cfSriastradh return Success; 167403b705cfSriastradh} 167503b705cfSriastradh 167603b705cfSriastradhstatic int 167703b705cfSriastradhI830QueryImageAttributes(ScrnInfoPtr scrn, 167803b705cfSriastradh int id, 167903b705cfSriastradh unsigned short *w, unsigned short *h, 168003b705cfSriastradh int *pitches, int *offsets) 168103b705cfSriastradh{ 168203b705cfSriastradh intel_screen_private *intel = intel_get_screen_private(scrn); 168303b705cfSriastradh int size, tmp; 168403b705cfSriastradh 168503b705cfSriastradh#if 0 168603b705cfSriastradh ErrorF("I830QueryImageAttributes: w is %d, h is %d\n", *w, *h); 168703b705cfSriastradh#endif 168803b705cfSriastradh 168903b705cfSriastradh if (IS_845G(intel) || IS_I830(intel)) { 169003b705cfSriastradh if (*w > IMAGE_MAX_WIDTH_LEGACY) 169103b705cfSriastradh *w = IMAGE_MAX_WIDTH_LEGACY; 169203b705cfSriastradh if (*h > IMAGE_MAX_HEIGHT_LEGACY) 169303b705cfSriastradh *h = IMAGE_MAX_HEIGHT_LEGACY; 169403b705cfSriastradh } else { 169503b705cfSriastradh if (*w > IMAGE_MAX_WIDTH) 169603b705cfSriastradh *w = IMAGE_MAX_WIDTH; 169703b705cfSriastradh if (*h > IMAGE_MAX_HEIGHT) 169803b705cfSriastradh *h = IMAGE_MAX_HEIGHT; 169903b705cfSriastradh } 170003b705cfSriastradh 170103b705cfSriastradh *w = (*w + 1) & ~1; 170203b705cfSriastradh if (offsets) 170303b705cfSriastradh offsets[0] = 0; 170403b705cfSriastradh 170503b705cfSriastradh switch (id) { 170603b705cfSriastradh /* IA44 is for XvMC only */ 170703b705cfSriastradh case FOURCC_IA44: 170803b705cfSriastradh case FOURCC_AI44: 170903b705cfSriastradh if (pitches) 171003b705cfSriastradh pitches[0] = *w; 171103b705cfSriastradh size = *w * *h; 171203b705cfSriastradh break; 171303b705cfSriastradh case FOURCC_YV12: 171403b705cfSriastradh case FOURCC_I420: 171503b705cfSriastradh *h = (*h + 1) & ~1; 171603b705cfSriastradh size = (*w + 3) & ~3; 171703b705cfSriastradh if (pitches) 171803b705cfSriastradh pitches[0] = size; 171903b705cfSriastradh size *= *h; 172003b705cfSriastradh if (offsets) 172103b705cfSriastradh offsets[1] = size; 172203b705cfSriastradh tmp = ((*w >> 1) + 3) & ~3; 172303b705cfSriastradh if (pitches) 172403b705cfSriastradh pitches[1] = pitches[2] = tmp; 172503b705cfSriastradh tmp *= (*h >> 1); 172603b705cfSriastradh size += tmp; 172703b705cfSriastradh if (offsets) 172803b705cfSriastradh offsets[2] = size; 172903b705cfSriastradh size += tmp; 173003b705cfSriastradh#if 0 173103b705cfSriastradh if (pitches) 173203b705cfSriastradh ErrorF("pitch 0 is %d, pitch 1 is %d, pitch 2 is %d\n", 173303b705cfSriastradh pitches[0], pitches[1], pitches[2]); 173403b705cfSriastradh if (offsets) 173503b705cfSriastradh ErrorF("offset 1 is %d, offset 2 is %d\n", offsets[1], 173603b705cfSriastradh offsets[2]); 173703b705cfSriastradh if (offsets) 173803b705cfSriastradh ErrorF("size is %d\n", size); 173903b705cfSriastradh#endif 174003b705cfSriastradh break; 174103b705cfSriastradh#ifdef INTEL_XVMC 174203b705cfSriastradh case FOURCC_XVMC: 174303b705cfSriastradh *h = (*h + 1) & ~1; 174403b705cfSriastradh size = sizeof(struct intel_xvmc_command); 174503b705cfSriastradh if (pitches) 174603b705cfSriastradh pitches[0] = size; 174703b705cfSriastradh break; 174803b705cfSriastradh#endif 174903b705cfSriastradh case FOURCC_UYVY: 175003b705cfSriastradh case FOURCC_YUY2: 175103b705cfSriastradh default: 175203b705cfSriastradh size = *w << 1; 175303b705cfSriastradh if (pitches) 175403b705cfSriastradh pitches[0] = size; 175503b705cfSriastradh size *= *h; 175603b705cfSriastradh break; 175703b705cfSriastradh } 175803b705cfSriastradh 175903b705cfSriastradh return size; 176003b705cfSriastradh} 176103b705cfSriastradh 176203b705cfSriastradhvoid 176303b705cfSriastradhintel_video_block_handler(intel_screen_private *intel) 176403b705cfSriastradh{ 176503b705cfSriastradh intel_adaptor_private *adaptor_priv; 176603b705cfSriastradh 176703b705cfSriastradh /* no overlay */ 176803b705cfSriastradh if (intel->adaptor == NULL) 176903b705cfSriastradh return; 177003b705cfSriastradh 177103b705cfSriastradh adaptor_priv = intel_get_adaptor_private(intel); 177203b705cfSriastradh if (adaptor_priv->videoStatus & OFF_TIMER) { 177303b705cfSriastradh Time now = currentTime.milliseconds; 177403b705cfSriastradh if (adaptor_priv->offTime < now) { 177503b705cfSriastradh /* Turn off the overlay */ 177603b705cfSriastradh intel_overlay_off(intel); 177703b705cfSriastradh intel_free_video_buffers(adaptor_priv); 177803b705cfSriastradh adaptor_priv->videoStatus = 0; 177903b705cfSriastradh } 178003b705cfSriastradh } 178103b705cfSriastradh} 1782