1428d7b3dSmrg/***************************************************************************
2428d7b3dSmrg
3428d7b3dSmrg Copyright 2000 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/*
28428d7b3dSmrg * i830_video.c: i830/i845 Xv driver.
29428d7b3dSmrg *
30428d7b3dSmrg * Copyright © 2002 by Alan Hourihane and David Dawes
31428d7b3dSmrg *
32428d7b3dSmrg * Authors:
33428d7b3dSmrg *	Alan Hourihane <alanh@tungstengraphics.com>
34428d7b3dSmrg *	David Dawes <dawes@xfree86.org>
35428d7b3dSmrg *
36428d7b3dSmrg * Derived from i810 Xv driver:
37428d7b3dSmrg *
38428d7b3dSmrg * Authors of i810 code:
39428d7b3dSmrg * 	Jonathan Bian <jonathan.bian@intel.com>
40428d7b3dSmrg *      Offscreen Images:
41428d7b3dSmrg *        Matt Sottek <matthew.j.sottek@intel.com>
42428d7b3dSmrg */
43428d7b3dSmrg
44428d7b3dSmrg/*
45428d7b3dSmrg * XXX Could support more formats.
46428d7b3dSmrg */
47428d7b3dSmrg
48428d7b3dSmrg#ifdef HAVE_CONFIG_H
49428d7b3dSmrg#include "config.h"
50428d7b3dSmrg#endif
51428d7b3dSmrg
52428d7b3dSmrg#include <inttypes.h>
53428d7b3dSmrg#include <math.h>
54428d7b3dSmrg#include <string.h>
55428d7b3dSmrg#include <assert.h>
56428d7b3dSmrg#include <errno.h>
57428d7b3dSmrg
58428d7b3dSmrg#include "xorg-server.h"
59428d7b3dSmrg#include "xf86.h"
60428d7b3dSmrg#include "xf86_OSproc.h"
61428d7b3dSmrg#include "compiler.h"
62428d7b3dSmrg#include "xf86Pci.h"
63428d7b3dSmrg#include "xf86fbman.h"
64428d7b3dSmrg#include "xf86drm.h"
65428d7b3dSmrg#include "regionstr.h"
66428d7b3dSmrg#include "randrstr.h"
67428d7b3dSmrg#include "windowstr.h"
68428d7b3dSmrg#include "damage.h"
69428d7b3dSmrg#include "intel.h"
70428d7b3dSmrg#include "intel_video.h"
71428d7b3dSmrg#include "i830_reg.h"
72428d7b3dSmrg#include "xf86xv.h"
73428d7b3dSmrg#include <X11/extensions/Xv.h>
74428d7b3dSmrg#include "dixstruct.h"
75428d7b3dSmrg#include "fourcc.h"
76428d7b3dSmrg
77428d7b3dSmrg#ifdef INTEL_XVMC
78428d7b3dSmrg#define _INTEL_XVMC_SERVER_
79428d7b3dSmrg#include "intel_xvmc.h"
80428d7b3dSmrg#endif
81428d7b3dSmrg#include "intel_uxa.h"
82428d7b3dSmrg#include "intel_video_overlay.h"
83428d7b3dSmrg
84428d7b3dSmrgAtom intel_xv_Brightness, intel_xv_Contrast, intel_xv_Saturation, intel_xv_ColorKey, intel_xv_Pipe;
85428d7b3dSmrgAtom intel_xv_Gamma0, intel_xv_Gamma1, intel_xv_Gamma2, intel_xv_Gamma3, intel_xv_Gamma4, intel_xv_Gamma5;
86428d7b3dSmrgAtom intel_xv_SyncToVblank;
87428d7b3dSmrg
88428d7b3dSmrg/* client libraries expect an encoding */
89428d7b3dSmrgconst XF86VideoEncodingRec intel_xv_dummy_encoding[1] = {
90428d7b3dSmrg	{
91428d7b3dSmrg	 0,
92428d7b3dSmrg	 "XV_IMAGE",
93428d7b3dSmrg	 IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
94428d7b3dSmrg	 {1, 1}
95428d7b3dSmrg	 }
96428d7b3dSmrg};
97428d7b3dSmrg
98428d7b3dSmrgXF86VideoFormatRec intel_xv_formats[NUM_FORMATS] = {
99428d7b3dSmrg	{15, TrueColor}, {16, TrueColor}, {24, TrueColor}
100428d7b3dSmrg};
101428d7b3dSmrg
102428d7b3dSmrgXF86AttributeRec intel_xv_attributes[NUM_ATTRIBUTES] = {
103428d7b3dSmrg	{XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
104428d7b3dSmrg	{XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
105428d7b3dSmrg	{XvSettable | XvGettable, 0, 255, "XV_CONTRAST"},
106428d7b3dSmrg	{XvSettable | XvGettable, 0, 1023, "XV_SATURATION"},
107428d7b3dSmrg	{XvSettable | XvGettable, -1, 1, "XV_PIPE"}
108428d7b3dSmrg};
109428d7b3dSmrg
110428d7b3dSmrg#define GAMMA_ATTRIBUTES 6
111428d7b3dSmrgXF86AttributeRec intel_xv_gamma_attributes[GAMMA_ATTRIBUTES] = {
112428d7b3dSmrg	{XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA0"},
113428d7b3dSmrg	{XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA1"},
114428d7b3dSmrg	{XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA2"},
115428d7b3dSmrg	{XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA3"},
116428d7b3dSmrg	{XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA4"},
117428d7b3dSmrg	{XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA5"}
118428d7b3dSmrg};
119428d7b3dSmrg
120428d7b3dSmrg#ifdef INTEL_XVMC
121428d7b3dSmrg#define NUM_IMAGES 5
122428d7b3dSmrg#define XVMC_IMAGE 1
123428d7b3dSmrg#else
124428d7b3dSmrg#define NUM_IMAGES 4
125428d7b3dSmrg#define XVMC_IMAGE 0
126428d7b3dSmrg#endif
127428d7b3dSmrg
128428d7b3dSmrgXF86ImageRec intel_xv_images[NUM_IMAGES] = {
129428d7b3dSmrg	XVIMAGE_YUY2,
130428d7b3dSmrg	XVIMAGE_YV12,
131428d7b3dSmrg	XVIMAGE_I420,
132428d7b3dSmrg	XVIMAGE_UYVY,
133428d7b3dSmrg#ifdef INTEL_XVMC
134428d7b3dSmrg	{
135428d7b3dSmrg	 /*
136428d7b3dSmrg	  * Below, a dummy picture type that is used in XvPutImage only to do
137428d7b3dSmrg	  * an overlay update. Introduced for the XvMC client lib.
138428d7b3dSmrg	  * Defined to have a zero data size.
139428d7b3dSmrg	  */
140428d7b3dSmrg	 FOURCC_XVMC,
141428d7b3dSmrg	 XvYUV,
142428d7b3dSmrg	 LSBFirst,
143428d7b3dSmrg	 {'X', 'V', 'M', 'C',
144428d7b3dSmrg	  0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0xAA, 0x00,
145428d7b3dSmrg	  0x38, 0x9B, 0x71},
146428d7b3dSmrg	 12,
147428d7b3dSmrg	 XvPlanar,
148428d7b3dSmrg	 3,
149428d7b3dSmrg	 0, 0, 0, 0,
150428d7b3dSmrg	 8, 8, 8,
151428d7b3dSmrg	 1, 2, 2,
152428d7b3dSmrg	 1, 2, 2,
153428d7b3dSmrg	 {'Y', 'V', 'U',
154428d7b3dSmrg	  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
155428d7b3dSmrg	  0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
156428d7b3dSmrg	 XvTopToBottom},
157428d7b3dSmrg#endif
158428d7b3dSmrg};
159428d7b3dSmrg
160428d7b3dSmrgvoid intel_video_init(ScreenPtr screen)
161428d7b3dSmrg{
162428d7b3dSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
163428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
164428d7b3dSmrg	XF86VideoAdaptorPtr *adaptors = NULL, *newAdaptors = NULL;
165428d7b3dSmrg	XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL;
166428d7b3dSmrg	int num_adaptors = xf86XVListGenericAdaptors(scrn, &adaptors);
167428d7b3dSmrg
168428d7b3dSmrg	/* Give our adaptor list enough space for the overlay and/or texture video
169428d7b3dSmrg	 * adaptors.
170428d7b3dSmrg	 */
171428d7b3dSmrg	newAdaptors = realloc(adaptors,
172428d7b3dSmrg			      (num_adaptors + 3) * sizeof(XF86VideoAdaptorPtr));
173428d7b3dSmrg
174428d7b3dSmrg	if (newAdaptors == NULL) {
175428d7b3dSmrg		free(adaptors);
176428d7b3dSmrg		return;
177428d7b3dSmrg	}
178428d7b3dSmrg	adaptors = newAdaptors;
179428d7b3dSmrg
180428d7b3dSmrg	/* Add the adaptors supported by our hardware.  First, set up the atoms
181428d7b3dSmrg	 * that will be used by both output adaptors.
182428d7b3dSmrg	 */
183428d7b3dSmrg	intel_xv_Brightness = MAKE_ATOM("XV_BRIGHTNESS");
184428d7b3dSmrg	intel_xv_Contrast = MAKE_ATOM("XV_CONTRAST");
185428d7b3dSmrg
186428d7b3dSmrg        /* Set up textured video if we can do it at this depth and we are on
187428d7b3dSmrg         * supported hardware.
188428d7b3dSmrg         */
189428d7b3dSmrg        if (!intel->force_fallback &&
190428d7b3dSmrg            scrn->bitsPerPixel >= 16 &&
191428d7b3dSmrg            INTEL_INFO(intel)->gen >= 030 &&
192428d7b3dSmrg            INTEL_INFO(intel)->gen < 0100) {
193428d7b3dSmrg                texturedAdaptor = intel_uxa_video_setup_image_textured(screen);
194428d7b3dSmrg                if (texturedAdaptor != NULL) {
195428d7b3dSmrg                        xf86DrvMsg(scrn->scrnIndex, X_INFO,
196428d7b3dSmrg                                   "Set up textured video\n");
197428d7b3dSmrg                } else {
198428d7b3dSmrg                        xf86DrvMsg(scrn->scrnIndex, X_ERROR,
199428d7b3dSmrg                                   "Failed to set up textured video\n");
200428d7b3dSmrg                }
201428d7b3dSmrg        }
202428d7b3dSmrg
203428d7b3dSmrg        overlayAdaptor = intel_video_overlay_setup_image(screen);
204428d7b3dSmrg
205428d7b3dSmrg        if (intel->use_overlay) {
206428d7b3dSmrg		if (overlayAdaptor != NULL) {
207428d7b3dSmrg			xf86DrvMsg(scrn->scrnIndex, X_INFO,
208428d7b3dSmrg				   "Set up overlay video\n");
209428d7b3dSmrg		} else {
210428d7b3dSmrg			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
211428d7b3dSmrg				   "Failed to set up overlay video\n");
212428d7b3dSmrg		}
213428d7b3dSmrg	}
214428d7b3dSmrg
215428d7b3dSmrg	if (overlayAdaptor && intel->XvPreferOverlay)
216428d7b3dSmrg		adaptors[num_adaptors++] = overlayAdaptor;
217428d7b3dSmrg
218428d7b3dSmrg	if (texturedAdaptor)
219428d7b3dSmrg		adaptors[num_adaptors++] = texturedAdaptor;
220428d7b3dSmrg
221428d7b3dSmrg	if (overlayAdaptor && !intel->XvPreferOverlay)
222428d7b3dSmrg		adaptors[num_adaptors++] = overlayAdaptor;
223428d7b3dSmrg
224428d7b3dSmrg	if (num_adaptors) {
225428d7b3dSmrg		xf86XVScreenInit(screen, adaptors, num_adaptors);
226428d7b3dSmrg	} else {
227428d7b3dSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
228428d7b3dSmrg			   "Disabling Xv because no adaptors could be initialized.\n");
229428d7b3dSmrg		intel->XvEnabled = FALSE;
230428d7b3dSmrg	}
231428d7b3dSmrg
232428d7b3dSmrg#ifdef INTEL_XVMC
233428d7b3dSmrg        if (texturedAdaptor)
234428d7b3dSmrg                intel_xvmc_adaptor_init(screen);
235428d7b3dSmrg#endif
236428d7b3dSmrg
237428d7b3dSmrg	free(adaptors);
238428d7b3dSmrg}
239428d7b3dSmrg
240428d7b3dSmrgvoid intel_free_video_buffers(intel_adaptor_private *adaptor_priv)
241428d7b3dSmrg{
242428d7b3dSmrg	int i;
243428d7b3dSmrg
244428d7b3dSmrg	for (i = 0; i < 2; i++) {
245428d7b3dSmrg		if (adaptor_priv->old_buf[i]) {
246428d7b3dSmrg			drm_intel_bo_disable_reuse(adaptor_priv->old_buf[i]);
247428d7b3dSmrg			drm_intel_bo_unreference(adaptor_priv->old_buf[i]);
248428d7b3dSmrg			adaptor_priv->old_buf[i] = NULL;
249428d7b3dSmrg		}
250428d7b3dSmrg	}
251428d7b3dSmrg
252428d7b3dSmrg	if (adaptor_priv->buf) {
253428d7b3dSmrg		drm_intel_bo_unreference(adaptor_priv->buf);
254428d7b3dSmrg		adaptor_priv->buf = NULL;
255428d7b3dSmrg	}
256428d7b3dSmrg}
257428d7b3dSmrg
258428d7b3dSmrgint
259428d7b3dSmrgintel_video_get_port_attribute(ScrnInfoPtr scrn,
260428d7b3dSmrg                               Atom attribute, INT32 * value, pointer data)
261428d7b3dSmrg{
262428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
263428d7b3dSmrg	intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data;
264428d7b3dSmrg
265428d7b3dSmrg	if (attribute == intel_xv_Brightness) {
266428d7b3dSmrg		*value = adaptor_priv->brightness;
267428d7b3dSmrg	} else if (attribute == intel_xv_Contrast) {
268428d7b3dSmrg		*value = adaptor_priv->contrast;
269428d7b3dSmrg	} else if (attribute == intel_xv_Saturation) {
270428d7b3dSmrg		*value = adaptor_priv->saturation;
271428d7b3dSmrg	} else if (attribute == intel_xv_Pipe) {
272428d7b3dSmrg		int c;
273428d7b3dSmrg		xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
274428d7b3dSmrg		for (c = 0; c < xf86_config->num_crtc; c++)
275428d7b3dSmrg			if (xf86_config->crtc[c] == adaptor_priv->desired_crtc)
276428d7b3dSmrg				break;
277428d7b3dSmrg		if (c == xf86_config->num_crtc)
278428d7b3dSmrg			c = -1;
279428d7b3dSmrg		*value = c;
280428d7b3dSmrg	} else if (attribute == intel_xv_Gamma0 && (INTEL_INFO(intel)->gen >= 030)) {
281428d7b3dSmrg		*value = adaptor_priv->gamma0;
282428d7b3dSmrg	} else if (attribute == intel_xv_Gamma1 && (INTEL_INFO(intel)->gen >= 030)) {
283428d7b3dSmrg		*value = adaptor_priv->gamma1;
284428d7b3dSmrg	} else if (attribute == intel_xv_Gamma2 && (INTEL_INFO(intel)->gen >= 030)) {
285428d7b3dSmrg		*value = adaptor_priv->gamma2;
286428d7b3dSmrg	} else if (attribute == intel_xv_Gamma3 && (INTEL_INFO(intel)->gen >= 030)) {
287428d7b3dSmrg		*value = adaptor_priv->gamma3;
288428d7b3dSmrg	} else if (attribute == intel_xv_Gamma4 && (INTEL_INFO(intel)->gen >= 030)) {
289428d7b3dSmrg		*value = adaptor_priv->gamma4;
290428d7b3dSmrg	} else if (attribute == intel_xv_Gamma5 && (INTEL_INFO(intel)->gen >= 030)) {
291428d7b3dSmrg		*value = adaptor_priv->gamma5;
292428d7b3dSmrg	} else if (attribute == intel_xv_ColorKey) {
293428d7b3dSmrg		*value = adaptor_priv->colorKey;
294428d7b3dSmrg	} else if (attribute == intel_xv_SyncToVblank) {
295428d7b3dSmrg		*value = adaptor_priv->SyncToVblank;
296428d7b3dSmrg	} else
297428d7b3dSmrg		return BadMatch;
298428d7b3dSmrg
299428d7b3dSmrg	return Success;
300428d7b3dSmrg}
301428d7b3dSmrg
302428d7b3dSmrgvoid
303428d7b3dSmrgintel_video_query_best_size(ScrnInfoPtr scrn,
304428d7b3dSmrg		  Bool motion,
305428d7b3dSmrg		  short vid_w, short vid_h,
306428d7b3dSmrg		  short drw_w, short drw_h,
307428d7b3dSmrg		  unsigned int *p_w, unsigned int *p_h, pointer data)
308428d7b3dSmrg{
309428d7b3dSmrg	if (vid_w > (drw_w << 1))
310428d7b3dSmrg		drw_w = vid_w >> 1;
311428d7b3dSmrg	if (vid_h > (drw_h << 1))
312428d7b3dSmrg		drw_h = vid_h >> 1;
313428d7b3dSmrg
314428d7b3dSmrg	*p_w = drw_w;
315428d7b3dSmrg	*p_h = drw_h;
316428d7b3dSmrg}
317428d7b3dSmrg
318428d7b3dSmrgstatic Bool
319428d7b3dSmrgintel_video_copy_packed_data(intel_adaptor_private *adaptor_priv,
320428d7b3dSmrg                                 unsigned char *buf,
321428d7b3dSmrg                                 int srcPitch, int dstPitch, int top, int left, int h, int w)
322428d7b3dSmrg{
323428d7b3dSmrg	unsigned char *src, *dst, *dst_base;
324428d7b3dSmrg	int i, j;
325428d7b3dSmrg	unsigned char *s;
326428d7b3dSmrg
327428d7b3dSmrg#if 0
328428d7b3dSmrg	ErrorF("intel_video_copy_packed_data: (%d,%d) (%d,%d)\n"
329428d7b3dSmrg	       "srcPitch: %d, dstPitch: %d\n", top, left, h, w,
330428d7b3dSmrg	       srcPitch, dstPitch);
331428d7b3dSmrg#endif
332428d7b3dSmrg
333428d7b3dSmrg	src = buf + (top * srcPitch) + (left << 1);
334428d7b3dSmrg
335428d7b3dSmrg	if (drm_intel_gem_bo_map_gtt(adaptor_priv->buf))
336428d7b3dSmrg		return FALSE;
337428d7b3dSmrg
338428d7b3dSmrg	dst_base = adaptor_priv->buf->virtual;
339428d7b3dSmrg
340428d7b3dSmrg	dst = dst_base + adaptor_priv->YBufOffset;
341428d7b3dSmrg
342428d7b3dSmrg	switch (adaptor_priv->rotation) {
343428d7b3dSmrg	case RR_Rotate_0:
344428d7b3dSmrg		w <<= 1;
345428d7b3dSmrg		for (i = 0; i < h; i++) {
346428d7b3dSmrg			memcpy(dst, src, w);
347428d7b3dSmrg			src += srcPitch;
348428d7b3dSmrg			dst += dstPitch;
349428d7b3dSmrg		}
350428d7b3dSmrg		break;
351428d7b3dSmrg	case RR_Rotate_90:
352428d7b3dSmrg		h <<= 1;
353428d7b3dSmrg		for (i = 0; i < h; i += 2) {
354428d7b3dSmrg			s = src;
355428d7b3dSmrg			for (j = 0; j < w; j++) {
356428d7b3dSmrg				/* Copy Y */
357428d7b3dSmrg				dst[(i + 0) + ((w - j - 1) * dstPitch)] = *s++;
358428d7b3dSmrg				(void)*s++;
359428d7b3dSmrg			}
360428d7b3dSmrg			src += srcPitch;
361428d7b3dSmrg		}
362428d7b3dSmrg		h >>= 1;
363428d7b3dSmrg		src = buf + (top * srcPitch) + (left << 1);
364428d7b3dSmrg		for (i = 0; i < h; i += 2) {
365428d7b3dSmrg			for (j = 0; j < w; j += 2) {
366428d7b3dSmrg				/* Copy U */
367428d7b3dSmrg				dst[((i * 2) + 1) + ((w - j - 1) * dstPitch)] =
368428d7b3dSmrg				    src[(j * 2) + 1 + (i * srcPitch)];
369428d7b3dSmrg				dst[((i * 2) + 1) + ((w - j - 2) * dstPitch)] =
370428d7b3dSmrg				    src[(j * 2) + 1 + ((i + 1) * srcPitch)];
371428d7b3dSmrg				/* Copy V */
372428d7b3dSmrg				dst[((i * 2) + 3) + ((w - j - 1) * dstPitch)] =
373428d7b3dSmrg				    src[(j * 2) + 3 + (i * srcPitch)];
374428d7b3dSmrg				dst[((i * 2) + 3) + ((w - j - 2) * dstPitch)] =
375428d7b3dSmrg				    src[(j * 2) + 3 + ((i + 1) * srcPitch)];
376428d7b3dSmrg			}
377428d7b3dSmrg		}
378428d7b3dSmrg		break;
379428d7b3dSmrg	case RR_Rotate_180:
380428d7b3dSmrg		w <<= 1;
381428d7b3dSmrg		for (i = 0; i < h; i++) {
382428d7b3dSmrg			s = src;
383428d7b3dSmrg			for (j = 0; j < w; j += 4) {
384428d7b3dSmrg				dst[(w - j - 4) + ((h - i - 1) * dstPitch)] =
385428d7b3dSmrg				    *s++;
386428d7b3dSmrg				dst[(w - j - 3) + ((h - i - 1) * dstPitch)] =
387428d7b3dSmrg				    *s++;
388428d7b3dSmrg				dst[(w - j - 2) + ((h - i - 1) * dstPitch)] =
389428d7b3dSmrg				    *s++;
390428d7b3dSmrg				dst[(w - j - 1) + ((h - i - 1) * dstPitch)] =
391428d7b3dSmrg				    *s++;
392428d7b3dSmrg			}
393428d7b3dSmrg			src += srcPitch;
394428d7b3dSmrg		}
395428d7b3dSmrg		break;
396428d7b3dSmrg	case RR_Rotate_270:
397428d7b3dSmrg		h <<= 1;
398428d7b3dSmrg		for (i = 0; i < h; i += 2) {
399428d7b3dSmrg			s = src;
400428d7b3dSmrg			for (j = 0; j < w; j++) {
401428d7b3dSmrg				/* Copy Y */
402428d7b3dSmrg				dst[(h - i - 2) + (j * dstPitch)] = *s++;
403428d7b3dSmrg				(void)*s++;
404428d7b3dSmrg			}
405428d7b3dSmrg			src += srcPitch;
406428d7b3dSmrg		}
407428d7b3dSmrg		h >>= 1;
408428d7b3dSmrg		src = buf + (top * srcPitch) + (left << 1);
409428d7b3dSmrg		for (i = 0; i < h; i += 2) {
410428d7b3dSmrg			for (j = 0; j < w; j += 2) {
411428d7b3dSmrg				/* Copy U */
412428d7b3dSmrg				dst[(((h - i) * 2) - 3) + (j * dstPitch)] =
413428d7b3dSmrg				    src[(j * 2) + 1 + (i * srcPitch)];
414428d7b3dSmrg				dst[(((h - i) * 2) - 3) +
415428d7b3dSmrg				    ((j + 1) * dstPitch)] =
416428d7b3dSmrg				    src[(j * 2) + 1 + ((i + 1) * srcPitch)];
417428d7b3dSmrg				/* Copy V */
418428d7b3dSmrg				dst[(((h - i) * 2) - 1) + (j * dstPitch)] =
419428d7b3dSmrg				    src[(j * 2) + 3 + (i * srcPitch)];
420428d7b3dSmrg				dst[(((h - i) * 2) - 1) +
421428d7b3dSmrg				    ((j + 1) * dstPitch)] =
422428d7b3dSmrg				    src[(j * 2) + 3 + ((i + 1) * srcPitch)];
423428d7b3dSmrg			}
424428d7b3dSmrg		}
425428d7b3dSmrg		break;
426428d7b3dSmrg	}
427428d7b3dSmrg
428428d7b3dSmrg	drm_intel_gem_bo_unmap_gtt(adaptor_priv->buf);
429428d7b3dSmrg	return TRUE;
430428d7b3dSmrg}
431428d7b3dSmrg
432428d7b3dSmrgstatic void intel_memcpy_plane(unsigned char *dst, unsigned char *src,
433428d7b3dSmrg			       int height, int width,
434428d7b3dSmrg			       int dstPitch, int srcPitch, Rotation rotation)
435428d7b3dSmrg{
436428d7b3dSmrg	int i, j = 0;
437428d7b3dSmrg	unsigned char *s;
438428d7b3dSmrg
439428d7b3dSmrg	switch (rotation) {
440428d7b3dSmrg	case RR_Rotate_0:
441428d7b3dSmrg		/* optimise for the case of no clipping */
442428d7b3dSmrg		if (srcPitch == dstPitch && srcPitch == width)
443428d7b3dSmrg			memcpy(dst, src, srcPitch * height);
444428d7b3dSmrg		else
445428d7b3dSmrg			for (i = 0; i < height; i++) {
446428d7b3dSmrg				memcpy(dst, src, width);
447428d7b3dSmrg				src += srcPitch;
448428d7b3dSmrg				dst += dstPitch;
449428d7b3dSmrg			}
450428d7b3dSmrg		break;
451428d7b3dSmrg	case RR_Rotate_90:
452428d7b3dSmrg		for (i = 0; i < height; i++) {
453428d7b3dSmrg			s = src;
454428d7b3dSmrg			for (j = 0; j < width; j++) {
455428d7b3dSmrg				dst[(i) + ((width - j - 1) * dstPitch)] = *s++;
456428d7b3dSmrg			}
457428d7b3dSmrg			src += srcPitch;
458428d7b3dSmrg		}
459428d7b3dSmrg		break;
460428d7b3dSmrg	case RR_Rotate_180:
461428d7b3dSmrg		for (i = 0; i < height; i++) {
462428d7b3dSmrg			s = src;
463428d7b3dSmrg			for (j = 0; j < width; j++) {
464428d7b3dSmrg				dst[(width - j - 1) +
465428d7b3dSmrg				    ((height - i - 1) * dstPitch)] = *s++;
466428d7b3dSmrg			}
467428d7b3dSmrg			src += srcPitch;
468428d7b3dSmrg		}
469428d7b3dSmrg		break;
470428d7b3dSmrg	case RR_Rotate_270:
471428d7b3dSmrg		for (i = 0; i < height; i++) {
472428d7b3dSmrg			s = src;
473428d7b3dSmrg			for (j = 0; j < width; j++) {
474428d7b3dSmrg				dst[(height - i - 1) + (j * dstPitch)] = *s++;
475428d7b3dSmrg			}
476428d7b3dSmrg			src += srcPitch;
477428d7b3dSmrg		}
478428d7b3dSmrg		break;
479428d7b3dSmrg	}
480428d7b3dSmrg}
481428d7b3dSmrg
482428d7b3dSmrgstatic Bool
483428d7b3dSmrgintel_video_copy_planar_data(intel_adaptor_private *adaptor_priv,
484428d7b3dSmrg		   unsigned char *buf, int srcPitch, int srcPitch2,
485428d7b3dSmrg		   int dstPitch, int dstPitch2,
486428d7b3dSmrg		   int srcH, int top, int left,
487428d7b3dSmrg		   int h, int w, int id)
488428d7b3dSmrg{
489428d7b3dSmrg	unsigned char *src1, *src2, *src3, *dst_base, *dst1, *dst2, *dst3;
490428d7b3dSmrg
491428d7b3dSmrg#if 0
492428d7b3dSmrg	ErrorF("intel_video_copy_planar_data: srcPitch %d, srcPitch %d, dstPitch %d\n"
493428d7b3dSmrg	       "nlines %d, npixels %d, top %d, left %d\n",
494428d7b3dSmrg	       srcPitch, srcPitch2, dstPitch, h, w, top, left);
495428d7b3dSmrg#endif
496428d7b3dSmrg
497428d7b3dSmrg	/* Copy Y data */
498428d7b3dSmrg	src1 = buf + (top * srcPitch) + left;
499428d7b3dSmrg#if 0
500428d7b3dSmrg	ErrorF("src1 is %p, offset is %ld\n", src1,
501428d7b3dSmrg	       (unsigned long)src1 - (unsigned long)buf);
502428d7b3dSmrg#endif
503428d7b3dSmrg
504428d7b3dSmrg	if (drm_intel_gem_bo_map_gtt(adaptor_priv->buf))
505428d7b3dSmrg		return FALSE;
506428d7b3dSmrg
507428d7b3dSmrg	dst_base = adaptor_priv->buf->virtual;
508428d7b3dSmrg
509428d7b3dSmrg	dst1 = dst_base + adaptor_priv->YBufOffset;
510428d7b3dSmrg
511428d7b3dSmrg	intel_memcpy_plane(dst1, src1, h, w, dstPitch2, srcPitch,
512428d7b3dSmrg			  adaptor_priv->rotation);
513428d7b3dSmrg
514428d7b3dSmrg	/* Copy V data for YV12, or U data for I420 */
515428d7b3dSmrg	src2 = buf +		/* start of YUV data */
516428d7b3dSmrg	    (srcH * srcPitch) +	/* move over Luma plane */
517428d7b3dSmrg	    ((top >> 1) * srcPitch2) +	/* move down from by top lines */
518428d7b3dSmrg	    (left >> 1);	/* move left by left pixels */
519428d7b3dSmrg
520428d7b3dSmrg#if 0
521428d7b3dSmrg	ErrorF("src2 is %p, offset is %ld\n", src2,
522428d7b3dSmrg	       (unsigned long)src2 - (unsigned long)buf);
523428d7b3dSmrg#endif
524428d7b3dSmrg	if (id == FOURCC_I420)
525428d7b3dSmrg		dst2 = dst_base + adaptor_priv->UBufOffset;
526428d7b3dSmrg	else
527428d7b3dSmrg		dst2 = dst_base + adaptor_priv->VBufOffset;
528428d7b3dSmrg
529428d7b3dSmrg	intel_memcpy_plane(dst2, src2, h / 2, w / 2,
530428d7b3dSmrg			  dstPitch, srcPitch2, adaptor_priv->rotation);
531428d7b3dSmrg
532428d7b3dSmrg	/* Copy U data for YV12, or V data for I420 */
533428d7b3dSmrg	src3 = buf +		/* start of YUV data */
534428d7b3dSmrg	    (srcH * srcPitch) +	/* move over Luma plane */
535428d7b3dSmrg	    ((srcH >> 1) * srcPitch2) +	/* move over Chroma plane */
536428d7b3dSmrg	    ((top >> 1) * srcPitch2) +	/* move down from by top lines */
537428d7b3dSmrg	    (left >> 1);	/* move left by left pixels */
538428d7b3dSmrg#if 0
539428d7b3dSmrg	ErrorF("src3 is %p, offset is %ld\n", src3,
540428d7b3dSmrg	       (unsigned long)src3 - (unsigned long)buf);
541428d7b3dSmrg#endif
542428d7b3dSmrg	if (id == FOURCC_I420)
543428d7b3dSmrg		dst3 = dst_base + adaptor_priv->VBufOffset;
544428d7b3dSmrg	else
545428d7b3dSmrg		dst3 = dst_base + adaptor_priv->UBufOffset;
546428d7b3dSmrg
547428d7b3dSmrg	intel_memcpy_plane(dst3, src3, h / 2, w / 2,
548428d7b3dSmrg			  dstPitch, srcPitch2, adaptor_priv->rotation);
549428d7b3dSmrg
550428d7b3dSmrg	drm_intel_gem_bo_unmap_gtt(adaptor_priv->buf);
551428d7b3dSmrg	return TRUE;
552428d7b3dSmrg}
553428d7b3dSmrg
554428d7b3dSmrgvoid
555428d7b3dSmrgintel_setup_dst_params(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv, short width,
556428d7b3dSmrg		       short height, int *dstPitch, int *dstPitch2, int *size,
557428d7b3dSmrg		       int id)
558428d7b3dSmrg{
559428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
560428d7b3dSmrg	int pitchAlign;
561428d7b3dSmrg
562428d7b3dSmrg	/* Only needs to be DWORD-aligned for textured on i915, but overlay has
563428d7b3dSmrg	 * stricter requirements.
564428d7b3dSmrg	 */
565428d7b3dSmrg	if (adaptor_priv->textured) {
566428d7b3dSmrg		pitchAlign = 4;
567428d7b3dSmrg	} else {
568428d7b3dSmrg		if (INTEL_INFO(intel)->gen >= 040)
569428d7b3dSmrg			/* Actually the alignment is 64 bytes, too. But the
570428d7b3dSmrg			 * stride must be at least 512 bytes. Take the easy fix
571428d7b3dSmrg			 * and align on 512 bytes unconditionally. */
572428d7b3dSmrg			pitchAlign = 512;
573428d7b3dSmrg		else if (IS_I830(intel) || IS_845G(intel))
574428d7b3dSmrg			/* Harsh, errata on these chipsets limit the stride to be
575428d7b3dSmrg			 * a multiple of 256 bytes.
576428d7b3dSmrg			 */
577428d7b3dSmrg			pitchAlign = 256;
578428d7b3dSmrg		else
579428d7b3dSmrg			pitchAlign = 64;
580428d7b3dSmrg	}
581428d7b3dSmrg
582428d7b3dSmrg#if INTEL_XVMC
583428d7b3dSmrg	/* for i915 xvmc, hw requires 1kb aligned surfaces */
584428d7b3dSmrg	if ((id == FOURCC_XVMC) && IS_GEN3(intel))
585428d7b3dSmrg		pitchAlign = 1024;
586428d7b3dSmrg#endif
587428d7b3dSmrg
588428d7b3dSmrg	/* Determine the desired destination pitch (representing the chroma's pitch,
589428d7b3dSmrg	 * in the planar case.
590428d7b3dSmrg	 */
591428d7b3dSmrg	if (is_planar_fourcc(id)) {
592428d7b3dSmrg		if (adaptor_priv->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
593428d7b3dSmrg			*dstPitch = ALIGN((height / 2), pitchAlign);
594428d7b3dSmrg			*dstPitch2 = ALIGN(height, pitchAlign);
595428d7b3dSmrg			*size = *dstPitch * width * 3;
596428d7b3dSmrg		} else {
597428d7b3dSmrg			*dstPitch = ALIGN((width / 2), pitchAlign);
598428d7b3dSmrg			*dstPitch2 = ALIGN(width, pitchAlign);
599428d7b3dSmrg			*size = *dstPitch * height * 3;
600428d7b3dSmrg		}
601428d7b3dSmrg	} else {
602428d7b3dSmrg		if (adaptor_priv->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
603428d7b3dSmrg			*dstPitch = ALIGN((height << 1), pitchAlign);
604428d7b3dSmrg			*size = *dstPitch * width;
605428d7b3dSmrg		} else {
606428d7b3dSmrg			*dstPitch = ALIGN((width << 1), pitchAlign);
607428d7b3dSmrg			*size = *dstPitch * height;
608428d7b3dSmrg		}
609428d7b3dSmrg		*dstPitch2 = 0;
610428d7b3dSmrg	}
611428d7b3dSmrg#if 0
612428d7b3dSmrg	ErrorF("srcPitch: %d, dstPitch: %d, size: %d\n", srcPitch, *dstPitch,
613428d7b3dSmrg	       size);
614428d7b3dSmrg#endif
615428d7b3dSmrg
616428d7b3dSmrg	adaptor_priv->YBufOffset = 0;
617428d7b3dSmrg
618428d7b3dSmrg	if (adaptor_priv->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
619428d7b3dSmrg		adaptor_priv->UBufOffset =
620428d7b3dSmrg		    adaptor_priv->YBufOffset + (*dstPitch2 * width);
621428d7b3dSmrg		adaptor_priv->VBufOffset =
622428d7b3dSmrg		    adaptor_priv->UBufOffset + (*dstPitch * width / 2);
623428d7b3dSmrg	} else {
624428d7b3dSmrg		adaptor_priv->UBufOffset =
625428d7b3dSmrg		    adaptor_priv->YBufOffset + (*dstPitch2 * height);
626428d7b3dSmrg		adaptor_priv->VBufOffset =
627428d7b3dSmrg		    adaptor_priv->UBufOffset + (*dstPitch * height / 2);
628428d7b3dSmrg	}
629428d7b3dSmrg}
630428d7b3dSmrg
631428d7b3dSmrgstatic Bool
632428d7b3dSmrgintel_setup_video_buffer(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv,
633428d7b3dSmrg			 int alloc_size, int id, unsigned char *buf)
634428d7b3dSmrg{
635428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
636428d7b3dSmrg
637428d7b3dSmrg	/* Free the current buffer if we're going to have to reallocate */
638428d7b3dSmrg	if (adaptor_priv->buf && adaptor_priv->buf->size < alloc_size)
639428d7b3dSmrg		intel_free_video_buffers(adaptor_priv);
640428d7b3dSmrg
641428d7b3dSmrg	if (adaptor_priv->buf == NULL) {
642428d7b3dSmrg		adaptor_priv->buf = drm_intel_bo_alloc(intel->bufmgr, "xv buffer",
643428d7b3dSmrg						       alloc_size, 4096);
644428d7b3dSmrg		if (adaptor_priv->buf == NULL)
645428d7b3dSmrg			return FALSE;
646428d7b3dSmrg
647428d7b3dSmrg		adaptor_priv->reusable = TRUE;
648428d7b3dSmrg	}
649428d7b3dSmrg
650428d7b3dSmrg	return TRUE;
651428d7b3dSmrg}
652428d7b3dSmrg
653428d7b3dSmrgBool
654428d7b3dSmrgintel_video_copy_data(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv,
655428d7b3dSmrg                      short width, short height, int *dstPitch, int *dstPitch2,
656428d7b3dSmrg                      int top, int left, int npixels, int nlines,
657428d7b3dSmrg                      int id, unsigned char *buf)
658428d7b3dSmrg{
659428d7b3dSmrg	int srcPitch = 0, srcPitch2 = 0;
660428d7b3dSmrg	int size;
661428d7b3dSmrg
662428d7b3dSmrg	if (is_planar_fourcc(id)) {
663428d7b3dSmrg		srcPitch = ALIGN(width, 0x4);
664428d7b3dSmrg		srcPitch2 = ALIGN((width >> 1), 0x4);
665428d7b3dSmrg	} else {
666428d7b3dSmrg		srcPitch = width << 1;
667428d7b3dSmrg	}
668428d7b3dSmrg
669428d7b3dSmrg	intel_setup_dst_params(scrn, adaptor_priv, width, height, dstPitch,
670428d7b3dSmrg				dstPitch2, &size, id);
671428d7b3dSmrg
672428d7b3dSmrg	if (!intel_setup_video_buffer(scrn, adaptor_priv, size, id, buf))
673428d7b3dSmrg		return FALSE;
674428d7b3dSmrg
675428d7b3dSmrg	/* copy data */
676428d7b3dSmrg	if (is_planar_fourcc(id)) {
677428d7b3dSmrg		return intel_video_copy_planar_data(adaptor_priv, buf, srcPitch, srcPitch2,
678428d7b3dSmrg					  *dstPitch, *dstPitch2,
679428d7b3dSmrg					  height, top, left, nlines,
680428d7b3dSmrg					  npixels, id);
681428d7b3dSmrg	} else {
682428d7b3dSmrg		return intel_video_copy_packed_data(adaptor_priv, buf, srcPitch, *dstPitch, top, left,
683428d7b3dSmrg					  nlines, npixels);
684428d7b3dSmrg	}
685428d7b3dSmrg}
686428d7b3dSmrg
687428d7b3dSmrgint is_planar_fourcc(int id)
688428d7b3dSmrg{
689428d7b3dSmrg	switch (id) {
690428d7b3dSmrg	case FOURCC_YV12:
691428d7b3dSmrg	case FOURCC_I420:
692428d7b3dSmrg#ifdef INTEL_XVMC
693428d7b3dSmrg	case FOURCC_XVMC:
694428d7b3dSmrg#endif
695428d7b3dSmrg		return 1;
696428d7b3dSmrg	case FOURCC_UYVY:
697428d7b3dSmrg	case FOURCC_YUY2:
698428d7b3dSmrg		return 0;
699428d7b3dSmrg	default:
700428d7b3dSmrg		ErrorF("Unknown format 0x%x\n", id);
701428d7b3dSmrg		return 0;
702428d7b3dSmrg	}
703428d7b3dSmrg}
704428d7b3dSmrg
705428d7b3dSmrgBool
706428d7b3dSmrgintel_clip_video_helper(ScrnInfoPtr scrn,
707428d7b3dSmrg			intel_adaptor_private *adaptor_priv,
708428d7b3dSmrg			xf86CrtcPtr * crtc_ret,
709428d7b3dSmrg			BoxPtr dst,
710428d7b3dSmrg			short src_x, short src_y,
711428d7b3dSmrg			short drw_x, short drw_y,
712428d7b3dSmrg			short src_w, short src_h,
713428d7b3dSmrg			short drw_w, short drw_h,
714428d7b3dSmrg			int id,
715428d7b3dSmrg			int *top, int* left, int* npixels, int *nlines,
716428d7b3dSmrg			RegionPtr reg, INT32 width, INT32 height)
717428d7b3dSmrg{
718428d7b3dSmrg	Bool ret;
719428d7b3dSmrg	RegionRec crtc_region_local;
720428d7b3dSmrg	RegionPtr crtc_region = reg;
721428d7b3dSmrg	BoxRec crtc_box;
722428d7b3dSmrg	INT32 x1, x2, y1, y2;
723428d7b3dSmrg	xf86CrtcPtr crtc;
724428d7b3dSmrg
725428d7b3dSmrg	x1 = src_x;
726428d7b3dSmrg	x2 = src_x + src_w;
727428d7b3dSmrg	y1 = src_y;
728428d7b3dSmrg	y2 = src_y + src_h;
729428d7b3dSmrg
730428d7b3dSmrg	dst->x1 = drw_x;
731428d7b3dSmrg	dst->x2 = drw_x + drw_w;
732428d7b3dSmrg	dst->y1 = drw_y;
733428d7b3dSmrg	dst->y2 = drw_y + drw_h;
734428d7b3dSmrg
735428d7b3dSmrg	/*
736428d7b3dSmrg	 * For overlay video, compute the relevant CRTC and
737428d7b3dSmrg	 * clip video to that
738428d7b3dSmrg	 */
739428d7b3dSmrg	crtc = intel_covering_crtc(scrn, dst, adaptor_priv->desired_crtc,
740428d7b3dSmrg				   &crtc_box);
741428d7b3dSmrg
742428d7b3dSmrg	/* For textured video, we don't actually want to clip at all. */
743428d7b3dSmrg	if (crtc && !adaptor_priv->textured) {
744428d7b3dSmrg		REGION_INIT(screen, &crtc_region_local, &crtc_box, 1);
745428d7b3dSmrg		crtc_region = &crtc_region_local;
746428d7b3dSmrg		REGION_INTERSECT(screen, crtc_region, crtc_region,
747428d7b3dSmrg				 reg);
748428d7b3dSmrg	}
749428d7b3dSmrg	*crtc_ret = crtc;
750428d7b3dSmrg
751428d7b3dSmrg	ret = xf86XVClipVideoHelper(dst, &x1, &x2, &y1, &y2,
752428d7b3dSmrg				    crtc_region, width, height);
753428d7b3dSmrg	if (crtc_region != reg)
754428d7b3dSmrg		REGION_UNINIT(screen, &crtc_region_local);
755428d7b3dSmrg
756428d7b3dSmrg	*top = y1 >> 16;
757428d7b3dSmrg	*left = (x1 >> 16) & ~1;
758428d7b3dSmrg	*npixels = ALIGN(((x2 + 0xffff) >> 16), 2) - *left;
759428d7b3dSmrg	if (is_planar_fourcc(id)) {
760428d7b3dSmrg		*top &= ~1;
761428d7b3dSmrg		*nlines = ALIGN(((y2 + 0xffff) >> 16), 2) - *top;
762428d7b3dSmrg	} else
763428d7b3dSmrg		*nlines = ((y2 + 0xffff) >> 16) - *top;
764428d7b3dSmrg
765428d7b3dSmrg	return ret;
766428d7b3dSmrg}
767428d7b3dSmrg
768428d7b3dSmrgint
769428d7b3dSmrgintel_video_query_image_attributes(ScrnInfoPtr scrn,
770428d7b3dSmrg                                   int id,
771428d7b3dSmrg                                   unsigned short *w, unsigned short *h,
772428d7b3dSmrg                                   int *pitches, int *offsets)
773428d7b3dSmrg{
774428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
775428d7b3dSmrg	int size, tmp;
776428d7b3dSmrg
777428d7b3dSmrg#if 0
778428d7b3dSmrg	ErrorF("intel_video_query_image_attributes: w is %d, h is %d\n", *w, *h);
779428d7b3dSmrg#endif
780428d7b3dSmrg
781428d7b3dSmrg	if (IS_845G(intel) || IS_I830(intel)) {
782428d7b3dSmrg		if (*w > IMAGE_MAX_WIDTH_LEGACY)
783428d7b3dSmrg			*w = IMAGE_MAX_WIDTH_LEGACY;
784428d7b3dSmrg		if (*h > IMAGE_MAX_HEIGHT_LEGACY)
785428d7b3dSmrg			*h = IMAGE_MAX_HEIGHT_LEGACY;
786428d7b3dSmrg	} else {
787428d7b3dSmrg		if (*w > IMAGE_MAX_WIDTH)
788428d7b3dSmrg			*w = IMAGE_MAX_WIDTH;
789428d7b3dSmrg		if (*h > IMAGE_MAX_HEIGHT)
790428d7b3dSmrg			*h = IMAGE_MAX_HEIGHT;
791428d7b3dSmrg	}
792428d7b3dSmrg
793428d7b3dSmrg	*w = (*w + 1) & ~1;
794428d7b3dSmrg	if (offsets)
795428d7b3dSmrg		offsets[0] = 0;
796428d7b3dSmrg
797428d7b3dSmrg	switch (id) {
798428d7b3dSmrg		/* IA44 is for XvMC only */
799428d7b3dSmrg	case FOURCC_IA44:
800428d7b3dSmrg	case FOURCC_AI44:
801428d7b3dSmrg		if (pitches)
802428d7b3dSmrg			pitches[0] = *w;
803428d7b3dSmrg		size = *w * *h;
804428d7b3dSmrg		break;
805428d7b3dSmrg	case FOURCC_YV12:
806428d7b3dSmrg	case FOURCC_I420:
807428d7b3dSmrg		*h = (*h + 1) & ~1;
808428d7b3dSmrg		size = (*w + 3) & ~3;
809428d7b3dSmrg		if (pitches)
810428d7b3dSmrg			pitches[0] = size;
811428d7b3dSmrg		size *= *h;
812428d7b3dSmrg		if (offsets)
813428d7b3dSmrg			offsets[1] = size;
814428d7b3dSmrg		tmp = ((*w >> 1) + 3) & ~3;
815428d7b3dSmrg		if (pitches)
816428d7b3dSmrg			pitches[1] = pitches[2] = tmp;
817428d7b3dSmrg		tmp *= (*h >> 1);
818428d7b3dSmrg		size += tmp;
819428d7b3dSmrg		if (offsets)
820428d7b3dSmrg			offsets[2] = size;
821428d7b3dSmrg		size += tmp;
822428d7b3dSmrg#if 0
823428d7b3dSmrg		if (pitches)
824428d7b3dSmrg			ErrorF("pitch 0 is %d, pitch 1 is %d, pitch 2 is %d\n",
825428d7b3dSmrg			       pitches[0], pitches[1], pitches[2]);
826428d7b3dSmrg		if (offsets)
827428d7b3dSmrg			ErrorF("offset 1 is %d, offset 2 is %d\n", offsets[1],
828428d7b3dSmrg			       offsets[2]);
829428d7b3dSmrg		if (offsets)
830428d7b3dSmrg			ErrorF("size is %d\n", size);
831428d7b3dSmrg#endif
832428d7b3dSmrg		break;
833428d7b3dSmrg#ifdef INTEL_XVMC
834428d7b3dSmrg	case FOURCC_XVMC:
835428d7b3dSmrg		*h = (*h + 1) & ~1;
836428d7b3dSmrg		size = sizeof(struct intel_xvmc_command);
837428d7b3dSmrg		if (pitches)
838428d7b3dSmrg			pitches[0] = size;
839428d7b3dSmrg		break;
840428d7b3dSmrg#endif
841428d7b3dSmrg	case FOURCC_UYVY:
842428d7b3dSmrg	case FOURCC_YUY2:
843428d7b3dSmrg	default:
844428d7b3dSmrg		size = *w << 1;
845428d7b3dSmrg		if (pitches)
846428d7b3dSmrg			pitches[0] = size;
847428d7b3dSmrg		size *= *h;
848428d7b3dSmrg		break;
849428d7b3dSmrg	}
850428d7b3dSmrg
851428d7b3dSmrg	return size;
852428d7b3dSmrg}
853428d7b3dSmrg
854428d7b3dSmrgvoid intel_video_stop_video(ScrnInfoPtr scrn, pointer data, Bool shutdown)
855428d7b3dSmrg{
856428d7b3dSmrg	intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data;
857428d7b3dSmrg
858428d7b3dSmrg	if (adaptor_priv->textured)
859428d7b3dSmrg		return;
860428d7b3dSmrg
861428d7b3dSmrg	REGION_EMPTY(scrn->pScreen, &adaptor_priv->clip);
862428d7b3dSmrg
863428d7b3dSmrg	if (shutdown) {
864428d7b3dSmrg		if (adaptor_priv->videoStatus & CLIENT_VIDEO_ON)
865428d7b3dSmrg			intel_video_overlay_off(intel_get_screen_private(scrn));
866428d7b3dSmrg
867428d7b3dSmrg		intel_free_video_buffers(adaptor_priv);
868428d7b3dSmrg		adaptor_priv->videoStatus = 0;
869428d7b3dSmrg	} else {
870428d7b3dSmrg		if (adaptor_priv->videoStatus & CLIENT_VIDEO_ON) {
871428d7b3dSmrg			adaptor_priv->videoStatus |= OFF_TIMER;
872428d7b3dSmrg			adaptor_priv->offTime = currentTime.milliseconds + OFF_DELAY;
873428d7b3dSmrg		}
874428d7b3dSmrg	}
875428d7b3dSmrg
876428d7b3dSmrg}
877428d7b3dSmrg
878428d7b3dSmrgvoid
879428d7b3dSmrgintel_video_block_handler(intel_screen_private *intel)
880428d7b3dSmrg{
881428d7b3dSmrg	intel_adaptor_private *adaptor_priv;
882428d7b3dSmrg
883428d7b3dSmrg	/* no overlay */
884428d7b3dSmrg	if (intel->adaptor == NULL)
885428d7b3dSmrg		return;
886428d7b3dSmrg
887428d7b3dSmrg	adaptor_priv = intel_get_adaptor_private(intel);
888428d7b3dSmrg	if (adaptor_priv->videoStatus & OFF_TIMER) {
889428d7b3dSmrg		Time now = currentTime.milliseconds;
890428d7b3dSmrg		if (adaptor_priv->offTime < now) {
891428d7b3dSmrg			/* Turn off the overlay */
892428d7b3dSmrg			intel_video_overlay_off(intel);
893428d7b3dSmrg			intel_free_video_buffers(adaptor_priv);
894428d7b3dSmrg			adaptor_priv->videoStatus = 0;
895428d7b3dSmrg		}
896428d7b3dSmrg	}
897428d7b3dSmrg}
898