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
},
45 pixel_to_float4(Pixel pixel
, float *color
)
49 a
= (pixel
>> 24) & 0xff;
50 r
= (pixel
>> 16) & 0xff;
51 g
= (pixel
>> 8) & 0xff;
52 b
= (pixel
>> 0) & 0xff;
53 color
[0] = ((float)r
) / 255.;
54 color
[1] = ((float)g
) / 255.;
55 color
[2] = ((float)b
) / 255.;
56 color
[3] = ((float)a
) / 255.;
60 render_pixel_to_float4(PictFormatPtr format
,
61 CARD32 pixel
, float *color
)
65 debug_assert(format
->type
== PictTypeDirect
);
67 r
= (pixel
>> format
->direct
.red
) & format
->direct
.redMask
;
68 g
= (pixel
>> format
->direct
.green
) & format
->direct
.greenMask
;
69 b
= (pixel
>> format
->direct
.blue
) & format
->direct
.blueMask
;
70 a
= (pixel
>> format
->direct
.alpha
) & format
->direct
.alphaMask
;
71 color
[0] = ((float)r
) / ((float)format
->direct
.redMask
);
72 color
[1] = ((float)g
) / ((float)format
->direct
.greenMask
);
73 color
[2] = ((float)b
) / ((float)format
->direct
.blueMask
);
74 color
[3] = ((float)a
) / ((float)format
->direct
.alphaMask
);
77 struct acceleration_info
{
80 int component_alpha
: 1;
82 static const struct acceleration_info accelerated_ops
[] = {
87 {PictOpOverReverse
, 1, 0},
89 {PictOpInReverse
, 1, 0},
91 {PictOpOutReverse
, 1, 0},
93 {PictOpAtopReverse
, 1, 0},
96 {PictOpSaturate
, 1, 0},
99 static struct xorg_composite_blend
102 const int num_blends
=
103 sizeof(xorg_blends
)/sizeof(struct xorg_composite_blend
);
106 for (i
= 0; i
< num_blends
; ++i
) {
107 if (xorg_blends
[i
].op
== op
)
108 return xorg_blends
[i
];
110 return xorg_blends
[BLEND_OP_OVER
];
114 render_repeat_to_gallium(int mode
)
118 return PIPE_TEX_WRAP_CLAMP
;
120 return PIPE_TEX_WRAP_REPEAT
;
122 return PIPE_TEX_WRAP_MIRROR_REPEAT
;
124 return PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
126 debug_printf("Unsupported repeat mode\n");
128 return PIPE_TEX_WRAP_REPEAT
;
133 setup_vertex0(float vertex
[2][4], float x
, float y
,
138 vertex
[0][2] = 0.f
; /*z*/
139 vertex
[0][3] = 1.f
; /*w*/
141 vertex
[1][0] = color
[0]; /*r*/
142 vertex
[1][1] = color
[1]; /*g*/
143 vertex
[1][2] = color
[2]; /*b*/
144 vertex
[1][3] = color
[3]; /*a*/
147 static struct pipe_buffer
*
148 setup_vertex_data0(struct exa_context
*ctx
,
149 int srcX
, int srcY
, int maskX
, int maskY
,
150 int dstX
, int dstY
, int width
, int height
)
152 float vertices
[4][2][4];
155 setup_vertex0(vertices
[0], dstX
, dstY
,
158 setup_vertex0(vertices
[1], dstX
+ width
, dstY
,
161 setup_vertex0(vertices
[2], dstX
+ width
, dstY
+ height
,
164 setup_vertex0(vertices
[3], dstX
, dstY
+ height
,
167 return pipe_user_buffer_create(ctx
->ctx
->screen
,
173 setup_vertex1(float vertex
[2][4], float x
, float y
, float s
, float t
)
177 vertex
[0][2] = 0.f
; /*z*/
178 vertex
[0][3] = 1.f
; /*w*/
180 vertex
[1][0] = s
; /*s*/
181 vertex
[1][1] = t
; /*t*/
182 vertex
[1][2] = 0.f
; /*r*/
183 vertex
[1][3] = 1.f
; /*q*/
186 static struct pipe_buffer
*
187 setup_vertex_data1(struct exa_context
*ctx
,
188 int srcX
, int srcY
, int maskX
, int maskY
,
189 int dstX
, int dstY
, int width
, int height
)
191 float vertices
[4][2][4];
192 float s0
, t0
, s1
, t1
;
193 struct pipe_texture
*src
= ctx
->bound_textures
[0];
195 s0
= srcX
/ src
->width
[0];
196 s1
= srcX
+ width
/ src
->width
[0];
197 t0
= srcY
/ src
->height
[0];
198 t1
= srcY
+ height
/ src
->height
[0];
201 setup_vertex1(vertices
[0], dstX
, dstY
,
204 setup_vertex1(vertices
[1], dstX
+ width
, dstY
,
207 setup_vertex1(vertices
[2], dstX
+ width
, dstY
+ height
,
210 setup_vertex1(vertices
[3], dstX
, dstY
+ height
,
213 return pipe_user_buffer_create(ctx
->ctx
->screen
,
220 setup_vertex2(float vertex
[3][4], float x
, float y
,
221 float s0
, float t0
, float s1
, float t1
)
225 vertex
[0][2] = 0.f
; /*z*/
226 vertex
[0][3] = 1.f
; /*w*/
228 vertex
[1][0] = s0
; /*s*/
229 vertex
[1][1] = t0
; /*t*/
230 vertex
[1][2] = 0.f
; /*r*/
231 vertex
[1][3] = 1.f
; /*q*/
233 vertex
[2][0] = s1
; /*s*/
234 vertex
[2][1] = t1
; /*t*/
235 vertex
[2][2] = 0.f
; /*r*/
236 vertex
[2][3] = 1.f
; /*q*/
239 static struct pipe_buffer
*
240 setup_vertex_data2(struct exa_context
*ctx
,
241 int srcX
, int srcY
, int maskX
, int maskY
,
242 int dstX
, int dstY
, int width
, int height
)
244 float vertices
[4][3][4];
245 float st0
[4], st1
[4];
246 struct pipe_texture
*src
= ctx
->bound_textures
[0];
247 struct pipe_texture
*mask
= ctx
->bound_textures
[0];
249 st0
[0] = srcX
/ src
->width
[0];
250 st0
[1] = srcY
/ src
->height
[0];
251 st0
[2] = srcX
+ width
/ src
->width
[0];
252 st0
[3] = srcY
+ height
/ src
->height
[0];
254 st1
[0] = maskX
/ mask
->width
[0];
255 st1
[1] = maskY
/ mask
->height
[0];
256 st1
[2] = maskX
+ width
/ mask
->width
[0];
257 st1
[3] = maskY
+ height
/ mask
->height
[0];
260 setup_vertex2(vertices
[0], dstX
, dstY
,
261 st0
[0], st0
[1], st1
[0], st1
[1]);
263 setup_vertex2(vertices
[1], dstX
+ width
, dstY
,
264 st0
[2], st0
[1], st1
[2], st1
[1]);
266 setup_vertex2(vertices
[2], dstX
+ width
, dstY
+ height
,
267 st0
[2], st0
[3], st1
[2], st1
[3]);
269 setup_vertex2(vertices
[3], dstX
, dstY
+ height
,
270 st0
[0], st0
[3], st1
[0], st1
[3]);
272 return pipe_user_buffer_create(ctx
->ctx
->screen
,
277 boolean
xorg_composite_accelerated(int op
,
278 PicturePtr pSrcPicture
,
279 PicturePtr pMaskPicture
,
280 PicturePtr pDstPicture
)
283 unsigned accel_ops_count
=
284 sizeof(accelerated_ops
)/sizeof(struct acceleration_info
);
287 /*FIXME: currently accel is disabled */
291 /* component alpha not supported */
292 if (pSrcPicture
->componentAlpha
)
294 /* fills not supported */
295 if (pSrcPicture
->pSourcePict
)
299 for (i
= 0; i
< accel_ops_count
; ++i
) {
300 if (op
== accelerated_ops
[i
].op
) {
301 if (pMaskPicture
&& !accelerated_ops
[i
].with_mask
)
310 bind_clip_state(struct exa_context
*exa
)
312 struct pipe_depth_stencil_alpha_state dsa
;
314 memset(&dsa
, 0, sizeof(struct pipe_depth_stencil_alpha_state
));
315 cso_set_depth_stencil_alpha(exa
->cso
, &dsa
);
319 bind_framebuffer_state(struct exa_context
*exa
, struct exa_pixmap_priv
*pDst
)
322 struct pipe_framebuffer_state state
;
323 struct pipe_surface
*surface
= exa_gpu_surface(exa
, pDst
);
324 memset(&state
, 0, sizeof(struct pipe_framebuffer_state
));
326 state
.width
= pDst
->tex
->width
[0];
327 state
.height
= pDst
->tex
->height
[0];
330 state
.cbufs
[0] = surface
;
331 for (i
= 1; i
< PIPE_MAX_COLOR_BUFS
; ++i
)
334 /* currently we don't use depth/stencil */
337 cso_set_framebuffer(exa
->cso
, &state
);
340 enum AxisOrientation
{
346 set_viewport(struct exa_context
*exa
, int width
, int height
,
347 enum AxisOrientation orientation
)
349 struct pipe_viewport_state viewport
;
350 float y_scale
= (orientation
== Y0_BOTTOM
) ? -2.f
: 2.f
;
352 viewport
.scale
[0] = width
/ 2.f
;
353 viewport
.scale
[1] = height
/ y_scale
;
354 viewport
.scale
[2] = 1.0;
355 viewport
.scale
[3] = 1.0;
356 viewport
.translate
[0] = width
/ 2.f
;
357 viewport
.translate
[1] = height
/ 2.f
;
358 viewport
.translate
[2] = 0.0;
359 viewport
.translate
[3] = 0.0;
361 cso_set_viewport(exa
->cso
, &viewport
);
365 bind_viewport_state(struct exa_context
*exa
, struct exa_pixmap_priv
*pDst
)
367 int width
= pDst
->tex
->width
[0];
368 int height
= pDst
->tex
->height
[0];
370 debug_printf("Bind viewport (%d, %d)\n", width
, height
);
372 set_viewport(exa
, width
, height
, Y0_TOP
);
376 bind_blend_state(struct exa_context
*exa
, int op
,
377 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
379 boolean component_alpha
= (pSrcPicture
) ?
380 pSrcPicture
->componentAlpha
: FALSE
;
381 struct xorg_composite_blend blend_opt
;
382 struct pipe_blend_state blend
;
384 if (component_alpha
) {
387 blend_opt
= blend_for_op(op
);
389 memset(&blend
, 0, sizeof(struct pipe_blend_state
));
390 blend
.blend_enable
= 1;
391 blend
.colormask
|= PIPE_MASK_R
;
392 blend
.colormask
|= PIPE_MASK_G
;
393 blend
.colormask
|= PIPE_MASK_B
;
394 blend
.colormask
|= PIPE_MASK_A
;
396 blend
.rgb_src_factor
= blend_opt
.rgb_src_factor
;
397 blend
.alpha_src_factor
= blend_opt
.alpha_src_factor
;
398 blend
.rgb_dst_factor
= blend_opt
.rgb_dst_factor
;
399 blend
.alpha_dst_factor
= blend_opt
.alpha_dst_factor
;
401 cso_set_blend(exa
->cso
, &blend
);
405 bind_rasterizer_state(struct exa_context
*exa
)
407 struct pipe_rasterizer_state raster
;
408 memset(&raster
, 0, sizeof(struct pipe_rasterizer_state
));
409 raster
.gl_rasterization_rules
= 1;
410 cso_set_rasterizer(exa
->cso
, &raster
);
414 bind_shaders(struct exa_context
*exa
, int op
,
415 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
417 unsigned vs_traits
= 0, fs_traits
= 0;
418 struct xorg_shader shader
;
420 exa
->has_solid_color
= FALSE
;
423 if (pSrcPicture
->pSourcePict
) {
424 if (pSrcPicture
->pSourcePict
->type
== SourcePictTypeSolidFill
) {
425 fs_traits
|= FS_SOLID_FILL
;
426 vs_traits
|= VS_SOLID_FILL
;
427 render_pixel_to_float4(pSrcPicture
->pFormat
,
428 pSrcPicture
->pSourcePict
->solidFill
.color
,
430 exa
->has_solid_color
= TRUE
;
432 debug_assert("!gradients not supported");
435 fs_traits
|= FS_COMPOSITE
;
436 vs_traits
|= VS_COMPOSITE
;
441 vs_traits
|= VS_MASK
;
442 fs_traits
|= FS_MASK
;
445 shader
= xorg_shaders_get(exa
->shaders
, vs_traits
, fs_traits
);
446 cso_set_vertex_shader_handle(exa
->cso
, shader
.vs
);
447 cso_set_fragment_shader_handle(exa
->cso
, shader
.fs
);
452 bind_samplers(struct exa_context
*exa
, int op
,
453 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
,
454 PicturePtr pDstPicture
,
455 struct exa_pixmap_priv
*pSrc
,
456 struct exa_pixmap_priv
*pMask
,
457 struct exa_pixmap_priv
*pDst
)
459 struct pipe_sampler_state
*samplers
[PIPE_MAX_SAMPLERS
];
460 struct pipe_sampler_state src_sampler
, mask_sampler
;
462 exa
->num_bound_samplers
= 0;
464 memset(&src_sampler
, 0, sizeof(struct pipe_sampler_state
));
465 memset(&mask_sampler
, 0, sizeof(struct pipe_sampler_state
));
467 if (pSrcPicture
&& pSrc
) {
468 unsigned src_wrap
= render_repeat_to_gallium(
469 pSrcPicture
->repeatType
);
470 src_sampler
.wrap_s
= src_wrap
;
471 src_sampler
.wrap_t
= src_wrap
;
472 src_sampler
.min_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
473 src_sampler
.mag_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
474 src_sampler
.normalized_coords
= 1;
475 samplers
[0] = &src_sampler
;
476 exa
->bound_textures
[0] = pSrc
->tex
;
477 ++exa
->num_bound_samplers
;
480 if (pMaskPicture
&& pMask
) {
481 unsigned mask_wrap
= render_repeat_to_gallium(
482 pMaskPicture
->repeatType
);
483 mask_sampler
.wrap_s
= mask_wrap
;
484 mask_sampler
.wrap_t
= mask_wrap
;
485 mask_sampler
.min_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
486 mask_sampler
.mag_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
487 mask_sampler
.normalized_coords
= 1;
488 samplers
[1] = &mask_sampler
;
489 exa
->bound_textures
[1] = pMask
->tex
;
490 ++exa
->num_bound_samplers
;
493 cso_set_samplers(exa
->cso
, exa
->num_bound_samplers
,
494 (const struct pipe_sampler_state
**)samplers
);
495 cso_set_sampler_textures(exa
->cso
, exa
->num_bound_samplers
,
496 exa
->bound_textures
);
500 setup_vs_constant_buffer(struct exa_context
*exa
,
501 int width
, int height
)
503 const int param_bytes
= 8 * sizeof(float);
504 float vs_consts
[8] = {
505 2.f
/width
, 2.f
/height
, 1, 1,
508 struct pipe_constant_buffer
*cbuf
= &exa
->vs_const_buffer
;
510 pipe_buffer_reference(&cbuf
->buffer
, NULL
);
511 cbuf
->buffer
= pipe_buffer_create(exa
->ctx
->screen
, 16,
512 PIPE_BUFFER_USAGE_CONSTANT
,
516 pipe_buffer_write(exa
->ctx
->screen
, cbuf
->buffer
,
517 0, param_bytes
, vs_consts
);
519 exa
->ctx
->set_constant_buffer(exa
->ctx
, PIPE_SHADER_VERTEX
, 0, cbuf
);
524 setup_fs_constant_buffer(struct exa_context
*exa
)
526 const int param_bytes
= 4 * sizeof(float);
527 float fs_consts
[8] = {
530 struct pipe_constant_buffer
*cbuf
= &exa
->fs_const_buffer
;
532 pipe_buffer_reference(&cbuf
->buffer
, NULL
);
533 cbuf
->buffer
= pipe_buffer_create(exa
->ctx
->screen
, 16,
534 PIPE_BUFFER_USAGE_CONSTANT
,
538 pipe_buffer_write(exa
->ctx
->screen
, cbuf
->buffer
,
539 0, param_bytes
, fs_consts
);
541 exa
->ctx
->set_constant_buffer(exa
->ctx
, PIPE_SHADER_FRAGMENT
, 0, cbuf
);
545 setup_constant_buffers(struct exa_context
*exa
, struct exa_pixmap_priv
*pDst
)
547 int width
= pDst
->tex
->width
[0];
548 int height
= pDst
->tex
->height
[0];
550 setup_vs_constant_buffer(exa
, width
, height
);
551 setup_fs_constant_buffer(exa
);
554 boolean
xorg_composite_bind_state(struct exa_context
*exa
,
556 PicturePtr pSrcPicture
,
557 PicturePtr pMaskPicture
,
558 PicturePtr pDstPicture
,
559 struct exa_pixmap_priv
*pSrc
,
560 struct exa_pixmap_priv
*pMask
,
561 struct exa_pixmap_priv
*pDst
)
563 bind_framebuffer_state(exa
, pDst
);
564 bind_viewport_state(exa
, pDst
);
565 bind_blend_state(exa
, op
, pSrcPicture
, pMaskPicture
);
566 bind_rasterizer_state(exa
);
567 bind_shaders(exa
, op
, pSrcPicture
, pMaskPicture
);
568 bind_samplers(exa
, op
, pSrcPicture
, pMaskPicture
,
569 pDstPicture
, pSrc
, pMask
, pDst
);
570 bind_clip_state(exa
);
571 setup_constant_buffers(exa
, pDst
);
576 void xorg_composite(struct exa_context
*exa
,
577 struct exa_pixmap_priv
*dst
,
578 int srcX
, int srcY
, int maskX
, int maskY
,
579 int dstX
, int dstY
, int width
, int height
)
581 struct pipe_context
*pipe
= exa
->ctx
;
582 struct pipe_buffer
*buf
= 0;
584 if (exa
->num_bound_samplers
== 0 ) { /* solid fill */
585 buf
= setup_vertex_data0(exa
,
586 srcX
, srcY
, maskX
, maskY
,
587 dstX
, dstY
, width
, height
);
588 } else if (exa
->num_bound_samplers
== 1 ) /* src */
589 buf
= setup_vertex_data1(exa
,
590 srcX
, srcY
, maskX
, maskY
,
591 dstX
, dstY
, width
, height
);
592 else if (exa
->num_bound_samplers
== 2) /* src + mask */
593 buf
= setup_vertex_data2(exa
,
594 srcX
, srcY
, maskX
, maskY
,
595 dstX
, dstY
, width
, height
);
596 else if (exa
->num_bound_samplers
== 3) { /* src + mask + dst */
597 debug_assert(!"src/mask/dst not handled right now");
599 buf
= setup_vertex_data2(exa
,
600 srcX
, srcY
, maskX
, maskY
,
601 dstX
, dstY
, width
, height
);
606 int num_attribs
= 1; /*pos*/
607 num_attribs
+= exa
->num_bound_samplers
;
608 if (exa
->has_solid_color
)
611 util_draw_vertex_buffer(pipe
, buf
, 0,
612 PIPE_PRIM_TRIANGLE_FAN
,
614 num_attribs
); /* attribs/vert */
616 pipe_buffer_reference(&buf
, NULL
);
620 boolean
xorg_solid_bind_state(struct exa_context
*exa
,
621 struct exa_pixmap_priv
*pixmap
,
624 unsigned vs_traits
, fs_traits
;
625 struct xorg_shader shader
;
627 pixel_to_float4(fg
, exa
->solid_color
);
628 exa
->has_solid_color
= TRUE
;
630 exa
->solid_color
[3] = 1.f
;
632 debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
633 (fg
>> 24) & 0xff, (fg
>> 16) & 0xff,
634 (fg
>> 8) & 0xff, (fg
>> 0) & 0xff,
635 exa
->solid_color
[0], exa
->solid_color
[1],
636 exa
->solid_color
[2], exa
->solid_color
[3]);
639 exa
->solid_color
[0] = 1.f
;
640 exa
->solid_color
[1] = 0.f
;
641 exa
->solid_color
[2] = 0.f
;
642 exa
->solid_color
[3] = 1.f
;
645 vs_traits
= VS_SOLID_FILL
;
646 fs_traits
= FS_SOLID_FILL
;
648 bind_framebuffer_state(exa
, pixmap
);
649 bind_viewport_state(exa
, pixmap
);
650 bind_rasterizer_state(exa
);
651 bind_blend_state(exa
, PictOpSrc
, NULL
, NULL
);
652 setup_constant_buffers(exa
, pixmap
);
653 bind_clip_state(exa
);
655 shader
= xorg_shaders_get(exa
->shaders
, vs_traits
, fs_traits
);
656 cso_set_vertex_shader_handle(exa
->cso
, shader
.vs
);
657 cso_set_fragment_shader_handle(exa
->cso
, shader
.fs
);
662 void xorg_solid(struct exa_context
*exa
,
663 struct exa_pixmap_priv
*pixmap
,
664 int x0
, int y0
, int x1
, int y1
)
666 struct pipe_context
*pipe
= exa
->ctx
;
667 struct pipe_buffer
*buf
= 0;
668 float vertices
[4][2][4];
674 setup_vertex0(vertices
[0], x0
, y0
,
677 setup_vertex0(vertices
[1], x1
, y0
,
680 setup_vertex0(vertices
[2], x1
, y1
,
683 setup_vertex0(vertices
[3], x0
, y1
,
686 buf
= pipe_user_buffer_create(exa
->ctx
->screen
,
692 debug_printf("Drawing buf is %p\n", buf
);
693 util_draw_vertex_buffer(pipe
, buf
, 0,
694 PIPE_PRIM_TRIANGLE_FAN
,
696 2); /* attribs/vert */
698 pipe_buffer_reference(&buf
, NULL
);
702 void xorg_copy_pixmap(struct exa_context
*ctx
,
703 struct exa_pixmap_priv
*dst
, int dx
, int dy
,
704 struct exa_pixmap_priv
*src
, int sx
, int sy
,
705 int width
, int height
)