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 struct xorg_composite_blend
{
15 unsigned rgb_src_factor
:5; /**< PIPE_BLENDFACTOR_x */
16 unsigned alpha_src_factor
:5; /**< PIPE_BLENDFACTOR_x */
18 unsigned rgb_dst_factor
:5; /**< PIPE_BLENDFACTOR_x */
19 unsigned alpha_dst_factor
:5; /**< PIPE_BLENDFACTOR_x */
22 #define BLEND_OP_OVER 3
23 static const struct xorg_composite_blend xorg_blends
[] = {
25 PIPE_BLENDFACTOR_CONST_COLOR
, PIPE_BLENDFACTOR_CONST_ALPHA
,
26 PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_ZERO
},
29 PIPE_BLENDFACTOR_ONE
, PIPE_BLENDFACTOR_ONE
,
30 PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_ZERO
},
33 PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_ZERO
,
34 PIPE_BLENDFACTOR_ONE
, PIPE_BLENDFACTOR_ONE
},
37 PIPE_BLENDFACTOR_SRC_ALPHA
, PIPE_BLENDFACTOR_ONE
,
38 PIPE_BLENDFACTOR_INV_SRC_ALPHA
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
41 PIPE_BLENDFACTOR_SRC_ALPHA
, PIPE_BLENDFACTOR_ONE
,
42 PIPE_BLENDFACTOR_INV_SRC_ALPHA
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
47 pixel_to_float4(Pixel pixel
, float *color
)
51 a
= (pixel
>> 24) & 0xff;
52 r
= (pixel
>> 16) & 0xff;
53 g
= (pixel
>> 8) & 0xff;
54 b
= (pixel
>> 0) & 0xff;
55 color
[0] = ((float)r
) / 255.;
56 color
[1] = ((float)g
) / 255.;
57 color
[2] = ((float)b
) / 255.;
58 color
[3] = ((float)a
) / 255.;
61 struct acceleration_info
{
64 int component_alpha
: 1;
66 static const struct acceleration_info accelerated_ops
[] = {
71 {PictOpOverReverse
, 1, 0},
73 {PictOpInReverse
, 1, 0},
75 {PictOpOutReverse
, 1, 0},
77 {PictOpAtopReverse
, 1, 0},
80 {PictOpSaturate
, 1, 0},
83 static struct xorg_composite_blend
86 const int num_blends
=
87 sizeof(xorg_blends
)/sizeof(struct xorg_composite_blend
);
90 for (i
= 0; i
< num_blends
; ++i
) {
91 if (xorg_blends
[i
].op
== op
)
92 return xorg_blends
[i
];
94 return xorg_blends
[BLEND_OP_OVER
];
98 render_repeat_to_gallium(int mode
)
102 return PIPE_TEX_WRAP_CLAMP
;
104 return PIPE_TEX_WRAP_REPEAT
;
106 return PIPE_TEX_WRAP_MIRROR_REPEAT
;
108 return PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
110 debug_printf("Unsupported repeat mode\n");
112 return PIPE_TEX_WRAP_REPEAT
;
115 boolean
xorg_composite_accelerated(int op
,
116 PicturePtr pSrcPicture
,
117 PicturePtr pMaskPicture
,
118 PicturePtr pDstPicture
)
120 ScreenPtr pScreen
= pDstPicture
->pDrawable
->pScreen
;
121 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
122 modesettingPtr ms
= modesettingPTR(pScrn
);
124 unsigned accel_ops_count
=
125 sizeof(accelerated_ops
)/sizeof(struct acceleration_info
);
127 if (pSrcPicture
->pSourcePict
) {
128 /* Gradients not yet supported */
129 if (pSrcPicture
->pSourcePict
->type
!= SourcePictTypeSolidFill
)
130 XORG_FALLBACK("gradients not yet supported");
132 /* Solid source with mask not yet handled properly */
134 XORG_FALLBACK("solid source with mask not yet handled properly");
137 for (i
= 0; i
< accel_ops_count
; ++i
) {
138 if (op
== accelerated_ops
[i
].op
) {
139 /* Check for unsupported component alpha */
140 if ((pSrcPicture
->componentAlpha
&&
141 !accelerated_ops
[i
].component_alpha
) ||
143 (!accelerated_ops
[i
].with_mask
||
144 (pMaskPicture
->componentAlpha
&&
145 !accelerated_ops
[i
].component_alpha
))))
146 XORG_FALLBACK("component alpha unsupported");
150 XORG_FALLBACK("unsupported operation");
154 bind_blend_state(struct exa_context
*exa
, int op
,
155 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
157 struct xorg_composite_blend blend_opt
;
158 struct pipe_blend_state blend
;
160 blend_opt
= blend_for_op(op
);
162 memset(&blend
, 0, sizeof(struct pipe_blend_state
));
163 blend
.blend_enable
= 1;
164 blend
.colormask
|= PIPE_MASK_R
;
165 blend
.colormask
|= PIPE_MASK_G
;
166 blend
.colormask
|= PIPE_MASK_B
;
167 blend
.colormask
|= PIPE_MASK_A
;
169 blend
.rgb_src_factor
= blend_opt
.rgb_src_factor
;
170 blend
.alpha_src_factor
= blend_opt
.alpha_src_factor
;
171 blend
.rgb_dst_factor
= blend_opt
.rgb_dst_factor
;
172 blend
.alpha_dst_factor
= blend_opt
.alpha_dst_factor
;
174 cso_set_blend(exa
->renderer
->cso
, &blend
);
179 bind_shaders(struct exa_context
*exa
, int op
,
180 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
182 unsigned vs_traits
= 0, fs_traits
= 0;
183 struct xorg_shader shader
;
185 exa
->has_solid_color
= FALSE
;
188 if (pSrcPicture
->pSourcePict
) {
189 if (pSrcPicture
->pSourcePict
->type
== SourcePictTypeSolidFill
) {
190 fs_traits
|= FS_SOLID_FILL
;
191 vs_traits
|= VS_SOLID_FILL
;
192 debug_assert(pSrcPicture
->format
== PICT_a8r8g8b8
);
193 pixel_to_float4(pSrcPicture
->pSourcePict
->solidFill
.color
,
195 exa
->has_solid_color
= TRUE
;
197 debug_assert("!gradients not supported");
200 fs_traits
|= FS_COMPOSITE
;
201 vs_traits
|= VS_COMPOSITE
;
206 vs_traits
|= VS_MASK
;
207 fs_traits
|= FS_MASK
;
210 shader
= xorg_shaders_get(exa
->renderer
->shaders
, vs_traits
, fs_traits
);
211 cso_set_vertex_shader_handle(exa
->renderer
->cso
, shader
.vs
);
212 cso_set_fragment_shader_handle(exa
->renderer
->cso
, shader
.fs
);
217 bind_samplers(struct exa_context
*exa
, int op
,
218 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
,
219 PicturePtr pDstPicture
,
220 struct exa_pixmap_priv
*pSrc
,
221 struct exa_pixmap_priv
*pMask
,
222 struct exa_pixmap_priv
*pDst
)
224 struct pipe_sampler_state
*samplers
[PIPE_MAX_SAMPLERS
];
225 struct pipe_sampler_state src_sampler
, mask_sampler
;
227 exa
->num_bound_samplers
= 0;
229 memset(&src_sampler
, 0, sizeof(struct pipe_sampler_state
));
230 memset(&mask_sampler
, 0, sizeof(struct pipe_sampler_state
));
232 if ((pSrc
&& exa
->pipe
->is_texture_referenced(exa
->pipe
, pSrc
->tex
, 0, 0) &
233 PIPE_REFERENCED_FOR_WRITE
) ||
234 (pMask
&& exa
->pipe
->is_texture_referenced(exa
->pipe
, pMask
->tex
, 0, 0) &
235 PIPE_REFERENCED_FOR_WRITE
))
236 exa
->pipe
->flush(exa
->pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
238 if (pSrcPicture
&& pSrc
) {
239 unsigned src_wrap
= render_repeat_to_gallium(
240 pSrcPicture
->repeatType
);
241 src_sampler
.wrap_s
= src_wrap
;
242 src_sampler
.wrap_t
= src_wrap
;
243 src_sampler
.min_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
244 src_sampler
.mag_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
245 src_sampler
.normalized_coords
= 1;
246 samplers
[0] = &src_sampler
;
247 exa
->bound_textures
[0] = pSrc
->tex
;
248 ++exa
->num_bound_samplers
;
251 if (pMaskPicture
&& pMask
) {
252 unsigned mask_wrap
= render_repeat_to_gallium(
253 pMaskPicture
->repeatType
);
254 mask_sampler
.wrap_s
= mask_wrap
;
255 mask_sampler
.wrap_t
= mask_wrap
;
256 mask_sampler
.min_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
257 mask_sampler
.mag_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
258 mask_sampler
.normalized_coords
= 1;
259 samplers
[1] = &mask_sampler
;
260 exa
->bound_textures
[1] = pMask
->tex
;
261 ++exa
->num_bound_samplers
;
264 cso_set_samplers(exa
->renderer
->cso
, exa
->num_bound_samplers
,
265 (const struct pipe_sampler_state
**)samplers
);
266 cso_set_sampler_textures(exa
->renderer
->cso
, exa
->num_bound_samplers
,
267 exa
->bound_textures
);
271 setup_vs_constant_buffer(struct exa_context
*exa
,
272 int width
, int height
)
274 const int param_bytes
= 8 * sizeof(float);
275 float vs_consts
[8] = {
276 2.f
/width
, 2.f
/height
, 1, 1,
279 renderer_set_constants(exa
->renderer
, PIPE_SHADER_VERTEX
,
280 vs_consts
, param_bytes
);
285 setup_fs_constant_buffer(struct exa_context
*exa
)
287 const int param_bytes
= 4 * sizeof(float);
288 const float fs_consts
[8] = {
291 renderer_set_constants(exa
->renderer
, PIPE_SHADER_FRAGMENT
,
292 fs_consts
, param_bytes
);
296 setup_constant_buffers(struct exa_context
*exa
, struct exa_pixmap_priv
*pDst
)
298 int width
= pDst
->tex
->width
[0];
299 int height
= pDst
->tex
->height
[0];
301 setup_vs_constant_buffer(exa
, width
, height
);
302 setup_fs_constant_buffer(exa
);
305 boolean
xorg_composite_bind_state(struct exa_context
*exa
,
307 PicturePtr pSrcPicture
,
308 PicturePtr pMaskPicture
,
309 PicturePtr pDstPicture
,
310 struct exa_pixmap_priv
*pSrc
,
311 struct exa_pixmap_priv
*pMask
,
312 struct exa_pixmap_priv
*pDst
)
314 renderer_bind_framebuffer(exa
->renderer
, pDst
);
315 renderer_bind_viewport(exa
->renderer
, pDst
);
316 bind_blend_state(exa
, op
, pSrcPicture
, pMaskPicture
);
317 renderer_bind_rasterizer(exa
->renderer
);
318 bind_shaders(exa
, op
, pSrcPicture
, pMaskPicture
);
319 bind_samplers(exa
, op
, pSrcPicture
, pMaskPicture
,
320 pDstPicture
, pSrc
, pMask
, pDst
);
321 setup_constant_buffers(exa
, pDst
);
326 void xorg_composite(struct exa_context
*exa
,
327 struct exa_pixmap_priv
*dst
,
328 int srcX
, int srcY
, int maskX
, int maskY
,
329 int dstX
, int dstY
, int width
, int height
)
331 if (exa
->num_bound_samplers
== 0 ) { /* solid fill */
332 renderer_draw_solid_rect(exa
->renderer
,
333 dstX
, dstY
, dstX
+ width
, dstY
+ height
,
336 int pos
[6] = {srcX
, srcY
, maskX
, maskY
, dstX
, dstY
};
337 renderer_draw_textures(exa
->renderer
,
340 exa
->num_bound_samplers
);
344 boolean
xorg_solid_bind_state(struct exa_context
*exa
,
345 struct exa_pixmap_priv
*pixmap
,
348 unsigned vs_traits
, fs_traits
;
349 struct xorg_shader shader
;
351 pixel_to_float4(fg
, exa
->solid_color
);
352 exa
->has_solid_color
= TRUE
;
354 exa
->solid_color
[3] = 1.f
;
357 debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
358 (fg
>> 24) & 0xff, (fg
>> 16) & 0xff,
359 (fg
>> 8) & 0xff, (fg
>> 0) & 0xff,
360 exa
->solid_color
[0], exa
->solid_color
[1],
361 exa
->solid_color
[2], exa
->solid_color
[3]);
364 vs_traits
= VS_SOLID_FILL
;
365 fs_traits
= FS_SOLID_FILL
;
367 renderer_bind_framebuffer(exa
->renderer
, pixmap
);
368 renderer_bind_viewport(exa
->renderer
, pixmap
);
369 renderer_bind_rasterizer(exa
->renderer
);
370 bind_blend_state(exa
, PictOpSrc
, NULL
, NULL
);
371 setup_constant_buffers(exa
, pixmap
);
373 shader
= xorg_shaders_get(exa
->renderer
->shaders
, vs_traits
, fs_traits
);
374 cso_set_vertex_shader_handle(exa
->renderer
->cso
, shader
.vs
);
375 cso_set_fragment_shader_handle(exa
->renderer
->cso
, shader
.fs
);
380 void xorg_solid(struct exa_context
*exa
,
381 struct exa_pixmap_priv
*pixmap
,
382 int x0
, int y0
, int x1
, int y1
)
384 renderer_draw_solid_rect(exa
->renderer
,
385 x0
, y0
, x1
, y1
, exa
->solid_color
);