113496ba1Ssnj/***************************************************************************
213496ba1Ssnj
313496ba1Ssnj Copyright 2000 Intel Corporation.  All Rights Reserved.
413496ba1Ssnj
513496ba1Ssnj Permission is hereby granted, free of charge, to any person obtaining a
613496ba1Ssnj copy of this software and associated documentation files (the
713496ba1Ssnj "Software"), to deal in the Software without restriction, including
813496ba1Ssnj without limitation the rights to use, copy, modify, merge, publish,
913496ba1Ssnj distribute, sub license, and/or sell copies of the Software, and to
1013496ba1Ssnj permit persons to whom the Software is furnished to do so, subject to
1113496ba1Ssnj the following conditions:
1213496ba1Ssnj
1313496ba1Ssnj The above copyright notice and this permission notice (including the
1413496ba1Ssnj next paragraph) shall be included in all copies or substantial portions
1513496ba1Ssnj of the Software.
1613496ba1Ssnj
1713496ba1Ssnj THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1813496ba1Ssnj OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1913496ba1Ssnj MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2013496ba1Ssnj IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
2113496ba1Ssnj DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
2213496ba1Ssnj OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
2313496ba1Ssnj THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2413496ba1Ssnj
2513496ba1Ssnj **************************************************************************/
2613496ba1Ssnj
2713496ba1Ssnj/*
2813496ba1Ssnj * i830_video.c: i830/i845 Xv driver.
2913496ba1Ssnj *
3013496ba1Ssnj * Copyright © 2002 by Alan Hourihane and David Dawes
3113496ba1Ssnj *
3213496ba1Ssnj * Authors:
3313496ba1Ssnj *	Alan Hourihane <alanh@tungstengraphics.com>
3413496ba1Ssnj *	David Dawes <dawes@xfree86.org>
3513496ba1Ssnj *
3613496ba1Ssnj * Derived from i810 Xv driver:
3713496ba1Ssnj *
3813496ba1Ssnj * Authors of i810 code:
3913496ba1Ssnj * 	Jonathan Bian <jonathan.bian@intel.com>
4013496ba1Ssnj *      Offscreen Images:
4113496ba1Ssnj *        Matt Sottek <matthew.j.sottek@intel.com>
4213496ba1Ssnj */
4313496ba1Ssnj
4413496ba1Ssnj/*
4513496ba1Ssnj * XXX Could support more formats.
4613496ba1Ssnj */
4713496ba1Ssnj
4813496ba1Ssnj#ifdef HAVE_CONFIG_H
4913496ba1Ssnj#include "config.h"
5013496ba1Ssnj#endif
5113496ba1Ssnj
5213496ba1Ssnj#include <inttypes.h>
5313496ba1Ssnj#include <math.h>
5413496ba1Ssnj#include <string.h>
5513496ba1Ssnj#include <assert.h>
5613496ba1Ssnj#include <errno.h>
5713496ba1Ssnj
5813496ba1Ssnj#include "xorg-server.h"
5913496ba1Ssnj#include "xf86.h"
6013496ba1Ssnj#include "xf86_OSproc.h"
6113496ba1Ssnj#include "compiler.h"
6213496ba1Ssnj#include "xf86Pci.h"
6313496ba1Ssnj#include "xf86fbman.h"
6413496ba1Ssnj#include "xf86drm.h"
6513496ba1Ssnj#include "regionstr.h"
6613496ba1Ssnj#include "randrstr.h"
6713496ba1Ssnj#include "windowstr.h"
6813496ba1Ssnj#include "damage.h"
6913496ba1Ssnj#include "intel.h"
7013496ba1Ssnj#include "intel_video.h"
7113496ba1Ssnj#include "i830_reg.h"
7213496ba1Ssnj#include "xf86xv.h"
7313496ba1Ssnj#include <X11/extensions/Xv.h>
7413496ba1Ssnj#include "dixstruct.h"
7513496ba1Ssnj#include "fourcc.h"
7613496ba1Ssnj#include "intel_video_overlay.h"
7713496ba1Ssnj
7813496ba1Ssnj/* overlay debugging printf function */
7913496ba1Ssnj#if 0
8013496ba1Ssnj#define OVERLAY_DEBUG ErrorF
8113496ba1Ssnj#else
8213496ba1Ssnj#define OVERLAY_DEBUG if (0) ErrorF
8313496ba1Ssnj#endif
8413496ba1Ssnj
8513496ba1Ssnj/* kernel modesetting overlay functions */
8613496ba1Ssnjstatic Bool intel_has_overlay(intel_screen_private *intel)
8713496ba1Ssnj{
8813496ba1Ssnj	struct drm_i915_getparam gp;
8913496ba1Ssnj	int has_overlay = 0;
9013496ba1Ssnj	int ret;
9113496ba1Ssnj
9213496ba1Ssnj	gp.param = I915_PARAM_HAS_OVERLAY;
9313496ba1Ssnj	gp.value = &has_overlay;
9413496ba1Ssnj	ret = drmCommandWriteRead(intel->drmSubFD, DRM_I915_GETPARAM, &gp, sizeof(gp));
9513496ba1Ssnj
9613496ba1Ssnj	return ret == 0 && !! has_overlay;
9713496ba1Ssnj}
9813496ba1Ssnj
9913496ba1Ssnjstatic Bool intel_overlay_update_attrs(intel_screen_private *intel)
10013496ba1Ssnj{
10113496ba1Ssnj	intel_adaptor_private *adaptor_priv = intel_get_adaptor_private(intel);
10213496ba1Ssnj	struct drm_intel_overlay_attrs attrs;
10313496ba1Ssnj
10413496ba1Ssnj	attrs.flags = I915_OVERLAY_UPDATE_ATTRS;
10513496ba1Ssnj	attrs.brightness = adaptor_priv->brightness;
10613496ba1Ssnj	attrs.contrast = adaptor_priv->contrast;
10713496ba1Ssnj	attrs.saturation = adaptor_priv->saturation;
10813496ba1Ssnj	attrs.color_key = adaptor_priv->colorKey;
10913496ba1Ssnj	attrs.gamma0 = adaptor_priv->gamma0;
11013496ba1Ssnj	attrs.gamma1 = adaptor_priv->gamma1;
11113496ba1Ssnj	attrs.gamma2 = adaptor_priv->gamma2;
11213496ba1Ssnj	attrs.gamma3 = adaptor_priv->gamma3;
11313496ba1Ssnj	attrs.gamma4 = adaptor_priv->gamma4;
11413496ba1Ssnj	attrs.gamma5 = adaptor_priv->gamma5;
11513496ba1Ssnj
11613496ba1Ssnj	return drmCommandWriteRead(intel->drmSubFD, DRM_I915_OVERLAY_ATTRS,
11713496ba1Ssnj				   &attrs, sizeof(attrs)) == 0;
11813496ba1Ssnj}
11913496ba1Ssnj
12013496ba1Ssnjvoid intel_video_overlay_off(intel_screen_private *intel)
12113496ba1Ssnj{
12213496ba1Ssnj	struct drm_intel_overlay_put_image request;
12313496ba1Ssnj	int ret;
12413496ba1Ssnj
12513496ba1Ssnj	request.flags = 0;
12613496ba1Ssnj
12713496ba1Ssnj	ret = drmCommandWrite(intel->drmSubFD, DRM_I915_OVERLAY_PUT_IMAGE,
12813496ba1Ssnj			      &request, sizeof(request));
12913496ba1Ssnj	(void) ret;
13013496ba1Ssnj}
13113496ba1Ssnjstatic int
13213496ba1Ssnjintel_video_overlay_set_port_attribute(ScrnInfoPtr scrn,
13313496ba1Ssnj                                       Atom attribute, INT32 value, pointer data)
13413496ba1Ssnj{
13513496ba1Ssnj	intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data;
13613496ba1Ssnj	intel_screen_private *intel = intel_get_screen_private(scrn);
13713496ba1Ssnj
13813496ba1Ssnj	if (attribute == intel_xv_Brightness) {
13913496ba1Ssnj		if ((value < -128) || (value > 127))
14013496ba1Ssnj			return BadValue;
14113496ba1Ssnj		adaptor_priv->brightness = value;
14213496ba1Ssnj		OVERLAY_DEBUG("BRIGHTNESS\n");
14313496ba1Ssnj	} else if (attribute == intel_xv_Contrast) {
14413496ba1Ssnj		if ((value < 0) || (value > 255))
14513496ba1Ssnj			return BadValue;
14613496ba1Ssnj		adaptor_priv->contrast = value;
14713496ba1Ssnj		OVERLAY_DEBUG("CONTRAST\n");
14813496ba1Ssnj	} else if (attribute == intel_xv_Saturation) {
14913496ba1Ssnj		if ((value < 0) || (value > 1023))
15013496ba1Ssnj			return BadValue;
15113496ba1Ssnj		adaptor_priv->saturation = value;
15213496ba1Ssnj	} else if (attribute == intel_xv_Pipe) {
15313496ba1Ssnj		xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
15413496ba1Ssnj		if ((value < -1) || (value >= xf86_config->num_crtc))
15513496ba1Ssnj			return BadValue;
15613496ba1Ssnj		if (value < 0)
15713496ba1Ssnj			adaptor_priv->desired_crtc = NULL;
15813496ba1Ssnj		else
15913496ba1Ssnj			adaptor_priv->desired_crtc = xf86_config->crtc[value];
16013496ba1Ssnj	} else if (attribute == intel_xv_Gamma0 && (INTEL_INFO(intel)->gen >= 030)) {
16113496ba1Ssnj		adaptor_priv->gamma0 = value;
16213496ba1Ssnj	} else if (attribute == intel_xv_Gamma1 && (INTEL_INFO(intel)->gen >= 030)) {
16313496ba1Ssnj		adaptor_priv->gamma1 = value;
16413496ba1Ssnj	} else if (attribute == intel_xv_Gamma2 && (INTEL_INFO(intel)->gen >= 030)) {
16513496ba1Ssnj		adaptor_priv->gamma2 = value;
16613496ba1Ssnj	} else if (attribute == intel_xv_Gamma3 && (INTEL_INFO(intel)->gen >= 030)) {
16713496ba1Ssnj		adaptor_priv->gamma3 = value;
16813496ba1Ssnj	} else if (attribute == intel_xv_Gamma4 && (INTEL_INFO(intel)->gen >= 030)) {
16913496ba1Ssnj		adaptor_priv->gamma4 = value;
17013496ba1Ssnj	} else if (attribute == intel_xv_Gamma5 && (INTEL_INFO(intel)->gen >= 030)) {
17113496ba1Ssnj		adaptor_priv->gamma5 = value;
17213496ba1Ssnj	} else if (attribute == intel_xv_ColorKey) {
17313496ba1Ssnj		adaptor_priv->colorKey = value;
17413496ba1Ssnj		OVERLAY_DEBUG("COLORKEY\n");
17513496ba1Ssnj	} else
17613496ba1Ssnj		return BadMatch;
17713496ba1Ssnj
17813496ba1Ssnj	if ((attribute == intel_xv_Gamma0 ||
17913496ba1Ssnj	     attribute == intel_xv_Gamma1 ||
18013496ba1Ssnj	     attribute == intel_xv_Gamma2 ||
18113496ba1Ssnj	     attribute == intel_xv_Gamma3 ||
18213496ba1Ssnj	     attribute == intel_xv_Gamma4 ||
18313496ba1Ssnj	     attribute == intel_xv_Gamma5) && (INTEL_INFO(intel)->gen >= 030)) {
18413496ba1Ssnj		OVERLAY_DEBUG("GAMMA\n");
18513496ba1Ssnj	}
18613496ba1Ssnj
18713496ba1Ssnj	if (!intel_overlay_update_attrs(intel))
18813496ba1Ssnj		return BadValue;
18913496ba1Ssnj
19013496ba1Ssnj	if (attribute == intel_xv_ColorKey)
19113496ba1Ssnj		REGION_EMPTY(scrn->pScreen, &adaptor_priv->clip);
19213496ba1Ssnj
19313496ba1Ssnj	return Success;
19413496ba1Ssnj}
19513496ba1Ssnj
19613496ba1Ssnjstatic Bool
19713496ba1Ssnjintel_overlay_put_image(intel_screen_private *intel,
19813496ba1Ssnj                        xf86CrtcPtr crtc,
19913496ba1Ssnj                        int id, short width, short height,
20013496ba1Ssnj                        int dstPitch, int dstPitch2,
20113496ba1Ssnj                        BoxPtr dstBox, short src_w, short src_h, short drw_w,
20213496ba1Ssnj                        short drw_h)
20313496ba1Ssnj{
20413496ba1Ssnj	intel_adaptor_private *adaptor_priv = intel_get_adaptor_private(intel);
20513496ba1Ssnj	struct drm_intel_overlay_put_image request;
20613496ba1Ssnj	int ret;
20713496ba1Ssnj	int planar = is_planar_fourcc(id);
20813496ba1Ssnj	float scale;
20913496ba1Ssnj	dri_bo *tmp;
21013496ba1Ssnj
21113496ba1Ssnj	request.flags = I915_OVERLAY_ENABLE;
21213496ba1Ssnj
21313496ba1Ssnj	request.bo_handle = adaptor_priv->buf->handle;
21413496ba1Ssnj	if (planar) {
21513496ba1Ssnj		request.stride_Y = dstPitch2;
21613496ba1Ssnj		request.stride_UV = dstPitch;
21713496ba1Ssnj	} else {
21813496ba1Ssnj		request.stride_Y = dstPitch;
21913496ba1Ssnj		request.stride_UV = 0;
22013496ba1Ssnj	}
22113496ba1Ssnj	request.offset_Y = adaptor_priv->YBufOffset;
22213496ba1Ssnj	request.offset_U = adaptor_priv->UBufOffset;
22313496ba1Ssnj	request.offset_V = adaptor_priv->VBufOffset;
22413496ba1Ssnj	OVERLAY_DEBUG("off_Y: %i, off_U: %i, off_V: %i\n", request.offset_Y,
22513496ba1Ssnj		      request.offset_U, request.offset_V);
22613496ba1Ssnj
22713496ba1Ssnj	request.crtc_id = intel_crtc_id(crtc);
22813496ba1Ssnj	request.dst_x = dstBox->x1;
22913496ba1Ssnj	request.dst_y = dstBox->y1;
23013496ba1Ssnj	request.dst_width = dstBox->x2 - dstBox->x1;
23113496ba1Ssnj	request.dst_height = dstBox->y2 - dstBox->y1;
23213496ba1Ssnj
23313496ba1Ssnj	request.src_width = width;
23413496ba1Ssnj	request.src_height = height;
23513496ba1Ssnj	/* adjust src dimensions */
23613496ba1Ssnj	if (request.dst_height > 1) {
23713496ba1Ssnj		scale = ((float)request.dst_height - 1) / ((float)drw_h - 1);
23813496ba1Ssnj		request.src_scan_height = src_h * scale;
23913496ba1Ssnj	} else
24013496ba1Ssnj		request.src_scan_height = 1;
24113496ba1Ssnj
24213496ba1Ssnj	if (request.dst_width > 1) {
24313496ba1Ssnj		scale = ((float)request.dst_width - 1) / ((float)drw_w - 1);
24413496ba1Ssnj		request.src_scan_width = src_w * scale;
24513496ba1Ssnj	} else
24613496ba1Ssnj		request.src_scan_width = 1;
24713496ba1Ssnj
24813496ba1Ssnj	if (planar) {
24913496ba1Ssnj		request.flags |= I915_OVERLAY_YUV_PLANAR | I915_OVERLAY_YUV420;
25013496ba1Ssnj	} else {
25113496ba1Ssnj		request.flags |= I915_OVERLAY_YUV_PACKED | I915_OVERLAY_YUV422;
25213496ba1Ssnj		if (id == FOURCC_UYVY)
25313496ba1Ssnj			request.flags |= I915_OVERLAY_Y_SWAP;
25413496ba1Ssnj	}
25513496ba1Ssnj
25613496ba1Ssnj	ret = drmCommandWrite(intel->drmSubFD, DRM_I915_OVERLAY_PUT_IMAGE,
25713496ba1Ssnj			      &request, sizeof(request));
25813496ba1Ssnj	if (ret)
25913496ba1Ssnj		return FALSE;
26013496ba1Ssnj
26113496ba1Ssnj	if (!adaptor_priv->reusable) {
26213496ba1Ssnj		drm_intel_bo_unreference(adaptor_priv->buf);
26313496ba1Ssnj		adaptor_priv->buf = NULL;
26413496ba1Ssnj		adaptor_priv->reusable = TRUE;
26513496ba1Ssnj	}
26613496ba1Ssnj
26713496ba1Ssnj	tmp = adaptor_priv->old_buf[1];
26813496ba1Ssnj	adaptor_priv->old_buf[1] = adaptor_priv->old_buf[0];
26913496ba1Ssnj	adaptor_priv->old_buf[0] = adaptor_priv->buf;
27013496ba1Ssnj	adaptor_priv->buf = tmp;
27113496ba1Ssnj
27213496ba1Ssnj	return TRUE;
27313496ba1Ssnj}
27413496ba1Ssnj
27513496ba1Ssnjstatic void
27613496ba1Ssnjintel_update_dst_box_to_crtc_coords(ScrnInfoPtr scrn, xf86CrtcPtr crtc,
27713496ba1Ssnj				    BoxPtr dstBox)
27813496ba1Ssnj{
27913496ba1Ssnj	int tmp;
28013496ba1Ssnj
28113496ba1Ssnj	/* for overlay, we should take it from crtc's screen
28213496ba1Ssnj	 * coordinate to current crtc's display mode.
28313496ba1Ssnj	 * yeah, a bit confusing.
28413496ba1Ssnj	 */
28513496ba1Ssnj	switch (crtc->rotation & 0xf) {
28613496ba1Ssnj	case RR_Rotate_0:
28713496ba1Ssnj		dstBox->x1 -= crtc->x;
28813496ba1Ssnj		dstBox->x2 -= crtc->x;
28913496ba1Ssnj		dstBox->y1 -= crtc->y;
29013496ba1Ssnj		dstBox->y2 -= crtc->y;
29113496ba1Ssnj		break;
29213496ba1Ssnj	case RR_Rotate_90:
29313496ba1Ssnj		tmp = dstBox->x1;
29413496ba1Ssnj		dstBox->x1 = dstBox->y1 - crtc->x;
29513496ba1Ssnj		dstBox->y1 = scrn->virtualX - tmp - crtc->y;
29613496ba1Ssnj		tmp = dstBox->x2;
29713496ba1Ssnj		dstBox->x2 = dstBox->y2 - crtc->x;
29813496ba1Ssnj		dstBox->y2 = scrn->virtualX - tmp - crtc->y;
29913496ba1Ssnj		tmp = dstBox->y1;
30013496ba1Ssnj		dstBox->y1 = dstBox->y2;
30113496ba1Ssnj		dstBox->y2 = tmp;
30213496ba1Ssnj		break;
30313496ba1Ssnj	case RR_Rotate_180:
30413496ba1Ssnj		tmp = dstBox->x1;
30513496ba1Ssnj		dstBox->x1 = scrn->virtualX - dstBox->x2 - crtc->x;
30613496ba1Ssnj		dstBox->x2 = scrn->virtualX - tmp - crtc->x;
30713496ba1Ssnj		tmp = dstBox->y1;
30813496ba1Ssnj		dstBox->y1 = scrn->virtualY - dstBox->y2 - crtc->y;
30913496ba1Ssnj		dstBox->y2 = scrn->virtualY - tmp - crtc->y;
31013496ba1Ssnj		break;
31113496ba1Ssnj	case RR_Rotate_270:
31213496ba1Ssnj		tmp = dstBox->x1;
31313496ba1Ssnj		dstBox->x1 = scrn->virtualY - dstBox->y1 - crtc->x;
31413496ba1Ssnj		dstBox->y1 = tmp - crtc->y;
31513496ba1Ssnj		tmp = dstBox->x2;
31613496ba1Ssnj		dstBox->x2 = scrn->virtualY - dstBox->y2 - crtc->x;
31713496ba1Ssnj		dstBox->y2 = tmp - crtc->y;
31813496ba1Ssnj		tmp = dstBox->x1;
31913496ba1Ssnj		dstBox->x1 = dstBox->x2;
32013496ba1Ssnj		dstBox->x2 = tmp;
32113496ba1Ssnj		break;
32213496ba1Ssnj	}
32313496ba1Ssnj
32413496ba1Ssnj	return;
32513496ba1Ssnj}
32613496ba1Ssnj
32713496ba1Ssnjstatic Bool
32813496ba1Ssnjintel_video_overlay_display(ScrnInfoPtr scrn, xf86CrtcPtr crtc,
32913496ba1Ssnj                            int id, short width, short height,
33013496ba1Ssnj                            int dstPitch, int dstPitch2,
33113496ba1Ssnj                            BoxPtr dstBox, short src_w, short src_h, short drw_w,
33213496ba1Ssnj                            short drw_h)
33313496ba1Ssnj{
33413496ba1Ssnj	intel_screen_private *intel = intel_get_screen_private(scrn);
33513496ba1Ssnj	int tmp;
33613496ba1Ssnj
33713496ba1Ssnj	OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
33813496ba1Ssnj		      dstPitch);
33913496ba1Ssnj
34013496ba1Ssnj	/*
34113496ba1Ssnj	 * If the video isn't visible on any CRTC, turn it off
34213496ba1Ssnj	 */
34313496ba1Ssnj	if (!crtc) {
34413496ba1Ssnj		intel_video_overlay_off(intel);
34513496ba1Ssnj		return TRUE;
34613496ba1Ssnj	}
34713496ba1Ssnj
34813496ba1Ssnj	intel_update_dst_box_to_crtc_coords(scrn, crtc, dstBox);
34913496ba1Ssnj
35013496ba1Ssnj	if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
35113496ba1Ssnj		tmp = width;
35213496ba1Ssnj		width = height;
35313496ba1Ssnj		height = tmp;
35413496ba1Ssnj		tmp = drw_w;
35513496ba1Ssnj		drw_w = drw_h;
35613496ba1Ssnj		drw_h = tmp;
35713496ba1Ssnj		tmp = src_w;
35813496ba1Ssnj		src_w = src_h;
35913496ba1Ssnj		src_h = tmp;
36013496ba1Ssnj	}
36113496ba1Ssnj
36213496ba1Ssnj	return intel_overlay_put_image(intel, crtc, id,
36313496ba1Ssnj					 width, height,
36413496ba1Ssnj					 dstPitch, dstPitch2, dstBox,
36513496ba1Ssnj					 src_w, src_h, drw_w, drw_h);
36613496ba1Ssnj}
36713496ba1Ssnj
36813496ba1Ssnjstatic int
36913496ba1Ssnjintel_video_overlay_put_image(ScrnInfoPtr scrn,
37013496ba1Ssnj                              short src_x, short src_y,
37113496ba1Ssnj                              short drw_x, short drw_y,
37213496ba1Ssnj                              short src_w, short src_h,
37313496ba1Ssnj                              short drw_w, short drw_h,
37413496ba1Ssnj                              int id, unsigned char *buf,
37513496ba1Ssnj                              short width, short height,
37613496ba1Ssnj                              Bool sync, RegionPtr clipBoxes, pointer data,
37713496ba1Ssnj                              DrawablePtr drawable)
37813496ba1Ssnj{
37913496ba1Ssnj	intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data;
38013496ba1Ssnj	int dstPitch, dstPitch2;
38113496ba1Ssnj	BoxRec dstBox;
38213496ba1Ssnj	xf86CrtcPtr crtc;
38313496ba1Ssnj	int top, left, npixels, nlines;
38413496ba1Ssnj
38513496ba1Ssnj#if 0
38613496ba1Ssnj	ErrorF("I830PutImage: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d)\n"
38713496ba1Ssnj	       "width %d, height %d\n", src_x, src_y, src_w, src_h, drw_x,
38813496ba1Ssnj	       drw_y, drw_w, drw_h, width, height);
38913496ba1Ssnj#endif
39013496ba1Ssnj
39113496ba1Ssnj	/* If dst width and height are less than 1/8th the src size, the
39213496ba1Ssnj	 * src/dst scale factor becomes larger than 8 and doesn't fit in
39313496ba1Ssnj	 * the scale register. */
39413496ba1Ssnj	if (src_w >= (drw_w * 8))
39513496ba1Ssnj		drw_w = src_w / 7;
39613496ba1Ssnj
39713496ba1Ssnj	if (src_h >= (drw_h * 8))
39813496ba1Ssnj		drw_h = src_h / 7;
39913496ba1Ssnj
40013496ba1Ssnj	if (!intel_clip_video_helper(scrn,
40113496ba1Ssnj				    adaptor_priv,
40213496ba1Ssnj				    &crtc,
40313496ba1Ssnj				    &dstBox,
40413496ba1Ssnj				    src_x, src_y, drw_x, drw_y,
40513496ba1Ssnj				    src_w, src_h, drw_w, drw_h,
40613496ba1Ssnj				    id,
40713496ba1Ssnj				    &top, &left, &npixels, &nlines, clipBoxes,
40813496ba1Ssnj				    width, height))
40913496ba1Ssnj		return Success;
41013496ba1Ssnj
41113496ba1Ssnj	/* overlay can't handle rotation natively, store it for the copy func */
41213496ba1Ssnj	if (crtc)
41313496ba1Ssnj		adaptor_priv->rotation = crtc->rotation;
41413496ba1Ssnj	else {
41513496ba1Ssnj		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
41613496ba1Ssnj			   "Fail to clip video to any crtc!\n");
41713496ba1Ssnj		return Success;
41813496ba1Ssnj	}
41913496ba1Ssnj
42013496ba1Ssnj	if (!intel_video_copy_data(scrn, adaptor_priv, width, height,
42113496ba1Ssnj				  &dstPitch, &dstPitch2,
42213496ba1Ssnj				  top, left, npixels, nlines, id, buf))
42313496ba1Ssnj		return BadAlloc;
42413496ba1Ssnj
42513496ba1Ssnj	if (!intel_video_overlay_display
42613496ba1Ssnj	    (scrn, crtc, id, width, height, dstPitch, dstPitch2,
42713496ba1Ssnj	     &dstBox, src_w, src_h, drw_w, drw_h))
42813496ba1Ssnj		return BadAlloc;
42913496ba1Ssnj
43013496ba1Ssnj	/* update cliplist */
43113496ba1Ssnj	if (!REGION_EQUAL(scrn->pScreen, &adaptor_priv->clip, clipBoxes)) {
43213496ba1Ssnj		REGION_COPY(scrn->pScreen, &adaptor_priv->clip, clipBoxes);
43313496ba1Ssnj		xf86XVFillKeyHelperDrawable(drawable,
43413496ba1Ssnj					    adaptor_priv->colorKey,
43513496ba1Ssnj					    clipBoxes);
43613496ba1Ssnj	}
43713496ba1Ssnj
43813496ba1Ssnj	adaptor_priv->videoStatus = CLIENT_VIDEO_ON;
43913496ba1Ssnj
44013496ba1Ssnj	return Success;
44113496ba1Ssnj}
44213496ba1Ssnj
44313496ba1SsnjXF86VideoAdaptorPtr intel_video_overlay_setup_image(ScreenPtr screen)
44413496ba1Ssnj{
44513496ba1Ssnj	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
44613496ba1Ssnj	intel_screen_private *intel = intel_get_screen_private(scrn);
44713496ba1Ssnj	XF86VideoAdaptorPtr adapt;
44813496ba1Ssnj	intel_adaptor_private *adaptor_priv;
44913496ba1Ssnj	XF86AttributePtr att;
45013496ba1Ssnj
45113496ba1Ssnj	/* Set up overlay video if it is available */
45213496ba1Ssnj	intel->use_overlay = intel_has_overlay(intel);
45313496ba1Ssnj	if (!intel->use_overlay)
45413496ba1Ssnj                return NULL;
45513496ba1Ssnj
45613496ba1Ssnj	OVERLAY_DEBUG("intel_video_overlay_setup_image\n");
45713496ba1Ssnj
45813496ba1Ssnj	if (!(adapt = calloc(1,
45913496ba1Ssnj			     sizeof(XF86VideoAdaptorRec) +
46013496ba1Ssnj			     sizeof(intel_adaptor_private) +
46113496ba1Ssnj			     sizeof(DevUnion))))
46213496ba1Ssnj		return NULL;
46313496ba1Ssnj
46413496ba1Ssnj	adapt->type = XvWindowMask | XvInputMask | XvImageMask;
46513496ba1Ssnj	adapt->flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT */ ;
46613496ba1Ssnj	adapt->name = "Intel(R) Video Overlay";
46713496ba1Ssnj	adapt->nEncodings = 1;
46813496ba1Ssnj	adapt->pEncodings = xnfalloc(sizeof(intel_xv_dummy_encoding));
46913496ba1Ssnj	memcpy(adapt->pEncodings, intel_xv_dummy_encoding, sizeof(intel_xv_dummy_encoding));
47013496ba1Ssnj	if (IS_845G(intel) || IS_I830(intel)) {
47113496ba1Ssnj		adapt->pEncodings->width = IMAGE_MAX_WIDTH_LEGACY;
47213496ba1Ssnj		adapt->pEncodings->height = IMAGE_MAX_HEIGHT_LEGACY;
47313496ba1Ssnj	}
47413496ba1Ssnj	adapt->nFormats = NUM_FORMATS;
47513496ba1Ssnj	adapt->pFormats = intel_xv_formats;
47613496ba1Ssnj	adapt->nPorts = 1;
47713496ba1Ssnj	adapt->pPortPrivates = (DevUnion *) (&adapt[1]);
47813496ba1Ssnj
47913496ba1Ssnj	adaptor_priv = (intel_adaptor_private *)&adapt->pPortPrivates[1];
48013496ba1Ssnj
48113496ba1Ssnj	adapt->pPortPrivates[0].ptr = (pointer) (adaptor_priv);
48213496ba1Ssnj	adapt->nAttributes = NUM_ATTRIBUTES;
48313496ba1Ssnj	if (INTEL_INFO(intel)->gen >= 030)
48413496ba1Ssnj		adapt->nAttributes += GAMMA_ATTRIBUTES;	/* has gamma */
48513496ba1Ssnj	adapt->pAttributes =
48613496ba1Ssnj	    xnfalloc(sizeof(XF86AttributeRec) * adapt->nAttributes);
48713496ba1Ssnj	/* Now copy the attributes */
48813496ba1Ssnj	att = adapt->pAttributes;
48913496ba1Ssnj	memcpy((char *)att, (char *)intel_xv_attributes,
49013496ba1Ssnj	       sizeof(XF86AttributeRec) * NUM_ATTRIBUTES);
49113496ba1Ssnj	att += NUM_ATTRIBUTES;
49213496ba1Ssnj	if (INTEL_INFO(intel)->gen >= 030) {
49313496ba1Ssnj		memcpy((char *)att, (char *)intel_xv_gamma_attributes,
49413496ba1Ssnj		       sizeof(XF86AttributeRec) * GAMMA_ATTRIBUTES);
49513496ba1Ssnj	}
49613496ba1Ssnj	adapt->nImages = NUM_IMAGES - XVMC_IMAGE;
49713496ba1Ssnj
49813496ba1Ssnj	adapt->pImages = intel_xv_images;
49913496ba1Ssnj	adapt->PutVideo = NULL;
50013496ba1Ssnj	adapt->PutStill = NULL;
50113496ba1Ssnj	adapt->GetVideo = NULL;
50213496ba1Ssnj	adapt->GetStill = NULL;
50313496ba1Ssnj	adapt->StopVideo = intel_video_stop_video;
50413496ba1Ssnj	adapt->SetPortAttribute = intel_video_overlay_set_port_attribute;
50513496ba1Ssnj	adapt->GetPortAttribute = intel_video_get_port_attribute;
50613496ba1Ssnj	adapt->QueryBestSize = intel_video_query_best_size;
50713496ba1Ssnj	adapt->PutImage = intel_video_overlay_put_image;
50813496ba1Ssnj	adapt->QueryImageAttributes = intel_video_query_image_attributes;
50913496ba1Ssnj
51013496ba1Ssnj	adaptor_priv->textured = FALSE;
51113496ba1Ssnj	adaptor_priv->colorKey = intel->colorKey & ((1 << scrn->depth) - 1);
51213496ba1Ssnj	adaptor_priv->videoStatus = 0;
51313496ba1Ssnj	adaptor_priv->brightness = -19;	/* (255/219) * -16 */
51413496ba1Ssnj	adaptor_priv->contrast = 75;	/* 255/219 * 64 */
51513496ba1Ssnj	adaptor_priv->saturation = 146;	/* 128/112 * 128 */
51613496ba1Ssnj	adaptor_priv->desired_crtc = NULL;
51713496ba1Ssnj	adaptor_priv->buf = NULL;
51813496ba1Ssnj	adaptor_priv->old_buf[0] = NULL;
51913496ba1Ssnj	adaptor_priv->old_buf[1] = NULL;
52013496ba1Ssnj	adaptor_priv->gamma5 = 0xc0c0c0;
52113496ba1Ssnj	adaptor_priv->gamma4 = 0x808080;
52213496ba1Ssnj	adaptor_priv->gamma3 = 0x404040;
52313496ba1Ssnj	adaptor_priv->gamma2 = 0x202020;
52413496ba1Ssnj	adaptor_priv->gamma1 = 0x101010;
52513496ba1Ssnj	adaptor_priv->gamma0 = 0x080808;
52613496ba1Ssnj
52713496ba1Ssnj	adaptor_priv->rotation = RR_Rotate_0;
52813496ba1Ssnj
52913496ba1Ssnj	/* gotta uninit this someplace */
53013496ba1Ssnj	REGION_NULL(screen, &adaptor_priv->clip);
53113496ba1Ssnj
53213496ba1Ssnj	intel->adaptor = adapt;
53313496ba1Ssnj
53413496ba1Ssnj	intel_xv_ColorKey = MAKE_ATOM("XV_COLORKEY");
53513496ba1Ssnj	intel_xv_Brightness = MAKE_ATOM("XV_BRIGHTNESS");
53613496ba1Ssnj	intel_xv_Contrast = MAKE_ATOM("XV_CONTRAST");
53713496ba1Ssnj	intel_xv_Saturation = MAKE_ATOM("XV_SATURATION");
53813496ba1Ssnj
53913496ba1Ssnj	/* Allow the pipe to be switched from pipe A to B when in clone mode */
54013496ba1Ssnj	intel_xv_Pipe = MAKE_ATOM("XV_PIPE");
54113496ba1Ssnj
54213496ba1Ssnj	if (INTEL_INFO(intel)->gen >= 030) {
54313496ba1Ssnj		intel_xv_Gamma0 = MAKE_ATOM("XV_GAMMA0");
54413496ba1Ssnj		intel_xv_Gamma1 = MAKE_ATOM("XV_GAMMA1");
54513496ba1Ssnj		intel_xv_Gamma2 = MAKE_ATOM("XV_GAMMA2");
54613496ba1Ssnj		intel_xv_Gamma3 = MAKE_ATOM("XV_GAMMA3");
54713496ba1Ssnj		intel_xv_Gamma4 = MAKE_ATOM("XV_GAMMA4");
54813496ba1Ssnj		intel_xv_Gamma5 = MAKE_ATOM("XV_GAMMA5");
54913496ba1Ssnj	}
55013496ba1Ssnj
55113496ba1Ssnj	intel_overlay_update_attrs(intel);
55213496ba1Ssnj
55313496ba1Ssnj	return adapt;
55413496ba1Ssnj}
555