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