1428d7b3dSmrg/*
2428d7b3dSmrg * Copyright © 2006 Intel Corporation
3428d7b3dSmrg *
4428d7b3dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5428d7b3dSmrg * copy of this software and associated documentation files (the "Software"),
6428d7b3dSmrg * to deal in the Software without restriction, including without limitation
7428d7b3dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8428d7b3dSmrg * and/or sell copies of the Software, and to permit persons to whom the
9428d7b3dSmrg * Software is furnished to do so, subject to the following conditions:
10428d7b3dSmrg *
11428d7b3dSmrg * The above copyright notice and this permission notice (including the next
12428d7b3dSmrg * paragraph) shall be included in all copies or substantial portions of the
13428d7b3dSmrg * Software.
14428d7b3dSmrg *
15428d7b3dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16428d7b3dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17428d7b3dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18428d7b3dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19428d7b3dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20428d7b3dSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21428d7b3dSmrg * SOFTWARE.
22428d7b3dSmrg *
23428d7b3dSmrg * Authors:
24428d7b3dSmrg *    Wang Zhenyu <zhenyu.z.wang@intel.com>
25428d7b3dSmrg *    Eric Anholt <eric@anholt.net>
26428d7b3dSmrg *
27428d7b3dSmrg */
28428d7b3dSmrg
29428d7b3dSmrg#ifdef HAVE_CONFIG_H
30428d7b3dSmrg#include "config.h"
31428d7b3dSmrg#endif
32428d7b3dSmrg
33428d7b3dSmrg#include "xorg-server.h"
34428d7b3dSmrg#include "xf86.h"
35428d7b3dSmrg#include "intel.h"
36428d7b3dSmrg#include "intel_uxa.h"
37428d7b3dSmrg#include "i830_reg.h"
38428d7b3dSmrg
39428d7b3dSmrgstruct blendinfo {
40428d7b3dSmrg	Bool dst_alpha;
41428d7b3dSmrg	Bool src_alpha;
42428d7b3dSmrg	uint32_t src_blend;
43428d7b3dSmrg	uint32_t dst_blend;
44428d7b3dSmrg};
45428d7b3dSmrg
46428d7b3dSmrgstruct formatinfo {
47428d7b3dSmrg	int fmt;
48428d7b3dSmrg	uint32_t card_fmt;
49428d7b3dSmrg};
50428d7b3dSmrg
51428d7b3dSmrg#define TB0C_LAST_STAGE	(1 << 31)
52428d7b3dSmrg#define TB0C_RESULT_SCALE_1X		(0 << 29)
53428d7b3dSmrg#define TB0C_RESULT_SCALE_2X		(1 << 29)
54428d7b3dSmrg#define TB0C_RESULT_SCALE_4X		(2 << 29)
55428d7b3dSmrg#define TB0C_OP_MODULE			(3 << 25)
56428d7b3dSmrg#define TB0C_OUTPUT_WRITE_CURRENT	(0 << 24)
57428d7b3dSmrg#define TB0C_OUTPUT_WRITE_ACCUM		(1 << 24)
58428d7b3dSmrg#define TB0C_ARG3_REPLICATE_ALPHA 	(1<<23)
59428d7b3dSmrg#define TB0C_ARG3_INVERT		(1<<22)
60428d7b3dSmrg#define TB0C_ARG3_SEL_XXX
61428d7b3dSmrg#define TB0C_ARG2_REPLICATE_ALPHA 	(1<<17)
62428d7b3dSmrg#define TB0C_ARG2_INVERT		(1<<16)
63428d7b3dSmrg#define TB0C_ARG2_SEL_ONE		(0 << 12)
64428d7b3dSmrg#define TB0C_ARG2_SEL_FACTOR		(1 << 12)
65428d7b3dSmrg#define TB0C_ARG2_SEL_TEXEL0		(6 << 12)
66428d7b3dSmrg#define TB0C_ARG2_SEL_TEXEL1		(7 << 12)
67428d7b3dSmrg#define TB0C_ARG2_SEL_TEXEL2		(8 << 12)
68428d7b3dSmrg#define TB0C_ARG2_SEL_TEXEL3		(9 << 12)
69428d7b3dSmrg#define TB0C_ARG1_REPLICATE_ALPHA 	(1<<11)
70428d7b3dSmrg#define TB0C_ARG1_INVERT		(1<<10)
71428d7b3dSmrg#define TB0C_ARG1_SEL_ONE		(0 << 6)
72428d7b3dSmrg#define TB0C_ARG1_SEL_TEXEL0		(6 << 6)
73428d7b3dSmrg#define TB0C_ARG1_SEL_TEXEL1		(7 << 6)
74428d7b3dSmrg#define TB0C_ARG1_SEL_TEXEL2		(8 << 6)
75428d7b3dSmrg#define TB0C_ARG1_SEL_TEXEL3		(9 << 6)
76428d7b3dSmrg#define TB0C_ARG0_REPLICATE_ALPHA 	(1<<5)
77428d7b3dSmrg#define TB0C_ARG0_SEL_XXX
78428d7b3dSmrg
79428d7b3dSmrg#define TB0A_CTR_STAGE_ENABLE 		(1<<31)
80428d7b3dSmrg#define TB0A_RESULT_SCALE_1X		(0 << 29)
81428d7b3dSmrg#define TB0A_RESULT_SCALE_2X		(1 << 29)
82428d7b3dSmrg#define TB0A_RESULT_SCALE_4X		(2 << 29)
83428d7b3dSmrg#define TB0A_OP_MODULE			(3 << 25)
84428d7b3dSmrg#define TB0A_OUTPUT_WRITE_CURRENT	(0<<24)
85428d7b3dSmrg#define TB0A_OUTPUT_WRITE_ACCUM		(1<<24)
86428d7b3dSmrg#define TB0A_CTR_STAGE_SEL_BITS_XXX
87428d7b3dSmrg#define TB0A_ARG3_SEL_XXX
88428d7b3dSmrg#define TB0A_ARG3_INVERT		(1<<17)
89428d7b3dSmrg#define TB0A_ARG2_INVERT		(1<<16)
90428d7b3dSmrg#define TB0A_ARG2_SEL_ONE		(0 << 12)
91428d7b3dSmrg#define TB0A_ARG2_SEL_TEXEL0		(6 << 12)
92428d7b3dSmrg#define TB0A_ARG2_SEL_TEXEL1		(7 << 12)
93428d7b3dSmrg#define TB0A_ARG2_SEL_TEXEL2		(8 << 12)
94428d7b3dSmrg#define TB0A_ARG2_SEL_TEXEL3		(9 << 12)
95428d7b3dSmrg#define TB0A_ARG1_INVERT		(1<<10)
96428d7b3dSmrg#define TB0A_ARG1_SEL_ONE		(0 << 6)
97428d7b3dSmrg#define TB0A_ARG1_SEL_TEXEL0		(6 << 6)
98428d7b3dSmrg#define TB0A_ARG1_SEL_TEXEL1		(7 << 6)
99428d7b3dSmrg#define TB0A_ARG1_SEL_TEXEL2		(8 << 6)
100428d7b3dSmrg#define TB0A_ARG1_SEL_TEXEL3		(9 << 6)
101428d7b3dSmrg
102428d7b3dSmrgstatic struct blendinfo i830_blend_op[] = {
103428d7b3dSmrg	/* Clear */
104428d7b3dSmrg	{0, 0, BLENDFACTOR_ZERO, BLENDFACTOR_ZERO},
105428d7b3dSmrg	/* Src */
106428d7b3dSmrg	{0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ZERO},
107428d7b3dSmrg	/* Dst */
108428d7b3dSmrg	{0, 0, BLENDFACTOR_ZERO, BLENDFACTOR_ONE},
109428d7b3dSmrg	/* Over */
110428d7b3dSmrg	{0, 1, BLENDFACTOR_ONE, BLENDFACTOR_INV_SRC_ALPHA},
111428d7b3dSmrg	/* OverReverse */
112428d7b3dSmrg	{1, 0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ONE},
113428d7b3dSmrg	/* In */
114428d7b3dSmrg	{1, 0, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_ZERO},
115428d7b3dSmrg	/* InReverse */
116428d7b3dSmrg	{0, 1, BLENDFACTOR_ZERO, BLENDFACTOR_SRC_ALPHA},
117428d7b3dSmrg	/* Out */
118428d7b3dSmrg	{1, 0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ZERO},
119428d7b3dSmrg	/* OutReverse */
120428d7b3dSmrg	{0, 1, BLENDFACTOR_ZERO, BLENDFACTOR_INV_SRC_ALPHA},
121428d7b3dSmrg	/* Atop */
122428d7b3dSmrg	{1, 1, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA},
123428d7b3dSmrg	/* AtopReverse */
124428d7b3dSmrg	{1, 1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_SRC_ALPHA},
125428d7b3dSmrg	/* Xor */
126428d7b3dSmrg	{1, 1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA},
127428d7b3dSmrg	/* Add */
128428d7b3dSmrg	{0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ONE},
129428d7b3dSmrg};
130428d7b3dSmrg
131428d7b3dSmrgstatic struct formatinfo i830_tex_formats[] = {
132428d7b3dSmrg	{PICT_a8, MAPSURF_8BIT | MT_8BIT_A8},
133428d7b3dSmrg	{PICT_a8r8g8b8, MAPSURF_32BIT | MT_32BIT_ARGB8888},
134428d7b3dSmrg	{PICT_a8b8g8r8, MAPSURF_32BIT | MT_32BIT_ABGR8888},
135428d7b3dSmrg	{PICT_r5g6b5, MAPSURF_16BIT | MT_16BIT_RGB565},
136428d7b3dSmrg	{PICT_a1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555},
137428d7b3dSmrg	{PICT_a4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444},
138428d7b3dSmrg};
139428d7b3dSmrg
140428d7b3dSmrgstatic struct formatinfo i855_tex_formats[] = {
141428d7b3dSmrg	{PICT_x8r8g8b8, MAPSURF_32BIT | MT_32BIT_XRGB8888},
142428d7b3dSmrg	{PICT_x8b8g8r8, MAPSURF_32BIT | MT_32BIT_XBGR8888},
143428d7b3dSmrg};
144428d7b3dSmrg
145428d7b3dSmrgstatic Bool i830_get_dest_format(PicturePtr dest_picture, uint32_t * dst_format)
146428d7b3dSmrg{
147428d7b3dSmrg	ScrnInfoPtr scrn;
148428d7b3dSmrg
149428d7b3dSmrg	switch (dest_picture->format) {
150428d7b3dSmrg	case PICT_a8r8g8b8:
151428d7b3dSmrg	case PICT_x8r8g8b8:
152428d7b3dSmrg		*dst_format = COLR_BUF_ARGB8888;
153428d7b3dSmrg		break;
154428d7b3dSmrg	case PICT_r5g6b5:
155428d7b3dSmrg		*dst_format = COLR_BUF_RGB565;
156428d7b3dSmrg		break;
157428d7b3dSmrg	case PICT_a1r5g5b5:
158428d7b3dSmrg	case PICT_x1r5g5b5:
159428d7b3dSmrg		*dst_format = COLR_BUF_ARGB1555;
160428d7b3dSmrg		break;
161428d7b3dSmrg	case PICT_a8:
162428d7b3dSmrg		*dst_format = COLR_BUF_8BIT;
163428d7b3dSmrg		break;
164428d7b3dSmrg	case PICT_a4r4g4b4:
165428d7b3dSmrg	case PICT_x4r4g4b4:
166428d7b3dSmrg		*dst_format = COLR_BUF_ARGB4444;
167428d7b3dSmrg		break;
168428d7b3dSmrg	default:
169428d7b3dSmrg		scrn = xf86ScreenToScrn(dest_picture->pDrawable->pScreen);
170428d7b3dSmrg		intel_uxa_debug_fallback(scrn, "Unsupported dest format 0x%x\n",
171428d7b3dSmrg				     (int)dest_picture->format);
172428d7b3dSmrg		return FALSE;
173428d7b3dSmrg	}
174428d7b3dSmrg	*dst_format |= DSTORG_HORT_BIAS(0x8) | DSTORG_VERT_BIAS(0x8);
175428d7b3dSmrg	return TRUE;
176428d7b3dSmrg}
177428d7b3dSmrg
178428d7b3dSmrgstatic Bool i830_get_blend_cntl(ScrnInfoPtr scrn, int op, PicturePtr mask,
179428d7b3dSmrg				uint32_t dst_format, uint32_t * blendctl)
180428d7b3dSmrg{
181428d7b3dSmrg	uint32_t sblend, dblend;
182428d7b3dSmrg
183428d7b3dSmrg	sblend = i830_blend_op[op].src_blend;
184428d7b3dSmrg	dblend = i830_blend_op[op].dst_blend;
185428d7b3dSmrg
186428d7b3dSmrg	/* If there's no dst alpha channel, adjust the blend op so that we'll treat
187428d7b3dSmrg	 * it as always 1.
188428d7b3dSmrg	 */
189428d7b3dSmrg	if (PICT_FORMAT_A(dst_format) == 0 && i830_blend_op[op].dst_alpha) {
190428d7b3dSmrg		if (sblend == BLENDFACTOR_DST_ALPHA)
191428d7b3dSmrg			sblend = BLENDFACTOR_ONE;
192428d7b3dSmrg		else if (sblend == BLENDFACTOR_INV_DST_ALPHA)
193428d7b3dSmrg			sblend = BLENDFACTOR_ZERO;
194428d7b3dSmrg	}
195428d7b3dSmrg
196428d7b3dSmrg	/* For blending purposes, COLR_BUF_8BIT values show up in the green
197428d7b3dSmrg	 * channel.  So we can't use the alpha channel.
198428d7b3dSmrg	 */
199428d7b3dSmrg	if (dst_format == PICT_a8 && ((sblend == BLENDFACTOR_DST_ALPHA ||
200428d7b3dSmrg				       sblend == BLENDFACTOR_INV_DST_ALPHA))) {
201428d7b3dSmrg		intel_uxa_debug_fallback(scrn, "Can't do dst alpha blending with "
202428d7b3dSmrg				     "PICT_a8 dest.\n");
203428d7b3dSmrg		return FALSE;
204428d7b3dSmrg	}
205428d7b3dSmrg
206428d7b3dSmrg	/* If the source alpha is being used, then we should only be in a case
207428d7b3dSmrg	 * where the source blend factor is 0, and the source blend value is the
208428d7b3dSmrg	 * mask channels multiplied by the source picture's alpha.
209428d7b3dSmrg	 */
210428d7b3dSmrg	if (mask && mask->componentAlpha && PICT_FORMAT_RGB(mask->format)
211428d7b3dSmrg	    && i830_blend_op[op].src_alpha) {
212428d7b3dSmrg		if (dblend == BLENDFACTOR_SRC_ALPHA) {
213428d7b3dSmrg			dblend = BLENDFACTOR_SRC_COLR;
214428d7b3dSmrg		} else if (dblend == BLENDFACTOR_INV_SRC_ALPHA) {
215428d7b3dSmrg			dblend = BLENDFACTOR_INV_SRC_COLR;
216428d7b3dSmrg		}
217428d7b3dSmrg	}
218428d7b3dSmrg
219428d7b3dSmrg	*blendctl = (sblend << S8_SRC_BLEND_FACTOR_SHIFT) |
220428d7b3dSmrg	    (dblend << S8_DST_BLEND_FACTOR_SHIFT);
221428d7b3dSmrg
222428d7b3dSmrg	return TRUE;
223428d7b3dSmrg}
224428d7b3dSmrg
225428d7b3dSmrgstatic uint32_t i8xx_get_card_format(intel_screen_private *intel,
226428d7b3dSmrg				     PicturePtr picture)
227428d7b3dSmrg{
228428d7b3dSmrg	int i;
229428d7b3dSmrg
230428d7b3dSmrg	for (i = 0; i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]);
231428d7b3dSmrg	     i++) {
232428d7b3dSmrg		if (i830_tex_formats[i].fmt == picture->format)
233428d7b3dSmrg			return i830_tex_formats[i].card_fmt;
234428d7b3dSmrg	}
235428d7b3dSmrg
236428d7b3dSmrg	if (!(IS_I830(intel) || IS_845G(intel))) {
237428d7b3dSmrg		for (i = 0; i < sizeof(i855_tex_formats) / sizeof(i855_tex_formats[0]);
238428d7b3dSmrg		     i++) {
239428d7b3dSmrg			if (i855_tex_formats[i].fmt == picture->format)
240428d7b3dSmrg				return i855_tex_formats[i].card_fmt;
241428d7b3dSmrg		}
242428d7b3dSmrg	}
243428d7b3dSmrg
244428d7b3dSmrg	return 0;
245428d7b3dSmrg}
246428d7b3dSmrg
247428d7b3dSmrgstatic void i830_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit)
248428d7b3dSmrg{
249428d7b3dSmrg
250428d7b3dSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(picture->pDrawable->pScreen);
251428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
252428d7b3dSmrg	uint32_t format, tiling_bits, pitch, filter;
253428d7b3dSmrg	uint32_t wrap_mode;
254428d7b3dSmrg	uint32_t texcoordtype;
255428d7b3dSmrg
256428d7b3dSmrg	pitch = intel_pixmap_pitch(pixmap);
257428d7b3dSmrg	intel->scale_units[unit][0] = pixmap->drawable.width;
258428d7b3dSmrg	intel->scale_units[unit][1] = pixmap->drawable.height;
259428d7b3dSmrg	intel->transform[unit] = picture->transform;
260428d7b3dSmrg
261428d7b3dSmrg	if (intel_uxa_transform_is_affine(intel->transform[unit]))
262428d7b3dSmrg		texcoordtype = TEXCOORDTYPE_CARTESIAN;
263428d7b3dSmrg	else
264428d7b3dSmrg		texcoordtype = TEXCOORDTYPE_HOMOGENEOUS;
265428d7b3dSmrg
266428d7b3dSmrg	switch (picture->repeatType) {
267428d7b3dSmrg	case RepeatNone:
268428d7b3dSmrg		wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
269428d7b3dSmrg		break;
270428d7b3dSmrg	case RepeatNormal:
271428d7b3dSmrg		wrap_mode = TEXCOORDMODE_WRAP;
272428d7b3dSmrg		break;
273428d7b3dSmrg	case RepeatPad:
274428d7b3dSmrg		wrap_mode = TEXCOORDMODE_CLAMP;
275428d7b3dSmrg		break;
276428d7b3dSmrg	case RepeatReflect:
277428d7b3dSmrg		wrap_mode = TEXCOORDMODE_MIRROR;
278428d7b3dSmrg		break;
279428d7b3dSmrg	default:
280428d7b3dSmrg		FatalError("Unknown repeat type %d\n", picture->repeatType);
281428d7b3dSmrg	}
282428d7b3dSmrg
283428d7b3dSmrg	switch (picture->filter) {
284428d7b3dSmrg	case PictFilterNearest:
285428d7b3dSmrg		filter = ((FILTER_NEAREST << TM0S3_MAG_FILTER_SHIFT) |
286428d7b3dSmrg			  (FILTER_NEAREST << TM0S3_MIN_FILTER_SHIFT));
287428d7b3dSmrg		break;
288428d7b3dSmrg	case PictFilterBilinear:
289428d7b3dSmrg		filter = ((FILTER_LINEAR << TM0S3_MAG_FILTER_SHIFT) |
290428d7b3dSmrg			  (FILTER_LINEAR << TM0S3_MIN_FILTER_SHIFT));
291428d7b3dSmrg		break;
292428d7b3dSmrg	default:
293428d7b3dSmrg		FatalError("Bad filter 0x%x\n", picture->filter);
294428d7b3dSmrg	}
295428d7b3dSmrg	filter |= (MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT);
296428d7b3dSmrg
297428d7b3dSmrg	if (intel_uxa_pixmap_tiled(pixmap)) {
298428d7b3dSmrg		tiling_bits = TM0S1_TILED_SURFACE;
299428d7b3dSmrg		if (intel_uxa_get_pixmap_private(pixmap)->tiling
300428d7b3dSmrg				== I915_TILING_Y)
301428d7b3dSmrg			tiling_bits |= TM0S1_TILE_WALK;
302428d7b3dSmrg	} else
303428d7b3dSmrg		tiling_bits = 0;
304428d7b3dSmrg
305428d7b3dSmrg	format = i8xx_get_card_format(intel, picture);
306428d7b3dSmrg
307428d7b3dSmrg	assert(intel->in_batch_atomic);
308428d7b3dSmrg
309428d7b3dSmrg	OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
310428d7b3dSmrg		  LOAD_TEXTURE_MAP(unit) | 4);
311428d7b3dSmrg	OUT_RELOC_PIXMAP(pixmap, I915_GEM_DOMAIN_SAMPLER, 0, 0);
312428d7b3dSmrg	OUT_BATCH(((pixmap->drawable.height -
313428d7b3dSmrg		    1) << TM0S1_HEIGHT_SHIFT) | ((pixmap->drawable.width -
314428d7b3dSmrg						  1) <<
315428d7b3dSmrg						 TM0S1_WIDTH_SHIFT) |
316428d7b3dSmrg		  format | tiling_bits);
317428d7b3dSmrg	OUT_BATCH((pitch / 4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
318428d7b3dSmrg	OUT_BATCH(filter);
319428d7b3dSmrg	OUT_BATCH(0);	/* default color */
320428d7b3dSmrg	OUT_BATCH(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) |
321428d7b3dSmrg		  ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL |
322428d7b3dSmrg		  texcoordtype | ENABLE_ADDR_V_CNTL |
323428d7b3dSmrg		  TEXCOORD_ADDR_V_MODE(wrap_mode) |
324428d7b3dSmrg		  ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode));
325428d7b3dSmrg	/* map texel stream */
326428d7b3dSmrg	OUT_BATCH(_3DSTATE_MAP_COORD_SETBIND_CMD);
327428d7b3dSmrg	if (unit == 0)
328428d7b3dSmrg		OUT_BATCH(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) |
329428d7b3dSmrg			  TEXBIND_SET1(TEXCOORDSRC_KEEP) |
330428d7b3dSmrg			  TEXBIND_SET2(TEXCOORDSRC_KEEP) |
331428d7b3dSmrg			  TEXBIND_SET3(TEXCOORDSRC_KEEP));
332428d7b3dSmrg	else
333428d7b3dSmrg		OUT_BATCH(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) |
334428d7b3dSmrg			  TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) |
335428d7b3dSmrg			  TEXBIND_SET2(TEXCOORDSRC_KEEP) |
336428d7b3dSmrg			  TEXBIND_SET3(TEXCOORDSRC_KEEP));
337428d7b3dSmrg	OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD | (unit << 16) |
338428d7b3dSmrg		  DISABLE_TEX_STREAM_BUMP |
339428d7b3dSmrg		  ENABLE_TEX_STREAM_COORD_SET |
340428d7b3dSmrg		  TEX_STREAM_COORD_SET(unit) |
341428d7b3dSmrg		  ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(unit));
342428d7b3dSmrg}
343428d7b3dSmrg
344428d7b3dSmrgBool
345428d7b3dSmrgi830_check_composite(int op,
346428d7b3dSmrg		     PicturePtr source_picture,
347428d7b3dSmrg		     PicturePtr mask_picture,
348428d7b3dSmrg		     PicturePtr dest_picture,
349428d7b3dSmrg		     int width, int height)
350428d7b3dSmrg{
351428d7b3dSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(dest_picture->pDrawable->pScreen);
352428d7b3dSmrg	uint32_t tmp1;
353428d7b3dSmrg
354428d7b3dSmrg	/* Check for unsupported compositing operations. */
355428d7b3dSmrg	if (op >= sizeof(i830_blend_op) / sizeof(i830_blend_op[0])) {
356428d7b3dSmrg		intel_uxa_debug_fallback(scrn, "Unsupported Composite op 0x%x\n",
357428d7b3dSmrg				     op);
358428d7b3dSmrg		return FALSE;
359428d7b3dSmrg	}
360428d7b3dSmrg
361428d7b3dSmrg	if (mask_picture != NULL && mask_picture->componentAlpha &&
362428d7b3dSmrg	    PICT_FORMAT_RGB(mask_picture->format)) {
363428d7b3dSmrg		/* Check if it's component alpha that relies on a source alpha and on
364428d7b3dSmrg		 * the source value.  We can only get one of those into the single
365428d7b3dSmrg		 * source value that we get to blend with.
366428d7b3dSmrg		 */
367428d7b3dSmrg		if (i830_blend_op[op].src_alpha &&
368428d7b3dSmrg		    (i830_blend_op[op].src_blend != BLENDFACTOR_ZERO)) {
369428d7b3dSmrg			intel_uxa_debug_fallback(scrn, "Component alpha not "
370428d7b3dSmrg					     "supported with source alpha and "
371428d7b3dSmrg					     "source value blending.\n");
372428d7b3dSmrg			return FALSE;
373428d7b3dSmrg		}
374428d7b3dSmrg	}
375428d7b3dSmrg
376428d7b3dSmrg	if (!i830_get_dest_format(dest_picture, &tmp1)) {
377428d7b3dSmrg		intel_uxa_debug_fallback(scrn, "Get Color buffer format\n");
378428d7b3dSmrg		return FALSE;
379428d7b3dSmrg	}
380428d7b3dSmrg
381428d7b3dSmrg	if (width > 2048 || height > 2048) {
382428d7b3dSmrg		intel_uxa_debug_fallback(scrn, "Operation is too large (%d, %d)\n", width, height);
383428d7b3dSmrg		return FALSE;
384428d7b3dSmrg	}
385428d7b3dSmrg
386428d7b3dSmrg	return TRUE;
387428d7b3dSmrg}
388428d7b3dSmrg
389428d7b3dSmrgBool
390428d7b3dSmrgi830_check_composite_target(PixmapPtr pixmap)
391428d7b3dSmrg{
392428d7b3dSmrg	if (pixmap->drawable.width > 2048 || pixmap->drawable.height > 2048)
393428d7b3dSmrg		return FALSE;
394428d7b3dSmrg
395428d7b3dSmrg	if(!intel_uxa_check_pitch_3d(pixmap))
396428d7b3dSmrg		return FALSE;
397428d7b3dSmrg
398428d7b3dSmrg	return TRUE;
399428d7b3dSmrg}
400428d7b3dSmrg
401428d7b3dSmrgBool
402428d7b3dSmrgi830_check_composite_texture(ScreenPtr screen, PicturePtr picture)
403428d7b3dSmrg{
404428d7b3dSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
405428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
406428d7b3dSmrg
407428d7b3dSmrg	if (picture->repeatType > RepeatReflect) {
408428d7b3dSmrg		intel_uxa_debug_fallback(scrn, "Unsupported picture repeat %d\n",
409428d7b3dSmrg			     picture->repeatType);
410428d7b3dSmrg		return FALSE;
411428d7b3dSmrg	}
412428d7b3dSmrg
413428d7b3dSmrg	if (picture->filter != PictFilterNearest &&
414428d7b3dSmrg	    picture->filter != PictFilterBilinear) {
415428d7b3dSmrg		intel_uxa_debug_fallback(scrn, "Unsupported filter 0x%x\n",
416428d7b3dSmrg				     picture->filter);
417428d7b3dSmrg		return FALSE;
418428d7b3dSmrg	}
419428d7b3dSmrg
420428d7b3dSmrg	if (picture->pDrawable) {
421428d7b3dSmrg		int w, h;
422428d7b3dSmrg
423428d7b3dSmrg		w = picture->pDrawable->width;
424428d7b3dSmrg		h = picture->pDrawable->height;
425428d7b3dSmrg		if ((w > 2048) || (h > 2048)) {
426428d7b3dSmrg			intel_uxa_debug_fallback(scrn,
427428d7b3dSmrg					     "Picture w/h too large (%dx%d)\n",
428428d7b3dSmrg					     w, h);
429428d7b3dSmrg			return FALSE;
430428d7b3dSmrg		}
431428d7b3dSmrg
432428d7b3dSmrg		/* XXX we can use the xrgb32 types if there the picture covers the clip */
433428d7b3dSmrg		if (!i8xx_get_card_format(intel, picture)) {
434428d7b3dSmrg			intel_uxa_debug_fallback(scrn, "Unsupported picture format "
435428d7b3dSmrg					     "0x%x\n",
436428d7b3dSmrg					     (int)picture->format);
437428d7b3dSmrg			return FALSE;
438428d7b3dSmrg		}
439428d7b3dSmrg
440428d7b3dSmrg		return TRUE;
441428d7b3dSmrg	}
442428d7b3dSmrg
443428d7b3dSmrg	return FALSE;
444428d7b3dSmrg}
445428d7b3dSmrg
446428d7b3dSmrgBool
447428d7b3dSmrgi830_prepare_composite(int op, PicturePtr source_picture,
448428d7b3dSmrg		       PicturePtr mask_picture, PicturePtr dest_picture,
449428d7b3dSmrg		       PixmapPtr source, PixmapPtr mask, PixmapPtr dest)
450428d7b3dSmrg{
451428d7b3dSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(dest_picture->pDrawable->pScreen);
452428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
453428d7b3dSmrg	drm_intel_bo *bo_table[] = {
454428d7b3dSmrg		NULL,		/* batch_bo */
455428d7b3dSmrg		intel_uxa_get_pixmap_bo(source),
456428d7b3dSmrg		mask ? intel_uxa_get_pixmap_bo(mask) : NULL,
457428d7b3dSmrg		intel_uxa_get_pixmap_bo(dest),
458428d7b3dSmrg	};
459428d7b3dSmrg
460428d7b3dSmrg	intel->render_source_picture = source_picture;
461428d7b3dSmrg	intel->render_source = source;
462428d7b3dSmrg	intel->render_mask_picture = mask_picture;
463428d7b3dSmrg	intel->render_mask = mask;
464428d7b3dSmrg	intel->render_dest_picture = dest_picture;
465428d7b3dSmrg	intel->render_dest = dest;
466428d7b3dSmrg
467428d7b3dSmrg	if (!intel_uxa_check_pitch_3d(source))
468428d7b3dSmrg		return FALSE;
469428d7b3dSmrg	if (mask) {
470428d7b3dSmrg		if (mask_picture->componentAlpha &&
471428d7b3dSmrg		    PICT_FORMAT_RGB(mask_picture->format)) {
472428d7b3dSmrg			/* Check if it's component alpha that relies on a source alpha and on
473428d7b3dSmrg			 * the source value.  We can only get one of those into the single
474428d7b3dSmrg			 * source value that we get to blend with.
475428d7b3dSmrg			 */
476428d7b3dSmrg			if (i830_blend_op[op].src_alpha &&
477428d7b3dSmrg			    (i830_blend_op[op].src_blend != BLENDFACTOR_ZERO)) {
478428d7b3dSmrg				intel_uxa_debug_fallback(scrn, "Component alpha not "
479428d7b3dSmrg						     "supported with source alpha and "
480428d7b3dSmrg						     "source value blending.\n");
481428d7b3dSmrg				return FALSE;
482428d7b3dSmrg			}
483428d7b3dSmrg		}
484428d7b3dSmrg		if (!intel_uxa_check_pitch_3d(mask))
485428d7b3dSmrg			return FALSE;
486428d7b3dSmrg	}
487428d7b3dSmrg	if (!intel_uxa_check_pitch_3d(dest))
488428d7b3dSmrg		return FALSE;
489428d7b3dSmrg
490428d7b3dSmrg	if (!i830_get_dest_format(dest_picture, &intel->render_dest_format))
491428d7b3dSmrg		return FALSE;
492428d7b3dSmrg
493428d7b3dSmrg	if (!intel_uxa_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
494428d7b3dSmrg		return FALSE;
495428d7b3dSmrg
496428d7b3dSmrg	if (mask) {
497428d7b3dSmrg		intel->transform[1] = NULL;
498428d7b3dSmrg		intel->scale_units[1][0] = -1;
499428d7b3dSmrg		intel->scale_units[1][1] = -1;
500428d7b3dSmrg	}
501428d7b3dSmrg
502428d7b3dSmrg	{
503428d7b3dSmrg		uint32_t cblend, ablend, blendctl;
504428d7b3dSmrg
505428d7b3dSmrg		/* If component alpha is active in the mask and the blend operation
506428d7b3dSmrg		 * uses the source alpha, then we know we don't need the source
507428d7b3dSmrg		 * value (otherwise we would have hit a fallback earlier), so we
508428d7b3dSmrg		 * provide the source alpha (src.A * mask.X) as output color.
509428d7b3dSmrg		 * Conversely, if CA is set and we don't need the source alpha, then
510428d7b3dSmrg		 * we produce the source value (src.X * mask.X) and the source alpha
511428d7b3dSmrg		 * is unused..  Otherwise, we provide the non-CA source value
512428d7b3dSmrg		 * (src.X * mask.A).
513428d7b3dSmrg		 *
514428d7b3dSmrg		 * The PICT_FORMAT_RGB(pict) == 0 fixups are not needed on 855+'s a8
515428d7b3dSmrg		 * pictures, but we need to implement it for 830/845 and there's no
516428d7b3dSmrg		 * harm done in leaving it in.
517428d7b3dSmrg		 */
518428d7b3dSmrg		cblend =
519428d7b3dSmrg		    TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULE |
520428d7b3dSmrg		    TB0C_OUTPUT_WRITE_CURRENT;
521428d7b3dSmrg		ablend =
522428d7b3dSmrg		    TB0A_RESULT_SCALE_1X | TB0A_OP_MODULE |
523428d7b3dSmrg		    TB0A_OUTPUT_WRITE_CURRENT;
524428d7b3dSmrg
525428d7b3dSmrg		/* Get the source picture's channels into TBx_ARG1 */
526428d7b3dSmrg		if ((mask_picture != NULL &&
527428d7b3dSmrg		     mask_picture->componentAlpha &&
528428d7b3dSmrg		     PICT_FORMAT_RGB(mask_picture->format) &&
529428d7b3dSmrg		     i830_blend_op[op].src_alpha)
530428d7b3dSmrg		    || dest_picture->format == PICT_a8) {
531428d7b3dSmrg			/* Producing source alpha value, so the first set of channels
532428d7b3dSmrg			 * is src.A instead of src.X.  We also do this if the destination
533428d7b3dSmrg			 * is a8, in which case src.G is what's written, and the other
534428d7b3dSmrg			 * channels are ignored.
535428d7b3dSmrg			 */
536428d7b3dSmrg			ablend |= TB0A_ARG1_SEL_TEXEL0;
537428d7b3dSmrg			cblend |= TB0C_ARG1_SEL_TEXEL0 | TB0C_ARG1_REPLICATE_ALPHA;
538428d7b3dSmrg		} else {
539428d7b3dSmrg			if (PICT_FORMAT_RGB(source_picture->format) != 0)
540428d7b3dSmrg				cblend |= TB0C_ARG1_SEL_TEXEL0;
541428d7b3dSmrg			else
542428d7b3dSmrg				cblend |= TB0C_ARG1_SEL_ONE | TB0C_ARG1_INVERT;	/* 0.0 */
543428d7b3dSmrg			ablend |= TB0A_ARG1_SEL_TEXEL0;
544428d7b3dSmrg		}
545428d7b3dSmrg
546428d7b3dSmrg		if (mask) {
547428d7b3dSmrg			cblend |= TB0C_ARG2_SEL_TEXEL1;
548428d7b3dSmrg			if (dest_picture->format == PICT_a8 ||
549428d7b3dSmrg			    ! mask_picture->componentAlpha ||
550428d7b3dSmrg			    ! PICT_FORMAT_RGB(mask_picture->format))
551428d7b3dSmrg				cblend |= TB0C_ARG2_REPLICATE_ALPHA;
552428d7b3dSmrg			ablend |= TB0A_ARG2_SEL_TEXEL1;
553428d7b3dSmrg		} else {
554428d7b3dSmrg			cblend |= TB0C_ARG2_SEL_ONE;
555428d7b3dSmrg			ablend |= TB0A_ARG2_SEL_ONE;
556428d7b3dSmrg		}
557428d7b3dSmrg
558428d7b3dSmrg		if (!i830_get_blend_cntl
559428d7b3dSmrg		    (scrn, op, mask_picture, dest_picture->format, &blendctl)) {
560428d7b3dSmrg			return FALSE;
561428d7b3dSmrg		}
562428d7b3dSmrg
563428d7b3dSmrg		intel->cblend = cblend;
564428d7b3dSmrg		intel->ablend = ablend;
565428d7b3dSmrg		intel->s8_blendctl = blendctl;
566428d7b3dSmrg	}
567428d7b3dSmrg
568428d7b3dSmrg	if (intel_uxa_pixmap_is_dirty(source) || intel_uxa_pixmap_is_dirty(mask))
569428d7b3dSmrg		intel_batch_emit_flush(scrn);
570428d7b3dSmrg
571428d7b3dSmrg	intel->needs_render_state_emit = TRUE;
572428d7b3dSmrg
573428d7b3dSmrg	return TRUE;
574428d7b3dSmrg}
575428d7b3dSmrg
576428d7b3dSmrgstatic void i830_emit_composite_state(ScrnInfoPtr scrn)
577428d7b3dSmrg{
578428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
579428d7b3dSmrg	uint32_t vf2, tiling_bits;
580428d7b3dSmrg	uint32_t texcoordfmt = 0;
581428d7b3dSmrg
582428d7b3dSmrg	intel->needs_render_state_emit = FALSE;
583428d7b3dSmrg
584428d7b3dSmrg	IntelEmitInvarientState(scrn);
585428d7b3dSmrg	intel->last_3d = LAST_3D_RENDER;
586428d7b3dSmrg
587428d7b3dSmrg	assert(intel->in_batch_atomic);
588428d7b3dSmrg
589428d7b3dSmrg	if (intel_uxa_pixmap_tiled(intel->render_dest)) {
590428d7b3dSmrg		tiling_bits = BUF_3D_TILED_SURFACE;
591428d7b3dSmrg		if (intel_uxa_get_pixmap_private(intel->render_dest)->tiling
592428d7b3dSmrg				== I915_TILING_Y)
593428d7b3dSmrg			tiling_bits |= BUF_3D_TILE_WALK_Y;
594428d7b3dSmrg	} else
595428d7b3dSmrg		tiling_bits = 0;
596428d7b3dSmrg
597428d7b3dSmrg	OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
598428d7b3dSmrg	OUT_BATCH(BUF_3D_ID_COLOR_BACK | tiling_bits |
599428d7b3dSmrg		  BUF_3D_PITCH(intel_pixmap_pitch(intel->render_dest)));
600428d7b3dSmrg	OUT_RELOC_PIXMAP(intel->render_dest,
601428d7b3dSmrg			 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
602428d7b3dSmrg
603428d7b3dSmrg	OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
604428d7b3dSmrg	OUT_BATCH(intel->render_dest_format);
605428d7b3dSmrg
606428d7b3dSmrg	OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
607428d7b3dSmrg	OUT_BATCH(0);
608428d7b3dSmrg	OUT_BATCH(0);		/* ymin, xmin */
609428d7b3dSmrg	OUT_BATCH(DRAW_YMAX(intel->render_dest->drawable.height - 1) |
610428d7b3dSmrg		  DRAW_XMAX(intel->render_dest->drawable.width - 1));
611428d7b3dSmrg	OUT_BATCH(0);		/* yorig, xorig */
612428d7b3dSmrg
613428d7b3dSmrg	OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
614428d7b3dSmrg		  I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2);
615428d7b3dSmrg	if (intel->render_mask)
616428d7b3dSmrg		vf2 = 2 << 12;	/* 2 texture coord sets */
617428d7b3dSmrg	else
618428d7b3dSmrg		vf2 = 1 << 12;
619428d7b3dSmrg	OUT_BATCH(vf2);		/* number of coordinate sets */
620428d7b3dSmrg	OUT_BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY);
621428d7b3dSmrg	OUT_BATCH(S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD | intel->
622428d7b3dSmrg		  s8_blendctl | S8_ENABLE_COLOR_BUFFER_WRITE);
623428d7b3dSmrg
624428d7b3dSmrg	OUT_BATCH(_3DSTATE_INDPT_ALPHA_BLEND_CMD | DISABLE_INDPT_ALPHA_BLEND);
625428d7b3dSmrg
626428d7b3dSmrg	OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
627428d7b3dSmrg		  LOAD_TEXTURE_BLEND_STAGE(0) | 1);
628428d7b3dSmrg	OUT_BATCH(intel->cblend);
629428d7b3dSmrg	OUT_BATCH(intel->ablend);
630428d7b3dSmrg
631428d7b3dSmrg	OUT_BATCH(_3DSTATE_ENABLES_1_CMD | DISABLE_LOGIC_OP |
632428d7b3dSmrg		  DISABLE_STENCIL_TEST | DISABLE_DEPTH_BIAS |
633428d7b3dSmrg		  DISABLE_SPEC_ADD | DISABLE_FOG | DISABLE_ALPHA_TEST |
634428d7b3dSmrg		  ENABLE_COLOR_BLEND | DISABLE_DEPTH_TEST);
635428d7b3dSmrg	/* We have to explicitly say we don't want write disabled */
636428d7b3dSmrg	OUT_BATCH(_3DSTATE_ENABLES_2_CMD | ENABLE_COLOR_MASK |
637428d7b3dSmrg		  DISABLE_STENCIL_WRITE | ENABLE_TEX_CACHE |
638428d7b3dSmrg		  DISABLE_DITHER | ENABLE_COLOR_WRITE | DISABLE_DEPTH_WRITE);
639428d7b3dSmrg
640428d7b3dSmrg	if (intel_uxa_transform_is_affine(intel->render_source_picture->transform))
641428d7b3dSmrg		texcoordfmt |= (TEXCOORDFMT_2D << 0);
642428d7b3dSmrg	else
643428d7b3dSmrg		texcoordfmt |= (TEXCOORDFMT_3D << 0);
644428d7b3dSmrg	if (intel->render_mask) {
645428d7b3dSmrg		if (intel_uxa_transform_is_affine
646428d7b3dSmrg		    (intel->render_mask_picture->transform))
647428d7b3dSmrg			texcoordfmt |= (TEXCOORDFMT_2D << 2);
648428d7b3dSmrg		else
649428d7b3dSmrg			texcoordfmt |= (TEXCOORDFMT_3D << 2);
650428d7b3dSmrg	}
651428d7b3dSmrg	OUT_BATCH(_3DSTATE_VERTEX_FORMAT_2_CMD | texcoordfmt);
652428d7b3dSmrg
653428d7b3dSmrg	i830_texture_setup(intel->render_source_picture, intel->render_source, 0);
654428d7b3dSmrg	if (intel->render_mask) {
655428d7b3dSmrg		i830_texture_setup(intel->render_mask_picture,
656428d7b3dSmrg				   intel->render_mask, 1);
657428d7b3dSmrg	}
658428d7b3dSmrg}
659428d7b3dSmrg
660428d7b3dSmrg/* Emit the vertices for a single composite rectangle.
661428d7b3dSmrg *
662428d7b3dSmrg * This function is no longer shared between i830 and i915 generation code.
663428d7b3dSmrg */
664428d7b3dSmrgstatic void
665428d7b3dSmrgi830_emit_composite_primitive(PixmapPtr dest,
666428d7b3dSmrg			      int srcX, int srcY,
667428d7b3dSmrg			      int maskX, int maskY,
668428d7b3dSmrg			      int dstX, int dstY, int w, int h)
669428d7b3dSmrg{
670428d7b3dSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen);
671428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
672428d7b3dSmrg	Bool is_affine_src, is_affine_mask = TRUE;
673428d7b3dSmrg	int per_vertex;
674428d7b3dSmrg	float src_x[3], src_y[3], src_w[3], mask_x[3], mask_y[3], mask_w[3];
675428d7b3dSmrg
676428d7b3dSmrg	per_vertex = 2;		/* dest x/y */
677428d7b3dSmrg
678428d7b3dSmrg	{
679428d7b3dSmrg		float x = srcX, y = srcY;
680428d7b3dSmrg
681428d7b3dSmrg		is_affine_src = intel_uxa_transform_is_affine(intel->transform[0]);
682428d7b3dSmrg		if (is_affine_src) {
683428d7b3dSmrg			if (!intel_uxa_get_transformed_coordinates(x, y,
684428d7b3dSmrg							      intel->
685428d7b3dSmrg							      transform[0],
686428d7b3dSmrg							      &src_x[0],
687428d7b3dSmrg							      &src_y[0]))
688428d7b3dSmrg				return;
689428d7b3dSmrg
690428d7b3dSmrg			if (!intel_uxa_get_transformed_coordinates(x, y + h,
691428d7b3dSmrg							      intel->
692428d7b3dSmrg							      transform[0],
693428d7b3dSmrg							      &src_x[1],
694428d7b3dSmrg							      &src_y[1]))
695428d7b3dSmrg				return;
696428d7b3dSmrg
697428d7b3dSmrg			if (!intel_uxa_get_transformed_coordinates(x + w, y + h,
698428d7b3dSmrg							      intel->
699428d7b3dSmrg							      transform[0],
700428d7b3dSmrg							      &src_x[2],
701428d7b3dSmrg							      &src_y[2]))
702428d7b3dSmrg				return;
703428d7b3dSmrg
704428d7b3dSmrg			per_vertex += 2;	/* src x/y */
705428d7b3dSmrg		} else {
706428d7b3dSmrg			if (!intel_uxa_get_transformed_coordinates_3d(x, y,
707428d7b3dSmrg								 intel->
708428d7b3dSmrg								 transform[0],
709428d7b3dSmrg								 &src_x[0],
710428d7b3dSmrg								 &src_y[0],
711428d7b3dSmrg								 &src_w[0]))
712428d7b3dSmrg				return;
713428d7b3dSmrg
714428d7b3dSmrg			if (!intel_uxa_get_transformed_coordinates_3d(x, y + h,
715428d7b3dSmrg								 intel->
716428d7b3dSmrg								 transform[0],
717428d7b3dSmrg								 &src_x[1],
718428d7b3dSmrg								 &src_y[1],
719428d7b3dSmrg								 &src_w[1]))
720428d7b3dSmrg				return;
721428d7b3dSmrg
722428d7b3dSmrg			if (!intel_uxa_get_transformed_coordinates_3d(x + w, y + h,
723428d7b3dSmrg								 intel->
724428d7b3dSmrg								 transform[0],
725428d7b3dSmrg								 &src_x[2],
726428d7b3dSmrg								 &src_y[2],
727428d7b3dSmrg								 &src_w[2]))
728428d7b3dSmrg				return;
729428d7b3dSmrg
730428d7b3dSmrg			per_vertex += 3;	/* src x/y/w */
731428d7b3dSmrg		}
732428d7b3dSmrg	}
733428d7b3dSmrg
734428d7b3dSmrg	if (intel->render_mask) {
735428d7b3dSmrg		float x = maskX, y = maskY;
736428d7b3dSmrg
737428d7b3dSmrg		is_affine_mask = intel_uxa_transform_is_affine(intel->transform[1]);
738428d7b3dSmrg		if (is_affine_mask) {
739428d7b3dSmrg			if (!intel_uxa_get_transformed_coordinates(x, y,
740428d7b3dSmrg							      intel->
741428d7b3dSmrg							      transform[1],
742428d7b3dSmrg							      &mask_x[0],
743428d7b3dSmrg							      &mask_y[0]))
744428d7b3dSmrg				return;
745428d7b3dSmrg
746428d7b3dSmrg			if (!intel_uxa_get_transformed_coordinates(x, y + h,
747428d7b3dSmrg							      intel->
748428d7b3dSmrg							      transform[1],
749428d7b3dSmrg							      &mask_x[1],
750428d7b3dSmrg							      &mask_y[1]))
751428d7b3dSmrg				return;
752428d7b3dSmrg
753428d7b3dSmrg			if (!intel_uxa_get_transformed_coordinates(x + w, y + h,
754428d7b3dSmrg							      intel->
755428d7b3dSmrg							      transform[1],
756428d7b3dSmrg							      &mask_x[2],
757428d7b3dSmrg							      &mask_y[2]))
758428d7b3dSmrg				return;
759428d7b3dSmrg
760428d7b3dSmrg			per_vertex += 2;	/* mask x/y */
761428d7b3dSmrg		} else {
762428d7b3dSmrg			if (!intel_uxa_get_transformed_coordinates_3d(x, y,
763428d7b3dSmrg								 intel->
764428d7b3dSmrg								 transform[1],
765428d7b3dSmrg								 &mask_x[0],
766428d7b3dSmrg								 &mask_y[0],
767428d7b3dSmrg								 &mask_w[0]))
768428d7b3dSmrg				return;
769428d7b3dSmrg
770428d7b3dSmrg			if (!intel_uxa_get_transformed_coordinates_3d(x, y + h,
771428d7b3dSmrg								 intel->
772428d7b3dSmrg								 transform[1],
773428d7b3dSmrg								 &mask_x[1],
774428d7b3dSmrg								 &mask_y[1],
775428d7b3dSmrg								 &mask_w[1]))
776428d7b3dSmrg				return;
777428d7b3dSmrg
778428d7b3dSmrg			if (!intel_uxa_get_transformed_coordinates_3d(x + w, y + h,
779428d7b3dSmrg								 intel->
780428d7b3dSmrg								 transform[1],
781428d7b3dSmrg								 &mask_x[2],
782428d7b3dSmrg								 &mask_y[2],
783428d7b3dSmrg								 &mask_w[2]))
784428d7b3dSmrg				return;
785428d7b3dSmrg
786428d7b3dSmrg			per_vertex += 3;	/* mask x/y/w */
787428d7b3dSmrg		}
788428d7b3dSmrg	}
789428d7b3dSmrg
790428d7b3dSmrg	if (intel->vertex_count == 0) {
791428d7b3dSmrg		intel->vertex_index = intel->batch_used;
792428d7b3dSmrg		OUT_BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST);
793428d7b3dSmrg	}
794428d7b3dSmrg	OUT_BATCH_F(dstX + w);
795428d7b3dSmrg	OUT_BATCH_F(dstY + h);
796428d7b3dSmrg	OUT_BATCH_F(src_x[2] / intel->scale_units[0][0]);
797428d7b3dSmrg	OUT_BATCH_F(src_y[2] / intel->scale_units[0][1]);
798428d7b3dSmrg	if (!is_affine_src) {
799428d7b3dSmrg		OUT_BATCH_F(src_w[2]);
800428d7b3dSmrg	}
801428d7b3dSmrg	if (intel->render_mask) {
802428d7b3dSmrg		OUT_BATCH_F(mask_x[2] / intel->scale_units[1][0]);
803428d7b3dSmrg		OUT_BATCH_F(mask_y[2] / intel->scale_units[1][1]);
804428d7b3dSmrg		if (!is_affine_mask) {
805428d7b3dSmrg			OUT_BATCH_F(mask_w[2]);
806428d7b3dSmrg		}
807428d7b3dSmrg	}
808428d7b3dSmrg
809428d7b3dSmrg	OUT_BATCH_F(dstX);
810428d7b3dSmrg	OUT_BATCH_F(dstY + h);
811428d7b3dSmrg	OUT_BATCH_F(src_x[1] / intel->scale_units[0][0]);
812428d7b3dSmrg	OUT_BATCH_F(src_y[1] / intel->scale_units[0][1]);
813428d7b3dSmrg	if (!is_affine_src) {
814428d7b3dSmrg		OUT_BATCH_F(src_w[1]);
815428d7b3dSmrg	}
816428d7b3dSmrg	if (intel->render_mask) {
817428d7b3dSmrg		OUT_BATCH_F(mask_x[1] / intel->scale_units[1][0]);
818428d7b3dSmrg		OUT_BATCH_F(mask_y[1] / intel->scale_units[1][1]);
819428d7b3dSmrg		if (!is_affine_mask) {
820428d7b3dSmrg			OUT_BATCH_F(mask_w[1]);
821428d7b3dSmrg		}
822428d7b3dSmrg	}
823428d7b3dSmrg
824428d7b3dSmrg	OUT_BATCH_F(dstX);
825428d7b3dSmrg	OUT_BATCH_F(dstY);
826428d7b3dSmrg	OUT_BATCH_F(src_x[0] / intel->scale_units[0][0]);
827428d7b3dSmrg	OUT_BATCH_F(src_y[0] / intel->scale_units[0][1]);
828428d7b3dSmrg	if (!is_affine_src) {
829428d7b3dSmrg		OUT_BATCH_F(src_w[0]);
830428d7b3dSmrg	}
831428d7b3dSmrg	if (intel->render_mask) {
832428d7b3dSmrg		OUT_BATCH_F(mask_x[0] / intel->scale_units[1][0]);
833428d7b3dSmrg		OUT_BATCH_F(mask_y[0] / intel->scale_units[1][1]);
834428d7b3dSmrg		if (!is_affine_mask) {
835428d7b3dSmrg			OUT_BATCH_F(mask_w[0]);
836428d7b3dSmrg		}
837428d7b3dSmrg	}
838428d7b3dSmrg
839428d7b3dSmrg	intel->vertex_count += 3 * per_vertex;
840428d7b3dSmrg
841428d7b3dSmrg}
842428d7b3dSmrg
843428d7b3dSmrgvoid i830_vertex_flush(intel_screen_private *intel)
844428d7b3dSmrg{
845428d7b3dSmrg	if (intel->vertex_count) {
846428d7b3dSmrg		intel->batch_ptr[intel->vertex_index] |= intel->vertex_count - 1;
847428d7b3dSmrg		intel->vertex_count = 0;
848428d7b3dSmrg	}
849428d7b3dSmrg}
850428d7b3dSmrg
851428d7b3dSmrg/**
852428d7b3dSmrg * Do a single rectangle composite operation.
853428d7b3dSmrg */
854428d7b3dSmrgvoid
855428d7b3dSmrgi830_composite(PixmapPtr dest, int srcX, int srcY, int maskX, int maskY,
856428d7b3dSmrg	       int dstX, int dstY, int w, int h)
857428d7b3dSmrg{
858428d7b3dSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen);
859428d7b3dSmrg	intel_screen_private *intel = intel_get_screen_private(scrn);
860428d7b3dSmrg
861428d7b3dSmrg	intel_batch_start_atomic(scrn, 58 +	/* invarient */
862428d7b3dSmrg				 22 +	/* setup */
863428d7b3dSmrg				 20 +	/* 2 * setup_texture */
864428d7b3dSmrg				 1 + 30 /* verts */ );
865428d7b3dSmrg
866428d7b3dSmrg	if (intel->needs_render_state_emit)
867428d7b3dSmrg		i830_emit_composite_state(scrn);
868428d7b3dSmrg
869428d7b3dSmrg	i830_emit_composite_primitive(dest, srcX, srcY, maskX, maskY, dstX,
870428d7b3dSmrg				      dstY, w, h);
871428d7b3dSmrg
872428d7b3dSmrg	intel_batch_end_atomic(scrn);
873428d7b3dSmrg}
874428d7b3dSmrg
875428d7b3dSmrgvoid i830_batch_commit_notify(intel_screen_private *intel)
876428d7b3dSmrg{
877428d7b3dSmrg	intel->needs_render_state_emit = TRUE;
878428d7b3dSmrg}
879