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