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 rgb_dst_factor
:5; /**< PIPE_BLENDFACTOR_x */
17 unsigned alpha_src_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
->ctx
->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
->ctx
->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
->ctx
->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
->ctx
->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
->ctx
->screen
, 16,
536 PIPE_BUFFER_USAGE_CONSTANT
,
540 pipe_buffer_write(exa
->ctx
->screen
, cbuf
->buffer
,
541 0, param_bytes
, vs_consts
);
543 exa
->ctx
->set_constant_buffer(exa
->ctx
, 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
->ctx
->screen
, 16,
558 PIPE_BUFFER_USAGE_CONSTANT
,
562 pipe_buffer_write(exa
->ctx
->screen
, cbuf
->buffer
,
563 0, param_bytes
, fs_consts
);
565 exa
->ctx
->set_constant_buffer(exa
->ctx
, 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
->ctx
;
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
;
656 debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
657 (fg
>> 24) & 0xff, (fg
>> 16) & 0xff,
658 (fg
>> 8) & 0xff, (fg
>> 0) & 0xff,
659 exa
->solid_color
[0], exa
->solid_color
[1],
660 exa
->solid_color
[2], exa
->solid_color
[3]);
663 exa
->solid_color
[0] = 1.f
;
664 exa
->solid_color
[1] = 0.f
;
665 exa
->solid_color
[2] = 0.f
;
666 exa
->solid_color
[3] = 1.f
;
669 vs_traits
= VS_SOLID_FILL
;
670 fs_traits
= FS_SOLID_FILL
;
672 bind_framebuffer_state(exa
, pixmap
);
673 bind_viewport_state(exa
, pixmap
);
674 bind_rasterizer_state(exa
);
675 bind_blend_state(exa
, PictOpSrc
, NULL
, NULL
);
676 setup_constant_buffers(exa
, pixmap
);
677 bind_clip_state(exa
);
679 shader
= xorg_shaders_get(exa
->shaders
, vs_traits
, fs_traits
);
680 cso_set_vertex_shader_handle(exa
->cso
, shader
.vs
);
681 cso_set_fragment_shader_handle(exa
->cso
, shader
.fs
);
686 void xorg_solid(struct exa_context
*exa
,
687 struct exa_pixmap_priv
*pixmap
,
688 int x0
, int y0
, int x1
, int y1
)
690 struct pipe_context
*pipe
= exa
->ctx
;
691 struct pipe_buffer
*buf
= 0;
692 float vertices
[4][2][4];
698 setup_vertex0(vertices
[0], x0
, y0
,
701 setup_vertex0(vertices
[1], x1
, y0
,
704 setup_vertex0(vertices
[2], x1
, y1
,
707 setup_vertex0(vertices
[3], x0
, y1
,
710 buf
= pipe_user_buffer_create(exa
->ctx
->screen
,
716 debug_printf("Drawing buf is %p\n", buf
);
717 util_draw_vertex_buffer(pipe
, buf
, 0,
718 PIPE_PRIM_TRIANGLE_FAN
,
720 2); /* attribs/vert */
722 pipe_buffer_reference(&buf
, NULL
);
727 static INLINE
void shift_rectx(float coords
[4],
734 coords
[2] = MIN2(coords
[2], bounds
[2]);
735 /* bound x/y + width/height */
736 if ((coords
[0] + coords
[2]) > (bounds
[0] + bounds
[2])) {
737 coords
[2] = (bounds
[0] + bounds
[2]) - coords
[0];
742 static INLINE
void shift_recty(float coords
[4],
749 coords
[3] = MIN2(coords
[3], bounds
[3]);
750 if ((coords
[1] + coords
[3]) > (bounds
[1] + bounds
[3])) {
751 coords
[3] = (bounds
[1] + bounds
[3]) - coords
[1];
756 static INLINE
void bound_rect(float coords
[4],
757 const float bounds
[4],
760 /* if outside the bounds */
761 if (coords
[0] > (bounds
[0] + bounds
[2]) ||
762 coords
[1] > (bounds
[1] + bounds
[3]) ||
763 (coords
[0] + coords
[2]) < bounds
[0] ||
764 (coords
[1] + coords
[3]) < bounds
[1]) {
775 if (coords
[0] < bounds
[0]) {
776 shift
[0] = bounds
[0] - coords
[0];
777 coords
[2] -= shift
[0];
778 coords
[0] = bounds
[0];
783 if (coords
[1] < bounds
[1]) {
784 shift
[1] = bounds
[1] - coords
[1];
785 coords
[3] -= shift
[1];
786 coords
[1] = bounds
[1];
790 shift
[2] = bounds
[2] - coords
[2];
791 shift
[3] = bounds
[3] - coords
[3];
792 /* bound width/height */
793 coords
[2] = MIN2(coords
[2], bounds
[2]);
794 coords
[3] = MIN2(coords
[3], bounds
[3]);
796 /* bound x/y + width/height */
797 if ((coords
[0] + coords
[2]) > (bounds
[0] + bounds
[2])) {
798 coords
[2] = (bounds
[0] + bounds
[2]) - coords
[0];
800 if ((coords
[1] + coords
[3]) > (bounds
[1] + bounds
[3])) {
801 coords
[3] = (bounds
[1] + bounds
[3]) - coords
[1];
804 /* if outside the bounds */
805 if ((coords
[0] + coords
[2]) < bounds
[0] ||
806 (coords
[1] + coords
[3]) < bounds
[1]) {
815 static INLINE
void sync_size(float *src_loc
, float *dst_loc
)
817 src_loc
[2] = MIN2(src_loc
[2], dst_loc
[2]);
818 src_loc
[3] = MIN2(src_loc
[3], dst_loc
[3]);
819 dst_loc
[2] = src_loc
[2];
820 dst_loc
[3] = src_loc
[3];
824 static void renderer_copy_texture(struct exa_context
*exa
,
825 struct pipe_texture
*src
,
826 float sx1
, float sy1
,
827 float sx2
, float sy2
,
828 struct pipe_texture
*dst
,
829 float dx1
, float dy1
,
830 float dx2
, float dy2
)
832 struct pipe_context
*pipe
= exa
->ctx
;
833 struct pipe_screen
*screen
= pipe
->screen
;
834 struct pipe_buffer
*buf
;
835 struct pipe_surface
*dst_surf
= screen
->get_tex_surface(
836 screen
, dst
, 0, 0, 0,
837 PIPE_BUFFER_USAGE_GPU_WRITE
);
838 struct pipe_framebuffer_state fb
;
839 float s0
, t0
, s1
, t1
;
840 struct xorg_shader shader
;
842 assert(src
->width
[0] != 0);
843 assert(src
->height
[0] != 0);
844 assert(dst
->width
[0] != 0);
845 assert(dst
->height
[0] != 0);
848 debug_printf("copy texture [%f, %f, %f, %f], [%f, %f, %f, %f]\n",
849 sx1
, sy1
, sx2
, sy2
, dx1
, dy1
, dx2
, dy2
);
853 s0
= sx1
/ src
->width
[0];
854 s1
= sx2
/ src
->width
[0];
855 t0
= sy1
/ src
->height
[0];
856 t1
= sy2
/ src
->height
[0];
864 assert(screen
->is_format_supported(screen
, dst_surf
->format
, PIPE_TEXTURE_2D
,
865 PIPE_TEXTURE_USAGE_RENDER_TARGET
, 0));
867 /* save state (restored below) */
868 cso_save_blend(exa
->cso
);
869 cso_save_samplers(exa
->cso
);
870 cso_save_sampler_textures(exa
->cso
);
871 cso_save_framebuffer(exa
->cso
);
872 cso_save_fragment_shader(exa
->cso
);
873 cso_save_vertex_shader(exa
->cso
);
875 cso_save_viewport(exa
->cso
);
878 /* set misc state we care about */
880 struct pipe_blend_state blend
;
881 memset(&blend
, 0, sizeof(blend
));
882 blend
.rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
883 blend
.alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
884 blend
.rgb_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
885 blend
.alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
886 blend
.colormask
= PIPE_MASK_RGBA
;
887 cso_set_blend(exa
->cso
, &blend
);
892 struct pipe_sampler_state sampler
;
893 memset(&sampler
, 0, sizeof(sampler
));
894 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
895 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
896 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
897 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
898 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
899 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
900 sampler
.normalized_coords
= 1;
901 cso_single_sampler(exa
->cso
, 0, &sampler
);
902 cso_single_sampler_done(exa
->cso
);
905 set_viewport(exa
, dst_surf
->width
, dst_surf
->height
, Y0_TOP
);
908 cso_set_sampler_textures(exa
->cso
, 1, &src
);
911 shader
= xorg_shaders_get(exa
->shaders
,
914 cso_set_vertex_shader_handle(exa
->cso
, shader
.vs
);
915 cso_set_fragment_shader_handle(exa
->cso
, shader
.fs
);
918 memset(&fb
, 0, sizeof(fb
));
919 fb
.width
= dst_surf
->width
;
920 fb
.height
= dst_surf
->height
;
922 fb
.cbufs
[0] = dst_surf
;
925 for (i
= 1; i
< PIPE_MAX_COLOR_BUFS
; ++i
)
928 cso_set_framebuffer(exa
->cso
, &fb
);
931 buf
= setup_vertex_data_tex(exa
,
938 util_draw_vertex_buffer(exa
->ctx
, buf
, 0,
939 PIPE_PRIM_TRIANGLE_FAN
,
941 2); /* attribs/vert */
943 pipe_buffer_reference(&buf
, NULL
);
946 /* restore state we changed */
947 cso_restore_blend(exa
->cso
);
948 cso_restore_samplers(exa
->cso
);
949 cso_restore_sampler_textures(exa
->cso
);
950 cso_restore_framebuffer(exa
->cso
);
951 cso_restore_vertex_shader(exa
->cso
);
952 cso_restore_fragment_shader(exa
->cso
);
953 cso_restore_viewport(exa
->cso
);
955 pipe_surface_reference(&dst_surf
, NULL
);
958 void xorg_copy_pixmap(struct exa_context
*ctx
,
959 struct exa_pixmap_priv
*dst_priv
, int dx
, int dy
,
960 struct exa_pixmap_priv
*src_priv
, int sx
, int sy
,
961 int width
, int height
)
963 float dst_loc
[4], src_loc
[4];
964 float dst_bounds
[4], src_bounds
[4];
965 float src_shift
[4], dst_shift
[4], shift
[4];
966 struct pipe_texture
*dst
= dst_priv
->tex
;
967 struct pipe_texture
*src
= src_priv
->tex
;
975 dst_bounds
[2] = dst
->width
[0];
976 dst_bounds
[3] = dst
->height
[0];
984 src_bounds
[2] = src
->width
[0];
985 src_bounds
[3] = src
->height
[0];
987 bound_rect(src_loc
, src_bounds
, src_shift
);
988 bound_rect(dst_loc
, dst_bounds
, dst_shift
);
989 shift
[0] = src_shift
[0] - dst_shift
[0];
990 shift
[1] = src_shift
[1] - dst_shift
[1];
993 shift_rectx(src_loc
, src_bounds
, -shift
[0]);
995 shift_rectx(dst_loc
, dst_bounds
, shift
[0]);
998 shift_recty(src_loc
, src_bounds
, -shift
[1]);
1000 shift_recty(dst_loc
, dst_bounds
, shift
[1]);
1002 sync_size(src_loc
, dst_loc
);
1004 if (src_loc
[2] >= 0 && src_loc
[3] >= 0 &&
1005 dst_loc
[2] >= 0 && dst_loc
[3] >= 0) {
1006 renderer_copy_texture(ctx
,
1009 src_loc
[1] + src_loc
[3],
1010 src_loc
[0] + src_loc
[2],
1014 dst_loc
[1] + dst_loc
[3],
1015 dst_loc
[0] + dst_loc
[2],