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 rgb_src_factor
:5; /**< PIPE_BLENDFACTOR_x */
19 unsigned alpha_src_factor
:5; /**< PIPE_BLENDFACTOR_x */
21 unsigned rgb_dst_factor
:5; /**< PIPE_BLENDFACTOR_x */
22 unsigned alpha_dst_factor
:5; /**< PIPE_BLENDFACTOR_x */
25 #define BLEND_OP_OVER 3
26 static const struct xorg_composite_blend xorg_blends
[] = {
28 PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_ZERO
,
29 PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_ZERO
},
32 PIPE_BLENDFACTOR_ONE
, PIPE_BLENDFACTOR_ONE
,
33 PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_ZERO
},
36 PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_ZERO
,
37 PIPE_BLENDFACTOR_ONE
, PIPE_BLENDFACTOR_ONE
},
40 PIPE_BLENDFACTOR_SRC_ALPHA
, PIPE_BLENDFACTOR_ONE
,
41 PIPE_BLENDFACTOR_INV_SRC_ALPHA
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
44 PIPE_BLENDFACTOR_INV_DST_ALPHA
, PIPE_BLENDFACTOR_ONE
,
45 PIPE_BLENDFACTOR_ONE
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
48 PIPE_BLENDFACTOR_DST_ALPHA
, PIPE_BLENDFACTOR_ONE
,
49 PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
52 PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_ONE
,
53 PIPE_BLENDFACTOR_SRC_ALPHA
, PIPE_BLENDFACTOR_ONE
},
56 PIPE_BLENDFACTOR_INV_DST_ALPHA
, PIPE_BLENDFACTOR_ONE
,
57 PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
60 PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_ONE
,
61 PIPE_BLENDFACTOR_INV_SRC_ALPHA
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
64 PIPE_BLENDFACTOR_DST_ALPHA
, PIPE_BLENDFACTOR_ONE
,
65 PIPE_BLENDFACTOR_INV_SRC_ALPHA
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
68 PIPE_BLENDFACTOR_INV_DST_ALPHA
, PIPE_BLENDFACTOR_ONE
,
69 PIPE_BLENDFACTOR_SRC_ALPHA
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
72 PIPE_BLENDFACTOR_INV_DST_ALPHA
, PIPE_BLENDFACTOR_ONE
,
73 PIPE_BLENDFACTOR_INV_SRC_ALPHA
, PIPE_BLENDFACTOR_ONE
},
76 PIPE_BLENDFACTOR_ONE
, PIPE_BLENDFACTOR_ONE
,
77 PIPE_BLENDFACTOR_ONE
, PIPE_BLENDFACTOR_ONE
},
82 pixel_to_float4(Pixel pixel
, float *color
)
86 a
= (pixel
>> 24) & 0xff;
87 r
= (pixel
>> 16) & 0xff;
88 g
= (pixel
>> 8) & 0xff;
89 b
= (pixel
>> 0) & 0xff;
90 color
[0] = ((float)r
) / 255.;
91 color
[1] = ((float)g
) / 255.;
92 color
[2] = ((float)b
) / 255.;
93 color
[3] = ((float)a
) / 255.;
96 struct acceleration_info
{
99 int component_alpha
: 1;
101 static const struct acceleration_info accelerated_ops
[] = {
106 {PictOpOverReverse
, 1, 0},
108 {PictOpInReverse
, 1, 0},
110 {PictOpOutReverse
, 1, 0},
112 {PictOpAtopReverse
, 1, 0},
115 {PictOpSaturate
, 1, 0},
118 static struct xorg_composite_blend
121 const int num_blends
=
122 sizeof(xorg_blends
)/sizeof(struct xorg_composite_blend
);
125 for (i
= 0; i
< num_blends
; ++i
) {
126 if (xorg_blends
[i
].op
== op
)
127 return xorg_blends
[i
];
129 return xorg_blends
[BLEND_OP_OVER
];
133 render_repeat_to_gallium(int mode
)
137 return PIPE_TEX_WRAP_CLAMP
;
139 return PIPE_TEX_WRAP_REPEAT
;
141 return PIPE_TEX_WRAP_MIRROR_REPEAT
;
143 return PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
145 debug_printf("Unsupported repeat mode\n");
147 return PIPE_TEX_WRAP_REPEAT
;
150 static INLINE boolean
151 render_filter_to_gallium(int xrender_filter
, int *out_filter
)
154 switch (xrender_filter
) {
155 case PictFilterNearest
:
156 *out_filter
= PIPE_TEX_FILTER_NEAREST
;
158 case PictFilterBilinear
:
159 *out_filter
= PIPE_TEX_FILTER_LINEAR
;
162 *out_filter
= PIPE_TEX_FILTER_NEAREST
;
165 *out_filter
= PIPE_TEX_FILTER_LINEAR
;
168 *out_filter
= PIPE_TEX_FILTER_LINEAR
;
171 debug_printf("Unkown xrender filter");
172 *out_filter
= PIPE_TEX_FILTER_NEAREST
;
179 static boolean
is_filter_accelerated(PicturePtr pic
)
182 if (pic
&& !render_filter_to_gallium(pic
->filter
, &filter
))
187 boolean
xorg_composite_accelerated(int op
,
188 PicturePtr pSrcPicture
,
189 PicturePtr pMaskPicture
,
190 PicturePtr pDstPicture
)
192 ScreenPtr pScreen
= pDstPicture
->pDrawable
->pScreen
;
193 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
194 modesettingPtr ms
= modesettingPTR(pScrn
);
196 unsigned accel_ops_count
=
197 sizeof(accelerated_ops
)/sizeof(struct acceleration_info
);
199 if (!is_filter_accelerated(pSrcPicture
) ||
200 !is_filter_accelerated(pMaskPicture
)) {
201 XORG_FALLBACK("Unsupported Xrender filter");
204 if (pSrcPicture
->pSourcePict
) {
205 if (pSrcPicture
->pSourcePict
->type
!= SourcePictTypeSolidFill
)
206 XORG_FALLBACK("gradients not enabled (haven't been well tested)");
209 for (i
= 0; i
< accel_ops_count
; ++i
) {
210 if (op
== accelerated_ops
[i
].op
) {
211 /* Check for component alpha */
213 (pMaskPicture
->componentAlpha
||
214 (!accelerated_ops
[i
].with_mask
)))
215 XORG_FALLBACK("component alpha unsupported (PictOpOver=%s(%d)",
216 (accelerated_ops
[i
].op
== PictOpOver
) ? "yes" : "no",
217 accelerated_ops
[i
].op
);
221 XORG_FALLBACK("unsupported operation");
225 bind_blend_state(struct exa_context
*exa
, int op
,
226 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
228 struct xorg_composite_blend blend_opt
;
229 struct pipe_blend_state blend
;
231 blend_opt
= blend_for_op(op
);
233 memset(&blend
, 0, sizeof(struct pipe_blend_state
));
234 blend
.blend_enable
= 1;
235 blend
.colormask
|= PIPE_MASK_RGBA
;
237 blend
.rgb_src_factor
= blend_opt
.rgb_src_factor
;
238 blend
.alpha_src_factor
= blend_opt
.alpha_src_factor
;
239 blend
.rgb_dst_factor
= blend_opt
.rgb_dst_factor
;
240 blend
.alpha_dst_factor
= blend_opt
.alpha_dst_factor
;
242 cso_set_blend(exa
->renderer
->cso
, &blend
);
247 bind_shaders(struct exa_context
*exa
, int op
,
248 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
250 unsigned vs_traits
= 0, fs_traits
= 0;
251 struct xorg_shader shader
;
253 exa
->has_solid_color
= FALSE
;
256 if (pSrcPicture
->pSourcePict
) {
257 if (pSrcPicture
->pSourcePict
->type
== SourcePictTypeSolidFill
) {
258 fs_traits
|= FS_SOLID_FILL
;
259 vs_traits
|= VS_SOLID_FILL
;
260 debug_assert(pSrcPicture
->format
== PICT_a8r8g8b8
);
261 pixel_to_float4(pSrcPicture
->pSourcePict
->solidFill
.color
,
263 exa
->has_solid_color
= TRUE
;
265 debug_assert("!gradients not supported");
268 fs_traits
|= FS_COMPOSITE
;
269 vs_traits
|= VS_COMPOSITE
;
274 vs_traits
|= VS_MASK
;
275 fs_traits
|= FS_MASK
;
278 shader
= xorg_shaders_get(exa
->renderer
->shaders
, vs_traits
, fs_traits
);
279 cso_set_vertex_shader_handle(exa
->renderer
->cso
, shader
.vs
);
280 cso_set_fragment_shader_handle(exa
->renderer
->cso
, shader
.fs
);
284 bind_samplers(struct exa_context
*exa
, int op
,
285 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
,
286 PicturePtr pDstPicture
,
287 struct exa_pixmap_priv
*pSrc
,
288 struct exa_pixmap_priv
*pMask
,
289 struct exa_pixmap_priv
*pDst
)
291 struct pipe_sampler_state
*samplers
[PIPE_MAX_SAMPLERS
];
292 struct pipe_sampler_state src_sampler
, mask_sampler
;
294 exa
->num_bound_samplers
= 0;
296 memset(&src_sampler
, 0, sizeof(struct pipe_sampler_state
));
297 memset(&mask_sampler
, 0, sizeof(struct pipe_sampler_state
));
299 if ((pSrc
&& exa
->pipe
->is_texture_referenced(exa
->pipe
, pSrc
->tex
, 0, 0) &
300 PIPE_REFERENCED_FOR_WRITE
) ||
301 (pMask
&& exa
->pipe
->is_texture_referenced(exa
->pipe
, pMask
->tex
, 0, 0) &
302 PIPE_REFERENCED_FOR_WRITE
))
303 exa
->pipe
->flush(exa
->pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
305 if (pSrcPicture
&& pSrc
) {
306 unsigned src_wrap
= render_repeat_to_gallium(
307 pSrcPicture
->repeatType
);
310 render_filter_to_gallium(pSrcPicture
->filter
, &filter
);
312 src_sampler
.wrap_s
= src_wrap
;
313 src_sampler
.wrap_t
= src_wrap
;
314 src_sampler
.min_img_filter
= filter
;
315 src_sampler
.mag_img_filter
= filter
;
316 src_sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
317 src_sampler
.normalized_coords
= 1;
318 samplers
[0] = &src_sampler
;
319 exa
->bound_textures
[0] = pSrc
->tex
;
320 ++exa
->num_bound_samplers
;
323 if (pMaskPicture
&& pMask
) {
324 unsigned mask_wrap
= render_repeat_to_gallium(
325 pMaskPicture
->repeatType
);
328 render_filter_to_gallium(pMaskPicture
->filter
, &filter
);
330 mask_sampler
.wrap_s
= mask_wrap
;
331 mask_sampler
.wrap_t
= mask_wrap
;
332 mask_sampler
.min_img_filter
= filter
;
333 mask_sampler
.mag_img_filter
= filter
;
334 src_sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
335 mask_sampler
.normalized_coords
= 1;
336 samplers
[1] = &mask_sampler
;
337 exa
->bound_textures
[1] = pMask
->tex
;
338 ++exa
->num_bound_samplers
;
341 cso_set_samplers(exa
->renderer
->cso
, exa
->num_bound_samplers
,
342 (const struct pipe_sampler_state
**)samplers
);
343 cso_set_sampler_textures(exa
->renderer
->cso
, exa
->num_bound_samplers
,
344 exa
->bound_textures
);
348 setup_vs_constant_buffer(struct exa_context
*exa
,
349 int width
, int height
)
351 const int param_bytes
= 8 * sizeof(float);
352 float vs_consts
[8] = {
353 2.f
/width
, 2.f
/height
, 1, 1,
356 renderer_set_constants(exa
->renderer
, PIPE_SHADER_VERTEX
,
357 vs_consts
, param_bytes
);
362 setup_fs_constant_buffer(struct exa_context
*exa
)
364 const int param_bytes
= 4 * sizeof(float);
365 const float fs_consts
[8] = {
368 renderer_set_constants(exa
->renderer
, PIPE_SHADER_FRAGMENT
,
369 fs_consts
, param_bytes
);
373 setup_constant_buffers(struct exa_context
*exa
, struct exa_pixmap_priv
*pDst
)
375 int width
= pDst
->tex
->width
[0];
376 int height
= pDst
->tex
->height
[0];
378 setup_vs_constant_buffer(exa
, width
, height
);
379 setup_fs_constant_buffer(exa
);
382 static INLINE boolean
matrix_from_pict_transform(PictTransform
*trans
, float *matrix
)
387 matrix
[0] = XFixedToDouble(trans
->matrix
[0][0]);
388 matrix
[1] = XFixedToDouble(trans
->matrix
[0][1]);
389 matrix
[2] = XFixedToDouble(trans
->matrix
[0][2]);
391 matrix
[3] = XFixedToDouble(trans
->matrix
[1][0]);
392 matrix
[4] = XFixedToDouble(trans
->matrix
[1][1]);
393 matrix
[5] = XFixedToDouble(trans
->matrix
[1][2]);
395 matrix
[6] = XFixedToDouble(trans
->matrix
[2][0]);
396 matrix
[7] = XFixedToDouble(trans
->matrix
[2][1]);
397 matrix
[8] = XFixedToDouble(trans
->matrix
[2][2]);
403 setup_transforms(struct exa_context
*exa
,
404 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
406 PictTransform
*src_t
= NULL
;
407 PictTransform
*mask_t
= NULL
;
410 src_t
= pSrcPicture
->transform
;
412 mask_t
= pMaskPicture
->transform
;
414 exa
->transform
.has_src
=
415 matrix_from_pict_transform(src_t
, exa
->transform
.src
);
416 exa
->transform
.has_mask
=
417 matrix_from_pict_transform(mask_t
, exa
->transform
.mask
);
420 boolean
xorg_composite_bind_state(struct exa_context
*exa
,
422 PicturePtr pSrcPicture
,
423 PicturePtr pMaskPicture
,
424 PicturePtr pDstPicture
,
425 struct exa_pixmap_priv
*pSrc
,
426 struct exa_pixmap_priv
*pMask
,
427 struct exa_pixmap_priv
*pDst
)
429 renderer_bind_framebuffer(exa
->renderer
, pDst
);
430 renderer_bind_viewport(exa
->renderer
, pDst
);
431 bind_blend_state(exa
, op
, pSrcPicture
, pMaskPicture
);
432 renderer_bind_rasterizer(exa
->renderer
);
433 bind_shaders(exa
, op
, pSrcPicture
, pMaskPicture
);
434 bind_samplers(exa
, op
, pSrcPicture
, pMaskPicture
,
435 pDstPicture
, pSrc
, pMask
, pDst
);
436 setup_constant_buffers(exa
, pDst
);
438 setup_transforms(exa
, pSrcPicture
, pMaskPicture
);
443 void xorg_composite(struct exa_context
*exa
,
444 struct exa_pixmap_priv
*dst
,
445 int srcX
, int srcY
, int maskX
, int maskY
,
446 int dstX
, int dstY
, int width
, int height
)
448 if (exa
->num_bound_samplers
== 0 ) { /* solid fill */
449 renderer_draw_solid_rect(exa
->renderer
,
450 dstX
, dstY
, dstX
+ width
, dstY
+ height
,
453 int pos
[6] = {srcX
, srcY
, maskX
, maskY
, dstX
, dstY
};
454 float *src_matrix
= NULL
;
455 float *mask_matrix
= NULL
;
457 if (exa
->transform
.has_src
)
458 src_matrix
= exa
->transform
.src
;
459 if (exa
->transform
.has_mask
)
460 mask_matrix
= exa
->transform
.mask
;
462 renderer_draw_textures(exa
->renderer
,
465 exa
->num_bound_samplers
,
466 src_matrix
, mask_matrix
);
470 boolean
xorg_solid_bind_state(struct exa_context
*exa
,
471 struct exa_pixmap_priv
*pixmap
,
474 unsigned vs_traits
, fs_traits
;
475 struct xorg_shader shader
;
477 pixel_to_float4(fg
, exa
->solid_color
);
478 exa
->has_solid_color
= TRUE
;
481 debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
482 (fg
>> 24) & 0xff, (fg
>> 16) & 0xff,
483 (fg
>> 8) & 0xff, (fg
>> 0) & 0xff,
484 exa
->solid_color
[0], exa
->solid_color
[1],
485 exa
->solid_color
[2], exa
->solid_color
[3]);
488 vs_traits
= VS_SOLID_FILL
;
489 fs_traits
= FS_SOLID_FILL
;
491 renderer_bind_framebuffer(exa
->renderer
, pixmap
);
492 renderer_bind_viewport(exa
->renderer
, pixmap
);
493 renderer_bind_rasterizer(exa
->renderer
);
494 bind_blend_state(exa
, PictOpSrc
, NULL
, NULL
);
495 setup_constant_buffers(exa
, pixmap
);
497 shader
= xorg_shaders_get(exa
->renderer
->shaders
, vs_traits
, fs_traits
);
498 cso_set_vertex_shader_handle(exa
->renderer
->cso
, shader
.vs
);
499 cso_set_fragment_shader_handle(exa
->renderer
->cso
, shader
.fs
);
504 void xorg_solid(struct exa_context
*exa
,
505 struct exa_pixmap_priv
*pixmap
,
506 int x0
, int y0
, int x1
, int y1
)
508 renderer_draw_solid_rect(exa
->renderer
,
509 x0
, y0
, x1
, y1
, exa
->solid_color
);