intel_uxa.c revision 13496ba1
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
17903b705cfSriastradh/**
18003b705cfSriastradh * Sets up hardware state for a series of solid fills.
18103b705cfSriastradh */
18203b705cfSriastradhstatic Bool
18303b705cfSriastradhintel_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg)
18403b705cfSriastradh{
18503b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
18603b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
18703b705cfSriastradh	drm_intel_bo *bo_table[] = {
18803b705cfSriastradh		NULL,		/* batch_bo */
18913496ba1Ssnj		intel_uxa_get_pixmap_bo(pixmap),
19003b705cfSriastradh	};
19103b705cfSriastradh
19213496ba1Ssnj	if (!intel_uxa_check_pitch_2d(pixmap))
19303b705cfSriastradh		return FALSE;
19403b705cfSriastradh
19513496ba1Ssnj	if (!intel_uxa_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
19603b705cfSriastradh		return FALSE;
19703b705cfSriastradh
19803b705cfSriastradh	intel->BR[13] = (I830PatternROP[alu] & 0xff) << 16;
19903b705cfSriastradh	switch (pixmap->drawable.bitsPerPixel) {
20003b705cfSriastradh	case 8:
20103b705cfSriastradh		break;
20203b705cfSriastradh	case 16:
20303b705cfSriastradh		/* RGB565 */
20403b705cfSriastradh		intel->BR[13] |= (1 << 24);
20503b705cfSriastradh		break;
20603b705cfSriastradh	case 32:
20703b705cfSriastradh		/* RGB8888 */
20803b705cfSriastradh		intel->BR[13] |= ((1 << 24) | (1 << 25));
20903b705cfSriastradh		break;
21003b705cfSriastradh	}
21103b705cfSriastradh	intel->BR[16] = fg;
21203b705cfSriastradh
21303b705cfSriastradh	return TRUE;
21403b705cfSriastradh}
21503b705cfSriastradh
21603b705cfSriastradhstatic void intel_uxa_solid(PixmapPtr pixmap, int x1, int y1, int x2, int y2)
21703b705cfSriastradh{
21803b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
21903b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
22003b705cfSriastradh	unsigned long pitch;
22103b705cfSriastradh	uint32_t cmd;
22203b705cfSriastradh
22303b705cfSriastradh	if (x1 < 0)
22403b705cfSriastradh		x1 = 0;
22503b705cfSriastradh	if (y1 < 0)
22603b705cfSriastradh		y1 = 0;
22703b705cfSriastradh	if (x2 > pixmap->drawable.width)
22803b705cfSriastradh		x2 = pixmap->drawable.width;
22903b705cfSriastradh	if (y2 > pixmap->drawable.height)
23003b705cfSriastradh		y2 = pixmap->drawable.height;
23103b705cfSriastradh
23203b705cfSriastradh	if (x2 <= x1 || y2 <= y1)
23303b705cfSriastradh		return;
23403b705cfSriastradh
23503b705cfSriastradh	pitch = intel_pixmap_pitch(pixmap);
23603b705cfSriastradh
23703b705cfSriastradh	{
23842542f5fSchristos		int len = INTEL_INFO(intel)->gen >= 0100 ? 7 : 6;
23942542f5fSchristos		BEGIN_BATCH_BLT(len);
24003b705cfSriastradh
24142542f5fSchristos		cmd = XY_COLOR_BLT_CMD | (len - 2);
24203b705cfSriastradh
24303b705cfSriastradh		if (pixmap->drawable.bitsPerPixel == 32)
24403b705cfSriastradh			cmd |=
24503b705cfSriastradh			    XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB;
24603b705cfSriastradh
24713496ba1Ssnj		if (INTEL_INFO(intel)->gen >= 040 && intel_uxa_pixmap_tiled(pixmap)) {
24803b705cfSriastradh			assert((pitch % 512) == 0);
24903b705cfSriastradh			pitch >>= 2;
25003b705cfSriastradh			cmd |= XY_COLOR_BLT_TILED;
25103b705cfSriastradh		}
25203b705cfSriastradh
25303b705cfSriastradh		OUT_BATCH(cmd);
25403b705cfSriastradh
25503b705cfSriastradh		OUT_BATCH(intel->BR[13] | pitch);
25603b705cfSriastradh		OUT_BATCH((y1 << 16) | (x1 & 0xffff));
25703b705cfSriastradh		OUT_BATCH((y2 << 16) | (x2 & 0xffff));
25803b705cfSriastradh		OUT_RELOC_PIXMAP_FENCED(pixmap, I915_GEM_DOMAIN_RENDER,
25903b705cfSriastradh					I915_GEM_DOMAIN_RENDER, 0);
26003b705cfSriastradh		OUT_BATCH(intel->BR[16]);
26103b705cfSriastradh		ADVANCE_BATCH();
26203b705cfSriastradh	}
26303b705cfSriastradh}
26403b705cfSriastradh
26503b705cfSriastradh/**
26603b705cfSriastradh * TODO:
26703b705cfSriastradh *   - support planemask using FULL_BLT_CMD?
26803b705cfSriastradh */
26903b705cfSriastradhstatic Bool
27003b705cfSriastradhintel_uxa_check_copy(PixmapPtr source, PixmapPtr dest,
27103b705cfSriastradh		    int alu, Pixel planemask)
27203b705cfSriastradh{
27303b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen);
27403b705cfSriastradh
27503b705cfSriastradh	if (!UXA_PM_IS_SOLID(&source->drawable, planemask)) {
27613496ba1Ssnj		intel_uxa_debug_fallback(scrn, "planemask is not solid");
27703b705cfSriastradh		return FALSE;
27803b705cfSriastradh	}
27903b705cfSriastradh
28003b705cfSriastradh	if (source->drawable.bitsPerPixel != dest->drawable.bitsPerPixel) {
28113496ba1Ssnj		intel_uxa_debug_fallback(scrn, "mixed bpp copies unsupported\n");
28203b705cfSriastradh		return FALSE;
28303b705cfSriastradh	}
28403b705cfSriastradh	switch (source->drawable.bitsPerPixel) {
28503b705cfSriastradh	case 8:
28603b705cfSriastradh	case 16:
28703b705cfSriastradh	case 32:
28803b705cfSriastradh		break;
28903b705cfSriastradh	default:
29003b705cfSriastradh		return FALSE;
29103b705cfSriastradh	}
29203b705cfSriastradh
29313496ba1Ssnj	if (!intel_uxa_check_pitch_2d(source))
29403b705cfSriastradh		return FALSE;
29513496ba1Ssnj	if (!intel_uxa_check_pitch_2d(dest))
29603b705cfSriastradh		return FALSE;
29703b705cfSriastradh
29803b705cfSriastradh	return TRUE;
29903b705cfSriastradh}
30003b705cfSriastradh
30103b705cfSriastradhstatic Bool
30203b705cfSriastradhintel_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir,
30303b705cfSriastradh		      int ydir, int alu, Pixel planemask)
30403b705cfSriastradh{
30503b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen);
30603b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
30703b705cfSriastradh	drm_intel_bo *bo_table[] = {
30803b705cfSriastradh		NULL,		/* batch_bo */
30913496ba1Ssnj		intel_uxa_get_pixmap_bo(source),
31013496ba1Ssnj		intel_uxa_get_pixmap_bo(dest),
31103b705cfSriastradh	};
31203b705cfSriastradh
31313496ba1Ssnj	if (!intel_uxa_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
31403b705cfSriastradh		return FALSE;
31503b705cfSriastradh
31603b705cfSriastradh	intel->render_source = source;
31703b705cfSriastradh
31803b705cfSriastradh	intel->BR[13] = I830CopyROP[alu] << 16;
31903b705cfSriastradh	switch (source->drawable.bitsPerPixel) {
32003b705cfSriastradh	case 8:
32103b705cfSriastradh		break;
32203b705cfSriastradh	case 16:
32303b705cfSriastradh		intel->BR[13] |= (1 << 24);
32403b705cfSriastradh		break;
32503b705cfSriastradh	case 32:
32603b705cfSriastradh		intel->BR[13] |= ((1 << 25) | (1 << 24));
32703b705cfSriastradh		break;
32803b705cfSriastradh	}
32903b705cfSriastradh
33003b705cfSriastradh	return TRUE;
33103b705cfSriastradh}
33203b705cfSriastradh
33303b705cfSriastradhstatic void
33403b705cfSriastradhintel_uxa_copy(PixmapPtr dest, int src_x1, int src_y1, int dst_x1,
33503b705cfSriastradh	      int dst_y1, int w, int h)
33603b705cfSriastradh{
33703b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen);
33803b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
33903b705cfSriastradh	uint32_t cmd;
34003b705cfSriastradh	int dst_x2, dst_y2, src_x2, src_y2;
34103b705cfSriastradh	unsigned int dst_pitch, src_pitch;
34203b705cfSriastradh
34303b705cfSriastradh	dst_x2 = dst_x1 + w;
34403b705cfSriastradh	dst_y2 = dst_y1 + h;
34503b705cfSriastradh
34603b705cfSriastradh	/* XXX Fixup extents as a lamentable workaround for missing
34703b705cfSriastradh	 * source clipping in the upper layers.
34803b705cfSriastradh	 */
34903b705cfSriastradh	if (dst_x1 < 0)
35003b705cfSriastradh		src_x1 -= dst_x1, dst_x1 = 0;
35103b705cfSriastradh	if (dst_y1 < 0)
35203b705cfSriastradh		src_y1 -= dst_y1, dst_y1 = 0;
35303b705cfSriastradh	if (dst_x2 > dest->drawable.width)
35403b705cfSriastradh		dst_x2 = dest->drawable.width;
35503b705cfSriastradh	if (dst_y2 > dest->drawable.height)
35603b705cfSriastradh		dst_y2 = dest->drawable.height;
35703b705cfSriastradh
35803b705cfSriastradh	src_x2 = src_x1 + (dst_x2 - dst_x1);
35903b705cfSriastradh	src_y2 = src_y1 + (dst_y2 - dst_y1);
36003b705cfSriastradh
36103b705cfSriastradh	if (src_x1 < 0)
36203b705cfSriastradh		dst_x1 -= src_x1, src_x1 = 0;
36303b705cfSriastradh	if (src_y1 < 0)
36403b705cfSriastradh		dst_y1 -= src_y1, src_y1 = 0;
36503b705cfSriastradh	if (src_x2 > intel->render_source->drawable.width)
36603b705cfSriastradh		dst_x2 -= src_x2 - intel->render_source->drawable.width;
36703b705cfSriastradh	if (src_y2 > intel->render_source->drawable.height)
36803b705cfSriastradh		dst_y2 -= src_y2 - intel->render_source->drawable.height;
36903b705cfSriastradh
37003b705cfSriastradh	if (dst_x2 <= dst_x1 || dst_y2 <= dst_y1)
37103b705cfSriastradh		return;
37203b705cfSriastradh
37303b705cfSriastradh	dst_pitch = intel_pixmap_pitch(dest);
37403b705cfSriastradh	src_pitch = intel_pixmap_pitch(intel->render_source);
37503b705cfSriastradh
37603b705cfSriastradh	{
37742542f5fSchristos		int len = INTEL_INFO(intel)->gen >= 0100 ? 10 : 8;
37842542f5fSchristos		BEGIN_BATCH_BLT(len);
37903b705cfSriastradh
38042542f5fSchristos		cmd = XY_SRC_COPY_BLT_CMD | (len - 2);
38103b705cfSriastradh
38203b705cfSriastradh		if (dest->drawable.bitsPerPixel == 32)
38303b705cfSriastradh			cmd |=
38403b705cfSriastradh			    XY_SRC_COPY_BLT_WRITE_ALPHA |
38503b705cfSriastradh			    XY_SRC_COPY_BLT_WRITE_RGB;
38603b705cfSriastradh
38703b705cfSriastradh		if (INTEL_INFO(intel)->gen >= 040) {
38813496ba1Ssnj			if (intel_uxa_pixmap_tiled(dest)) {
38903b705cfSriastradh				assert((dst_pitch % 512) == 0);
39003b705cfSriastradh				dst_pitch >>= 2;
39103b705cfSriastradh				cmd |= XY_SRC_COPY_BLT_DST_TILED;
39203b705cfSriastradh			}
39303b705cfSriastradh
39413496ba1Ssnj			if (intel_uxa_pixmap_tiled(intel->render_source)) {
39503b705cfSriastradh				assert((src_pitch % 512) == 0);
39603b705cfSriastradh				src_pitch >>= 2;
39703b705cfSriastradh				cmd |= XY_SRC_COPY_BLT_SRC_TILED;
39803b705cfSriastradh			}
39903b705cfSriastradh		}
40003b705cfSriastradh
40103b705cfSriastradh		OUT_BATCH(cmd);
40203b705cfSriastradh
40303b705cfSriastradh		OUT_BATCH(intel->BR[13] | dst_pitch);
40403b705cfSriastradh		OUT_BATCH((dst_y1 << 16) | (dst_x1 & 0xffff));
40503b705cfSriastradh		OUT_BATCH((dst_y2 << 16) | (dst_x2 & 0xffff));
40603b705cfSriastradh		OUT_RELOC_PIXMAP_FENCED(dest,
40703b705cfSriastradh					I915_GEM_DOMAIN_RENDER,
40803b705cfSriastradh					I915_GEM_DOMAIN_RENDER,
40903b705cfSriastradh					0);
41003b705cfSriastradh		OUT_BATCH((src_y1 << 16) | (src_x1 & 0xffff));
41103b705cfSriastradh		OUT_BATCH(src_pitch);
41203b705cfSriastradh		OUT_RELOC_PIXMAP_FENCED(intel->render_source,
41303b705cfSriastradh					I915_GEM_DOMAIN_RENDER, 0,
41403b705cfSriastradh					0);
41503b705cfSriastradh
41603b705cfSriastradh		ADVANCE_BATCH();
41703b705cfSriastradh	}
41803b705cfSriastradh}
41903b705cfSriastradh
42003b705cfSriastradhstatic void intel_uxa_done(PixmapPtr pixmap)
42103b705cfSriastradh{
42203b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
42303b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
42403b705cfSriastradh
42542542f5fSchristos	if (INTEL_INFO(intel)->gen >= 060) {
42603b705cfSriastradh		/* workaround a random BLT hang */
42703b705cfSriastradh		BEGIN_BATCH_BLT(3);
42842542f5fSchristos		OUT_BATCH(XY_SETUP_CLIP_BLT_CMD | (3 - 2));
42903b705cfSriastradh		OUT_BATCH(0);
43003b705cfSriastradh		OUT_BATCH(0);
43103b705cfSriastradh		ADVANCE_BATCH();
43203b705cfSriastradh	}
43303b705cfSriastradh
43413496ba1Ssnj	intel_uxa_debug_flush(scrn);
43503b705cfSriastradh}
43603b705cfSriastradh
43703b705cfSriastradh/**
43803b705cfSriastradh * Do any cleanup from the Composite operation.
43903b705cfSriastradh *
44003b705cfSriastradh * This is shared between i830 through i965.
44103b705cfSriastradh */
44203b705cfSriastradhstatic void i830_done_composite(PixmapPtr dest)
44303b705cfSriastradh{
44403b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen);
44503b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
44603b705cfSriastradh
44703b705cfSriastradh	if (intel->vertex_flush)
44803b705cfSriastradh		intel->vertex_flush(intel);
44903b705cfSriastradh
45013496ba1Ssnj	intel_uxa_debug_flush(scrn);
45103b705cfSriastradh}
45203b705cfSriastradh
45303b705cfSriastradh#define xFixedToFloat(val) \
45403b705cfSriastradh	((float)xFixedToInt(val) + ((float)xFixedFrac(val) / 65536.0))
45503b705cfSriastradh
45603b705cfSriastradhstatic Bool
45703b705cfSriastradh_intel_transform_point(PictTransformPtr transform,
45803b705cfSriastradh		       float x, float y, float result[3])
45903b705cfSriastradh{
46003b705cfSriastradh	int j;
46103b705cfSriastradh
46203b705cfSriastradh	for (j = 0; j < 3; j++) {
46303b705cfSriastradh		result[j] = (xFixedToFloat(transform->matrix[j][0]) * x +
46403b705cfSriastradh			     xFixedToFloat(transform->matrix[j][1]) * y +
46503b705cfSriastradh			     xFixedToFloat(transform->matrix[j][2]));
46603b705cfSriastradh	}
46703b705cfSriastradh	if (!result[2])
46803b705cfSriastradh		return FALSE;
46903b705cfSriastradh	return TRUE;
47003b705cfSriastradh}
47103b705cfSriastradh
47203b705cfSriastradh/**
47303b705cfSriastradh * Returns the floating-point coordinates transformed by the given transform.
47403b705cfSriastradh *
47503b705cfSriastradh * transform may be null.
47603b705cfSriastradh */
47703b705cfSriastradhBool
47813496ba1Ssnjintel_uxa_get_transformed_coordinates(int x, int y, PictTransformPtr transform,
47903b705cfSriastradh				  float *x_out, float *y_out)
48003b705cfSriastradh{
48103b705cfSriastradh	if (transform == NULL) {
48203b705cfSriastradh		*x_out = x;
48303b705cfSriastradh		*y_out = y;
48403b705cfSriastradh	} else {
48503b705cfSriastradh		float result[3];
48603b705cfSriastradh
48703b705cfSriastradh		if (!_intel_transform_point(transform,
48803b705cfSriastradh					    x, y,
48903b705cfSriastradh					    result))
49003b705cfSriastradh			return FALSE;
49103b705cfSriastradh		*x_out = result[0] / result[2];
49203b705cfSriastradh		*y_out = result[1] / result[2];
49303b705cfSriastradh	}
49403b705cfSriastradh	return TRUE;
49503b705cfSriastradh}
49603b705cfSriastradh
49703b705cfSriastradh/**
49803b705cfSriastradh * Returns the un-normalized floating-point coordinates transformed by the given transform.
49903b705cfSriastradh *
50003b705cfSriastradh * transform may be null.
50103b705cfSriastradh */
50203b705cfSriastradhBool
50313496ba1Ssnjintel_uxa_get_transformed_coordinates_3d(int x, int y, PictTransformPtr transform,
50403b705cfSriastradh				     float *x_out, float *y_out, float *w_out)
50503b705cfSriastradh{
50603b705cfSriastradh	if (transform == NULL) {
50703b705cfSriastradh		*x_out = x;
50803b705cfSriastradh		*y_out = y;
50903b705cfSriastradh		*w_out = 1;
51003b705cfSriastradh	} else {
51103b705cfSriastradh		float result[3];
51203b705cfSriastradh
51303b705cfSriastradh		if (!_intel_transform_point(transform,
51403b705cfSriastradh					    x, y,
51503b705cfSriastradh					    result))
51603b705cfSriastradh			return FALSE;
51703b705cfSriastradh		*x_out = result[0];
51803b705cfSriastradh		*y_out = result[1];
51903b705cfSriastradh		*w_out = result[2];
52003b705cfSriastradh	}
52103b705cfSriastradh	return TRUE;
52203b705cfSriastradh}
52303b705cfSriastradh
52403b705cfSriastradh/**
52503b705cfSriastradh * Returns whether the provided transform is affine.
52603b705cfSriastradh *
52703b705cfSriastradh * transform may be null.
52803b705cfSriastradh */
52913496ba1SsnjBool intel_uxa_transform_is_affine(PictTransformPtr t)
53003b705cfSriastradh{
53103b705cfSriastradh	if (t == NULL)
53203b705cfSriastradh		return TRUE;
53303b705cfSriastradh	return t->matrix[2][0] == 0 && t->matrix[2][1] == 0;
53403b705cfSriastradh}
53503b705cfSriastradh
53613496ba1Ssnjdri_bo *intel_uxa_get_pixmap_bo(PixmapPtr pixmap)
53703b705cfSriastradh{
53813496ba1Ssnj	struct intel_uxa_pixmap *intel;
53903b705cfSriastradh
54013496ba1Ssnj	intel = intel_uxa_get_pixmap_private(pixmap);
54103b705cfSriastradh	if (intel == NULL)
54203b705cfSriastradh		return NULL;
54303b705cfSriastradh
54403b705cfSriastradh	return intel->bo;
54503b705cfSriastradh}
54603b705cfSriastradh
54742542f5fSchristosstatic unsigned intel_get_tile_width(intel_screen_private *intel, int tiling, int pitch)
54842542f5fSchristos{
54942542f5fSchristos	unsigned long tile_width;
55042542f5fSchristos
55142542f5fSchristos	if (tiling == I915_TILING_NONE)
55242542f5fSchristos		return 4;
55342542f5fSchristos
55442542f5fSchristos	tile_width = (tiling == I915_TILING_Y) ? 128 : 512;
55542542f5fSchristos	if (INTEL_INFO(intel)->gen >= 040)
55642542f5fSchristos		return tile_width;
55742542f5fSchristos
55842542f5fSchristos	while (tile_width < pitch)
55942542f5fSchristos		tile_width <<= 1;
56042542f5fSchristos
56142542f5fSchristos	return tile_width;
56242542f5fSchristos}
56342542f5fSchristos
56413496ba1Ssnjvoid intel_uxa_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo)
56503b705cfSriastradh{
56642542f5fSchristos	ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
56742542f5fSchristos	intel_screen_private *intel = intel_get_screen_private(scrn);
56813496ba1Ssnj	struct intel_uxa_pixmap *priv;
56903b705cfSriastradh
57013496ba1Ssnj	priv = intel_uxa_get_pixmap_private(pixmap);
57103b705cfSriastradh	if (priv == NULL && bo == NULL)
57242542f5fSchristos		return;
57303b705cfSriastradh
57403b705cfSriastradh	if (priv != NULL) {
57503b705cfSriastradh		if (priv->bo == bo)
57603b705cfSriastradh			return;
57703b705cfSriastradh
57842542f5fSchristosfree_priv:
57903b705cfSriastradh		dri_bo_unreference(priv->bo);
58003b705cfSriastradh		list_del(&priv->batch);
58103b705cfSriastradh
58203b705cfSriastradh		free(priv);
58303b705cfSriastradh		priv = NULL;
58403b705cfSriastradh	}
58503b705cfSriastradh
58603b705cfSriastradh	if (bo != NULL) {
58742542f5fSchristos		uint32_t tiling, swizzle_mode;
58842542f5fSchristos		unsigned tile_width;
58942542f5fSchristos		int size, stride;
59003b705cfSriastradh
59113496ba1Ssnj		priv = calloc(1, sizeof (struct intel_uxa_pixmap));
59203b705cfSriastradh		if (priv == NULL)
59303b705cfSriastradh			goto BAIL;
59403b705cfSriastradh
59503b705cfSriastradh		list_init(&priv->batch);
59603b705cfSriastradh
59703b705cfSriastradh		dri_bo_reference(bo);
59803b705cfSriastradh		priv->bo = bo;
59903b705cfSriastradh
60042542f5fSchristos		if (drm_intel_bo_get_tiling(bo, &tiling, &swizzle_mode)) {
60142542f5fSchristos			bo = NULL;
60242542f5fSchristos			goto free_priv;
60303b705cfSriastradh		}
60403b705cfSriastradh
60503b705cfSriastradh		priv->tiling = tiling;
60603b705cfSriastradh		priv->busy = -1;
60703b705cfSriastradh		priv->offscreen = 1;
60842542f5fSchristos
60942542f5fSchristos		stride = (pixmap->drawable.width * pixmap->drawable.bitsPerPixel + 7) / 8;
61042542f5fSchristos		tile_width = intel_get_tile_width(intel, tiling, stride);
61142542f5fSchristos		stride = ALIGN(stride, tile_width);
61242542f5fSchristos
61313496ba1Ssnj		if (intel_pixmap_pitch(pixmap) < stride ||
61413496ba1Ssnj		    intel_pixmap_pitch(pixmap) & (tile_width - 1) ||
61513496ba1Ssnj		    intel_pixmap_pitch(pixmap) >= KB(32)) {
61642542f5fSchristos			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
61742542f5fSchristos				   "%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",
61813496ba1Ssnj				   __FUNCTION__, intel_pixmap_pitch(pixmap), stride, KB(32), tile_width);
61942542f5fSchristos			bo = NULL;
62042542f5fSchristos			goto free_priv;
62142542f5fSchristos		}
62242542f5fSchristos
62342542f5fSchristos		if (tiling != I915_TILING_NONE) {
62442542f5fSchristos			int height;
62542542f5fSchristos
62642542f5fSchristos			if (IS_GEN2(intel))
62742542f5fSchristos				height = 16;
62842542f5fSchristos			else if (tiling == I915_TILING_X)
62942542f5fSchristos				height = 8;
63042542f5fSchristos			else
63142542f5fSchristos				height = 32;
63242542f5fSchristos
63313496ba1Ssnj			height = ALIGN(pixmap->drawable.height, height);
63413496ba1Ssnj			size = intel_get_fence_size(intel, intel_pixmap_pitch(pixmap) * height);
63542542f5fSchristos		} else
63613496ba1Ssnj			size = intel_pixmap_pitch(pixmap) * pixmap->drawable.height;
63742542f5fSchristos
63842542f5fSchristos		if (bo->size < size || bo->size > intel->max_bo_size) {
63942542f5fSchristos			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
64042542f5fSchristos				   "%s: size of buffer object does not match constraints: size=%ld, must be greater than %d, but less than %d\n",
64142542f5fSchristos				   __FUNCTION__, (long)bo->size, size, intel->max_bo_size);
64242542f5fSchristos			bo = NULL;
64342542f5fSchristos			goto free_priv;
64442542f5fSchristos		}
64503b705cfSriastradh	}
64603b705cfSriastradh
64703b705cfSriastradh  BAIL:
64813496ba1Ssnj	intel_uxa_set_pixmap_private(pixmap, priv);
64903b705cfSriastradh}
65003b705cfSriastradh
65103b705cfSriastradhstatic Bool intel_uxa_prepare_access(PixmapPtr pixmap, uxa_access_t access)
65203b705cfSriastradh{
65303b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
65403b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
65513496ba1Ssnj	struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap);
65603b705cfSriastradh	dri_bo *bo = priv->bo;
65703b705cfSriastradh	int ret;
65803b705cfSriastradh
65903b705cfSriastradh	/* When falling back to swrast, flush all pending operations */
66003b705cfSriastradh	if (access == UXA_ACCESS_RW || priv->dirty)
66103b705cfSriastradh		intel_batch_submit(scrn);
66203b705cfSriastradh
66303b705cfSriastradh	assert(bo->size <= intel->max_gtt_map_size);
66403b705cfSriastradh	ret = drm_intel_gem_bo_map_gtt(bo);
66503b705cfSriastradh	if (ret) {
66603b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
66703b705cfSriastradh			   "%s: bo map (use gtt? %d, access %d) failed: %s\n",
66803b705cfSriastradh			   __FUNCTION__,
66903b705cfSriastradh			   priv->tiling || bo->size <= intel->max_gtt_map_size,
67003b705cfSriastradh			   access,
67103b705cfSriastradh			   strerror(-ret));
67203b705cfSriastradh		return FALSE;
67303b705cfSriastradh	}
67403b705cfSriastradh
67503b705cfSriastradh	pixmap->devPrivate.ptr = bo->virtual;
67603b705cfSriastradh	priv->busy = 0;
67703b705cfSriastradh
67803b705cfSriastradh	return TRUE;
67903b705cfSriastradh}
68003b705cfSriastradh
68103b705cfSriastradhstatic void intel_uxa_finish_access(PixmapPtr pixmap, uxa_access_t access)
68203b705cfSriastradh{
68313496ba1Ssnj	struct intel_uxa_pixmap *priv;
68403b705cfSriastradh
68513496ba1Ssnj	priv = intel_uxa_get_pixmap_private(pixmap);
68603b705cfSriastradh	if (priv == NULL)
68703b705cfSriastradh		return;
68803b705cfSriastradh
68903b705cfSriastradh	drm_intel_gem_bo_unmap_gtt(priv->bo);
69003b705cfSriastradh	pixmap->devPrivate.ptr = NULL;
69103b705cfSriastradh}
69203b705cfSriastradh
69303b705cfSriastradhstatic Bool intel_uxa_pixmap_put_image(PixmapPtr pixmap,
69403b705cfSriastradh				       char *src, int src_pitch,
69503b705cfSriastradh				       int x, int y, int w, int h)
69603b705cfSriastradh{
69713496ba1Ssnj	struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap);
69803b705cfSriastradh	int stride = intel_pixmap_pitch(pixmap);
69903b705cfSriastradh	int cpp = pixmap->drawable.bitsPerPixel/8;
70003b705cfSriastradh	int ret = FALSE;
70103b705cfSriastradh
70203b705cfSriastradh	if (priv == NULL || priv->bo == NULL)
70303b705cfSriastradh		return FALSE;
70403b705cfSriastradh
70503b705cfSriastradh	if (priv->tiling == I915_TILING_NONE &&
70603b705cfSriastradh	    (h == 1 || (src_pitch == stride && w == pixmap->drawable.width))) {
70703b705cfSriastradh		return drm_intel_bo_subdata(priv->bo, y*stride + x*cpp, stride*(h-1) + w*cpp, src) == 0;
70803b705cfSriastradh	} else if (drm_intel_gem_bo_map_gtt(priv->bo) == 0) {
70903b705cfSriastradh		char *dst = priv->bo->virtual;
71003b705cfSriastradh		int row_length = w * cpp;
71103b705cfSriastradh		int num_rows = h;
71203b705cfSriastradh		if (row_length == src_pitch && src_pitch == stride)
71303b705cfSriastradh			num_rows = 1, row_length *= h;
71403b705cfSriastradh		dst += y * stride + x * cpp;
71503b705cfSriastradh		do {
71603b705cfSriastradh			memcpy (dst, src, row_length);
71703b705cfSriastradh			src += src_pitch;
71803b705cfSriastradh			dst += stride;
71903b705cfSriastradh		} while (--num_rows);
72003b705cfSriastradh		drm_intel_gem_bo_unmap_gtt(priv->bo);
72103b705cfSriastradh		ret = TRUE;
72203b705cfSriastradh	}
72303b705cfSriastradh
72403b705cfSriastradh	return ret;
72503b705cfSriastradh}
72603b705cfSriastradh
72703b705cfSriastradhstatic Bool intel_uxa_put_image(PixmapPtr pixmap,
72803b705cfSriastradh				int x, int y,
72903b705cfSriastradh				int w, int h,
73003b705cfSriastradh				char *src, int src_pitch)
73103b705cfSriastradh{
73213496ba1Ssnj	struct intel_uxa_pixmap *priv;
73303b705cfSriastradh
73413496ba1Ssnj	priv = intel_uxa_get_pixmap_private(pixmap);
73513496ba1Ssnj	if (!intel_uxa_pixmap_is_busy(priv)) {
73603b705cfSriastradh		/* bo is not busy so can be replaced without a stall, upload in-place. */
73703b705cfSriastradh		return intel_uxa_pixmap_put_image(pixmap, src, src_pitch, x, y, w, h);
73803b705cfSriastradh	} else {
73903b705cfSriastradh		ScreenPtr screen = pixmap->drawable.pScreen;
74003b705cfSriastradh
74103b705cfSriastradh		if (!priv->pinned &&
74203b705cfSriastradh		    x == 0 && y == 0 &&
74303b705cfSriastradh		    w == pixmap->drawable.width &&
74403b705cfSriastradh		    h == pixmap->drawable.height)
74503b705cfSriastradh		{
74603b705cfSriastradh			intel_screen_private *intel = intel_get_screen_private(xf86ScreenToScrn(screen));
74703b705cfSriastradh			uint32_t tiling = priv->tiling;
74803b705cfSriastradh			int size, stride;
74903b705cfSriastradh			dri_bo *bo;
75003b705cfSriastradh
75103b705cfSriastradh			/* Replace busy bo. */
75213496ba1Ssnj			size = intel_compute_size(intel,
75313496ba1Ssnj                                                  w, h,
75413496ba1Ssnj                                                  pixmap->drawable.bitsPerPixel, pixmap->usage_hint,
75513496ba1Ssnj                                                  &tiling, &stride);
75603b705cfSriastradh			if (size > intel->max_gtt_map_size)
75703b705cfSriastradh				return FALSE;
75803b705cfSriastradh
75903b705cfSriastradh			bo = drm_intel_bo_alloc(intel->bufmgr, "pixmap", size, 0);
76003b705cfSriastradh			if (bo == NULL)
76103b705cfSriastradh				return FALSE;
76203b705cfSriastradh
76303b705cfSriastradh			if (tiling != I915_TILING_NONE)
76403b705cfSriastradh				drm_intel_bo_set_tiling(bo, &tiling, stride);
76503b705cfSriastradh			priv->tiling = tiling;
76603b705cfSriastradh
76703b705cfSriastradh			screen->ModifyPixmapHeader(pixmap,
76803b705cfSriastradh						   w, h,
76903b705cfSriastradh						   0, 0,
77003b705cfSriastradh						   stride, NULL);
77113496ba1Ssnj			intel_uxa_set_pixmap_bo(pixmap, bo);
77203b705cfSriastradh			dri_bo_unreference(bo);
77303b705cfSriastradh
77403b705cfSriastradh			return intel_uxa_pixmap_put_image(pixmap, src, src_pitch, 0, 0, w, h);
77503b705cfSriastradh		}
77603b705cfSriastradh		else
77703b705cfSriastradh		{
77803b705cfSriastradh			PixmapPtr scratch;
77903b705cfSriastradh			Bool ret;
78003b705cfSriastradh
78103b705cfSriastradh			/* Upload to a linear buffer and queue a blit.  */
78203b705cfSriastradh			scratch = (*screen->CreatePixmap)(screen, w, h,
78303b705cfSriastradh							  pixmap->drawable.depth,
78403b705cfSriastradh							  UXA_CREATE_PIXMAP_FOR_MAP);
78503b705cfSriastradh			if (!scratch)
78603b705cfSriastradh				return FALSE;
78703b705cfSriastradh
78803b705cfSriastradh			if (!intel_uxa_pixmap_is_offscreen(scratch)) {
78903b705cfSriastradh				screen->DestroyPixmap(scratch);
79003b705cfSriastradh				return FALSE;
79103b705cfSriastradh			}
79203b705cfSriastradh
79303b705cfSriastradh			ret = intel_uxa_pixmap_put_image(scratch, src, src_pitch, 0, 0, w, h);
79403b705cfSriastradh			if (ret) {
79503b705cfSriastradh				GCPtr gc = GetScratchGC(pixmap->drawable.depth, screen);
79603b705cfSriastradh				if (gc) {
79703b705cfSriastradh					ValidateGC(&pixmap->drawable, gc);
79803b705cfSriastradh
79903b705cfSriastradh					(*gc->ops->CopyArea)(&scratch->drawable,
80003b705cfSriastradh							     &pixmap->drawable,
80103b705cfSriastradh							     gc, 0, 0, w, h, x, y);
80203b705cfSriastradh
80303b705cfSriastradh					FreeScratchGC(gc);
80403b705cfSriastradh				} else
80503b705cfSriastradh					ret = FALSE;
80603b705cfSriastradh			}
80703b705cfSriastradh
80803b705cfSriastradh			(*screen->DestroyPixmap)(scratch);
80903b705cfSriastradh			return ret;
81003b705cfSriastradh		}
81103b705cfSriastradh	}
81203b705cfSriastradh}
81303b705cfSriastradh
81403b705cfSriastradhstatic Bool intel_uxa_pixmap_get_image(PixmapPtr pixmap,
81503b705cfSriastradh				       int x, int y, int w, int h,
81603b705cfSriastradh				       char *dst, int dst_pitch)
81703b705cfSriastradh{
81813496ba1Ssnj	struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap);
81903b705cfSriastradh	int stride = intel_pixmap_pitch(pixmap);
82003b705cfSriastradh	int cpp = pixmap->drawable.bitsPerPixel/8;
82103b705cfSriastradh
82203b705cfSriastradh	/* assert(priv->tiling == I915_TILING_NONE); */
82303b705cfSriastradh	if (h == 1 || (dst_pitch == stride && w == pixmap->drawable.width)) {
82403b705cfSriastradh		return drm_intel_bo_get_subdata(priv->bo, y*stride + x*cpp, (h-1)*stride + w*cpp, dst) == 0;
82503b705cfSriastradh	} else {
82603b705cfSriastradh		char *src;
82703b705cfSriastradh
82803b705cfSriastradh		if (drm_intel_gem_bo_map_gtt(priv->bo))
82903b705cfSriastradh		    return FALSE;
83003b705cfSriastradh
83103b705cfSriastradh		src = (char *) priv->bo->virtual + y * stride + x * cpp;
83203b705cfSriastradh		w *= cpp;
83303b705cfSriastradh		do {
83403b705cfSriastradh			memcpy(dst, src, w);
83503b705cfSriastradh			src += stride;
83603b705cfSriastradh			dst += dst_pitch;
83703b705cfSriastradh		} while (--h);
83803b705cfSriastradh
83903b705cfSriastradh		drm_intel_gem_bo_unmap_gtt(priv->bo);
84003b705cfSriastradh
84103b705cfSriastradh		return TRUE;
84203b705cfSriastradh	}
84303b705cfSriastradh}
84403b705cfSriastradh
84503b705cfSriastradhstatic Bool intel_uxa_get_image(PixmapPtr pixmap,
84603b705cfSriastradh				int x, int y,
84703b705cfSriastradh				int w, int h,
84803b705cfSriastradh				char *dst, int dst_pitch)
84903b705cfSriastradh{
85013496ba1Ssnj	struct intel_uxa_pixmap *priv;
85103b705cfSriastradh	PixmapPtr scratch = NULL;
85203b705cfSriastradh	Bool ret;
85303b705cfSriastradh
85403b705cfSriastradh	/* The presumption is that we wish to keep the target hot, so
85503b705cfSriastradh	 * copy to a new bo and move that to the CPU in preference to
85603b705cfSriastradh	 * causing ping-pong of the original.
85703b705cfSriastradh	 *
85803b705cfSriastradh	 * Also the gpu is much faster at detiling.
85903b705cfSriastradh	 */
86003b705cfSriastradh
86113496ba1Ssnj	priv = intel_uxa_get_pixmap_private(pixmap);
86213496ba1Ssnj	if (intel_uxa_pixmap_is_busy(priv) || priv->tiling != I915_TILING_NONE) {
86303b705cfSriastradh		ScreenPtr screen = pixmap->drawable.pScreen;
86403b705cfSriastradh		GCPtr gc;
86503b705cfSriastradh
86603b705cfSriastradh		/* Copy to a linear buffer and pull.  */
86703b705cfSriastradh		scratch = screen->CreatePixmap(screen, w, h,
86803b705cfSriastradh					       pixmap->drawable.depth,
86903b705cfSriastradh					       INTEL_CREATE_PIXMAP_TILING_NONE);
87003b705cfSriastradh		if (!scratch)
87103b705cfSriastradh			return FALSE;
87203b705cfSriastradh
87303b705cfSriastradh		if (!intel_uxa_pixmap_is_offscreen(scratch)) {
87403b705cfSriastradh			screen->DestroyPixmap(scratch);
87503b705cfSriastradh			return FALSE;
87603b705cfSriastradh		}
87703b705cfSriastradh
87803b705cfSriastradh		gc = GetScratchGC(pixmap->drawable.depth, screen);
87903b705cfSriastradh		if (!gc) {
88003b705cfSriastradh			screen->DestroyPixmap(scratch);
88103b705cfSriastradh			return FALSE;
88203b705cfSriastradh		}
88303b705cfSriastradh
88403b705cfSriastradh		ValidateGC(&pixmap->drawable, gc);
88503b705cfSriastradh
88603b705cfSriastradh		gc->ops->CopyArea(&pixmap->drawable,
88703b705cfSriastradh				  &scratch->drawable,
88803b705cfSriastradh				  gc, x, y, w, h, 0, 0);
88903b705cfSriastradh
89003b705cfSriastradh		FreeScratchGC(gc);
89103b705cfSriastradh
89203b705cfSriastradh		intel_batch_submit(xf86ScreenToScrn(screen));
89303b705cfSriastradh
89403b705cfSriastradh		x = y = 0;
89503b705cfSriastradh		pixmap = scratch;
89603b705cfSriastradh	}
89703b705cfSriastradh
89803b705cfSriastradh	ret = intel_uxa_pixmap_get_image(pixmap, x, y, w, h, dst, dst_pitch);
89903b705cfSriastradh
90003b705cfSriastradh	if (scratch)
90103b705cfSriastradh		scratch->drawable.pScreen->DestroyPixmap(scratch);
90203b705cfSriastradh
90303b705cfSriastradh	return ret;
90403b705cfSriastradh}
90503b705cfSriastradh
90603b705cfSriastradhstatic CARD32 intel_cache_expire(OsTimerPtr timer, CARD32 now, pointer data)
90703b705cfSriastradh{
90803b705cfSriastradh	intel_screen_private *intel = data;
90903b705cfSriastradh
91003b705cfSriastradh	/* We just want to create and destroy a bo as this causes libdrm
91103b705cfSriastradh	 * to reap its caches. However, since we can't remove that buffer
91203b705cfSriastradh	 * from the cache due to its own activity, we want to use something
91303b705cfSriastradh	 * that we know we will reuse later. The most frequently reused buffer
91403b705cfSriastradh	 * we have is the batchbuffer, and the best way to trigger its
91503b705cfSriastradh	 * reallocation is to submit a flush.
91603b705cfSriastradh	 */
91703b705cfSriastradh	intel_batch_emit_flush(intel->scrn);
91803b705cfSriastradh	intel_batch_submit(intel->scrn);
91903b705cfSriastradh
92003b705cfSriastradh	return 0;
92103b705cfSriastradh}
92203b705cfSriastradh
92303b705cfSriastradhstatic void intel_flush_rendering(intel_screen_private *intel)
92403b705cfSriastradh{
92503b705cfSriastradh	if (intel->needs_flush == 0)
92603b705cfSriastradh		return;
92703b705cfSriastradh
92803b705cfSriastradh	if (intel->has_kernel_flush) {
92903b705cfSriastradh		intel_batch_submit(intel->scrn);
93003b705cfSriastradh		drm_intel_bo_busy(intel->front_buffer);
93103b705cfSriastradh	} else {
93203b705cfSriastradh		intel_batch_emit_flush(intel->scrn);
93303b705cfSriastradh		intel_batch_submit(intel->scrn);
93403b705cfSriastradh	}
93503b705cfSriastradh
93603b705cfSriastradh	intel->cache_expire = TimerSet(intel->cache_expire, 0, 3000,
93703b705cfSriastradh				       intel_cache_expire, intel);
93803b705cfSriastradh
93903b705cfSriastradh	intel->needs_flush = 0;
94003b705cfSriastradh}
94103b705cfSriastradh
94203b705cfSriastradhstatic void intel_throttle(intel_screen_private *intel)
94303b705cfSriastradh{
94403b705cfSriastradh	drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE);
94503b705cfSriastradh}
94603b705cfSriastradh
94703b705cfSriastradhvoid intel_uxa_block_handler(intel_screen_private *intel)
94803b705cfSriastradh{
94903b705cfSriastradh	/* Emit a flush of the rendering cache, or on the 965
95003b705cfSriastradh	 * and beyond rendering results may not hit the
95103b705cfSriastradh	 * framebuffer until significantly later.
95203b705cfSriastradh	 */
95303b705cfSriastradh	intel_flush_rendering(intel);
95403b705cfSriastradh	intel_throttle(intel);
95503b705cfSriastradh}
95603b705cfSriastradh
95703b705cfSriastradhstatic PixmapPtr
95803b705cfSriastradhintel_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth,
95903b705cfSriastradh			unsigned usage)
96003b705cfSriastradh{
96103b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
96203b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
96313496ba1Ssnj	struct intel_uxa_pixmap *priv;
96403b705cfSriastradh	PixmapPtr pixmap, new_pixmap = NULL;
96503b705cfSriastradh
96603b705cfSriastradh	if (w > 32767 || h > 32767)
96703b705cfSriastradh		return NullPixmap;
96803b705cfSriastradh
96903b705cfSriastradh	if (depth == 1 || intel->force_fallback)
97003b705cfSriastradh		return fbCreatePixmap(screen, w, h, depth, usage);
97103b705cfSriastradh
97203b705cfSriastradh	if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 32 && h <= 32)
97303b705cfSriastradh		return fbCreatePixmap(screen, w, h, depth, usage);
97403b705cfSriastradh
97503b705cfSriastradh	pixmap = fbCreatePixmap(screen, 0, 0, depth, usage);
97603b705cfSriastradh	if (pixmap == NullPixmap)
97703b705cfSriastradh		return pixmap;
97803b705cfSriastradh
97903b705cfSriastradh	if (w && h) {
98003b705cfSriastradh		unsigned int size, tiling;
98103b705cfSriastradh		int stride;
98203b705cfSriastradh
98303b705cfSriastradh		/* Always attempt to tile, compute_size() will remove the
98403b705cfSriastradh		 * tiling for pixmaps that are either too large or too small
98503b705cfSriastradh		 * to be effectively tiled.
98603b705cfSriastradh		 */
98703b705cfSriastradh		tiling = I915_TILING_X;
98803b705cfSriastradh		if (usage & INTEL_CREATE_PIXMAP_TILING_Y)
98903b705cfSriastradh			tiling = I915_TILING_Y;
99003b705cfSriastradh		if (usage == UXA_CREATE_PIXMAP_FOR_MAP || usage & INTEL_CREATE_PIXMAP_TILING_NONE)
99103b705cfSriastradh			tiling = I915_TILING_NONE;
99203b705cfSriastradh
99303b705cfSriastradh#ifdef CREATE_PIXMAP_USAGE_SHARED
99403b705cfSriastradh		if (usage == CREATE_PIXMAP_USAGE_SHARED)
99503b705cfSriastradh			tiling = I915_TILING_NONE;
99603b705cfSriastradh#endif
99703b705cfSriastradh		/* if tiling is off force to none */
99803b705cfSriastradh		if (!intel->tiling)
99903b705cfSriastradh			tiling = I915_TILING_NONE;
100003b705cfSriastradh
100103b705cfSriastradh		if (tiling != I915_TILING_NONE && !(usage & INTEL_CREATE_PIXMAP_DRI2)) {
100203b705cfSriastradh		    if (h <= 4)
100303b705cfSriastradh			tiling = I915_TILING_NONE;
100403b705cfSriastradh		    if (h <= 16 && tiling == I915_TILING_Y)
100503b705cfSriastradh			tiling = I915_TILING_X;
100603b705cfSriastradh		}
100713496ba1Ssnj		size = intel_compute_size(intel,
100813496ba1Ssnj                                          w, h, pixmap->drawable.bitsPerPixel, usage,
100913496ba1Ssnj                                          &tiling, &stride);
101003b705cfSriastradh
101103b705cfSriastradh		/* Fail very large allocations.  Large BOs will tend to hit SW fallbacks
101203b705cfSriastradh		 * frequently, and also will tend to fail to successfully map when doing
101303b705cfSriastradh		 * SW fallbacks because we overcommit address space for BO access.
101403b705cfSriastradh		 */
101503b705cfSriastradh		if (size > intel->max_bo_size || stride >= KB(32))
101603b705cfSriastradh			goto fallback_pixmap;
101703b705cfSriastradh
101813496ba1Ssnj		priv = calloc(1, sizeof (struct intel_uxa_pixmap));
101903b705cfSriastradh		if (priv == NULL)
102003b705cfSriastradh			goto fallback_pixmap;
102103b705cfSriastradh
102203b705cfSriastradh		if (usage == UXA_CREATE_PIXMAP_FOR_MAP) {
102303b705cfSriastradh			priv->busy = 0;
102403b705cfSriastradh			priv->bo = drm_intel_bo_alloc(intel->bufmgr,
102503b705cfSriastradh						      "pixmap", size, 0);
102603b705cfSriastradh		} else {
102703b705cfSriastradh			priv->busy = -1;
102803b705cfSriastradh			priv->bo = drm_intel_bo_alloc_for_render(intel->bufmgr,
102903b705cfSriastradh								 "pixmap",
103003b705cfSriastradh								 size, 0);
103103b705cfSriastradh		}
103203b705cfSriastradh		if (!priv->bo)
103303b705cfSriastradh			goto fallback_priv;
103403b705cfSriastradh
103503b705cfSriastradh		if (tiling != I915_TILING_NONE)
103603b705cfSriastradh			drm_intel_bo_set_tiling(priv->bo, &tiling, stride);
103703b705cfSriastradh		priv->tiling = tiling;
103803b705cfSriastradh		priv->offscreen = 1;
103903b705cfSriastradh
104003b705cfSriastradh		list_init(&priv->batch);
104113496ba1Ssnj		intel_uxa_set_pixmap_private(pixmap, priv);
104203b705cfSriastradh
104303b705cfSriastradh		screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL);
104403b705cfSriastradh	}
104503b705cfSriastradh
104603b705cfSriastradh	return pixmap;
104703b705cfSriastradh
104803b705cfSriastradhfallback_priv:
104903b705cfSriastradh	free(priv);
105003b705cfSriastradhfallback_pixmap:
105103b705cfSriastradh	fbDestroyPixmap(pixmap);
105203b705cfSriastradh	if (new_pixmap)
105303b705cfSriastradh		return new_pixmap;
105403b705cfSriastradh	else
105503b705cfSriastradh		return fbCreatePixmap(screen, w, h, depth, usage);
105603b705cfSriastradh}
105703b705cfSriastradh
105803b705cfSriastradhstatic Bool intel_uxa_destroy_pixmap(PixmapPtr pixmap)
105903b705cfSriastradh{
106013496ba1Ssnj	if (pixmap->refcnt == 1)
106113496ba1Ssnj		intel_uxa_set_pixmap_bo(pixmap, NULL);
106203b705cfSriastradh	fbDestroyPixmap(pixmap);
106303b705cfSriastradh	return TRUE;
106403b705cfSriastradh}
106503b705cfSriastradh
106603b705cfSriastradhBool intel_uxa_create_screen_resources(ScreenPtr screen)
106703b705cfSriastradh{
106803b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
106903b705cfSriastradh	PixmapPtr pixmap;
107003b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
107103b705cfSriastradh	dri_bo *bo = intel->front_buffer;
107242542f5fSchristos	int old_width, old_height, old_pitch;
107303b705cfSriastradh
107403b705cfSriastradh	if (!uxa_resources_init(screen))
107503b705cfSriastradh		return FALSE;
107603b705cfSriastradh
107703b705cfSriastradh	if (drm_intel_gem_bo_map_gtt(bo))
107803b705cfSriastradh		return FALSE;
107903b705cfSriastradh
108003b705cfSriastradh	pixmap = screen->GetScreenPixmap(screen);
108142542f5fSchristos	old_width = pixmap->drawable.width;
108242542f5fSchristos	old_height = pixmap->drawable.height;
108342542f5fSchristos	old_pitch = pixmap->devKind;
108442542f5fSchristos
108542542f5fSchristos	if (!screen->ModifyPixmapHeader(pixmap,
108642542f5fSchristos					scrn->virtualX,
108742542f5fSchristos					scrn->virtualY,
108842542f5fSchristos					-1, -1,
108942542f5fSchristos					intel->front_pitch,
109042542f5fSchristos					NULL))
109142542f5fSchristos		return FALSE;
109242542f5fSchristos
109313496ba1Ssnj	intel_uxa_set_pixmap_bo(pixmap, bo);
109413496ba1Ssnj	if (intel_uxa_get_pixmap_private(pixmap) == NULL)
109542542f5fSchristos		goto err;
109603b705cfSriastradh
109713496ba1Ssnj	intel_uxa_get_pixmap_private(pixmap)->pinned |= PIN_SCANOUT;
109842542f5fSchristos	scrn->displayWidth = intel->front_pitch / intel->cpp;
109903b705cfSriastradh
110003b705cfSriastradh	return TRUE;
110142542f5fSchristos
110242542f5fSchristoserr:
110342542f5fSchristos	screen->ModifyPixmapHeader(pixmap,
110442542f5fSchristos				   old_width, old_height, -1, -1, old_pitch, NULL);
110542542f5fSchristos	return FALSE;
110603b705cfSriastradh}
110703b705cfSriastradh
110803b705cfSriastradh#ifdef CREATE_PIXMAP_USAGE_SHARED
110903b705cfSriastradhstatic Bool
111003b705cfSriastradhintel_uxa_share_pixmap_backing(PixmapPtr ppix, ScreenPtr slave, void **fd_handle)
111103b705cfSriastradh{
111203b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(ppix->drawable.pScreen);
111303b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
111413496ba1Ssnj	struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(ppix);
111503b705cfSriastradh	unsigned int size, tiling, swizzle;
111613496ba1Ssnj	dri_bo *bo = intel_uxa_get_pixmap_bo(ppix), *newbo;
111703b705cfSriastradh	int stride;
111803b705cfSriastradh	int handle;
111903b705cfSriastradh
112003b705cfSriastradh	if (drm_intel_bo_references(intel->batch_bo, bo))
112103b705cfSriastradh		intel_batch_submit(intel->scrn);
112203b705cfSriastradh
112303b705cfSriastradh	drm_intel_bo_get_tiling(bo, &tiling, &swizzle);
112403b705cfSriastradh
112503b705cfSriastradh	if (tiling == I915_TILING_X) {
112642542f5fSchristos		if (priv->pinned)
112703b705cfSriastradh			return FALSE;
112803b705cfSriastradh
112903b705cfSriastradh	        tiling = I915_TILING_NONE;
113003b705cfSriastradh
113113496ba1Ssnj		size = intel_compute_size(intel,
113213496ba1Ssnj                                          ppix->drawable.width, ppix->drawable.height,
113313496ba1Ssnj                                          ppix->drawable.bitsPerPixel, INTEL_CREATE_PIXMAP_DRI2,
113413496ba1Ssnj                                          &tiling, &stride);
113503b705cfSriastradh
113603b705cfSriastradh		newbo = drm_intel_bo_alloc_for_render(intel->bufmgr,
113703b705cfSriastradh						      "pixmap",
113803b705cfSriastradh						      size, 0);
113903b705cfSriastradh
114003b705cfSriastradh		if (tiling != I915_TILING_NONE)
114103b705cfSriastradh			drm_intel_bo_set_tiling(newbo, &tiling, stride);
114203b705cfSriastradh		priv->tiling = tiling;
114313496ba1Ssnj		intel_uxa_set_pixmap_bo(ppix, newbo);
114403b705cfSriastradh
114503b705cfSriastradh		ppix->drawable.pScreen->ModifyPixmapHeader(ppix, ppix->drawable.width,
114603b705cfSriastradh					   ppix->drawable.height, 0, 0,
114703b705cfSriastradh					   stride, NULL);
114803b705cfSriastradh		bo = newbo;
114903b705cfSriastradh	}
115003b705cfSriastradh	drm_intel_bo_get_tiling(bo, &tiling, &swizzle);
115103b705cfSriastradh	drm_intel_bo_gem_export_to_prime(bo, &handle);
115242542f5fSchristos	priv->pinned |= PIN_PRIME;
115303b705cfSriastradh
115403b705cfSriastradh	*fd_handle = (void *)(long)handle;
115503b705cfSriastradh	return TRUE;
115603b705cfSriastradh}
115703b705cfSriastradh
115803b705cfSriastradhstatic Bool
115903b705cfSriastradhintel_uxa_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle)
116003b705cfSriastradh{
116103b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(ppix->drawable.pScreen);
116203b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
116303b705cfSriastradh	dri_bo *bo;
116403b705cfSriastradh	int ihandle = (int)(long)fd_handle;
116503b705cfSriastradh
116603b705cfSriastradh	/* force untiled for now */
116703b705cfSriastradh	bo = drm_intel_bo_gem_create_from_prime(intel->bufmgr, ihandle, 0);
116803b705cfSriastradh	if (!bo)
116903b705cfSriastradh		return FALSE;
117003b705cfSriastradh
117113496ba1Ssnj	intel_uxa_set_pixmap_bo(ppix, bo);
117203b705cfSriastradh	close(ihandle);
117303b705cfSriastradh	return TRUE;
117403b705cfSriastradh}
117503b705cfSriastradh#endif
117603b705cfSriastradh
117703b705cfSriastradhstatic void
117803b705cfSriastradhintel_limits_init(intel_screen_private *intel)
117903b705cfSriastradh{
118003b705cfSriastradh	/* Limits are described in the BLT engine chapter under Graphics Data Size
118103b705cfSriastradh	 * Limitations, and the descriptions of SURFACE_STATE, 3DSTATE_BUFFER_INFO,
118203b705cfSriastradh	 * 3DSTATE_DRAWING_RECTANGLE, 3DSTATE_MAP_INFO, and 3DSTATE_MAP_INFO.
118303b705cfSriastradh	 *
118403b705cfSriastradh	 * i845 through i965 limits 2D rendering to 65536 lines and pitch of 32768.
118503b705cfSriastradh	 *
118603b705cfSriastradh	 * i965 limits 3D surface to (2*element size)-aligned offset if un-tiled.
118703b705cfSriastradh	 * i965 limits 3D surface to 4kB-aligned offset if tiled.
118803b705cfSriastradh	 * i965 limits 3D surfaces to w,h of ?,8192.
118903b705cfSriastradh	 * i965 limits 3D surface to pitch of 1B - 128kB.
119003b705cfSriastradh	 * i965 limits 3D surface pitch alignment to 1 or 2 times the element size.
119103b705cfSriastradh	 * i965 limits 3D surface pitch alignment to 512B if tiled.
119203b705cfSriastradh	 * i965 limits 3D destination drawing rect to w,h of 8192,8192.
119303b705cfSriastradh	 *
119403b705cfSriastradh	 * i915 limits 3D textures to 4B-aligned offset if un-tiled.
119503b705cfSriastradh	 * i915 limits 3D textures to ~4kB-aligned offset if tiled.
119603b705cfSriastradh	 * i915 limits 3D textures to width,height of 2048,2048.
119703b705cfSriastradh	 * i915 limits 3D textures to pitch of 16B - 8kB, in dwords.
119803b705cfSriastradh	 * i915 limits 3D destination to ~4kB-aligned offset if tiled.
119903b705cfSriastradh	 * i915 limits 3D destination to pitch of 16B - 8kB, in dwords, if un-tiled.
120003b705cfSriastradh	 * i915 limits 3D destination to pitch 64B-aligned if used with depth.
120103b705cfSriastradh	 * i915 limits 3D destination to pitch of 512B - 8kB, in tiles, if tiled.
120203b705cfSriastradh	 * i915 limits 3D destination to POT aligned pitch if tiled.
120303b705cfSriastradh	 * i915 limits 3D destination drawing rect to w,h of 2048,2048.
120403b705cfSriastradh	 *
120503b705cfSriastradh	 * i845 limits 3D textures to 4B-aligned offset if un-tiled.
120603b705cfSriastradh	 * i845 limits 3D textures to ~4kB-aligned offset if tiled.
120703b705cfSriastradh	 * i845 limits 3D textures to width,height of 2048,2048.
120803b705cfSriastradh	 * i845 limits 3D textures to pitch of 4B - 8kB, in dwords.
120903b705cfSriastradh	 * i845 limits 3D destination to 4B-aligned offset if un-tiled.
121003b705cfSriastradh	 * i845 limits 3D destination to ~4kB-aligned offset if tiled.
121103b705cfSriastradh	 * i845 limits 3D destination to pitch of 8B - 8kB, in dwords.
121203b705cfSriastradh	 * i845 limits 3D destination drawing rect to w,h of 2048,2048.
121303b705cfSriastradh	 *
121403b705cfSriastradh	 * For the tiled issues, the only tiled buffer we draw to should be
121503b705cfSriastradh	 * the front, which will have an appropriate pitch/offset already set up,
121603b705cfSriastradh	 * so UXA doesn't need to worry.
121703b705cfSriastradh	 */
121803b705cfSriastradh	if (INTEL_INFO(intel)->gen >= 040) {
121903b705cfSriastradh		intel->accel_pixmap_offset_alignment = 4 * 2;
122003b705cfSriastradh		intel->accel_max_x = 8192;
122103b705cfSriastradh		intel->accel_max_y = 8192;
122203b705cfSriastradh	} else {
122303b705cfSriastradh		intel->accel_pixmap_offset_alignment = 4;
122403b705cfSriastradh		intel->accel_max_x = 2048;
122503b705cfSriastradh		intel->accel_max_y = 2048;
122603b705cfSriastradh	}
122703b705cfSriastradh}
122803b705cfSriastradh
122942542f5fSchristosstatic Bool intel_option_accel_none(intel_screen_private *intel)
123042542f5fSchristos{
123142542f5fSchristos	const char *s;
123242542f5fSchristos
123342542f5fSchristos	s = xf86GetOptValString(intel->Options, OPTION_ACCEL_METHOD);
123442542f5fSchristos	if (s == NULL)
123542542f5fSchristos		return IS_DEFAULT_ACCEL_METHOD(NOACCEL);
123642542f5fSchristos
123742542f5fSchristos	return strcasecmp(s, "none") == 0;
123842542f5fSchristos}
123942542f5fSchristos
124003b705cfSriastradhstatic Bool intel_option_accel_blt(intel_screen_private *intel)
124103b705cfSriastradh{
124203b705cfSriastradh	const char *s;
124303b705cfSriastradh
124403b705cfSriastradh	s = xf86GetOptValString(intel->Options, OPTION_ACCEL_METHOD);
124503b705cfSriastradh	if (s == NULL)
124603b705cfSriastradh		return FALSE;
124703b705cfSriastradh
124803b705cfSriastradh	return strcasecmp(s, "blt") == 0;
124903b705cfSriastradh}
125003b705cfSriastradh
125113496ba1Ssnj/**
125213496ba1Ssnj * Intialiazes the hardware for the 3D pipeline use in the 2D driver.
125313496ba1Ssnj *
125413496ba1Ssnj * Some state caching is performed to avoid redundant state emits.  This
125513496ba1Ssnj * function is also responsible for marking the state as clobbered for DRI
125613496ba1Ssnj * clients.
125713496ba1Ssnj */
125813496ba1Ssnjvoid IntelEmitInvarientState(ScrnInfoPtr scrn)
125913496ba1Ssnj{
126013496ba1Ssnj	intel_screen_private *intel = intel_get_screen_private(scrn);
126113496ba1Ssnj
126213496ba1Ssnj	/* If we've emitted our state since the last clobber by another client,
126313496ba1Ssnj	 * skip it.
126413496ba1Ssnj	 */
126513496ba1Ssnj	if (intel->last_3d != LAST_3D_OTHER)
126613496ba1Ssnj		return;
126713496ba1Ssnj
126813496ba1Ssnj	if (IS_GEN2(intel))
126913496ba1Ssnj		I830EmitInvarientState(scrn);
127013496ba1Ssnj	else if IS_GEN3(intel)
127113496ba1Ssnj		I915EmitInvarientState(scrn);
127213496ba1Ssnj}
127313496ba1Ssnj
127403b705cfSriastradhBool intel_uxa_init(ScreenPtr screen)
127503b705cfSriastradh{
127603b705cfSriastradh	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
127703b705cfSriastradh	intel_screen_private *intel = intel_get_screen_private(scrn);
127803b705cfSriastradh
127913496ba1Ssnj	intel_batch_init(scrn);
128013496ba1Ssnj
128113496ba1Ssnj	if (INTEL_INFO(intel)->gen >= 040 && INTEL_INFO(intel)->gen < 0100)
128213496ba1Ssnj		gen4_render_state_init(scrn);
128313496ba1Ssnj
128403b705cfSriastradh#if HAS_DIXREGISTERPRIVATEKEY
128503b705cfSriastradh	if (!dixRegisterPrivateKey(&uxa_pixmap_index, PRIVATE_PIXMAP, 0))
128603b705cfSriastradh#else
128703b705cfSriastradh	if (!dixRequestPrivate(&uxa_pixmap_index, 0))
128803b705cfSriastradh#endif
128903b705cfSriastradh		return FALSE;
129003b705cfSriastradh
129103b705cfSriastradh	intel_limits_init(intel);
129203b705cfSriastradh
129303b705cfSriastradh	intel->uxa_driver = uxa_driver_alloc();
129403b705cfSriastradh	if (intel->uxa_driver == NULL)
129503b705cfSriastradh		return FALSE;
129603b705cfSriastradh
129703b705cfSriastradh	memset(intel->uxa_driver, 0, sizeof(*intel->uxa_driver));
129803b705cfSriastradh
129903b705cfSriastradh	intel->uxa_driver->uxa_major = 1;
130003b705cfSriastradh	intel->uxa_driver->uxa_minor = 0;
130103b705cfSriastradh
130203b705cfSriastradh	intel->prim_offset = 0;
130303b705cfSriastradh	intel->vertex_count = 0;
130403b705cfSriastradh	intel->vertex_offset = 0;
130503b705cfSriastradh	intel->vertex_used = 0;
130603b705cfSriastradh	intel->floats_per_vertex = 0;
130703b705cfSriastradh	intel->last_floats_per_vertex = 0;
130803b705cfSriastradh	intel->vertex_bo = NULL;
130903b705cfSriastradh	intel->surface_used = 0;
131003b705cfSriastradh	intel->surface_reloc = 0;
131103b705cfSriastradh
131203b705cfSriastradh	/* Solid fill */
131303b705cfSriastradh	intel->uxa_driver->check_solid = intel_uxa_check_solid;
131403b705cfSriastradh	intel->uxa_driver->prepare_solid = intel_uxa_prepare_solid;
131503b705cfSriastradh	intel->uxa_driver->solid = intel_uxa_solid;
131603b705cfSriastradh	intel->uxa_driver->done_solid = intel_uxa_done;
131703b705cfSriastradh
131803b705cfSriastradh	/* Copy */
131903b705cfSriastradh	intel->uxa_driver->check_copy = intel_uxa_check_copy;
132003b705cfSriastradh	intel->uxa_driver->prepare_copy = intel_uxa_prepare_copy;
132103b705cfSriastradh	intel->uxa_driver->copy = intel_uxa_copy;
132203b705cfSriastradh	intel->uxa_driver->done_copy = intel_uxa_done;
132303b705cfSriastradh
132403b705cfSriastradh	/* Composite */
132503b705cfSriastradh	if (intel_option_accel_blt(intel)) {
132642542f5fSchristos	} else if (INTEL_INFO(intel)->gen < 030) {
132703b705cfSriastradh		intel->uxa_driver->check_composite = i830_check_composite;
132803b705cfSriastradh		intel->uxa_driver->check_composite_target = i830_check_composite_target;
132903b705cfSriastradh		intel->uxa_driver->check_composite_texture = i830_check_composite_texture;
133003b705cfSriastradh		intel->uxa_driver->prepare_composite = i830_prepare_composite;
133103b705cfSriastradh		intel->uxa_driver->composite = i830_composite;
133203b705cfSriastradh		intel->uxa_driver->done_composite = i830_done_composite;
133303b705cfSriastradh
133403b705cfSriastradh		intel->vertex_flush = i830_vertex_flush;
133503b705cfSriastradh		intel->batch_commit_notify = i830_batch_commit_notify;
133642542f5fSchristos	} else if (INTEL_INFO(intel)->gen < 040) {
133703b705cfSriastradh		intel->uxa_driver->check_composite = i915_check_composite;
133803b705cfSriastradh		intel->uxa_driver->check_composite_target = i915_check_composite_target;
133903b705cfSriastradh		intel->uxa_driver->check_composite_texture = i915_check_composite_texture;
134003b705cfSriastradh		intel->uxa_driver->prepare_composite = i915_prepare_composite;
134103b705cfSriastradh		intel->uxa_driver->composite = i915_composite;
134203b705cfSriastradh		intel->uxa_driver->done_composite = i830_done_composite;
134303b705cfSriastradh
134403b705cfSriastradh		intel->vertex_flush = i915_vertex_flush;
134503b705cfSriastradh		intel->batch_commit_notify = i915_batch_commit_notify;
134642542f5fSchristos	} else if (INTEL_INFO(intel)->gen < 0100) {
134703b705cfSriastradh		intel->uxa_driver->check_composite = i965_check_composite;
134803b705cfSriastradh		intel->uxa_driver->check_composite_texture = i965_check_composite_texture;
134903b705cfSriastradh		intel->uxa_driver->prepare_composite = i965_prepare_composite;
135003b705cfSriastradh		intel->uxa_driver->composite = i965_composite;
135103b705cfSriastradh		intel->uxa_driver->done_composite = i830_done_composite;
135203b705cfSriastradh
135303b705cfSriastradh		intel->vertex_flush = i965_vertex_flush;
135403b705cfSriastradh		intel->batch_flush = i965_batch_flush;
135503b705cfSriastradh		intel->batch_commit_notify = i965_batch_commit_notify;
135603b705cfSriastradh
135742542f5fSchristos		if (INTEL_INFO(intel)->gen < 050) {
135803b705cfSriastradh			intel->context_switch = gen4_context_switch;
135942542f5fSchristos		} else if (INTEL_INFO(intel)->gen < 060) {
136003b705cfSriastradh			intel->context_switch = gen5_context_switch;
136103b705cfSriastradh		} else {
136203b705cfSriastradh			intel->context_switch = gen6_context_switch;
136303b705cfSriastradh		}
136403b705cfSriastradh	}
136503b705cfSriastradh
136603b705cfSriastradh	/* PutImage */
136703b705cfSriastradh	intel->uxa_driver->put_image = intel_uxa_put_image;
136803b705cfSriastradh	intel->uxa_driver->get_image = intel_uxa_get_image;
136903b705cfSriastradh
137003b705cfSriastradh	intel->uxa_driver->prepare_access = intel_uxa_prepare_access;
137103b705cfSriastradh	intel->uxa_driver->finish_access = intel_uxa_finish_access;
137203b705cfSriastradh	intel->uxa_driver->pixmap_is_offscreen = intel_uxa_pixmap_is_offscreen;
137303b705cfSriastradh
137403b705cfSriastradh	screen->CreatePixmap = intel_uxa_create_pixmap;
137503b705cfSriastradh	screen->DestroyPixmap = intel_uxa_destroy_pixmap;
137603b705cfSriastradh
137703b705cfSriastradh#ifdef CREATE_PIXMAP_USAGE_SHARED
137803b705cfSriastradh	screen->SharePixmapBacking = intel_uxa_share_pixmap_backing;
137903b705cfSriastradh	screen->SetSharedPixmapBacking = intel_uxa_set_shared_pixmap_backing;
138003b705cfSriastradh#endif
138103b705cfSriastradh
138203b705cfSriastradh	if (!uxa_driver_init(screen, intel->uxa_driver)) {
138303b705cfSriastradh		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
138403b705cfSriastradh			   "UXA initialization failed\n");
138503b705cfSriastradh		free(intel->uxa_driver);
138603b705cfSriastradh		return FALSE;
138703b705cfSriastradh	}
138803b705cfSriastradh
138942542f5fSchristos	if (intel_option_accel_none(intel))
139042542f5fSchristos		intel->force_fallback = 1;
139142542f5fSchristos
139203b705cfSriastradh	uxa_set_fallback_debug(screen, intel->fallback_debug);
139303b705cfSriastradh	uxa_set_force_fallback(screen, intel->force_fallback);
139403b705cfSriastradh
139542542f5fSchristos	intel->flush_rendering = intel_flush_rendering;
139603b705cfSriastradh	return TRUE;
139703b705cfSriastradh}
1398