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_draw_quad.h"
8 #include "util/u_math.h"
10 #include "pipe/p_inlines.h"
12 /*XXX also in Xrender.h but the including it here breaks compilition */
13 #define XFixedToDouble(f) (((double) (f)) / 65536.)
15 struct xorg_composite_blend
{
18 unsigned alpha_dst
: 4;
19 unsigned alpha_src
: 4;
21 unsigned rgb_src
: 8; /**< PIPE_BLENDFACTOR_x */
22 unsigned rgb_dst
: 8; /**< PIPE_BLENDFACTOR_x */
25 #define BLEND_OP_OVER 3
26 static const struct xorg_composite_blend xorg_blends
[] = {
28 0, 0, PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_ZERO
},
30 0, 0, PIPE_BLENDFACTOR_ONE
, PIPE_BLENDFACTOR_ZERO
},
32 0, 0, PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_ONE
},
34 0, 1, PIPE_BLENDFACTOR_ONE
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
36 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA
, PIPE_BLENDFACTOR_ONE
},
38 1, 0, PIPE_BLENDFACTOR_DST_ALPHA
, PIPE_BLENDFACTOR_ZERO
},
40 0, 1, PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_SRC_ALPHA
},
42 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA
, PIPE_BLENDFACTOR_ZERO
},
44 0, 1, PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
46 1, 1, PIPE_BLENDFACTOR_DST_ALPHA
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
48 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA
, PIPE_BLENDFACTOR_SRC_ALPHA
},
50 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
52 0, 0, PIPE_BLENDFACTOR_ONE
, PIPE_BLENDFACTOR_ONE
},
57 pixel_to_float4(Pixel pixel
, float *color
)
61 a
= (pixel
>> 24) & 0xff;
62 r
= (pixel
>> 16) & 0xff;
63 g
= (pixel
>> 8) & 0xff;
64 b
= (pixel
>> 0) & 0xff;
65 color
[0] = ((float)r
) / 255.;
66 color
[1] = ((float)g
) / 255.;
67 color
[2] = ((float)b
) / 255.;
68 color
[3] = ((float)a
) / 255.;
71 struct acceleration_info
{
74 static const struct acceleration_info accelerated_ops
[] = {
79 {PictOpOverReverse
, },
85 {PictOpAtopReverse
, },
91 static struct xorg_composite_blend
92 blend_for_op(int op
, PicturePtr pSrcPicture
, PicturePtr pMaskPicture
,
93 PicturePtr pDstPicture
)
95 const int num_blends
=
96 sizeof(xorg_blends
)/sizeof(struct xorg_composite_blend
);
98 struct xorg_composite_blend blend
= xorg_blends
[BLEND_OP_OVER
];
100 for (i
= 0; i
< num_blends
; ++i
) {
101 if (xorg_blends
[i
].op
== op
)
102 blend
= xorg_blends
[i
];
105 /* If there's no dst alpha channel, adjust the blend op so that we'll treat
109 PICT_FORMAT_A(pDstPicture
->format
) == 0 && blend
.alpha_dst
) {
110 if (blend
.rgb_src
== PIPE_BLENDFACTOR_DST_ALPHA
)
111 blend
.rgb_src
= PIPE_BLENDFACTOR_ONE
;
112 else if (blend
.rgb_src
== PIPE_BLENDFACTOR_INV_DST_ALPHA
)
113 blend
.rgb_src
= PIPE_BLENDFACTOR_ZERO
;
116 /* If the source alpha is being used, then we should only be in a case where
117 * the source blend factor is 0, and the source blend value is the mask
118 * channels multiplied by the source picture's alpha.
120 if (pMaskPicture
&& pMaskPicture
->componentAlpha
&&
121 PICT_FORMAT_RGB(pMaskPicture
->format
) && blend
.alpha_src
) {
122 if (blend
.rgb_dst
== PIPE_BLENDFACTOR_SRC_ALPHA
) {
123 blend
.rgb_dst
= PIPE_BLENDFACTOR_SRC_COLOR
;
124 } else if (blend
.rgb_dst
== PIPE_BLENDFACTOR_INV_SRC_ALPHA
) {
125 blend
.rgb_dst
= PIPE_BLENDFACTOR_INV_SRC_COLOR
;
132 render_repeat_to_gallium(int mode
)
136 return PIPE_TEX_WRAP_CLAMP
;
138 return PIPE_TEX_WRAP_REPEAT
;
140 return PIPE_TEX_WRAP_MIRROR_REPEAT
;
142 return PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
144 debug_printf("Unsupported repeat mode\n");
146 return PIPE_TEX_WRAP_REPEAT
;
149 static INLINE boolean
150 render_filter_to_gallium(int xrender_filter
, int *out_filter
)
153 switch (xrender_filter
) {
154 case PictFilterNearest
:
155 *out_filter
= PIPE_TEX_FILTER_NEAREST
;
157 case PictFilterBilinear
:
158 *out_filter
= PIPE_TEX_FILTER_LINEAR
;
161 *out_filter
= PIPE_TEX_FILTER_NEAREST
;
164 *out_filter
= PIPE_TEX_FILTER_LINEAR
;
167 *out_filter
= PIPE_TEX_FILTER_LINEAR
;
170 debug_printf("Unkown xrender filter");
171 *out_filter
= PIPE_TEX_FILTER_NEAREST
;
178 static boolean
is_filter_accelerated(PicturePtr pic
)
181 if (pic
&& !render_filter_to_gallium(pic
->filter
, &filter
))
186 boolean
xorg_composite_accelerated(int op
,
187 PicturePtr pSrcPicture
,
188 PicturePtr pMaskPicture
,
189 PicturePtr pDstPicture
)
191 ScreenPtr pScreen
= pDstPicture
->pDrawable
->pScreen
;
192 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
193 modesettingPtr ms
= modesettingPTR(pScrn
);
195 unsigned accel_ops_count
=
196 sizeof(accelerated_ops
)/sizeof(struct acceleration_info
);
198 if (!is_filter_accelerated(pSrcPicture
) ||
199 !is_filter_accelerated(pMaskPicture
)) {
200 XORG_FALLBACK("Unsupported Xrender filter");
203 if (pSrcPicture
->pSourcePict
) {
204 if (pSrcPicture
->pSourcePict
->type
!= SourcePictTypeSolidFill
)
205 XORG_FALLBACK("Gradients not enabled (haven't been well tested)");
208 for (i
= 0; i
< accel_ops_count
; ++i
) {
209 if (op
== accelerated_ops
[i
].op
) {
210 struct xorg_composite_blend blend
= blend_for_op(op
,
214 /* Check for component alpha */
215 if (pMaskPicture
&& pMaskPicture
->componentAlpha
&&
216 PICT_FORMAT_RGB(pMaskPicture
->format
)) {
217 if (blend
.alpha_src
&&
218 blend
.rgb_src
!= PIPE_BLENDFACTOR_ZERO
) {
219 XORG_FALLBACK("Component alpha not supported with source "
220 "alpha and source value blending. (op=%d)",
227 XORG_FALLBACK("Unsupported composition operation = %d", op
);
231 bind_blend_state(struct exa_context
*exa
, int op
,
232 PicturePtr pSrcPicture
,
233 PicturePtr pMaskPicture
,
234 PicturePtr pDstPicture
)
236 struct xorg_composite_blend blend_opt
;
237 struct pipe_blend_state blend
;
239 blend_opt
= blend_for_op(op
, pSrcPicture
, pMaskPicture
, pDstPicture
);
241 memset(&blend
, 0, sizeof(struct pipe_blend_state
));
242 blend
.blend_enable
= 1;
243 blend
.colormask
|= PIPE_MASK_RGBA
;
245 blend
.rgb_src_factor
= blend_opt
.rgb_src
;
246 blend
.alpha_src_factor
= blend_opt
.rgb_src
;
247 blend
.rgb_dst_factor
= blend_opt
.rgb_dst
;
248 blend
.alpha_dst_factor
= blend_opt
.rgb_dst
;
250 cso_set_blend(exa
->renderer
->cso
, &blend
);
255 bind_shaders(struct exa_context
*exa
, int op
,
256 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
258 unsigned vs_traits
= 0, fs_traits
= 0;
259 struct xorg_shader shader
;
261 exa
->has_solid_color
= FALSE
;
264 if (pSrcPicture
->pSourcePict
) {
265 if (pSrcPicture
->pSourcePict
->type
== SourcePictTypeSolidFill
) {
266 fs_traits
|= FS_SOLID_FILL
;
267 vs_traits
|= VS_SOLID_FILL
;
268 debug_assert(pSrcPicture
->format
== PICT_a8r8g8b8
);
269 pixel_to_float4(pSrcPicture
->pSourcePict
->solidFill
.color
,
271 exa
->has_solid_color
= TRUE
;
273 debug_assert("!gradients not supported");
276 fs_traits
|= FS_COMPOSITE
;
277 vs_traits
|= VS_COMPOSITE
;
282 vs_traits
|= VS_MASK
;
283 fs_traits
|= FS_MASK
;
284 if (pMaskPicture
->componentAlpha
)
285 fs_traits
|= FS_COMPONENT_ALPHA
;
288 shader
= xorg_shaders_get(exa
->renderer
->shaders
, vs_traits
, fs_traits
);
289 cso_set_vertex_shader_handle(exa
->renderer
->cso
, shader
.vs
);
290 cso_set_fragment_shader_handle(exa
->renderer
->cso
, shader
.fs
);
294 bind_samplers(struct exa_context
*exa
, int op
,
295 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
,
296 PicturePtr pDstPicture
,
297 struct exa_pixmap_priv
*pSrc
,
298 struct exa_pixmap_priv
*pMask
,
299 struct exa_pixmap_priv
*pDst
)
301 struct pipe_sampler_state
*samplers
[PIPE_MAX_SAMPLERS
];
302 struct pipe_sampler_state src_sampler
, mask_sampler
;
304 exa
->num_bound_samplers
= 0;
306 memset(&src_sampler
, 0, sizeof(struct pipe_sampler_state
));
307 memset(&mask_sampler
, 0, sizeof(struct pipe_sampler_state
));
309 if ((pSrc
&& exa
->pipe
->is_texture_referenced(exa
->pipe
, pSrc
->tex
, 0, 0) &
310 PIPE_REFERENCED_FOR_WRITE
) ||
311 (pMask
&& exa
->pipe
->is_texture_referenced(exa
->pipe
, pMask
->tex
, 0, 0) &
312 PIPE_REFERENCED_FOR_WRITE
))
313 exa
->pipe
->flush(exa
->pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
315 if (pSrcPicture
&& pSrc
) {
316 unsigned src_wrap
= render_repeat_to_gallium(
317 pSrcPicture
->repeatType
);
320 render_filter_to_gallium(pSrcPicture
->filter
, &filter
);
322 src_sampler
.wrap_s
= src_wrap
;
323 src_sampler
.wrap_t
= src_wrap
;
324 src_sampler
.min_img_filter
= filter
;
325 src_sampler
.mag_img_filter
= filter
;
326 src_sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
327 src_sampler
.normalized_coords
= 1;
328 samplers
[0] = &src_sampler
;
329 exa
->bound_textures
[0] = pSrc
->tex
;
330 ++exa
->num_bound_samplers
;
333 if (pMaskPicture
&& pMask
) {
334 unsigned mask_wrap
= render_repeat_to_gallium(
335 pMaskPicture
->repeatType
);
338 render_filter_to_gallium(pMaskPicture
->filter
, &filter
);
340 mask_sampler
.wrap_s
= mask_wrap
;
341 mask_sampler
.wrap_t
= mask_wrap
;
342 mask_sampler
.min_img_filter
= filter
;
343 mask_sampler
.mag_img_filter
= filter
;
344 src_sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
345 mask_sampler
.normalized_coords
= 1;
346 samplers
[1] = &mask_sampler
;
347 exa
->bound_textures
[1] = pMask
->tex
;
348 ++exa
->num_bound_samplers
;
351 cso_set_samplers(exa
->renderer
->cso
, exa
->num_bound_samplers
,
352 (const struct pipe_sampler_state
**)samplers
);
353 cso_set_sampler_textures(exa
->renderer
->cso
, exa
->num_bound_samplers
,
354 exa
->bound_textures
);
358 setup_vs_constant_buffer(struct exa_context
*exa
,
359 int width
, int height
)
361 const int param_bytes
= 8 * sizeof(float);
362 float vs_consts
[8] = {
363 2.f
/width
, 2.f
/height
, 1, 1,
366 renderer_set_constants(exa
->renderer
, PIPE_SHADER_VERTEX
,
367 vs_consts
, param_bytes
);
372 setup_fs_constant_buffer(struct exa_context
*exa
)
374 const int param_bytes
= 4 * sizeof(float);
375 const float fs_consts
[8] = {
378 renderer_set_constants(exa
->renderer
, PIPE_SHADER_FRAGMENT
,
379 fs_consts
, param_bytes
);
383 setup_constant_buffers(struct exa_context
*exa
, struct exa_pixmap_priv
*pDst
)
385 int width
= pDst
->tex
->width
[0];
386 int height
= pDst
->tex
->height
[0];
388 setup_vs_constant_buffer(exa
, width
, height
);
389 setup_fs_constant_buffer(exa
);
392 static INLINE boolean
matrix_from_pict_transform(PictTransform
*trans
, float *matrix
)
397 matrix
[0] = XFixedToDouble(trans
->matrix
[0][0]);
398 matrix
[1] = XFixedToDouble(trans
->matrix
[0][1]);
399 matrix
[2] = XFixedToDouble(trans
->matrix
[0][2]);
401 matrix
[3] = XFixedToDouble(trans
->matrix
[1][0]);
402 matrix
[4] = XFixedToDouble(trans
->matrix
[1][1]);
403 matrix
[5] = XFixedToDouble(trans
->matrix
[1][2]);
405 matrix
[6] = XFixedToDouble(trans
->matrix
[2][0]);
406 matrix
[7] = XFixedToDouble(trans
->matrix
[2][1]);
407 matrix
[8] = XFixedToDouble(trans
->matrix
[2][2]);
413 setup_transforms(struct exa_context
*exa
,
414 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
416 PictTransform
*src_t
= NULL
;
417 PictTransform
*mask_t
= NULL
;
420 src_t
= pSrcPicture
->transform
;
422 mask_t
= pMaskPicture
->transform
;
424 exa
->transform
.has_src
=
425 matrix_from_pict_transform(src_t
, exa
->transform
.src
);
426 exa
->transform
.has_mask
=
427 matrix_from_pict_transform(mask_t
, exa
->transform
.mask
);
430 boolean
xorg_composite_bind_state(struct exa_context
*exa
,
432 PicturePtr pSrcPicture
,
433 PicturePtr pMaskPicture
,
434 PicturePtr pDstPicture
,
435 struct exa_pixmap_priv
*pSrc
,
436 struct exa_pixmap_priv
*pMask
,
437 struct exa_pixmap_priv
*pDst
)
439 renderer_bind_framebuffer(exa
->renderer
, pDst
);
440 renderer_bind_viewport(exa
->renderer
, pDst
);
441 bind_blend_state(exa
, op
, pSrcPicture
, pMaskPicture
, pDstPicture
);
442 renderer_bind_rasterizer(exa
->renderer
);
443 bind_shaders(exa
, op
, pSrcPicture
, pMaskPicture
);
444 bind_samplers(exa
, op
, pSrcPicture
, pMaskPicture
,
445 pDstPicture
, pSrc
, pMask
, pDst
);
446 setup_constant_buffers(exa
, pDst
);
448 setup_transforms(exa
, pSrcPicture
, pMaskPicture
);
453 void xorg_composite(struct exa_context
*exa
,
454 struct exa_pixmap_priv
*dst
,
455 int srcX
, int srcY
, int maskX
, int maskY
,
456 int dstX
, int dstY
, int width
, int height
)
458 if (exa
->num_bound_samplers
== 0 ) { /* solid fill */
459 renderer_draw_solid_rect(exa
->renderer
,
460 dstX
, dstY
, dstX
+ width
, dstY
+ height
,
463 int pos
[6] = {srcX
, srcY
, maskX
, maskY
, dstX
, dstY
};
464 float *src_matrix
= NULL
;
465 float *mask_matrix
= NULL
;
467 if (exa
->transform
.has_src
)
468 src_matrix
= exa
->transform
.src
;
469 if (exa
->transform
.has_mask
)
470 mask_matrix
= exa
->transform
.mask
;
472 renderer_draw_textures(exa
->renderer
,
475 exa
->num_bound_samplers
,
476 src_matrix
, mask_matrix
);
480 boolean
xorg_solid_bind_state(struct exa_context
*exa
,
481 struct exa_pixmap_priv
*pixmap
,
484 unsigned vs_traits
, fs_traits
;
485 struct xorg_shader shader
;
487 pixel_to_float4(fg
, exa
->solid_color
);
488 exa
->has_solid_color
= TRUE
;
491 debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
492 (fg
>> 24) & 0xff, (fg
>> 16) & 0xff,
493 (fg
>> 8) & 0xff, (fg
>> 0) & 0xff,
494 exa
->solid_color
[0], exa
->solid_color
[1],
495 exa
->solid_color
[2], exa
->solid_color
[3]);
498 vs_traits
= VS_SOLID_FILL
;
499 fs_traits
= FS_SOLID_FILL
;
501 renderer_bind_framebuffer(exa
->renderer
, pixmap
);
502 renderer_bind_viewport(exa
->renderer
, pixmap
);
503 renderer_bind_rasterizer(exa
->renderer
);
504 bind_blend_state(exa
, PictOpSrc
, NULL
, NULL
, NULL
);
505 setup_constant_buffers(exa
, pixmap
);
507 shader
= xorg_shaders_get(exa
->renderer
->shaders
, vs_traits
, fs_traits
);
508 cso_set_vertex_shader_handle(exa
->renderer
->cso
, shader
.vs
);
509 cso_set_fragment_shader_handle(exa
->renderer
->cso
, shader
.fs
);
514 void xorg_solid(struct exa_context
*exa
,
515 struct exa_pixmap_priv
*pixmap
,
516 int x0
, int y0
, int x1
, int y1
)
518 renderer_draw_solid_rect(exa
->renderer
,
519 x0
, y0
, x1
, y1
, exa
->solid_color
);