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 
39 struct blendinfo {
40 	Bool dst_alpha;
41 	Bool src_alpha;
42 	uint32_t src_blend;
43 	uint32_t dst_blend;
44 };
45 
46 struct 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 
102 static 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 
131 static 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 
140 static struct formatinfo i855_tex_formats[] = {
141 	{PICT_x8r8g8b8, MAPSURF_32BIT | MT_32BIT_XRGB8888},
142 	{PICT_x8b8g8r8, MAPSURF_32BIT | MT_32BIT_XBGR8888},
143 };
144 
i830_get_dest_format(PicturePtr dest_picture,uint32_t * dst_format)145 static 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 
i830_get_blend_cntl(ScrnInfoPtr scrn,int op,PicturePtr mask,uint32_t dst_format,uint32_t * blendctl)178 static 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 
i8xx_get_card_format(intel_screen_private * intel,PicturePtr picture)225 static 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 
i830_texture_setup(PicturePtr picture,PixmapPtr pixmap,int unit)247 static 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 
344 Bool
i830_check_composite(int op,PicturePtr source_picture,PicturePtr mask_picture,PicturePtr dest_picture,int width,int height)345 i830_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 
389 Bool
i830_check_composite_target(PixmapPtr pixmap)390 i830_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 
401 Bool
i830_check_composite_texture(ScreenPtr screen,PicturePtr picture)402 i830_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 
446 Bool
i830_prepare_composite(int op,PicturePtr source_picture,PicturePtr mask_picture,PicturePtr dest_picture,PixmapPtr source,PixmapPtr mask,PixmapPtr dest)447 i830_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 
i830_emit_composite_state(ScrnInfoPtr scrn)576 static 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  */
664 static void
i830_emit_composite_primitive(PixmapPtr dest,int srcX,int srcY,int maskX,int maskY,int dstX,int dstY,int w,int h)665 i830_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 
i830_vertex_flush(intel_screen_private * intel)843 void 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  */
854 void
i830_composite(PixmapPtr dest,int srcX,int srcY,int maskX,int maskY,int dstX,int dstY,int w,int h)855 i830_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 
i830_batch_commit_notify(intel_screen_private * intel)875 void i830_batch_commit_notify(intel_screen_private *intel)
876 {
877 	intel->needs_render_state_emit = TRUE;
878 }
879