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"
7 #include "util/u_math.h"
9 #include "pipe/p_inlines.h"
11 struct xorg_composite_blend
{
14 unsigned rgb_src_factor
:5; /**< PIPE_BLENDFACTOR_x */
15 unsigned alpha_src_factor
:5; /**< PIPE_BLENDFACTOR_x */
17 unsigned rgb_dst_factor
:5; /**< PIPE_BLENDFACTOR_x */
18 unsigned alpha_dst_factor
:5; /**< PIPE_BLENDFACTOR_x */
21 #define BLEND_OP_OVER 3
22 static const struct xorg_composite_blend xorg_blends
[] = {
24 PIPE_BLENDFACTOR_CONST_COLOR
, PIPE_BLENDFACTOR_CONST_ALPHA
,
25 PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_ZERO
},
28 PIPE_BLENDFACTOR_ONE
, PIPE_BLENDFACTOR_ONE
,
29 PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_ZERO
},
32 PIPE_BLENDFACTOR_ZERO
, PIPE_BLENDFACTOR_ZERO
,
33 PIPE_BLENDFACTOR_ONE
, PIPE_BLENDFACTOR_ONE
},
36 PIPE_BLENDFACTOR_SRC_ALPHA
, PIPE_BLENDFACTOR_ONE
,
37 PIPE_BLENDFACTOR_INV_SRC_ALPHA
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
40 PIPE_BLENDFACTOR_SRC_ALPHA
, PIPE_BLENDFACTOR_ONE
,
41 PIPE_BLENDFACTOR_INV_SRC_ALPHA
, PIPE_BLENDFACTOR_INV_SRC_ALPHA
},
46 pixel_to_float4(Pixel pixel
, float *color
)
50 a
= (pixel
>> 24) & 0xff;
51 r
= (pixel
>> 16) & 0xff;
52 g
= (pixel
>> 8) & 0xff;
53 b
= (pixel
>> 0) & 0xff;
54 color
[0] = ((float)r
) / 255.;
55 color
[1] = ((float)g
) / 255.;
56 color
[2] = ((float)b
) / 255.;
57 color
[3] = ((float)a
) / 255.;
61 render_pixel_to_float4(PictFormatPtr format
,
62 CARD32 pixel
, float *color
)
66 debug_assert(format
->type
== PictTypeDirect
);
68 r
= (pixel
>> format
->direct
.red
) & format
->direct
.redMask
;
69 g
= (pixel
>> format
->direct
.green
) & format
->direct
.greenMask
;
70 b
= (pixel
>> format
->direct
.blue
) & format
->direct
.blueMask
;
71 a
= (pixel
>> format
->direct
.alpha
) & format
->direct
.alphaMask
;
72 color
[0] = ((float)r
) / ((float)format
->direct
.redMask
);
73 color
[1] = ((float)g
) / ((float)format
->direct
.greenMask
);
74 color
[2] = ((float)b
) / ((float)format
->direct
.blueMask
);
75 color
[3] = ((float)a
) / ((float)format
->direct
.alphaMask
);
78 struct acceleration_info
{
81 int component_alpha
: 1;
83 static const struct acceleration_info accelerated_ops
[] = {
88 {PictOpOverReverse
, 1, 0},
90 {PictOpInReverse
, 1, 0},
92 {PictOpOutReverse
, 1, 0},
94 {PictOpAtopReverse
, 1, 0},
97 {PictOpSaturate
, 1, 0},
100 static struct xorg_composite_blend
103 const int num_blends
=
104 sizeof(xorg_blends
)/sizeof(struct xorg_composite_blend
);
107 for (i
= 0; i
< num_blends
; ++i
) {
108 if (xorg_blends
[i
].op
== op
)
109 return xorg_blends
[i
];
111 return xorg_blends
[BLEND_OP_OVER
];
115 render_repeat_to_gallium(int mode
)
119 return PIPE_TEX_WRAP_CLAMP
;
121 return PIPE_TEX_WRAP_REPEAT
;
123 return PIPE_TEX_WRAP_MIRROR_REPEAT
;
125 return PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
127 debug_printf("Unsupported repeat mode\n");
129 return PIPE_TEX_WRAP_REPEAT
;
134 setup_vertex0(float vertex
[2][4], float x
, float y
,
139 vertex
[0][2] = 0.f
; /*z*/
140 vertex
[0][3] = 1.f
; /*w*/
142 vertex
[1][0] = color
[0]; /*r*/
143 vertex
[1][1] = color
[1]; /*g*/
144 vertex
[1][2] = color
[2]; /*b*/
145 vertex
[1][3] = color
[3]; /*a*/
148 static struct pipe_buffer
*
149 setup_vertex_data0(struct exa_context
*ctx
,
150 int srcX
, int srcY
, int maskX
, int maskY
,
151 int dstX
, int dstY
, int width
, int height
)
154 setup_vertex0(ctx
->vertices2
[0], dstX
, dstY
,
157 setup_vertex0(ctx
->vertices2
[1], dstX
+ width
, dstY
,
160 setup_vertex0(ctx
->vertices2
[2], dstX
+ width
, dstY
+ height
,
163 setup_vertex0(ctx
->vertices2
[3], dstX
, dstY
+ height
,
166 return pipe_user_buffer_create(ctx
->pipe
->screen
,
168 sizeof(ctx
->vertices2
));
172 setup_vertex1(float vertex
[2][4], float x
, float y
, float s
, float t
)
176 vertex
[0][2] = 0.f
; /*z*/
177 vertex
[0][3] = 1.f
; /*w*/
179 vertex
[1][0] = s
; /*s*/
180 vertex
[1][1] = t
; /*t*/
181 vertex
[1][2] = 0.f
; /*r*/
182 vertex
[1][3] = 1.f
; /*q*/
185 static struct pipe_buffer
*
186 setup_vertex_data1(struct exa_context
*ctx
,
187 int srcX
, int srcY
, int maskX
, int maskY
,
188 int dstX
, int dstY
, int width
, int height
)
190 float s0
, t0
, s1
, t1
;
191 struct pipe_texture
*src
= ctx
->bound_textures
[0];
193 s0
= srcX
/ src
->width
[0];
194 s1
= srcX
+ width
/ src
->width
[0];
195 t0
= srcY
/ src
->height
[0];
196 t1
= srcY
+ height
/ src
->height
[0];
199 setup_vertex1(ctx
->vertices2
[0], dstX
, dstY
,
202 setup_vertex1(ctx
->vertices2
[1], dstX
+ width
, dstY
,
205 setup_vertex1(ctx
->vertices2
[2], dstX
+ width
, dstY
+ height
,
208 setup_vertex1(ctx
->vertices2
[3], dstX
, dstY
+ height
,
211 return pipe_user_buffer_create(ctx
->pipe
->screen
,
213 sizeof(ctx
->vertices2
));
216 static struct pipe_buffer
*
217 setup_vertex_data_tex(struct exa_context
*ctx
,
218 float x0
, float y0
, float x1
, float y1
,
219 float s0
, float t0
, float s1
, float t1
,
223 setup_vertex1(ctx
->vertices2
[0], x0
, y0
,
226 setup_vertex1(ctx
->vertices2
[1], x1
, y0
,
229 setup_vertex1(ctx
->vertices2
[2], x1
, y1
,
232 setup_vertex1(ctx
->vertices2
[3], x0
, y1
,
235 return pipe_user_buffer_create(ctx
->pipe
->screen
,
237 sizeof(ctx
->vertices2
));
243 setup_vertex2(float vertex
[3][4], float x
, float y
,
244 float s0
, float t0
, float s1
, float t1
)
248 vertex
[0][2] = 0.f
; /*z*/
249 vertex
[0][3] = 1.f
; /*w*/
251 vertex
[1][0] = s0
; /*s*/
252 vertex
[1][1] = t0
; /*t*/
253 vertex
[1][2] = 0.f
; /*r*/
254 vertex
[1][3] = 1.f
; /*q*/
256 vertex
[2][0] = s1
; /*s*/
257 vertex
[2][1] = t1
; /*t*/
258 vertex
[2][2] = 0.f
; /*r*/
259 vertex
[2][3] = 1.f
; /*q*/
262 static struct pipe_buffer
*
263 setup_vertex_data2(struct exa_context
*ctx
,
264 int srcX
, int srcY
, int maskX
, int maskY
,
265 int dstX
, int dstY
, int width
, int height
)
267 float st0
[4], st1
[4];
268 struct pipe_texture
*src
= ctx
->bound_textures
[0];
269 struct pipe_texture
*mask
= ctx
->bound_textures
[0];
271 st0
[0] = srcX
/ src
->width
[0];
272 st0
[1] = srcY
/ src
->height
[0];
273 st0
[2] = srcX
+ width
/ src
->width
[0];
274 st0
[3] = srcY
+ height
/ src
->height
[0];
276 st1
[0] = maskX
/ mask
->width
[0];
277 st1
[1] = maskY
/ mask
->height
[0];
278 st1
[2] = maskX
+ width
/ mask
->width
[0];
279 st1
[3] = maskY
+ height
/ mask
->height
[0];
282 setup_vertex2(ctx
->vertices3
[0], dstX
, dstY
,
283 st0
[0], st0
[1], st1
[0], st1
[1]);
285 setup_vertex2(ctx
->vertices3
[1], dstX
+ width
, dstY
,
286 st0
[2], st0
[1], st1
[2], st1
[1]);
288 setup_vertex2(ctx
->vertices3
[2], dstX
+ width
, dstY
+ height
,
289 st0
[2], st0
[3], st1
[2], st1
[3]);
291 setup_vertex2(ctx
->vertices3
[3], dstX
, dstY
+ height
,
292 st0
[0], st0
[3], st1
[0], st1
[3]);
294 return pipe_user_buffer_create(ctx
->pipe
->screen
,
296 sizeof(ctx
->vertices3
));
299 boolean
xorg_composite_accelerated(int op
,
300 PicturePtr pSrcPicture
,
301 PicturePtr pMaskPicture
,
302 PicturePtr pDstPicture
)
305 unsigned accel_ops_count
=
306 sizeof(accelerated_ops
)/sizeof(struct acceleration_info
);
309 /*FIXME: currently accel is disabled */
313 /* component alpha not supported */
314 if (pSrcPicture
->componentAlpha
)
316 /* fills not supported */
317 if (pSrcPicture
->pSourcePict
)
321 for (i
= 0; i
< accel_ops_count
; ++i
) {
322 if (op
== accelerated_ops
[i
].op
) {
323 if (pMaskPicture
&& !accelerated_ops
[i
].with_mask
)
332 bind_clip_state(struct exa_context
*exa
)
337 bind_framebuffer_state(struct exa_context
*exa
, struct exa_pixmap_priv
*pDst
)
340 struct pipe_framebuffer_state state
;
341 struct pipe_surface
*surface
= exa_gpu_surface(exa
, pDst
);
342 memset(&state
, 0, sizeof(struct pipe_framebuffer_state
));
344 state
.width
= pDst
->tex
->width
[0];
345 state
.height
= pDst
->tex
->height
[0];
348 state
.cbufs
[0] = surface
;
349 for (i
= 1; i
< PIPE_MAX_COLOR_BUFS
; ++i
)
352 /* currently we don't use depth/stencil */
355 cso_set_framebuffer(exa
->cso
, &state
);
357 /* we do fire and forget for the framebuffer, this is the forget part */
358 pipe_surface_reference(&surface
, NULL
);
361 enum AxisOrientation
{
367 set_viewport(struct exa_context
*exa
, int width
, int height
,
368 enum AxisOrientation orientation
)
370 struct pipe_viewport_state viewport
;
371 float y_scale
= (orientation
== Y0_BOTTOM
) ? -2.f
: 2.f
;
373 viewport
.scale
[0] = width
/ 2.f
;
374 viewport
.scale
[1] = height
/ y_scale
;
375 viewport
.scale
[2] = 1.0;
376 viewport
.scale
[3] = 1.0;
377 viewport
.translate
[0] = width
/ 2.f
;
378 viewport
.translate
[1] = height
/ 2.f
;
379 viewport
.translate
[2] = 0.0;
380 viewport
.translate
[3] = 0.0;
382 cso_set_viewport(exa
->cso
, &viewport
);
386 bind_viewport_state(struct exa_context
*exa
, struct exa_pixmap_priv
*pDst
)
388 int width
= pDst
->tex
->width
[0];
389 int height
= pDst
->tex
->height
[0];
391 debug_printf("Bind viewport (%d, %d)\n", width
, height
);
393 set_viewport(exa
, width
, height
, Y0_TOP
);
397 bind_blend_state(struct exa_context
*exa
, int op
,
398 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
400 boolean component_alpha
= (pSrcPicture
) ?
401 pSrcPicture
->componentAlpha
: FALSE
;
402 struct xorg_composite_blend blend_opt
;
403 struct pipe_blend_state blend
;
405 if (component_alpha
) {
408 blend_opt
= blend_for_op(op
);
410 memset(&blend
, 0, sizeof(struct pipe_blend_state
));
411 blend
.blend_enable
= 1;
412 blend
.colormask
|= PIPE_MASK_R
;
413 blend
.colormask
|= PIPE_MASK_G
;
414 blend
.colormask
|= PIPE_MASK_B
;
415 blend
.colormask
|= PIPE_MASK_A
;
417 blend
.rgb_src_factor
= blend_opt
.rgb_src_factor
;
418 blend
.alpha_src_factor
= blend_opt
.alpha_src_factor
;
419 blend
.rgb_dst_factor
= blend_opt
.rgb_dst_factor
;
420 blend
.alpha_dst_factor
= blend_opt
.alpha_dst_factor
;
422 cso_set_blend(exa
->cso
, &blend
);
426 bind_rasterizer_state(struct exa_context
*exa
)
428 struct pipe_rasterizer_state raster
;
429 memset(&raster
, 0, sizeof(struct pipe_rasterizer_state
));
430 raster
.gl_rasterization_rules
= 1;
431 cso_set_rasterizer(exa
->cso
, &raster
);
435 bind_shaders(struct exa_context
*exa
, int op
,
436 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
438 unsigned vs_traits
= 0, fs_traits
= 0;
439 struct xorg_shader shader
;
441 exa
->has_solid_color
= FALSE
;
444 if (pSrcPicture
->pSourcePict
) {
445 if (pSrcPicture
->pSourcePict
->type
== SourcePictTypeSolidFill
) {
446 fs_traits
|= FS_SOLID_FILL
;
447 vs_traits
|= VS_SOLID_FILL
;
448 render_pixel_to_float4(pSrcPicture
->pFormat
,
449 pSrcPicture
->pSourcePict
->solidFill
.color
,
451 exa
->has_solid_color
= TRUE
;
453 debug_assert("!gradients not supported");
456 fs_traits
|= FS_COMPOSITE
;
457 vs_traits
|= VS_COMPOSITE
;
462 vs_traits
|= VS_MASK
;
463 fs_traits
|= FS_MASK
;
466 shader
= xorg_shaders_get(exa
->shaders
, vs_traits
, fs_traits
);
467 cso_set_vertex_shader_handle(exa
->cso
, shader
.vs
);
468 cso_set_fragment_shader_handle(exa
->cso
, shader
.fs
);
473 bind_samplers(struct exa_context
*exa
, int op
,
474 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
,
475 PicturePtr pDstPicture
,
476 struct exa_pixmap_priv
*pSrc
,
477 struct exa_pixmap_priv
*pMask
,
478 struct exa_pixmap_priv
*pDst
)
480 struct pipe_sampler_state
*samplers
[PIPE_MAX_SAMPLERS
];
481 struct pipe_sampler_state src_sampler
, mask_sampler
;
483 exa
->num_bound_samplers
= 0;
485 memset(&src_sampler
, 0, sizeof(struct pipe_sampler_state
));
486 memset(&mask_sampler
, 0, sizeof(struct pipe_sampler_state
));
488 if (pSrcPicture
&& pSrc
) {
489 unsigned src_wrap
= render_repeat_to_gallium(
490 pSrcPicture
->repeatType
);
491 src_sampler
.wrap_s
= src_wrap
;
492 src_sampler
.wrap_t
= src_wrap
;
493 src_sampler
.min_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
494 src_sampler
.mag_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
495 src_sampler
.normalized_coords
= 1;
496 samplers
[0] = &src_sampler
;
497 exa
->bound_textures
[0] = pSrc
->tex
;
498 ++exa
->num_bound_samplers
;
501 if (pMaskPicture
&& pMask
) {
502 unsigned mask_wrap
= render_repeat_to_gallium(
503 pMaskPicture
->repeatType
);
504 mask_sampler
.wrap_s
= mask_wrap
;
505 mask_sampler
.wrap_t
= mask_wrap
;
506 mask_sampler
.min_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
507 mask_sampler
.mag_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
508 mask_sampler
.normalized_coords
= 1;
509 samplers
[1] = &mask_sampler
;
510 exa
->bound_textures
[1] = pMask
->tex
;
511 ++exa
->num_bound_samplers
;
514 cso_set_samplers(exa
->cso
, exa
->num_bound_samplers
,
515 (const struct pipe_sampler_state
**)samplers
);
516 cso_set_sampler_textures(exa
->cso
, exa
->num_bound_samplers
,
517 exa
->bound_textures
);
521 setup_vs_constant_buffer(struct exa_context
*exa
,
522 int width
, int height
)
524 const int param_bytes
= 8 * sizeof(float);
525 float vs_consts
[8] = {
526 2.f
/width
, 2.f
/height
, 1, 1,
529 struct pipe_constant_buffer
*cbuf
= &exa
->vs_const_buffer
;
531 pipe_buffer_reference(&cbuf
->buffer
, NULL
);
532 cbuf
->buffer
= pipe_buffer_create(exa
->pipe
->screen
, 16,
533 PIPE_BUFFER_USAGE_CONSTANT
,
537 pipe_buffer_write(exa
->pipe
->screen
, cbuf
->buffer
,
538 0, param_bytes
, vs_consts
);
540 exa
->pipe
->set_constant_buffer(exa
->pipe
, PIPE_SHADER_VERTEX
, 0, cbuf
);
545 setup_fs_constant_buffer(struct exa_context
*exa
)
547 const int param_bytes
= 4 * sizeof(float);
548 float fs_consts
[8] = {
551 struct pipe_constant_buffer
*cbuf
= &exa
->fs_const_buffer
;
553 pipe_buffer_reference(&cbuf
->buffer
, NULL
);
554 cbuf
->buffer
= pipe_buffer_create(exa
->pipe
->screen
, 16,
555 PIPE_BUFFER_USAGE_CONSTANT
,
559 pipe_buffer_write(exa
->pipe
->screen
, cbuf
->buffer
,
560 0, param_bytes
, fs_consts
);
562 exa
->pipe
->set_constant_buffer(exa
->pipe
, PIPE_SHADER_FRAGMENT
, 0, cbuf
);
566 setup_constant_buffers(struct exa_context
*exa
, struct exa_pixmap_priv
*pDst
)
568 int width
= pDst
->tex
->width
[0];
569 int height
= pDst
->tex
->height
[0];
571 setup_vs_constant_buffer(exa
, width
, height
);
572 setup_fs_constant_buffer(exa
);
575 boolean
xorg_composite_bind_state(struct exa_context
*exa
,
577 PicturePtr pSrcPicture
,
578 PicturePtr pMaskPicture
,
579 PicturePtr pDstPicture
,
580 struct exa_pixmap_priv
*pSrc
,
581 struct exa_pixmap_priv
*pMask
,
582 struct exa_pixmap_priv
*pDst
)
584 bind_framebuffer_state(exa
, pDst
);
585 bind_viewport_state(exa
, pDst
);
586 bind_blend_state(exa
, op
, pSrcPicture
, pMaskPicture
);
587 bind_rasterizer_state(exa
);
588 bind_shaders(exa
, op
, pSrcPicture
, pMaskPicture
);
589 bind_samplers(exa
, op
, pSrcPicture
, pMaskPicture
,
590 pDstPicture
, pSrc
, pMask
, pDst
);
591 bind_clip_state(exa
);
592 setup_constant_buffers(exa
, pDst
);
597 void xorg_composite(struct exa_context
*exa
,
598 struct exa_pixmap_priv
*dst
,
599 int srcX
, int srcY
, int maskX
, int maskY
,
600 int dstX
, int dstY
, int width
, int height
)
602 struct pipe_context
*pipe
= exa
->pipe
;
603 struct pipe_buffer
*buf
= 0;
605 if (exa
->num_bound_samplers
== 0 ) { /* solid fill */
606 buf
= setup_vertex_data0(exa
,
607 srcX
, srcY
, maskX
, maskY
,
608 dstX
, dstY
, width
, height
);
609 } else if (exa
->num_bound_samplers
== 1 ) /* src */
610 buf
= setup_vertex_data1(exa
,
611 srcX
, srcY
, maskX
, maskY
,
612 dstX
, dstY
, width
, height
);
613 else if (exa
->num_bound_samplers
== 2) /* src + mask */
614 buf
= setup_vertex_data2(exa
,
615 srcX
, srcY
, maskX
, maskY
,
616 dstX
, dstY
, width
, height
);
617 else if (exa
->num_bound_samplers
== 3) { /* src + mask + dst */
618 debug_assert(!"src/mask/dst not handled right now");
620 buf
= setup_vertex_data2(exa
,
621 srcX
, srcY
, maskX
, maskY
,
622 dstX
, dstY
, width
, height
);
627 int num_attribs
= 1; /*pos*/
628 num_attribs
+= exa
->num_bound_samplers
;
629 if (exa
->has_solid_color
)
632 util_draw_vertex_buffer(pipe
, buf
, 0,
633 PIPE_PRIM_TRIANGLE_FAN
,
635 num_attribs
); /* attribs/vert */
637 pipe_buffer_reference(&buf
, NULL
);
641 boolean
xorg_solid_bind_state(struct exa_context
*exa
,
642 struct exa_pixmap_priv
*pixmap
,
645 unsigned vs_traits
, fs_traits
;
646 struct xorg_shader shader
;
648 pixel_to_float4(fg
, exa
->solid_color
);
649 exa
->has_solid_color
= TRUE
;
651 exa
->solid_color
[3] = 1.f
;
654 debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
655 (fg
>> 24) & 0xff, (fg
>> 16) & 0xff,
656 (fg
>> 8) & 0xff, (fg
>> 0) & 0xff,
657 exa
->solid_color
[0], exa
->solid_color
[1],
658 exa
->solid_color
[2], exa
->solid_color
[3]);
661 vs_traits
= VS_SOLID_FILL
;
662 fs_traits
= FS_SOLID_FILL
;
664 bind_framebuffer_state(exa
, pixmap
);
665 bind_viewport_state(exa
, pixmap
);
666 bind_rasterizer_state(exa
);
667 bind_blend_state(exa
, PictOpSrc
, NULL
, NULL
);
668 setup_constant_buffers(exa
, pixmap
);
669 bind_clip_state(exa
);
671 shader
= xorg_shaders_get(exa
->shaders
, vs_traits
, fs_traits
);
672 cso_set_vertex_shader_handle(exa
->cso
, shader
.vs
);
673 cso_set_fragment_shader_handle(exa
->cso
, shader
.fs
);
678 void xorg_solid(struct exa_context
*exa
,
679 struct exa_pixmap_priv
*pixmap
,
680 int x0
, int y0
, int x1
, int y1
)
682 struct pipe_context
*pipe
= exa
->pipe
;
683 struct pipe_buffer
*buf
= 0;
686 setup_vertex0(exa
->vertices2
[0], x0
, y0
,
689 setup_vertex0(exa
->vertices2
[1], x1
, y0
,
692 setup_vertex0(exa
->vertices2
[2], x1
, y1
,
695 setup_vertex0(exa
->vertices2
[3], x0
, y1
,
698 buf
= pipe_user_buffer_create(exa
->pipe
->screen
,
700 sizeof(exa
->vertices2
));
704 debug_printf("Drawing buf is %p\n", buf
);
705 util_draw_vertex_buffer(pipe
, buf
, 0,
706 PIPE_PRIM_TRIANGLE_FAN
,
708 2); /* attribs/vert */
710 pipe_buffer_reference(&buf
, NULL
);
715 static INLINE
void shift_rectx(float coords
[4],
722 coords
[2] = MIN2(coords
[2], bounds
[2]);
723 /* bound x/y + width/height */
724 if ((coords
[0] + coords
[2]) > (bounds
[0] + bounds
[2])) {
725 coords
[2] = (bounds
[0] + bounds
[2]) - coords
[0];
730 static INLINE
void shift_recty(float coords
[4],
737 coords
[3] = MIN2(coords
[3], bounds
[3]);
738 if ((coords
[1] + coords
[3]) > (bounds
[1] + bounds
[3])) {
739 coords
[3] = (bounds
[1] + bounds
[3]) - coords
[1];
744 static INLINE
void bound_rect(float coords
[4],
745 const float bounds
[4],
748 /* if outside the bounds */
749 if (coords
[0] > (bounds
[0] + bounds
[2]) ||
750 coords
[1] > (bounds
[1] + bounds
[3]) ||
751 (coords
[0] + coords
[2]) < bounds
[0] ||
752 (coords
[1] + coords
[3]) < bounds
[1]) {
763 if (coords
[0] < bounds
[0]) {
764 shift
[0] = bounds
[0] - coords
[0];
765 coords
[2] -= shift
[0];
766 coords
[0] = bounds
[0];
771 if (coords
[1] < bounds
[1]) {
772 shift
[1] = bounds
[1] - coords
[1];
773 coords
[3] -= shift
[1];
774 coords
[1] = bounds
[1];
778 shift
[2] = bounds
[2] - coords
[2];
779 shift
[3] = bounds
[3] - coords
[3];
780 /* bound width/height */
781 coords
[2] = MIN2(coords
[2], bounds
[2]);
782 coords
[3] = MIN2(coords
[3], bounds
[3]);
784 /* bound x/y + width/height */
785 if ((coords
[0] + coords
[2]) > (bounds
[0] + bounds
[2])) {
786 coords
[2] = (bounds
[0] + bounds
[2]) - coords
[0];
788 if ((coords
[1] + coords
[3]) > (bounds
[1] + bounds
[3])) {
789 coords
[3] = (bounds
[1] + bounds
[3]) - coords
[1];
792 /* if outside the bounds */
793 if ((coords
[0] + coords
[2]) < bounds
[0] ||
794 (coords
[1] + coords
[3]) < bounds
[1]) {
803 static INLINE
void sync_size(float *src_loc
, float *dst_loc
)
805 src_loc
[2] = MIN2(src_loc
[2], dst_loc
[2]);
806 src_loc
[3] = MIN2(src_loc
[3], dst_loc
[3]);
807 dst_loc
[2] = src_loc
[2];
808 dst_loc
[3] = src_loc
[3];
812 static void renderer_copy_texture(struct exa_context
*exa
,
813 struct pipe_texture
*src
,
814 float sx1
, float sy1
,
815 float sx2
, float sy2
,
816 struct pipe_texture
*dst
,
817 float dx1
, float dy1
,
818 float dx2
, float dy2
)
820 struct pipe_context
*pipe
= exa
->pipe
;
821 struct pipe_screen
*screen
= pipe
->screen
;
822 struct pipe_buffer
*buf
;
823 struct pipe_surface
*dst_surf
= screen
->get_tex_surface(
824 screen
, dst
, 0, 0, 0,
825 PIPE_BUFFER_USAGE_GPU_WRITE
);
826 struct pipe_framebuffer_state fb
;
827 float s0
, t0
, s1
, t1
;
828 struct xorg_shader shader
;
830 assert(src
->width
[0] != 0);
831 assert(src
->height
[0] != 0);
832 assert(dst
->width
[0] != 0);
833 assert(dst
->height
[0] != 0);
836 s0
= sx1
/ src
->width
[0];
837 s1
= sx2
/ src
->width
[0];
838 t0
= sy1
/ src
->height
[0];
839 t1
= sy2
/ src
->height
[0];
848 debug_printf("copy texture src=[%f, %f, %f, %f], dst=[%f, %f, %f, %f], tex=[%f, %f, %f, %f]\n",
849 sx1
, sy1
, sx2
, sy2
, dx1
, dy1
, dx2
, dy2
,
853 assert(screen
->is_format_supported(screen
, dst_surf
->format
,
855 PIPE_TEXTURE_USAGE_RENDER_TARGET
,
858 /* save state (restored below) */
859 cso_save_blend(exa
->cso
);
860 cso_save_samplers(exa
->cso
);
861 cso_save_sampler_textures(exa
->cso
);
862 cso_save_framebuffer(exa
->cso
);
863 cso_save_fragment_shader(exa
->cso
);
864 cso_save_vertex_shader(exa
->cso
);
866 cso_save_viewport(exa
->cso
);
869 /* set misc state we care about */
871 struct pipe_blend_state blend
;
872 memset(&blend
, 0, sizeof(blend
));
873 blend
.rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
874 blend
.alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
875 blend
.rgb_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
876 blend
.alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
877 blend
.colormask
= PIPE_MASK_RGBA
;
878 cso_set_blend(exa
->cso
, &blend
);
883 struct pipe_sampler_state sampler
;
884 memset(&sampler
, 0, sizeof(sampler
));
885 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
886 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
887 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
888 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
889 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
890 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
891 sampler
.normalized_coords
= 1;
892 cso_single_sampler(exa
->cso
, 0, &sampler
);
893 cso_single_sampler_done(exa
->cso
);
896 set_viewport(exa
, dst_surf
->width
, dst_surf
->height
, Y0_TOP
);
899 cso_set_sampler_textures(exa
->cso
, 1, &src
);
902 shader
= xorg_shaders_get(exa
->shaders
,
905 cso_set_vertex_shader_handle(exa
->cso
, shader
.vs
);
906 cso_set_fragment_shader_handle(exa
->cso
, shader
.fs
);
909 memset(&fb
, 0, sizeof(fb
));
910 fb
.width
= dst_surf
->width
;
911 fb
.height
= dst_surf
->height
;
913 fb
.cbufs
[0] = dst_surf
;
916 for (i
= 1; i
< PIPE_MAX_COLOR_BUFS
; ++i
)
919 cso_set_framebuffer(exa
->cso
, &fb
);
920 setup_vs_constant_buffer(exa
, fb
.width
, fb
.height
);
921 setup_fs_constant_buffer(exa
);
924 buf
= setup_vertex_data_tex(exa
,
931 util_draw_vertex_buffer(exa
->pipe
, buf
, 0,
932 PIPE_PRIM_TRIANGLE_FAN
,
934 2); /* attribs/vert */
936 pipe_buffer_reference(&buf
, NULL
);
939 /* restore state we changed */
940 cso_restore_blend(exa
->cso
);
941 cso_restore_samplers(exa
->cso
);
942 cso_restore_sampler_textures(exa
->cso
);
943 cso_restore_framebuffer(exa
->cso
);
944 cso_restore_vertex_shader(exa
->cso
);
945 cso_restore_fragment_shader(exa
->cso
);
946 cso_restore_viewport(exa
->cso
);
948 pipe_surface_reference(&dst_surf
, NULL
);
952 static struct pipe_texture
*
953 create_sampler_texture(struct exa_context
*ctx
,
954 struct pipe_texture
*src
)
956 enum pipe_format format
;
957 struct pipe_context
*pipe
= ctx
->pipe
;
958 struct pipe_screen
*screen
= pipe
->screen
;
959 struct pipe_texture
*pt
;
960 struct pipe_texture templ
;
962 pipe
->flush(pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
964 /* the coming in texture should already have that invariance */
965 debug_assert(screen
->is_format_supported(screen
, src
->format
,
967 PIPE_TEXTURE_USAGE_SAMPLER
, 0));
969 format
= src
->format
;
971 memset(&templ
, 0, sizeof(templ
));
972 templ
.target
= PIPE_TEXTURE_2D
;
973 templ
.format
= format
;
974 templ
.last_level
= 0;
975 templ
.width
[0] = src
->width
[0];
976 templ
.height
[0] = src
->height
[0];
978 pf_get_block(format
, &templ
.block
);
979 templ
.tex_usage
= PIPE_TEXTURE_USAGE_SAMPLER
;
981 pt
= screen
->texture_create(screen
, &templ
);
983 debug_assert(!pt
|| pipe_is_referenced(&pt
->reference
));
989 /* copy source framebuffer surface into texture */
990 struct pipe_surface
*ps_read
= screen
->get_tex_surface(
991 screen
, src
, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ
);
992 struct pipe_surface
*ps_tex
= screen
->get_tex_surface(
993 screen
, pt
, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE
);
994 pipe
->surface_copy(pipe
,
998 0, 0, src
->width
[0], src
->height
[0]);
999 pipe_surface_reference(&ps_read
, NULL
);
1000 pipe_surface_reference(&ps_tex
, NULL
);
1006 void xorg_copy_pixmap(struct exa_context
*ctx
,
1007 struct exa_pixmap_priv
*dst_priv
, int dx
, int dy
,
1008 struct exa_pixmap_priv
*src_priv
, int sx
, int sy
,
1009 int width
, int height
)
1011 float dst_loc
[4], src_loc
[4];
1012 float dst_bounds
[4], src_bounds
[4];
1013 float src_shift
[4], dst_shift
[4], shift
[4];
1014 struct pipe_texture
*dst
= dst_priv
->tex
;
1015 struct pipe_texture
*src
= src_priv
->tex
;
1017 xorg_exa_finish(ctx
);
1022 dst_loc
[3] = height
;
1023 dst_bounds
[0] = 0.f
;
1024 dst_bounds
[1] = 0.f
;
1025 dst_bounds
[2] = dst
->width
[0];
1026 dst_bounds
[3] = dst
->height
[0];
1031 src_loc
[3] = height
;
1032 src_bounds
[0] = 0.f
;
1033 src_bounds
[1] = 0.f
;
1034 src_bounds
[2] = src
->width
[0];
1035 src_bounds
[3] = src
->height
[0];
1037 bound_rect(src_loc
, src_bounds
, src_shift
);
1038 bound_rect(dst_loc
, dst_bounds
, dst_shift
);
1039 shift
[0] = src_shift
[0] - dst_shift
[0];
1040 shift
[1] = src_shift
[1] - dst_shift
[1];
1043 shift_rectx(src_loc
, src_bounds
, -shift
[0]);
1045 shift_rectx(dst_loc
, dst_bounds
, shift
[0]);
1048 shift_recty(src_loc
, src_bounds
, -shift
[1]);
1050 shift_recty(dst_loc
, dst_bounds
, shift
[1]);
1052 sync_size(src_loc
, dst_loc
);
1054 if (src_loc
[2] >= 0 && src_loc
[3] >= 0 &&
1055 dst_loc
[2] >= 0 && dst_loc
[3] >= 0) {
1056 struct pipe_texture
*temp_src
= src
;
1059 temp_src
= create_sampler_texture(ctx
, src
);
1061 renderer_copy_texture(ctx
,
1065 src_loc
[0] + src_loc
[2],
1066 src_loc
[1] + src_loc
[3],
1070 dst_loc
[0] + dst_loc
[2],
1071 dst_loc
[1] + dst_loc
[3]);
1074 pipe_texture_reference(&temp_src
, NULL
);