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
];
99 setup_vertex0(float vertex
[2][4], float x
, float y
,
104 vertex
[0][2] = 0.f
; /*z*/
105 vertex
[0][3] = 1.f
; /*w*/
107 vertex
[1][0] = color
[0]; /*r*/
108 vertex
[1][1] = color
[1]; /*g*/
109 vertex
[1][2] = color
[2]; /*b*/
110 vertex
[1][3] = color
[3]; /*a*/
113 static struct pipe_buffer
*
114 setup_vertex_data0(struct exa_context
*ctx
,
115 int srcX
, int srcY
, int maskX
, int maskY
,
116 int dstX
, int dstY
, int width
, int height
)
118 float vertices
[4][2][4];
121 setup_vertex0(vertices
[0], dstX
, dstY
,
124 setup_vertex0(vertices
[1], dstX
+ width
, dstY
,
127 setup_vertex0(vertices
[2], dstX
+ width
, dstY
+ height
,
130 setup_vertex0(vertices
[3], dstX
, dstY
+ height
,
133 return pipe_user_buffer_create(ctx
->ctx
->screen
,
139 setup_vertex1(float vertex
[2][4], float x
, float y
, float s
, float t
)
143 vertex
[0][2] = 0.f
; /*z*/
144 vertex
[0][3] = 1.f
; /*w*/
146 vertex
[1][0] = s
; /*s*/
147 vertex
[1][1] = t
; /*t*/
148 vertex
[1][2] = 0.f
; /*r*/
149 vertex
[1][3] = 1.f
; /*q*/
152 static struct pipe_buffer
*
153 setup_vertex_data1(struct exa_context
*ctx
,
154 int srcX
, int srcY
, int maskX
, int maskY
,
155 int dstX
, int dstY
, int width
, int height
)
157 float vertices
[4][2][4];
158 float s0
, t0
, s1
, t1
;
159 struct pipe_texture
*src
= ctx
->bound_textures
[0];
161 s0
= srcX
/ src
->width
[0];
162 s1
= srcX
+ width
/ src
->width
[0];
163 t0
= srcY
/ src
->height
[0];
164 t1
= srcY
+ height
/ src
->height
[0];
167 setup_vertex1(vertices
[0], dstX
, dstY
,
170 setup_vertex1(vertices
[1], dstX
+ width
, dstY
,
173 setup_vertex1(vertices
[2], dstX
+ width
, dstY
+ height
,
176 setup_vertex1(vertices
[3], dstX
, dstY
+ height
,
179 return pipe_user_buffer_create(ctx
->ctx
->screen
,
186 setup_vertex2(float vertex
[3][4], float x
, float y
,
187 float s0
, float t0
, float s1
, float t1
)
191 vertex
[0][2] = 0.f
; /*z*/
192 vertex
[0][3] = 1.f
; /*w*/
194 vertex
[1][0] = s0
; /*s*/
195 vertex
[1][1] = t0
; /*t*/
196 vertex
[1][2] = 0.f
; /*r*/
197 vertex
[1][3] = 1.f
; /*q*/
199 vertex
[2][0] = s1
; /*s*/
200 vertex
[2][1] = t1
; /*t*/
201 vertex
[2][2] = 0.f
; /*r*/
202 vertex
[2][3] = 1.f
; /*q*/
205 static struct pipe_buffer
*
206 setup_vertex_data2(struct exa_context
*ctx
,
207 int srcX
, int srcY
, int maskX
, int maskY
,
208 int dstX
, int dstY
, int width
, int height
)
210 float vertices
[4][3][4];
211 float st0
[4], st1
[4];
212 struct pipe_texture
*src
= ctx
->bound_textures
[0];
213 struct pipe_texture
*mask
= ctx
->bound_textures
[0];
215 st0
[0] = srcX
/ src
->width
[0];
216 st0
[1] = srcY
/ src
->height
[0];
217 st0
[2] = srcX
+ width
/ src
->width
[0];
218 st0
[3] = srcY
+ height
/ src
->height
[0];
220 st1
[0] = maskX
/ mask
->width
[0];
221 st1
[1] = maskY
/ mask
->height
[0];
222 st1
[2] = maskX
+ width
/ mask
->width
[0];
223 st1
[3] = maskY
+ height
/ mask
->height
[0];
226 setup_vertex2(vertices
[0], dstX
, dstY
,
227 st0
[0], st0
[1], st1
[0], st1
[1]);
229 setup_vertex2(vertices
[1], dstX
+ width
, dstY
,
230 st0
[2], st0
[1], st1
[2], st1
[1]);
232 setup_vertex2(vertices
[2], dstX
+ width
, dstY
+ height
,
233 st0
[2], st0
[3], st1
[2], st1
[3]);
235 setup_vertex2(vertices
[3], dstX
, dstY
+ height
,
236 st0
[0], st0
[3], st1
[0], st1
[3]);
238 return pipe_user_buffer_create(ctx
->ctx
->screen
,
243 boolean
xorg_composite_accelerated(int op
,
244 PicturePtr pSrcPicture
,
245 PicturePtr pMaskPicture
,
246 PicturePtr pDstPicture
)
249 unsigned accel_ops_count
=
250 sizeof(accelerated_ops
)/sizeof(struct acceleration_info
);
253 /*FIXME: currently accel is disabled */
257 /* component alpha not supported */
258 if (pSrcPicture
->componentAlpha
)
260 /* fills not supported */
261 if (pSrcPicture
->pSourcePict
)
265 for (i
= 0; i
< accel_ops_count
; ++i
) {
266 if (op
== accelerated_ops
[i
].op
) {
267 if (pMaskPicture
&& !accelerated_ops
[i
].with_mask
)
276 bind_framebuffer_state(struct exa_context
*exa
, PicturePtr pDstPicture
,
277 struct exa_pixmap_priv
*pDst
)
280 struct pipe_framebuffer_state state
;
281 struct pipe_surface
*surface
= exa_gpu_surface(exa
, pDst
);
282 memset(&state
, 0, sizeof(struct pipe_framebuffer_state
));
284 state
.width
= pDstPicture
->pDrawable
->width
;
285 state
.height
= pDstPicture
->pDrawable
->height
;
288 state
.cbufs
[0] = surface
;
289 for (i
= 1; i
< PIPE_MAX_COLOR_BUFS
; ++i
)
292 /* currently we don't use depth/stencil */
295 cso_set_framebuffer(exa
->cso
, &state
);
298 enum AxisOrientation
{
304 set_viewport(struct exa_context
*exa
, int width
, int height
,
305 enum AxisOrientation orientation
)
307 struct pipe_viewport_state viewport
;
308 float y_scale
= (orientation
== Y0_BOTTOM
) ? -2.f
: 2.f
;
310 viewport
.scale
[0] = width
/ 2.f
;
311 viewport
.scale
[1] = height
/ y_scale
;
312 viewport
.scale
[2] = 1.0;
313 viewport
.scale
[3] = 1.0;
314 viewport
.translate
[0] = width
/ 2.f
;
315 viewport
.translate
[1] = height
/ 2.f
;
316 viewport
.translate
[2] = 0.0;
317 viewport
.translate
[3] = 0.0;
319 cso_set_viewport(exa
->cso
, &viewport
);
323 bind_viewport_state(struct exa_context
*exa
, PicturePtr pDstPicture
)
325 int width
= pDstPicture
->pDrawable
->width
;
326 int height
= pDstPicture
->pDrawable
->height
;
328 set_viewport(exa
, width
, height
, Y0_TOP
);
332 bind_blend_state(struct exa_context
*exa
, int op
,
333 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
335 boolean component_alpha
= pSrcPicture
->componentAlpha
;
336 struct xorg_composite_blend blend_opt
;
337 struct pipe_blend_state blend
;
339 if (component_alpha
) {
342 blend_opt
= blend_for_op(op
);
344 memset(&blend
, 0, sizeof(struct pipe_blend_state
));
345 blend
.blend_enable
= 1;
346 blend
.colormask
|= PIPE_MASK_R
;
347 blend
.colormask
|= PIPE_MASK_G
;
348 blend
.colormask
|= PIPE_MASK_B
;
349 blend
.colormask
|= PIPE_MASK_A
;
351 blend
.rgb_src_factor
= blend_opt
.rgb_src_factor
;
352 blend
.alpha_src_factor
= blend_opt
.alpha_src_factor
;
353 blend
.rgb_dst_factor
= blend_opt
.rgb_dst_factor
;
354 blend
.alpha_dst_factor
= blend_opt
.alpha_dst_factor
;
356 cso_set_blend(exa
->cso
, &blend
);
360 bind_rasterizer_state(struct exa_context
*exa
)
362 struct pipe_rasterizer_state raster
;
363 memset(&raster
, 0, sizeof(struct pipe_rasterizer_state
));
364 raster
.gl_rasterization_rules
= 1;
365 cso_set_rasterizer(exa
->cso
, &raster
);
369 bind_shaders(struct exa_context
*exa
, int op
,
370 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
372 unsigned vs_traits
= 0, fs_traits
= 0;
373 struct xorg_shader shader
;
376 if (pSrcPicture
->pSourcePict
) {
377 if (pSrcPicture
->pSourcePict
->type
== SourcePictTypeSolidFill
) {
378 fs_traits
|= FS_FILL
;
379 vs_traits
|= VS_FILL
;
380 pixel_to_float4(pSrcPicture
->pFormat
,
381 pSrcPicture
->pSourcePict
->solidFill
.color
,
384 debug_assert("!gradients not supported");
387 fs_traits
|= FS_COMPOSITE
;
388 vs_traits
|= VS_COMPOSITE
;
393 vs_traits
|= VS_MASK
;
394 fs_traits
|= FS_MASK
;
397 shader
= xorg_shaders_get(exa
->shaders
, vs_traits
, fs_traits
);
398 cso_set_vertex_shader_handle(exa
->cso
, shader
.vs
);
399 cso_set_fragment_shader_handle(exa
->cso
, shader
.fs
);
404 bind_samplers(struct exa_context
*exa
, int op
,
405 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
,
406 PicturePtr pDstPicture
,
407 struct exa_pixmap_priv
*pSrc
,
408 struct exa_pixmap_priv
*pMask
,
409 struct exa_pixmap_priv
*pDst
)
411 struct pipe_sampler_state
*samplers
[PIPE_MAX_SAMPLERS
];
412 struct pipe_sampler_state src_sampler
, mask_sampler
;
414 exa
->num_bound_samplers
= 0;
416 memset(&src_sampler
, 0, sizeof(struct pipe_sampler_state
));
417 memset(&mask_sampler
, 0, sizeof(struct pipe_sampler_state
));
419 if (pSrcPicture
&& pSrc
) {
420 src_sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
421 src_sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
422 src_sampler
.min_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
423 src_sampler
.mag_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
424 src_sampler
.normalized_coords
= 1;
425 samplers
[0] = &src_sampler
;
426 exa
->bound_textures
[0] = pSrc
->tex
;
427 ++exa
->num_bound_samplers
;
430 if (pMaskPicture
&& pMask
) {
431 mask_sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
432 mask_sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
433 mask_sampler
.min_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
434 mask_sampler
.mag_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
435 mask_sampler
.normalized_coords
= 1;
436 samplers
[1] = &mask_sampler
;
437 exa
->bound_textures
[1] = pMask
->tex
;
438 ++exa
->num_bound_samplers
;
441 cso_set_samplers(exa
->cso
, exa
->num_bound_samplers
,
442 (const struct pipe_sampler_state
**)samplers
);
443 cso_set_sampler_textures(exa
->cso
, exa
->num_bound_samplers
,
444 exa
->bound_textures
);
448 setup_vs_constant_buffer(struct exa_context
*exa
,
449 int width
, int height
)
451 const int param_bytes
= 8 * sizeof(float);
452 float vs_consts
[8] = {
453 2.f
/width
, 2.f
/height
, 1, 1,
456 struct pipe_constant_buffer
*cbuf
= &exa
->vs_const_buffer
;
458 pipe_buffer_reference(&cbuf
->buffer
, NULL
);
459 cbuf
->buffer
= pipe_buffer_create(exa
->ctx
->screen
, 16,
460 PIPE_BUFFER_USAGE_CONSTANT
,
464 pipe_buffer_write(exa
->ctx
->screen
, cbuf
->buffer
,
465 0, param_bytes
, vs_consts
);
467 exa
->ctx
->set_constant_buffer(exa
->ctx
, PIPE_SHADER_VERTEX
, 0, cbuf
);
472 setup_fs_constant_buffer(struct exa_context
*exa
)
474 const int param_bytes
= 4 * sizeof(float);
475 float fs_consts
[8] = {
478 struct pipe_constant_buffer
*cbuf
= &exa
->fs_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
, fs_consts
);
489 exa
->ctx
->set_constant_buffer(exa
->ctx
, PIPE_SHADER_FRAGMENT
, 0, cbuf
);
493 setup_constant_buffers(struct exa_context
*exa
, PicturePtr pDstPicture
)
495 int width
= pDstPicture
->pDrawable
->width
;
496 int height
= pDstPicture
->pDrawable
->height
;
498 setup_vs_constant_buffer(exa
, width
, height
);
499 setup_fs_constant_buffer(exa
);
502 boolean
xorg_composite_bind_state(struct exa_context
*exa
,
504 PicturePtr pSrcPicture
,
505 PicturePtr pMaskPicture
,
506 PicturePtr pDstPicture
,
507 struct exa_pixmap_priv
*pSrc
,
508 struct exa_pixmap_priv
*pMask
,
509 struct exa_pixmap_priv
*pDst
)
511 bind_framebuffer_state(exa
, pDstPicture
, pDst
);
512 bind_viewport_state(exa
, pDstPicture
);
513 bind_blend_state(exa
, op
, pSrcPicture
, pMaskPicture
);
514 bind_rasterizer_state(exa
);
515 bind_shaders(exa
, op
, pSrcPicture
, pMaskPicture
);
516 bind_samplers(exa
, op
, pSrcPicture
, pMaskPicture
,
517 pDstPicture
, pSrc
, pMask
, pDst
);
519 setup_constant_buffers(exa
, pDstPicture
);
524 void xorg_composite(struct exa_context
*exa
,
525 struct exa_pixmap_priv
*dst
,
526 int srcX
, int srcY
, int maskX
, int maskY
,
527 int dstX
, int dstY
, int width
, int height
)
529 struct pipe_context
*pipe
= exa
->ctx
;
530 struct pipe_buffer
*buf
= 0;
532 if (exa
->num_bound_samplers
== 0 ) { /* solid fill */
533 buf
= setup_vertex_data0(exa
,
534 srcX
, srcY
, maskX
, maskY
,
535 dstX
, dstY
, width
, height
);
536 } else if (exa
->num_bound_samplers
== 1 ) /* src */
537 buf
= setup_vertex_data1(exa
,
538 srcX
, srcY
, maskX
, maskY
,
539 dstX
, dstY
, width
, height
);
540 else if (exa
->num_bound_samplers
== 2) /* src + mask */
541 buf
= setup_vertex_data2(exa
,
542 srcX
, srcY
, maskX
, maskY
,
543 dstX
, dstY
, width
, height
);
544 else if (exa
->num_bound_samplers
== 3) { /* src + mask + dst */
545 debug_assert(!"src/mask/dst not handled right now");
547 buf
= setup_vertex_data2(exa
,
548 srcX
, srcY
, maskX
, maskY
,
549 dstX
, dstY
, width
, height
);
554 util_draw_vertex_buffer(pipe
, buf
, 0,
555 PIPE_PRIM_TRIANGLE_FAN
,
557 1 + exa
->num_bound_samplers
); /* attribs/vert */
559 pipe_buffer_reference(&buf
, NULL
);