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
)
153 float vertices
[4][2][4];
156 setup_vertex0(vertices
[0], dstX
, dstY
,
159 setup_vertex0(vertices
[1], dstX
+ width
, dstY
,
162 setup_vertex0(vertices
[2], dstX
+ width
, dstY
+ height
,
165 setup_vertex0(vertices
[3], dstX
, dstY
+ height
,
168 return pipe_user_buffer_create(ctx
->pipe
->screen
,
174 setup_vertex1(float vertex
[2][4], float x
, float y
, float s
, float t
)
178 vertex
[0][2] = 0.f
; /*z*/
179 vertex
[0][3] = 1.f
; /*w*/
181 vertex
[1][0] = s
; /*s*/
182 vertex
[1][1] = t
; /*t*/
183 vertex
[1][2] = 0.f
; /*r*/
184 vertex
[1][3] = 1.f
; /*q*/
187 static struct pipe_buffer
*
188 setup_vertex_data1(struct exa_context
*ctx
,
189 int srcX
, int srcY
, int maskX
, int maskY
,
190 int dstX
, int dstY
, int width
, int height
)
192 float vertices
[4][2][4];
193 float s0
, t0
, s1
, t1
;
194 struct pipe_texture
*src
= ctx
->bound_textures
[0];
196 s0
= srcX
/ src
->width
[0];
197 s1
= srcX
+ width
/ src
->width
[0];
198 t0
= srcY
/ src
->height
[0];
199 t1
= srcY
+ height
/ src
->height
[0];
202 setup_vertex1(vertices
[0], dstX
, dstY
,
205 setup_vertex1(vertices
[1], dstX
+ width
, dstY
,
208 setup_vertex1(vertices
[2], dstX
+ width
, dstY
+ height
,
211 setup_vertex1(vertices
[3], dstX
, dstY
+ height
,
214 return pipe_user_buffer_create(ctx
->pipe
->screen
,
219 static struct pipe_buffer
*
220 setup_vertex_data_tex(struct exa_context
*ctx
,
221 float x0
, float y0
, float x1
, float y1
,
222 float s0
, float t0
, float s1
, float t1
,
225 float vertices
[4][2][4];
228 setup_vertex1(vertices
[0], x0
, y0
,
231 setup_vertex1(vertices
[1], x1
, y0
,
234 setup_vertex1(vertices
[2], x1
, y1
,
237 setup_vertex1(vertices
[3], x0
, y1
,
240 return pipe_user_buffer_create(ctx
->pipe
->screen
,
248 setup_vertex2(float vertex
[3][4], float x
, float y
,
249 float s0
, float t0
, float s1
, float t1
)
253 vertex
[0][2] = 0.f
; /*z*/
254 vertex
[0][3] = 1.f
; /*w*/
256 vertex
[1][0] = s0
; /*s*/
257 vertex
[1][1] = t0
; /*t*/
258 vertex
[1][2] = 0.f
; /*r*/
259 vertex
[1][3] = 1.f
; /*q*/
261 vertex
[2][0] = s1
; /*s*/
262 vertex
[2][1] = t1
; /*t*/
263 vertex
[2][2] = 0.f
; /*r*/
264 vertex
[2][3] = 1.f
; /*q*/
267 static struct pipe_buffer
*
268 setup_vertex_data2(struct exa_context
*ctx
,
269 int srcX
, int srcY
, int maskX
, int maskY
,
270 int dstX
, int dstY
, int width
, int height
)
272 float vertices
[4][3][4];
273 float st0
[4], st1
[4];
274 struct pipe_texture
*src
= ctx
->bound_textures
[0];
275 struct pipe_texture
*mask
= ctx
->bound_textures
[0];
277 st0
[0] = srcX
/ src
->width
[0];
278 st0
[1] = srcY
/ src
->height
[0];
279 st0
[2] = srcX
+ width
/ src
->width
[0];
280 st0
[3] = srcY
+ height
/ src
->height
[0];
282 st1
[0] = maskX
/ mask
->width
[0];
283 st1
[1] = maskY
/ mask
->height
[0];
284 st1
[2] = maskX
+ width
/ mask
->width
[0];
285 st1
[3] = maskY
+ height
/ mask
->height
[0];
288 setup_vertex2(vertices
[0], dstX
, dstY
,
289 st0
[0], st0
[1], st1
[0], st1
[1]);
291 setup_vertex2(vertices
[1], dstX
+ width
, dstY
,
292 st0
[2], st0
[1], st1
[2], st1
[1]);
294 setup_vertex2(vertices
[2], dstX
+ width
, dstY
+ height
,
295 st0
[2], st0
[3], st1
[2], st1
[3]);
297 setup_vertex2(vertices
[3], dstX
, dstY
+ height
,
298 st0
[0], st0
[3], st1
[0], st1
[3]);
300 return pipe_user_buffer_create(ctx
->pipe
->screen
,
305 boolean
xorg_composite_accelerated(int op
,
306 PicturePtr pSrcPicture
,
307 PicturePtr pMaskPicture
,
308 PicturePtr pDstPicture
)
311 unsigned accel_ops_count
=
312 sizeof(accelerated_ops
)/sizeof(struct acceleration_info
);
315 /*FIXME: currently accel is disabled */
319 /* component alpha not supported */
320 if (pSrcPicture
->componentAlpha
)
322 /* fills not supported */
323 if (pSrcPicture
->pSourcePict
)
327 for (i
= 0; i
< accel_ops_count
; ++i
) {
328 if (op
== accelerated_ops
[i
].op
) {
329 if (pMaskPicture
&& !accelerated_ops
[i
].with_mask
)
338 bind_clip_state(struct exa_context
*exa
)
343 bind_framebuffer_state(struct exa_context
*exa
, struct exa_pixmap_priv
*pDst
)
346 struct pipe_framebuffer_state state
;
347 struct pipe_surface
*surface
= exa_gpu_surface(exa
, pDst
);
348 memset(&state
, 0, sizeof(struct pipe_framebuffer_state
));
350 state
.width
= pDst
->tex
->width
[0];
351 state
.height
= pDst
->tex
->height
[0];
354 state
.cbufs
[0] = surface
;
355 for (i
= 1; i
< PIPE_MAX_COLOR_BUFS
; ++i
)
358 /* currently we don't use depth/stencil */
361 cso_set_framebuffer(exa
->cso
, &state
);
364 enum AxisOrientation
{
370 set_viewport(struct exa_context
*exa
, int width
, int height
,
371 enum AxisOrientation orientation
)
373 struct pipe_viewport_state viewport
;
374 float y_scale
= (orientation
== Y0_BOTTOM
) ? -2.f
: 2.f
;
376 viewport
.scale
[0] = width
/ 2.f
;
377 viewport
.scale
[1] = height
/ y_scale
;
378 viewport
.scale
[2] = 1.0;
379 viewport
.scale
[3] = 1.0;
380 viewport
.translate
[0] = width
/ 2.f
;
381 viewport
.translate
[1] = height
/ 2.f
;
382 viewport
.translate
[2] = 0.0;
383 viewport
.translate
[3] = 0.0;
385 cso_set_viewport(exa
->cso
, &viewport
);
389 bind_viewport_state(struct exa_context
*exa
, struct exa_pixmap_priv
*pDst
)
391 int width
= pDst
->tex
->width
[0];
392 int height
= pDst
->tex
->height
[0];
394 debug_printf("Bind viewport (%d, %d)\n", width
, height
);
396 set_viewport(exa
, width
, height
, Y0_TOP
);
400 bind_blend_state(struct exa_context
*exa
, int op
,
401 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
403 boolean component_alpha
= (pSrcPicture
) ?
404 pSrcPicture
->componentAlpha
: FALSE
;
405 struct xorg_composite_blend blend_opt
;
406 struct pipe_blend_state blend
;
408 if (component_alpha
) {
411 blend_opt
= blend_for_op(op
);
413 memset(&blend
, 0, sizeof(struct pipe_blend_state
));
414 blend
.blend_enable
= 1;
415 blend
.colormask
|= PIPE_MASK_R
;
416 blend
.colormask
|= PIPE_MASK_G
;
417 blend
.colormask
|= PIPE_MASK_B
;
418 blend
.colormask
|= PIPE_MASK_A
;
420 blend
.rgb_src_factor
= blend_opt
.rgb_src_factor
;
421 blend
.alpha_src_factor
= blend_opt
.alpha_src_factor
;
422 blend
.rgb_dst_factor
= blend_opt
.rgb_dst_factor
;
423 blend
.alpha_dst_factor
= blend_opt
.alpha_dst_factor
;
425 cso_set_blend(exa
->cso
, &blend
);
429 bind_rasterizer_state(struct exa_context
*exa
)
431 struct pipe_rasterizer_state raster
;
432 memset(&raster
, 0, sizeof(struct pipe_rasterizer_state
));
433 raster
.gl_rasterization_rules
= 1;
434 cso_set_rasterizer(exa
->cso
, &raster
);
438 bind_shaders(struct exa_context
*exa
, int op
,
439 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
441 unsigned vs_traits
= 0, fs_traits
= 0;
442 struct xorg_shader shader
;
444 exa
->has_solid_color
= FALSE
;
447 if (pSrcPicture
->pSourcePict
) {
448 if (pSrcPicture
->pSourcePict
->type
== SourcePictTypeSolidFill
) {
449 fs_traits
|= FS_SOLID_FILL
;
450 vs_traits
|= VS_SOLID_FILL
;
451 render_pixel_to_float4(pSrcPicture
->pFormat
,
452 pSrcPicture
->pSourcePict
->solidFill
.color
,
454 exa
->has_solid_color
= TRUE
;
456 debug_assert("!gradients not supported");
459 fs_traits
|= FS_COMPOSITE
;
460 vs_traits
|= VS_COMPOSITE
;
465 vs_traits
|= VS_MASK
;
466 fs_traits
|= FS_MASK
;
469 shader
= xorg_shaders_get(exa
->shaders
, vs_traits
, fs_traits
);
470 cso_set_vertex_shader_handle(exa
->cso
, shader
.vs
);
471 cso_set_fragment_shader_handle(exa
->cso
, shader
.fs
);
476 bind_samplers(struct exa_context
*exa
, int op
,
477 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
,
478 PicturePtr pDstPicture
,
479 struct exa_pixmap_priv
*pSrc
,
480 struct exa_pixmap_priv
*pMask
,
481 struct exa_pixmap_priv
*pDst
)
483 struct pipe_sampler_state
*samplers
[PIPE_MAX_SAMPLERS
];
484 struct pipe_sampler_state src_sampler
, mask_sampler
;
486 exa
->num_bound_samplers
= 0;
488 memset(&src_sampler
, 0, sizeof(struct pipe_sampler_state
));
489 memset(&mask_sampler
, 0, sizeof(struct pipe_sampler_state
));
491 if (pSrcPicture
&& pSrc
) {
492 unsigned src_wrap
= render_repeat_to_gallium(
493 pSrcPicture
->repeatType
);
494 src_sampler
.wrap_s
= src_wrap
;
495 src_sampler
.wrap_t
= src_wrap
;
496 src_sampler
.min_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
497 src_sampler
.mag_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
498 src_sampler
.normalized_coords
= 1;
499 samplers
[0] = &src_sampler
;
500 exa
->bound_textures
[0] = pSrc
->tex
;
501 ++exa
->num_bound_samplers
;
504 if (pMaskPicture
&& pMask
) {
505 unsigned mask_wrap
= render_repeat_to_gallium(
506 pMaskPicture
->repeatType
);
507 mask_sampler
.wrap_s
= mask_wrap
;
508 mask_sampler
.wrap_t
= mask_wrap
;
509 mask_sampler
.min_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
510 mask_sampler
.mag_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
511 mask_sampler
.normalized_coords
= 1;
512 samplers
[1] = &mask_sampler
;
513 exa
->bound_textures
[1] = pMask
->tex
;
514 ++exa
->num_bound_samplers
;
517 cso_set_samplers(exa
->cso
, exa
->num_bound_samplers
,
518 (const struct pipe_sampler_state
**)samplers
);
519 cso_set_sampler_textures(exa
->cso
, exa
->num_bound_samplers
,
520 exa
->bound_textures
);
524 setup_vs_constant_buffer(struct exa_context
*exa
,
525 int width
, int height
)
527 const int param_bytes
= 8 * sizeof(float);
528 float vs_consts
[8] = {
529 2.f
/width
, 2.f
/height
, 1, 1,
532 struct pipe_constant_buffer
*cbuf
= &exa
->vs_const_buffer
;
534 pipe_buffer_reference(&cbuf
->buffer
, NULL
);
535 cbuf
->buffer
= pipe_buffer_create(exa
->pipe
->screen
, 16,
536 PIPE_BUFFER_USAGE_CONSTANT
,
540 pipe_buffer_write(exa
->pipe
->screen
, cbuf
->buffer
,
541 0, param_bytes
, vs_consts
);
543 exa
->pipe
->set_constant_buffer(exa
->pipe
, PIPE_SHADER_VERTEX
, 0, cbuf
);
548 setup_fs_constant_buffer(struct exa_context
*exa
)
550 const int param_bytes
= 4 * sizeof(float);
551 float fs_consts
[8] = {
554 struct pipe_constant_buffer
*cbuf
= &exa
->fs_const_buffer
;
556 pipe_buffer_reference(&cbuf
->buffer
, NULL
);
557 cbuf
->buffer
= pipe_buffer_create(exa
->pipe
->screen
, 16,
558 PIPE_BUFFER_USAGE_CONSTANT
,
562 pipe_buffer_write(exa
->pipe
->screen
, cbuf
->buffer
,
563 0, param_bytes
, fs_consts
);
565 exa
->pipe
->set_constant_buffer(exa
->pipe
, PIPE_SHADER_FRAGMENT
, 0, cbuf
);
569 setup_constant_buffers(struct exa_context
*exa
, struct exa_pixmap_priv
*pDst
)
571 int width
= pDst
->tex
->width
[0];
572 int height
= pDst
->tex
->height
[0];
574 setup_vs_constant_buffer(exa
, width
, height
);
575 setup_fs_constant_buffer(exa
);
578 boolean
xorg_composite_bind_state(struct exa_context
*exa
,
580 PicturePtr pSrcPicture
,
581 PicturePtr pMaskPicture
,
582 PicturePtr pDstPicture
,
583 struct exa_pixmap_priv
*pSrc
,
584 struct exa_pixmap_priv
*pMask
,
585 struct exa_pixmap_priv
*pDst
)
587 bind_framebuffer_state(exa
, pDst
);
588 bind_viewport_state(exa
, pDst
);
589 bind_blend_state(exa
, op
, pSrcPicture
, pMaskPicture
);
590 bind_rasterizer_state(exa
);
591 bind_shaders(exa
, op
, pSrcPicture
, pMaskPicture
);
592 bind_samplers(exa
, op
, pSrcPicture
, pMaskPicture
,
593 pDstPicture
, pSrc
, pMask
, pDst
);
594 bind_clip_state(exa
);
595 setup_constant_buffers(exa
, pDst
);
600 void xorg_composite(struct exa_context
*exa
,
601 struct exa_pixmap_priv
*dst
,
602 int srcX
, int srcY
, int maskX
, int maskY
,
603 int dstX
, int dstY
, int width
, int height
)
605 struct pipe_context
*pipe
= exa
->pipe
;
606 struct pipe_buffer
*buf
= 0;
608 if (exa
->num_bound_samplers
== 0 ) { /* solid fill */
609 buf
= setup_vertex_data0(exa
,
610 srcX
, srcY
, maskX
, maskY
,
611 dstX
, dstY
, width
, height
);
612 } else if (exa
->num_bound_samplers
== 1 ) /* src */
613 buf
= setup_vertex_data1(exa
,
614 srcX
, srcY
, maskX
, maskY
,
615 dstX
, dstY
, width
, height
);
616 else if (exa
->num_bound_samplers
== 2) /* src + mask */
617 buf
= setup_vertex_data2(exa
,
618 srcX
, srcY
, maskX
, maskY
,
619 dstX
, dstY
, width
, height
);
620 else if (exa
->num_bound_samplers
== 3) { /* src + mask + dst */
621 debug_assert(!"src/mask/dst not handled right now");
623 buf
= setup_vertex_data2(exa
,
624 srcX
, srcY
, maskX
, maskY
,
625 dstX
, dstY
, width
, height
);
630 int num_attribs
= 1; /*pos*/
631 num_attribs
+= exa
->num_bound_samplers
;
632 if (exa
->has_solid_color
)
635 util_draw_vertex_buffer(pipe
, buf
, 0,
636 PIPE_PRIM_TRIANGLE_FAN
,
638 num_attribs
); /* attribs/vert */
640 pipe_buffer_reference(&buf
, NULL
);
644 boolean
xorg_solid_bind_state(struct exa_context
*exa
,
645 struct exa_pixmap_priv
*pixmap
,
648 unsigned vs_traits
, fs_traits
;
649 struct xorg_shader shader
;
651 pixel_to_float4(fg
, exa
->solid_color
);
652 exa
->has_solid_color
= TRUE
;
654 exa
->solid_color
[3] = 1.f
;
657 debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
658 (fg
>> 24) & 0xff, (fg
>> 16) & 0xff,
659 (fg
>> 8) & 0xff, (fg
>> 0) & 0xff,
660 exa
->solid_color
[0], exa
->solid_color
[1],
661 exa
->solid_color
[2], exa
->solid_color
[3]);
664 vs_traits
= VS_SOLID_FILL
;
665 fs_traits
= FS_SOLID_FILL
;
667 bind_framebuffer_state(exa
, pixmap
);
668 bind_viewport_state(exa
, pixmap
);
669 bind_rasterizer_state(exa
);
670 bind_blend_state(exa
, PictOpSrc
, NULL
, NULL
);
671 setup_constant_buffers(exa
, pixmap
);
672 bind_clip_state(exa
);
674 shader
= xorg_shaders_get(exa
->shaders
, vs_traits
, fs_traits
);
675 cso_set_vertex_shader_handle(exa
->cso
, shader
.vs
);
676 cso_set_fragment_shader_handle(exa
->cso
, shader
.fs
);
681 void xorg_solid(struct exa_context
*exa
,
682 struct exa_pixmap_priv
*pixmap
,
683 int x0
, int y0
, int x1
, int y1
)
685 struct pipe_context
*pipe
= exa
->pipe
;
686 struct pipe_buffer
*buf
= 0;
687 float vertices
[4][2][4];
690 setup_vertex0(vertices
[0], x0
, y0
,
693 setup_vertex0(vertices
[1], x1
, y0
,
696 setup_vertex0(vertices
[2], x1
, y1
,
699 setup_vertex0(vertices
[3], x0
, y1
,
702 buf
= pipe_user_buffer_create(exa
->pipe
->screen
,
708 debug_printf("Drawing buf is %p\n", buf
);
709 util_draw_vertex_buffer(pipe
, buf
, 0,
710 PIPE_PRIM_TRIANGLE_FAN
,
712 2); /* attribs/vert */
714 pipe_buffer_reference(&buf
, NULL
);
719 static INLINE
void shift_rectx(float coords
[4],
726 coords
[2] = MIN2(coords
[2], bounds
[2]);
727 /* bound x/y + width/height */
728 if ((coords
[0] + coords
[2]) > (bounds
[0] + bounds
[2])) {
729 coords
[2] = (bounds
[0] + bounds
[2]) - coords
[0];
734 static INLINE
void shift_recty(float coords
[4],
741 coords
[3] = MIN2(coords
[3], bounds
[3]);
742 if ((coords
[1] + coords
[3]) > (bounds
[1] + bounds
[3])) {
743 coords
[3] = (bounds
[1] + bounds
[3]) - coords
[1];
748 static INLINE
void bound_rect(float coords
[4],
749 const float bounds
[4],
752 /* if outside the bounds */
753 if (coords
[0] > (bounds
[0] + bounds
[2]) ||
754 coords
[1] > (bounds
[1] + bounds
[3]) ||
755 (coords
[0] + coords
[2]) < bounds
[0] ||
756 (coords
[1] + coords
[3]) < bounds
[1]) {
767 if (coords
[0] < bounds
[0]) {
768 shift
[0] = bounds
[0] - coords
[0];
769 coords
[2] -= shift
[0];
770 coords
[0] = bounds
[0];
775 if (coords
[1] < bounds
[1]) {
776 shift
[1] = bounds
[1] - coords
[1];
777 coords
[3] -= shift
[1];
778 coords
[1] = bounds
[1];
782 shift
[2] = bounds
[2] - coords
[2];
783 shift
[3] = bounds
[3] - coords
[3];
784 /* bound width/height */
785 coords
[2] = MIN2(coords
[2], bounds
[2]);
786 coords
[3] = MIN2(coords
[3], bounds
[3]);
788 /* bound x/y + width/height */
789 if ((coords
[0] + coords
[2]) > (bounds
[0] + bounds
[2])) {
790 coords
[2] = (bounds
[0] + bounds
[2]) - coords
[0];
792 if ((coords
[1] + coords
[3]) > (bounds
[1] + bounds
[3])) {
793 coords
[3] = (bounds
[1] + bounds
[3]) - coords
[1];
796 /* if outside the bounds */
797 if ((coords
[0] + coords
[2]) < bounds
[0] ||
798 (coords
[1] + coords
[3]) < bounds
[1]) {
807 static INLINE
void sync_size(float *src_loc
, float *dst_loc
)
809 src_loc
[2] = MIN2(src_loc
[2], dst_loc
[2]);
810 src_loc
[3] = MIN2(src_loc
[3], dst_loc
[3]);
811 dst_loc
[2] = src_loc
[2];
812 dst_loc
[3] = src_loc
[3];
816 static void renderer_copy_texture(struct exa_context
*exa
,
817 struct pipe_texture
*src
,
818 float sx1
, float sy1
,
819 float sx2
, float sy2
,
820 struct pipe_texture
*dst
,
821 float dx1
, float dy1
,
822 float dx2
, float dy2
)
824 struct pipe_context
*pipe
= exa
->pipe
;
825 struct pipe_screen
*screen
= pipe
->screen
;
826 struct pipe_buffer
*buf
;
827 struct pipe_surface
*dst_surf
= screen
->get_tex_surface(
828 screen
, dst
, 0, 0, 0,
829 PIPE_BUFFER_USAGE_GPU_WRITE
);
830 struct pipe_framebuffer_state fb
;
831 float s0
, t0
, s1
, t1
;
832 struct xorg_shader shader
;
834 assert(src
->width
[0] != 0);
835 assert(src
->height
[0] != 0);
836 assert(dst
->width
[0] != 0);
837 assert(dst
->height
[0] != 0);
840 s0
= sx1
/ src
->width
[0];
841 s1
= sx2
/ src
->width
[0];
842 t0
= sy1
/ src
->height
[0];
843 t1
= sy2
/ src
->height
[0];
852 debug_printf("copy texture src=[%f, %f, %f, %f], dst=[%f, %f, %f, %f], tex=[%f, %f, %f, %f]\n",
853 sx1
, sy1
, sx2
, sy2
, dx1
, dy1
, dx2
, dy2
,
857 assert(screen
->is_format_supported(screen
, dst_surf
->format
,
859 PIPE_TEXTURE_USAGE_RENDER_TARGET
,
862 /* save state (restored below) */
863 cso_save_blend(exa
->cso
);
864 cso_save_samplers(exa
->cso
);
865 cso_save_sampler_textures(exa
->cso
);
866 cso_save_framebuffer(exa
->cso
);
867 cso_save_fragment_shader(exa
->cso
);
868 cso_save_vertex_shader(exa
->cso
);
870 cso_save_viewport(exa
->cso
);
873 /* set misc state we care about */
875 struct pipe_blend_state blend
;
876 memset(&blend
, 0, sizeof(blend
));
877 blend
.rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
878 blend
.alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
879 blend
.rgb_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
880 blend
.alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
881 blend
.colormask
= PIPE_MASK_RGBA
;
882 cso_set_blend(exa
->cso
, &blend
);
887 struct pipe_sampler_state sampler
;
888 memset(&sampler
, 0, sizeof(sampler
));
889 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
890 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
891 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
892 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
893 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
894 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
895 sampler
.normalized_coords
= 1;
896 cso_single_sampler(exa
->cso
, 0, &sampler
);
897 cso_single_sampler_done(exa
->cso
);
900 set_viewport(exa
, dst_surf
->width
, dst_surf
->height
, Y0_TOP
);
903 cso_set_sampler_textures(exa
->cso
, 1, &src
);
906 shader
= xorg_shaders_get(exa
->shaders
,
909 cso_set_vertex_shader_handle(exa
->cso
, shader
.vs
);
910 cso_set_fragment_shader_handle(exa
->cso
, shader
.fs
);
913 memset(&fb
, 0, sizeof(fb
));
914 fb
.width
= dst_surf
->width
;
915 fb
.height
= dst_surf
->height
;
917 fb
.cbufs
[0] = dst_surf
;
920 for (i
= 1; i
< PIPE_MAX_COLOR_BUFS
; ++i
)
923 cso_set_framebuffer(exa
->cso
, &fb
);
924 setup_vs_constant_buffer(exa
, fb
.width
, fb
.height
);
925 setup_fs_constant_buffer(exa
);
928 buf
= setup_vertex_data_tex(exa
,
935 util_draw_vertex_buffer(exa
->pipe
, buf
, 0,
936 PIPE_PRIM_TRIANGLE_FAN
,
938 2); /* attribs/vert */
940 pipe_buffer_reference(&buf
, NULL
);
943 /* restore state we changed */
944 cso_restore_blend(exa
->cso
);
945 cso_restore_samplers(exa
->cso
);
946 cso_restore_sampler_textures(exa
->cso
);
947 cso_restore_framebuffer(exa
->cso
);
948 cso_restore_vertex_shader(exa
->cso
);
949 cso_restore_fragment_shader(exa
->cso
);
950 cso_restore_viewport(exa
->cso
);
952 pipe_surface_reference(&dst_surf
, NULL
);
956 static struct pipe_texture
*
957 create_sampler_texture(struct exa_context
*ctx
,
958 struct pipe_texture
*src
)
960 enum pipe_format format
;
961 struct pipe_context
*pipe
= ctx
->pipe
;
962 struct pipe_screen
*screen
= pipe
->screen
;
963 struct pipe_texture
*pt
;
964 struct pipe_texture templ
;
966 pipe
->flush(pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
968 /* the coming in texture should already have that invariance */
969 debug_assert(screen
->is_format_supported(screen
, src
->format
,
971 PIPE_TEXTURE_USAGE_SAMPLER
, 0));
973 format
= src
->format
;
975 memset(&templ
, 0, sizeof(templ
));
976 templ
.target
= PIPE_TEXTURE_2D
;
977 templ
.format
= format
;
978 templ
.last_level
= 0;
979 templ
.width
[0] = src
->width
[0];
980 templ
.height
[0] = src
->height
[0];
982 pf_get_block(format
, &templ
.block
);
983 templ
.tex_usage
= PIPE_TEXTURE_USAGE_SAMPLER
;
985 pt
= screen
->texture_create(screen
, &templ
);
987 debug_assert(!pt
|| pipe_is_referenced(&pt
->reference
));
993 /* copy source framebuffer surface into texture */
994 struct pipe_surface
*ps_read
= screen
->get_tex_surface(
995 screen
, src
, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ
);
996 struct pipe_surface
*ps_tex
= screen
->get_tex_surface(
997 screen
, pt
, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE
);
998 pipe
->surface_copy(pipe
,
1002 0, 0, src
->width
[0], src
->height
[0]);
1003 pipe_surface_reference(&ps_read
, NULL
);
1004 pipe_surface_reference(&ps_tex
, NULL
);
1010 void xorg_copy_pixmap(struct exa_context
*ctx
,
1011 struct exa_pixmap_priv
*dst_priv
, int dx
, int dy
,
1012 struct exa_pixmap_priv
*src_priv
, int sx
, int sy
,
1013 int width
, int height
)
1015 float dst_loc
[4], src_loc
[4];
1016 float dst_bounds
[4], src_bounds
[4];
1017 float src_shift
[4], dst_shift
[4], shift
[4];
1018 struct pipe_texture
*dst
= dst_priv
->tex
;
1019 struct pipe_texture
*src
= src_priv
->tex
;
1021 xorg_exa_finish(ctx
);
1026 dst_loc
[3] = height
;
1027 dst_bounds
[0] = 0.f
;
1028 dst_bounds
[1] = 0.f
;
1029 dst_bounds
[2] = dst
->width
[0];
1030 dst_bounds
[3] = dst
->height
[0];
1035 src_loc
[3] = height
;
1036 src_bounds
[0] = 0.f
;
1037 src_bounds
[1] = 0.f
;
1038 src_bounds
[2] = src
->width
[0];
1039 src_bounds
[3] = src
->height
[0];
1041 bound_rect(src_loc
, src_bounds
, src_shift
);
1042 bound_rect(dst_loc
, dst_bounds
, dst_shift
);
1043 shift
[0] = src_shift
[0] - dst_shift
[0];
1044 shift
[1] = src_shift
[1] - dst_shift
[1];
1047 shift_rectx(src_loc
, src_bounds
, -shift
[0]);
1049 shift_rectx(dst_loc
, dst_bounds
, shift
[0]);
1052 shift_recty(src_loc
, src_bounds
, -shift
[1]);
1054 shift_recty(dst_loc
, dst_bounds
, shift
[1]);
1056 sync_size(src_loc
, dst_loc
);
1058 if (src_loc
[2] >= 0 && src_loc
[3] >= 0 &&
1059 dst_loc
[2] >= 0 && dst_loc
[3] >= 0) {
1060 struct pipe_texture
*temp_src
= src
;
1063 temp_src
= create_sampler_texture(ctx
, src
);
1065 renderer_copy_texture(ctx
,
1069 src_loc
[0] + src_loc
[2],
1070 src_loc
[1] + src_loc
[3],
1074 dst_loc
[0] + dst_loc
[2],
1075 dst_loc
[1] + dst_loc
[3]);
1078 pipe_texture_reference(&temp_src
, NULL
);