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