1fa225cbcSrjs/*
2fa225cbcSrjs * Copyright © 2006 Intel Corporation
3fa225cbcSrjs *
4fa225cbcSrjs * Permission is hereby granted, free of charge, to any person obtaining a
5fa225cbcSrjs * copy of this software and associated documentation files (the "Software"),
6fa225cbcSrjs * to deal in the Software without restriction, including without limitation
7fa225cbcSrjs * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8fa225cbcSrjs * and/or sell copies of the Software, and to permit persons to whom the
9fa225cbcSrjs * Software is furnished to do so, subject to the following conditions:
10fa225cbcSrjs *
11fa225cbcSrjs * The above copyright notice and this permission notice (including the next
12fa225cbcSrjs * paragraph) shall be included in all copies or substantial portions of the
13fa225cbcSrjs * Software.
14fa225cbcSrjs *
15fa225cbcSrjs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16fa225cbcSrjs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17fa225cbcSrjs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18fa225cbcSrjs * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19fa225cbcSrjs * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20fa225cbcSrjs * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21fa225cbcSrjs * SOFTWARE.
22fa225cbcSrjs *
23fa225cbcSrjs * Authors:
24fa225cbcSrjs *    Wang Zhenyu <zhenyu.z.wang@intel.com>
25fa225cbcSrjs *    Eric Anholt <eric@anholt.net>
26fa225cbcSrjs *
27fa225cbcSrjs */
28fa225cbcSrjs
29fa225cbcSrjs#ifdef HAVE_CONFIG_H
30fa225cbcSrjs#include "config.h"
31fa225cbcSrjs#endif
32fa225cbcSrjs
33fa225cbcSrjs#include "xf86.h"
34fa225cbcSrjs#include "i830.h"
35fa225cbcSrjs#include "i830_reg.h"
36fa225cbcSrjs
37fa225cbcSrjsstruct blendinfo {
38fa225cbcSrjs    Bool dst_alpha;
39fa225cbcSrjs    Bool src_alpha;
40fa225cbcSrjs    uint32_t src_blend;
41fa225cbcSrjs    uint32_t dst_blend;
42fa225cbcSrjs};
43fa225cbcSrjs
44fa225cbcSrjsstruct formatinfo {
45fa225cbcSrjs    int fmt;
46fa225cbcSrjs    uint32_t card_fmt;
47fa225cbcSrjs};
48fa225cbcSrjs
49fa225cbcSrjs#define TB0C_LAST_STAGE	(1 << 31)
50fa225cbcSrjs#define TB0C_RESULT_SCALE_1X		(0 << 29)
51fa225cbcSrjs#define TB0C_RESULT_SCALE_2X		(1 << 29)
52fa225cbcSrjs#define TB0C_RESULT_SCALE_4X		(2 << 29)
53fa225cbcSrjs#define TB0C_OP_MODULE			(3 << 25)
54fa225cbcSrjs#define TB0C_OUTPUT_WRITE_CURRENT	(0 << 24)
55fa225cbcSrjs#define TB0C_OUTPUT_WRITE_ACCUM		(1 << 24)
56fa225cbcSrjs#define TB0C_ARG3_REPLICATE_ALPHA 	(1<<23)
57fa225cbcSrjs#define TB0C_ARG3_INVERT		(1<<22)
58fa225cbcSrjs#define TB0C_ARG3_SEL_XXX
59fa225cbcSrjs#define TB0C_ARG2_REPLICATE_ALPHA 	(1<<17)
60fa225cbcSrjs#define TB0C_ARG2_INVERT		(1<<16)
61fa225cbcSrjs#define TB0C_ARG2_SEL_ONE		(0 << 12)
62fa225cbcSrjs#define TB0C_ARG2_SEL_FACTOR		(1 << 12)
63fa225cbcSrjs#define TB0C_ARG2_SEL_TEXEL0		(6 << 12)
64fa225cbcSrjs#define TB0C_ARG2_SEL_TEXEL1		(7 << 12)
65fa225cbcSrjs#define TB0C_ARG2_SEL_TEXEL2		(8 << 12)
66fa225cbcSrjs#define TB0C_ARG2_SEL_TEXEL3		(9 << 12)
67fa225cbcSrjs#define TB0C_ARG1_REPLICATE_ALPHA 	(1<<11)
68fa225cbcSrjs#define TB0C_ARG1_INVERT		(1<<10)
69fa225cbcSrjs#define TB0C_ARG1_SEL_ONE		(0 << 6)
70fa225cbcSrjs#define TB0C_ARG1_SEL_TEXEL0		(6 << 6)
71fa225cbcSrjs#define TB0C_ARG1_SEL_TEXEL1		(7 << 6)
72fa225cbcSrjs#define TB0C_ARG1_SEL_TEXEL2		(8 << 6)
73fa225cbcSrjs#define TB0C_ARG1_SEL_TEXEL3		(9 << 6)
74fa225cbcSrjs#define TB0C_ARG0_REPLICATE_ALPHA 	(1<<5)
75fa225cbcSrjs#define TB0C_ARG0_SEL_XXX
76fa225cbcSrjs
77fa225cbcSrjs#define TB0A_CTR_STAGE_ENABLE 		(1<<31)
78fa225cbcSrjs#define TB0A_RESULT_SCALE_1X		(0 << 29)
79fa225cbcSrjs#define TB0A_RESULT_SCALE_2X		(1 << 29)
80fa225cbcSrjs#define TB0A_RESULT_SCALE_4X		(2 << 29)
81fa225cbcSrjs#define TB0A_OP_MODULE			(3 << 25)
82fa225cbcSrjs#define TB0A_OUTPUT_WRITE_CURRENT	(0<<24)
83fa225cbcSrjs#define TB0A_OUTPUT_WRITE_ACCUM		(1<<24)
84fa225cbcSrjs#define TB0A_CTR_STAGE_SEL_BITS_XXX
85fa225cbcSrjs#define TB0A_ARG3_SEL_XXX
86fa225cbcSrjs#define TB0A_ARG3_INVERT		(1<<17)
87fa225cbcSrjs#define TB0A_ARG2_INVERT		(1<<16)
88fa225cbcSrjs#define TB0A_ARG2_SEL_ONE		(0 << 12)
89fa225cbcSrjs#define TB0A_ARG2_SEL_TEXEL0		(6 << 12)
90fa225cbcSrjs#define TB0A_ARG2_SEL_TEXEL1		(7 << 12)
91fa225cbcSrjs#define TB0A_ARG2_SEL_TEXEL2		(8 << 12)
92fa225cbcSrjs#define TB0A_ARG2_SEL_TEXEL3		(9 << 12)
93fa225cbcSrjs#define TB0A_ARG1_INVERT		(1<<10)
94fa225cbcSrjs#define TB0A_ARG1_SEL_ONE		(0 << 6)
95fa225cbcSrjs#define TB0A_ARG1_SEL_TEXEL0		(6 << 6)
96fa225cbcSrjs#define TB0A_ARG1_SEL_TEXEL1		(7 << 6)
97fa225cbcSrjs#define TB0A_ARG1_SEL_TEXEL2		(8 << 6)
98fa225cbcSrjs#define TB0A_ARG1_SEL_TEXEL3		(9 << 6)
99fa225cbcSrjs
100fa225cbcSrjsstatic struct blendinfo i830_blend_op[] = {
101fa225cbcSrjs    /* Clear */
102fa225cbcSrjs    {0, 0, BLENDFACTOR_ZERO, 		BLENDFACTOR_ZERO},
103fa225cbcSrjs    /* Src */
104fa225cbcSrjs    {0, 0, BLENDFACTOR_ONE, 		BLENDFACTOR_ZERO},
105fa225cbcSrjs    /* Dst */
106fa225cbcSrjs    {0, 0, BLENDFACTOR_ZERO,		BLENDFACTOR_ONE},
107fa225cbcSrjs    /* Over */
108fa225cbcSrjs    {0, 1, BLENDFACTOR_ONE,		BLENDFACTOR_INV_SRC_ALPHA},
109fa225cbcSrjs    /* OverReverse */
110fa225cbcSrjs    {1, 0, BLENDFACTOR_INV_DST_ALPHA,	BLENDFACTOR_ONE},
111fa225cbcSrjs    /* In */
112fa225cbcSrjs    {1, 0, BLENDFACTOR_DST_ALPHA,	BLENDFACTOR_ZERO},
113fa225cbcSrjs    /* InReverse */
114fa225cbcSrjs    {0, 1, BLENDFACTOR_ZERO,		BLENDFACTOR_SRC_ALPHA},
115fa225cbcSrjs    /* Out */
116fa225cbcSrjs    {1, 0, BLENDFACTOR_INV_DST_ALPHA,	BLENDFACTOR_ZERO},
117fa225cbcSrjs    /* OutReverse */
118fa225cbcSrjs    {0, 1, BLENDFACTOR_ZERO,		BLENDFACTOR_INV_SRC_ALPHA},
119fa225cbcSrjs    /* Atop */
120fa225cbcSrjs    {1, 1, BLENDFACTOR_DST_ALPHA,	BLENDFACTOR_INV_SRC_ALPHA},
121fa225cbcSrjs    /* AtopReverse */
122fa225cbcSrjs    {1, 1, BLENDFACTOR_INV_DST_ALPHA,	BLENDFACTOR_SRC_ALPHA},
123fa225cbcSrjs    /* Xor */
124fa225cbcSrjs    {1, 1, BLENDFACTOR_INV_DST_ALPHA,	BLENDFACTOR_INV_SRC_ALPHA},
125fa225cbcSrjs    /* Add */
126fa225cbcSrjs    {0, 0, BLENDFACTOR_ONE, 		BLENDFACTOR_ONE},
127fa225cbcSrjs};
128fa225cbcSrjs
129fa225cbcSrjs/* The x8* formats could use MT_32BIT_X* on 855+, but since we implement
130fa225cbcSrjs * workarounds for 830/845 anyway, we just rely on those whether the hardware
131fa225cbcSrjs * could handle it for us or not.
132fa225cbcSrjs */
133fa225cbcSrjsstatic struct formatinfo i830_tex_formats[] = {
134fa225cbcSrjs    {PICT_a8r8g8b8, MT_32BIT_ARGB8888 },
135fa225cbcSrjs    {PICT_x8r8g8b8, MT_32BIT_ARGB8888 },
136fa225cbcSrjs    {PICT_a8b8g8r8, MT_32BIT_ABGR8888 },
137fa225cbcSrjs    {PICT_x8b8g8r8, MT_32BIT_ABGR8888 },
138fa225cbcSrjs    {PICT_r5g6b5,   MT_16BIT_RGB565   },
139fa225cbcSrjs    {PICT_a1r5g5b5, MT_16BIT_ARGB1555 },
140fa225cbcSrjs    {PICT_x1r5g5b5, MT_16BIT_ARGB1555 },
141fa225cbcSrjs    {PICT_a8,       MT_8BIT_A8        },
142fa225cbcSrjs};
143fa225cbcSrjs
144fa225cbcSrjsstatic Bool i830_get_dest_format(PicturePtr pDstPicture, uint32_t *dst_format)
145fa225cbcSrjs{
146fa225cbcSrjs    switch (pDstPicture->format) {
147fa225cbcSrjs    case PICT_a8r8g8b8:
148fa225cbcSrjs    case PICT_x8r8g8b8:
149fa225cbcSrjs        *dst_format = COLR_BUF_ARGB8888;
150fa225cbcSrjs        break;
151fa225cbcSrjs    case PICT_r5g6b5:
152fa225cbcSrjs        *dst_format = COLR_BUF_RGB565;
153fa225cbcSrjs        break;
154fa225cbcSrjs    case PICT_a1r5g5b5:
155fa225cbcSrjs    case PICT_x1r5g5b5:
156fa225cbcSrjs        *dst_format = COLR_BUF_ARGB1555;
157fa225cbcSrjs        break;
158fa225cbcSrjs    case PICT_a8:
159fa225cbcSrjs        *dst_format = COLR_BUF_8BIT;
160fa225cbcSrjs        break;
161fa225cbcSrjs    case PICT_a4r4g4b4:
162fa225cbcSrjs    case PICT_x4r4g4b4:
163fa225cbcSrjs	*dst_format = COLR_BUF_ARGB4444;
164fa225cbcSrjs	break;
165fa225cbcSrjs    default:
166fa225cbcSrjs	{
167fa225cbcSrjs	    ScrnInfoPtr pScrn;
168fa225cbcSrjs
169fa225cbcSrjs	    pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum];
170fa225cbcSrjs	    I830FALLBACK("Unsupported dest format 0x%x\n",
171fa225cbcSrjs			 (int)pDstPicture->format);
172fa225cbcSrjs	}
173fa225cbcSrjs    }
174fa225cbcSrjs    *dst_format |= DSTORG_HORT_BIAS (0x8) | DSTORG_VERT_BIAS (0x8);
175fa225cbcSrjs    return TRUE;
176fa225cbcSrjs}
177fa225cbcSrjs
178fa225cbcSrjs
179fa225cbcSrjsstatic Bool i830_get_blend_cntl(ScrnInfoPtr pScrn, int op, PicturePtr pMask,
180fa225cbcSrjs				uint32_t dst_format, uint32_t *blendctl)
181fa225cbcSrjs{
182fa225cbcSrjs    uint32_t sblend, dblend;
183fa225cbcSrjs
184fa225cbcSrjs    sblend = i830_blend_op[op].src_blend;
185fa225cbcSrjs    dblend = i830_blend_op[op].dst_blend;
186fa225cbcSrjs
187fa225cbcSrjs    /* If there's no dst alpha channel, adjust the blend op so that we'll treat
188fa225cbcSrjs     * it as always 1.
189fa225cbcSrjs     */
190fa225cbcSrjs    if (PICT_FORMAT_A(dst_format) == 0 && i830_blend_op[op].dst_alpha) {
191fa225cbcSrjs        if (sblend == BLENDFACTOR_DST_ALPHA)
192fa225cbcSrjs            sblend = BLENDFACTOR_ONE;
193fa225cbcSrjs        else if (sblend == BLENDFACTOR_INV_DST_ALPHA)
194fa225cbcSrjs            sblend = BLENDFACTOR_ZERO;
195fa225cbcSrjs    }
196fa225cbcSrjs
197fa225cbcSrjs    /* For blending purposes, COLR_BUF_8BIT values show up in the green
198fa225cbcSrjs     * channel.  So we can't use the alpha channel.
199fa225cbcSrjs     */
200fa225cbcSrjs    if (dst_format == PICT_a8 && ((sblend == BLENDFACTOR_DST_ALPHA ||
201fa225cbcSrjs				   sblend == BLENDFACTOR_INV_DST_ALPHA))) {
202fa225cbcSrjs	I830FALLBACK("Can't do dst alpha blending with PICT_a8 dest.\n");
203fa225cbcSrjs    }
204fa225cbcSrjs
205fa225cbcSrjs    /* If the source alpha is being used, then we should only be in a case
206fa225cbcSrjs     * where the source blend factor is 0, and the source blend value is the
207fa225cbcSrjs     * mask channels multiplied by the source picture's alpha.
208fa225cbcSrjs     */
209fa225cbcSrjs    if (pMask && pMask->componentAlpha && PICT_FORMAT_RGB(pMask->format)
210fa225cbcSrjs	    && i830_blend_op[op].src_alpha) {
211fa225cbcSrjs        if (dblend == BLENDFACTOR_SRC_ALPHA) {
212fa225cbcSrjs            dblend = BLENDFACTOR_SRC_COLR;
213fa225cbcSrjs        } else if (dblend == BLENDFACTOR_INV_SRC_ALPHA) {
214fa225cbcSrjs            dblend = BLENDFACTOR_INV_SRC_COLR;
215fa225cbcSrjs        }
216fa225cbcSrjs    }
217fa225cbcSrjs
218fa225cbcSrjs    *blendctl = (sblend << S8_SRC_BLEND_FACTOR_SHIFT) |
219fa225cbcSrjs	(dblend << S8_DST_BLEND_FACTOR_SHIFT);
220fa225cbcSrjs
221fa225cbcSrjs    return TRUE;
222fa225cbcSrjs}
223fa225cbcSrjs
224fa225cbcSrjsstatic Bool i830_check_composite_texture(ScrnInfoPtr pScrn, PicturePtr pPict, int unit)
225fa225cbcSrjs{
226fa225cbcSrjs    if (pPict->repeatType > RepeatReflect)
227fa225cbcSrjs        I830FALLBACK("Unsupported picture repeat %d\n", pPict->repeatType);
228fa225cbcSrjs
229fa225cbcSrjs    if (pPict->filter != PictFilterNearest &&
230fa225cbcSrjs        pPict->filter != PictFilterBilinear)
231fa225cbcSrjs    {
232fa225cbcSrjs        I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
233fa225cbcSrjs    }
234fa225cbcSrjs
235fa225cbcSrjs    if (pPict->pDrawable)
236fa225cbcSrjs    {
237fa225cbcSrjs	int w, h, i;
238fa225cbcSrjs
239fa225cbcSrjs	w = pPict->pDrawable->width;
240fa225cbcSrjs	h = pPict->pDrawable->height;
241fa225cbcSrjs	if ((w > 2048) || (h > 2048))
242fa225cbcSrjs	    I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
243fa225cbcSrjs
244fa225cbcSrjs	for (i = 0; i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]);
245fa225cbcSrjs	     i++)
246fa225cbcSrjs	{
247fa225cbcSrjs	    if (i830_tex_formats[i].fmt == pPict->format)
248fa225cbcSrjs		break;
249fa225cbcSrjs	}
250fa225cbcSrjs	if (i == sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]))
251fa225cbcSrjs	    I830FALLBACK("Unsupported picture format 0x%x\n",
252fa225cbcSrjs			 (int)pPict->format);
253fa225cbcSrjs    }
254fa225cbcSrjs
255fa225cbcSrjs    return TRUE;
256fa225cbcSrjs}
257fa225cbcSrjs
258fa225cbcSrjsstatic uint32_t
259fa225cbcSrjsi8xx_get_card_format(PicturePtr pPict)
260fa225cbcSrjs{
261fa225cbcSrjs    int i;
262fa225cbcSrjs    for (i = 0; i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]);
263fa225cbcSrjs	    i++)
264fa225cbcSrjs    {
265fa225cbcSrjs	if (i830_tex_formats[i].fmt == pPict->format)
266fa225cbcSrjs	    return i830_tex_formats[i].card_fmt;
267fa225cbcSrjs    }
268fa225cbcSrjs    FatalError("Unsupported format type %d\n", pPict->format);
269fa225cbcSrjs}
270fa225cbcSrjs
271fa225cbcSrjsstatic void
272fa225cbcSrjsi830_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
273fa225cbcSrjs{
274fa225cbcSrjs
275fa225cbcSrjs    ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
276fa225cbcSrjs    I830Ptr pI830 = I830PTR(pScrn);
277fa225cbcSrjs    uint32_t format, pitch, filter;
278fa225cbcSrjs    uint32_t wrap_mode;
279fa225cbcSrjs    uint32_t texcoordtype;
280fa225cbcSrjs
281fa225cbcSrjs    pitch = intel_get_pixmap_pitch(pPix);
282fa225cbcSrjs    pI830->scale_units[unit][0] = pPix->drawable.width;
283fa225cbcSrjs    pI830->scale_units[unit][1] = pPix->drawable.height;
284fa225cbcSrjs    pI830->transform[unit] = pPict->transform;
285fa225cbcSrjs
286fa225cbcSrjs    if (i830_transform_is_affine(pI830->transform[unit]))
287fa225cbcSrjs	texcoordtype = TEXCOORDTYPE_CARTESIAN;
288fa225cbcSrjs    else
289fa225cbcSrjs	texcoordtype = TEXCOORDTYPE_HOMOGENEOUS;
290fa225cbcSrjs
291fa225cbcSrjs    format = i8xx_get_card_format(pPict);
292fa225cbcSrjs
293fa225cbcSrjs    switch (pPict->repeatType) {
294fa225cbcSrjs    case RepeatNone:
295fa225cbcSrjs	wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
296fa225cbcSrjs	break;
297fa225cbcSrjs    case RepeatNormal:
298fa225cbcSrjs	wrap_mode = TEXCOORDMODE_WRAP;
299fa225cbcSrjs	break;
300fa225cbcSrjs    case RepeatPad:
301fa225cbcSrjs	wrap_mode = TEXCOORDMODE_CLAMP;
302fa225cbcSrjs	break;
303fa225cbcSrjs    case RepeatReflect:
304fa225cbcSrjs	wrap_mode = TEXCOORDMODE_MIRROR;
305fa225cbcSrjs	break;
306fa225cbcSrjs    default:
307fa225cbcSrjs	FatalError("Unknown repeat type %d\n", pPict->repeatType);
308fa225cbcSrjs    }
309fa225cbcSrjs
310fa225cbcSrjs    switch (pPict->filter) {
311fa225cbcSrjs    case PictFilterNearest:
312fa225cbcSrjs        filter = ((FILTER_NEAREST<<TM0S3_MAG_FILTER_SHIFT) |
313fa225cbcSrjs		  (FILTER_NEAREST<<TM0S3_MIN_FILTER_SHIFT));
314fa225cbcSrjs        break;
315fa225cbcSrjs    case PictFilterBilinear:
316fa225cbcSrjs        filter = ((FILTER_LINEAR<<TM0S3_MAG_FILTER_SHIFT) |
317fa225cbcSrjs		  (FILTER_LINEAR<<TM0S3_MIN_FILTER_SHIFT));
318fa225cbcSrjs        break;
319fa225cbcSrjs    default:
320fa225cbcSrjs	filter = 0;
321fa225cbcSrjs        FatalError("Bad filter 0x%x\n", pPict->filter);
322fa225cbcSrjs    }
323fa225cbcSrjs    filter |= (MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT);
324fa225cbcSrjs
325fa225cbcSrjs    {
326fa225cbcSrjs	if (pPix->drawable.bitsPerPixel == 8)
327fa225cbcSrjs	    format |= MAPSURF_8BIT;
328fa225cbcSrjs	else if (pPix->drawable.bitsPerPixel == 16)
329fa225cbcSrjs	    format |= MAPSURF_16BIT;
330fa225cbcSrjs	else
331fa225cbcSrjs	    format |= MAPSURF_32BIT;
332fa225cbcSrjs
333fa225cbcSrjs	BEGIN_BATCH(10);
334fa225cbcSrjs	OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(unit) | 4);
335fa225cbcSrjs	OUT_RELOC_PIXMAP(pPix, I915_GEM_DOMAIN_SAMPLER, 0, TM0S0_USE_FENCE);
336fa225cbcSrjs	OUT_BATCH(((pPix->drawable.height - 1) << TM0S1_HEIGHT_SHIFT) |
337fa225cbcSrjs		  ((pPix->drawable.width - 1) << TM0S1_WIDTH_SHIFT) | format);
338fa225cbcSrjs	OUT_BATCH((pitch/4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
339fa225cbcSrjs	OUT_BATCH(filter);
340fa225cbcSrjs	OUT_BATCH(0); /* default color */
341fa225cbcSrjs	OUT_BATCH(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) |
342fa225cbcSrjs		  ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL |
343fa225cbcSrjs		  texcoordtype | ENABLE_ADDR_V_CNTL |
344fa225cbcSrjs		  TEXCOORD_ADDR_V_MODE(wrap_mode) |
345fa225cbcSrjs		  ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode));
346fa225cbcSrjs	/* map texel stream */
347fa225cbcSrjs	OUT_BATCH(_3DSTATE_MAP_COORD_SETBIND_CMD);
348fa225cbcSrjs	if (unit == 0)
349fa225cbcSrjs	    OUT_BATCH(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) |
350fa225cbcSrjs		      TEXBIND_SET1(TEXCOORDSRC_KEEP) |
351fa225cbcSrjs		      TEXBIND_SET2(TEXCOORDSRC_KEEP) |
352fa225cbcSrjs		      TEXBIND_SET3(TEXCOORDSRC_KEEP));
353fa225cbcSrjs	else
354fa225cbcSrjs	    OUT_BATCH(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) |
355fa225cbcSrjs		      TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) |
356fa225cbcSrjs		      TEXBIND_SET2(TEXCOORDSRC_KEEP) |
357fa225cbcSrjs		      TEXBIND_SET3(TEXCOORDSRC_KEEP));
358fa225cbcSrjs	OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD | (unit << 16) |
359fa225cbcSrjs		  DISABLE_TEX_STREAM_BUMP |
360fa225cbcSrjs		  ENABLE_TEX_STREAM_COORD_SET |
361fa225cbcSrjs		  TEX_STREAM_COORD_SET(unit) |
362fa225cbcSrjs		  ENABLE_TEX_STREAM_MAP_IDX |
363fa225cbcSrjs		  TEX_STREAM_MAP_IDX(unit));
364fa225cbcSrjs	ADVANCE_BATCH();
365fa225cbcSrjs     }
366fa225cbcSrjs}
367fa225cbcSrjs
368fa225cbcSrjsBool
369fa225cbcSrjsi830_check_composite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
370fa225cbcSrjs		     PicturePtr pDstPicture)
371fa225cbcSrjs{
372fa225cbcSrjs    ScrnInfoPtr pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum];
373fa225cbcSrjs    uint32_t tmp1;
374fa225cbcSrjs
375fa225cbcSrjs    /* Check for unsupported compositing operations. */
376fa225cbcSrjs    if (op >= sizeof(i830_blend_op) / sizeof(i830_blend_op[0]))
377fa225cbcSrjs        I830FALLBACK("Unsupported Composite op 0x%x\n", op);
378fa225cbcSrjs
379fa225cbcSrjs    if (pMaskPicture != NULL && pMaskPicture->componentAlpha &&
380fa225cbcSrjs	    PICT_FORMAT_RGB(pMaskPicture->format)) {
381fa225cbcSrjs        /* Check if it's component alpha that relies on a source alpha and on
382fa225cbcSrjs         * the source value.  We can only get one of those into the single
383fa225cbcSrjs         * source value that we get to blend with.
384fa225cbcSrjs         */
385fa225cbcSrjs        if (i830_blend_op[op].src_alpha &&
386fa225cbcSrjs            (i830_blend_op[op].src_blend != BLENDFACTOR_ZERO))
387fa225cbcSrjs            	I830FALLBACK("Component alpha not supported with source "
388fa225cbcSrjs			     "alpha and source value blending.\n");
389fa225cbcSrjs    }
390fa225cbcSrjs
391fa225cbcSrjs    if (!i830_check_composite_texture(pScrn, pSrcPicture, 0))
392fa225cbcSrjs        I830FALLBACK("Check Src picture texture\n");
393fa225cbcSrjs    if (pMaskPicture != NULL && !i830_check_composite_texture(pScrn, pMaskPicture, 1))
394fa225cbcSrjs        I830FALLBACK("Check Mask picture texture\n");
395fa225cbcSrjs
396fa225cbcSrjs    if (!i830_get_dest_format(pDstPicture, &tmp1))
397fa225cbcSrjs	I830FALLBACK("Get Color buffer format\n");
398fa225cbcSrjs
399fa225cbcSrjs    return TRUE;
400fa225cbcSrjs}
401fa225cbcSrjs
402fa225cbcSrjsBool
403fa225cbcSrjsi830_prepare_composite(int op, PicturePtr pSrcPicture,
404fa225cbcSrjs		       PicturePtr pMaskPicture, PicturePtr pDstPicture,
405fa225cbcSrjs		       PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
406fa225cbcSrjs{
407fa225cbcSrjs    ScrnInfoPtr pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum];
408fa225cbcSrjs    I830Ptr pI830 = I830PTR(pScrn);
409fa225cbcSrjs
410fa225cbcSrjs    pI830->render_src_picture = pSrcPicture;
411fa225cbcSrjs    pI830->render_src = pSrc;
412fa225cbcSrjs    pI830->render_mask_picture = pMaskPicture;
413fa225cbcSrjs    pI830->render_mask = pMask;
414fa225cbcSrjs    pI830->render_dst_picture = pDstPicture;
415fa225cbcSrjs    pI830->render_dst = pDst;
416fa225cbcSrjs
417fa225cbcSrjs    i830_exa_check_pitch_3d(pSrc);
418fa225cbcSrjs    if (pMask)
419fa225cbcSrjs	i830_exa_check_pitch_3d(pMask);
420fa225cbcSrjs    i830_exa_check_pitch_3d(pDst);
421fa225cbcSrjs
422fa225cbcSrjs    if (!i830_get_dest_format(pDstPicture, &pI830->render_dst_format))
423fa225cbcSrjs	return FALSE;
424fa225cbcSrjs
425fa225cbcSrjs    pI830->dst_coord_adjust = 0;
426fa225cbcSrjs    pI830->src_coord_adjust = 0;
427fa225cbcSrjs    pI830->mask_coord_adjust = 0;
428fa225cbcSrjs    if (pSrcPicture->filter == PictFilterNearest)
429fa225cbcSrjs	pI830->src_coord_adjust = 0.375;
430fa225cbcSrjs    if (pMask != NULL) {
431fa225cbcSrjs	pI830->mask_coord_adjust = 0;
432fa225cbcSrjs	if (pMaskPicture->filter == PictFilterNearest)
433fa225cbcSrjs	    pI830->mask_coord_adjust = 0.375;
434fa225cbcSrjs    } else {
435fa225cbcSrjs	pI830->transform[1] = NULL;
436fa225cbcSrjs	pI830->scale_units[1][0] = -1;
437fa225cbcSrjs	pI830->scale_units[1][1] = -1;
438fa225cbcSrjs    }
439fa225cbcSrjs
440fa225cbcSrjs    {
441fa225cbcSrjs	uint32_t cblend, ablend, blendctl;
442fa225cbcSrjs
443fa225cbcSrjs	/* If component alpha is active in the mask and the blend operation
444fa225cbcSrjs	 * uses the source alpha, then we know we don't need the source
445fa225cbcSrjs	 * value (otherwise we would have hit a fallback earlier), so we
446fa225cbcSrjs	 * provide the source alpha (src.A * mask.X) as output color.
447fa225cbcSrjs	 * Conversely, if CA is set and we don't need the source alpha, then
448fa225cbcSrjs	 * we produce the source value (src.X * mask.X) and the source alpha
449fa225cbcSrjs	 * is unused..  Otherwise, we provide the non-CA source value
450fa225cbcSrjs	 * (src.X * mask.A).
451fa225cbcSrjs	 *
452fa225cbcSrjs	 * The PICT_FORMAT_RGB(pict) == 0 fixups are not needed on 855+'s a8
453fa225cbcSrjs	 * pictures, but we need to implement it for 830/845 and there's no
454fa225cbcSrjs	 * harm done in leaving it in.
455fa225cbcSrjs	 */
456fa225cbcSrjs	cblend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULE |
457fa225cbcSrjs		 TB0C_OUTPUT_WRITE_CURRENT;
458fa225cbcSrjs	ablend = TB0A_RESULT_SCALE_1X | TB0A_OP_MODULE |
459fa225cbcSrjs		 TB0A_OUTPUT_WRITE_CURRENT;
460fa225cbcSrjs
461fa225cbcSrjs	/* Get the source picture's channels into TBx_ARG1 */
462fa225cbcSrjs	if ((pMaskPicture != NULL &&
463fa225cbcSrjs	     pMaskPicture->componentAlpha &&
464fa225cbcSrjs	     PICT_FORMAT_RGB(pMaskPicture->format) &&
465fa225cbcSrjs	     i830_blend_op[op].src_alpha) || pDstPicture->format == PICT_a8)
466fa225cbcSrjs	{
467fa225cbcSrjs	    /* Producing source alpha value, so the first set of channels
468fa225cbcSrjs	     * is src.A instead of src.X.  We also do this if the destination
469fa225cbcSrjs	     * is a8, in which case src.G is what's written, and the other
470fa225cbcSrjs	     * channels are ignored.
471fa225cbcSrjs	     */
472fa225cbcSrjs	    if (PICT_FORMAT_A(pSrcPicture->format) != 0) {
473fa225cbcSrjs		ablend |= TB0A_ARG1_SEL_TEXEL0;
474fa225cbcSrjs		cblend |= TB0C_ARG1_SEL_TEXEL0 | TB0C_ARG1_REPLICATE_ALPHA;
475fa225cbcSrjs	    } else {
476fa225cbcSrjs		ablend |= TB0A_ARG1_SEL_ONE;
477fa225cbcSrjs		cblend |= TB0C_ARG1_SEL_ONE;
478fa225cbcSrjs	    }
479fa225cbcSrjs	} else {
480fa225cbcSrjs	    if (PICT_FORMAT_A(pSrcPicture->format) != 0) {
481fa225cbcSrjs		ablend |= TB0A_ARG1_SEL_TEXEL0;
482fa225cbcSrjs	    } else {
483fa225cbcSrjs		ablend |= TB0A_ARG1_SEL_ONE;
484fa225cbcSrjs	    }
485fa225cbcSrjs	    if (PICT_FORMAT_RGB(pSrcPicture->format) != 0)
486fa225cbcSrjs		cblend |= TB0C_ARG1_SEL_TEXEL0;
487fa225cbcSrjs	    else
488fa225cbcSrjs		cblend |= TB0C_ARG1_SEL_ONE | TB0C_ARG1_INVERT; /* 0.0 */
489fa225cbcSrjs	}
490fa225cbcSrjs
491fa225cbcSrjs	if (pMask) {
492fa225cbcSrjs	    if (pDstPicture->format != PICT_a8 &&
493fa225cbcSrjs		(pMaskPicture->componentAlpha &&
494fa225cbcSrjs		 PICT_FORMAT_RGB(pMaskPicture->format)))
495fa225cbcSrjs	    {
496fa225cbcSrjs		cblend |= TB0C_ARG2_SEL_TEXEL1;
497fa225cbcSrjs	    } else {
498fa225cbcSrjs		if (PICT_FORMAT_A(pMaskPicture->format) != 0)
499fa225cbcSrjs		    cblend |= TB0C_ARG2_SEL_TEXEL1 |
500fa225cbcSrjs			TB0C_ARG2_REPLICATE_ALPHA;
501fa225cbcSrjs		else
502fa225cbcSrjs		    cblend |= TB0C_ARG2_SEL_ONE;
503fa225cbcSrjs	    }
504fa225cbcSrjs	    if (PICT_FORMAT_A(pMaskPicture->format) != 0)
505fa225cbcSrjs		ablend |= TB0A_ARG2_SEL_TEXEL1;
506fa225cbcSrjs	    else
507fa225cbcSrjs		ablend |= TB0A_ARG2_SEL_ONE;
508fa225cbcSrjs	} else {
509fa225cbcSrjs	    cblend |= TB0C_ARG2_SEL_ONE;
510fa225cbcSrjs	    ablend |= TB0A_ARG2_SEL_ONE;
511fa225cbcSrjs	}
512fa225cbcSrjs
513fa225cbcSrjs	if (!i830_get_blend_cntl(pScrn, op, pMaskPicture, pDstPicture->format,
514fa225cbcSrjs				 &blendctl)) {
515fa225cbcSrjs	    return FALSE;
516fa225cbcSrjs	}
517fa225cbcSrjs
518fa225cbcSrjs	pI830->cblend = cblend;
519fa225cbcSrjs	pI830->ablend = ablend;
520fa225cbcSrjs	pI830->s8_blendctl = blendctl;
521fa225cbcSrjs    }
522fa225cbcSrjs
523fa225cbcSrjs    i830_debug_sync(pScrn);
524fa225cbcSrjs
525fa225cbcSrjs    pI830->needs_render_state_emit = TRUE;
526fa225cbcSrjs
527fa225cbcSrjs    return TRUE;
528fa225cbcSrjs}
529fa225cbcSrjs
530fa225cbcSrjsstatic void
531fa225cbcSrjsi830_emit_composite_state(ScrnInfoPtr pScrn)
532fa225cbcSrjs{
533fa225cbcSrjs    I830Ptr pI830 = I830PTR(pScrn);
534fa225cbcSrjs    uint32_t vf2;
535fa225cbcSrjs    uint32_t texcoordfmt = 0;
536fa225cbcSrjs
537fa225cbcSrjs    pI830->needs_render_state_emit = FALSE;
538fa225cbcSrjs
539fa225cbcSrjs    IntelEmitInvarientState(pScrn);
540fa225cbcSrjs    pI830->last_3d = LAST_3D_RENDER;
541fa225cbcSrjs
542fa225cbcSrjs    BEGIN_BATCH(21);
543fa225cbcSrjs
544fa225cbcSrjs    OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
545fa225cbcSrjs    OUT_BATCH(BUF_3D_ID_COLOR_BACK| BUF_3D_USE_FENCE |
546fa225cbcSrjs	      BUF_3D_PITCH(intel_get_pixmap_pitch(pI830->render_dst)));
547fa225cbcSrjs    OUT_RELOC_PIXMAP(pI830->render_dst,
548fa225cbcSrjs		     I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
549fa225cbcSrjs
550fa225cbcSrjs    OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
551fa225cbcSrjs    OUT_BATCH(pI830->render_dst_format);
552fa225cbcSrjs
553fa225cbcSrjs    OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
554fa225cbcSrjs    OUT_BATCH(0);
555fa225cbcSrjs    OUT_BATCH(0); /* ymin, xmin */
556fa225cbcSrjs    OUT_BATCH(DRAW_YMAX(pI830->render_dst->drawable.height - 1) |
557fa225cbcSrjs	      DRAW_XMAX(pI830->render_dst->drawable.width - 1));
558fa225cbcSrjs    OUT_BATCH(0); /* yorig, xorig */
559fa225cbcSrjs
560fa225cbcSrjs    OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
561fa225cbcSrjs	      I1_LOAD_S(2) |
562fa225cbcSrjs	      I1_LOAD_S(3) |
563fa225cbcSrjs	      I1_LOAD_S(8) |
564fa225cbcSrjs	      2);
565fa225cbcSrjs    if (pI830->render_mask)
566fa225cbcSrjs	vf2 = 2 << 12; /* 2 texture coord sets */
567fa225cbcSrjs    else
568fa225cbcSrjs	vf2 = 1 << 12;
569fa225cbcSrjs    OUT_BATCH(vf2); /* number of coordinate sets */
570fa225cbcSrjs    OUT_BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY);
571fa225cbcSrjs    OUT_BATCH(S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD | pI830->s8_blendctl |
572fa225cbcSrjs	      S8_ENABLE_COLOR_BUFFER_WRITE);
573fa225cbcSrjs
574fa225cbcSrjs    OUT_BATCH(_3DSTATE_INDPT_ALPHA_BLEND_CMD | DISABLE_INDPT_ALPHA_BLEND);
575fa225cbcSrjs
576fa225cbcSrjs    OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
577fa225cbcSrjs	      LOAD_TEXTURE_BLEND_STAGE(0)|1);
578fa225cbcSrjs    OUT_BATCH(pI830->cblend);
579fa225cbcSrjs    OUT_BATCH(pI830->ablend);
580fa225cbcSrjs
581fa225cbcSrjs    OUT_BATCH(_3DSTATE_ENABLES_1_CMD | DISABLE_LOGIC_OP |
582fa225cbcSrjs	      DISABLE_STENCIL_TEST | DISABLE_DEPTH_BIAS |
583fa225cbcSrjs	      DISABLE_SPEC_ADD | DISABLE_FOG | DISABLE_ALPHA_TEST |
584fa225cbcSrjs	      ENABLE_COLOR_BLEND | DISABLE_DEPTH_TEST);
585fa225cbcSrjs    /* We have to explicitly say we don't want write disabled */
586fa225cbcSrjs    OUT_BATCH(_3DSTATE_ENABLES_2_CMD | ENABLE_COLOR_MASK |
587fa225cbcSrjs	      DISABLE_STENCIL_WRITE | ENABLE_TEX_CACHE |
588fa225cbcSrjs	      DISABLE_DITHER | ENABLE_COLOR_WRITE |
589fa225cbcSrjs	      DISABLE_DEPTH_WRITE);
590fa225cbcSrjs
591fa225cbcSrjs    if (i830_transform_is_affine(pI830->render_src_picture->transform))
592fa225cbcSrjs	texcoordfmt |= (TEXCOORDFMT_2D << 0);
593fa225cbcSrjs    else
594fa225cbcSrjs	texcoordfmt |= (TEXCOORDFMT_3D << 0);
595fa225cbcSrjs    if (pI830->render_mask) {
596fa225cbcSrjs	if (i830_transform_is_affine(pI830->render_mask_picture->transform))
597fa225cbcSrjs	    texcoordfmt |= (TEXCOORDFMT_2D << 2);
598fa225cbcSrjs	else
599fa225cbcSrjs	    texcoordfmt |= (TEXCOORDFMT_3D << 2);
600fa225cbcSrjs    }
601fa225cbcSrjs    OUT_BATCH(_3DSTATE_VERTEX_FORMAT_2_CMD | texcoordfmt);
602fa225cbcSrjs
603fa225cbcSrjs    ADVANCE_BATCH();
604fa225cbcSrjs
605fa225cbcSrjs    i830_texture_setup(pI830->render_src_picture, pI830->render_src, 0);
606fa225cbcSrjs    if (pI830->render_mask) {
607fa225cbcSrjs	i830_texture_setup(pI830->render_mask_picture,
608fa225cbcSrjs			   pI830->render_mask, 1);
609fa225cbcSrjs    }
610fa225cbcSrjs}
611fa225cbcSrjs
612fa225cbcSrjs/* Emit the vertices for a single composite rectangle.
613fa225cbcSrjs *
614fa225cbcSrjs * This function is no longer shared between i830 and i915 generation code.
615fa225cbcSrjs */
616fa225cbcSrjsstatic void
617fa225cbcSrjsi830_emit_composite_primitive(PixmapPtr pDst,
618fa225cbcSrjs			      int srcX, int srcY,
619fa225cbcSrjs			      int maskX, int maskY,
620fa225cbcSrjs			      int dstX, int dstY,
621fa225cbcSrjs			      int w, int h)
622fa225cbcSrjs{
623fa225cbcSrjs    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
624fa225cbcSrjs    I830Ptr pI830 = I830PTR(pScrn);
625fa225cbcSrjs    Bool is_affine_src, is_affine_mask = TRUE;
626fa225cbcSrjs    int per_vertex, num_floats;
627fa225cbcSrjs    float src_x[3], src_y[3], src_w[3], mask_x[3], mask_y[3], mask_w[3];
628fa225cbcSrjs
629fa225cbcSrjs    per_vertex = 2; /* dest x/y */
630fa225cbcSrjs
631fa225cbcSrjs    {
632fa225cbcSrjs	float x = srcX + pI830->src_coord_adjust;
633fa225cbcSrjs	float y = srcY + pI830->src_coord_adjust;
634fa225cbcSrjs
635fa225cbcSrjs	is_affine_src = i830_transform_is_affine (pI830->transform[0]);
636fa225cbcSrjs	if (is_affine_src) {
637fa225cbcSrjs	    if (!i830_get_transformed_coordinates(x, y,
638fa225cbcSrjs						  pI830->transform[0],
639fa225cbcSrjs						  &src_x[0], &src_y[0]))
640fa225cbcSrjs		return;
641fa225cbcSrjs
642fa225cbcSrjs	    if (!i830_get_transformed_coordinates(x, y + h,
643fa225cbcSrjs						  pI830->transform[0],
644fa225cbcSrjs						  &src_x[1], &src_y[1]))
645fa225cbcSrjs		return;
646fa225cbcSrjs
647fa225cbcSrjs	    if (!i830_get_transformed_coordinates(x + w, y + h,
648fa225cbcSrjs						  pI830->transform[0],
649fa225cbcSrjs						  &src_x[2], &src_y[2]))
650fa225cbcSrjs		return;
651fa225cbcSrjs
652fa225cbcSrjs	    per_vertex += 2;    /* src x/y */
653fa225cbcSrjs	} else {
654fa225cbcSrjs	    if (!i830_get_transformed_coordinates_3d(x, y,
655fa225cbcSrjs						     pI830->transform[0],
656fa225cbcSrjs						     &src_x[0],
657fa225cbcSrjs						     &src_y[0],
658fa225cbcSrjs						     &src_w[0]))
659fa225cbcSrjs		return;
660fa225cbcSrjs
661fa225cbcSrjs	    if (!i830_get_transformed_coordinates_3d(x, y + h,
662fa225cbcSrjs						     pI830->transform[0],
663fa225cbcSrjs						     &src_x[1],
664fa225cbcSrjs						     &src_y[1],
665fa225cbcSrjs						     &src_w[1]))
666fa225cbcSrjs		return;
667fa225cbcSrjs
668fa225cbcSrjs	    if (!i830_get_transformed_coordinates_3d(x + w, y + h,
669fa225cbcSrjs						     pI830->transform[0],
670fa225cbcSrjs						     &src_x[2],
671fa225cbcSrjs						     &src_y[2],
672fa225cbcSrjs						     &src_w[2]))
673fa225cbcSrjs		return;
674fa225cbcSrjs
675fa225cbcSrjs	    per_vertex += 3;    /* src x/y/w */
676fa225cbcSrjs	}
677fa225cbcSrjs    }
678fa225cbcSrjs
679fa225cbcSrjs    if (pI830->render_mask) {
680fa225cbcSrjs	float x = maskX + pI830->mask_coord_adjust;
681fa225cbcSrjs	float y = maskY + pI830->mask_coord_adjust;
682fa225cbcSrjs
683fa225cbcSrjs	is_affine_mask = i830_transform_is_affine (pI830->transform[1]);
684fa225cbcSrjs	if (is_affine_mask) {
685fa225cbcSrjs	    if (!i830_get_transformed_coordinates(x, y,
686fa225cbcSrjs						  pI830->transform[1],
687fa225cbcSrjs						  &mask_x[0], &mask_y[0]))
688fa225cbcSrjs		return;
689fa225cbcSrjs
690fa225cbcSrjs	    if (!i830_get_transformed_coordinates(x, y + h,
691fa225cbcSrjs						  pI830->transform[1],
692fa225cbcSrjs						  &mask_x[1], &mask_y[1]))
693fa225cbcSrjs		return;
694fa225cbcSrjs
695fa225cbcSrjs	    if (!i830_get_transformed_coordinates(x + w, y + h,
696fa225cbcSrjs						  pI830->transform[1],
697fa225cbcSrjs						  &mask_x[2], &mask_y[2]))
698fa225cbcSrjs		return;
699fa225cbcSrjs
700fa225cbcSrjs	    per_vertex += 2;	/* mask x/y */
701fa225cbcSrjs	} else {
702fa225cbcSrjs	    if (!i830_get_transformed_coordinates_3d(x, y,
703fa225cbcSrjs						     pI830->transform[1],
704fa225cbcSrjs						     &mask_x[0],
705fa225cbcSrjs						     &mask_y[0],
706fa225cbcSrjs						     &mask_w[0]))
707fa225cbcSrjs		return;
708fa225cbcSrjs
709fa225cbcSrjs	    if (!i830_get_transformed_coordinates_3d(x, y + h,
710fa225cbcSrjs						     pI830->transform[1],
711fa225cbcSrjs						     &mask_x[1],
712fa225cbcSrjs						     &mask_y[1],
713fa225cbcSrjs						     &mask_w[1]))
714fa225cbcSrjs		return;
715fa225cbcSrjs
716fa225cbcSrjs	    if (!i830_get_transformed_coordinates_3d(x + w, y + h,
717fa225cbcSrjs						     pI830->transform[1],
718fa225cbcSrjs						     &mask_x[2],
719fa225cbcSrjs						     &mask_y[2],
720fa225cbcSrjs						     &mask_w[2]))
721fa225cbcSrjs		return;
722fa225cbcSrjs
723fa225cbcSrjs	    per_vertex += 3;	/* mask x/y/w */
724fa225cbcSrjs	}
725fa225cbcSrjs    }
726fa225cbcSrjs
727fa225cbcSrjs    num_floats = 3 * per_vertex;
728fa225cbcSrjs
729fa225cbcSrjs    BEGIN_BATCH(1 + num_floats);
730fa225cbcSrjs
731fa225cbcSrjs    OUT_BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST | (num_floats-1));
732fa225cbcSrjs    OUT_BATCH_F(pI830->dst_coord_adjust + dstX + w);
733fa225cbcSrjs    OUT_BATCH_F(pI830->dst_coord_adjust + dstY + h);
734fa225cbcSrjs    OUT_BATCH_F(src_x[2] / pI830->scale_units[0][0]);
735fa225cbcSrjs    OUT_BATCH_F(src_y[2] / pI830->scale_units[0][1]);
736fa225cbcSrjs    if (!is_affine_src) {
737fa225cbcSrjs	OUT_BATCH_F(src_w[2]);
738fa225cbcSrjs    }
739fa225cbcSrjs    if (pI830->render_mask) {
740fa225cbcSrjs	OUT_BATCH_F(mask_x[2] / pI830->scale_units[1][0]);
741fa225cbcSrjs	OUT_BATCH_F(mask_y[2] / pI830->scale_units[1][1]);
742fa225cbcSrjs	if (!is_affine_mask) {
743fa225cbcSrjs	    OUT_BATCH_F(mask_w[2]);
744fa225cbcSrjs	}
745fa225cbcSrjs    }
746fa225cbcSrjs
747fa225cbcSrjs    OUT_BATCH_F(pI830->dst_coord_adjust + dstX);
748fa225cbcSrjs    OUT_BATCH_F(pI830->dst_coord_adjust + dstY + h);
749fa225cbcSrjs    OUT_BATCH_F(src_x[1] / pI830->scale_units[0][0]);
750fa225cbcSrjs    OUT_BATCH_F(src_y[1] / pI830->scale_units[0][1]);
751fa225cbcSrjs    if (!is_affine_src) {
752fa225cbcSrjs	OUT_BATCH_F(src_w[1]);
753fa225cbcSrjs    }
754fa225cbcSrjs    if (pI830->render_mask) {
755fa225cbcSrjs	OUT_BATCH_F(mask_x[1] / pI830->scale_units[1][0]);
756fa225cbcSrjs	OUT_BATCH_F(mask_y[1] / pI830->scale_units[1][1]);
757fa225cbcSrjs	if (!is_affine_mask) {
758fa225cbcSrjs	    OUT_BATCH_F(mask_w[1]);
759fa225cbcSrjs	}
760fa225cbcSrjs    }
761fa225cbcSrjs
762fa225cbcSrjs    OUT_BATCH_F(pI830->dst_coord_adjust + dstX);
763fa225cbcSrjs    OUT_BATCH_F(pI830->dst_coord_adjust + dstY);
764fa225cbcSrjs    OUT_BATCH_F(src_x[0] / pI830->scale_units[0][0]);
765fa225cbcSrjs    OUT_BATCH_F(src_y[0] / pI830->scale_units[0][1]);
766fa225cbcSrjs    if (!is_affine_src) {
767fa225cbcSrjs	OUT_BATCH_F(src_w[0]);
768fa225cbcSrjs    }
769fa225cbcSrjs    if (pI830->render_mask) {
770fa225cbcSrjs	OUT_BATCH_F(mask_x[0] / pI830->scale_units[1][0]);
771fa225cbcSrjs	OUT_BATCH_F(mask_y[0] / pI830->scale_units[1][1]);
772fa225cbcSrjs	if (!is_affine_mask) {
773fa225cbcSrjs	    OUT_BATCH_F(mask_w[0]);
774fa225cbcSrjs	}
775fa225cbcSrjs    }
776fa225cbcSrjs
777fa225cbcSrjs    ADVANCE_BATCH();
778fa225cbcSrjs}
779fa225cbcSrjs
780fa225cbcSrjs
781fa225cbcSrjs/**
782fa225cbcSrjs * Do a single rectangle composite operation.
783fa225cbcSrjs */
784fa225cbcSrjsvoid
785fa225cbcSrjsi830_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
786fa225cbcSrjs	       int dstX, int dstY, int w, int h)
787fa225cbcSrjs{
788fa225cbcSrjs    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
789fa225cbcSrjs    I830Ptr pI830 = I830PTR(pScrn);
790fa225cbcSrjs
791fa225cbcSrjs    intel_batch_start_atomic(pScrn,
792fa225cbcSrjs			     58 + /* invarient */
793fa225cbcSrjs			     22 + /* setup */
794fa225cbcSrjs			     20 + /* 2 * setup_texture */
795fa225cbcSrjs			     1 + 30 /* verts */);
796fa225cbcSrjs
797fa225cbcSrjs    if (pI830->needs_render_state_emit)
798fa225cbcSrjs	i830_emit_composite_state(pScrn);
799fa225cbcSrjs
800fa225cbcSrjs    i830_emit_composite_primitive(pDst, srcX, srcY, maskX, maskY, dstX, dstY,
801fa225cbcSrjs				  w, h);
802fa225cbcSrjs
803fa225cbcSrjs    intel_batch_end_atomic(pScrn);
804fa225cbcSrjs
805fa225cbcSrjs    i830_debug_sync(pScrn);
806fa225cbcSrjs}
807fa225cbcSrjs
808fa225cbcSrjsvoid
809fa225cbcSrjsi830_batch_flush_notify(ScrnInfoPtr scrn)
810fa225cbcSrjs{
811fa225cbcSrjs    I830Ptr i830 = I830PTR(scrn);
812fa225cbcSrjs
813fa225cbcSrjs    i830->needs_render_state_emit = TRUE;
814fa225cbcSrjs}
815