i915_render.c revision fa225cbc
1/*
2 * Copyright © 2006 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 *    Wang Zhenyu <zhenyu.z.wang@intel.com>
25 *    Eric Anholt <eric@anholt.net>
26 *
27 */
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include "xf86.h"
34#include "i830.h"
35#include "i915_reg.h"
36#include "i915_3d.h"
37
38struct formatinfo {
39    int fmt;
40    uint32_t card_fmt;
41};
42
43struct blendinfo {
44    Bool dst_alpha;
45    Bool src_alpha;
46    uint32_t src_blend;
47    uint32_t dst_blend;
48};
49
50static struct blendinfo i915_blend_op[] = {
51    /* Clear */
52    {0, 0, BLENDFACT_ZERO,          BLENDFACT_ZERO},
53    /* Src */
54    {0, 0, BLENDFACT_ONE,           BLENDFACT_ZERO},
55    /* Dst */
56    {0, 0, BLENDFACT_ZERO,          BLENDFACT_ONE},
57    /* Over */
58    {0, 1, BLENDFACT_ONE,           BLENDFACT_INV_SRC_ALPHA},
59    /* OverReverse */
60    {1, 0, BLENDFACT_INV_DST_ALPHA, BLENDFACT_ONE},
61    /* In */
62    {1, 0, BLENDFACT_DST_ALPHA,     BLENDFACT_ZERO},
63    /* InReverse */
64    {0, 1, BLENDFACT_ZERO,          BLENDFACT_SRC_ALPHA},
65    /* Out */
66    {1, 0, BLENDFACT_INV_DST_ALPHA, BLENDFACT_ZERO},
67    /* OutReverse */
68    {0, 1, BLENDFACT_ZERO,          BLENDFACT_INV_SRC_ALPHA},
69    /* Atop */
70    {1, 1, BLENDFACT_DST_ALPHA,     BLENDFACT_INV_SRC_ALPHA},
71    /* AtopReverse */
72    {1, 1, BLENDFACT_INV_DST_ALPHA, BLENDFACT_SRC_ALPHA},
73    /* Xor */
74    {1, 1, BLENDFACT_INV_DST_ALPHA, BLENDFACT_INV_SRC_ALPHA},
75    /* Add */
76    {0, 0, BLENDFACT_ONE,           BLENDFACT_ONE},
77};
78
79static struct formatinfo i915_tex_formats[] = {
80    {PICT_a8r8g8b8, MAPSURF_32BIT | MT_32BIT_ARGB8888 },
81    {PICT_x8r8g8b8, MAPSURF_32BIT | MT_32BIT_XRGB8888 },
82    {PICT_a8b8g8r8, MAPSURF_32BIT | MT_32BIT_ABGR8888 },
83    {PICT_x8b8g8r8, MAPSURF_32BIT | MT_32BIT_XBGR8888 },
84    {PICT_r5g6b5,   MAPSURF_16BIT | MT_16BIT_RGB565   },
85    {PICT_a1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 },
86    {PICT_x1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555 },
87    {PICT_a4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444 },
88    {PICT_x4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444 },
89    {PICT_a8,       MAPSURF_8BIT | MT_8BIT_A8 	  },
90};
91
92static uint32_t i915_get_blend_cntl(int op, PicturePtr pMask,
93				    uint32_t dst_format)
94{
95    uint32_t sblend, dblend;
96
97    sblend = i915_blend_op[op].src_blend;
98    dblend = i915_blend_op[op].dst_blend;
99
100    /* If there's no dst alpha channel, adjust the blend op so that we'll treat
101     * it as always 1.
102     */
103    if (PICT_FORMAT_A(dst_format) == 0 && i915_blend_op[op].dst_alpha) {
104        if (sblend == BLENDFACT_DST_ALPHA)
105            sblend = BLENDFACT_ONE;
106        else if (sblend == BLENDFACT_INV_DST_ALPHA)
107            sblend = BLENDFACT_ZERO;
108    }
109
110    /* i915 engine reads 8bit color buffer into green channel in cases
111       like color buffer blending .etc, and also writes back green channel.
112       So with dst_alpha blend we should use color factor. See spec on
113       "8-bit rendering" */
114    if ((dst_format == PICT_a8) && i915_blend_op[op].dst_alpha) {
115        if (sblend == BLENDFACT_DST_ALPHA)
116            sblend = BLENDFACT_DST_COLR;
117        else if (sblend == BLENDFACT_INV_DST_ALPHA)
118            sblend = BLENDFACT_INV_DST_COLR;
119    }
120
121    /* If the source alpha is being used, then we should only be in a case
122     * where the source blend factor is 0, and the source blend value is the
123     * mask channels multiplied by the source picture's alpha.
124     */
125    if (pMask && pMask->componentAlpha && PICT_FORMAT_RGB(pMask->format) &&
126	i915_blend_op[op].src_alpha)
127    {
128        if (dblend == BLENDFACT_SRC_ALPHA) {
129	    dblend = BLENDFACT_SRC_COLR;
130        } else if (dblend == BLENDFACT_INV_SRC_ALPHA) {
131	    dblend = BLENDFACT_INV_SRC_COLR;
132        }
133    }
134
135    return (sblend << S6_CBUF_SRC_BLEND_FACT_SHIFT) |
136	(dblend << S6_CBUF_DST_BLEND_FACT_SHIFT);
137}
138
139static Bool i915_get_dest_format(PicturePtr pDstPicture, uint32_t *dst_format)
140{
141    switch (pDstPicture->format) {
142    case PICT_a8r8g8b8:
143    case PICT_x8r8g8b8:
144        *dst_format = COLR_BUF_ARGB8888;
145        break;
146    case PICT_r5g6b5:
147        *dst_format = COLR_BUF_RGB565;
148        break;
149    case PICT_a1r5g5b5:
150    case PICT_x1r5g5b5:
151        *dst_format = COLR_BUF_ARGB1555;
152        break;
153    case PICT_a8:
154        *dst_format = COLR_BUF_8BIT;
155        break;
156    case PICT_a4r4g4b4:
157    case PICT_x4r4g4b4:
158	*dst_format = COLR_BUF_ARGB4444;
159	break;
160    default:
161	{
162	    ScrnInfoPtr pScrn;
163
164	    pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum];
165	    I830FALLBACK("Unsupported dest format 0x%x\n",
166			 (int)pDstPicture->format);
167	}
168    }
169    return TRUE;
170}
171
172static Bool i915_check_composite_texture(ScrnInfoPtr pScrn, PicturePtr pPict, int unit)
173{
174    if (pPict->repeatType > RepeatReflect)
175        I830FALLBACK("Unsupported picture repeat %d\n", pPict->repeatType);
176
177    if (pPict->filter != PictFilterNearest &&
178        pPict->filter != PictFilterBilinear)
179        I830FALLBACK("Unsupported filter 0x%x\n", pPict->filter);
180
181    if (pPict->pDrawable)
182    {
183	int w, h, i;
184
185	w = pPict->pDrawable->width;
186	h = pPict->pDrawable->height;
187	if ((w > 2048) || (h > 2048))
188	    I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
189
190	for (i = 0; i < sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0]);
191	     i++)
192	{
193	    if (i915_tex_formats[i].fmt == pPict->format)
194		break;
195	}
196	if (i == sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0]))
197	    I830FALLBACK("Unsupported picture format 0x%x\n",
198			 (int)pPict->format);
199    }
200
201    return TRUE;
202}
203
204Bool
205i915_check_composite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
206		     PicturePtr pDstPicture)
207{
208    ScrnInfoPtr pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum];
209    uint32_t tmp1;
210
211    /* Check for unsupported compositing operations. */
212    if (op >= sizeof(i915_blend_op) / sizeof(i915_blend_op[0]))
213        I830FALLBACK("Unsupported Composite op 0x%x\n", op);
214    if (pMaskPicture != NULL && pMaskPicture->componentAlpha &&
215	PICT_FORMAT_RGB(pMaskPicture->format))
216    {
217        /* Check if it's component alpha that relies on a source alpha and on
218         * the source value.  We can only get one of those into the single
219         * source value that we get to blend with.
220         */
221        if (i915_blend_op[op].src_alpha &&
222            (i915_blend_op[op].src_blend != BLENDFACT_ZERO))
223            	I830FALLBACK("Component alpha not supported with source "
224			     "alpha and source value blending.\n");
225    }
226
227    if (!i915_check_composite_texture(pScrn, pSrcPicture, 0))
228        I830FALLBACK("Check Src picture texture\n");
229    if (pMaskPicture != NULL && !i915_check_composite_texture(pScrn, pMaskPicture, 1))
230        I830FALLBACK("Check Mask picture texture\n");
231
232    if (!i915_get_dest_format(pDstPicture, &tmp1))
233	I830FALLBACK("Get Color buffer format\n");
234
235    return TRUE;
236}
237
238static Bool
239i915_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
240{
241    ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
242    I830Ptr pI830 = I830PTR(pScrn);
243    uint32_t format, pitch, filter;
244    int w, h, i;
245    uint32_t wrap_mode;
246
247    pitch = intel_get_pixmap_pitch(pPix);
248    w = pPict->pDrawable->width;
249    h = pPict->pDrawable->height;
250    pI830->scale_units[unit][0] = pPix->drawable.width;
251    pI830->scale_units[unit][1] = pPix->drawable.height;
252
253    for (i = 0; i < sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0]);
254	 i++)
255    {
256        if (i915_tex_formats[i].fmt == pPict->format)
257	    break;
258    }
259    if (i == sizeof(i915_tex_formats)/ sizeof(i915_tex_formats[0]))
260	I830FALLBACK("unknown texture format\n");
261    format = i915_tex_formats[i].card_fmt;
262
263    switch (pPict->repeatType) {
264    case RepeatNone:
265	wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
266	break;
267    case RepeatNormal:
268	wrap_mode = TEXCOORDMODE_WRAP;
269	break;
270    case RepeatPad:
271	wrap_mode = TEXCOORDMODE_CLAMP_EDGE;
272	break;
273    case RepeatReflect:
274	wrap_mode = TEXCOORDMODE_MIRROR;
275	break;
276    default:
277	FatalError("Unknown repeat type %d\n", pPict->repeatType);
278    }
279
280    switch (pPict->filter) {
281    case PictFilterNearest:
282        filter = (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT) |
283	    (FILTER_NEAREST << SS2_MIN_FILTER_SHIFT);
284        break;
285    case PictFilterBilinear:
286        filter = (FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) |
287	    (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT);
288        break;
289    default:
290	filter = 0;
291        I830FALLBACK("Bad filter 0x%x\n", pPict->filter);
292    }
293
294    pI830->mapstate[unit * 3 + 0] = 0; /* offset filled in at emit time */
295    pI830->mapstate[unit * 3 + 1] = format |
296	MS3_USE_FENCE_REGS |
297	((pPix->drawable.height - 1) << MS3_HEIGHT_SHIFT) |
298	((pPix->drawable.width - 1) << MS3_WIDTH_SHIFT);
299    pI830->mapstate[unit * 3 + 2] = ((pitch / 4) - 1) << MS4_PITCH_SHIFT;
300
301    pI830->samplerstate[unit * 3 + 0] = (MIPFILTER_NONE <<
302					 SS2_MIP_FILTER_SHIFT);
303    pI830->samplerstate[unit * 3 + 0] |= filter;
304    pI830->samplerstate[unit * 3 + 1] = SS3_NORMALIZED_COORDS;
305    pI830->samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCX_ADDR_MODE_SHIFT;
306    pI830->samplerstate[unit * 3 + 1] |= wrap_mode << SS3_TCY_ADDR_MODE_SHIFT;
307    pI830->samplerstate[unit * 3 + 1] |= unit << SS3_TEXTUREMAP_INDEX_SHIFT;
308    pI830->samplerstate[unit * 3 + 2] = 0x00000000; /* border color */
309
310    pI830->transform[unit] = pPict->transform;
311
312    return TRUE;
313}
314
315Bool
316i915_prepare_composite(int op, PicturePtr pSrcPicture,
317		       PicturePtr pMaskPicture, PicturePtr pDstPicture,
318		       PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
319{
320    ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
321    I830Ptr pI830 = I830PTR(pScrn);
322    drm_intel_bo *bo_table[] = {
323	NULL, /* batch_bo */
324	i830_get_pixmap_bo(pSrc),
325	pMask ? i830_get_pixmap_bo(pMask) : NULL,
326	i830_get_pixmap_bo(pDst),
327    };
328
329    pI830->render_src_picture = pSrcPicture;
330    pI830->render_src = pSrc;
331    pI830->render_mask_picture = pMaskPicture;
332    pI830->render_mask = pMask;
333    pI830->render_dst_picture = pDstPicture;
334    pI830->render_dst = pDst;
335
336    i830_exa_check_pitch_3d(pSrc);
337    if (pMask)
338	i830_exa_check_pitch_3d(pMask);
339    i830_exa_check_pitch_3d(pDst);
340
341    if (!i915_get_dest_format(pDstPicture,
342			      &pI830->i915_render_state.dst_format))
343	return FALSE;
344
345    if (!i830_get_aperture_space(pScrn, bo_table, ARRAY_SIZE(bo_table)))
346	return FALSE;
347
348    if (!i915_texture_setup(pSrcPicture, pSrc, 0))
349	I830FALLBACK("fail to setup src texture\n");
350
351    pI830->dst_coord_adjust = 0;
352    pI830->src_coord_adjust = 0;
353    pI830->mask_coord_adjust = 0;
354    if (pSrcPicture->filter == PictFilterNearest)
355	pI830->dst_coord_adjust = -0.125;
356    if (pMask != NULL) {
357	if (!i915_texture_setup(pMaskPicture, pMask, 1))
358	    I830FALLBACK("fail to setup mask texture\n");
359
360	if (pMaskPicture->filter == PictFilterNearest)
361	    pI830->dst_coord_adjust = -0.125;
362    } else {
363	pI830->transform[1] = NULL;
364	pI830->scale_units[1][0] = -1;
365	pI830->scale_units[1][1] = -1;
366    }
367
368    pI830->i915_render_state.op = op;
369    pI830->i915_render_state.needs_emit = TRUE;
370
371    return TRUE;
372}
373
374static void
375i915_emit_composite_setup(ScrnInfoPtr pScrn)
376{
377    I830Ptr pI830 = I830PTR(pScrn);
378    int op = pI830->i915_render_state.op;
379    PicturePtr pSrcPicture = pI830->render_src_picture;
380    PicturePtr pMaskPicture = pI830->render_mask_picture;
381    PicturePtr pDstPicture = pI830->render_dst_picture;
382    PixmapPtr pSrc = pI830->render_src;
383    PixmapPtr pMask = pI830->render_mask;
384    PixmapPtr pDst = pI830->render_dst;
385    uint32_t dst_format = pI830->i915_render_state.dst_format, dst_pitch;
386    uint32_t blendctl;
387    int out_reg = FS_OC;
388    FS_LOCALS(20);
389    Bool is_affine_src, is_affine_mask;
390
391    pI830->i915_render_state.needs_emit = FALSE;
392
393    IntelEmitInvarientState(pScrn);
394    pI830->last_3d = LAST_3D_RENDER;
395
396    dst_pitch = intel_get_pixmap_pitch(pDst);
397
398    is_affine_src = i830_transform_is_affine (pI830->transform[0]);
399    is_affine_mask = i830_transform_is_affine (pI830->transform[1]);
400
401    if (pMask == NULL) {
402	BEGIN_BATCH(10);
403	OUT_BATCH(_3DSTATE_MAP_STATE | 3);
404	OUT_BATCH(0x00000001); /* map 0 */
405	OUT_RELOC_PIXMAP(pSrc, I915_GEM_DOMAIN_SAMPLER, 0, 0);
406	OUT_BATCH(pI830->mapstate[1]);
407	OUT_BATCH(pI830->mapstate[2]);
408
409	OUT_BATCH(_3DSTATE_SAMPLER_STATE | 3);
410	OUT_BATCH(0x00000001); /* sampler 0 */
411	OUT_BATCH(pI830->samplerstate[0]);
412	OUT_BATCH(pI830->samplerstate[1]);
413	OUT_BATCH(pI830->samplerstate[2]);
414	ADVANCE_BATCH();
415    } else {
416	BEGIN_BATCH(16);
417	OUT_BATCH(_3DSTATE_MAP_STATE | 6);
418	OUT_BATCH(0x00000003); /* map 0,1 */
419	OUT_RELOC_PIXMAP(pSrc, I915_GEM_DOMAIN_SAMPLER, 0, 0);
420	OUT_BATCH(pI830->mapstate[1]);
421	OUT_BATCH(pI830->mapstate[2]);
422	OUT_RELOC_PIXMAP(pMask, I915_GEM_DOMAIN_SAMPLER, 0, 0);
423	OUT_BATCH(pI830->mapstate[4]);
424	OUT_BATCH(pI830->mapstate[5]);
425
426	OUT_BATCH(_3DSTATE_SAMPLER_STATE | 6);
427	OUT_BATCH(0x00000003); /* sampler 0,1 */
428	OUT_BATCH(pI830->samplerstate[0]);
429	OUT_BATCH(pI830->samplerstate[1]);
430	OUT_BATCH(pI830->samplerstate[2]);
431	OUT_BATCH(pI830->samplerstate[3]);
432	OUT_BATCH(pI830->samplerstate[4]);
433	OUT_BATCH(pI830->samplerstate[5]);
434	ADVANCE_BATCH();
435    }
436    {
437	uint32_t ss2;
438
439	BEGIN_BATCH(16);
440	OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
441	OUT_BATCH(BUF_3D_ID_COLOR_BACK| BUF_3D_USE_FENCE|
442		  BUF_3D_PITCH(dst_pitch));
443	OUT_RELOC_PIXMAP(pDst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
444
445	OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
446	OUT_BATCH(dst_format);
447
448	OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) |
449		  I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 3);
450	ss2 = S2_TEXCOORD_FMT(0, is_affine_src ? TEXCOORDFMT_2D : TEXCOORDFMT_4D);
451	if (pMask)
452		ss2 |= S2_TEXCOORD_FMT(1, is_affine_mask ? TEXCOORDFMT_2D : TEXCOORDFMT_4D);
453	else
454		ss2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT);
455	ss2 |= S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT);
456	ss2 |= S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT);
457	ss2 |= S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT);
458	ss2 |= S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT);
459	ss2 |= S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT);
460	ss2 |= S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT);
461	OUT_BATCH(ss2);
462	OUT_BATCH((1 << S4_POINT_WIDTH_SHIFT) | S4_LINE_WIDTH_ONE |
463		  S4_CULLMODE_NONE| S4_VFMT_XY);
464	blendctl = i915_get_blend_cntl(op, pMaskPicture, pDstPicture->format);
465	OUT_BATCH(0x00000000); /* Disable stencil buffer */
466	OUT_BATCH(S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE |
467		  (BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT) | blendctl);
468
469	/* draw rect is unconditional */
470	OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
471	OUT_BATCH(0x00000000);
472	OUT_BATCH(0x00000000);  /* ymin, xmin*/
473	OUT_BATCH(DRAW_YMAX(pDst->drawable.height - 1) |
474		  DRAW_XMAX(pDst->drawable.width - 1));
475	OUT_BATCH(0x00000000);  /* yorig, xorig (relate to color buffer?)*/
476	OUT_BATCH(MI_NOOP);
477	ADVANCE_BATCH();
478    }
479
480    if (dst_format == COLR_BUF_8BIT)
481	out_reg = FS_U0;
482
483    FS_BEGIN();
484
485    /* Declare the registers necessary for our program.  I don't think the
486     * S then T ordering is necessary.
487     */
488    i915_fs_dcl(FS_S0);
489    if (pMask)
490	i915_fs_dcl(FS_S1);
491    i915_fs_dcl(FS_T0);
492    if (pMask)
493	i915_fs_dcl(FS_T1);
494
495    /* Load the pSrcPicture texel */
496    if (is_affine_src) {
497	i915_fs_texld(FS_R0, FS_S0, FS_T0);
498    } else {
499	i915_fs_texldp(FS_R0, FS_S0, FS_T0);
500    }
501
502    /* If the texture lacks an alpha channel, force the alpha to 1. */
503    if (PICT_FORMAT_A(pSrcPicture->format) == 0)
504	i915_fs_mov_masked(FS_R0, MASK_W, i915_fs_operand_one());
505
506    if (!pMask) {
507	/* No mask, so move to output color */
508	i915_fs_mov(out_reg, i915_fs_operand_reg(FS_R0));
509    } else {
510	/* Load the pMaskPicture texel */
511	if (is_affine_mask) {
512	    i915_fs_texld(FS_R1, FS_S1, FS_T1);
513	} else {
514	    i915_fs_texldp(FS_R1, FS_S1, FS_T1);
515	}
516	/* If the texture lacks an alpha channel, force the alpha to 1. */
517	if (PICT_FORMAT_A(pMaskPicture->format) == 0)
518	    i915_fs_mov_masked(FS_R1, MASK_W, i915_fs_operand_one());
519
520	/* If component alpha is active in the mask and the blend operation
521	 * uses the source alpha, then we know we don't need the source
522	 * value (otherwise we would have hit a fallback earlier), so we
523	 * provide the source alpha (src.A * mask.X) as output color.
524	 * Conversely, if CA is set and we don't need the source alpha, then
525	 * we produce the source value (src.X * mask.X) and the source alpha
526	 * is unused..  Otherwise, we provide the non-CA source value
527	 * (src.X * mask.A).
528	 */
529	if (pMaskPicture->componentAlpha &&
530	    PICT_FORMAT_RGB(pMaskPicture->format))
531	{
532	    if (i915_blend_op[op].src_alpha) {
533		i915_fs_mul(out_reg, i915_fs_operand(FS_R0, W, W, W, W),
534			    i915_fs_operand_reg(FS_R1));
535	    } else {
536		i915_fs_mul(out_reg, i915_fs_operand_reg(FS_R0),
537			    i915_fs_operand_reg(FS_R1));
538	    }
539	} else {
540	    i915_fs_mul(out_reg, i915_fs_operand_reg(FS_R0),
541			i915_fs_operand(FS_R1, W, W, W, W));
542	}
543    }
544    if (dst_format == COLR_BUF_8BIT)
545	i915_fs_mov(FS_OC, i915_fs_operand(out_reg, W, W, W, W));
546
547    FS_END();
548}
549
550
551
552/* Emit the vertices for a single composite rectangle.
553 *
554 * This function is no longer shared between i830 and i915 generation code.
555 */
556static void
557i915_emit_composite_primitive(PixmapPtr pDst,
558			      int srcX, int srcY,
559			      int maskX, int maskY,
560			      int dstX, int dstY,
561			      int w, int h)
562{
563    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
564    I830Ptr pI830 = I830PTR(pScrn);
565    Bool is_affine_src, is_affine_mask = TRUE;
566    int per_vertex, num_floats;
567    float src_x[3], src_y[3], src_w[3], mask_x[3], mask_y[3], mask_w[3];
568
569    per_vertex = 2; /* dest x/y */
570
571    {
572	float x = srcX + pI830->src_coord_adjust;
573	float y = srcY + pI830->src_coord_adjust;
574
575	is_affine_src = i830_transform_is_affine (pI830->transform[0]);
576	if (is_affine_src) {
577	    if (!i830_get_transformed_coordinates(x, y,
578						  pI830->transform[0],
579						  &src_x[0], &src_y[0]))
580		return;
581
582	    if (!i830_get_transformed_coordinates(x, y + h,
583						  pI830->transform[0],
584						  &src_x[1], &src_y[1]))
585		return;
586
587	    if (!i830_get_transformed_coordinates(x + w, y + h,
588						  pI830->transform[0],
589						  &src_x[2], &src_y[2]))
590		return;
591
592	    per_vertex += 2;    /* src x/y */
593	} else {
594	    if (!i830_get_transformed_coordinates_3d(x, y,
595						     pI830->transform[0],
596						     &src_x[0],
597						     &src_y[0],
598						     &src_w[0]))
599		return;
600
601	    if (!i830_get_transformed_coordinates_3d(x, y + h,
602						     pI830->transform[0],
603						     &src_x[1],
604						     &src_y[1],
605						     &src_w[1]))
606		return;
607
608	    if (!i830_get_transformed_coordinates_3d(x + w, y + h,
609						     pI830->transform[0],
610						     &src_x[2],
611						     &src_y[2],
612						     &src_w[2]))
613		return;
614
615	    per_vertex += 4;    /* src x/y/z/w */
616	}
617    }
618
619    if (pI830->render_mask) {
620	float x = maskX + pI830->mask_coord_adjust;
621	float y = maskY + pI830->mask_coord_adjust;
622
623	is_affine_mask = i830_transform_is_affine (pI830->transform[1]);
624	if (is_affine_mask) {
625	    if (!i830_get_transformed_coordinates(x, y,
626						  pI830->transform[1],
627						  &mask_x[0], &mask_y[0]))
628		return;
629
630	    if (!i830_get_transformed_coordinates(x, y + h,
631						  pI830->transform[1],
632						  &mask_x[1], &mask_y[1]))
633		return;
634
635	    if (!i830_get_transformed_coordinates(x + w, y + h,
636						  pI830->transform[1],
637						  &mask_x[2], &mask_y[2]))
638		return;
639
640	    per_vertex += 2;	/* mask x/y */
641	} else {
642	    if (!i830_get_transformed_coordinates_3d(x, y,
643						     pI830->transform[1],
644						     &mask_x[0],
645						     &mask_y[0],
646						     &mask_w[0]))
647		return;
648
649	    if (!i830_get_transformed_coordinates_3d(x, y + h,
650						     pI830->transform[1],
651						     &mask_x[1],
652						     &mask_y[1],
653						     &mask_w[1]))
654		return;
655
656	    if (!i830_get_transformed_coordinates_3d(x + w, y + h,
657						     pI830->transform[1],
658						     &mask_x[2],
659						     &mask_y[2],
660						     &mask_w[2]))
661		return;
662
663	    per_vertex += 4;	/* mask x/y/z/w */
664	}
665    }
666
667    num_floats = 3 * per_vertex;
668
669    BEGIN_BATCH(1 + num_floats);
670
671    OUT_BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST | (num_floats-1));
672    OUT_BATCH_F(pI830->dst_coord_adjust + dstX + w);
673    OUT_BATCH_F(pI830->dst_coord_adjust + dstY + h);
674    OUT_BATCH_F(src_x[2] / pI830->scale_units[0][0]);
675    OUT_BATCH_F(src_y[2] / pI830->scale_units[0][1]);
676    if (!is_affine_src) {
677	OUT_BATCH_F(0.0);
678	OUT_BATCH_F(src_w[2]);
679    }
680    if (pI830->render_mask) {
681	OUT_BATCH_F(mask_x[2] / pI830->scale_units[1][0]);
682	OUT_BATCH_F(mask_y[2] / pI830->scale_units[1][1]);
683	if (!is_affine_mask) {
684	    OUT_BATCH_F(0.0);
685	    OUT_BATCH_F(mask_w[2]);
686	}
687    }
688
689    OUT_BATCH_F(pI830->dst_coord_adjust + dstX);
690    OUT_BATCH_F(pI830->dst_coord_adjust + dstY + h);
691    OUT_BATCH_F(src_x[1] / pI830->scale_units[0][0]);
692    OUT_BATCH_F(src_y[1] / pI830->scale_units[0][1]);
693    if (!is_affine_src) {
694	OUT_BATCH_F(0.0);
695	OUT_BATCH_F(src_w[1]);
696    }
697    if (pI830->render_mask) {
698	OUT_BATCH_F(mask_x[1] / pI830->scale_units[1][0]);
699	OUT_BATCH_F(mask_y[1] / pI830->scale_units[1][1]);
700	if (!is_affine_mask) {
701	    OUT_BATCH_F(0.0);
702	    OUT_BATCH_F(mask_w[1]);
703	}
704    }
705
706    OUT_BATCH_F(pI830->dst_coord_adjust + dstX);
707    OUT_BATCH_F(pI830->dst_coord_adjust + dstY);
708    OUT_BATCH_F(src_x[0] / pI830->scale_units[0][0]);
709    OUT_BATCH_F(src_y[0] / pI830->scale_units[0][1]);
710    if (!is_affine_src) {
711	OUT_BATCH_F(0.0);
712	OUT_BATCH_F(src_w[0]);
713    }
714    if (pI830->render_mask) {
715	OUT_BATCH_F(mask_x[0] / pI830->scale_units[1][0]);
716	OUT_BATCH_F(mask_y[0] / pI830->scale_units[1][1]);
717	if (!is_affine_mask) {
718	    OUT_BATCH_F(0.0);
719	    OUT_BATCH_F(mask_w[0]);
720	}
721    }
722
723    ADVANCE_BATCH();
724}
725
726void
727i915_composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
728	       int dstX, int dstY, int w, int h)
729{
730    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
731    I830Ptr pI830 = I830PTR(pScrn);
732
733    intel_batch_start_atomic(pScrn, 150);
734
735    if (pI830->i915_render_state.needs_emit)
736	i915_emit_composite_setup(pScrn);
737
738    i915_emit_composite_primitive(pDst, srcX, srcY, maskX, maskY, dstX, dstY,
739				  w, h);
740
741    intel_batch_end_atomic(pScrn);
742}
743
744void
745i915_batch_flush_notify(ScrnInfoPtr pScrn)
746{
747    I830Ptr pI830 = I830PTR(pScrn);
748
749    pI830->i915_render_state.needs_emit = TRUE;
750}
751