intel_video.c revision 13496ba1
103b705cfSriastradh/***************************************************************************
203b705cfSriastradh
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
2303b705cfSriastradh THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2403b705cfSriastradh
2503b705cfSriastradh **************************************************************************/
2603b705cfSriastradh
2703b705cfSriastradh/*
2813496ba1Ssnj * i830_video.c: i830/i845 Xv driver.
2903b705cfSriastradh *
3003b705cfSriastradh * Copyright © 2002 by Alan Hourihane and David Dawes
3103b705cfSriastradh *
3213496ba1Ssnj * Authors:
3303b705cfSriastradh *	Alan Hourihane <alanh@tungstengraphics.com>
3403b705cfSriastradh *	David Dawes <dawes@xfree86.org>
3503b705cfSriastradh *
3603b705cfSriastradh * Derived from i810 Xv driver:
3703b705cfSriastradh *
3803b705cfSriastradh * Authors of i810 code:
3903b705cfSriastradh * 	Jonathan Bian <jonathan.bian@intel.com>
4003b705cfSriastradh *      Offscreen Images:
4103b705cfSriastradh *        Matt Sottek <matthew.j.sottek@intel.com>
4203b705cfSriastradh */
4303b705cfSriastradh
4403b705cfSriastradh/*
4503b705cfSriastradh * XXX Could support more formats.
4603b705cfSriastradh */
4703b705cfSriastradh
4803b705cfSriastradh#ifdef HAVE_CONFIG_H
4903b705cfSriastradh#include "config.h"
5003b705cfSriastradh#endif
5103b705cfSriastradh
5203b705cfSriastradh#include <inttypes.h>
5303b705cfSriastradh#include <math.h>
5403b705cfSriastradh#include <string.h>
5503b705cfSriastradh#include <assert.h>
5603b705cfSriastradh#include <errno.h>
5703b705cfSriastradh
5842542f5fSchristos#include "xorg-server.h"
5903b705cfSriastradh#include "xf86.h"
6003b705cfSriastradh#include "xf86_OSproc.h"
6103b705cfSriastradh#include "compiler.h"
6203b705cfSriastradh#include "xf86Pci.h"
6303b705cfSriastradh#include "xf86fbman.h"
6403b705cfSriastradh#include "xf86drm.h"
6503b705cfSriastradh#include "regionstr.h"
6603b705cfSriastradh#include "randrstr.h"
6703b705cfSriastradh#include "windowstr.h"
6803b705cfSriastradh#include "damage.h"
6903b705cfSriastradh#include "intel.h"
7003b705cfSriastradh#include "intel_video.h"
7103b705cfSriastradh#include "i830_reg.h"
7203b705cfSriastradh#include "xf86xv.h"
7303b705cfSriastradh#include <X11/extensions/Xv.h>
7403b705cfSriastradh#include "dixstruct.h"
7503b705cfSriastradh#include "fourcc.h"
7603b705cfSriastradh
7703b705cfSriastradh#ifdef INTEL_XVMC
7803b705cfSriastradh#define _INTEL_XVMC_SERVER_
7903b705cfSriastradh#include "intel_xvmc.h"
8003b705cfSriastradh#endif
8113496ba1Ssnj#include "intel_uxa.h"
8213496ba1Ssnj#include "intel_video_overlay.h"
8303b705cfSriastradh
8413496ba1SsnjAtom intel_xv_Brightness, intel_xv_Contrast, intel_xv_Saturation, intel_xv_ColorKey, intel_xv_Pipe;
8513496ba1SsnjAtom intel_xv_Gamma0, intel_xv_Gamma1, intel_xv_Gamma2, intel_xv_Gamma3, intel_xv_Gamma4, intel_xv_Gamma5;
8613496ba1SsnjAtom intel_xv_SyncToVblank;
8703b705cfSriastradh
8803b705cfSriastradh/* client libraries expect an encoding */
8913496ba1Ssnjconst XF86VideoEncodingRec intel_xv_dummy_encoding[1] = {
9003b705cfSriastradh	{
9103b705cfSriastradh	 0,
9203b705cfSriastradh	 "XV_IMAGE",
9303b705cfSriastradh	 IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
9403b705cfSriastradh	 {1, 1}
9503b705cfSriastradh	 }
9603b705cfSriastradh};
9703b705cfSriastradh
9813496ba1SsnjXF86VideoFormatRec intel_xv_formats[NUM_FORMATS] = {
9903b705cfSriastradh	{15, TrueColor}, {16, TrueColor}, {24, TrueColor}
10003b705cfSriastradh};
10103b705cfSriastradh
10213496ba1SsnjXF86AttributeRec intel_xv_attributes[NUM_ATTRIBUTES] = {
10303b705cfSriastradh	{XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
10403b705cfSriastradh	{XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
10503b705cfSriastradh	{XvSettable | XvGettable, 0, 255, "XV_CONTRAST"},
10603b705cfSriastradh	{XvSettable | XvGettable, 0, 1023, "XV_SATURATION"},
10703b705cfSriastradh	{XvSettable | XvGettable, -1, 1, "XV_PIPE"}
10803b705cfSriastradh};
10903b705cfSriastradh
11003b705cfSriastradh#define GAMMA_ATTRIBUTES 6
11113496ba1SsnjXF86AttributeRec intel_xv_gamma_attributes[GAMMA_ATTRIBUTES] = {
11203b705cfSriastradh	{XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA0"},
11303b705cfSriastradh	{XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA1"},
11403b705cfSriastradh	{XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA2"},
11503b705cfSriastradh	{XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA3"},
11603b705cfSriastradh	{XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA4"},
11703b705cfSriastradh	{XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA5"}
11803b705cfSriastradh};
11903b705cfSriastradh
12003b705cfSriastradh#ifdef INTEL_XVMC
12103b705cfSriastradh#define NUM_IMAGES 5
12203b705cfSriastradh#define XVMC_IMAGE 1
12303b705cfSriastradh#else
12403b705cfSriastradh#define NUM_IMAGES 4
12503b705cfSriastradh#define XVMC_IMAGE 0
12603b705cfSriastradh#endif
12703b705cfSriastradh
12813496ba1SsnjXF86ImageRec intel_xv_images[NUM_IMAGES] = {
12903b705cfSriastradh	XVIMAGE_YUY2,
13003b705cfSriastradh	XVIMAGE_YV12,
13103b705cfSriastradh	XVIMAGE_I420,
13203b705cfSriastradh	XVIMAGE_UYVY,
13303b705cfSriastradh#ifdef INTEL_XVMC
13403b705cfSriastradh	{
13503b705cfSriastradh	 /*
13603b705cfSriastradh	  * Below, a dummy picture type that is used in XvPutImage only to do
13703b705cfSriastradh	  * an overlay update. Introduced for the XvMC client lib.
13803b705cfSriastradh	  * Defined to have a zero data size.
13903b705cfSriastradh	  */
14003b705cfSriastradh	 FOURCC_XVMC,
14103b705cfSriastradh	 XvYUV,
14203b705cfSriastradh	 LSBFirst,
14303b705cfSriastradh	 {'X', 'V', 'M', 'C',
14403b705cfSriastradh	  0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0xAA, 0x00,
14503b705cfSriastradh	  0x38, 0x9B, 0x71},
14603b705cfSriastradh	 12,
14703b705cfSriastradh	 XvPlanar,
14803b705cfSriastradh	 3,
14903b705cfSriastradh	 0, 0, 0, 0,
15003b705cfSriastradh	 8, 8, 8,
15103b705cfSriastradh	 1, 2, 2,
15203b705cfSriastradh	 1, 2, 2,
15303b705cfSriastradh	 {'Y', 'V', 'U',
15403b705cfSriastradh	  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
15503b705cfSriastradh	  0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
15603b705cfSriastradh	 XvTopToBottom},
15703b705cfSriastradh#endif
15803b705cfSriastradh};
15903b705cfSriastradh
16013496ba1Ssnjvoid intel_video_init(ScreenPtr screen)
16103b705cfSriastradh{
16203b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
16303b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
16403b705cfSriastradh	XF86VideoAdaptorPtr *adaptors = NULL, *newAdaptors = NULL;
16513496ba1Ssnj	XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL;
16603b705cfSriastradh	int num_adaptors = xf86XVListGenericAdaptors(scrn, &adaptors);
16713496ba1Ssnj
16803b705cfSriastradh	/* Give our adaptor list enough space for the overlay and/or texture video
16903b705cfSriastradh	 * adaptors.
17003b705cfSriastradh	 */
17103b705cfSriastradh	newAdaptors = realloc(adaptors,
17242542f5fSchristos			      (num_adaptors + 3) * sizeof(XF86VideoAdaptorPtr));
17313496ba1Ssnj
17403b705cfSriastradh	if (newAdaptors == NULL) {
17503b705cfSriastradh		free(adaptors);
17603b705cfSriastradh		return;
17703b705cfSriastradh	}
17803b705cfSriastradh	adaptors = newAdaptors;
17903b705cfSriastradh
18003b705cfSriastradh	/* Add the adaptors supported by our hardware.  First, set up the atoms
18103b705cfSriastradh	 * that will be used by both output adaptors.
18203b705cfSriastradh	 */
18313496ba1Ssnj	intel_xv_Brightness = MAKE_ATOM("XV_BRIGHTNESS");
18413496ba1Ssnj	intel_xv_Contrast = MAKE_ATOM("XV_CONTRAST");
18513496ba1Ssnj
18613496ba1Ssnj        /* Set up textured video if we can do it at this depth and we are on
18713496ba1Ssnj         * supported hardware.
18813496ba1Ssnj         */
18913496ba1Ssnj        if (!intel->force_fallback &&
19013496ba1Ssnj            scrn->bitsPerPixel >= 16 &&
19113496ba1Ssnj            INTEL_INFO(intel)->gen >= 030 &&
19213496ba1Ssnj            INTEL_INFO(intel)->gen < 0100) {
19313496ba1Ssnj                texturedAdaptor = intel_uxa_video_setup_image_textured(screen);
19413496ba1Ssnj                if (texturedAdaptor != NULL) {
19513496ba1Ssnj                        xf86DrvMsg(scrn->scrnIndex, X_INFO,
19613496ba1Ssnj                                   "Set up textured video\n");
19713496ba1Ssnj                } else {
19813496ba1Ssnj                        xf86DrvMsg(scrn->scrnIndex, X_ERROR,
19913496ba1Ssnj                                   "Failed to set up textured video\n");
20013496ba1Ssnj                }
20113496ba1Ssnj        }
20213496ba1Ssnj
20313496ba1Ssnj        overlayAdaptor = intel_video_overlay_setup_image(screen);
20413496ba1Ssnj
20513496ba1Ssnj        if (intel->use_overlay) {
20603b705cfSriastradh		if (overlayAdaptor != NULL) {
20703b705cfSriastradh			xf86DrvMsg(scrn->scrnIndex, X_INFO,
20803b705cfSriastradh				   "Set up overlay video\n");
20903b705cfSriastradh		} else {
21003b705cfSriastradh			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
21103b705cfSriastradh				   "Failed to set up overlay video\n");
21203b705cfSriastradh		}
21303b705cfSriastradh	}
21403b705cfSriastradh
21503b705cfSriastradh	if (overlayAdaptor && intel->XvPreferOverlay)
21603b705cfSriastradh		adaptors[num_adaptors++] = overlayAdaptor;
21703b705cfSriastradh
21803b705cfSriastradh	if (texturedAdaptor)
21903b705cfSriastradh		adaptors[num_adaptors++] = texturedAdaptor;
22003b705cfSriastradh
22103b705cfSriastradh	if (overlayAdaptor && !intel->XvPreferOverlay)
22203b705cfSriastradh		adaptors[num_adaptors++] = overlayAdaptor;
22303b705cfSriastradh
22403b705cfSriastradh	if (num_adaptors) {
22503b705cfSriastradh		xf86XVScreenInit(screen, adaptors, num_adaptors);
22603b705cfSriastradh	} else {
22703b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
22803b705cfSriastradh			   "Disabling Xv because no adaptors could be initialized.\n");
22903b705cfSriastradh		intel->XvEnabled = FALSE;
23003b705cfSriastradh	}
23103b705cfSriastradh
23203b705cfSriastradh#ifdef INTEL_XVMC
23313496ba1Ssnj        if (texturedAdaptor)
23413496ba1Ssnj                intel_xvmc_adaptor_init(screen);
23503b705cfSriastradh#endif
23603b705cfSriastradh
23713496ba1Ssnj	free(adaptors);
23803b705cfSriastradh}
23903b705cfSriastradh
24013496ba1Ssnjvoid intel_free_video_buffers(intel_adaptor_private *adaptor_priv)
24103b705cfSriastradh{
24203b705cfSriastradh	int i;
24303b705cfSriastradh
24403b705cfSriastradh	for (i = 0; i < 2; i++) {
24503b705cfSriastradh		if (adaptor_priv->old_buf[i]) {
24603b705cfSriastradh			drm_intel_bo_disable_reuse(adaptor_priv->old_buf[i]);
24703b705cfSriastradh			drm_intel_bo_unreference(adaptor_priv->old_buf[i]);
24803b705cfSriastradh			adaptor_priv->old_buf[i] = NULL;
24903b705cfSriastradh		}
25003b705cfSriastradh	}
25103b705cfSriastradh
25203b705cfSriastradh	if (adaptor_priv->buf) {
25303b705cfSriastradh		drm_intel_bo_unreference(adaptor_priv->buf);
25403b705cfSriastradh		adaptor_priv->buf = NULL;
25503b705cfSriastradh	}
25603b705cfSriastradh}
25703b705cfSriastradh
25813496ba1Ssnjint
25913496ba1Ssnjintel_video_get_port_attribute(ScrnInfoPtr scrn,
26013496ba1Ssnj                               Atom attribute, INT32 * value, pointer data)
26103b705cfSriastradh{
26203b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
26303b705cfSriastradh	intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data;
26403b705cfSriastradh
26513496ba1Ssnj	if (attribute == intel_xv_Brightness) {
26603b705cfSriastradh		*value = adaptor_priv->brightness;
26713496ba1Ssnj	} else if (attribute == intel_xv_Contrast) {
26803b705cfSriastradh		*value = adaptor_priv->contrast;
26913496ba1Ssnj	} else if (attribute == intel_xv_Saturation) {
27003b705cfSriastradh		*value = adaptor_priv->saturation;
27113496ba1Ssnj	} else if (attribute == intel_xv_Pipe) {
27203b705cfSriastradh		int c;
27303b705cfSriastradh		xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
27403b705cfSriastradh		for (c = 0; c < xf86_config->num_crtc; c++)
27503b705cfSriastradh			if (xf86_config->crtc[c] == adaptor_priv->desired_crtc)
27603b705cfSriastradh				break;
27703b705cfSriastradh		if (c == xf86_config->num_crtc)
27803b705cfSriastradh			c = -1;
27903b705cfSriastradh		*value = c;
28013496ba1Ssnj	} else if (attribute == intel_xv_Gamma0 && (INTEL_INFO(intel)->gen >= 030)) {
28103b705cfSriastradh		*value = adaptor_priv->gamma0;
28213496ba1Ssnj	} else if (attribute == intel_xv_Gamma1 && (INTEL_INFO(intel)->gen >= 030)) {
28303b705cfSriastradh		*value = adaptor_priv->gamma1;
28413496ba1Ssnj	} else if (attribute == intel_xv_Gamma2 && (INTEL_INFO(intel)->gen >= 030)) {
28503b705cfSriastradh		*value = adaptor_priv->gamma2;
28613496ba1Ssnj	} else if (attribute == intel_xv_Gamma3 && (INTEL_INFO(intel)->gen >= 030)) {
28703b705cfSriastradh		*value = adaptor_priv->gamma3;
28813496ba1Ssnj	} else if (attribute == intel_xv_Gamma4 && (INTEL_INFO(intel)->gen >= 030)) {
28903b705cfSriastradh		*value = adaptor_priv->gamma4;
29013496ba1Ssnj	} else if (attribute == intel_xv_Gamma5 && (INTEL_INFO(intel)->gen >= 030)) {
29103b705cfSriastradh		*value = adaptor_priv->gamma5;
29213496ba1Ssnj	} else if (attribute == intel_xv_ColorKey) {
29303b705cfSriastradh		*value = adaptor_priv->colorKey;
29413496ba1Ssnj	} else if (attribute == intel_xv_SyncToVblank) {
29503b705cfSriastradh		*value = adaptor_priv->SyncToVblank;
29603b705cfSriastradh	} else
29703b705cfSriastradh		return BadMatch;
29803b705cfSriastradh
29903b705cfSriastradh	return Success;
30003b705cfSriastradh}
30103b705cfSriastradh
30213496ba1Ssnjvoid
30313496ba1Ssnjintel_video_query_best_size(ScrnInfoPtr scrn,
30403b705cfSriastradh		  Bool motion,
30503b705cfSriastradh		  short vid_w, short vid_h,
30603b705cfSriastradh		  short drw_w, short drw_h,
30703b705cfSriastradh		  unsigned int *p_w, unsigned int *p_h, pointer data)
30803b705cfSriastradh{
30903b705cfSriastradh	if (vid_w > (drw_w << 1))
31003b705cfSriastradh		drw_w = vid_w >> 1;
31103b705cfSriastradh	if (vid_h > (drw_h << 1))
31203b705cfSriastradh		drw_h = vid_h >> 1;
31303b705cfSriastradh
31403b705cfSriastradh	*p_w = drw_w;
31503b705cfSriastradh	*p_h = drw_h;
31603b705cfSriastradh}
31703b705cfSriastradh
31803b705cfSriastradhstatic Bool
31913496ba1Ssnjintel_video_copy_packed_data(intel_adaptor_private *adaptor_priv,
32013496ba1Ssnj                                 unsigned char *buf,
32113496ba1Ssnj                                 int srcPitch, int dstPitch, int top, int left, int h, int w)
32203b705cfSriastradh{
32303b705cfSriastradh	unsigned char *src, *dst, *dst_base;
32403b705cfSriastradh	int i, j;
32503b705cfSriastradh	unsigned char *s;
32603b705cfSriastradh
32703b705cfSriastradh#if 0
32813496ba1Ssnj	ErrorF("intel_video_copy_packed_data: (%d,%d) (%d,%d)\n"
32903b705cfSriastradh	       "srcPitch: %d, dstPitch: %d\n", top, left, h, w,
33003b705cfSriastradh	       srcPitch, dstPitch);
33103b705cfSriastradh#endif
33203b705cfSriastradh
33303b705cfSriastradh	src = buf + (top * srcPitch) + (left << 1);
33403b705cfSriastradh
33503b705cfSriastradh	if (drm_intel_gem_bo_map_gtt(adaptor_priv->buf))
33603b705cfSriastradh		return FALSE;
33703b705cfSriastradh
33803b705cfSriastradh	dst_base = adaptor_priv->buf->virtual;
33903b705cfSriastradh
34003b705cfSriastradh	dst = dst_base + adaptor_priv->YBufOffset;
34103b705cfSriastradh
34203b705cfSriastradh	switch (adaptor_priv->rotation) {
34303b705cfSriastradh	case RR_Rotate_0:
34403b705cfSriastradh		w <<= 1;
34503b705cfSriastradh		for (i = 0; i < h; i++) {
34603b705cfSriastradh			memcpy(dst, src, w);
34703b705cfSriastradh			src += srcPitch;
34803b705cfSriastradh			dst += dstPitch;
34903b705cfSriastradh		}
35003b705cfSriastradh		break;
35103b705cfSriastradh	case RR_Rotate_90:
35203b705cfSriastradh		h <<= 1;
35303b705cfSriastradh		for (i = 0; i < h; i += 2) {
35403b705cfSriastradh			s = src;
35503b705cfSriastradh			for (j = 0; j < w; j++) {
35603b705cfSriastradh				/* Copy Y */
35703b705cfSriastradh				dst[(i + 0) + ((w - j - 1) * dstPitch)] = *s++;
35803b705cfSriastradh				(void)*s++;
35903b705cfSriastradh			}
36003b705cfSriastradh			src += srcPitch;
36103b705cfSriastradh		}
36203b705cfSriastradh		h >>= 1;
36303b705cfSriastradh		src = buf + (top * srcPitch) + (left << 1);
36403b705cfSriastradh		for (i = 0; i < h; i += 2) {
36503b705cfSriastradh			for (j = 0; j < w; j += 2) {
36603b705cfSriastradh				/* Copy U */
36703b705cfSriastradh				dst[((i * 2) + 1) + ((w - j - 1) * dstPitch)] =
36803b705cfSriastradh				    src[(j * 2) + 1 + (i * srcPitch)];
36903b705cfSriastradh				dst[((i * 2) + 1) + ((w - j - 2) * dstPitch)] =
37003b705cfSriastradh				    src[(j * 2) + 1 + ((i + 1) * srcPitch)];
37103b705cfSriastradh				/* Copy V */
37203b705cfSriastradh				dst[((i * 2) + 3) + ((w - j - 1) * dstPitch)] =
37303b705cfSriastradh				    src[(j * 2) + 3 + (i * srcPitch)];
37403b705cfSriastradh				dst[((i * 2) + 3) + ((w - j - 2) * dstPitch)] =
37503b705cfSriastradh				    src[(j * 2) + 3 + ((i + 1) * srcPitch)];
37603b705cfSriastradh			}
37703b705cfSriastradh		}
37803b705cfSriastradh		break;
37903b705cfSriastradh	case RR_Rotate_180:
38003b705cfSriastradh		w <<= 1;
38103b705cfSriastradh		for (i = 0; i < h; i++) {
38203b705cfSriastradh			s = src;
38303b705cfSriastradh			for (j = 0; j < w; j += 4) {
38403b705cfSriastradh				dst[(w - j - 4) + ((h - i - 1) * dstPitch)] =
38503b705cfSriastradh				    *s++;
38603b705cfSriastradh				dst[(w - j - 3) + ((h - i - 1) * dstPitch)] =
38703b705cfSriastradh				    *s++;
38803b705cfSriastradh				dst[(w - j - 2) + ((h - i - 1) * dstPitch)] =
38903b705cfSriastradh				    *s++;
39003b705cfSriastradh				dst[(w - j - 1) + ((h - i - 1) * dstPitch)] =
39103b705cfSriastradh				    *s++;
39203b705cfSriastradh			}
39303b705cfSriastradh			src += srcPitch;
39403b705cfSriastradh		}
39503b705cfSriastradh		break;
39603b705cfSriastradh	case RR_Rotate_270:
39703b705cfSriastradh		h <<= 1;
39803b705cfSriastradh		for (i = 0; i < h; i += 2) {
39903b705cfSriastradh			s = src;
40003b705cfSriastradh			for (j = 0; j < w; j++) {
40103b705cfSriastradh				/* Copy Y */
40203b705cfSriastradh				dst[(h - i - 2) + (j * dstPitch)] = *s++;
40303b705cfSriastradh				(void)*s++;
40403b705cfSriastradh			}
40503b705cfSriastradh			src += srcPitch;
40603b705cfSriastradh		}
40703b705cfSriastradh		h >>= 1;
40803b705cfSriastradh		src = buf + (top * srcPitch) + (left << 1);
40903b705cfSriastradh		for (i = 0; i < h; i += 2) {
41003b705cfSriastradh			for (j = 0; j < w; j += 2) {
41103b705cfSriastradh				/* Copy U */
41203b705cfSriastradh				dst[(((h - i) * 2) - 3) + (j * dstPitch)] =
41303b705cfSriastradh				    src[(j * 2) + 1 + (i * srcPitch)];
41403b705cfSriastradh				dst[(((h - i) * 2) - 3) +
41503b705cfSriastradh				    ((j + 1) * dstPitch)] =
41603b705cfSriastradh				    src[(j * 2) + 1 + ((i + 1) * srcPitch)];
41703b705cfSriastradh				/* Copy V */
41803b705cfSriastradh				dst[(((h - i) * 2) - 1) + (j * dstPitch)] =
41903b705cfSriastradh				    src[(j * 2) + 3 + (i * srcPitch)];
42003b705cfSriastradh				dst[(((h - i) * 2) - 1) +
42103b705cfSriastradh				    ((j + 1) * dstPitch)] =
42203b705cfSriastradh				    src[(j * 2) + 3 + ((i + 1) * srcPitch)];
42303b705cfSriastradh			}
42403b705cfSriastradh		}
42503b705cfSriastradh		break;
42603b705cfSriastradh	}
42703b705cfSriastradh
42803b705cfSriastradh	drm_intel_gem_bo_unmap_gtt(adaptor_priv->buf);
42903b705cfSriastradh	return TRUE;
43003b705cfSriastradh}
43103b705cfSriastradh
43203b705cfSriastradhstatic void intel_memcpy_plane(unsigned char *dst, unsigned char *src,
43303b705cfSriastradh			       int height, int width,
43403b705cfSriastradh			       int dstPitch, int srcPitch, Rotation rotation)
43503b705cfSriastradh{
43603b705cfSriastradh	int i, j = 0;
43703b705cfSriastradh	unsigned char *s;
43803b705cfSriastradh
43903b705cfSriastradh	switch (rotation) {
44003b705cfSriastradh	case RR_Rotate_0:
44103b705cfSriastradh		/* optimise for the case of no clipping */
44203b705cfSriastradh		if (srcPitch == dstPitch && srcPitch == width)
44303b705cfSriastradh			memcpy(dst, src, srcPitch * height);
44403b705cfSriastradh		else
44503b705cfSriastradh			for (i = 0; i < height; i++) {
44603b705cfSriastradh				memcpy(dst, src, width);
44703b705cfSriastradh				src += srcPitch;
44803b705cfSriastradh				dst += dstPitch;
44903b705cfSriastradh			}
45003b705cfSriastradh		break;
45103b705cfSriastradh	case RR_Rotate_90:
45203b705cfSriastradh		for (i = 0; i < height; i++) {
45303b705cfSriastradh			s = src;
45403b705cfSriastradh			for (j = 0; j < width; j++) {
45503b705cfSriastradh				dst[(i) + ((width - j - 1) * dstPitch)] = *s++;
45603b705cfSriastradh			}
45703b705cfSriastradh			src += srcPitch;
45803b705cfSriastradh		}
45903b705cfSriastradh		break;
46003b705cfSriastradh	case RR_Rotate_180:
46103b705cfSriastradh		for (i = 0; i < height; i++) {
46203b705cfSriastradh			s = src;
46303b705cfSriastradh			for (j = 0; j < width; j++) {
46403b705cfSriastradh				dst[(width - j - 1) +
46503b705cfSriastradh				    ((height - i - 1) * dstPitch)] = *s++;
46603b705cfSriastradh			}
46703b705cfSriastradh			src += srcPitch;
46803b705cfSriastradh		}
46903b705cfSriastradh		break;
47003b705cfSriastradh	case RR_Rotate_270:
47103b705cfSriastradh		for (i = 0; i < height; i++) {
47203b705cfSriastradh			s = src;
47303b705cfSriastradh			for (j = 0; j < width; j++) {
47403b705cfSriastradh				dst[(height - i - 1) + (j * dstPitch)] = *s++;
47503b705cfSriastradh			}
47603b705cfSriastradh			src += srcPitch;
47703b705cfSriastradh		}
47803b705cfSriastradh		break;
47903b705cfSriastradh	}
48003b705cfSriastradh}
48103b705cfSriastradh
48203b705cfSriastradhstatic Bool
48313496ba1Ssnjintel_video_copy_planar_data(intel_adaptor_private *adaptor_priv,
48403b705cfSriastradh		   unsigned char *buf, int srcPitch, int srcPitch2,
48503b705cfSriastradh		   int dstPitch, int dstPitch2,
48603b705cfSriastradh		   int srcH, int top, int left,
48703b705cfSriastradh		   int h, int w, int id)
48803b705cfSriastradh{
48903b705cfSriastradh	unsigned char *src1, *src2, *src3, *dst_base, *dst1, *dst2, *dst3;
49003b705cfSriastradh
49103b705cfSriastradh#if 0
49213496ba1Ssnj	ErrorF("intel_video_copy_planar_data: srcPitch %d, srcPitch %d, dstPitch %d\n"
49303b705cfSriastradh	       "nlines %d, npixels %d, top %d, left %d\n",
49403b705cfSriastradh	       srcPitch, srcPitch2, dstPitch, h, w, top, left);
49503b705cfSriastradh#endif
49603b705cfSriastradh
49703b705cfSriastradh	/* Copy Y data */
49803b705cfSriastradh	src1 = buf + (top * srcPitch) + left;
49903b705cfSriastradh#if 0
50003b705cfSriastradh	ErrorF("src1 is %p, offset is %ld\n", src1,
50103b705cfSriastradh	       (unsigned long)src1 - (unsigned long)buf);
50203b705cfSriastradh#endif
50303b705cfSriastradh
50403b705cfSriastradh	if (drm_intel_gem_bo_map_gtt(adaptor_priv->buf))
50503b705cfSriastradh		return FALSE;
50603b705cfSriastradh
50703b705cfSriastradh	dst_base = adaptor_priv->buf->virtual;
50803b705cfSriastradh
50903b705cfSriastradh	dst1 = dst_base + adaptor_priv->YBufOffset;
51003b705cfSriastradh
51103b705cfSriastradh	intel_memcpy_plane(dst1, src1, h, w, dstPitch2, srcPitch,
51203b705cfSriastradh			  adaptor_priv->rotation);
51303b705cfSriastradh
51403b705cfSriastradh	/* Copy V data for YV12, or U data for I420 */
51503b705cfSriastradh	src2 = buf +		/* start of YUV data */
51603b705cfSriastradh	    (srcH * srcPitch) +	/* move over Luma plane */
51703b705cfSriastradh	    ((top >> 1) * srcPitch2) +	/* move down from by top lines */
51803b705cfSriastradh	    (left >> 1);	/* move left by left pixels */
51903b705cfSriastradh
52003b705cfSriastradh#if 0
52103b705cfSriastradh	ErrorF("src2 is %p, offset is %ld\n", src2,
52203b705cfSriastradh	       (unsigned long)src2 - (unsigned long)buf);
52303b705cfSriastradh#endif
52403b705cfSriastradh	if (id == FOURCC_I420)
52503b705cfSriastradh		dst2 = dst_base + adaptor_priv->UBufOffset;
52603b705cfSriastradh	else
52703b705cfSriastradh		dst2 = dst_base + adaptor_priv->VBufOffset;
52803b705cfSriastradh
52903b705cfSriastradh	intel_memcpy_plane(dst2, src2, h / 2, w / 2,
53003b705cfSriastradh			  dstPitch, srcPitch2, adaptor_priv->rotation);
53103b705cfSriastradh
53203b705cfSriastradh	/* Copy U data for YV12, or V data for I420 */
53303b705cfSriastradh	src3 = buf +		/* start of YUV data */
53403b705cfSriastradh	    (srcH * srcPitch) +	/* move over Luma plane */
53503b705cfSriastradh	    ((srcH >> 1) * srcPitch2) +	/* move over Chroma plane */
53603b705cfSriastradh	    ((top >> 1) * srcPitch2) +	/* move down from by top lines */
53703b705cfSriastradh	    (left >> 1);	/* move left by left pixels */
53803b705cfSriastradh#if 0
53903b705cfSriastradh	ErrorF("src3 is %p, offset is %ld\n", src3,
54003b705cfSriastradh	       (unsigned long)src3 - (unsigned long)buf);
54103b705cfSriastradh#endif
54203b705cfSriastradh	if (id == FOURCC_I420)
54303b705cfSriastradh		dst3 = dst_base + adaptor_priv->VBufOffset;
54403b705cfSriastradh	else
54503b705cfSriastradh		dst3 = dst_base + adaptor_priv->UBufOffset;
54603b705cfSriastradh
54703b705cfSriastradh	intel_memcpy_plane(dst3, src3, h / 2, w / 2,
54803b705cfSriastradh			  dstPitch, srcPitch2, adaptor_priv->rotation);
54903b705cfSriastradh
55003b705cfSriastradh	drm_intel_gem_bo_unmap_gtt(adaptor_priv->buf);
55103b705cfSriastradh	return TRUE;
55203b705cfSriastradh}
55303b705cfSriastradh
55413496ba1Ssnjvoid
55503b705cfSriastradhintel_setup_dst_params(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv, short width,
55603b705cfSriastradh		       short height, int *dstPitch, int *dstPitch2, int *size,
55703b705cfSriastradh		       int id)
55803b705cfSriastradh{
55903b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
56003b705cfSriastradh	int pitchAlign;
56103b705cfSriastradh
56203b705cfSriastradh	/* Only needs to be DWORD-aligned for textured on i915, but overlay has
56303b705cfSriastradh	 * stricter requirements.
56403b705cfSriastradh	 */
56503b705cfSriastradh	if (adaptor_priv->textured) {
56603b705cfSriastradh		pitchAlign = 4;
56703b705cfSriastradh	} else {
56803b705cfSriastradh		if (INTEL_INFO(intel)->gen >= 040)
56903b705cfSriastradh			/* Actually the alignment is 64 bytes, too. But the
57003b705cfSriastradh			 * stride must be at least 512 bytes. Take the easy fix
57103b705cfSriastradh			 * and align on 512 bytes unconditionally. */
57203b705cfSriastradh			pitchAlign = 512;
57303b705cfSriastradh		else if (IS_I830(intel) || IS_845G(intel))
57403b705cfSriastradh			/* Harsh, errata on these chipsets limit the stride to be
57503b705cfSriastradh			 * a multiple of 256 bytes.
57603b705cfSriastradh			 */
57703b705cfSriastradh			pitchAlign = 256;
57803b705cfSriastradh		else
57903b705cfSriastradh			pitchAlign = 64;
58003b705cfSriastradh	}
58103b705cfSriastradh
58203b705cfSriastradh#if INTEL_XVMC
58303b705cfSriastradh	/* for i915 xvmc, hw requires 1kb aligned surfaces */
58403b705cfSriastradh	if ((id == FOURCC_XVMC) && IS_GEN3(intel))
58503b705cfSriastradh		pitchAlign = 1024;
58603b705cfSriastradh#endif
58703b705cfSriastradh
58803b705cfSriastradh	/* Determine the desired destination pitch (representing the chroma's pitch,
58903b705cfSriastradh	 * in the planar case.
59003b705cfSriastradh	 */
59103b705cfSriastradh	if (is_planar_fourcc(id)) {
59203b705cfSriastradh		if (adaptor_priv->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
59303b705cfSriastradh			*dstPitch = ALIGN((height / 2), pitchAlign);
59403b705cfSriastradh			*dstPitch2 = ALIGN(height, pitchAlign);
59503b705cfSriastradh			*size = *dstPitch * width * 3;
59603b705cfSriastradh		} else {
59703b705cfSriastradh			*dstPitch = ALIGN((width / 2), pitchAlign);
59803b705cfSriastradh			*dstPitch2 = ALIGN(width, pitchAlign);
59903b705cfSriastradh			*size = *dstPitch * height * 3;
60003b705cfSriastradh		}
60103b705cfSriastradh	} else {
60203b705cfSriastradh		if (adaptor_priv->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
60303b705cfSriastradh			*dstPitch = ALIGN((height << 1), pitchAlign);
60403b705cfSriastradh			*size = *dstPitch * width;
60503b705cfSriastradh		} else {
60603b705cfSriastradh			*dstPitch = ALIGN((width << 1), pitchAlign);
60703b705cfSriastradh			*size = *dstPitch * height;
60803b705cfSriastradh		}
60903b705cfSriastradh		*dstPitch2 = 0;
61003b705cfSriastradh	}
61103b705cfSriastradh#if 0
61203b705cfSriastradh	ErrorF("srcPitch: %d, dstPitch: %d, size: %d\n", srcPitch, *dstPitch,
61303b705cfSriastradh	       size);
61403b705cfSriastradh#endif
61503b705cfSriastradh
61603b705cfSriastradh	adaptor_priv->YBufOffset = 0;
61703b705cfSriastradh
61803b705cfSriastradh	if (adaptor_priv->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
61903b705cfSriastradh		adaptor_priv->UBufOffset =
62003b705cfSriastradh		    adaptor_priv->YBufOffset + (*dstPitch2 * width);
62103b705cfSriastradh		adaptor_priv->VBufOffset =
62203b705cfSriastradh		    adaptor_priv->UBufOffset + (*dstPitch * width / 2);
62303b705cfSriastradh	} else {
62403b705cfSriastradh		adaptor_priv->UBufOffset =
62503b705cfSriastradh		    adaptor_priv->YBufOffset + (*dstPitch2 * height);
62603b705cfSriastradh		adaptor_priv->VBufOffset =
62703b705cfSriastradh		    adaptor_priv->UBufOffset + (*dstPitch * height / 2);
62803b705cfSriastradh	}
62903b705cfSriastradh}
63003b705cfSriastradh
63103b705cfSriastradhstatic Bool
63213496ba1Ssnjintel_setup_video_buffer(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv,
63313496ba1Ssnj			 int alloc_size, int id, unsigned char *buf)
63413496ba1Ssnj{
63513496ba1Ssnj	intel_screen_private *intel = intel_get_screen_private(scrn);
63613496ba1Ssnj
63713496ba1Ssnj	/* Free the current buffer if we're going to have to reallocate */
63813496ba1Ssnj	if (adaptor_priv->buf && adaptor_priv->buf->size < alloc_size)
63913496ba1Ssnj		intel_free_video_buffers(adaptor_priv);
64013496ba1Ssnj
64113496ba1Ssnj	if (adaptor_priv->buf == NULL) {
64213496ba1Ssnj		adaptor_priv->buf = drm_intel_bo_alloc(intel->bufmgr, "xv buffer",
64313496ba1Ssnj						       alloc_size, 4096);
64413496ba1Ssnj		if (adaptor_priv->buf == NULL)
64513496ba1Ssnj			return FALSE;
64613496ba1Ssnj
64713496ba1Ssnj		adaptor_priv->reusable = TRUE;
64813496ba1Ssnj	}
64913496ba1Ssnj
65013496ba1Ssnj	return TRUE;
65113496ba1Ssnj}
65213496ba1Ssnj
65313496ba1SsnjBool
65413496ba1Ssnjintel_video_copy_data(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv,
65513496ba1Ssnj                      short width, short height, int *dstPitch, int *dstPitch2,
65613496ba1Ssnj                      int top, int left, int npixels, int nlines,
65713496ba1Ssnj                      int id, unsigned char *buf)
65803b705cfSriastradh{
65903b705cfSriastradh	int srcPitch = 0, srcPitch2 = 0;
66003b705cfSriastradh	int size;
66103b705cfSriastradh
66203b705cfSriastradh	if (is_planar_fourcc(id)) {
66303b705cfSriastradh		srcPitch = ALIGN(width, 0x4);
66403b705cfSriastradh		srcPitch2 = ALIGN((width >> 1), 0x4);
66503b705cfSriastradh	} else {
66603b705cfSriastradh		srcPitch = width << 1;
66703b705cfSriastradh	}
66803b705cfSriastradh
66903b705cfSriastradh	intel_setup_dst_params(scrn, adaptor_priv, width, height, dstPitch,
67003b705cfSriastradh				dstPitch2, &size, id);
67103b705cfSriastradh
67203b705cfSriastradh	if (!intel_setup_video_buffer(scrn, adaptor_priv, size, id, buf))
67303b705cfSriastradh		return FALSE;
67403b705cfSriastradh
67503b705cfSriastradh	/* copy data */
67603b705cfSriastradh	if (is_planar_fourcc(id)) {
67713496ba1Ssnj		return intel_video_copy_planar_data(adaptor_priv, buf, srcPitch, srcPitch2,
67803b705cfSriastradh					  *dstPitch, *dstPitch2,
67903b705cfSriastradh					  height, top, left, nlines,
68003b705cfSriastradh					  npixels, id);
68103b705cfSriastradh	} else {
68213496ba1Ssnj		return intel_video_copy_packed_data(adaptor_priv, buf, srcPitch, *dstPitch, top, left,
68303b705cfSriastradh					  nlines, npixels);
68403b705cfSriastradh	}
68503b705cfSriastradh}
68603b705cfSriastradh
68713496ba1Ssnjint is_planar_fourcc(int id)
68803b705cfSriastradh{
68913496ba1Ssnj	switch (id) {
69013496ba1Ssnj	case FOURCC_YV12:
69113496ba1Ssnj	case FOURCC_I420:
69213496ba1Ssnj#ifdef INTEL_XVMC
69313496ba1Ssnj	case FOURCC_XVMC:
69403b705cfSriastradh#endif
69513496ba1Ssnj		return 1;
69613496ba1Ssnj	case FOURCC_UYVY:
69713496ba1Ssnj	case FOURCC_YUY2:
69813496ba1Ssnj		return 0;
69913496ba1Ssnj	default:
70013496ba1Ssnj		ErrorF("Unknown format 0x%x\n", id);
70113496ba1Ssnj		return 0;
70203b705cfSriastradh	}
70303b705cfSriastradh}
70403b705cfSriastradh
70513496ba1SsnjBool
70613496ba1Ssnjintel_clip_video_helper(ScrnInfoPtr scrn,
70713496ba1Ssnj			intel_adaptor_private *adaptor_priv,
70813496ba1Ssnj			xf86CrtcPtr * crtc_ret,
70913496ba1Ssnj			BoxPtr dst,
71013496ba1Ssnj			short src_x, short src_y,
71113496ba1Ssnj			short drw_x, short drw_y,
71213496ba1Ssnj			short src_w, short src_h,
71313496ba1Ssnj			short drw_w, short drw_h,
71413496ba1Ssnj			int id,
71513496ba1Ssnj			int *top, int* left, int* npixels, int *nlines,
71613496ba1Ssnj			RegionPtr reg, INT32 width, INT32 height)
71703b705cfSriastradh{
71813496ba1Ssnj	Bool ret;
71913496ba1Ssnj	RegionRec crtc_region_local;
72013496ba1Ssnj	RegionPtr crtc_region = reg;
72113496ba1Ssnj	BoxRec crtc_box;
72213496ba1Ssnj	INT32 x1, x2, y1, y2;
72303b705cfSriastradh	xf86CrtcPtr crtc;
72403b705cfSriastradh
72513496ba1Ssnj	x1 = src_x;
72613496ba1Ssnj	x2 = src_x + src_w;
72713496ba1Ssnj	y1 = src_y;
72813496ba1Ssnj	y2 = src_y + src_h;
72903b705cfSriastradh
73013496ba1Ssnj	dst->x1 = drw_x;
73113496ba1Ssnj	dst->x2 = drw_x + drw_w;
73213496ba1Ssnj	dst->y1 = drw_y;
73313496ba1Ssnj	dst->y2 = drw_y + drw_h;
73413496ba1Ssnj
73513496ba1Ssnj	/*
73613496ba1Ssnj	 * For overlay video, compute the relevant CRTC and
73713496ba1Ssnj	 * clip video to that
73813496ba1Ssnj	 */
73913496ba1Ssnj	crtc = intel_covering_crtc(scrn, dst, adaptor_priv->desired_crtc,
74013496ba1Ssnj				   &crtc_box);
74103b705cfSriastradh
74213496ba1Ssnj	/* For textured video, we don't actually want to clip at all. */
74313496ba1Ssnj	if (crtc && !adaptor_priv->textured) {
74413496ba1Ssnj		REGION_INIT(screen, &crtc_region_local, &crtc_box, 1);
74513496ba1Ssnj		crtc_region = &crtc_region_local;
74613496ba1Ssnj		REGION_INTERSECT(screen, crtc_region, crtc_region,
74713496ba1Ssnj				 reg);
74803b705cfSriastradh	}
74913496ba1Ssnj	*crtc_ret = crtc;
75003b705cfSriastradh
75113496ba1Ssnj	ret = xf86XVClipVideoHelper(dst, &x1, &x2, &y1, &y2,
75213496ba1Ssnj				    crtc_region, width, height);
75313496ba1Ssnj	if (crtc_region != reg)
75413496ba1Ssnj		REGION_UNINIT(screen, &crtc_region_local);
75503b705cfSriastradh
75613496ba1Ssnj	*top = y1 >> 16;
75713496ba1Ssnj	*left = (x1 >> 16) & ~1;
75813496ba1Ssnj	*npixels = ALIGN(((x2 + 0xffff) >> 16), 2) - *left;
75913496ba1Ssnj	if (is_planar_fourcc(id)) {
76013496ba1Ssnj		*top &= ~1;
76113496ba1Ssnj		*nlines = ALIGN(((y2 + 0xffff) >> 16), 2) - *top;
76213496ba1Ssnj	} else
76313496ba1Ssnj		*nlines = ((y2 + 0xffff) >> 16) - *top;
76413496ba1Ssnj
76513496ba1Ssnj	return ret;
76603b705cfSriastradh}
76703b705cfSriastradh
76813496ba1Ssnjint
76913496ba1Ssnjintel_video_query_image_attributes(ScrnInfoPtr scrn,
77013496ba1Ssnj                                   int id,
77113496ba1Ssnj                                   unsigned short *w, unsigned short *h,
77213496ba1Ssnj                                   int *pitches, int *offsets)
77303b705cfSriastradh{
77403b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
77503b705cfSriastradh	int size, tmp;
77603b705cfSriastradh
77703b705cfSriastradh#if 0
77813496ba1Ssnj	ErrorF("intel_video_query_image_attributes: w is %d, h is %d\n", *w, *h);
77903b705cfSriastradh#endif
78003b705cfSriastradh
78103b705cfSriastradh	if (IS_845G(intel) || IS_I830(intel)) {
78203b705cfSriastradh		if (*w > IMAGE_MAX_WIDTH_LEGACY)
78303b705cfSriastradh			*w = IMAGE_MAX_WIDTH_LEGACY;
78403b705cfSriastradh		if (*h > IMAGE_MAX_HEIGHT_LEGACY)
78503b705cfSriastradh			*h = IMAGE_MAX_HEIGHT_LEGACY;
78603b705cfSriastradh	} else {
78703b705cfSriastradh		if (*w > IMAGE_MAX_WIDTH)
78803b705cfSriastradh			*w = IMAGE_MAX_WIDTH;
78903b705cfSriastradh		if (*h > IMAGE_MAX_HEIGHT)
79003b705cfSriastradh			*h = IMAGE_MAX_HEIGHT;
79103b705cfSriastradh	}
79203b705cfSriastradh
79303b705cfSriastradh	*w = (*w + 1) & ~1;
79403b705cfSriastradh	if (offsets)
79503b705cfSriastradh		offsets[0] = 0;
79603b705cfSriastradh
79703b705cfSriastradh	switch (id) {
79803b705cfSriastradh		/* IA44 is for XvMC only */
79903b705cfSriastradh	case FOURCC_IA44:
80003b705cfSriastradh	case FOURCC_AI44:
80103b705cfSriastradh		if (pitches)
80203b705cfSriastradh			pitches[0] = *w;
80303b705cfSriastradh		size = *w * *h;
80403b705cfSriastradh		break;
80503b705cfSriastradh	case FOURCC_YV12:
80603b705cfSriastradh	case FOURCC_I420:
80703b705cfSriastradh		*h = (*h + 1) & ~1;
80803b705cfSriastradh		size = (*w + 3) & ~3;
80903b705cfSriastradh		if (pitches)
81003b705cfSriastradh			pitches[0] = size;
81103b705cfSriastradh		size *= *h;
81203b705cfSriastradh		if (offsets)
81303b705cfSriastradh			offsets[1] = size;
81403b705cfSriastradh		tmp = ((*w >> 1) + 3) & ~3;
81503b705cfSriastradh		if (pitches)
81603b705cfSriastradh			pitches[1] = pitches[2] = tmp;
81703b705cfSriastradh		tmp *= (*h >> 1);
81803b705cfSriastradh		size += tmp;
81903b705cfSriastradh		if (offsets)
82003b705cfSriastradh			offsets[2] = size;
82103b705cfSriastradh		size += tmp;
82203b705cfSriastradh#if 0
82303b705cfSriastradh		if (pitches)
82403b705cfSriastradh			ErrorF("pitch 0 is %d, pitch 1 is %d, pitch 2 is %d\n",
82503b705cfSriastradh			       pitches[0], pitches[1], pitches[2]);
82603b705cfSriastradh		if (offsets)
82703b705cfSriastradh			ErrorF("offset 1 is %d, offset 2 is %d\n", offsets[1],
82803b705cfSriastradh			       offsets[2]);
82903b705cfSriastradh		if (offsets)
83003b705cfSriastradh			ErrorF("size is %d\n", size);
83103b705cfSriastradh#endif
83203b705cfSriastradh		break;
83303b705cfSriastradh#ifdef INTEL_XVMC
83403b705cfSriastradh	case FOURCC_XVMC:
83503b705cfSriastradh		*h = (*h + 1) & ~1;
83603b705cfSriastradh		size = sizeof(struct intel_xvmc_command);
83703b705cfSriastradh		if (pitches)
83803b705cfSriastradh			pitches[0] = size;
83903b705cfSriastradh		break;
84003b705cfSriastradh#endif
84103b705cfSriastradh	case FOURCC_UYVY:
84203b705cfSriastradh	case FOURCC_YUY2:
84303b705cfSriastradh	default:
84403b705cfSriastradh		size = *w << 1;
84503b705cfSriastradh		if (pitches)
84603b705cfSriastradh			pitches[0] = size;
84703b705cfSriastradh		size *= *h;
84803b705cfSriastradh		break;
84903b705cfSriastradh	}
85003b705cfSriastradh
85103b705cfSriastradh	return size;
85203b705cfSriastradh}
85303b705cfSriastradh
85413496ba1Ssnjvoid intel_video_stop_video(ScrnInfoPtr scrn, pointer data, Bool shutdown)
85513496ba1Ssnj{
85613496ba1Ssnj	intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data;
85713496ba1Ssnj
85813496ba1Ssnj	if (adaptor_priv->textured)
85913496ba1Ssnj		return;
86013496ba1Ssnj
86113496ba1Ssnj	REGION_EMPTY(scrn->pScreen, &adaptor_priv->clip);
86213496ba1Ssnj
86313496ba1Ssnj	if (shutdown) {
86413496ba1Ssnj		if (adaptor_priv->videoStatus & CLIENT_VIDEO_ON)
86513496ba1Ssnj			intel_video_overlay_off(intel_get_screen_private(scrn));
86613496ba1Ssnj
86713496ba1Ssnj		intel_free_video_buffers(adaptor_priv);
86813496ba1Ssnj		adaptor_priv->videoStatus = 0;
86913496ba1Ssnj	} else {
87013496ba1Ssnj		if (adaptor_priv->videoStatus & CLIENT_VIDEO_ON) {
87113496ba1Ssnj			adaptor_priv->videoStatus |= OFF_TIMER;
87213496ba1Ssnj			adaptor_priv->offTime = currentTime.milliseconds + OFF_DELAY;
87313496ba1Ssnj		}
87413496ba1Ssnj	}
87513496ba1Ssnj
87613496ba1Ssnj}
87713496ba1Ssnj
87803b705cfSriastradhvoid
87903b705cfSriastradhintel_video_block_handler(intel_screen_private *intel)
88003b705cfSriastradh{
88103b705cfSriastradh	intel_adaptor_private *adaptor_priv;
88203b705cfSriastradh
88303b705cfSriastradh	/* no overlay */
88403b705cfSriastradh	if (intel->adaptor == NULL)
88503b705cfSriastradh		return;
88603b705cfSriastradh
88703b705cfSriastradh	adaptor_priv = intel_get_adaptor_private(intel);
88803b705cfSriastradh	if (adaptor_priv->videoStatus & OFF_TIMER) {
88903b705cfSriastradh		Time now = currentTime.milliseconds;
89003b705cfSriastradh		if (adaptor_priv->offTime < now) {
89103b705cfSriastradh			/* Turn off the overlay */
89213496ba1Ssnj			intel_video_overlay_off(intel);
89303b705cfSriastradh			intel_free_video_buffers(adaptor_priv);
89403b705cfSriastradh			adaptor_priv->videoStatus = 0;
89503b705cfSriastradh		}
89603b705cfSriastradh	}
89703b705cfSriastradh}
898