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 "i915_reg.h"
38 #include "i915_3d.h"
39
40 struct formatinfo {
41 int fmt;
42 uint32_t card_fmt;
43 };
44
45 struct blendinfo {
46 Bool dst_alpha;
47 Bool src_alpha;
48 uint32_t src_blend;
49 uint32_t dst_blend;
50 };
51
52 static struct blendinfo i915_blend_op[] = {
53 /* Clear */
54 {0, 0, BLENDFACT_ZERO, BLENDFACT_ZERO},
55 /* Src */
56 {0, 0, BLENDFACT_ONE, BLENDFACT_ZERO},
57 /* Dst */
58 {0, 0, BLENDFACT_ZERO, BLENDFACT_ONE},
59 /* Over */
60 {0, 1, BLENDFACT_ONE, BLENDFACT_INV_SRC_ALPHA},
61 /* OverReverse */
62 {1, 0, BLENDFACT_INV_DST_ALPHA, BLENDFACT_ONE},
63 /* In */
64 {1, 0, BLENDFACT_DST_ALPHA, BLENDFACT_ZERO},
65 /* InReverse */
66 {0, 1, BLENDFACT_ZERO, BLENDFACT_SRC_ALPHA},
67 /* Out */
68 {1, 0, BLENDFACT_INV_DST_ALPHA, BLENDFACT_ZERO},
69 /* OutReverse */
70 {0, 1, BLENDFACT_ZERO, BLENDFACT_INV_SRC_ALPHA},
71 /* Atop */
72 {1, 1, BLENDFACT_DST_ALPHA, BLENDFACT_INV_SRC_ALPHA},
73 /* AtopReverse */
74 {1, 1, BLENDFACT_INV_DST_ALPHA, BLENDFACT_SRC_ALPHA},
75 /* Xor */
76 {1, 1, BLENDFACT_INV_DST_ALPHA, BLENDFACT_INV_SRC_ALPHA},
77 /* Add */
78 {0, 0, BLENDFACT_ONE, BLENDFACT_ONE},
79 };
80
81 static struct formatinfo i915_tex_formats[] = {
82 {PICT_a8, MAPSURF_8BIT | MT_8BIT_A8},
83 {PICT_a8r8g8b8, MAPSURF_32BIT | MT_32BIT_ARGB8888},
84 {PICT_x8r8g8b8, MAPSURF_32BIT | MT_32BIT_XRGB8888},
85 {PICT_a8b8g8r8, MAPSURF_32BIT | MT_32BIT_ABGR8888},
86 {PICT_x8b8g8r8, MAPSURF_32BIT | MT_32BIT_XBGR8888},
87 #if XORG_VERSION_CURRENT >= 10699900
88 {PICT_a2r10g10b10, MAPSURF_32BIT | MT_32BIT_ARGB2101010},
89 {PICT_a2b10g10r10, MAPSURF_32BIT | MT_32BIT_ABGR2101010},
90 #endif
91 {PICT_r5g6b5, MAPSURF_16BIT | MT_16BIT_RGB565},
92 {PICT_a1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555},
93 {PICT_a4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444},
94 };
95
i915_get_blend_cntl(int op,PicturePtr mask,uint32_t dst_format)96 static uint32_t i915_get_blend_cntl(int op, PicturePtr mask,
97 uint32_t dst_format)
98 {
99 uint32_t sblend, dblend;
100
101 sblend = i915_blend_op[op].src_blend;
102 dblend = i915_blend_op[op].dst_blend;
103
104 /* If there's no dst alpha channel, adjust the blend op so that we'll
105 * treat it as always 1.
106 */
107 if (PICT_FORMAT_A(dst_format) == 0 && i915_blend_op[op].dst_alpha) {
108 if (sblend == BLENDFACT_DST_ALPHA)
109 sblend = BLENDFACT_ONE;
110 else if (sblend == BLENDFACT_INV_DST_ALPHA)
111 sblend = BLENDFACT_ZERO;
112 }
113
114 /* i915 engine reads 8bit color buffer into green channel in cases
115 like color buffer blending .etc, and also writes back green channel.
116 So with dst_alpha blend we should use color factor. See spec on
117 "8-bit rendering" */
118 if ((dst_format == PICT_a8) && i915_blend_op[op].dst_alpha) {
119 if (sblend == BLENDFACT_DST_ALPHA)
120 sblend = BLENDFACT_DST_COLR;
121 else if (sblend == BLENDFACT_INV_DST_ALPHA)
122 sblend = BLENDFACT_INV_DST_COLR;
123 }
124
125 /* If the source alpha is being used, then we should only be in a case
126 * where the source blend factor is 0, and the source blend value is the
127 * mask channels multiplied by the source picture's alpha.
128 */
129 if (mask && mask->componentAlpha && PICT_FORMAT_RGB(mask->format) &&
130 i915_blend_op[op].src_alpha) {
131 if (dblend == BLENDFACT_SRC_ALPHA) {
132 dblend = BLENDFACT_SRC_COLR;
133 } else if (dblend == BLENDFACT_INV_SRC_ALPHA) {
134 dblend = BLENDFACT_INV_SRC_COLR;
135 }
136 }
137
138 return S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE |
139 (BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT) |
140 (sblend << S6_CBUF_SRC_BLEND_FACT_SHIFT) |
141 (dblend << S6_CBUF_DST_BLEND_FACT_SHIFT);
142 }
143
144 #define DSTORG_HORT_BIAS(x) ((x)<<20)
145 #define DSTORG_VERT_BIAS(x) ((x)<<16)
146
i915_get_dest_format(PicturePtr dest_picture,uint32_t * dst_format)147 static Bool i915_get_dest_format(PicturePtr dest_picture, uint32_t * dst_format)
148 {
149 ScrnInfoPtr scrn;
150
151 switch (dest_picture->format) {
152 case PICT_a8r8g8b8:
153 case PICT_x8r8g8b8:
154 *dst_format = COLR_BUF_ARGB8888;
155 break;
156 case PICT_r5g6b5:
157 *dst_format = COLR_BUF_RGB565;
158 break;
159 case PICT_a1r5g5b5:
160 case PICT_x1r5g5b5:
161 *dst_format = COLR_BUF_ARGB1555;
162 break;
163 #if XORG_VERSION_CURRENT >= 10699900
164 case PICT_a2r10g10b10:
165 case PICT_x2r10g10b10:
166 *dst_format = COLR_BUF_ARGB2AAA;
167 break;
168 #endif
169 case PICT_a8:
170 *dst_format = COLR_BUF_8BIT;
171 break;
172 case PICT_a4r4g4b4:
173 case PICT_x4r4g4b4:
174 *dst_format = COLR_BUF_ARGB4444;
175 break;
176 default:
177 scrn = xf86ScreenToScrn(dest_picture->pDrawable->pScreen);
178 intel_uxa_debug_fallback(scrn,
179 "Unsupported dest format 0x%x\n",
180 (int)dest_picture->format);
181 return FALSE;
182 }
183 *dst_format |= DSTORG_HORT_BIAS(0x8) | DSTORG_VERT_BIAS(0x8);
184 return TRUE;
185 }
186
187 Bool
i915_check_composite(int op,PicturePtr source_picture,PicturePtr mask_picture,PicturePtr dest_picture,int width,int height)188 i915_check_composite(int op,
189 PicturePtr source_picture,
190 PicturePtr mask_picture,
191 PicturePtr dest_picture,
192 int width, int height)
193 {
194 ScrnInfoPtr scrn = xf86ScreenToScrn(dest_picture->pDrawable->pScreen);
195 uint32_t tmp1;
196
197 /* Check for unsupported compositing operations. */
198 if (op >= sizeof(i915_blend_op) / sizeof(i915_blend_op[0])) {
199 intel_uxa_debug_fallback(scrn, "Unsupported Composite op 0x%x\n",
200 op);
201 return FALSE;
202 }
203 if (mask_picture != NULL && mask_picture->componentAlpha &&
204 PICT_FORMAT_RGB(mask_picture->format)) {
205 /* Check if it's component alpha that relies on a source alpha
206 * and on the source value. We can only get one of those
207 * into the single source value that we get to blend with.
208 */
209 if (i915_blend_op[op].src_alpha &&
210 (i915_blend_op[op].src_blend != BLENDFACT_ZERO)) {
211 if (op != PictOpOver) {
212 intel_uxa_debug_fallback(scrn,
213 "Component alpha not supported "
214 "with source alpha and source "
215 "value blending.\n");
216 return FALSE;
217 }
218 }
219 }
220
221 if (!i915_get_dest_format(dest_picture, &tmp1)) {
222 intel_uxa_debug_fallback(scrn, "Get Color buffer format\n");
223 return FALSE;
224 }
225
226 if (width > 2048 || height > 2048)
227 return FALSE;
228
229 return TRUE;
230 }
231
232 Bool
i915_check_composite_target(PixmapPtr pixmap)233 i915_check_composite_target(PixmapPtr pixmap)
234 {
235 if (pixmap->drawable.width > 2048 || pixmap->drawable.height > 2048)
236 return FALSE;
237
238 if(!intel_uxa_check_pitch_3d(pixmap))
239 return FALSE;
240
241 return TRUE;
242 }
243
244 Bool
i915_check_composite_texture(ScreenPtr screen,PicturePtr picture)245 i915_check_composite_texture(ScreenPtr screen, PicturePtr picture)
246 {
247 if (picture->repeatType > RepeatReflect) {
248 ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
249 intel_uxa_debug_fallback(scrn, "Unsupported picture repeat %d\n",
250 picture->repeatType);
251 return FALSE;
252 }
253
254 if (picture->filter != PictFilterNearest &&
255 picture->filter != PictFilterBilinear) {
256 ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
257 intel_uxa_debug_fallback(scrn, "Unsupported filter 0x%x\n",
258 picture->filter);
259 return FALSE;
260 }
261
262 if (picture->pSourcePict)
263 return FALSE;
264
265 if (picture->pDrawable) {
266 int w, h, i;
267
268 w = picture->pDrawable->width;
269 h = picture->pDrawable->height;
270 if ((w > 2048) || (h > 2048)) {
271 ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
272 intel_uxa_debug_fallback(scrn,
273 "Picture w/h too large (%dx%d)\n",
274 w, h);
275 return FALSE;
276 }
277
278 for (i = 0;
279 i < sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0]);
280 i++) {
281 if (i915_tex_formats[i].fmt == picture->format)
282 break;
283 }
284 if (i == sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0]))
285 {
286 ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
287 intel_uxa_debug_fallback(scrn, "Unsupported picture format "
288 "0x%x\n",
289 (int)picture->format);
290 return FALSE;
291 }
292
293 return TRUE;
294 }
295
296 return FALSE;
297 }
298
i915_texture_setup(PicturePtr picture,PixmapPtr pixmap,int unit)299 static Bool i915_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit)
300 {
301 ScrnInfoPtr scrn = xf86ScreenToScrn(picture->pDrawable->pScreen);
302 intel_screen_private *intel = intel_get_screen_private(scrn);
303 uint32_t format, pitch, filter;
304 uint32_t wrap_mode, tiling_bits;
305 int i;
306
307 pitch = intel_pixmap_pitch(pixmap);
308 intel->scale_units[unit][0] = 1. / pixmap->drawable.width;
309 intel->scale_units[unit][1] = 1. / pixmap->drawable.height;
310
311 for (i = 0; i < sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0]);
312 i++) {
313 if (i915_tex_formats[i].fmt == picture->format)
314 break;
315 }
316 if (i == sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0])) {
317 intel_uxa_debug_fallback(scrn, "unknown texture format\n");
318 return FALSE;
319 }
320 format = i915_tex_formats[i].card_fmt;
321
322 switch (picture->repeatType) {
323 case RepeatNone:
324 wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
325 break;
326 case RepeatNormal:
327 wrap_mode = TEXCOORDMODE_WRAP;
328 break;
329 case RepeatPad:
330 wrap_mode = TEXCOORDMODE_CLAMP_EDGE;
331 break;
332 case RepeatReflect:
333 wrap_mode = TEXCOORDMODE_MIRROR;
334 break;
335 default:
336 FatalError("Unknown repeat type %d\n", picture->repeatType);
337 }
338
339 switch (picture->filter) {
340 case PictFilterNearest:
341 filter = (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT) |
342 (FILTER_NEAREST << SS2_MIN_FILTER_SHIFT);
343 break;
344 case PictFilterBilinear:
345 filter = (FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) |
346 (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT);
347 break;
348 default:
349 intel_uxa_debug_fallback(scrn, "Bad filter 0x%x\n",
350 picture->filter);
351 return FALSE;
352 }
353
354 /* offset filled in at emit time */
355 if (intel_uxa_pixmap_tiled(pixmap)) {
356 tiling_bits = MS3_TILED_SURFACE;
357 if (intel_uxa_get_pixmap_private(pixmap)->tiling
358 == I915_TILING_Y)
359 tiling_bits |= MS3_TILE_WALK;
360 } else
361 tiling_bits = 0;
362
363 intel->texture[unit] = pixmap;
364 intel->mapstate[unit * 3 + 0] = 0;
365 intel->mapstate[unit * 3 + 1] = format |
366 tiling_bits |
367 ((pixmap->drawable.height - 1) << MS3_HEIGHT_SHIFT) |
368 ((pixmap->drawable.width - 1) << MS3_WIDTH_SHIFT);
369 intel->mapstate[unit * 3 + 2] = ((pitch / 4) - 1) << MS4_PITCH_SHIFT;
370
371 intel->samplerstate[unit * 3 + 0] = (MIPFILTER_NONE <<
372 SS2_MIP_FILTER_SHIFT);
373 intel->samplerstate[unit * 3 + 0] |= filter;
374 intel->samplerstate[unit * 3 + 1] = SS3_NORMALIZED_COORDS;
375 intel->samplerstate[unit * 3 + 1] |=
376 wrap_mode << SS3_TCX_ADDR_MODE_SHIFT;
377 intel->samplerstate[unit * 3 + 1] |=
378 wrap_mode << SS3_TCY_ADDR_MODE_SHIFT;
379 intel->samplerstate[unit * 3 + 1] |= unit << SS3_TEXTUREMAP_INDEX_SHIFT;
380 intel->samplerstate[unit * 3 + 2] = 0x00000000; /* border color */
381
382 intel->transform[unit] = picture->transform;
383
384 return TRUE;
385 }
386
387 static void
i915_emit_composite_primitive_identity_source(intel_screen_private * intel,int srcX,int srcY,int maskX,int maskY,int dstX,int dstY,int w,int h)388 i915_emit_composite_primitive_identity_source(intel_screen_private *intel,
389 int srcX, int srcY,
390 int maskX, int maskY,
391 int dstX, int dstY,
392 int w, int h)
393 {
394 OUT_VERTEX(dstX + w);
395 OUT_VERTEX(dstY + h);
396 OUT_VERTEX((srcX + w) * intel->scale_units[0][0]);
397 OUT_VERTEX((srcY + h) * intel->scale_units[0][1]);
398
399 OUT_VERTEX(dstX);
400 OUT_VERTEX(dstY + h);
401 OUT_VERTEX(srcX * intel->scale_units[0][0]);
402 OUT_VERTEX((srcY + h) * intel->scale_units[0][1]);
403
404 OUT_VERTEX(dstX);
405 OUT_VERTEX(dstY);
406 OUT_VERTEX(srcX * intel->scale_units[0][0]);
407 OUT_VERTEX(srcY * intel->scale_units[0][1]);
408 }
409
410 static void
i915_emit_composite_primitive_affine_source(intel_screen_private * intel,int srcX,int srcY,int maskX,int maskY,int dstX,int dstY,int w,int h)411 i915_emit_composite_primitive_affine_source(intel_screen_private *intel,
412 int srcX, int srcY,
413 int maskX, int maskY,
414 int dstX, int dstY,
415 int w, int h)
416 {
417 float src_x[3], src_y[3];
418
419 if (!intel_uxa_get_transformed_coordinates(srcX, srcY,
420 intel->transform[0],
421 &src_x[0],
422 &src_y[0]))
423 return;
424
425 if (!intel_uxa_get_transformed_coordinates(srcX, srcY + h,
426 intel->transform[0],
427 &src_x[1],
428 &src_y[1]))
429 return;
430
431 if (!intel_uxa_get_transformed_coordinates(srcX + w, srcY + h,
432 intel->transform[0],
433 &src_x[2],
434 &src_y[2]))
435 return;
436
437 OUT_VERTEX(dstX + w);
438 OUT_VERTEX(dstY + h);
439 OUT_VERTEX(src_x[2] * intel->scale_units[0][0]);
440 OUT_VERTEX(src_y[2] * intel->scale_units[0][1]);
441
442 OUT_VERTEX(dstX);
443 OUT_VERTEX(dstY + h);
444 OUT_VERTEX(src_x[1] * intel->scale_units[0][0]);
445 OUT_VERTEX(src_y[1] * intel->scale_units[0][1]);
446
447 OUT_VERTEX(dstX);
448 OUT_VERTEX(dstY);
449 OUT_VERTEX(src_x[0] * intel->scale_units[0][0]);
450 OUT_VERTEX(src_y[0] * intel->scale_units[0][1]);
451 }
452
453 static void
i915_emit_composite_primitive_identity_source_mask(intel_screen_private * intel,int srcX,int srcY,int maskX,int maskY,int dstX,int dstY,int w,int h)454 i915_emit_composite_primitive_identity_source_mask(intel_screen_private *intel,
455 int srcX, int srcY,
456 int maskX, int maskY,
457 int dstX, int dstY,
458 int w, int h)
459 {
460 OUT_VERTEX(dstX + w);
461 OUT_VERTEX(dstY + h);
462 OUT_VERTEX((srcX + w) * intel->scale_units[0][0]);
463 OUT_VERTEX((srcY + h) * intel->scale_units[0][1]);
464 OUT_VERTEX((maskX + w) * intel->scale_units[1][0]);
465 OUT_VERTEX((maskY + h) * intel->scale_units[1][1]);
466
467 OUT_VERTEX(dstX);
468 OUT_VERTEX(dstY + h);
469 OUT_VERTEX(srcX * intel->scale_units[0][0]);
470 OUT_VERTEX((srcY + h) * intel->scale_units[0][1]);
471 OUT_VERTEX(maskX * intel->scale_units[1][0]);
472 OUT_VERTEX((maskY + h) * intel->scale_units[1][1]);
473
474 OUT_VERTEX(dstX);
475 OUT_VERTEX(dstY);
476 OUT_VERTEX(srcX * intel->scale_units[0][0]);
477 OUT_VERTEX(srcY * intel->scale_units[0][1]);
478 OUT_VERTEX(maskX * intel->scale_units[1][0]);
479 OUT_VERTEX(maskY * intel->scale_units[1][1]);
480 }
481
482 static void
i915_emit_composite_primitive(intel_screen_private * intel,int srcX,int srcY,int maskX,int maskY,int dstX,int dstY,int w,int h)483 i915_emit_composite_primitive(intel_screen_private *intel,
484 int srcX, int srcY,
485 int maskX, int maskY,
486 int dstX, int dstY,
487 int w, int h)
488 {
489 Bool is_affine_src = TRUE, is_affine_mask = TRUE;
490 int tex_unit = 0;
491 int src_unit = -1, mask_unit = -1;
492 float src_x[3], src_y[3], src_w[3], mask_x[3], mask_y[3], mask_w[3];
493
494 src_unit = tex_unit++;
495
496 is_affine_src = intel_uxa_transform_is_affine(intel->transform[src_unit]);
497 if (is_affine_src) {
498 if (!intel_uxa_get_transformed_coordinates(srcX, srcY,
499 intel->
500 transform[src_unit],
501 &src_x[0],
502 &src_y[0]))
503 return;
504
505 if (!intel_uxa_get_transformed_coordinates(srcX, srcY + h,
506 intel->
507 transform[src_unit],
508 &src_x[1],
509 &src_y[1]))
510 return;
511
512 if (!intel_uxa_get_transformed_coordinates(srcX + w, srcY + h,
513 intel->
514 transform[src_unit],
515 &src_x[2],
516 &src_y[2]))
517 return;
518 } else {
519 if (!intel_uxa_get_transformed_coordinates_3d(srcX, srcY,
520 intel->
521 transform[src_unit],
522 &src_x[0],
523 &src_y[0],
524 &src_w[0]))
525 return;
526
527 if (!intel_uxa_get_transformed_coordinates_3d(srcX, srcY + h,
528 intel->
529 transform[src_unit],
530 &src_x[1],
531 &src_y[1],
532 &src_w[1]))
533 return;
534
535 if (!intel_uxa_get_transformed_coordinates_3d(srcX + w, srcY + h,
536 intel->
537 transform[src_unit],
538 &src_x[2],
539 &src_y[2],
540 &src_w[2]))
541 return;
542 }
543
544 if (intel->render_mask) {
545 mask_unit = tex_unit++;
546
547 is_affine_mask = intel_uxa_transform_is_affine(intel->transform[mask_unit]);
548 if (is_affine_mask) {
549 if (!intel_uxa_get_transformed_coordinates(maskX, maskY,
550 intel->
551 transform[mask_unit],
552 &mask_x[0],
553 &mask_y[0]))
554 return;
555
556 if (!intel_uxa_get_transformed_coordinates(maskX, maskY + h,
557 intel->
558 transform[mask_unit],
559 &mask_x[1],
560 &mask_y[1]))
561 return;
562
563 if (!intel_uxa_get_transformed_coordinates(maskX + w, maskY + h,
564 intel->
565 transform[mask_unit],
566 &mask_x[2],
567 &mask_y[2]))
568 return;
569 } else {
570 if (!intel_uxa_get_transformed_coordinates_3d(maskX, maskY,
571 intel->
572 transform[mask_unit],
573 &mask_x[0],
574 &mask_y[0],
575 &mask_w[0]))
576 return;
577
578 if (!intel_uxa_get_transformed_coordinates_3d(maskX, maskY + h,
579 intel->
580 transform[mask_unit],
581 &mask_x[1],
582 &mask_y[1],
583 &mask_w[1]))
584 return;
585
586 if (!intel_uxa_get_transformed_coordinates_3d(maskX + w, maskY + h,
587 intel->
588 transform[mask_unit],
589 &mask_x[2],
590 &mask_y[2],
591 &mask_w[2]))
592 return;
593 }
594 }
595
596 OUT_VERTEX(dstX + w);
597 OUT_VERTEX(dstY + h);
598 OUT_VERTEX(src_x[2] * intel->scale_units[src_unit][0]);
599 OUT_VERTEX(src_y[2] * intel->scale_units[src_unit][1]);
600 if (!is_affine_src) {
601 OUT_VERTEX(0.0);
602 OUT_VERTEX(src_w[2]);
603 }
604 if (intel->render_mask) {
605 OUT_VERTEX(mask_x[2] * intel->scale_units[mask_unit][0]);
606 OUT_VERTEX(mask_y[2] * intel->scale_units[mask_unit][1]);
607 if (!is_affine_mask) {
608 OUT_VERTEX(0.0);
609 OUT_VERTEX(mask_w[2]);
610 }
611 }
612
613 OUT_VERTEX(dstX);
614 OUT_VERTEX(dstY + h);
615 OUT_VERTEX(src_x[1] * intel->scale_units[src_unit][0]);
616 OUT_VERTEX(src_y[1] * intel->scale_units[src_unit][1]);
617 if (!is_affine_src) {
618 OUT_VERTEX(0.0);
619 OUT_VERTEX(src_w[1]);
620 }
621 if (intel->render_mask) {
622 OUT_VERTEX(mask_x[1] * intel->scale_units[mask_unit][0]);
623 OUT_VERTEX(mask_y[1] * intel->scale_units[mask_unit][1]);
624 if (!is_affine_mask) {
625 OUT_VERTEX(0.0);
626 OUT_VERTEX(mask_w[1]);
627 }
628 }
629
630 OUT_VERTEX(dstX);
631 OUT_VERTEX(dstY);
632 OUT_VERTEX(src_x[0] * intel->scale_units[src_unit][0]);
633 OUT_VERTEX(src_y[0] * intel->scale_units[src_unit][1]);
634 if (!is_affine_src) {
635 OUT_VERTEX(0.0);
636 OUT_VERTEX(src_w[0]);
637 }
638 if (intel->render_mask) {
639 OUT_VERTEX(mask_x[0] * intel->scale_units[mask_unit][0]);
640 OUT_VERTEX(mask_y[0] * intel->scale_units[mask_unit][1]);
641 if (!is_affine_mask) {
642 OUT_VERTEX(0.0);
643 OUT_VERTEX(mask_w[0]);
644 }
645 }
646 }
647
648 Bool
i915_prepare_composite(int op,PicturePtr source_picture,PicturePtr mask_picture,PicturePtr dest_picture,PixmapPtr source,PixmapPtr mask,PixmapPtr dest)649 i915_prepare_composite(int op, PicturePtr source_picture,
650 PicturePtr mask_picture, PicturePtr dest_picture,
651 PixmapPtr source, PixmapPtr mask, PixmapPtr dest)
652 {
653 ScrnInfoPtr scrn = xf86ScreenToScrn(dest_picture->pDrawable->pScreen);
654 intel_screen_private *intel = intel_get_screen_private(scrn);
655 drm_intel_bo *bo_table[] = {
656 NULL, /* batch_bo */
657 intel_uxa_get_pixmap_bo(dest),
658 intel_uxa_get_pixmap_bo(source),
659 mask ? intel_uxa_get_pixmap_bo(mask) : NULL,
660 };
661 int tex_unit = 0;
662 int floats_per_vertex;
663
664 intel->render_source_picture = source_picture;
665 intel->render_source = source;
666 intel->render_mask_picture = mask_picture;
667 intel->render_mask = mask;
668 intel->render_dest_picture = dest_picture;
669 intel->render_dest = dest;
670
671 if (!intel_uxa_check_pitch_3d(source))
672 return FALSE;
673
674 if (mask && !intel_uxa_check_pitch_3d(mask))
675 return FALSE;
676
677 if (!intel_uxa_check_pitch_3d(dest))
678 return FALSE;
679
680 if (!i915_get_dest_format(dest_picture,
681 &intel->i915_render_state.dst_format))
682 return FALSE;
683
684 if (!intel_uxa_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
685 return FALSE;
686
687 if (mask_picture != NULL && mask_picture->componentAlpha &&
688 PICT_FORMAT_RGB(mask_picture->format)) {
689 /* Check if it's component alpha that relies on a source alpha
690 * and on the source value. We can only get one of those
691 * into the single source value that we get to blend with.
692 */
693 if (i915_blend_op[op].src_alpha &&
694 (i915_blend_op[op].src_blend != BLENDFACT_ZERO))
695 return FALSE;
696 }
697
698 intel->transform[0] = NULL;
699 intel->scale_units[0][0] = -1;
700 intel->scale_units[0][1] = -1;
701 intel->transform[1] = NULL;
702 intel->scale_units[1][0] = -1;
703 intel->scale_units[1][1] = -1;
704
705 floats_per_vertex = 2; /* dest x/y */
706 if (!i915_texture_setup(source_picture, source, tex_unit++)) {
707 intel_uxa_debug_fallback(scrn, "fail to setup src texture\n");
708 return FALSE;
709 }
710
711 if (intel_uxa_transform_is_affine(source_picture->transform))
712 floats_per_vertex += 2; /* src x/y */
713 else
714 floats_per_vertex += 4; /* src x/y/z/w */
715
716 if (mask_picture != NULL) {
717 assert(mask != NULL);
718 if (!i915_texture_setup(mask_picture, mask, tex_unit++)) {
719 intel_uxa_debug_fallback(scrn,
720 "fail to setup mask texture\n");
721 return FALSE;
722 }
723
724 if (intel_uxa_transform_is_affine(mask_picture->transform))
725 floats_per_vertex += 2; /* mask x/y */
726 else
727 floats_per_vertex += 4; /* mask x/y/z/w */
728 }
729
730 intel->i915_render_state.op = op;
731
732 if (intel_uxa_pixmap_is_dirty(source) || intel_uxa_pixmap_is_dirty(mask))
733 intel_batch_emit_flush(scrn);
734
735 intel->needs_render_state_emit = TRUE;
736
737 intel->prim_emit = i915_emit_composite_primitive;
738 if (!mask) {
739 if (intel->transform[0] == NULL)
740 intel->prim_emit = i915_emit_composite_primitive_identity_source;
741 else if (intel_uxa_transform_is_affine(intel->transform[0]))
742 intel->prim_emit = i915_emit_composite_primitive_affine_source;
743 } else {
744 if (intel->transform[0] == NULL) {
745 if (intel->transform[1] == NULL)
746 intel->prim_emit = i915_emit_composite_primitive_identity_source_mask;
747 }
748 }
749
750 if (floats_per_vertex != intel->floats_per_vertex) {
751 intel->floats_per_vertex = floats_per_vertex;
752 intel->needs_render_vertex_emit = TRUE;
753 }
754
755 return TRUE;
756 }
757
758 static void
i915_composite_emit_shader(intel_screen_private * intel,CARD8 op)759 i915_composite_emit_shader(intel_screen_private *intel, CARD8 op)
760 {
761 PicturePtr mask_picture = intel->render_mask_picture;
762 PixmapPtr mask = intel->render_mask;
763 int src_reg, mask_reg;
764 Bool dest_is_alpha = PIXMAN_FORMAT_RGB(intel->render_dest_picture->format) == 0;
765 FS_LOCALS();
766
767 FS_BEGIN();
768
769 /* Declare the registers necessary for our program. */
770 i915_fs_dcl(FS_T0);
771 i915_fs_dcl(FS_S0);
772 if (!mask) {
773 /* No mask, so load directly to output color */
774 if (dest_is_alpha)
775 src_reg = FS_R0;
776 else
777 src_reg = FS_OC;
778
779 if (intel_uxa_transform_is_affine(intel->transform[0]))
780 i915_fs_texld(src_reg, FS_S0, FS_T0);
781 else
782 i915_fs_texldp(src_reg, FS_S0, FS_T0);
783
784 if (src_reg != FS_OC)
785 i915_fs_mov(FS_OC, i915_fs_operand(src_reg, W, W, W, W));
786 } else {
787 i915_fs_dcl(FS_T1);
788 i915_fs_dcl(FS_S1);
789
790 /* Load the source_picture texel */
791 if (intel_uxa_transform_is_affine(intel->transform[0]))
792 i915_fs_texld(FS_R0, FS_S0, FS_T0);
793 else
794 i915_fs_texldp(FS_R0, FS_S0, FS_T0);
795
796 src_reg = FS_R0;
797
798 /* Load the mask_picture texel */
799 if (intel_uxa_transform_is_affine(intel->transform[1]))
800 i915_fs_texld(FS_R1, FS_S1, FS_T1);
801 else
802 i915_fs_texldp(FS_R1, FS_S1, FS_T1);
803
804 mask_reg = FS_R1;
805
806 if (dest_is_alpha) {
807 i915_fs_mul(FS_OC,
808 i915_fs_operand(src_reg, W, W, W, W),
809 i915_fs_operand(mask_reg, W, W, W, W));
810 } else {
811 /* If component alpha is active in the mask and the blend
812 * operation uses the source alpha, then we know we don't
813 * need the source value (otherwise we would have hit a
814 * fallback earlier), so we provide the source alpha (src.A *
815 * mask.X) as output color.
816 * Conversely, if CA is set and we don't need the source alpha,
817 * then we produce the source value (src.X * mask.X) and the
818 * source alpha is unused. Otherwise, we provide the non-CA
819 * source value (src.X * mask.A).
820 */
821 if (mask_picture->componentAlpha &&
822 PICT_FORMAT_RGB(mask_picture->format)) {
823 if (i915_blend_op[op].src_alpha) {
824 i915_fs_mul(FS_OC,
825 i915_fs_operand(src_reg, W, W, W, W),
826 i915_fs_operand_reg(mask_reg));
827 } else {
828 i915_fs_mul(FS_OC,
829 i915_fs_operand_reg(src_reg),
830 i915_fs_operand_reg(mask_reg));
831 }
832 } else {
833 i915_fs_mul(FS_OC,
834 i915_fs_operand_reg(src_reg),
835 i915_fs_operand(mask_reg, W, W, W, W));
836 }
837 }
838 }
839
840 FS_END();
841 }
842
i915_emit_composite_setup(ScrnInfoPtr scrn)843 static void i915_emit_composite_setup(ScrnInfoPtr scrn)
844 {
845 intel_screen_private *intel = intel_get_screen_private(scrn);
846 int op = intel->i915_render_state.op;
847 PicturePtr mask_picture = intel->render_mask_picture;
848 PicturePtr dest_picture = intel->render_dest_picture;
849 PixmapPtr mask = intel->render_mask;
850 PixmapPtr dest = intel->render_dest;
851 int tex_count, t;
852
853 intel->needs_render_state_emit = FALSE;
854
855 IntelEmitInvarientState(scrn);
856 intel->last_3d = LAST_3D_RENDER;
857
858 tex_count = 1 + (mask != NULL);
859
860 assert(intel->in_batch_atomic);
861
862 if (tex_count != 0) {
863 OUT_BATCH(_3DSTATE_MAP_STATE | (3 * tex_count));
864 OUT_BATCH((1 << tex_count) - 1);
865 for (t = 0; t < tex_count; t++) {
866 OUT_RELOC_PIXMAP(intel->texture[t], I915_GEM_DOMAIN_SAMPLER, 0, 0);
867 OUT_BATCH(intel->mapstate[3*t + 1]);
868 OUT_BATCH(intel->mapstate[3*t + 2]);
869 }
870
871 OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * tex_count));
872 OUT_BATCH((1 << tex_count) - 1);
873 for (t = 0; t < tex_count; t++) {
874 OUT_BATCH(intel->samplerstate[3*t + 0]);
875 OUT_BATCH(intel->samplerstate[3*t + 1]);
876 OUT_BATCH(intel->samplerstate[3*t + 2]);
877 }
878 }
879
880 /* BUF_INFO is an implicit flush, so avoid if the target has not changed.
881 * XXX However for reasons unfathomed, correct rendering in KDE requires
882 * at least a MI_FLUSH | INHIBIT_RENDER_CACHE_FLUSH here.
883 */
884 if (1) {
885 uint32_t tiling_bits;
886
887 if (intel_uxa_pixmap_tiled(dest)) {
888 tiling_bits = BUF_3D_TILED_SURFACE;
889 if (intel_uxa_get_pixmap_private(dest)->tiling
890 == I915_TILING_Y)
891 tiling_bits |= BUF_3D_TILE_WALK_Y;
892 } else
893 tiling_bits = 0;
894
895 OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
896 OUT_BATCH(BUF_3D_ID_COLOR_BACK | tiling_bits |
897 BUF_3D_PITCH(intel_pixmap_pitch(dest)));
898 OUT_RELOC_PIXMAP(dest, I915_GEM_DOMAIN_RENDER,
899 I915_GEM_DOMAIN_RENDER, 0);
900
901 OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
902 OUT_BATCH(intel->i915_render_state.dst_format);
903
904 /* draw rect is unconditional */
905 OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
906 OUT_BATCH(0x00000000);
907 OUT_BATCH(0x00000000); /* ymin, xmin */
908 OUT_BATCH(DRAW_YMAX(dest->drawable.height - 1) |
909 DRAW_XMAX(dest->drawable.width - 1));
910 /* yorig, xorig (relate to color buffer?) */
911 OUT_BATCH(0x00000000);
912 }
913
914 {
915 uint32_t ss2;
916
917 ss2 = ~0;
918 ss2 &= ~S2_TEXCOORD_FMT(0, TEXCOORDFMT_NOT_PRESENT);
919 ss2 |= S2_TEXCOORD_FMT(0,
920 intel_uxa_transform_is_affine(intel->transform[0]) ?
921 TEXCOORDFMT_2D : TEXCOORDFMT_4D);
922 if (mask) {
923 ss2 &= ~S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT);
924 ss2 |= S2_TEXCOORD_FMT(1,
925 intel_uxa_transform_is_affine(intel->transform[1]) ?
926 TEXCOORDFMT_2D : TEXCOORDFMT_4D);
927 }
928
929 OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | I1_LOAD_S(6) | 1);
930 OUT_BATCH(ss2);
931 OUT_BATCH(i915_get_blend_cntl(op, mask_picture, dest_picture->format));
932 }
933
934 i915_composite_emit_shader(intel, op);
935 }
936
937 void
i915_composite(PixmapPtr dest,int srcX,int srcY,int maskX,int maskY,int dstX,int dstY,int w,int h)938 i915_composite(PixmapPtr dest, int srcX, int srcY, int maskX, int maskY,
939 int dstX, int dstY, int w, int h)
940 {
941 ScrnInfoPtr scrn = xf86ScreenToScrn(dest->drawable.pScreen);
942 intel_screen_private *intel = intel_get_screen_private(scrn);
943
944 /* 28 + 16 + 10 + 20 + 32 + 16 */
945 intel_batch_start_atomic(scrn, 150);
946
947 if (intel->needs_render_state_emit)
948 i915_emit_composite_setup(scrn);
949
950 if (intel->needs_render_vertex_emit ||
951 intel_vertex_space(intel) < 3*4*intel->floats_per_vertex) {
952 i915_vertex_flush(intel);
953
954 if (intel_vertex_space(intel) < 256) {
955 intel_next_vertex(intel);
956
957 OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
958 I1_LOAD_S(0) | I1_LOAD_S(1) | 1);
959 OUT_RELOC(intel->vertex_bo, I915_GEM_DOMAIN_VERTEX, 0, 0);
960 OUT_BATCH((intel->floats_per_vertex << S1_VERTEX_WIDTH_SHIFT) |
961 (intel->floats_per_vertex << S1_VERTEX_PITCH_SHIFT));
962 intel->vertex_index = 0;
963 } else if (intel->floats_per_vertex != intel->last_floats_per_vertex){
964 OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
965 I1_LOAD_S(1) | 0);
966 OUT_BATCH((intel->floats_per_vertex << S1_VERTEX_WIDTH_SHIFT) |
967 (intel->floats_per_vertex << S1_VERTEX_PITCH_SHIFT));
968
969 intel->vertex_index =
970 (intel->vertex_used + intel->floats_per_vertex - 1) / intel->floats_per_vertex;
971 intel->vertex_used = intel->vertex_index * intel->floats_per_vertex;
972 }
973
974 intel->last_floats_per_vertex = intel->floats_per_vertex;
975 intel->needs_render_vertex_emit = FALSE;
976 }
977
978 if (intel->prim_offset == 0) {
979 intel->prim_offset = intel->batch_used;
980 OUT_BATCH(PRIM3D_RECTLIST | PRIM3D_INDIRECT_SEQUENTIAL);
981 OUT_BATCH(intel->vertex_index);
982 }
983 intel->vertex_count += 3;
984
985 intel->prim_emit(intel,
986 srcX, srcY,
987 maskX, maskY,
988 dstX, dstY,
989 w, h);
990
991 intel_batch_end_atomic(scrn);
992 }
993
994 void
i915_vertex_flush(intel_screen_private * intel)995 i915_vertex_flush(intel_screen_private *intel)
996 {
997 if (intel->prim_offset == 0)
998 return;
999
1000 intel->batch_ptr[intel->prim_offset] |= intel->vertex_count;
1001 intel->prim_offset = 0;
1002
1003 intel->vertex_index += intel->vertex_count;
1004 intel->vertex_count = 0;
1005 }
1006
1007 void
i915_batch_commit_notify(intel_screen_private * intel)1008 i915_batch_commit_notify(intel_screen_private *intel)
1009 {
1010 intel->needs_render_state_emit = TRUE;
1011 intel->last_floats_per_vertex = 0;
1012 }
1013