1 #include "xorg_composite.h"
3 #include "xorg_exa_tgsi.h"
5 #include "cso_cache/cso_context.h"
6 #include "util/u_draw_quad.h"
8 #include "pipe/p_inlines.h"
10 struct xorg_composite_blend
{
13 unsigned rgb_src_factor
:5; /**< PIPE_BLENDFACTOR_x */
14 unsigned rgb_dst_factor
:5; /**< PIPE_BLENDFACTOR_x */
16 unsigned alpha_src_factor
:5; /**< PIPE_BLENDFACTOR_x */
17 unsigned alpha_dst_factor
:5; /**< PIPE_BLENDFACTOR_x */
20 #define BLEND_OP_OVER 3
21 static const struct xorg_composite_blend xorg_blends
[] = {
23 PIPE_BLENDFACTOR_CONST_COLOR
, PIPE_BLENDFACTOR_CONST_ALPHA
,
24 PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_ZERO
},
27 PIPE_BLENDFACTOR_ONE
, PIPE_BLENDFACTOR_ONE
,
28 PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_ZERO
},
31 PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_ZERO
,
32 PIPE_BLENDFACTOR_ONE
, PIPE_BLENDFACTOR_ONE
},
35 PIPE_BLENDFACTOR_SRC_ALPHA
, PIPE_BLENDFACTOR_ONE
,
36 PIPE_BLENDFACTOR_INV_SRC_ALPHA
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
39 PIPE_BLENDFACTOR_SRC_ALPHA
, PIPE_BLENDFACTOR_ONE
,
40 PIPE_BLENDFACTOR_INV_SRC_ALPHA
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
44 pixel_to_float4(PictFormatPtr format
,
45 CARD32 pixel
, float *color
)
49 debug_assert(format
->type
== PictTypeDirect
);
51 r
= (pixel
>> format
->direct
.red
) & format
->direct
.redMask
;
52 g
= (pixel
>> format
->direct
.green
) & format
->direct
.greenMask
;
53 b
= (pixel
>> format
->direct
.blue
) & format
->direct
.blueMask
;
54 a
= (pixel
>> format
->direct
.alpha
) & format
->direct
.alphaMask
;
55 color
[0] = ((float)r
) / ((float)format
->direct
.redMask
);
56 color
[1] = ((float)g
) / ((float)format
->direct
.greenMask
);
57 color
[2] = ((float)b
) / ((float)format
->direct
.blueMask
);
58 color
[3] = ((float)a
) / ((float)format
->direct
.alphaMask
);
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
;
117 setup_vertex0(float vertex
[2][4], float x
, float y
,
122 vertex
[0][2] = 0.f
; /*z*/
123 vertex
[0][3] = 1.f
; /*w*/
125 vertex
[1][0] = color
[0]; /*r*/
126 vertex
[1][1] = color
[1]; /*g*/
127 vertex
[1][2] = color
[2]; /*b*/
128 vertex
[1][3] = color
[3]; /*a*/
131 static struct pipe_buffer
*
132 setup_vertex_data0(struct exa_context
*ctx
,
133 int srcX
, int srcY
, int maskX
, int maskY
,
134 int dstX
, int dstY
, int width
, int height
)
136 float vertices
[4][2][4];
139 setup_vertex0(vertices
[0], dstX
, dstY
,
142 setup_vertex0(vertices
[1], dstX
+ width
, dstY
,
145 setup_vertex0(vertices
[2], dstX
+ width
, dstY
+ height
,
148 setup_vertex0(vertices
[3], dstX
, dstY
+ height
,
151 return pipe_user_buffer_create(ctx
->ctx
->screen
,
157 setup_vertex1(float vertex
[2][4], float x
, float y
, float s
, float t
)
161 vertex
[0][2] = 0.f
; /*z*/
162 vertex
[0][3] = 1.f
; /*w*/
164 vertex
[1][0] = s
; /*s*/
165 vertex
[1][1] = t
; /*t*/
166 vertex
[1][2] = 0.f
; /*r*/
167 vertex
[1][3] = 1.f
; /*q*/
170 static struct pipe_buffer
*
171 setup_vertex_data1(struct exa_context
*ctx
,
172 int srcX
, int srcY
, int maskX
, int maskY
,
173 int dstX
, int dstY
, int width
, int height
)
175 float vertices
[4][2][4];
176 float s0
, t0
, s1
, t1
;
177 struct pipe_texture
*src
= ctx
->bound_textures
[0];
179 s0
= srcX
/ src
->width
[0];
180 s1
= srcX
+ width
/ src
->width
[0];
181 t0
= srcY
/ src
->height
[0];
182 t1
= srcY
+ height
/ src
->height
[0];
185 setup_vertex1(vertices
[0], dstX
, dstY
,
188 setup_vertex1(vertices
[1], dstX
+ width
, dstY
,
191 setup_vertex1(vertices
[2], dstX
+ width
, dstY
+ height
,
194 setup_vertex1(vertices
[3], dstX
, dstY
+ height
,
197 return pipe_user_buffer_create(ctx
->ctx
->screen
,
204 setup_vertex2(float vertex
[3][4], float x
, float y
,
205 float s0
, float t0
, float s1
, float t1
)
209 vertex
[0][2] = 0.f
; /*z*/
210 vertex
[0][3] = 1.f
; /*w*/
212 vertex
[1][0] = s0
; /*s*/
213 vertex
[1][1] = t0
; /*t*/
214 vertex
[1][2] = 0.f
; /*r*/
215 vertex
[1][3] = 1.f
; /*q*/
217 vertex
[2][0] = s1
; /*s*/
218 vertex
[2][1] = t1
; /*t*/
219 vertex
[2][2] = 0.f
; /*r*/
220 vertex
[2][3] = 1.f
; /*q*/
223 static struct pipe_buffer
*
224 setup_vertex_data2(struct exa_context
*ctx
,
225 int srcX
, int srcY
, int maskX
, int maskY
,
226 int dstX
, int dstY
, int width
, int height
)
228 float vertices
[4][3][4];
229 float st0
[4], st1
[4];
230 struct pipe_texture
*src
= ctx
->bound_textures
[0];
231 struct pipe_texture
*mask
= ctx
->bound_textures
[0];
233 st0
[0] = srcX
/ src
->width
[0];
234 st0
[1] = srcY
/ src
->height
[0];
235 st0
[2] = srcX
+ width
/ src
->width
[0];
236 st0
[3] = srcY
+ height
/ src
->height
[0];
238 st1
[0] = maskX
/ mask
->width
[0];
239 st1
[1] = maskY
/ mask
->height
[0];
240 st1
[2] = maskX
+ width
/ mask
->width
[0];
241 st1
[3] = maskY
+ height
/ mask
->height
[0];
244 setup_vertex2(vertices
[0], dstX
, dstY
,
245 st0
[0], st0
[1], st1
[0], st1
[1]);
247 setup_vertex2(vertices
[1], dstX
+ width
, dstY
,
248 st0
[2], st0
[1], st1
[2], st1
[1]);
250 setup_vertex2(vertices
[2], dstX
+ width
, dstY
+ height
,
251 st0
[2], st0
[3], st1
[2], st1
[3]);
253 setup_vertex2(vertices
[3], dstX
, dstY
+ height
,
254 st0
[0], st0
[3], st1
[0], st1
[3]);
256 return pipe_user_buffer_create(ctx
->ctx
->screen
,
261 boolean
xorg_composite_accelerated(int op
,
262 PicturePtr pSrcPicture
,
263 PicturePtr pMaskPicture
,
264 PicturePtr pDstPicture
)
267 unsigned accel_ops_count
=
268 sizeof(accelerated_ops
)/sizeof(struct acceleration_info
);
271 /*FIXME: currently accel is disabled */
275 /* component alpha not supported */
276 if (pSrcPicture
->componentAlpha
)
278 /* fills not supported */
279 if (pSrcPicture
->pSourcePict
)
283 for (i
= 0; i
< accel_ops_count
; ++i
) {
284 if (op
== accelerated_ops
[i
].op
) {
285 if (pMaskPicture
&& !accelerated_ops
[i
].with_mask
)
294 bind_framebuffer_state(struct exa_context
*exa
, PicturePtr pDstPicture
,
295 struct exa_pixmap_priv
*pDst
)
298 struct pipe_framebuffer_state state
;
299 struct pipe_surface
*surface
= exa_gpu_surface(exa
, pDst
);
300 memset(&state
, 0, sizeof(struct pipe_framebuffer_state
));
302 state
.width
= pDstPicture
->pDrawable
->width
;
303 state
.height
= pDstPicture
->pDrawable
->height
;
306 state
.cbufs
[0] = surface
;
307 for (i
= 1; i
< PIPE_MAX_COLOR_BUFS
; ++i
)
310 /* currently we don't use depth/stencil */
313 cso_set_framebuffer(exa
->cso
, &state
);
316 enum AxisOrientation
{
322 set_viewport(struct exa_context
*exa
, int width
, int height
,
323 enum AxisOrientation orientation
)
325 struct pipe_viewport_state viewport
;
326 float y_scale
= (orientation
== Y0_BOTTOM
) ? -2.f
: 2.f
;
328 viewport
.scale
[0] = width
/ 2.f
;
329 viewport
.scale
[1] = height
/ y_scale
;
330 viewport
.scale
[2] = 1.0;
331 viewport
.scale
[3] = 1.0;
332 viewport
.translate
[0] = width
/ 2.f
;
333 viewport
.translate
[1] = height
/ 2.f
;
334 viewport
.translate
[2] = 0.0;
335 viewport
.translate
[3] = 0.0;
337 cso_set_viewport(exa
->cso
, &viewport
);
341 bind_viewport_state(struct exa_context
*exa
, PicturePtr pDstPicture
)
343 int width
= pDstPicture
->pDrawable
->width
;
344 int height
= pDstPicture
->pDrawable
->height
;
346 set_viewport(exa
, width
, height
, Y0_TOP
);
350 bind_blend_state(struct exa_context
*exa
, int op
,
351 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
353 boolean component_alpha
= pSrcPicture
->componentAlpha
;
354 struct xorg_composite_blend blend_opt
;
355 struct pipe_blend_state blend
;
357 if (component_alpha
) {
360 blend_opt
= blend_for_op(op
);
362 memset(&blend
, 0, sizeof(struct pipe_blend_state
));
363 blend
.blend_enable
= 1;
364 blend
.colormask
|= PIPE_MASK_R
;
365 blend
.colormask
|= PIPE_MASK_G
;
366 blend
.colormask
|= PIPE_MASK_B
;
367 blend
.colormask
|= PIPE_MASK_A
;
369 blend
.rgb_src_factor
= blend_opt
.rgb_src_factor
;
370 blend
.alpha_src_factor
= blend_opt
.alpha_src_factor
;
371 blend
.rgb_dst_factor
= blend_opt
.rgb_dst_factor
;
372 blend
.alpha_dst_factor
= blend_opt
.alpha_dst_factor
;
374 cso_set_blend(exa
->cso
, &blend
);
378 bind_rasterizer_state(struct exa_context
*exa
)
380 struct pipe_rasterizer_state raster
;
381 memset(&raster
, 0, sizeof(struct pipe_rasterizer_state
));
382 raster
.gl_rasterization_rules
= 1;
383 cso_set_rasterizer(exa
->cso
, &raster
);
387 bind_shaders(struct exa_context
*exa
, int op
,
388 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
390 unsigned vs_traits
= 0, fs_traits
= 0;
391 struct xorg_shader shader
;
394 if (pSrcPicture
->pSourcePict
) {
395 if (pSrcPicture
->pSourcePict
->type
== SourcePictTypeSolidFill
) {
396 fs_traits
|= FS_SOLID_FILL
;
397 vs_traits
|= VS_SOLID_FILL
;
398 pixel_to_float4(pSrcPicture
->pFormat
,
399 pSrcPicture
->pSourcePict
->solidFill
.color
,
402 debug_assert("!gradients not supported");
405 fs_traits
|= FS_COMPOSITE
;
406 vs_traits
|= VS_COMPOSITE
;
411 vs_traits
|= VS_MASK
;
412 fs_traits
|= FS_MASK
;
415 shader
= xorg_shaders_get(exa
->shaders
, vs_traits
, fs_traits
);
416 cso_set_vertex_shader_handle(exa
->cso
, shader
.vs
);
417 cso_set_fragment_shader_handle(exa
->cso
, shader
.fs
);
422 bind_samplers(struct exa_context
*exa
, int op
,
423 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
,
424 PicturePtr pDstPicture
,
425 struct exa_pixmap_priv
*pSrc
,
426 struct exa_pixmap_priv
*pMask
,
427 struct exa_pixmap_priv
*pDst
)
429 struct pipe_sampler_state
*samplers
[PIPE_MAX_SAMPLERS
];
430 struct pipe_sampler_state src_sampler
, mask_sampler
;
432 exa
->num_bound_samplers
= 0;
434 memset(&src_sampler
, 0, sizeof(struct pipe_sampler_state
));
435 memset(&mask_sampler
, 0, sizeof(struct pipe_sampler_state
));
437 if (pSrcPicture
&& pSrc
) {
438 unsigned src_wrap
= render_repeat_to_gallium(
439 pSrcPicture
->repeatType
);
440 src_sampler
.wrap_s
= src_wrap
;
441 src_sampler
.wrap_t
= src_wrap
;
442 src_sampler
.min_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
443 src_sampler
.mag_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
444 src_sampler
.normalized_coords
= 1;
445 samplers
[0] = &src_sampler
;
446 exa
->bound_textures
[0] = pSrc
->tex
;
447 ++exa
->num_bound_samplers
;
450 if (pMaskPicture
&& pMask
) {
451 unsigned mask_wrap
= render_repeat_to_gallium(
452 pMaskPicture
->repeatType
);
453 mask_sampler
.wrap_s
= mask_wrap
;
454 mask_sampler
.wrap_t
= mask_wrap
;
455 mask_sampler
.min_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
456 mask_sampler
.mag_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
457 mask_sampler
.normalized_coords
= 1;
458 samplers
[1] = &mask_sampler
;
459 exa
->bound_textures
[1] = pMask
->tex
;
460 ++exa
->num_bound_samplers
;
463 cso_set_samplers(exa
->cso
, exa
->num_bound_samplers
,
464 (const struct pipe_sampler_state
**)samplers
);
465 cso_set_sampler_textures(exa
->cso
, exa
->num_bound_samplers
,
466 exa
->bound_textures
);
470 setup_vs_constant_buffer(struct exa_context
*exa
,
471 int width
, int height
)
473 const int param_bytes
= 8 * sizeof(float);
474 float vs_consts
[8] = {
475 2.f
/width
, 2.f
/height
, 1, 1,
478 struct pipe_constant_buffer
*cbuf
= &exa
->vs_const_buffer
;
480 pipe_buffer_reference(&cbuf
->buffer
, NULL
);
481 cbuf
->buffer
= pipe_buffer_create(exa
->ctx
->screen
, 16,
482 PIPE_BUFFER_USAGE_CONSTANT
,
486 pipe_buffer_write(exa
->ctx
->screen
, cbuf
->buffer
,
487 0, param_bytes
, vs_consts
);
489 exa
->ctx
->set_constant_buffer(exa
->ctx
, PIPE_SHADER_VERTEX
, 0, cbuf
);
494 setup_fs_constant_buffer(struct exa_context
*exa
)
496 const int param_bytes
= 4 * sizeof(float);
497 float fs_consts
[8] = {
500 struct pipe_constant_buffer
*cbuf
= &exa
->fs_const_buffer
;
502 pipe_buffer_reference(&cbuf
->buffer
, NULL
);
503 cbuf
->buffer
= pipe_buffer_create(exa
->ctx
->screen
, 16,
504 PIPE_BUFFER_USAGE_CONSTANT
,
508 pipe_buffer_write(exa
->ctx
->screen
, cbuf
->buffer
,
509 0, param_bytes
, fs_consts
);
511 exa
->ctx
->set_constant_buffer(exa
->ctx
, PIPE_SHADER_FRAGMENT
, 0, cbuf
);
515 setup_constant_buffers(struct exa_context
*exa
, PicturePtr pDstPicture
)
517 int width
= pDstPicture
->pDrawable
->width
;
518 int height
= pDstPicture
->pDrawable
->height
;
520 setup_vs_constant_buffer(exa
, width
, height
);
521 setup_fs_constant_buffer(exa
);
524 boolean
xorg_composite_bind_state(struct exa_context
*exa
,
526 PicturePtr pSrcPicture
,
527 PicturePtr pMaskPicture
,
528 PicturePtr pDstPicture
,
529 struct exa_pixmap_priv
*pSrc
,
530 struct exa_pixmap_priv
*pMask
,
531 struct exa_pixmap_priv
*pDst
)
533 bind_framebuffer_state(exa
, pDstPicture
, pDst
);
534 bind_viewport_state(exa
, pDstPicture
);
535 bind_blend_state(exa
, op
, pSrcPicture
, pMaskPicture
);
536 bind_rasterizer_state(exa
);
537 bind_shaders(exa
, op
, pSrcPicture
, pMaskPicture
);
538 bind_samplers(exa
, op
, pSrcPicture
, pMaskPicture
,
539 pDstPicture
, pSrc
, pMask
, pDst
);
541 setup_constant_buffers(exa
, pDstPicture
);
546 void xorg_composite(struct exa_context
*exa
,
547 struct exa_pixmap_priv
*dst
,
548 int srcX
, int srcY
, int maskX
, int maskY
,
549 int dstX
, int dstY
, int width
, int height
)
551 struct pipe_context
*pipe
= exa
->ctx
;
552 struct pipe_buffer
*buf
= 0;
554 if (exa
->num_bound_samplers
== 0 ) { /* solid fill */
555 buf
= setup_vertex_data0(exa
,
556 srcX
, srcY
, maskX
, maskY
,
557 dstX
, dstY
, width
, height
);
558 } else if (exa
->num_bound_samplers
== 1 ) /* src */
559 buf
= setup_vertex_data1(exa
,
560 srcX
, srcY
, maskX
, maskY
,
561 dstX
, dstY
, width
, height
);
562 else if (exa
->num_bound_samplers
== 2) /* src + mask */
563 buf
= setup_vertex_data2(exa
,
564 srcX
, srcY
, maskX
, maskY
,
565 dstX
, dstY
, width
, height
);
566 else if (exa
->num_bound_samplers
== 3) { /* src + mask + dst */
567 debug_assert(!"src/mask/dst not handled right now");
569 buf
= setup_vertex_data2(exa
,
570 srcX
, srcY
, maskX
, maskY
,
571 dstX
, dstY
, width
, height
);
576 util_draw_vertex_buffer(pipe
, buf
, 0,
577 PIPE_PRIM_TRIANGLE_FAN
,
579 1 + exa
->num_bound_samplers
); /* attribs/vert */
581 pipe_buffer_reference(&buf
, NULL
);