1 #include "xorg_composite.h"
3 #include "xorg_renderer.h"
4 #include "xorg_exa_tgsi.h"
6 #include "cso_cache/cso_context.h"
7 #include "util/u_sampler.h"
10 /*XXX also in Xrender.h but the including it here breaks compilition */
11 #define XFixedToDouble(f) (((double) (f)) / 65536.)
13 struct xorg_composite_blend
{
16 unsigned alpha_dst
: 4;
17 unsigned alpha_src
: 4;
19 unsigned rgb_src
: 8; /**< PIPE_BLENDFACTOR_x */
20 unsigned rgb_dst
: 8; /**< PIPE_BLENDFACTOR_x */
23 #define BLEND_OP_OVER 3
24 static const struct xorg_composite_blend xorg_blends
[] = {
26 0, 0, PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_ZERO
},
28 0, 0, PIPE_BLENDFACTOR_ONE
, PIPE_BLENDFACTOR_ZERO
},
30 0, 0, PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_ONE
},
32 0, 1, PIPE_BLENDFACTOR_ONE
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
34 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA
, PIPE_BLENDFACTOR_ONE
},
36 1, 0, PIPE_BLENDFACTOR_DST_ALPHA
, PIPE_BLENDFACTOR_ZERO
},
38 0, 1, PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_SRC_ALPHA
},
40 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA
, PIPE_BLENDFACTOR_ZERO
},
42 0, 1, PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
44 1, 1, PIPE_BLENDFACTOR_DST_ALPHA
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
46 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA
, PIPE_BLENDFACTOR_SRC_ALPHA
},
48 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
50 0, 0, PIPE_BLENDFACTOR_ONE
, PIPE_BLENDFACTOR_ONE
},
55 pixel_to_float4(Pixel pixel
, float *color
)
59 a
= (pixel
>> 24) & 0xff;
60 r
= (pixel
>> 16) & 0xff;
61 g
= (pixel
>> 8) & 0xff;
62 b
= (pixel
>> 0) & 0xff;
63 color
[0] = ((float)r
) / 255.;
64 color
[1] = ((float)g
) / 255.;
65 color
[2] = ((float)b
) / 255.;
66 color
[3] = ((float)a
) / 255.;
70 blend_for_op(struct xorg_composite_blend
*blend
,
71 int op
, PicturePtr pSrcPicture
, PicturePtr pMaskPicture
,
72 PicturePtr pDstPicture
)
74 const int num_blends
=
75 sizeof(xorg_blends
)/sizeof(struct xorg_composite_blend
);
77 boolean supported
= FALSE
;
79 /* our default in case something goes wrong */
80 *blend
= xorg_blends
[BLEND_OP_OVER
];
82 for (i
= 0; i
< num_blends
; ++i
) {
83 if (xorg_blends
[i
].op
== op
) {
84 *blend
= xorg_blends
[i
];
89 /* If there's no dst alpha channel, adjust the blend op so that we'll treat
92 PICT_FORMAT_A(pDstPicture
->format
) == 0 && blend
->alpha_dst
) {
93 if (blend
->rgb_src
== PIPE_BLENDFACTOR_DST_ALPHA
)
94 blend
->rgb_src
= PIPE_BLENDFACTOR_ONE
;
95 else if (blend
->rgb_src
== PIPE_BLENDFACTOR_INV_DST_ALPHA
)
96 blend
->rgb_src
= PIPE_BLENDFACTOR_ZERO
;
99 /* If the source alpha is being used, then we should only be in a case where
100 * the source blend factor is 0, and the source blend value is the mask
101 * channels multiplied by the source picture's alpha. */
102 if (pMaskPicture
&& pMaskPicture
->componentAlpha
&&
103 PICT_FORMAT_RGB(pMaskPicture
->format
) && blend
->alpha_src
) {
104 if (blend
->rgb_dst
== PIPE_BLENDFACTOR_SRC_ALPHA
) {
105 blend
->rgb_dst
= PIPE_BLENDFACTOR_SRC_COLOR
;
106 } else if (blend
->rgb_dst
== PIPE_BLENDFACTOR_INV_SRC_ALPHA
) {
107 blend
->rgb_dst
= PIPE_BLENDFACTOR_INV_SRC_COLOR
;
115 render_repeat_to_gallium(int mode
)
119 return PIPE_TEX_WRAP_CLAMP_TO_BORDER
;
121 return PIPE_TEX_WRAP_REPEAT
;
123 return PIPE_TEX_WRAP_MIRROR_REPEAT
;
125 return PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
127 debug_printf("Unsupported repeat mode\n");
129 return PIPE_TEX_WRAP_REPEAT
;
132 static INLINE boolean
133 render_filter_to_gallium(int xrender_filter
, int *out_filter
)
136 switch (xrender_filter
) {
137 case PictFilterNearest
:
138 *out_filter
= PIPE_TEX_FILTER_NEAREST
;
140 case PictFilterBilinear
:
141 *out_filter
= PIPE_TEX_FILTER_LINEAR
;
144 *out_filter
= PIPE_TEX_FILTER_NEAREST
;
147 *out_filter
= PIPE_TEX_FILTER_LINEAR
;
150 *out_filter
= PIPE_TEX_FILTER_LINEAR
;
152 case PictFilterConvolution
:
153 *out_filter
= PIPE_TEX_FILTER_NEAREST
;
156 debug_printf("Unknown xrender filter\n");
157 *out_filter
= PIPE_TEX_FILTER_NEAREST
;
164 static boolean
is_filter_accelerated(PicturePtr pic
)
167 if (pic
&& !render_filter_to_gallium(pic
->filter
, &filter
))
172 boolean
xorg_composite_accelerated(int op
,
173 PicturePtr pSrcPicture
,
174 PicturePtr pMaskPicture
,
175 PicturePtr pDstPicture
)
177 ScreenPtr pScreen
= pDstPicture
->pDrawable
->pScreen
;
178 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
179 modesettingPtr ms
= modesettingPTR(pScrn
);
180 struct xorg_composite_blend blend
;
182 if (!is_filter_accelerated(pSrcPicture
) ||
183 !is_filter_accelerated(pMaskPicture
)) {
184 XORG_FALLBACK("Unsupported Xrender filter");
187 if (pSrcPicture
->pSourcePict
) {
188 if (pSrcPicture
->pSourcePict
->type
!= SourcePictTypeSolidFill
)
189 XORG_FALLBACK("Gradients not enabled (haven't been well tested)");
192 if (blend_for_op(&blend
, op
,
193 pSrcPicture
, pMaskPicture
, pDstPicture
)) {
194 /* Check for component alpha */
195 if (pMaskPicture
&& pMaskPicture
->componentAlpha
&&
196 PICT_FORMAT_RGB(pMaskPicture
->format
)) {
197 if (blend
.alpha_src
&& blend
.rgb_src
!= PIPE_BLENDFACTOR_ZERO
) {
198 XORG_FALLBACK("Component alpha not supported with source "
199 "alpha and source value blending. (op=%d)",
206 XORG_FALLBACK("Unsupported composition operation = %d", op
);
210 bind_blend_state(struct exa_context
*exa
, int op
,
211 PicturePtr pSrcPicture
,
212 PicturePtr pMaskPicture
,
213 PicturePtr pDstPicture
)
215 struct xorg_composite_blend blend_opt
;
216 struct pipe_blend_state blend
;
218 blend_for_op(&blend_opt
, op
, pSrcPicture
, pMaskPicture
, pDstPicture
);
220 memset(&blend
, 0, sizeof(struct pipe_blend_state
));
221 blend
.rt
[0].blend_enable
= 1;
222 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
224 blend
.rt
[0].rgb_src_factor
= blend_opt
.rgb_src
;
225 blend
.rt
[0].alpha_src_factor
= blend_opt
.rgb_src
;
226 blend
.rt
[0].rgb_dst_factor
= blend_opt
.rgb_dst
;
227 blend
.rt
[0].alpha_dst_factor
= blend_opt
.rgb_dst
;
229 cso_set_blend(exa
->renderer
->cso
, &blend
);
233 picture_format_fixups(struct exa_pixmap_priv
*pSrc
, PicturePtr pSrcPicture
, boolean mask
,
234 PicturePtr pDstPicture
)
236 boolean set_alpha
= FALSE
;
237 boolean swizzle
= FALSE
;
240 if (pSrc
->picture_format
== pSrcPicture
->format
) {
241 if (pSrc
->picture_format
== PICT_a8
) {
243 return FS_MASK_LUMINANCE
;
244 else if (pDstPicture
->format
!= PICT_a8
) {
245 /* if both dst and src are luminance then
246 * we don't want to swizzle the alpha (X) of the
247 * source into W component of the dst because
248 * it will break our destination */
249 return FS_SRC_LUMINANCE
;
255 if (pSrc
->picture_format
!= PICT_a8r8g8b8
) {
256 assert(!"can not handle formats");
260 /* pSrc->picture_format == PICT_a8r8g8b8 */
261 switch (pSrcPicture
->format
) {
264 set_alpha
= TRUE
; /* fall trough */
270 set_alpha
= TRUE
; /* fall through */
273 #ifdef PICT_TYPE_BGRA
276 case PICT_a2r10g10b10
:
277 case PICT_x2r10g10b10
:
278 case PICT_a2b10g10r10
:
279 case PICT_x2b10g10r10
:
282 assert(!"can not handle formats");
287 ret
|= mask
? FS_MASK_SET_ALPHA
: FS_SRC_SET_ALPHA
;
289 ret
|= mask
? FS_MASK_SWIZZLE_RGB
: FS_SRC_SWIZZLE_RGB
;
295 bind_shaders(struct exa_context
*exa
, int op
,
296 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
, PicturePtr pDstPicture
,
297 struct exa_pixmap_priv
*pSrc
, struct exa_pixmap_priv
*pMask
)
299 unsigned vs_traits
= 0, fs_traits
= 0;
300 struct xorg_shader shader
;
302 exa
->has_solid_color
= FALSE
;
305 if (pSrcPicture
->repeatType
== RepeatNone
&& pSrcPicture
->transform
)
306 fs_traits
|= FS_SRC_REPEAT_NONE
;
308 if (pSrcPicture
->pSourcePict
) {
309 if (pSrcPicture
->pSourcePict
->type
== SourcePictTypeSolidFill
) {
310 fs_traits
|= FS_SOLID_FILL
;
311 vs_traits
|= VS_SOLID_FILL
;
312 debug_assert(pSrcPicture
->format
== PICT_a8r8g8b8
);
313 pixel_to_float4(pSrcPicture
->pSourcePict
->solidFill
.color
,
315 exa
->has_solid_color
= TRUE
;
317 debug_assert("!gradients not supported");
320 fs_traits
|= FS_COMPOSITE
;
321 vs_traits
|= VS_COMPOSITE
;
324 fs_traits
|= picture_format_fixups(pSrc
, pSrcPicture
, FALSE
, pDstPicture
);
328 vs_traits
|= VS_MASK
;
329 fs_traits
|= FS_MASK
;
330 if (pMaskPicture
->repeatType
== RepeatNone
&& pMaskPicture
->transform
)
331 fs_traits
|= FS_MASK_REPEAT_NONE
;
332 if (pMaskPicture
->componentAlpha
) {
333 struct xorg_composite_blend blend
;
334 blend_for_op(&blend
, op
,
335 pSrcPicture
, pMaskPicture
, NULL
);
336 if (blend
.alpha_src
) {
337 fs_traits
|= FS_CA_SRCALPHA
;
339 fs_traits
|= FS_CA_FULL
;
342 fs_traits
|= picture_format_fixups(pMask
, pMaskPicture
, TRUE
, pDstPicture
);
345 shader
= xorg_shaders_get(exa
->renderer
->shaders
, vs_traits
, fs_traits
);
346 cso_set_vertex_shader_handle(exa
->renderer
->cso
, shader
.vs
);
347 cso_set_fragment_shader_handle(exa
->renderer
->cso
, shader
.fs
);
351 bind_samplers(struct exa_context
*exa
, int op
,
352 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
,
353 PicturePtr pDstPicture
,
354 struct exa_pixmap_priv
*pSrc
,
355 struct exa_pixmap_priv
*pMask
,
356 struct exa_pixmap_priv
*pDst
)
358 struct pipe_sampler_state
*samplers
[PIPE_MAX_SAMPLERS
];
359 struct pipe_sampler_state src_sampler
, mask_sampler
;
360 struct pipe_sampler_view view_templ
;
361 struct pipe_sampler_view
*src_view
;
362 struct pipe_context
*pipe
= exa
->pipe
;
364 exa
->num_bound_samplers
= 0;
366 memset(&src_sampler
, 0, sizeof(struct pipe_sampler_state
));
367 memset(&mask_sampler
, 0, sizeof(struct pipe_sampler_state
));
369 if (pSrcPicture
&& pSrc
) {
370 if (exa
->has_solid_color
) {
371 debug_assert(!"solid color with textures");
373 pipe_sampler_view_reference(&exa
->bound_sampler_views
[0], NULL
);
375 unsigned src_wrap
= render_repeat_to_gallium(
376 pSrcPicture
->repeatType
);
379 render_filter_to_gallium(pSrcPicture
->filter
, &filter
);
381 src_sampler
.wrap_s
= src_wrap
;
382 src_sampler
.wrap_t
= src_wrap
;
383 src_sampler
.min_img_filter
= filter
;
384 src_sampler
.mag_img_filter
= filter
;
385 src_sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
386 src_sampler
.normalized_coords
= 1;
387 samplers
[0] = &src_sampler
;
388 exa
->num_bound_samplers
= 1;
389 u_sampler_view_default_template(&view_templ
,
392 src_view
= pipe
->create_sampler_view(pipe
, pSrc
->tex
, &view_templ
);
393 pipe_sampler_view_reference(&exa
->bound_sampler_views
[0], NULL
);
394 exa
->bound_sampler_views
[0] = src_view
;
398 if (pMaskPicture
&& pMask
) {
399 unsigned mask_wrap
= render_repeat_to_gallium(
400 pMaskPicture
->repeatType
);
403 render_filter_to_gallium(pMaskPicture
->filter
, &filter
);
405 mask_sampler
.wrap_s
= mask_wrap
;
406 mask_sampler
.wrap_t
= mask_wrap
;
407 mask_sampler
.min_img_filter
= filter
;
408 mask_sampler
.mag_img_filter
= filter
;
409 src_sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
410 mask_sampler
.normalized_coords
= 1;
411 samplers
[1] = &mask_sampler
;
412 exa
->num_bound_samplers
= 2;
413 u_sampler_view_default_template(&view_templ
,
416 src_view
= pipe
->create_sampler_view(pipe
, pMask
->tex
, &view_templ
);
417 pipe_sampler_view_reference(&exa
->bound_sampler_views
[1], NULL
);
418 exa
->bound_sampler_views
[1] = src_view
;
421 cso_set_samplers(exa
->renderer
->cso
, exa
->num_bound_samplers
,
422 (const struct pipe_sampler_state
**)samplers
);
423 cso_set_fragment_sampler_views(exa
->renderer
->cso
, exa
->num_bound_samplers
,
424 exa
->bound_sampler_views
);
429 static INLINE boolean
matrix_from_pict_transform(PictTransform
*trans
, float *matrix
)
434 matrix
[0] = XFixedToDouble(trans
->matrix
[0][0]);
435 matrix
[3] = XFixedToDouble(trans
->matrix
[0][1]);
436 matrix
[6] = XFixedToDouble(trans
->matrix
[0][2]);
438 matrix
[1] = XFixedToDouble(trans
->matrix
[1][0]);
439 matrix
[4] = XFixedToDouble(trans
->matrix
[1][1]);
440 matrix
[7] = XFixedToDouble(trans
->matrix
[1][2]);
442 matrix
[2] = XFixedToDouble(trans
->matrix
[2][0]);
443 matrix
[5] = XFixedToDouble(trans
->matrix
[2][1]);
444 matrix
[8] = XFixedToDouble(trans
->matrix
[2][2]);
450 setup_transforms(struct exa_context
*exa
,
451 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
453 PictTransform
*src_t
= NULL
;
454 PictTransform
*mask_t
= NULL
;
457 src_t
= pSrcPicture
->transform
;
459 mask_t
= pMaskPicture
->transform
;
461 exa
->transform
.has_src
=
462 matrix_from_pict_transform(src_t
, exa
->transform
.src
);
463 exa
->transform
.has_mask
=
464 matrix_from_pict_transform(mask_t
, exa
->transform
.mask
);
467 boolean
xorg_composite_bind_state(struct exa_context
*exa
,
469 PicturePtr pSrcPicture
,
470 PicturePtr pMaskPicture
,
471 PicturePtr pDstPicture
,
472 struct exa_pixmap_priv
*pSrc
,
473 struct exa_pixmap_priv
*pMask
,
474 struct exa_pixmap_priv
*pDst
)
476 struct pipe_surface
*dst_surf
= xorg_gpu_surface(exa
->scrn
, pDst
);
478 renderer_bind_destination(exa
->renderer
, dst_surf
,
482 bind_blend_state(exa
, op
, pSrcPicture
, pMaskPicture
, pDstPicture
);
483 bind_shaders(exa
, op
, pSrcPicture
, pMaskPicture
, pDstPicture
, pSrc
, pMask
);
484 bind_samplers(exa
, op
, pSrcPicture
, pMaskPicture
,
485 pDstPicture
, pSrc
, pMask
, pDst
);
487 setup_transforms(exa
, pSrcPicture
, pMaskPicture
);
489 if (exa
->num_bound_samplers
== 0 ) { /* solid fill */
490 renderer_begin_solid(exa
->renderer
);
492 renderer_begin_textures(exa
->renderer
,
493 exa
->num_bound_samplers
);
497 pipe_surface_reference(&dst_surf
, NULL
);
501 void xorg_composite(struct exa_context
*exa
,
502 struct exa_pixmap_priv
*dst
,
503 int srcX
, int srcY
, int maskX
, int maskY
,
504 int dstX
, int dstY
, int width
, int height
)
506 if (exa
->num_bound_samplers
== 0 ) { /* solid fill */
507 renderer_solid(exa
->renderer
,
508 dstX
, dstY
, dstX
+ width
, dstY
+ height
,
511 int pos
[6] = {srcX
, srcY
, maskX
, maskY
, dstX
, dstY
};
512 float *src_matrix
= NULL
;
513 float *mask_matrix
= NULL
;
515 if (exa
->transform
.has_src
)
516 src_matrix
= exa
->transform
.src
;
517 if (exa
->transform
.has_mask
)
518 mask_matrix
= exa
->transform
.mask
;
520 renderer_texture(exa
->renderer
,
522 exa
->bound_sampler_views
,
523 exa
->num_bound_samplers
,
524 src_matrix
, mask_matrix
);
528 boolean
xorg_solid_bind_state(struct exa_context
*exa
,
529 struct exa_pixmap_priv
*pixmap
,
532 struct pipe_surface
*dst_surf
= xorg_gpu_surface(exa
->scrn
, pixmap
);
533 unsigned vs_traits
, fs_traits
;
534 struct xorg_shader shader
;
536 pixel_to_float4(fg
, exa
->solid_color
);
537 exa
->has_solid_color
= TRUE
;
540 debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
541 (fg
>> 24) & 0xff, (fg
>> 16) & 0xff,
542 (fg
>> 8) & 0xff, (fg
>> 0) & 0xff,
543 exa
->solid_color
[0], exa
->solid_color
[1],
544 exa
->solid_color
[2], exa
->solid_color
[3]);
547 vs_traits
= VS_SOLID_FILL
;
548 fs_traits
= FS_SOLID_FILL
;
550 renderer_bind_destination(exa
->renderer
, dst_surf
,
551 pixmap
->width
, pixmap
->height
);
552 bind_blend_state(exa
, PictOpSrc
, NULL
, NULL
, NULL
);
553 cso_set_samplers(exa
->renderer
->cso
, 0, NULL
);
554 cso_set_fragment_sampler_views(exa
->renderer
->cso
, 0, NULL
);
556 shader
= xorg_shaders_get(exa
->renderer
->shaders
, vs_traits
, fs_traits
);
557 cso_set_vertex_shader_handle(exa
->renderer
->cso
, shader
.vs
);
558 cso_set_fragment_shader_handle(exa
->renderer
->cso
, shader
.fs
);
560 renderer_begin_solid(exa
->renderer
);
562 pipe_surface_reference(&dst_surf
, NULL
);
566 void xorg_solid(struct exa_context
*exa
,
567 struct exa_pixmap_priv
*pixmap
,
568 int x0
, int y0
, int x1
, int y1
)
570 renderer_solid(exa
->renderer
,
571 x0
, y0
, x1
, y1
, exa
->solid_color
);
575 xorg_composite_done(struct exa_context
*exa
)
577 renderer_draw_flush(exa
->renderer
);
579 exa
->transform
.has_src
= FALSE
;
580 exa
->transform
.has_mask
= FALSE
;
581 exa
->has_solid_color
= FALSE
;
582 exa
->num_bound_samplers
= 0;