intel_uxa.c revision fe8aea9e
103b705cfSriastradh/**************************************************************************
203b705cfSriastradh
303b705cfSriastradhCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
403b705cfSriastradhAll Rights Reserved.
503b705cfSriastradhCopyright (c) 2005 Jesse Barnes <jbarnes@virtuousgeek.org>
603b705cfSriastradh  Based on code from i830_xaa.c.
703b705cfSriastradh
803b705cfSriastradhPermission is hereby granted, free of charge, to any person obtaining a
903b705cfSriastradhcopy of this software and associated documentation files (the
1003b705cfSriastradh"Software"), to deal in the Software without restriction, including
1103b705cfSriastradhwithout limitation the rights to use, copy, modify, merge, publish,
1203b705cfSriastradhdistribute, sub license, and/or sell copies of the Software, and to
1303b705cfSriastradhpermit persons to whom the Software is furnished to do so, subject to
1403b705cfSriastradhthe following conditions:
1503b705cfSriastradh
1603b705cfSriastradhThe above copyright notice and this permission notice (including the
1703b705cfSriastradhnext paragraph) shall be included in all copies or substantial portions
1803b705cfSriastradhof the Software.
1903b705cfSriastradh
2003b705cfSriastradhTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2103b705cfSriastradhOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2203b705cfSriastradhMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2303b705cfSriastradhIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
2403b705cfSriastradhANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2503b705cfSriastradhTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2603b705cfSriastradhSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2703b705cfSriastradh
2803b705cfSriastradh**************************************************************************/
2903b705cfSriastradh
3003b705cfSriastradh#ifdef HAVE_CONFIG_H
3103b705cfSriastradh#include "config.h"
3203b705cfSriastradh#endif
3303b705cfSriastradh
3442542f5fSchristos#include "xorg-server.h"
3503b705cfSriastradh#include <xf86.h>
3603b705cfSriastradh#include <xf86drm.h>
3703b705cfSriastradh#include <xaarop.h>
3803b705cfSriastradh#include <string.h>
3903b705cfSriastradh#include <errno.h>
4003b705cfSriastradh#include <unistd.h>
4103b705cfSriastradh
4203b705cfSriastradh#include "intel.h"
4313496ba1Ssnj#include "intel_uxa.h"
4403b705cfSriastradh
4503b705cfSriastradh#include "i830_reg.h"
4603b705cfSriastradh#include "i915_drm.h"
4703b705cfSriastradh#include "brw_defines.h"
4803b705cfSriastradh
4903b705cfSriastradhstatic const int I830CopyROP[16] = {
5003b705cfSriastradh	ROP_0,			/* GXclear */
5103b705cfSriastradh	ROP_DSa,		/* GXand */
5203b705cfSriastradh	ROP_SDna,		/* GXandReverse */
5303b705cfSriastradh	ROP_S,			/* GXcopy */
5403b705cfSriastradh	ROP_DSna,		/* GXandInverted */
5503b705cfSriastradh	ROP_D,			/* GXnoop */
5603b705cfSriastradh	ROP_DSx,		/* GXxor */
5703b705cfSriastradh	ROP_DSo,		/* GXor */
5803b705cfSriastradh	ROP_DSon,		/* GXnor */
5903b705cfSriastradh	ROP_DSxn,		/* GXequiv */
6003b705cfSriastradh	ROP_Dn,			/* GXinvert */
6103b705cfSriastradh	ROP_SDno,		/* GXorReverse */
6203b705cfSriastradh	ROP_Sn,			/* GXcopyInverted */
6303b705cfSriastradh	ROP_DSno,		/* GXorInverted */
6403b705cfSriastradh	ROP_DSan,		/* GXnand */
6503b705cfSriastradh	ROP_1			/* GXset */
6603b705cfSriastradh};
6703b705cfSriastradh
6803b705cfSriastradhstatic const int I830PatternROP[16] = {
6903b705cfSriastradh	ROP_0,
7003b705cfSriastradh	ROP_DPa,
7103b705cfSriastradh	ROP_PDna,
7203b705cfSriastradh	ROP_P,
7303b705cfSriastradh	ROP_DPna,
7403b705cfSriastradh	ROP_D,
7503b705cfSriastradh	ROP_DPx,
7603b705cfSriastradh	ROP_DPo,
7703b705cfSriastradh	ROP_DPon,
7803b705cfSriastradh	ROP_PDxn,
7903b705cfSriastradh	ROP_Dn,
8003b705cfSriastradh	ROP_PDno,
8103b705cfSriastradh	ROP_Pn,
8203b705cfSriastradh	ROP_DPno,
8303b705cfSriastradh	ROP_DPan,
8403b705cfSriastradh	ROP_1
8503b705cfSriastradh};
8603b705cfSriastradh
8703b705cfSriastradh#if HAS_DEVPRIVATEKEYREC
8803b705cfSriastradhDevPrivateKeyRec uxa_pixmap_index;
8903b705cfSriastradh#else
9003b705cfSriastradhint uxa_pixmap_index;
9103b705cfSriastradh#endif
9203b705cfSriastradh
9303b705cfSriastradhstatic void
9403b705cfSriastradhgen6_context_switch(intel_screen_private *intel,
9503b705cfSriastradh		    int new_mode)
9603b705cfSriastradh{
9703b705cfSriastradh	intel_batch_submit(intel->scrn);
9803b705cfSriastradh}
9903b705cfSriastradh
10003b705cfSriastradhstatic void
10103b705cfSriastradhgen5_context_switch(intel_screen_private *intel,
10203b705cfSriastradh		    int new_mode)
10303b705cfSriastradh{
10403b705cfSriastradh	/* Ironlake has a limitation that a 3D or Media command can't
10503b705cfSriastradh	 * be the first command after a BLT, unless it's
10603b705cfSriastradh	 * non-pipelined.  Instead of trying to track it and emit a
10703b705cfSriastradh	 * command at the right time, we just emit a dummy
10803b705cfSriastradh	 * non-pipelined 3D instruction after each blit.
10903b705cfSriastradh	 */
11003b705cfSriastradh
11103b705cfSriastradh	if (new_mode == I915_EXEC_BLT) {
11203b705cfSriastradh		OUT_BATCH(MI_FLUSH |
11303b705cfSriastradh			  MI_STATE_INSTRUCTION_CACHE_FLUSH |
11403b705cfSriastradh			  MI_INHIBIT_RENDER_CACHE_FLUSH);
11503b705cfSriastradh	} else {
11603b705cfSriastradh		OUT_BATCH(CMD_POLY_STIPPLE_OFFSET << 16);
11703b705cfSriastradh		OUT_BATCH(0);
11803b705cfSriastradh	}
11903b705cfSriastradh}
12003b705cfSriastradh
12103b705cfSriastradhstatic void
12203b705cfSriastradhgen4_context_switch(intel_screen_private *intel,
12303b705cfSriastradh		    int new_mode)
12403b705cfSriastradh{
12503b705cfSriastradh	if (new_mode == I915_EXEC_BLT) {
12603b705cfSriastradh		OUT_BATCH(MI_FLUSH |
12703b705cfSriastradh			  MI_STATE_INSTRUCTION_CACHE_FLUSH |
12803b705cfSriastradh			  MI_INHIBIT_RENDER_CACHE_FLUSH);
12903b705cfSriastradh	}
13003b705cfSriastradh}
13103b705cfSriastradh
13203b705cfSriastradhBool
13313496ba1Ssnjintel_uxa_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table,
13403b705cfSriastradh			 int num_bos)
13503b705cfSriastradh{
13603b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
13703b705cfSriastradh
13803b705cfSriastradh	if (intel->batch_bo == NULL) {
13913496ba1Ssnj		intel_uxa_debug_fallback(scrn, "VT inactive\n");
14003b705cfSriastradh		return FALSE;
14103b705cfSriastradh	}
14203b705cfSriastradh
14303b705cfSriastradh	bo_table[0] = intel->batch_bo;
14403b705cfSriastradh	if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) != 0) {
14503b705cfSriastradh		intel_batch_submit(scrn);
14603b705cfSriastradh		bo_table[0] = intel->batch_bo;
14703b705cfSriastradh		if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) !=
14803b705cfSriastradh		    0) {
14913496ba1Ssnj			intel_uxa_debug_fallback(scrn, "Couldn't get aperture "
15003b705cfSriastradh					    "space for BOs\n");
15103b705cfSriastradh			return FALSE;
15203b705cfSriastradh		}
15303b705cfSriastradh	}
15403b705cfSriastradh	return TRUE;
15503b705cfSriastradh}
15603b705cfSriastradh
15703b705cfSriastradhstatic Bool
15803b705cfSriastradhintel_uxa_check_solid(DrawablePtr drawable, int alu, Pixel planemask)
15903b705cfSriastradh{
16003b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(drawable->pScreen);
16103b705cfSriastradh
16203b705cfSriastradh	if (!UXA_PM_IS_SOLID(drawable, planemask)) {
16313496ba1Ssnj		intel_uxa_debug_fallback(scrn, "planemask is not solid\n");
16403b705cfSriastradh		return FALSE;
16503b705cfSriastradh	}
16603b705cfSriastradh
16703b705cfSriastradh	switch (drawable->bitsPerPixel) {
16803b705cfSriastradh	case 8:
16903b705cfSriastradh	case 16:
17003b705cfSriastradh	case 32:
17103b705cfSriastradh		break;
17203b705cfSriastradh	default:
17303b705cfSriastradh		return FALSE;
17403b705cfSriastradh	}
17503b705cfSriastradh
17603b705cfSriastradh	return TRUE;
17703b705cfSriastradh}
17803b705cfSriastradh
179fe8aea9eSmrgstatic Bool
180fe8aea9eSmrgintel_uxa_check_bo_tiling(intel_screen_private *intel,
181fe8aea9eSmrg			  PixmapPtr pixmap,
182fe8aea9eSmrg			  unsigned *tiling_out)
183fe8aea9eSmrg{
184fe8aea9eSmrg	struct intel_uxa_pixmap *priv;
185fe8aea9eSmrg
186fe8aea9eSmrg	priv = intel_uxa_get_pixmap_private(pixmap);
187fe8aea9eSmrg	if (!priv)
188fe8aea9eSmrg		return FALSE;
189fe8aea9eSmrg
190fe8aea9eSmrg	if (priv->tiling == I915_TILING_Y && INTEL_INFO(intel)->gen < 060)
191fe8aea9eSmrg		return FALSE;
192fe8aea9eSmrg
193fe8aea9eSmrg	*tiling_out = priv->tiling;
194fe8aea9eSmrg	return TRUE;
195fe8aea9eSmrg}
196fe8aea9eSmrg
19703b705cfSriastradh/**
19803b705cfSriastradh * Sets up hardware state for a series of solid fills.
19903b705cfSriastradh */
20003b705cfSriastradhstatic Bool
20103b705cfSriastradhintel_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg)
20203b705cfSriastradh{
20303b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
20403b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
20503b705cfSriastradh	drm_intel_bo *bo_table[] = {
20603b705cfSriastradh		NULL,		/* batch_bo */
20713496ba1Ssnj		intel_uxa_get_pixmap_bo(pixmap),
20803b705cfSriastradh	};
20903b705cfSriastradh
210fe8aea9eSmrg	if (!intel_uxa_check_bo_tiling(intel, pixmap, &intel->BR_tiling[0]))
211fe8aea9eSmrg		return FALSE;
212fe8aea9eSmrg
21313496ba1Ssnj	if (!intel_uxa_check_pitch_2d(pixmap))
21403b705cfSriastradh		return FALSE;
21503b705cfSriastradh
21613496ba1Ssnj	if (!intel_uxa_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
21703b705cfSriastradh		return FALSE;
21803b705cfSriastradh
21903b705cfSriastradh	intel->BR[13] = (I830PatternROP[alu] & 0xff) << 16;
22003b705cfSriastradh	switch (pixmap->drawable.bitsPerPixel) {
22103b705cfSriastradh	case 8:
22203b705cfSriastradh		break;
22303b705cfSriastradh	case 16:
22403b705cfSriastradh		/* RGB565 */
22503b705cfSriastradh		intel->BR[13] |= (1 << 24);
22603b705cfSriastradh		break;
22703b705cfSriastradh	case 32:
22803b705cfSriastradh		/* RGB8888 */
22903b705cfSriastradh		intel->BR[13] |= ((1 << 24) | (1 << 25));
23003b705cfSriastradh		break;
23103b705cfSriastradh	}
23203b705cfSriastradh	intel->BR[16] = fg;
23303b705cfSriastradh
23403b705cfSriastradh	return TRUE;
23503b705cfSriastradh}
23603b705cfSriastradh
23703b705cfSriastradhstatic void intel_uxa_solid(PixmapPtr pixmap, int x1, int y1, int x2, int y2)
23803b705cfSriastradh{
23903b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
24003b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
24103b705cfSriastradh	unsigned long pitch;
24203b705cfSriastradh	uint32_t cmd;
24303b705cfSriastradh
24403b705cfSriastradh	if (x1 < 0)
24503b705cfSriastradh		x1 = 0;
24603b705cfSriastradh	if (y1 < 0)
24703b705cfSriastradh		y1 = 0;
24803b705cfSriastradh	if (x2 > pixmap->drawable.width)
24903b705cfSriastradh		x2 = pixmap->drawable.width;
25003b705cfSriastradh	if (y2 > pixmap->drawable.height)
25103b705cfSriastradh		y2 = pixmap->drawable.height;
25203b705cfSriastradh
25303b705cfSriastradh	if (x2 <= x1 || y2 <= y1)
25403b705cfSriastradh		return;
25503b705cfSriastradh
25603b705cfSriastradh	pitch = intel_pixmap_pitch(pixmap);
25703b705cfSriastradh
25803b705cfSriastradh	{
25942542f5fSchristos		int len = INTEL_INFO(intel)->gen >= 0100 ? 7 : 6;
260fe8aea9eSmrg		BEGIN_BATCH_BLT_TILED(len);
26103b705cfSriastradh
26242542f5fSchristos		cmd = XY_COLOR_BLT_CMD | (len - 2);
26303b705cfSriastradh
26403b705cfSriastradh		if (pixmap->drawable.bitsPerPixel == 32)
26503b705cfSriastradh			cmd |=
26603b705cfSriastradh			    XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB;
26703b705cfSriastradh
26813496ba1Ssnj		if (INTEL_INFO(intel)->gen >= 040 && intel_uxa_pixmap_tiled(pixmap)) {
26903b705cfSriastradh			assert((pitch % 512) == 0);
27003b705cfSriastradh			pitch >>= 2;
27103b705cfSriastradh			cmd |= XY_COLOR_BLT_TILED;
27203b705cfSriastradh		}
27303b705cfSriastradh
27403b705cfSriastradh		OUT_BATCH(cmd);
27503b705cfSriastradh
27603b705cfSriastradh		OUT_BATCH(intel->BR[13] | pitch);
27703b705cfSriastradh		OUT_BATCH((y1 << 16) | (x1 & 0xffff));
27803b705cfSriastradh		OUT_BATCH((y2 << 16) | (x2 & 0xffff));
27903b705cfSriastradh		OUT_RELOC_PIXMAP_FENCED(pixmap, I915_GEM_DOMAIN_RENDER,
28003b705cfSriastradh					I915_GEM_DOMAIN_RENDER, 0);
28103b705cfSriastradh		OUT_BATCH(intel->BR[16]);
28203b705cfSriastradh		ADVANCE_BATCH();
28303b705cfSriastradh	}
28403b705cfSriastradh}
28503b705cfSriastradh
28603b705cfSriastradh/**
28703b705cfSriastradh * TODO:
28803b705cfSriastradh *   - support planemask using FULL_BLT_CMD?
28903b705cfSriastradh */
29003b705cfSriastradhstatic Bool
29103b705cfSriastradhintel_uxa_check_copy(PixmapPtr source, PixmapPtr dest,
29203b705cfSriastradh		    int alu, Pixel planemask)
29303b705cfSriastradh{
29403b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen);
29503b705cfSriastradh
29603b705cfSriastradh	if (!UXA_PM_IS_SOLID(&source->drawable, planemask)) {
29713496ba1Ssnj		intel_uxa_debug_fallback(scrn, "planemask is not solid");
29803b705cfSriastradh		return FALSE;
29903b705cfSriastradh	}
30003b705cfSriastradh
30103b705cfSriastradh	if (source->drawable.bitsPerPixel != dest->drawable.bitsPerPixel) {
30213496ba1Ssnj		intel_uxa_debug_fallback(scrn, "mixed bpp copies unsupported\n");
30303b705cfSriastradh		return FALSE;
30403b705cfSriastradh	}
30503b705cfSriastradh	switch (source->drawable.bitsPerPixel) {
30603b705cfSriastradh	case 8:
30703b705cfSriastradh	case 16:
30803b705cfSriastradh	case 32:
30903b705cfSriastradh		break;
31003b705cfSriastradh	default:
31103b705cfSriastradh		return FALSE;
31203b705cfSriastradh	}
31303b705cfSriastradh
31413496ba1Ssnj	if (!intel_uxa_check_pitch_2d(source))
31503b705cfSriastradh		return FALSE;
31613496ba1Ssnj	if (!intel_uxa_check_pitch_2d(dest))
31703b705cfSriastradh		return FALSE;
31803b705cfSriastradh
31903b705cfSriastradh	return TRUE;
32003b705cfSriastradh}
32103b705cfSriastradh
32203b705cfSriastradhstatic Bool
32303b705cfSriastradhintel_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir,
32403b705cfSriastradh		      int ydir, int alu, Pixel planemask)
32503b705cfSriastradh{
32603b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen);
32703b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
32803b705cfSriastradh	drm_intel_bo *bo_table[] = {
32903b705cfSriastradh		NULL,		/* batch_bo */
33013496ba1Ssnj		intel_uxa_get_pixmap_bo(source),
33113496ba1Ssnj		intel_uxa_get_pixmap_bo(dest),
33203b705cfSriastradh	};
33303b705cfSriastradh
334fe8aea9eSmrg	if (!intel_uxa_check_bo_tiling(intel, dest, &intel->BR_tiling[0]) ||
335fe8aea9eSmrg	    !intel_uxa_check_bo_tiling(intel, source, &intel->BR_tiling[1]))
336fe8aea9eSmrg		return FALSE;
337fe8aea9eSmrg
33813496ba1Ssnj	if (!intel_uxa_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
33903b705cfSriastradh		return FALSE;
34003b705cfSriastradh
34103b705cfSriastradh	intel->render_source = source;
34203b705cfSriastradh
34303b705cfSriastradh	intel->BR[13] = I830CopyROP[alu] << 16;
34403b705cfSriastradh	switch (source->drawable.bitsPerPixel) {
34503b705cfSriastradh	case 8:
34603b705cfSriastradh		break;
34703b705cfSriastradh	case 16:
34803b705cfSriastradh		intel->BR[13] |= (1 << 24);
34903b705cfSriastradh		break;
35003b705cfSriastradh	case 32:
35103b705cfSriastradh		intel->BR[13] |= ((1 << 25) | (1 << 24));
35203b705cfSriastradh		break;
35303b705cfSriastradh	}
35403b705cfSriastradh
35503b705cfSriastradh	return TRUE;
35603b705cfSriastradh}
35703b705cfSriastradh
35803b705cfSriastradhstatic void
35903b705cfSriastradhintel_uxa_copy(PixmapPtr dest, int src_x1, int src_y1, int dst_x1,
36003b705cfSriastradh	      int dst_y1, int w, int h)
36103b705cfSriastradh{
36203b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen);
36303b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
36403b705cfSriastradh	uint32_t cmd;
36503b705cfSriastradh	int dst_x2, dst_y2, src_x2, src_y2;
36603b705cfSriastradh	unsigned int dst_pitch, src_pitch;
36703b705cfSriastradh
36803b705cfSriastradh	dst_x2 = dst_x1 + w;
36903b705cfSriastradh	dst_y2 = dst_y1 + h;
37003b705cfSriastradh
37103b705cfSriastradh	/* XXX Fixup extents as a lamentable workaround for missing
37203b705cfSriastradh	 * source clipping in the upper layers.
37303b705cfSriastradh	 */
37403b705cfSriastradh	if (dst_x1 < 0)
37503b705cfSriastradh		src_x1 -= dst_x1, dst_x1 = 0;
37603b705cfSriastradh	if (dst_y1 < 0)
37703b705cfSriastradh		src_y1 -= dst_y1, dst_y1 = 0;
37803b705cfSriastradh	if (dst_x2 > dest->drawable.width)
37903b705cfSriastradh		dst_x2 = dest->drawable.width;
38003b705cfSriastradh	if (dst_y2 > dest->drawable.height)
38103b705cfSriastradh		dst_y2 = dest->drawable.height;
38203b705cfSriastradh
38303b705cfSriastradh	src_x2 = src_x1 + (dst_x2 - dst_x1);
38403b705cfSriastradh	src_y2 = src_y1 + (dst_y2 - dst_y1);
38503b705cfSriastradh
38603b705cfSriastradh	if (src_x1 < 0)
38703b705cfSriastradh		dst_x1 -= src_x1, src_x1 = 0;
38803b705cfSriastradh	if (src_y1 < 0)
38903b705cfSriastradh		dst_y1 -= src_y1, src_y1 = 0;
39003b705cfSriastradh	if (src_x2 > intel->render_source->drawable.width)
39103b705cfSriastradh		dst_x2 -= src_x2 - intel->render_source->drawable.width;
39203b705cfSriastradh	if (src_y2 > intel->render_source->drawable.height)
39303b705cfSriastradh		dst_y2 -= src_y2 - intel->render_source->drawable.height;
39403b705cfSriastradh
39503b705cfSriastradh	if (dst_x2 <= dst_x1 || dst_y2 <= dst_y1)
39603b705cfSriastradh		return;
39703b705cfSriastradh
39803b705cfSriastradh	dst_pitch = intel_pixmap_pitch(dest);
39903b705cfSriastradh	src_pitch = intel_pixmap_pitch(intel->render_source);
40003b705cfSriastradh
40103b705cfSriastradh	{
40242542f5fSchristos		int len = INTEL_INFO(intel)->gen >= 0100 ? 10 : 8;
403fe8aea9eSmrg		BEGIN_BATCH_BLT_TILED(len);
40403b705cfSriastradh
40542542f5fSchristos		cmd = XY_SRC_COPY_BLT_CMD | (len - 2);
40603b705cfSriastradh
40703b705cfSriastradh		if (dest->drawable.bitsPerPixel == 32)
40803b705cfSriastradh			cmd |=
40903b705cfSriastradh			    XY_SRC_COPY_BLT_WRITE_ALPHA |
41003b705cfSriastradh			    XY_SRC_COPY_BLT_WRITE_RGB;
41103b705cfSriastradh
41203b705cfSriastradh		if (INTEL_INFO(intel)->gen >= 040) {
41313496ba1Ssnj			if (intel_uxa_pixmap_tiled(dest)) {
41403b705cfSriastradh				assert((dst_pitch % 512) == 0);
41503b705cfSriastradh				dst_pitch >>= 2;
41603b705cfSriastradh				cmd |= XY_SRC_COPY_BLT_DST_TILED;
41703b705cfSriastradh			}
41803b705cfSriastradh
41913496ba1Ssnj			if (intel_uxa_pixmap_tiled(intel->render_source)) {
42003b705cfSriastradh				assert((src_pitch % 512) == 0);
42103b705cfSriastradh				src_pitch >>= 2;
42203b705cfSriastradh				cmd |= XY_SRC_COPY_BLT_SRC_TILED;
42303b705cfSriastradh			}
42403b705cfSriastradh		}
42503b705cfSriastradh
42603b705cfSriastradh		OUT_BATCH(cmd);
42703b705cfSriastradh
42803b705cfSriastradh		OUT_BATCH(intel->BR[13] | dst_pitch);
42903b705cfSriastradh		OUT_BATCH((dst_y1 << 16) | (dst_x1 & 0xffff));
43003b705cfSriastradh		OUT_BATCH((dst_y2 << 16) | (dst_x2 & 0xffff));
43103b705cfSriastradh		OUT_RELOC_PIXMAP_FENCED(dest,
43203b705cfSriastradh					I915_GEM_DOMAIN_RENDER,
43303b705cfSriastradh					I915_GEM_DOMAIN_RENDER,
43403b705cfSriastradh					0);
43503b705cfSriastradh		OUT_BATCH((src_y1 << 16) | (src_x1 & 0xffff));
43603b705cfSriastradh		OUT_BATCH(src_pitch);
43703b705cfSriastradh		OUT_RELOC_PIXMAP_FENCED(intel->render_source,
43803b705cfSriastradh					I915_GEM_DOMAIN_RENDER, 0,
43903b705cfSriastradh					0);
44003b705cfSriastradh
44103b705cfSriastradh		ADVANCE_BATCH();
44203b705cfSriastradh	}
44303b705cfSriastradh}
44403b705cfSriastradh
44503b705cfSriastradhstatic void intel_uxa_done(PixmapPtr pixmap)
44603b705cfSriastradh{
44703b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
44803b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
44903b705cfSriastradh
45042542f5fSchristos	if (INTEL_INFO(intel)->gen >= 060) {
45103b705cfSriastradh		/* workaround a random BLT hang */
45203b705cfSriastradh		BEGIN_BATCH_BLT(3);
45342542f5fSchristos		OUT_BATCH(XY_SETUP_CLIP_BLT_CMD | (3 - 2));
45403b705cfSriastradh		OUT_BATCH(0);
45503b705cfSriastradh		OUT_BATCH(0);
45603b705cfSriastradh		ADVANCE_BATCH();
45703b705cfSriastradh	}
45803b705cfSriastradh
45913496ba1Ssnj	intel_uxa_debug_flush(scrn);
46003b705cfSriastradh}
46103b705cfSriastradh
46203b705cfSriastradh/**
46303b705cfSriastradh * Do any cleanup from the Composite operation.
46403b705cfSriastradh *
46503b705cfSriastradh * This is shared between i830 through i965.
46603b705cfSriastradh */
46703b705cfSriastradhstatic void i830_done_composite(PixmapPtr dest)
46803b705cfSriastradh{
46903b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen);
47003b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
47103b705cfSriastradh
47203b705cfSriastradh	if (intel->vertex_flush)
47303b705cfSriastradh		intel->vertex_flush(intel);
47403b705cfSriastradh
47513496ba1Ssnj	intel_uxa_debug_flush(scrn);
47603b705cfSriastradh}
47703b705cfSriastradh
47803b705cfSriastradh#define xFixedToFloat(val) \
47903b705cfSriastradh	((float)xFixedToInt(val) + ((float)xFixedFrac(val) / 65536.0))
48003b705cfSriastradh
48103b705cfSriastradhstatic Bool
48203b705cfSriastradh_intel_transform_point(PictTransformPtr transform,
48303b705cfSriastradh		       float x, float y, float result[3])
48403b705cfSriastradh{
48503b705cfSriastradh	int j;
48603b705cfSriastradh
48703b705cfSriastradh	for (j = 0; j < 3; j++) {
48803b705cfSriastradh		result[j] = (xFixedToFloat(transform->matrix[j][0]) * x +
48903b705cfSriastradh			     xFixedToFloat(transform->matrix[j][1]) * y +
49003b705cfSriastradh			     xFixedToFloat(transform->matrix[j][2]));
49103b705cfSriastradh	}
49203b705cfSriastradh	if (!result[2])
49303b705cfSriastradh		return FALSE;
49403b705cfSriastradh	return TRUE;
49503b705cfSriastradh}
49603b705cfSriastradh
49703b705cfSriastradh/**
49803b705cfSriastradh * Returns the floating-point coordinates transformed by the given transform.
49903b705cfSriastradh *
50003b705cfSriastradh * transform may be null.
50103b705cfSriastradh */
50203b705cfSriastradhBool
50313496ba1Ssnjintel_uxa_get_transformed_coordinates(int x, int y, PictTransformPtr transform,
50403b705cfSriastradh				  float *x_out, float *y_out)
50503b705cfSriastradh{
50603b705cfSriastradh	if (transform == NULL) {
50703b705cfSriastradh		*x_out = x;
50803b705cfSriastradh		*y_out = y;
50903b705cfSriastradh	} else {
51003b705cfSriastradh		float result[3];
51103b705cfSriastradh
51203b705cfSriastradh		if (!_intel_transform_point(transform,
51303b705cfSriastradh					    x, y,
51403b705cfSriastradh					    result))
51503b705cfSriastradh			return FALSE;
51603b705cfSriastradh		*x_out = result[0] / result[2];
51703b705cfSriastradh		*y_out = result[1] / result[2];
51803b705cfSriastradh	}
51903b705cfSriastradh	return TRUE;
52003b705cfSriastradh}
52103b705cfSriastradh
52203b705cfSriastradh/**
52303b705cfSriastradh * Returns the un-normalized floating-point coordinates transformed by the given transform.
52403b705cfSriastradh *
52503b705cfSriastradh * transform may be null.
52603b705cfSriastradh */
52703b705cfSriastradhBool
52813496ba1Ssnjintel_uxa_get_transformed_coordinates_3d(int x, int y, PictTransformPtr transform,
52903b705cfSriastradh				     float *x_out, float *y_out, float *w_out)
53003b705cfSriastradh{
53103b705cfSriastradh	if (transform == NULL) {
53203b705cfSriastradh		*x_out = x;
53303b705cfSriastradh		*y_out = y;
53403b705cfSriastradh		*w_out = 1;
53503b705cfSriastradh	} else {
53603b705cfSriastradh		float result[3];
53703b705cfSriastradh
53803b705cfSriastradh		if (!_intel_transform_point(transform,
53903b705cfSriastradh					    x, y,
54003b705cfSriastradh					    result))
54103b705cfSriastradh			return FALSE;
54203b705cfSriastradh		*x_out = result[0];
54303b705cfSriastradh		*y_out = result[1];
54403b705cfSriastradh		*w_out = result[2];
54503b705cfSriastradh	}
54603b705cfSriastradh	return TRUE;
54703b705cfSriastradh}
54803b705cfSriastradh
54903b705cfSriastradh/**
55003b705cfSriastradh * Returns whether the provided transform is affine.
55103b705cfSriastradh *
55203b705cfSriastradh * transform may be null.
55303b705cfSriastradh */
55413496ba1SsnjBool intel_uxa_transform_is_affine(PictTransformPtr t)
55503b705cfSriastradh{
55603b705cfSriastradh	if (t == NULL)
55703b705cfSriastradh		return TRUE;
55803b705cfSriastradh	return t->matrix[2][0] == 0 && t->matrix[2][1] == 0;
55903b705cfSriastradh}
56003b705cfSriastradh
56113496ba1Ssnjdri_bo *intel_uxa_get_pixmap_bo(PixmapPtr pixmap)
56203b705cfSriastradh{
56313496ba1Ssnj	struct intel_uxa_pixmap *intel;
56403b705cfSriastradh
56513496ba1Ssnj	intel = intel_uxa_get_pixmap_private(pixmap);
56603b705cfSriastradh	if (intel == NULL)
56703b705cfSriastradh		return NULL;
56803b705cfSriastradh
56903b705cfSriastradh	return intel->bo;
57003b705cfSriastradh}
57103b705cfSriastradh
57242542f5fSchristosstatic unsigned intel_get_tile_width(intel_screen_private *intel, int tiling, int pitch)
57342542f5fSchristos{
57442542f5fSchristos	unsigned long tile_width;
57542542f5fSchristos
57642542f5fSchristos	if (tiling == I915_TILING_NONE)
57742542f5fSchristos		return 4;
57842542f5fSchristos
57942542f5fSchristos	tile_width = (tiling == I915_TILING_Y) ? 128 : 512;
58042542f5fSchristos	if (INTEL_INFO(intel)->gen >= 040)
58142542f5fSchristos		return tile_width;
58242542f5fSchristos
58342542f5fSchristos	while (tile_width < pitch)
58442542f5fSchristos		tile_width <<= 1;
58542542f5fSchristos
58642542f5fSchristos	return tile_width;
58742542f5fSchristos}
58842542f5fSchristos
58913496ba1Ssnjvoid intel_uxa_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo)
59003b705cfSriastradh{
59142542f5fSchristos	ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
59242542f5fSchristos	intel_screen_private *intel = intel_get_screen_private(scrn);
59313496ba1Ssnj	struct intel_uxa_pixmap *priv;
59403b705cfSriastradh
59513496ba1Ssnj	priv = intel_uxa_get_pixmap_private(pixmap);
59603b705cfSriastradh	if (priv == NULL && bo == NULL)
59742542f5fSchristos		return;
59803b705cfSriastradh
59903b705cfSriastradh	if (priv != NULL) {
60003b705cfSriastradh		if (priv->bo == bo)
60103b705cfSriastradh			return;
60203b705cfSriastradh
60342542f5fSchristosfree_priv:
60403b705cfSriastradh		dri_bo_unreference(priv->bo);
60503b705cfSriastradh		list_del(&priv->batch);
60603b705cfSriastradh
60703b705cfSriastradh		free(priv);
60803b705cfSriastradh		priv = NULL;
60903b705cfSriastradh	}
61003b705cfSriastradh
61103b705cfSriastradh	if (bo != NULL) {
61242542f5fSchristos		uint32_t tiling, swizzle_mode;
61342542f5fSchristos		unsigned tile_width;
61442542f5fSchristos		int size, stride;
61503b705cfSriastradh
61613496ba1Ssnj		priv = calloc(1, sizeof (struct intel_uxa_pixmap));
61703b705cfSriastradh		if (priv == NULL)
61803b705cfSriastradh			goto BAIL;
61903b705cfSriastradh
62003b705cfSriastradh		list_init(&priv->batch);
62103b705cfSriastradh
62203b705cfSriastradh		dri_bo_reference(bo);
62303b705cfSriastradh		priv->bo = bo;
62403b705cfSriastradh
62542542f5fSchristos		if (drm_intel_bo_get_tiling(bo, &tiling, &swizzle_mode)) {
62642542f5fSchristos			bo = NULL;
62742542f5fSchristos			goto free_priv;
62803b705cfSriastradh		}
62903b705cfSriastradh
63003b705cfSriastradh		priv->tiling = tiling;
63103b705cfSriastradh		priv->busy = -1;
63203b705cfSriastradh		priv->offscreen = 1;
63342542f5fSchristos
63442542f5fSchristos		stride = (pixmap->drawable.width * pixmap->drawable.bitsPerPixel + 7) / 8;
63542542f5fSchristos		tile_width = intel_get_tile_width(intel, tiling, stride);
63642542f5fSchristos		stride = ALIGN(stride, tile_width);
63742542f5fSchristos
63813496ba1Ssnj		if (intel_pixmap_pitch(pixmap) < stride ||
63913496ba1Ssnj		    intel_pixmap_pitch(pixmap) & (tile_width - 1) ||
64013496ba1Ssnj		    intel_pixmap_pitch(pixmap) >= KB(32)) {
64142542f5fSchristos			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
64242542f5fSchristos				   "%s: stride on buffer object does not match constraints: stride=%d, must be greater than %d, but less than %d, and have alignment at least %d\n",
64313496ba1Ssnj				   __FUNCTION__, intel_pixmap_pitch(pixmap), stride, KB(32), tile_width);
64442542f5fSchristos			bo = NULL;
64542542f5fSchristos			goto free_priv;
64642542f5fSchristos		}
64742542f5fSchristos
64842542f5fSchristos		if (tiling != I915_TILING_NONE) {
64942542f5fSchristos			int height;
65042542f5fSchristos
65142542f5fSchristos			if (IS_GEN2(intel))
65242542f5fSchristos				height = 16;
65342542f5fSchristos			else if (tiling == I915_TILING_X)
65442542f5fSchristos				height = 8;
65542542f5fSchristos			else
65642542f5fSchristos				height = 32;
65742542f5fSchristos
65813496ba1Ssnj			height = ALIGN(pixmap->drawable.height, height);
65913496ba1Ssnj			size = intel_get_fence_size(intel, intel_pixmap_pitch(pixmap) * height);
66042542f5fSchristos		} else
66113496ba1Ssnj			size = intel_pixmap_pitch(pixmap) * pixmap->drawable.height;
66242542f5fSchristos
66342542f5fSchristos		if (bo->size < size || bo->size > intel->max_bo_size) {
66442542f5fSchristos			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
66542542f5fSchristos				   "%s: size of buffer object does not match constraints: size=%ld, must be greater than %d, but less than %d\n",
66642542f5fSchristos				   __FUNCTION__, (long)bo->size, size, intel->max_bo_size);
66742542f5fSchristos			bo = NULL;
66842542f5fSchristos			goto free_priv;
66942542f5fSchristos		}
67003b705cfSriastradh	}
67103b705cfSriastradh
67203b705cfSriastradh  BAIL:
67313496ba1Ssnj	intel_uxa_set_pixmap_private(pixmap, priv);
67403b705cfSriastradh}
67503b705cfSriastradh
67603b705cfSriastradhstatic Bool intel_uxa_prepare_access(PixmapPtr pixmap, uxa_access_t access)
67703b705cfSriastradh{
67803b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
67903b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
68013496ba1Ssnj	struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap);
68103b705cfSriastradh	dri_bo *bo = priv->bo;
68203b705cfSriastradh	int ret;
68303b705cfSriastradh
68403b705cfSriastradh	/* When falling back to swrast, flush all pending operations */
68503b705cfSriastradh	if (access == UXA_ACCESS_RW || priv->dirty)
68603b705cfSriastradh		intel_batch_submit(scrn);
68703b705cfSriastradh
68803b705cfSriastradh	assert(bo->size <= intel->max_gtt_map_size);
68903b705cfSriastradh	ret = drm_intel_gem_bo_map_gtt(bo);
69003b705cfSriastradh	if (ret) {
69103b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
69203b705cfSriastradh			   "%s: bo map (use gtt? %d, access %d) failed: %s\n",
69303b705cfSriastradh			   __FUNCTION__,
69403b705cfSriastradh			   priv->tiling || bo->size <= intel->max_gtt_map_size,
69503b705cfSriastradh			   access,
69603b705cfSriastradh			   strerror(-ret));
69703b705cfSriastradh		return FALSE;
69803b705cfSriastradh	}
69903b705cfSriastradh
70003b705cfSriastradh	pixmap->devPrivate.ptr = bo->virtual;
70103b705cfSriastradh	priv->busy = 0;
70203b705cfSriastradh
70303b705cfSriastradh	return TRUE;
70403b705cfSriastradh}
70503b705cfSriastradh
70603b705cfSriastradhstatic void intel_uxa_finish_access(PixmapPtr pixmap, uxa_access_t access)
70703b705cfSriastradh{
70813496ba1Ssnj	struct intel_uxa_pixmap *priv;
70903b705cfSriastradh
71013496ba1Ssnj	priv = intel_uxa_get_pixmap_private(pixmap);
71103b705cfSriastradh	if (priv == NULL)
71203b705cfSriastradh		return;
71303b705cfSriastradh
71403b705cfSriastradh	drm_intel_gem_bo_unmap_gtt(priv->bo);
71503b705cfSriastradh	pixmap->devPrivate.ptr = NULL;
71603b705cfSriastradh}
71703b705cfSriastradh
71803b705cfSriastradhstatic Bool intel_uxa_pixmap_put_image(PixmapPtr pixmap,
71903b705cfSriastradh				       char *src, int src_pitch,
72003b705cfSriastradh				       int x, int y, int w, int h)
72103b705cfSriastradh{
72213496ba1Ssnj	struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap);
72303b705cfSriastradh	int stride = intel_pixmap_pitch(pixmap);
72403b705cfSriastradh	int cpp = pixmap->drawable.bitsPerPixel/8;
72503b705cfSriastradh	int ret = FALSE;
72603b705cfSriastradh
72703b705cfSriastradh	if (priv == NULL || priv->bo == NULL)
72803b705cfSriastradh		return FALSE;
72903b705cfSriastradh
73003b705cfSriastradh	if (priv->tiling == I915_TILING_NONE &&
73103b705cfSriastradh	    (h == 1 || (src_pitch == stride && w == pixmap->drawable.width))) {
73203b705cfSriastradh		return drm_intel_bo_subdata(priv->bo, y*stride + x*cpp, stride*(h-1) + w*cpp, src) == 0;
73303b705cfSriastradh	} else if (drm_intel_gem_bo_map_gtt(priv->bo) == 0) {
73403b705cfSriastradh		char *dst = priv->bo->virtual;
73503b705cfSriastradh		int row_length = w * cpp;
73603b705cfSriastradh		int num_rows = h;
73703b705cfSriastradh		if (row_length == src_pitch && src_pitch == stride)
73803b705cfSriastradh			num_rows = 1, row_length *= h;
73903b705cfSriastradh		dst += y * stride + x * cpp;
74003b705cfSriastradh		do {
74103b705cfSriastradh			memcpy (dst, src, row_length);
74203b705cfSriastradh			src += src_pitch;
74303b705cfSriastradh			dst += stride;
74403b705cfSriastradh		} while (--num_rows);
74503b705cfSriastradh		drm_intel_gem_bo_unmap_gtt(priv->bo);
74603b705cfSriastradh		ret = TRUE;
74703b705cfSriastradh	}
74803b705cfSriastradh
74903b705cfSriastradh	return ret;
75003b705cfSriastradh}
75103b705cfSriastradh
75203b705cfSriastradhstatic Bool intel_uxa_put_image(PixmapPtr pixmap,
75303b705cfSriastradh				int x, int y,
75403b705cfSriastradh				int w, int h,
75503b705cfSriastradh				char *src, int src_pitch)
75603b705cfSriastradh{
75713496ba1Ssnj	struct intel_uxa_pixmap *priv;
75803b705cfSriastradh
75913496ba1Ssnj	priv = intel_uxa_get_pixmap_private(pixmap);
76013496ba1Ssnj	if (!intel_uxa_pixmap_is_busy(priv)) {
76103b705cfSriastradh		/* bo is not busy so can be replaced without a stall, upload in-place. */
76203b705cfSriastradh		return intel_uxa_pixmap_put_image(pixmap, src, src_pitch, x, y, w, h);
76303b705cfSriastradh	} else {
76403b705cfSriastradh		ScreenPtr screen = pixmap->drawable.pScreen;
76503b705cfSriastradh
76603b705cfSriastradh		if (!priv->pinned &&
76703b705cfSriastradh		    x == 0 && y == 0 &&
76803b705cfSriastradh		    w == pixmap->drawable.width &&
76903b705cfSriastradh		    h == pixmap->drawable.height)
77003b705cfSriastradh		{
77103b705cfSriastradh			intel_screen_private *intel = intel_get_screen_private(xf86ScreenToScrn(screen));
77203b705cfSriastradh			uint32_t tiling = priv->tiling;
77303b705cfSriastradh			int size, stride;
77403b705cfSriastradh			dri_bo *bo;
77503b705cfSriastradh
77603b705cfSriastradh			/* Replace busy bo. */
77713496ba1Ssnj			size = intel_compute_size(intel,
77813496ba1Ssnj                                                  w, h,
77913496ba1Ssnj                                                  pixmap->drawable.bitsPerPixel, pixmap->usage_hint,
78013496ba1Ssnj                                                  &tiling, &stride);
78103b705cfSriastradh			if (size > intel->max_gtt_map_size)
78203b705cfSriastradh				return FALSE;
78303b705cfSriastradh
78403b705cfSriastradh			bo = drm_intel_bo_alloc(intel->bufmgr, "pixmap", size, 0);
78503b705cfSriastradh			if (bo == NULL)
78603b705cfSriastradh				return FALSE;
78703b705cfSriastradh
78803b705cfSriastradh			if (tiling != I915_TILING_NONE)
78903b705cfSriastradh				drm_intel_bo_set_tiling(bo, &tiling, stride);
79003b705cfSriastradh			priv->tiling = tiling;
79103b705cfSriastradh
79203b705cfSriastradh			screen->ModifyPixmapHeader(pixmap,
79303b705cfSriastradh						   w, h,
79403b705cfSriastradh						   0, 0,
79503b705cfSriastradh						   stride, NULL);
79613496ba1Ssnj			intel_uxa_set_pixmap_bo(pixmap, bo);
79703b705cfSriastradh			dri_bo_unreference(bo);
79803b705cfSriastradh
79903b705cfSriastradh			return intel_uxa_pixmap_put_image(pixmap, src, src_pitch, 0, 0, w, h);
80003b705cfSriastradh		}
80103b705cfSriastradh		else
80203b705cfSriastradh		{
80303b705cfSriastradh			PixmapPtr scratch;
80403b705cfSriastradh			Bool ret;
80503b705cfSriastradh
80603b705cfSriastradh			/* Upload to a linear buffer and queue a blit.  */
80703b705cfSriastradh			scratch = (*screen->CreatePixmap)(screen, w, h,
80803b705cfSriastradh							  pixmap->drawable.depth,
80903b705cfSriastradh							  UXA_CREATE_PIXMAP_FOR_MAP);
81003b705cfSriastradh			if (!scratch)
81103b705cfSriastradh				return FALSE;
81203b705cfSriastradh
81303b705cfSriastradh			if (!intel_uxa_pixmap_is_offscreen(scratch)) {
81403b705cfSriastradh				screen->DestroyPixmap(scratch);
81503b705cfSriastradh				return FALSE;
81603b705cfSriastradh			}
81703b705cfSriastradh
81803b705cfSriastradh			ret = intel_uxa_pixmap_put_image(scratch, src, src_pitch, 0, 0, w, h);
81903b705cfSriastradh			if (ret) {
82003b705cfSriastradh				GCPtr gc = GetScratchGC(pixmap->drawable.depth, screen);
82103b705cfSriastradh				if (gc) {
82203b705cfSriastradh					ValidateGC(&pixmap->drawable, gc);
82303b705cfSriastradh
82403b705cfSriastradh					(*gc->ops->CopyArea)(&scratch->drawable,
82503b705cfSriastradh							     &pixmap->drawable,
82603b705cfSriastradh							     gc, 0, 0, w, h, x, y);
82703b705cfSriastradh
82803b705cfSriastradh					FreeScratchGC(gc);
82903b705cfSriastradh				} else
83003b705cfSriastradh					ret = FALSE;
83103b705cfSriastradh			}
83203b705cfSriastradh
83303b705cfSriastradh			(*screen->DestroyPixmap)(scratch);
83403b705cfSriastradh			return ret;
83503b705cfSriastradh		}
83603b705cfSriastradh	}
83703b705cfSriastradh}
83803b705cfSriastradh
83903b705cfSriastradhstatic Bool intel_uxa_pixmap_get_image(PixmapPtr pixmap,
84003b705cfSriastradh				       int x, int y, int w, int h,
84103b705cfSriastradh				       char *dst, int dst_pitch)
84203b705cfSriastradh{
84313496ba1Ssnj	struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap);
84403b705cfSriastradh	int stride = intel_pixmap_pitch(pixmap);
84503b705cfSriastradh	int cpp = pixmap->drawable.bitsPerPixel/8;
84603b705cfSriastradh
84703b705cfSriastradh	/* assert(priv->tiling == I915_TILING_NONE); */
84803b705cfSriastradh	if (h == 1 || (dst_pitch == stride && w == pixmap->drawable.width)) {
84903b705cfSriastradh		return drm_intel_bo_get_subdata(priv->bo, y*stride + x*cpp, (h-1)*stride + w*cpp, dst) == 0;
85003b705cfSriastradh	} else {
85103b705cfSriastradh		char *src;
85203b705cfSriastradh
85303b705cfSriastradh		if (drm_intel_gem_bo_map_gtt(priv->bo))
85403b705cfSriastradh		    return FALSE;
85503b705cfSriastradh
85603b705cfSriastradh		src = (char *) priv->bo->virtual + y * stride + x * cpp;
85703b705cfSriastradh		w *= cpp;
85803b705cfSriastradh		do {
85903b705cfSriastradh			memcpy(dst, src, w);
86003b705cfSriastradh			src += stride;
86103b705cfSriastradh			dst += dst_pitch;
86203b705cfSriastradh		} while (--h);
86303b705cfSriastradh
86403b705cfSriastradh		drm_intel_gem_bo_unmap_gtt(priv->bo);
86503b705cfSriastradh
86603b705cfSriastradh		return TRUE;
86703b705cfSriastradh	}
86803b705cfSriastradh}
86903b705cfSriastradh
87003b705cfSriastradhstatic Bool intel_uxa_get_image(PixmapPtr pixmap,
87103b705cfSriastradh				int x, int y,
87203b705cfSriastradh				int w, int h,
87303b705cfSriastradh				char *dst, int dst_pitch)
87403b705cfSriastradh{
87513496ba1Ssnj	struct intel_uxa_pixmap *priv;
87603b705cfSriastradh	PixmapPtr scratch = NULL;
87703b705cfSriastradh	Bool ret;
87803b705cfSriastradh
87903b705cfSriastradh	/* The presumption is that we wish to keep the target hot, so
88003b705cfSriastradh	 * copy to a new bo and move that to the CPU in preference to
88103b705cfSriastradh	 * causing ping-pong of the original.
88203b705cfSriastradh	 *
88303b705cfSriastradh	 * Also the gpu is much faster at detiling.
88403b705cfSriastradh	 */
88503b705cfSriastradh
88613496ba1Ssnj	priv = intel_uxa_get_pixmap_private(pixmap);
88713496ba1Ssnj	if (intel_uxa_pixmap_is_busy(priv) || priv->tiling != I915_TILING_NONE) {
88803b705cfSriastradh		ScreenPtr screen = pixmap->drawable.pScreen;
88903b705cfSriastradh		GCPtr gc;
89003b705cfSriastradh
89103b705cfSriastradh		/* Copy to a linear buffer and pull.  */
89203b705cfSriastradh		scratch = screen->CreatePixmap(screen, w, h,
89303b705cfSriastradh					       pixmap->drawable.depth,
89403b705cfSriastradh					       INTEL_CREATE_PIXMAP_TILING_NONE);
89503b705cfSriastradh		if (!scratch)
89603b705cfSriastradh			return FALSE;
89703b705cfSriastradh
89803b705cfSriastradh		if (!intel_uxa_pixmap_is_offscreen(scratch)) {
89903b705cfSriastradh			screen->DestroyPixmap(scratch);
90003b705cfSriastradh			return FALSE;
90103b705cfSriastradh		}
90203b705cfSriastradh
90303b705cfSriastradh		gc = GetScratchGC(pixmap->drawable.depth, screen);
90403b705cfSriastradh		if (!gc) {
90503b705cfSriastradh			screen->DestroyPixmap(scratch);
90603b705cfSriastradh			return FALSE;
90703b705cfSriastradh		}
90803b705cfSriastradh
90903b705cfSriastradh		ValidateGC(&pixmap->drawable, gc);
91003b705cfSriastradh
91103b705cfSriastradh		gc->ops->CopyArea(&pixmap->drawable,
91203b705cfSriastradh				  &scratch->drawable,
91303b705cfSriastradh				  gc, x, y, w, h, 0, 0);
91403b705cfSriastradh
91503b705cfSriastradh		FreeScratchGC(gc);
91603b705cfSriastradh
91703b705cfSriastradh		intel_batch_submit(xf86ScreenToScrn(screen));
91803b705cfSriastradh
91903b705cfSriastradh		x = y = 0;
92003b705cfSriastradh		pixmap = scratch;
92103b705cfSriastradh	}
92203b705cfSriastradh
92303b705cfSriastradh	ret = intel_uxa_pixmap_get_image(pixmap, x, y, w, h, dst, dst_pitch);
92403b705cfSriastradh
92503b705cfSriastradh	if (scratch)
92603b705cfSriastradh		scratch->drawable.pScreen->DestroyPixmap(scratch);
92703b705cfSriastradh
92803b705cfSriastradh	return ret;
92903b705cfSriastradh}
93003b705cfSriastradh
93103b705cfSriastradhstatic CARD32 intel_cache_expire(OsTimerPtr timer, CARD32 now, pointer data)
93203b705cfSriastradh{
93303b705cfSriastradh	intel_screen_private *intel = data;
93403b705cfSriastradh
93503b705cfSriastradh	/* We just want to create and destroy a bo as this causes libdrm
93603b705cfSriastradh	 * to reap its caches. However, since we can't remove that buffer
93703b705cfSriastradh	 * from the cache due to its own activity, we want to use something
93803b705cfSriastradh	 * that we know we will reuse later. The most frequently reused buffer
93903b705cfSriastradh	 * we have is the batchbuffer, and the best way to trigger its
94003b705cfSriastradh	 * reallocation is to submit a flush.
94103b705cfSriastradh	 */
94203b705cfSriastradh	intel_batch_emit_flush(intel->scrn);
94303b705cfSriastradh	intel_batch_submit(intel->scrn);
94403b705cfSriastradh
94503b705cfSriastradh	return 0;
94603b705cfSriastradh}
94703b705cfSriastradh
94803b705cfSriastradhstatic void intel_flush_rendering(intel_screen_private *intel)
94903b705cfSriastradh{
95003b705cfSriastradh	if (intel->needs_flush == 0)
95103b705cfSriastradh		return;
95203b705cfSriastradh
95303b705cfSriastradh	if (intel->has_kernel_flush) {
95403b705cfSriastradh		intel_batch_submit(intel->scrn);
95503b705cfSriastradh		drm_intel_bo_busy(intel->front_buffer);
95603b705cfSriastradh	} else {
95703b705cfSriastradh		intel_batch_emit_flush(intel->scrn);
95803b705cfSriastradh		intel_batch_submit(intel->scrn);
95903b705cfSriastradh	}
96003b705cfSriastradh
96103b705cfSriastradh	intel->cache_expire = TimerSet(intel->cache_expire, 0, 3000,
96203b705cfSriastradh				       intel_cache_expire, intel);
96303b705cfSriastradh
96403b705cfSriastradh	intel->needs_flush = 0;
96503b705cfSriastradh}
96603b705cfSriastradh
96703b705cfSriastradhstatic void intel_throttle(intel_screen_private *intel)
96803b705cfSriastradh{
96903b705cfSriastradh	drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE);
97003b705cfSriastradh}
97103b705cfSriastradh
97203b705cfSriastradhvoid intel_uxa_block_handler(intel_screen_private *intel)
97303b705cfSriastradh{
97403b705cfSriastradh	/* Emit a flush of the rendering cache, or on the 965
97503b705cfSriastradh	 * and beyond rendering results may not hit the
97603b705cfSriastradh	 * framebuffer until significantly later.
97703b705cfSriastradh	 */
97803b705cfSriastradh	intel_flush_rendering(intel);
97903b705cfSriastradh	intel_throttle(intel);
98003b705cfSriastradh}
98103b705cfSriastradh
98203b705cfSriastradhstatic PixmapPtr
98303b705cfSriastradhintel_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth,
98403b705cfSriastradh			unsigned usage)
98503b705cfSriastradh{
98603b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
98703b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
98813496ba1Ssnj	struct intel_uxa_pixmap *priv;
98903b705cfSriastradh	PixmapPtr pixmap, new_pixmap = NULL;
99003b705cfSriastradh
99103b705cfSriastradh	if (w > 32767 || h > 32767)
99203b705cfSriastradh		return NullPixmap;
99303b705cfSriastradh
99403b705cfSriastradh	if (depth == 1 || intel->force_fallback)
99503b705cfSriastradh		return fbCreatePixmap(screen, w, h, depth, usage);
99603b705cfSriastradh
99703b705cfSriastradh	if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 32 && h <= 32)
99803b705cfSriastradh		return fbCreatePixmap(screen, w, h, depth, usage);
99903b705cfSriastradh
100003b705cfSriastradh	pixmap = fbCreatePixmap(screen, 0, 0, depth, usage);
100103b705cfSriastradh	if (pixmap == NullPixmap)
100203b705cfSriastradh		return pixmap;
100303b705cfSriastradh
100403b705cfSriastradh	if (w && h) {
100503b705cfSriastradh		unsigned int size, tiling;
100603b705cfSriastradh		int stride;
100703b705cfSriastradh
100803b705cfSriastradh		/* Always attempt to tile, compute_size() will remove the
100903b705cfSriastradh		 * tiling for pixmaps that are either too large or too small
101003b705cfSriastradh		 * to be effectively tiled.
101103b705cfSriastradh		 */
101203b705cfSriastradh		tiling = I915_TILING_X;
101303b705cfSriastradh		if (usage & INTEL_CREATE_PIXMAP_TILING_Y)
101403b705cfSriastradh			tiling = I915_TILING_Y;
101503b705cfSriastradh		if (usage == UXA_CREATE_PIXMAP_FOR_MAP || usage & INTEL_CREATE_PIXMAP_TILING_NONE)
101603b705cfSriastradh			tiling = I915_TILING_NONE;
101703b705cfSriastradh
101803b705cfSriastradh#ifdef CREATE_PIXMAP_USAGE_SHARED
101903b705cfSriastradh		if (usage == CREATE_PIXMAP_USAGE_SHARED)
102003b705cfSriastradh			tiling = I915_TILING_NONE;
102103b705cfSriastradh#endif
102203b705cfSriastradh		/* if tiling is off force to none */
102303b705cfSriastradh		if (!intel->tiling)
102403b705cfSriastradh			tiling = I915_TILING_NONE;
102503b705cfSriastradh
102603b705cfSriastradh		if (tiling != I915_TILING_NONE && !(usage & INTEL_CREATE_PIXMAP_DRI2)) {
102703b705cfSriastradh		    if (h <= 4)
102803b705cfSriastradh			tiling = I915_TILING_NONE;
102903b705cfSriastradh		    if (h <= 16 && tiling == I915_TILING_Y)
103003b705cfSriastradh			tiling = I915_TILING_X;
103103b705cfSriastradh		}
103213496ba1Ssnj		size = intel_compute_size(intel,
103313496ba1Ssnj                                          w, h, pixmap->drawable.bitsPerPixel, usage,
103413496ba1Ssnj                                          &tiling, &stride);
103503b705cfSriastradh
103603b705cfSriastradh		/* Fail very large allocations.  Large BOs will tend to hit SW fallbacks
103703b705cfSriastradh		 * frequently, and also will tend to fail to successfully map when doing
103803b705cfSriastradh		 * SW fallbacks because we overcommit address space for BO access.
103903b705cfSriastradh		 */
104003b705cfSriastradh		if (size > intel->max_bo_size || stride >= KB(32))
104103b705cfSriastradh			goto fallback_pixmap;
104203b705cfSriastradh
104313496ba1Ssnj		priv = calloc(1, sizeof (struct intel_uxa_pixmap));
104403b705cfSriastradh		if (priv == NULL)
104503b705cfSriastradh			goto fallback_pixmap;
104603b705cfSriastradh
104703b705cfSriastradh		if (usage == UXA_CREATE_PIXMAP_FOR_MAP) {
104803b705cfSriastradh			priv->busy = 0;
104903b705cfSriastradh			priv->bo = drm_intel_bo_alloc(intel->bufmgr,
105003b705cfSriastradh						      "pixmap", size, 0);
105103b705cfSriastradh		} else {
105203b705cfSriastradh			priv->busy = -1;
105303b705cfSriastradh			priv->bo = drm_intel_bo_alloc_for_render(intel->bufmgr,
105403b705cfSriastradh								 "pixmap",
105503b705cfSriastradh								 size, 0);
105603b705cfSriastradh		}
105703b705cfSriastradh		if (!priv->bo)
105803b705cfSriastradh			goto fallback_priv;
105903b705cfSriastradh
106003b705cfSriastradh		if (tiling != I915_TILING_NONE)
106103b705cfSriastradh			drm_intel_bo_set_tiling(priv->bo, &tiling, stride);
106203b705cfSriastradh		priv->tiling = tiling;
106303b705cfSriastradh		priv->offscreen = 1;
106403b705cfSriastradh
106503b705cfSriastradh		list_init(&priv->batch);
106613496ba1Ssnj		intel_uxa_set_pixmap_private(pixmap, priv);
106703b705cfSriastradh
106803b705cfSriastradh		screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL);
106903b705cfSriastradh	}
107003b705cfSriastradh
107103b705cfSriastradh	return pixmap;
107203b705cfSriastradh
107303b705cfSriastradhfallback_priv:
107403b705cfSriastradh	free(priv);
107503b705cfSriastradhfallback_pixmap:
107603b705cfSriastradh	fbDestroyPixmap(pixmap);
107703b705cfSriastradh	if (new_pixmap)
107803b705cfSriastradh		return new_pixmap;
107903b705cfSriastradh	else
108003b705cfSriastradh		return fbCreatePixmap(screen, w, h, depth, usage);
108103b705cfSriastradh}
108203b705cfSriastradh
108303b705cfSriastradhstatic Bool intel_uxa_destroy_pixmap(PixmapPtr pixmap)
108403b705cfSriastradh{
108513496ba1Ssnj	if (pixmap->refcnt == 1)
108613496ba1Ssnj		intel_uxa_set_pixmap_bo(pixmap, NULL);
108703b705cfSriastradh	fbDestroyPixmap(pixmap);
108803b705cfSriastradh	return TRUE;
108903b705cfSriastradh}
109003b705cfSriastradh
109103b705cfSriastradhBool intel_uxa_create_screen_resources(ScreenPtr screen)
109203b705cfSriastradh{
109303b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
109403b705cfSriastradh	PixmapPtr pixmap;
109503b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
1096fe8aea9eSmrg	dri_bo *bo = intel->front_buffer, *old_bo;
109742542f5fSchristos	int old_width, old_height, old_pitch;
109803b705cfSriastradh
109903b705cfSriastradh	if (!uxa_resources_init(screen))
110003b705cfSriastradh		return FALSE;
110103b705cfSriastradh
110203b705cfSriastradh	if (drm_intel_gem_bo_map_gtt(bo))
110303b705cfSriastradh		return FALSE;
110403b705cfSriastradh
110503b705cfSriastradh	pixmap = screen->GetScreenPixmap(screen);
110642542f5fSchristos	old_width = pixmap->drawable.width;
110742542f5fSchristos	old_height = pixmap->drawable.height;
110842542f5fSchristos	old_pitch = pixmap->devKind;
1109fe8aea9eSmrg	old_bo = intel_uxa_get_pixmap_bo(pixmap);
111042542f5fSchristos
111142542f5fSchristos	if (!screen->ModifyPixmapHeader(pixmap,
111242542f5fSchristos					scrn->virtualX,
111342542f5fSchristos					scrn->virtualY,
111442542f5fSchristos					-1, -1,
111542542f5fSchristos					intel->front_pitch,
111642542f5fSchristos					NULL))
111742542f5fSchristos		return FALSE;
111842542f5fSchristos
111913496ba1Ssnj	intel_uxa_set_pixmap_bo(pixmap, bo);
112013496ba1Ssnj	if (intel_uxa_get_pixmap_private(pixmap) == NULL)
112142542f5fSchristos		goto err;
112203b705cfSriastradh
112313496ba1Ssnj	intel_uxa_get_pixmap_private(pixmap)->pinned |= PIN_SCANOUT;
112442542f5fSchristos	scrn->displayWidth = intel->front_pitch / intel->cpp;
112503b705cfSriastradh
112603b705cfSriastradh	return TRUE;
112742542f5fSchristos
112842542f5fSchristoserr:
112942542f5fSchristos	screen->ModifyPixmapHeader(pixmap,
113042542f5fSchristos				   old_width, old_height, -1, -1, old_pitch, NULL);
1131fe8aea9eSmrg	if (old_bo)
1132fe8aea9eSmrg		intel_uxa_set_pixmap_bo(pixmap, old_bo);
1133fe8aea9eSmrg
113442542f5fSchristos	return FALSE;
113503b705cfSriastradh}
113603b705cfSriastradh
113703b705cfSriastradh#ifdef CREATE_PIXMAP_USAGE_SHARED
113803b705cfSriastradhstatic Bool
113903b705cfSriastradhintel_uxa_share_pixmap_backing(PixmapPtr ppix, ScreenPtr slave, void **fd_handle)
114003b705cfSriastradh{
114103b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(ppix->drawable.pScreen);
114203b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
114313496ba1Ssnj	struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(ppix);
114403b705cfSriastradh	unsigned int size, tiling, swizzle;
114513496ba1Ssnj	dri_bo *bo = intel_uxa_get_pixmap_bo(ppix), *newbo;
114603b705cfSriastradh	int stride;
114703b705cfSriastradh	int handle;
114803b705cfSriastradh
114903b705cfSriastradh	if (drm_intel_bo_references(intel->batch_bo, bo))
115003b705cfSriastradh		intel_batch_submit(intel->scrn);
115103b705cfSriastradh
115203b705cfSriastradh	drm_intel_bo_get_tiling(bo, &tiling, &swizzle);
115303b705cfSriastradh
115403b705cfSriastradh	if (tiling == I915_TILING_X) {
115542542f5fSchristos		if (priv->pinned)
115603b705cfSriastradh			return FALSE;
115703b705cfSriastradh
115803b705cfSriastradh	        tiling = I915_TILING_NONE;
115903b705cfSriastradh
116013496ba1Ssnj		size = intel_compute_size(intel,
116113496ba1Ssnj                                          ppix->drawable.width, ppix->drawable.height,
116213496ba1Ssnj                                          ppix->drawable.bitsPerPixel, INTEL_CREATE_PIXMAP_DRI2,
116313496ba1Ssnj                                          &tiling, &stride);
116403b705cfSriastradh
116503b705cfSriastradh		newbo = drm_intel_bo_alloc_for_render(intel->bufmgr,
116603b705cfSriastradh						      "pixmap",
116703b705cfSriastradh						      size, 0);
116803b705cfSriastradh
116903b705cfSriastradh		if (tiling != I915_TILING_NONE)
117003b705cfSriastradh			drm_intel_bo_set_tiling(newbo, &tiling, stride);
117103b705cfSriastradh		priv->tiling = tiling;
117213496ba1Ssnj		intel_uxa_set_pixmap_bo(ppix, newbo);
117303b705cfSriastradh
117403b705cfSriastradh		ppix->drawable.pScreen->ModifyPixmapHeader(ppix, ppix->drawable.width,
117503b705cfSriastradh					   ppix->drawable.height, 0, 0,
117603b705cfSriastradh					   stride, NULL);
117703b705cfSriastradh		bo = newbo;
117803b705cfSriastradh	}
117903b705cfSriastradh	drm_intel_bo_get_tiling(bo, &tiling, &swizzle);
118003b705cfSriastradh	drm_intel_bo_gem_export_to_prime(bo, &handle);
118142542f5fSchristos	priv->pinned |= PIN_PRIME;
118203b705cfSriastradh
118303b705cfSriastradh	*fd_handle = (void *)(long)handle;
118403b705cfSriastradh	return TRUE;
118503b705cfSriastradh}
118603b705cfSriastradh
118703b705cfSriastradhstatic Bool
118803b705cfSriastradhintel_uxa_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle)
118903b705cfSriastradh{
119003b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(ppix->drawable.pScreen);
119103b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
119203b705cfSriastradh	dri_bo *bo;
119303b705cfSriastradh	int ihandle = (int)(long)fd_handle;
119403b705cfSriastradh
119503b705cfSriastradh	/* force untiled for now */
119603b705cfSriastradh	bo = drm_intel_bo_gem_create_from_prime(intel->bufmgr, ihandle, 0);
119703b705cfSriastradh	if (!bo)
119803b705cfSriastradh		return FALSE;
119903b705cfSriastradh
120013496ba1Ssnj	intel_uxa_set_pixmap_bo(ppix, bo);
120103b705cfSriastradh	close(ihandle);
120203b705cfSriastradh	return TRUE;
120303b705cfSriastradh}
120403b705cfSriastradh#endif
120503b705cfSriastradh
120603b705cfSriastradhstatic void
120703b705cfSriastradhintel_limits_init(intel_screen_private *intel)
120803b705cfSriastradh{
120903b705cfSriastradh	/* Limits are described in the BLT engine chapter under Graphics Data Size
121003b705cfSriastradh	 * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO,
121103b705cfSriastradh	 * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO.
121203b705cfSriastradh	 *
121303b705cfSriastradh	 * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768.
121403b705cfSriastradh	 *
121503b705cfSriastradh	 * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled.
121603b705cfSriastradh	 * i965 limits 3D surface to 4kB-aligned offset if tiled.
121703b705cfSriastradh	 * i965 limits 3D surfaces to w,h of ?,8192.
121803b705cfSriastradh	 * i965 limits 3D surface to pitch of 1B - 128kB.
121903b705cfSriastradh	 * i965 limits 3D surface pitch alignment to 1 or 2 times the element size.
122003b705cfSriastradh	 * i965 limits 3D surface pitch alignment to 512B if tiled.
122103b705cfSriastradh	 * i965 limits 3D destination drawing rect to w,h of 8192,8192.
122203b705cfSriastradh	 *
122303b705cfSriastradh	 * i915 limits 3D textures to 4B-aligned offset if un-tiled.
122403b705cfSriastradh	 * i915 limits 3D textures to ~4kB-aligned offset if tiled.
122503b705cfSriastradh	 * i915 limits 3D textures to width,height of 2048,2048.
122603b705cfSriastradh	 * i915 limits 3D textures to pitch of 16B - 8kB, in dwords.
122703b705cfSriastradh	 * i915 limits 3D destination to ~4kB-aligned offset if tiled.
122803b705cfSriastradh	 * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled.
122903b705cfSriastradh	 * i915 limits 3D destination to pitch 64B-aligned if used with depth.
123003b705cfSriastradh	 * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled.
123103b705cfSriastradh	 * i915 limits 3D destination to POT aligned pitch if tiled.
123203b705cfSriastradh	 * i915 limits 3D destination drawing rect to w,h of 2048,2048.
123303b705cfSriastradh	 *
123403b705cfSriastradh	 * i845 limits 3D textures to 4B-aligned offset if un-tiled.
123503b705cfSriastradh	 * i845 limits 3D textures to ~4kB-aligned offset if tiled.
123603b705cfSriastradh	 * i845 limits 3D textures to width,height of 2048,2048.
123703b705cfSriastradh	 * i845 limits 3D textures to pitch of 4B - 8kB, in dwords.
123803b705cfSriastradh	 * i845 limits 3D destination to 4B-aligned offset if un-tiled.
123903b705cfSriastradh	 * i845 limits 3D destination to ~4kB-aligned offset if tiled.
124003b705cfSriastradh	 * i845 limits 3D destination to pitch of 8B - 8kB, in dwords.
124103b705cfSriastradh	 * i845 limits 3D destination drawing rect to w,h of 2048,2048.
124203b705cfSriastradh	 *
124303b705cfSriastradh	 * For the tiled issues, the only tiled buffer we draw to should be
124403b705cfSriastradh	 * the front, which will have an appropriate pitch/offset already set up,
124503b705cfSriastradh	 * so UXA doesn't need to worry.
124603b705cfSriastradh	 */
124703b705cfSriastradh	if (INTEL_INFO(intel)->gen >= 040) {
124803b705cfSriastradh		intel->accel_pixmap_offset_alignment = 4 * 2;
124903b705cfSriastradh		intel->accel_max_x = 8192;
125003b705cfSriastradh		intel->accel_max_y = 8192;
125103b705cfSriastradh	} else {
125203b705cfSriastradh		intel->accel_pixmap_offset_alignment = 4;
125303b705cfSriastradh		intel->accel_max_x = 2048;
125403b705cfSriastradh		intel->accel_max_y = 2048;
125503b705cfSriastradh	}
125603b705cfSriastradh}
125703b705cfSriastradh
125842542f5fSchristosstatic Bool intel_option_accel_none(intel_screen_private *intel)
125942542f5fSchristos{
126042542f5fSchristos	const char *s;
126142542f5fSchristos
126242542f5fSchristos	s = xf86GetOptValString(intel->Options, OPTION_ACCEL_METHOD);
126342542f5fSchristos	if (s == NULL)
126442542f5fSchristos		return IS_DEFAULT_ACCEL_METHOD(NOACCEL);
126542542f5fSchristos
126642542f5fSchristos	return strcasecmp(s, "none") == 0;
126742542f5fSchristos}
126842542f5fSchristos
126903b705cfSriastradhstatic Bool intel_option_accel_blt(intel_screen_private *intel)
127003b705cfSriastradh{
127103b705cfSriastradh	const char *s;
127203b705cfSriastradh
127303b705cfSriastradh	s = xf86GetOptValString(intel->Options, OPTION_ACCEL_METHOD);
127403b705cfSriastradh	if (s == NULL)
127503b705cfSriastradh		return FALSE;
127603b705cfSriastradh
127703b705cfSriastradh	return strcasecmp(s, "blt") == 0;
127803b705cfSriastradh}
127903b705cfSriastradh
128013496ba1Ssnj/**
128113496ba1Ssnj * Intialiazes the hardware for the 3D pipeline use in the 2D driver.
128213496ba1Ssnj *
128313496ba1Ssnj * Some state caching is performed to avoid redundant state emits.  This
128413496ba1Ssnj * function is also responsible for marking the state as clobbered for DRI
128513496ba1Ssnj * clients.
128613496ba1Ssnj */
128713496ba1Ssnjvoid IntelEmitInvarientState(ScrnInfoPtr scrn)
128813496ba1Ssnj{
128913496ba1Ssnj	intel_screen_private *intel = intel_get_screen_private(scrn);
129013496ba1Ssnj
129113496ba1Ssnj	/* If we've emitted our state since the last clobber by another client,
129213496ba1Ssnj	 * skip it.
129313496ba1Ssnj	 */
129413496ba1Ssnj	if (intel->last_3d != LAST_3D_OTHER)
129513496ba1Ssnj		return;
129613496ba1Ssnj
129713496ba1Ssnj	if (IS_GEN2(intel))
129813496ba1Ssnj		I830EmitInvarientState(scrn);
129913496ba1Ssnj	else if IS_GEN3(intel)
130013496ba1Ssnj		I915EmitInvarientState(scrn);
130113496ba1Ssnj}
130213496ba1Ssnj
130303b705cfSriastradhBool intel_uxa_init(ScreenPtr screen)
130403b705cfSriastradh{
130503b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
130603b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
130703b705cfSriastradh
130813496ba1Ssnj	intel_batch_init(scrn);
130913496ba1Ssnj
131013496ba1Ssnj	if (INTEL_INFO(intel)->gen >= 040 && INTEL_INFO(intel)->gen < 0100)
131113496ba1Ssnj		gen4_render_state_init(scrn);
131213496ba1Ssnj
131303b705cfSriastradh#if HAS_DIXREGISTERPRIVATEKEY
131403b705cfSriastradh	if (!dixRegisterPrivateKey(&uxa_pixmap_index, PRIVATE_PIXMAP, 0))
131503b705cfSriastradh#else
131603b705cfSriastradh	if (!dixRequestPrivate(&uxa_pixmap_index, 0))
131703b705cfSriastradh#endif
131803b705cfSriastradh		return FALSE;
131903b705cfSriastradh
132003b705cfSriastradh	intel_limits_init(intel);
132103b705cfSriastradh
132203b705cfSriastradh	intel->uxa_driver = uxa_driver_alloc();
132303b705cfSriastradh	if (intel->uxa_driver == NULL)
132403b705cfSriastradh		return FALSE;
132503b705cfSriastradh
132603b705cfSriastradh	memset(intel->uxa_driver, 0, sizeof(*intel->uxa_driver));
132703b705cfSriastradh
132803b705cfSriastradh	intel->uxa_driver->uxa_major = 1;
132903b705cfSriastradh	intel->uxa_driver->uxa_minor = 0;
133003b705cfSriastradh
133103b705cfSriastradh	intel->prim_offset = 0;
133203b705cfSriastradh	intel->vertex_count = 0;
133303b705cfSriastradh	intel->vertex_offset = 0;
133403b705cfSriastradh	intel->vertex_used = 0;
133503b705cfSriastradh	intel->floats_per_vertex = 0;
133603b705cfSriastradh	intel->last_floats_per_vertex = 0;
133703b705cfSriastradh	intel->vertex_bo = NULL;
133803b705cfSriastradh	intel->surface_used = 0;
133903b705cfSriastradh	intel->surface_reloc = 0;
134003b705cfSriastradh
134103b705cfSriastradh	/* Solid fill */
134203b705cfSriastradh	intel->uxa_driver->check_solid = intel_uxa_check_solid;
134303b705cfSriastradh	intel->uxa_driver->prepare_solid = intel_uxa_prepare_solid;
134403b705cfSriastradh	intel->uxa_driver->solid = intel_uxa_solid;
134503b705cfSriastradh	intel->uxa_driver->done_solid = intel_uxa_done;
134603b705cfSriastradh
134703b705cfSriastradh	/* Copy */
134803b705cfSriastradh	intel->uxa_driver->check_copy = intel_uxa_check_copy;
134903b705cfSriastradh	intel->uxa_driver->prepare_copy = intel_uxa_prepare_copy;
135003b705cfSriastradh	intel->uxa_driver->copy = intel_uxa_copy;
135103b705cfSriastradh	intel->uxa_driver->done_copy = intel_uxa_done;
135203b705cfSriastradh
135303b705cfSriastradh	/* Composite */
135403b705cfSriastradh	if (intel_option_accel_blt(intel)) {
135542542f5fSchristos	} else if (INTEL_INFO(intel)->gen < 030) {
135603b705cfSriastradh		intel->uxa_driver->check_composite = i830_check_composite;
135703b705cfSriastradh		intel->uxa_driver->check_composite_target = i830_check_composite_target;
135803b705cfSriastradh		intel->uxa_driver->check_composite_texture = i830_check_composite_texture;
135903b705cfSriastradh		intel->uxa_driver->prepare_composite = i830_prepare_composite;
136003b705cfSriastradh		intel->uxa_driver->composite = i830_composite;
136103b705cfSriastradh		intel->uxa_driver->done_composite = i830_done_composite;
136203b705cfSriastradh
136303b705cfSriastradh		intel->vertex_flush = i830_vertex_flush;
136403b705cfSriastradh		intel->batch_commit_notify = i830_batch_commit_notify;
136542542f5fSchristos	} else if (INTEL_INFO(intel)->gen < 040) {
136603b705cfSriastradh		intel->uxa_driver->check_composite = i915_check_composite;
136703b705cfSriastradh		intel->uxa_driver->check_composite_target = i915_check_composite_target;
136803b705cfSriastradh		intel->uxa_driver->check_composite_texture = i915_check_composite_texture;
136903b705cfSriastradh		intel->uxa_driver->prepare_composite = i915_prepare_composite;
137003b705cfSriastradh		intel->uxa_driver->composite = i915_composite;
137103b705cfSriastradh		intel->uxa_driver->done_composite = i830_done_composite;
137203b705cfSriastradh
137303b705cfSriastradh		intel->vertex_flush = i915_vertex_flush;
137403b705cfSriastradh		intel->batch_commit_notify = i915_batch_commit_notify;
137542542f5fSchristos	} else if (INTEL_INFO(intel)->gen < 0100) {
137603b705cfSriastradh		intel->uxa_driver->check_composite = i965_check_composite;
137703b705cfSriastradh		intel->uxa_driver->check_composite_texture = i965_check_composite_texture;
137803b705cfSriastradh		intel->uxa_driver->prepare_composite = i965_prepare_composite;
137903b705cfSriastradh		intel->uxa_driver->composite = i965_composite;
138003b705cfSriastradh		intel->uxa_driver->done_composite = i830_done_composite;
138103b705cfSriastradh
138203b705cfSriastradh		intel->vertex_flush = i965_vertex_flush;
138303b705cfSriastradh		intel->batch_flush = i965_batch_flush;
138403b705cfSriastradh		intel->batch_commit_notify = i965_batch_commit_notify;
138503b705cfSriastradh
138642542f5fSchristos		if (INTEL_INFO(intel)->gen < 050) {
138703b705cfSriastradh			intel->context_switch = gen4_context_switch;
138842542f5fSchristos		} else if (INTEL_INFO(intel)->gen < 060) {
138903b705cfSriastradh			intel->context_switch = gen5_context_switch;
139003b705cfSriastradh		} else {
139103b705cfSriastradh			intel->context_switch = gen6_context_switch;
139203b705cfSriastradh		}
139303b705cfSriastradh	}
139403b705cfSriastradh
139503b705cfSriastradh	/* PutImage */
139603b705cfSriastradh	intel->uxa_driver->put_image = intel_uxa_put_image;
139703b705cfSriastradh	intel->uxa_driver->get_image = intel_uxa_get_image;
139803b705cfSriastradh
139903b705cfSriastradh	intel->uxa_driver->prepare_access = intel_uxa_prepare_access;
140003b705cfSriastradh	intel->uxa_driver->finish_access = intel_uxa_finish_access;
140103b705cfSriastradh	intel->uxa_driver->pixmap_is_offscreen = intel_uxa_pixmap_is_offscreen;
140203b705cfSriastradh
140303b705cfSriastradh	screen->CreatePixmap = intel_uxa_create_pixmap;
140403b705cfSriastradh	screen->DestroyPixmap = intel_uxa_destroy_pixmap;
140503b705cfSriastradh
140603b705cfSriastradh#ifdef CREATE_PIXMAP_USAGE_SHARED
140703b705cfSriastradh	screen->SharePixmapBacking = intel_uxa_share_pixmap_backing;
140803b705cfSriastradh	screen->SetSharedPixmapBacking = intel_uxa_set_shared_pixmap_backing;
140903b705cfSriastradh#endif
141003b705cfSriastradh
141103b705cfSriastradh	if (!uxa_driver_init(screen, intel->uxa_driver)) {
141203b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
141303b705cfSriastradh			   "UXA initialization failed\n");
141403b705cfSriastradh		free(intel->uxa_driver);
141503b705cfSriastradh		return FALSE;
141603b705cfSriastradh	}
141703b705cfSriastradh
141842542f5fSchristos	if (intel_option_accel_none(intel))
141942542f5fSchristos		intel->force_fallback = 1;
142042542f5fSchristos
142103b705cfSriastradh	uxa_set_fallback_debug(screen, intel->fallback_debug);
142203b705cfSriastradh	uxa_set_force_fallback(screen, intel->force_fallback);
142303b705cfSriastradh
142442542f5fSchristos	intel->flush_rendering = intel_flush_rendering;
142503b705cfSriastradh	return TRUE;
142603b705cfSriastradh}
1427