1428d7b3dSmrg/***************************************************************************
2428d7b3dSmrg
3428d7b3dSmrg Copyright 2000-2011 Intel Corporation.  All Rights Reserved.
4428d7b3dSmrg
5428d7b3dSmrg Permission is hereby granted, free of charge, to any person obtaining a
6428d7b3dSmrg copy of this software and associated documentation files (the
7428d7b3dSmrg "Software"), to deal in the Software without restriction, including
8428d7b3dSmrg without limitation the rights to use, copy, modify, merge, publish,
9428d7b3dSmrg distribute, sub license, and/or sell copies of the Software, and to
10428d7b3dSmrg permit persons to whom the Software is furnished to do so, subject to
11428d7b3dSmrg the following conditions:
12428d7b3dSmrg
13428d7b3dSmrg The above copyright notice and this permission notice (including the
14428d7b3dSmrg next paragraph) shall be included in all copies or substantial portions
15428d7b3dSmrg of the Software.
16428d7b3dSmrg
17428d7b3dSmrg THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18428d7b3dSmrg OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19428d7b3dSmrg MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20428d7b3dSmrg IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
21428d7b3dSmrg DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22428d7b3dSmrg OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
23428d7b3dSmrg THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24428d7b3dSmrg
25428d7b3dSmrg **************************************************************************/
26428d7b3dSmrg
27428d7b3dSmrg#ifdef HAVE_CONFIG_H
28428d7b3dSmrg#include "config.h"
29428d7b3dSmrg#endif
30428d7b3dSmrg
31428d7b3dSmrg#include "sna.h"
32428d7b3dSmrg#include "sna_video.h"
33428d7b3dSmrg
34428d7b3dSmrg#include <xf86drm.h>
35428d7b3dSmrg#include <xf86xv.h>
36428d7b3dSmrg#include <X11/extensions/Xv.h>
37428d7b3dSmrg#include <fourcc.h>
38428d7b3dSmrg#include <i915_drm.h>
39428d7b3dSmrg
40428d7b3dSmrg#include "intel_options.h"
41428d7b3dSmrg
42428d7b3dSmrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
43428d7b3dSmrg
44428d7b3dSmrg#define HAS_GAMMA(sna) ((sna)->kgem.gen >= 030)
45428d7b3dSmrg
46428d7b3dSmrgstatic Atom xvBrightness, xvContrast, xvSaturation, xvColorKey, xvPipe, xvAlwaysOnTop;
47428d7b3dSmrgstatic Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5;
48428d7b3dSmrg
49428d7b3dSmrg/* Limits for the overlay/textured video source sizes.  The documented hardware
50428d7b3dSmrg * limits are 2048x2048 or better for overlay and both of our textured video
51428d7b3dSmrg * implementations.  Additionally, on the 830 and 845, larger sizes resulted in
52428d7b3dSmrg * the card hanging, so we keep the limits lower there.
53428d7b3dSmrg */
54428d7b3dSmrg#define IMAGE_MAX_WIDTH		2048
55428d7b3dSmrg#define IMAGE_MAX_HEIGHT	2048
56428d7b3dSmrg#define IMAGE_MAX_WIDTH_LEGACY	1024
57428d7b3dSmrg#define IMAGE_MAX_HEIGHT_LEGACY	1088
58428d7b3dSmrg
59428d7b3dSmrgstatic XvFormatRec Formats[] = { {15}, {16}, {24} };
60428d7b3dSmrg
61428d7b3dSmrgstatic const XvAttributeRec Attributes[] = {
62428d7b3dSmrg	{XvSettable | XvGettable, 0, (1 << 24) - 1, (char *)"XV_COLORKEY"},
63428d7b3dSmrg	{XvSettable | XvGettable, 0, 1, (char *)"XV_ALWAYS_ON_TOP"},
64428d7b3dSmrg	{XvSettable | XvGettable, -128, 127, (char *)"XV_BRIGHTNESS"},
65428d7b3dSmrg	{XvSettable | XvGettable, 0, 255, (char *)"XV_CONTRAST"},
66428d7b3dSmrg	{XvSettable | XvGettable, 0, 1023, (char *)"XV_SATURATION"},
67428d7b3dSmrg	{XvSettable | XvGettable, -1, 1, (char *)"XV_PIPE"},
68428d7b3dSmrg#define NUM_ATTRIBUTES 6
69428d7b3dSmrg
70428d7b3dSmrg	{XvSettable | XvGettable, 0, 0xffffff, (char *)"XV_GAMMA0"},
71428d7b3dSmrg	{XvSettable | XvGettable, 0, 0xffffff, (char *)"XV_GAMMA1"},
72428d7b3dSmrg	{XvSettable | XvGettable, 0, 0xffffff, (char *)"XV_GAMMA2"},
73428d7b3dSmrg	{XvSettable | XvGettable, 0, 0xffffff, (char *)"XV_GAMMA3"},
74428d7b3dSmrg	{XvSettable | XvGettable, 0, 0xffffff, (char *)"XV_GAMMA4"},
75428d7b3dSmrg	{XvSettable | XvGettable, 0, 0xffffff, (char *)"XV_GAMMA5"}
76428d7b3dSmrg#define GAMMA_ATTRIBUTES 6
77428d7b3dSmrg};
78428d7b3dSmrg
79428d7b3dSmrgstatic const XvImageRec Images[] = {
80428d7b3dSmrg	XVIMAGE_YUY2,
81428d7b3dSmrg	XVIMAGE_YV12,
82428d7b3dSmrg	XVIMAGE_I420,
83428d7b3dSmrg	XVIMAGE_UYVY,
84428d7b3dSmrg	XVMC_YUV
85428d7b3dSmrg};
86428d7b3dSmrg
87428d7b3dSmrg/* kernel modesetting overlay functions */
88428d7b3dSmrgstatic bool sna_has_overlay(struct sna *sna)
89428d7b3dSmrg{
90428d7b3dSmrg	struct drm_i915_getparam gp;
91428d7b3dSmrg	int has_overlay = 0;
92428d7b3dSmrg	int ret;
93428d7b3dSmrg
94428d7b3dSmrg	VG_CLEAR(gp);
95428d7b3dSmrg	gp.param = I915_PARAM_HAS_OVERLAY;
96428d7b3dSmrg	gp.value = &has_overlay;
97428d7b3dSmrg	ret = drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GETPARAM, &gp);
98428d7b3dSmrg	return ret == 0 && has_overlay;
99428d7b3dSmrg}
100428d7b3dSmrg
101428d7b3dSmrgstatic bool sna_video_overlay_update_attrs(struct sna_video *video)
102428d7b3dSmrg{
103428d7b3dSmrg	struct drm_intel_overlay_attrs attrs;
104428d7b3dSmrg
105428d7b3dSmrg	DBG(("%s()\n", __FUNCTION__));
106428d7b3dSmrg
107428d7b3dSmrg	attrs.flags = I915_OVERLAY_UPDATE_ATTRS;
108428d7b3dSmrg	attrs.brightness = video->brightness;
109428d7b3dSmrg	attrs.contrast = video->contrast;
110428d7b3dSmrg	attrs.saturation = video->saturation;
111428d7b3dSmrg	attrs.color_key = video->color_key;
112428d7b3dSmrg	attrs.gamma0 = video->gamma0;
113428d7b3dSmrg	attrs.gamma1 = video->gamma1;
114428d7b3dSmrg	attrs.gamma2 = video->gamma2;
115428d7b3dSmrg	attrs.gamma3 = video->gamma3;
116428d7b3dSmrg	attrs.gamma4 = video->gamma4;
117428d7b3dSmrg	attrs.gamma5 = video->gamma5;
118428d7b3dSmrg
119428d7b3dSmrg	if (video->AlwaysOnTop)
120428d7b3dSmrg		attrs.flags |= 1<<2;
121428d7b3dSmrg
122428d7b3dSmrg	return drmIoctl(video->sna->kgem.fd, DRM_IOCTL_I915_OVERLAY_ATTRS, &attrs) == 0;
123428d7b3dSmrg}
124428d7b3dSmrg
125428d7b3dSmrgstatic int sna_video_overlay_stop(ddStopVideo_ARGS)
126428d7b3dSmrg{
127428d7b3dSmrg	struct sna_video *video = port->devPriv.ptr;
128428d7b3dSmrg	struct sna *sna = video->sna;
129428d7b3dSmrg	struct drm_intel_overlay_put_image request;
130428d7b3dSmrg
131428d7b3dSmrg	DBG(("%s()\n", __FUNCTION__));
132428d7b3dSmrg
133428d7b3dSmrg	REGION_EMPTY(scrn->pScreen, &video->clip);
134428d7b3dSmrg
135428d7b3dSmrg	request.flags = 0;
136428d7b3dSmrg	(void)drmIoctl(sna->kgem.fd,
137428d7b3dSmrg		       DRM_IOCTL_I915_OVERLAY_PUT_IMAGE,
138428d7b3dSmrg		       &request);
139428d7b3dSmrg
140428d7b3dSmrg	if (video->bo[0])
141428d7b3dSmrg		kgem_bo_destroy(&sna->kgem, video->bo[0]);
142428d7b3dSmrg	video->bo[0] = NULL;
143428d7b3dSmrg
144428d7b3dSmrg	sna_video_free_buffers(video);
145428d7b3dSmrg	sna_window_set_port((WindowPtr)draw, NULL);
146428d7b3dSmrg	return Success;
147428d7b3dSmrg}
148428d7b3dSmrg
149428d7b3dSmrgstatic int
150428d7b3dSmrgsna_video_overlay_set_attribute(ddSetPortAttribute_ARGS)
151428d7b3dSmrg{
152428d7b3dSmrg	struct sna_video *video = port->devPriv.ptr;
153428d7b3dSmrg	struct sna *sna = video->sna;
154428d7b3dSmrg
155428d7b3dSmrg	DBG(("%s: set(%lx) to %d\n", __FUNCTION__, (long)attribute, (int)value));
156428d7b3dSmrg	if (attribute == xvBrightness) {
157428d7b3dSmrg		if ((value < -128) || (value > 127))
158428d7b3dSmrg			return BadValue;
159428d7b3dSmrg		DBG(("%s: BRIGHTNESS %d -> %d\n", __FUNCTION__,
160428d7b3dSmrg		     video->contrast, (int)value));
161428d7b3dSmrg		video->brightness = value;
162428d7b3dSmrg	} else if (attribute == xvContrast) {
163428d7b3dSmrg		if ((value < 0) || (value > 255))
164428d7b3dSmrg			return BadValue;
165428d7b3dSmrg		DBG(("%s: CONTRAST %d -> %d\n", __FUNCTION__,
166428d7b3dSmrg		     video->contrast, (int)value));
167428d7b3dSmrg		video->contrast = value;
168428d7b3dSmrg	} else if (attribute == xvSaturation) {
169428d7b3dSmrg		if ((value < 0) || (value > 1023))
170428d7b3dSmrg			return BadValue;
171428d7b3dSmrg		DBG(("%s: SATURATION %d -> %d\n", __FUNCTION__,
172428d7b3dSmrg		     video->saturation, (int)value));
173428d7b3dSmrg		video->saturation = value;
174428d7b3dSmrg	} else if (attribute == xvPipe) {
175428d7b3dSmrg		xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(sna->scrn);
176428d7b3dSmrg		if ((value < -1) || (value >= xf86_config->num_crtc))
177428d7b3dSmrg			return BadValue;
178428d7b3dSmrg		if (value < 0)
179428d7b3dSmrg			video->desired_crtc = NULL;
180428d7b3dSmrg		else
181428d7b3dSmrg			video->desired_crtc = xf86_config->crtc[value];
182428d7b3dSmrg	} else if (attribute == xvAlwaysOnTop) {
183428d7b3dSmrg		DBG(("%s: ALWAYS_ON_TOP: %d -> %d\n", __FUNCTION__,
184428d7b3dSmrg		     video->AlwaysOnTop, !!value));
185428d7b3dSmrg		video->AlwaysOnTop = !!value;
186428d7b3dSmrg	} else if (attribute == xvGamma0 && HAS_GAMMA(sna)) {
187428d7b3dSmrg		video->gamma0 = value;
188428d7b3dSmrg	} else if (attribute == xvGamma1 && HAS_GAMMA(sna)) {
189428d7b3dSmrg		video->gamma1 = value;
190428d7b3dSmrg	} else if (attribute == xvGamma2 && HAS_GAMMA(sna)) {
191428d7b3dSmrg		video->gamma2 = value;
192428d7b3dSmrg	} else if (attribute == xvGamma3 && HAS_GAMMA(sna)) {
193428d7b3dSmrg		video->gamma3 = value;
194428d7b3dSmrg	} else if (attribute == xvGamma4 && HAS_GAMMA(sna)) {
195428d7b3dSmrg		video->gamma4 = value;
196428d7b3dSmrg	} else if (attribute == xvGamma5 && HAS_GAMMA(sna)) {
197428d7b3dSmrg		video->gamma5 = value;
198428d7b3dSmrg	} else if (attribute == xvColorKey) {
199428d7b3dSmrg		video->color_key = value;
200428d7b3dSmrg		RegionEmpty(&video->clip);
201428d7b3dSmrg		DBG(("COLORKEY\n"));
202428d7b3dSmrg	} else
203428d7b3dSmrg		return BadMatch;
204428d7b3dSmrg
205428d7b3dSmrg	if ((attribute == xvGamma0 ||
206428d7b3dSmrg	     attribute == xvGamma1 ||
207428d7b3dSmrg	     attribute == xvGamma2 ||
208428d7b3dSmrg	     attribute == xvGamma3 ||
209428d7b3dSmrg	     attribute == xvGamma4 ||
210428d7b3dSmrg	     attribute == xvGamma5) && HAS_GAMMA(sna)) {
211428d7b3dSmrg		DBG(("%s: GAMMA\n", __FUNCTION__));
212428d7b3dSmrg	}
213428d7b3dSmrg
214428d7b3dSmrg	if (!sna_video_overlay_update_attrs(video))
215428d7b3dSmrg		return BadValue;
216428d7b3dSmrg
217428d7b3dSmrg	return Success;
218428d7b3dSmrg}
219428d7b3dSmrg
220428d7b3dSmrgstatic int
221428d7b3dSmrgsna_video_overlay_get_attribute(ddGetPortAttribute_ARGS)
222428d7b3dSmrg{
223428d7b3dSmrg	struct sna_video *video = port->devPriv.ptr;
224428d7b3dSmrg	struct sna *sna = video->sna;
225428d7b3dSmrg
226428d7b3dSmrg	if (attribute == xvBrightness) {
227428d7b3dSmrg		*value = video->brightness;
228428d7b3dSmrg	} else if (attribute == xvContrast) {
229428d7b3dSmrg		*value = video->contrast;
230428d7b3dSmrg	} else if (attribute == xvSaturation) {
231428d7b3dSmrg		*value = video->saturation;
232428d7b3dSmrg	} else if (attribute == xvPipe) {
233428d7b3dSmrg		int c;
234428d7b3dSmrg		xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(sna->scrn);
235428d7b3dSmrg		for (c = 0; c < xf86_config->num_crtc; c++)
236428d7b3dSmrg			if (xf86_config->crtc[c] == video->desired_crtc)
237428d7b3dSmrg				break;
238428d7b3dSmrg		if (c == xf86_config->num_crtc)
239428d7b3dSmrg			c = -1;
240428d7b3dSmrg		*value = c;
241428d7b3dSmrg	} else if (attribute == xvAlwaysOnTop) {
242428d7b3dSmrg		*value = video->AlwaysOnTop;
243428d7b3dSmrg	} else if (attribute == xvGamma0 && HAS_GAMMA(sna)) {
244428d7b3dSmrg		*value = video->gamma0;
245428d7b3dSmrg	} else if (attribute == xvGamma1 && HAS_GAMMA(sna)) {
246428d7b3dSmrg		*value = video->gamma1;
247428d7b3dSmrg	} else if (attribute == xvGamma2 && HAS_GAMMA(sna)) {
248428d7b3dSmrg		*value = video->gamma2;
249428d7b3dSmrg	} else if (attribute == xvGamma3 && HAS_GAMMA(sna)) {
250428d7b3dSmrg		*value = video->gamma3;
251428d7b3dSmrg	} else if (attribute == xvGamma4 && HAS_GAMMA(sna)) {
252428d7b3dSmrg		*value = video->gamma4;
253428d7b3dSmrg	} else if (attribute == xvGamma5 && HAS_GAMMA(sna)) {
254428d7b3dSmrg		*value = video->gamma5;
255428d7b3dSmrg	} else if (attribute == xvColorKey) {
256428d7b3dSmrg		*value = video->color_key;
257428d7b3dSmrg	} else
258428d7b3dSmrg		return BadMatch;
259428d7b3dSmrg
260428d7b3dSmrg	return Success;
261428d7b3dSmrg}
262428d7b3dSmrg
263428d7b3dSmrgstatic int
264428d7b3dSmrgsna_video_overlay_best_size(ddQueryBestSize_ARGS)
265428d7b3dSmrg{
266428d7b3dSmrg	struct sna_video *video = port->devPriv.ptr;
267428d7b3dSmrg	struct sna *sna = video->sna;
268428d7b3dSmrg	short max_w, max_h;
269428d7b3dSmrg
270428d7b3dSmrg	if (vid_w > (drw_w << 1) || vid_h > (drw_h << 1)){
271428d7b3dSmrg		drw_w = vid_w >> 1;
272428d7b3dSmrg		drw_h = vid_h >> 1;
273428d7b3dSmrg	}
274428d7b3dSmrg
275428d7b3dSmrg	if (sna->kgem.gen < 021) {
276428d7b3dSmrg		max_w = IMAGE_MAX_WIDTH_LEGACY;
277428d7b3dSmrg		max_h = IMAGE_MAX_HEIGHT_LEGACY;
278428d7b3dSmrg	} else {
279428d7b3dSmrg		max_w = IMAGE_MAX_WIDTH;
280428d7b3dSmrg		max_h = IMAGE_MAX_HEIGHT;
281428d7b3dSmrg	}
282428d7b3dSmrg
283428d7b3dSmrg	while (drw_w > max_w || drw_h > max_h) {
284428d7b3dSmrg		drw_w >>= 1;
285428d7b3dSmrg		drw_h >>= 1;
286428d7b3dSmrg	}
287428d7b3dSmrg
288428d7b3dSmrg	*p_w = drw_w;
289428d7b3dSmrg	*p_h = drw_h;
290428d7b3dSmrg	return Success;
291428d7b3dSmrg}
292428d7b3dSmrg
293428d7b3dSmrgstatic void
294428d7b3dSmrgupdate_dst_box_to_crtc_coords(struct sna *sna, xf86CrtcPtr crtc, BoxPtr dstBox)
295428d7b3dSmrg{
296428d7b3dSmrg	ScrnInfoPtr scrn = sna->scrn;
297428d7b3dSmrg	int tmp;
298428d7b3dSmrg
299428d7b3dSmrg	/* for overlay, we should take it from crtc's screen
300428d7b3dSmrg	 * coordinate to current crtc's display mode.
301428d7b3dSmrg	 * yeah, a bit confusing.
302428d7b3dSmrg	 */
303428d7b3dSmrg	switch (crtc->rotation & 0xf) {
304428d7b3dSmrg	case RR_Rotate_0:
305428d7b3dSmrg		dstBox->x1 -= crtc->x;
306428d7b3dSmrg		dstBox->x2 -= crtc->x;
307428d7b3dSmrg		dstBox->y1 -= crtc->y;
308428d7b3dSmrg		dstBox->y2 -= crtc->y;
309428d7b3dSmrg		break;
310428d7b3dSmrg	case RR_Rotate_90:
311428d7b3dSmrg		tmp = dstBox->x1;
312428d7b3dSmrg		dstBox->x1 = dstBox->y1 - crtc->x;
313428d7b3dSmrg		dstBox->y1 = scrn->virtualX - tmp - crtc->y;
314428d7b3dSmrg		tmp = dstBox->x2;
315428d7b3dSmrg		dstBox->x2 = dstBox->y2 - crtc->x;
316428d7b3dSmrg		dstBox->y2 = scrn->virtualX - tmp - crtc->y;
317428d7b3dSmrg		tmp = dstBox->y1;
318428d7b3dSmrg		dstBox->y1 = dstBox->y2;
319428d7b3dSmrg		dstBox->y2 = tmp;
320428d7b3dSmrg		break;
321428d7b3dSmrg	case RR_Rotate_180:
322428d7b3dSmrg		tmp = dstBox->x1;
323428d7b3dSmrg		dstBox->x1 = scrn->virtualX - dstBox->x2 - crtc->x;
324428d7b3dSmrg		dstBox->x2 = scrn->virtualX - tmp - crtc->x;
325428d7b3dSmrg		tmp = dstBox->y1;
326428d7b3dSmrg		dstBox->y1 = scrn->virtualY - dstBox->y2 - crtc->y;
327428d7b3dSmrg		dstBox->y2 = scrn->virtualY - tmp - crtc->y;
328428d7b3dSmrg		break;
329428d7b3dSmrg	case RR_Rotate_270:
330428d7b3dSmrg		tmp = dstBox->x1;
331428d7b3dSmrg		dstBox->x1 = scrn->virtualY - dstBox->y1 - crtc->x;
332428d7b3dSmrg		dstBox->y1 = tmp - crtc->y;
333428d7b3dSmrg		tmp = dstBox->x2;
334428d7b3dSmrg		dstBox->x2 = scrn->virtualY - dstBox->y2 - crtc->x;
335428d7b3dSmrg		dstBox->y2 = tmp - crtc->y;
336428d7b3dSmrg		tmp = dstBox->x1;
337428d7b3dSmrg		dstBox->x1 = dstBox->x2;
338428d7b3dSmrg		dstBox->x2 = tmp;
339428d7b3dSmrg		break;
340428d7b3dSmrg	}
341428d7b3dSmrg
342428d7b3dSmrg	return;
343428d7b3dSmrg}
344428d7b3dSmrg
345428d7b3dSmrgstatic bool
346428d7b3dSmrgsna_video_overlay_show(struct sna *sna,
347428d7b3dSmrg		       struct sna_video *video,
348428d7b3dSmrg		       struct sna_video_frame *frame,
349428d7b3dSmrg		       xf86CrtcPtr crtc,
350428d7b3dSmrg		       BoxPtr dstBox,
351428d7b3dSmrg		       short src_w, short src_h,
352428d7b3dSmrg		       short drw_w, short drw_h)
353428d7b3dSmrg{
354428d7b3dSmrg	struct drm_intel_overlay_put_image request;
355428d7b3dSmrg	bool planar = is_planar_fourcc(frame->id);
356428d7b3dSmrg	float scale;
357428d7b3dSmrg
358428d7b3dSmrg	DBG(("%s: src=(%dx%d), dst=(%dx%d)\n", __FUNCTION__,
359428d7b3dSmrg	     src_w, src_h, drw_w, drw_h));
360428d7b3dSmrg
361428d7b3dSmrg	update_dst_box_to_crtc_coords(sna, crtc, dstBox);
362428d7b3dSmrg	if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
363428d7b3dSmrg		int tmp;
364428d7b3dSmrg
365428d7b3dSmrg		tmp = frame->width;
366428d7b3dSmrg		frame->width = frame->height;
367428d7b3dSmrg		frame->height = tmp;
368428d7b3dSmrg
369428d7b3dSmrg		tmp = drw_w;
370428d7b3dSmrg		drw_w = drw_h;
371428d7b3dSmrg		drw_h = tmp;
372428d7b3dSmrg
373428d7b3dSmrg		tmp = src_w;
374428d7b3dSmrg		src_w = src_h;
375428d7b3dSmrg		src_h = tmp;
376428d7b3dSmrg	}
377428d7b3dSmrg
378428d7b3dSmrg	memset(&request, 0, sizeof(request));
379428d7b3dSmrg	request.flags = I915_OVERLAY_ENABLE;
380428d7b3dSmrg
381428d7b3dSmrg	request.bo_handle = frame->bo->handle;
382428d7b3dSmrg	if (planar) {
383428d7b3dSmrg		request.stride_Y = frame->pitch[1];
384428d7b3dSmrg		request.stride_UV = frame->pitch[0];
385428d7b3dSmrg	} else {
386428d7b3dSmrg		request.stride_Y = frame->pitch[0];
387428d7b3dSmrg		request.stride_UV = 0;
388428d7b3dSmrg	}
389428d7b3dSmrg	request.offset_Y = 0;
390428d7b3dSmrg	request.offset_U = frame->UBufOffset;
391428d7b3dSmrg	request.offset_V = frame->VBufOffset;
392428d7b3dSmrg	DBG(("%s: handle=%d, stride_Y=%d, stride_UV=%d, off_Y: %i, off_U: %i, off_V: %i\n",
393428d7b3dSmrg	     __FUNCTION__,
394428d7b3dSmrg	     request.bo_handle, request.stride_Y, request.stride_UV,
395428d7b3dSmrg	     request.offset_Y, request.offset_U, request.offset_V));
396428d7b3dSmrg
397428d7b3dSmrg	request.crtc_id = sna_crtc_id(crtc);
398428d7b3dSmrg	request.dst_x = dstBox->x1;
399428d7b3dSmrg	request.dst_y = dstBox->y1;
400428d7b3dSmrg	request.dst_width = dstBox->x2 - dstBox->x1;
401428d7b3dSmrg	request.dst_height = dstBox->y2 - dstBox->y1;
402428d7b3dSmrg
403428d7b3dSmrg	DBG(("%s: crtc=%d, dst=(%d, %d)x(%d, %d)\n",
404428d7b3dSmrg	     __FUNCTION__, request.crtc_id,
405428d7b3dSmrg	     request.dst_x, request.dst_y,
406428d7b3dSmrg	     request.dst_width, request.dst_height));
407428d7b3dSmrg
408428d7b3dSmrg	request.src_width = frame->width;
409428d7b3dSmrg	request.src_height = frame->height;
410428d7b3dSmrg	/* adjust src dimensions */
411428d7b3dSmrg	if (request.dst_height > 1) {
412428d7b3dSmrg		scale = ((float)request.dst_height - 1) / ((float)drw_h - 1);
413428d7b3dSmrg		request.src_scan_height = src_h * scale;
414428d7b3dSmrg	} else
415428d7b3dSmrg		request.src_scan_height = 1;
416428d7b3dSmrg
417428d7b3dSmrg	if (request.dst_width > 1) {
418428d7b3dSmrg		scale = ((float)request.dst_width - 1) / ((float)drw_w - 1);
419428d7b3dSmrg		request.src_scan_width = src_w * scale;
420428d7b3dSmrg	} else
421428d7b3dSmrg		request.src_scan_width = 1;
422428d7b3dSmrg
423428d7b3dSmrg	DBG(("%s: src=(%d, %d) scan=(%d, %d)\n",
424428d7b3dSmrg	     __FUNCTION__,
425428d7b3dSmrg	     request.src_width, request.src_height,
426428d7b3dSmrg	     request.src_scan_width, request.src_scan_height));
427428d7b3dSmrg
428428d7b3dSmrg	if (planar) {
429428d7b3dSmrg		request.flags |= I915_OVERLAY_YUV_PLANAR | I915_OVERLAY_YUV420;
430428d7b3dSmrg	} else {
431428d7b3dSmrg		request.flags |= I915_OVERLAY_YUV_PACKED | I915_OVERLAY_YUV422;
432428d7b3dSmrg		if (frame->id == FOURCC_UYVY)
433428d7b3dSmrg			request.flags |= I915_OVERLAY_Y_SWAP;
434428d7b3dSmrg	}
435428d7b3dSmrg
436428d7b3dSmrg	DBG(("%s: flags=%x\n", __FUNCTION__, request.flags));
437428d7b3dSmrg
438428d7b3dSmrg	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_OVERLAY_PUT_IMAGE, &request)) {
439428d7b3dSmrg		DBG(("%s: Putimage failed\n", __FUNCTION__));
440428d7b3dSmrg		return false;
441428d7b3dSmrg	}
442428d7b3dSmrg
443428d7b3dSmrg	if (video->bo[0] != frame->bo) {
444428d7b3dSmrg		if (video->bo[0])
445428d7b3dSmrg			kgem_bo_destroy(&sna->kgem, video->bo[0]);
446428d7b3dSmrg		video->bo[0] = kgem_bo_reference(frame->bo);
447428d7b3dSmrg	}
448428d7b3dSmrg
449428d7b3dSmrg	return true;
450428d7b3dSmrg}
451428d7b3dSmrg
452428d7b3dSmrgstatic int
453428d7b3dSmrgsna_video_overlay_put_image(ddPutImage_ARGS)
454428d7b3dSmrg{
455428d7b3dSmrg	struct sna_video *video = port->devPriv.ptr;
456428d7b3dSmrg	struct sna *sna = video->sna;
457428d7b3dSmrg	struct sna_video_frame frame;
458428d7b3dSmrg	xf86CrtcPtr crtc;
459428d7b3dSmrg	BoxRec dstBox;
460428d7b3dSmrg	RegionRec clip;
461428d7b3dSmrg	int ret;
462428d7b3dSmrg
463428d7b3dSmrg	DBG(("%s: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d), width %d, height %d\n",
464428d7b3dSmrg	     __FUNCTION__,
465428d7b3dSmrg	     src_x, src_y, src_w, src_h, drw_x,
466428d7b3dSmrg	     drw_y, drw_w, drw_h, width, height));
467428d7b3dSmrg
468428d7b3dSmrg	/* If dst width and height are less than 1/8th the src size, the
469428d7b3dSmrg	 * src/dst scale factor becomes larger than 8 and doesn't fit in
470428d7b3dSmrg	 * the scale register. */
471428d7b3dSmrg	if (src_w >= (drw_w * 8))
472428d7b3dSmrg		drw_w = src_w / 7;
473428d7b3dSmrg
474428d7b3dSmrg	if (src_h >= (drw_h * 8))
475428d7b3dSmrg		drw_h = src_h / 7;
476428d7b3dSmrg
477428d7b3dSmrg	clip.extents.x1 = draw->x + drw_x;
478428d7b3dSmrg	clip.extents.y1 = draw->y + drw_y;
479428d7b3dSmrg	clip.extents.x2 = clip.extents.x1 + drw_w;
480428d7b3dSmrg	clip.extents.y2 = clip.extents.y1 + drw_h;
481428d7b3dSmrg	clip.data = NULL;
482428d7b3dSmrg
483428d7b3dSmrg	DBG(("%s: always_on_top=%d\n", __FUNCTION__, video->AlwaysOnTop));
484428d7b3dSmrg	if (!video->AlwaysOnTop)
485428d7b3dSmrg		RegionIntersect(&clip, &clip, gc->pCompositeClip);
486428d7b3dSmrg	if (box_empty(&clip.extents))
487428d7b3dSmrg		goto invisible;
488428d7b3dSmrg
489428d7b3dSmrg	DBG(("%s: src=(%d, %d),(%d, %d), dst=(%d, %d),(%d, %d), id=%d, sizep=%dx%d, sync?=%d\n",
490428d7b3dSmrg	     __FUNCTION__,
491428d7b3dSmrg	     src_x, src_y, src_w, src_h,
492428d7b3dSmrg	     drw_x, drw_y, drw_w, drw_h,
493428d7b3dSmrg	     format->id, width, height, sync));
494428d7b3dSmrg
495428d7b3dSmrg	DBG(("%s: region %d:(%d, %d), (%d, %d)\n", __FUNCTION__,
496428d7b3dSmrg	     region_num_rects(&clip),
497428d7b3dSmrg	     clip.extents.x1, clip.extents.y1,
498428d7b3dSmrg	     clip.extents.x2, clip.extents.y2));
499428d7b3dSmrg
500428d7b3dSmrg	sna_video_frame_init(video, format->id, width, height, &frame);
501428d7b3dSmrg
502428d7b3dSmrg	if (!sna_video_clip_helper(video, &frame, &crtc, &dstBox,
503428d7b3dSmrg				   src_x, src_y, draw->x + drw_x, draw->y + drw_y,
504428d7b3dSmrg				   src_w, src_h, drw_w, drw_h,
505428d7b3dSmrg				   &clip))
506428d7b3dSmrg		goto invisible;
507428d7b3dSmrg
508428d7b3dSmrg	if (!crtc)
509428d7b3dSmrg		goto invisible;
510428d7b3dSmrg
511428d7b3dSmrg	/* overlay can't handle rotation natively, store it for the copy func */
512428d7b3dSmrg	sna_video_frame_set_rotation(video, &frame, crtc->rotation);
513428d7b3dSmrg
514428d7b3dSmrg	if (xvmc_passthrough(format->id)) {
515428d7b3dSmrg		DBG(("%s: using passthough, name=%d\n",
516428d7b3dSmrg		     __FUNCTION__, *(uint32_t *)buf));
517428d7b3dSmrg
518428d7b3dSmrg		if (*(uint32_t*)buf == 0)
519428d7b3dSmrg			goto invisible;
520428d7b3dSmrg
521428d7b3dSmrg		frame.bo = kgem_create_for_name(&sna->kgem, *(uint32_t*)buf);
522428d7b3dSmrg		if (frame.bo == NULL) {
523428d7b3dSmrg			DBG(("%s: failed to open bo\n", __FUNCTION__));
524428d7b3dSmrg			return BadAlloc;
525428d7b3dSmrg		}
526428d7b3dSmrg
527428d7b3dSmrg		if (kgem_bo_size(frame.bo) < frame.size) {
528428d7b3dSmrg			DBG(("%s: bo size=%d, expected=%d\n",
529428d7b3dSmrg			     __FUNCTION__, kgem_bo_size(frame.bo), frame.size));
530428d7b3dSmrg			kgem_bo_destroy(&sna->kgem, frame.bo);
531428d7b3dSmrg			return BadAlloc;
532428d7b3dSmrg		}
533428d7b3dSmrg
534428d7b3dSmrg		frame.image.x1 = 0;
535428d7b3dSmrg		frame.image.y1 = 0;
536428d7b3dSmrg		frame.image.x2 = frame.width;
537428d7b3dSmrg		frame.image.y2 = frame.height;
538428d7b3dSmrg	} else {
539428d7b3dSmrg		frame.bo = sna_video_buffer(video, &frame);
540428d7b3dSmrg		if (frame.bo == NULL) {
541428d7b3dSmrg			DBG(("%s: failed to allocate video bo\n", __FUNCTION__));
542428d7b3dSmrg			return BadAlloc;
543428d7b3dSmrg		}
544428d7b3dSmrg
545428d7b3dSmrg		if (!sna_video_copy_data(video, &frame, buf)) {
546428d7b3dSmrg			DBG(("%s: failed to copy video data\n", __FUNCTION__));
547428d7b3dSmrg			return BadAlloc;
548428d7b3dSmrg		}
549428d7b3dSmrg	}
550428d7b3dSmrg
551428d7b3dSmrg	ret = Success;
552428d7b3dSmrg	if (sna_video_overlay_show
553428d7b3dSmrg	    (sna, video, &frame, crtc, &dstBox, src_w, src_h, drw_w, drw_h)) {
554428d7b3dSmrg		//xf86XVFillKeyHelperDrawable(draw, video->color_key, &clip);
555428d7b3dSmrg		if (!video->AlwaysOnTop && !RegionEqual(&video->clip, &clip) &&
556428d7b3dSmrg		    sna_blt_fill_boxes(sna, GXcopy,
557428d7b3dSmrg				       __sna_pixmap_get_bo(sna->front),
558428d7b3dSmrg				       sna->front->drawable.bitsPerPixel,
559428d7b3dSmrg				       video->color_key,
560428d7b3dSmrg				       region_rects(&clip),
561428d7b3dSmrg				       region_num_rects(&clip)))
562428d7b3dSmrg			RegionCopy(&video->clip, &clip);
563428d7b3dSmrg		sna_window_set_port((WindowPtr)draw, port);
564428d7b3dSmrg	} else {
565428d7b3dSmrg		DBG(("%s: failed to show video frame\n", __FUNCTION__));
566428d7b3dSmrg		ret = BadAlloc;
567428d7b3dSmrg	}
568428d7b3dSmrg
569428d7b3dSmrg	frame.bo->domain = DOMAIN_NONE;
570428d7b3dSmrg	if (xvmc_passthrough(format->id))
571428d7b3dSmrg		kgem_bo_destroy(&sna->kgem, frame.bo);
572428d7b3dSmrg	else
573428d7b3dSmrg		sna_video_buffer_fini(video);
574428d7b3dSmrg
575428d7b3dSmrg	return ret;
576428d7b3dSmrg
577428d7b3dSmrginvisible:
578428d7b3dSmrg	/*
579428d7b3dSmrg	 * If the video isn't visible on any CRTC, turn it off
580428d7b3dSmrg	 */
581428d7b3dSmrg#if XORG_XV_VERSION < 2
582428d7b3dSmrg	sna_video_overlay_stop(client, port, draw);
583428d7b3dSmrg#else
584428d7b3dSmrg	sna_video_overlay_stop(port, draw);
585428d7b3dSmrg#endif
586428d7b3dSmrg	return Success;
587428d7b3dSmrg}
588428d7b3dSmrg
589428d7b3dSmrgstatic int
590428d7b3dSmrgsna_video_overlay_query(ddQueryImageAttributes_ARGS)
591428d7b3dSmrg{
592428d7b3dSmrg	struct sna_video *video = port->devPriv.ptr;
593428d7b3dSmrg	struct sna_video_frame frame;
594428d7b3dSmrg	struct sna *sna = video->sna;
595428d7b3dSmrg	int size, tmp;
596428d7b3dSmrg
597428d7b3dSmrg	DBG(("%s: w is %d, h is %d\n", __FUNCTION__, *w, *h));
598428d7b3dSmrg
599428d7b3dSmrg	if (sna->kgem.gen < 021) {
600428d7b3dSmrg		if (*w > IMAGE_MAX_WIDTH_LEGACY)
601428d7b3dSmrg			*w = IMAGE_MAX_WIDTH_LEGACY;
602428d7b3dSmrg		if (*h > IMAGE_MAX_HEIGHT_LEGACY)
603428d7b3dSmrg			*h = IMAGE_MAX_HEIGHT_LEGACY;
604428d7b3dSmrg	} else {
605428d7b3dSmrg		if (*w > IMAGE_MAX_WIDTH)
606428d7b3dSmrg			*w = IMAGE_MAX_WIDTH;
607428d7b3dSmrg		if (*h > IMAGE_MAX_HEIGHT)
608428d7b3dSmrg			*h = IMAGE_MAX_HEIGHT;
609428d7b3dSmrg	}
610428d7b3dSmrg
611428d7b3dSmrg	*w = (*w + 1) & ~1;
612428d7b3dSmrg	if (offsets)
613428d7b3dSmrg		offsets[0] = 0;
614428d7b3dSmrg
615428d7b3dSmrg	switch (format->id) {
616428d7b3dSmrg	case FOURCC_XVMC:
617428d7b3dSmrg		*h = (*h + 1) & ~1;
618428d7b3dSmrg		sna_video_frame_init(video, format->id, *w, *h, &frame);
619428d7b3dSmrg		sna_video_frame_set_rotation(video, &frame, RR_Rotate_0);
620428d7b3dSmrg		size = sizeof(uint32_t);
621428d7b3dSmrg		if (pitches) {
622428d7b3dSmrg			pitches[0] = frame.pitch[1];
623428d7b3dSmrg			pitches[1] = frame.pitch[0];
624428d7b3dSmrg			pitches[2] = frame.pitch[0];
625428d7b3dSmrg		}
626428d7b3dSmrg		if (offsets) {
627428d7b3dSmrg			offsets[1] = frame.UBufOffset;
628428d7b3dSmrg			offsets[2] = frame.VBufOffset;
629428d7b3dSmrg		}
630428d7b3dSmrg		break;
631428d7b3dSmrg
632428d7b3dSmrg		/* IA44 is for XvMC only */
633428d7b3dSmrg	case FOURCC_IA44:
634428d7b3dSmrg	case FOURCC_AI44:
635428d7b3dSmrg		if (pitches)
636428d7b3dSmrg			pitches[0] = *w;
637428d7b3dSmrg		size = *w * *h;
638428d7b3dSmrg		break;
639428d7b3dSmrg	case FOURCC_YV12:
640428d7b3dSmrg	case FOURCC_I420:
641428d7b3dSmrg		*h = (*h + 1) & ~1;
642428d7b3dSmrg		size = (*w + 3) & ~3;
643428d7b3dSmrg		if (pitches)
644428d7b3dSmrg			pitches[0] = size;
645428d7b3dSmrg		size *= *h;
646428d7b3dSmrg		if (offsets)
647428d7b3dSmrg			offsets[1] = size;
648428d7b3dSmrg		tmp = ((*w >> 1) + 3) & ~3;
649428d7b3dSmrg		if (pitches)
650428d7b3dSmrg			pitches[1] = pitches[2] = tmp;
651428d7b3dSmrg		tmp *= (*h >> 1);
652428d7b3dSmrg		size += tmp;
653428d7b3dSmrg		if (offsets)
654428d7b3dSmrg			offsets[2] = size;
655428d7b3dSmrg		size += tmp;
656428d7b3dSmrg#if 0
657428d7b3dSmrg		if (pitches)
658428d7b3dSmrg			ErrorF("pitch 0 is %d, pitch 1 is %d, pitch 2 is %d\n",
659428d7b3dSmrg			       pitches[0], pitches[1], pitches[2]);
660428d7b3dSmrg		if (offsets)
661428d7b3dSmrg			ErrorF("offset 1 is %d, offset 2 is %d\n", offsets[1],
662428d7b3dSmrg			       offsets[2]);
663428d7b3dSmrg		if (offsets)
664428d7b3dSmrg			ErrorF("size is %d\n", size);
665428d7b3dSmrg#endif
666428d7b3dSmrg		break;
667428d7b3dSmrg	case FOURCC_UYVY:
668428d7b3dSmrg	case FOURCC_YUY2:
669428d7b3dSmrg	default:
670428d7b3dSmrg		size = *w << 1;
671428d7b3dSmrg		if (pitches)
672428d7b3dSmrg			pitches[0] = size;
673428d7b3dSmrg		size *= *h;
674428d7b3dSmrg		break;
675428d7b3dSmrg	}
676428d7b3dSmrg
677428d7b3dSmrg	return size;
678428d7b3dSmrg}
679428d7b3dSmrg
680428d7b3dSmrgstatic int sna_video_overlay_color_key(struct sna *sna)
681428d7b3dSmrg{
682428d7b3dSmrg	ScrnInfoPtr scrn = sna->scrn;
683428d7b3dSmrg	int color_key;
684428d7b3dSmrg
685428d7b3dSmrg	if (xf86GetOptValInteger(sna->Options, OPTION_VIDEO_KEY,
686428d7b3dSmrg				 &color_key)) {
687428d7b3dSmrg	} else if (xf86GetOptValInteger(sna->Options, OPTION_COLOR_KEY,
688428d7b3dSmrg					&color_key)) {
689428d7b3dSmrg	} else {
690428d7b3dSmrg		color_key =
691428d7b3dSmrg		    (1 << scrn->offset.red) |
692428d7b3dSmrg		    (1 << scrn->offset.green) |
693428d7b3dSmrg		    (((scrn->mask.blue >> scrn->offset.blue) - 1) << scrn->offset.blue);
694428d7b3dSmrg	}
695428d7b3dSmrg
696428d7b3dSmrg	return color_key & ((1 << scrn->depth) - 1);
697428d7b3dSmrg}
698428d7b3dSmrg
699428d7b3dSmrgvoid sna_video_overlay_setup(struct sna *sna, ScreenPtr screen)
700428d7b3dSmrg{
701428d7b3dSmrg	XvAdaptorPtr adaptor;
702428d7b3dSmrg	struct sna_video *video;
703428d7b3dSmrg	XvPortPtr port;
704428d7b3dSmrg
705428d7b3dSmrg	if (sna->flags & SNA_IS_HOSTED)
706428d7b3dSmrg		return;
707428d7b3dSmrg
708428d7b3dSmrg	if (!sna_has_overlay(sna))
709428d7b3dSmrg		return;
710428d7b3dSmrg
711428d7b3dSmrg	DBG(("%s()\n", __FUNCTION__));
712428d7b3dSmrg
713428d7b3dSmrg	adaptor = sna_xv_adaptor_alloc(sna);
714428d7b3dSmrg	if (adaptor == NULL)
715428d7b3dSmrg		return;
716428d7b3dSmrg
717428d7b3dSmrg	video = calloc(1, sizeof(*video));
718428d7b3dSmrg	port = calloc(1, sizeof(*port));
719428d7b3dSmrg	if (video == NULL || port == NULL) {
720428d7b3dSmrg		free(video);
721428d7b3dSmrg		free(port);
722428d7b3dSmrg		sna->xv.num_adaptors--;
723428d7b3dSmrg		return;
724428d7b3dSmrg	}
725428d7b3dSmrg
726428d7b3dSmrg	adaptor->type = XvInputMask | XvImageMask;
727428d7b3dSmrg	adaptor->pScreen = screen;
728428d7b3dSmrg	adaptor->name = (char *)"Intel(R) Video Overlay";
729428d7b3dSmrg	adaptor->nEncodings = 1;
730428d7b3dSmrg	adaptor->pEncodings = xnfalloc(sizeof(XvEncodingRec));
731428d7b3dSmrg	adaptor->pEncodings[0].id = 0;
732428d7b3dSmrg	adaptor->pEncodings[0].pScreen = screen;
733428d7b3dSmrg	adaptor->pEncodings[0].name = (char *)"XV_IMAGE";
734428d7b3dSmrg	adaptor->pEncodings[0].width = sna->kgem.gen < 021 ? IMAGE_MAX_WIDTH_LEGACY : IMAGE_MAX_WIDTH;
735428d7b3dSmrg	adaptor->pEncodings[0].height = sna->kgem.gen < 021 ? IMAGE_MAX_HEIGHT_LEGACY : IMAGE_MAX_HEIGHT;
736428d7b3dSmrg	adaptor->pEncodings[0].rate.numerator = 1;
737428d7b3dSmrg	adaptor->pEncodings[0].rate.denominator = 1;
738428d7b3dSmrg	adaptor->pFormats = Formats;
739428d7b3dSmrg	adaptor->nFormats = sna_xv_fixup_formats(screen, Formats,
740428d7b3dSmrg						 ARRAY_SIZE(Formats));
741428d7b3dSmrg	adaptor->nAttributes = NUM_ATTRIBUTES;
742428d7b3dSmrg	if (HAS_GAMMA(sna))
743428d7b3dSmrg		adaptor->nAttributes += GAMMA_ATTRIBUTES;
744428d7b3dSmrg	adaptor->pAttributes = (XvAttributeRec *)Attributes;
745428d7b3dSmrg	adaptor->nImages = ARRAY_SIZE(Images);
746428d7b3dSmrg	adaptor->pImages = (XvImageRec *)Images;
747428d7b3dSmrg#if XORG_XV_VERSION < 2
748428d7b3dSmrg	adaptor->ddAllocatePort = sna_xv_alloc_port;
749428d7b3dSmrg	adaptor->ddFreePort = sna_xv_free_port;
750428d7b3dSmrg#endif
751428d7b3dSmrg	adaptor->ddPutVideo = NULL;
752428d7b3dSmrg	adaptor->ddPutStill = NULL;
753428d7b3dSmrg	adaptor->ddGetVideo = NULL;
754428d7b3dSmrg	adaptor->ddGetStill = NULL;
755428d7b3dSmrg	adaptor->ddStopVideo = sna_video_overlay_stop;
756428d7b3dSmrg	adaptor->ddSetPortAttribute = sna_video_overlay_set_attribute;
757428d7b3dSmrg	adaptor->ddGetPortAttribute = sna_video_overlay_get_attribute;
758428d7b3dSmrg	adaptor->ddQueryBestSize = sna_video_overlay_best_size;
759428d7b3dSmrg	adaptor->ddPutImage = sna_video_overlay_put_image;
760428d7b3dSmrg	adaptor->ddQueryImageAttributes = sna_video_overlay_query;
761428d7b3dSmrg
762428d7b3dSmrg	adaptor->nPorts = 1;
763428d7b3dSmrg	adaptor->pPorts = port;
764428d7b3dSmrg	adaptor->base_id = port->id = FakeClientID(0);
765428d7b3dSmrg	AddResource(port->id, XvGetRTPort(), port);
766428d7b3dSmrg
767428d7b3dSmrg	port->pAdaptor = adaptor;
768428d7b3dSmrg	port->pNotify =  NULL;
769428d7b3dSmrg	port->pDraw =  NULL;
770428d7b3dSmrg	port->client =  NULL;
771428d7b3dSmrg	port->grab.client =  NULL;
772428d7b3dSmrg	port->time = currentTime;
773428d7b3dSmrg	port->devPriv.ptr = video;
774428d7b3dSmrg
775428d7b3dSmrg	video->sna = sna;
776428d7b3dSmrg	if (sna->kgem.gen >= 040)
777428d7b3dSmrg		/* Actually the alignment is 64 bytes, too. But the
778428d7b3dSmrg		 * stride must be at least 512 bytes. Take the easy fix
779428d7b3dSmrg		 * and align on 512 bytes unconditionally. */
780428d7b3dSmrg		video->alignment = 512;
781428d7b3dSmrg	else if (sna->kgem.gen < 021)
782428d7b3dSmrg		/* Harsh, errata on these chipsets limit the stride
783428d7b3dSmrg		 * to be a multiple of 256 bytes.
784428d7b3dSmrg		 */
785428d7b3dSmrg		video->alignment = 256;
786428d7b3dSmrg	else
787428d7b3dSmrg		video->alignment = 64;
788428d7b3dSmrg	video->color_key = sna_video_overlay_color_key(sna);
789428d7b3dSmrg	video->brightness = -19;	/* (255/219) * -16 */
790428d7b3dSmrg	video->contrast = 75;	/* 255/219 * 64 */
791428d7b3dSmrg	video->saturation = 146;	/* 128/112 * 128 */
792428d7b3dSmrg	video->desired_crtc = NULL;
793428d7b3dSmrg	video->gamma5 = 0xc0c0c0;
794428d7b3dSmrg	video->gamma4 = 0x808080;
795428d7b3dSmrg	video->gamma3 = 0x404040;
796428d7b3dSmrg	video->gamma2 = 0x202020;
797428d7b3dSmrg	video->gamma1 = 0x101010;
798428d7b3dSmrg	video->gamma0 = 0x080808;
799428d7b3dSmrg	RegionNull(&video->clip);
800428d7b3dSmrg
801428d7b3dSmrg	xvColorKey = MAKE_ATOM("XV_COLORKEY");
802428d7b3dSmrg	xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
803428d7b3dSmrg	xvContrast = MAKE_ATOM("XV_CONTRAST");
804428d7b3dSmrg	xvSaturation = MAKE_ATOM("XV_SATURATION");
805428d7b3dSmrg
806428d7b3dSmrg	/* Allow the pipe to be switched from pipe A to B when in clone mode */
807428d7b3dSmrg	xvPipe = MAKE_ATOM("XV_PIPE");
808428d7b3dSmrg	xvAlwaysOnTop = MAKE_ATOM("XV_ALWAYS_ON_TOP");
809428d7b3dSmrg
810428d7b3dSmrg	if (HAS_GAMMA(sna)) {
811428d7b3dSmrg		xvGamma0 = MAKE_ATOM("XV_GAMMA0");
812428d7b3dSmrg		xvGamma1 = MAKE_ATOM("XV_GAMMA1");
813428d7b3dSmrg		xvGamma2 = MAKE_ATOM("XV_GAMMA2");
814428d7b3dSmrg		xvGamma3 = MAKE_ATOM("XV_GAMMA3");
815428d7b3dSmrg		xvGamma4 = MAKE_ATOM("XV_GAMMA4");
816428d7b3dSmrg		xvGamma5 = MAKE_ATOM("XV_GAMMA5");
817428d7b3dSmrg	}
818428d7b3dSmrg
819428d7b3dSmrg	sna_video_overlay_update_attrs(video);
820428d7b3dSmrg
821428d7b3dSmrg	DBG(("%s: '%s' initialized %d ports\n", __FUNCTION__, adaptor->name, adaptor->nPorts));
822428d7b3dSmrg}
823