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 /* component alpha not supported */
310 if (pSrcPicture
->componentAlpha
)
314 for (i
= 0; i
< accel_ops_count
; ++i
) {
315 if (op
== accelerated_ops
[i
].op
) {
316 if (pMaskPicture
&& !accelerated_ops
[i
].with_mask
)
325 bind_clip_state(struct exa_context
*exa
)
330 bind_framebuffer_state(struct exa_context
*exa
, struct exa_pixmap_priv
*pDst
)
333 struct pipe_framebuffer_state state
;
334 struct pipe_surface
*surface
= exa_gpu_surface(exa
, pDst
);
335 memset(&state
, 0, sizeof(struct pipe_framebuffer_state
));
337 state
.width
= pDst
->tex
->width
[0];
338 state
.height
= pDst
->tex
->height
[0];
341 state
.cbufs
[0] = surface
;
342 for (i
= 1; i
< PIPE_MAX_COLOR_BUFS
; ++i
)
345 /* currently we don't use depth/stencil */
348 cso_set_framebuffer(exa
->cso
, &state
);
350 /* we do fire and forget for the framebuffer, this is the forget part */
351 pipe_surface_reference(&surface
, NULL
);
354 enum AxisOrientation
{
360 set_viewport(struct exa_context
*exa
, int width
, int height
,
361 enum AxisOrientation orientation
)
363 struct pipe_viewport_state viewport
;
364 float y_scale
= (orientation
== Y0_BOTTOM
) ? -2.f
: 2.f
;
366 viewport
.scale
[0] = width
/ 2.f
;
367 viewport
.scale
[1] = height
/ y_scale
;
368 viewport
.scale
[2] = 1.0;
369 viewport
.scale
[3] = 1.0;
370 viewport
.translate
[0] = width
/ 2.f
;
371 viewport
.translate
[1] = height
/ 2.f
;
372 viewport
.translate
[2] = 0.0;
373 viewport
.translate
[3] = 0.0;
375 cso_set_viewport(exa
->cso
, &viewport
);
379 bind_viewport_state(struct exa_context
*exa
, struct exa_pixmap_priv
*pDst
)
381 int width
= pDst
->tex
->width
[0];
382 int height
= pDst
->tex
->height
[0];
384 /*debug_printf("Bind viewport (%d, %d)\n", width, height);*/
386 set_viewport(exa
, width
, height
, Y0_TOP
);
390 bind_blend_state(struct exa_context
*exa
, int op
,
391 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
393 boolean component_alpha
= (pSrcPicture
) ?
394 pSrcPicture
->componentAlpha
: FALSE
;
395 struct xorg_composite_blend blend_opt
;
396 struct pipe_blend_state blend
;
398 if (component_alpha
) {
401 blend_opt
= blend_for_op(op
);
403 memset(&blend
, 0, sizeof(struct pipe_blend_state
));
404 blend
.blend_enable
= 1;
405 blend
.colormask
|= PIPE_MASK_R
;
406 blend
.colormask
|= PIPE_MASK_G
;
407 blend
.colormask
|= PIPE_MASK_B
;
408 blend
.colormask
|= PIPE_MASK_A
;
410 blend
.rgb_src_factor
= blend_opt
.rgb_src_factor
;
411 blend
.alpha_src_factor
= blend_opt
.alpha_src_factor
;
412 blend
.rgb_dst_factor
= blend_opt
.rgb_dst_factor
;
413 blend
.alpha_dst_factor
= blend_opt
.alpha_dst_factor
;
415 cso_set_blend(exa
->cso
, &blend
);
419 bind_rasterizer_state(struct exa_context
*exa
)
421 struct pipe_rasterizer_state raster
;
422 memset(&raster
, 0, sizeof(struct pipe_rasterizer_state
));
423 raster
.gl_rasterization_rules
= 1;
424 cso_set_rasterizer(exa
->cso
, &raster
);
428 bind_shaders(struct exa_context
*exa
, int op
,
429 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
431 unsigned vs_traits
= 0, fs_traits
= 0;
432 struct xorg_shader shader
;
434 exa
->has_solid_color
= FALSE
;
437 if (pSrcPicture
->pSourcePict
) {
438 if (pSrcPicture
->pSourcePict
->type
== SourcePictTypeSolidFill
) {
439 fs_traits
|= FS_SOLID_FILL
;
440 vs_traits
|= VS_SOLID_FILL
;
441 render_pixel_to_float4(pSrcPicture
->pFormat
,
442 pSrcPicture
->pSourcePict
->solidFill
.color
,
444 exa
->has_solid_color
= TRUE
;
446 debug_assert("!gradients not supported");
449 fs_traits
|= FS_COMPOSITE
;
450 vs_traits
|= VS_COMPOSITE
;
455 vs_traits
|= VS_MASK
;
456 fs_traits
|= FS_MASK
;
459 shader
= xorg_shaders_get(exa
->shaders
, vs_traits
, fs_traits
);
460 cso_set_vertex_shader_handle(exa
->cso
, shader
.vs
);
461 cso_set_fragment_shader_handle(exa
->cso
, shader
.fs
);
466 bind_samplers(struct exa_context
*exa
, int op
,
467 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
,
468 PicturePtr pDstPicture
,
469 struct exa_pixmap_priv
*pSrc
,
470 struct exa_pixmap_priv
*pMask
,
471 struct exa_pixmap_priv
*pDst
)
473 struct pipe_sampler_state
*samplers
[PIPE_MAX_SAMPLERS
];
474 struct pipe_sampler_state src_sampler
, mask_sampler
;
476 exa
->num_bound_samplers
= 0;
478 memset(&src_sampler
, 0, sizeof(struct pipe_sampler_state
));
479 memset(&mask_sampler
, 0, sizeof(struct pipe_sampler_state
));
481 if (pSrcPicture
&& pSrc
) {
482 unsigned src_wrap
= render_repeat_to_gallium(
483 pSrcPicture
->repeatType
);
484 src_sampler
.wrap_s
= src_wrap
;
485 src_sampler
.wrap_t
= src_wrap
;
486 src_sampler
.min_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
487 src_sampler
.mag_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
488 src_sampler
.normalized_coords
= 1;
489 samplers
[0] = &src_sampler
;
490 exa
->bound_textures
[0] = pSrc
->tex
;
491 ++exa
->num_bound_samplers
;
494 if (pMaskPicture
&& pMask
) {
495 unsigned mask_wrap
= render_repeat_to_gallium(
496 pMaskPicture
->repeatType
);
497 mask_sampler
.wrap_s
= mask_wrap
;
498 mask_sampler
.wrap_t
= mask_wrap
;
499 mask_sampler
.min_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
500 mask_sampler
.mag_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
501 mask_sampler
.normalized_coords
= 1;
502 samplers
[1] = &mask_sampler
;
503 exa
->bound_textures
[1] = pMask
->tex
;
504 ++exa
->num_bound_samplers
;
507 cso_set_samplers(exa
->cso
, exa
->num_bound_samplers
,
508 (const struct pipe_sampler_state
**)samplers
);
509 cso_set_sampler_textures(exa
->cso
, exa
->num_bound_samplers
,
510 exa
->bound_textures
);
514 setup_vs_constant_buffer(struct exa_context
*exa
,
515 int width
, int height
)
517 const int param_bytes
= 8 * sizeof(float);
518 float vs_consts
[8] = {
519 2.f
/width
, 2.f
/height
, 1, 1,
522 struct pipe_constant_buffer
*cbuf
= &exa
->vs_const_buffer
;
524 pipe_buffer_reference(&cbuf
->buffer
, NULL
);
525 cbuf
->buffer
= pipe_buffer_create(exa
->pipe
->screen
, 16,
526 PIPE_BUFFER_USAGE_CONSTANT
,
530 pipe_buffer_write(exa
->pipe
->screen
, cbuf
->buffer
,
531 0, param_bytes
, vs_consts
);
533 exa
->pipe
->set_constant_buffer(exa
->pipe
, PIPE_SHADER_VERTEX
, 0, cbuf
);
538 setup_fs_constant_buffer(struct exa_context
*exa
)
540 const int param_bytes
= 4 * sizeof(float);
541 float fs_consts
[8] = {
544 struct pipe_constant_buffer
*cbuf
= &exa
->fs_const_buffer
;
546 pipe_buffer_reference(&cbuf
->buffer
, NULL
);
547 cbuf
->buffer
= pipe_buffer_create(exa
->pipe
->screen
, 16,
548 PIPE_BUFFER_USAGE_CONSTANT
,
552 pipe_buffer_write(exa
->pipe
->screen
, cbuf
->buffer
,
553 0, param_bytes
, fs_consts
);
555 exa
->pipe
->set_constant_buffer(exa
->pipe
, PIPE_SHADER_FRAGMENT
, 0, cbuf
);
559 setup_constant_buffers(struct exa_context
*exa
, struct exa_pixmap_priv
*pDst
)
561 int width
= pDst
->tex
->width
[0];
562 int height
= pDst
->tex
->height
[0];
564 setup_vs_constant_buffer(exa
, width
, height
);
565 setup_fs_constant_buffer(exa
);
568 boolean
xorg_composite_bind_state(struct exa_context
*exa
,
570 PicturePtr pSrcPicture
,
571 PicturePtr pMaskPicture
,
572 PicturePtr pDstPicture
,
573 struct exa_pixmap_priv
*pSrc
,
574 struct exa_pixmap_priv
*pMask
,
575 struct exa_pixmap_priv
*pDst
)
577 bind_framebuffer_state(exa
, pDst
);
578 bind_viewport_state(exa
, pDst
);
579 bind_blend_state(exa
, op
, pSrcPicture
, pMaskPicture
);
580 bind_rasterizer_state(exa
);
581 bind_shaders(exa
, op
, pSrcPicture
, pMaskPicture
);
582 bind_samplers(exa
, op
, pSrcPicture
, pMaskPicture
,
583 pDstPicture
, pSrc
, pMask
, pDst
);
584 bind_clip_state(exa
);
585 setup_constant_buffers(exa
, pDst
);
590 void xorg_composite(struct exa_context
*exa
,
591 struct exa_pixmap_priv
*dst
,
592 int srcX
, int srcY
, int maskX
, int maskY
,
593 int dstX
, int dstY
, int width
, int height
)
595 struct pipe_context
*pipe
= exa
->pipe
;
596 struct pipe_buffer
*buf
= 0;
598 if (exa
->num_bound_samplers
== 0 ) { /* solid fill */
599 buf
= setup_vertex_data0(exa
,
600 srcX
, srcY
, maskX
, maskY
,
601 dstX
, dstY
, width
, height
);
602 } else if (exa
->num_bound_samplers
== 1 ) /* src */
603 buf
= setup_vertex_data1(exa
,
604 srcX
, srcY
, maskX
, maskY
,
605 dstX
, dstY
, width
, height
);
606 else if (exa
->num_bound_samplers
== 2) /* src + mask */
607 buf
= setup_vertex_data2(exa
,
608 srcX
, srcY
, maskX
, maskY
,
609 dstX
, dstY
, width
, height
);
610 else if (exa
->num_bound_samplers
== 3) { /* src + mask + dst */
611 debug_assert(!"src/mask/dst not handled right now");
613 buf
= setup_vertex_data2(exa
,
614 srcX
, srcY
, maskX
, maskY
,
615 dstX
, dstY
, width
, height
);
620 int num_attribs
= 1; /*pos*/
621 num_attribs
+= exa
->num_bound_samplers
;
622 if (exa
->has_solid_color
)
625 util_draw_vertex_buffer(pipe
, buf
, 0,
626 PIPE_PRIM_TRIANGLE_FAN
,
628 num_attribs
); /* attribs/vert */
630 pipe_buffer_reference(&buf
, NULL
);
634 boolean
xorg_solid_bind_state(struct exa_context
*exa
,
635 struct exa_pixmap_priv
*pixmap
,
638 unsigned vs_traits
, fs_traits
;
639 struct xorg_shader shader
;
641 pixel_to_float4(fg
, exa
->solid_color
);
642 exa
->has_solid_color
= TRUE
;
644 exa
->solid_color
[3] = 1.f
;
647 debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
648 (fg
>> 24) & 0xff, (fg
>> 16) & 0xff,
649 (fg
>> 8) & 0xff, (fg
>> 0) & 0xff,
650 exa
->solid_color
[0], exa
->solid_color
[1],
651 exa
->solid_color
[2], exa
->solid_color
[3]);
654 vs_traits
= VS_SOLID_FILL
;
655 fs_traits
= FS_SOLID_FILL
;
657 bind_framebuffer_state(exa
, pixmap
);
658 bind_viewport_state(exa
, pixmap
);
659 bind_rasterizer_state(exa
);
660 bind_blend_state(exa
, PictOpSrc
, NULL
, NULL
);
661 setup_constant_buffers(exa
, pixmap
);
662 bind_clip_state(exa
);
664 shader
= xorg_shaders_get(exa
->shaders
, vs_traits
, fs_traits
);
665 cso_set_vertex_shader_handle(exa
->cso
, shader
.vs
);
666 cso_set_fragment_shader_handle(exa
->cso
, shader
.fs
);
671 void xorg_solid(struct exa_context
*exa
,
672 struct exa_pixmap_priv
*pixmap
,
673 int x0
, int y0
, int x1
, int y1
)
675 struct pipe_context
*pipe
= exa
->pipe
;
676 struct pipe_buffer
*buf
= 0;
679 setup_vertex0(exa
->vertices2
[0], x0
, y0
,
682 setup_vertex0(exa
->vertices2
[1], x1
, y0
,
685 setup_vertex0(exa
->vertices2
[2], x1
, y1
,
688 setup_vertex0(exa
->vertices2
[3], x0
, y1
,
691 buf
= pipe_user_buffer_create(exa
->pipe
->screen
,
693 sizeof(exa
->vertices2
));
697 util_draw_vertex_buffer(pipe
, buf
, 0,
698 PIPE_PRIM_TRIANGLE_FAN
,
700 2); /* attribs/vert */
702 pipe_buffer_reference(&buf
, NULL
);
707 static INLINE
void shift_rectx(float coords
[4],
714 coords
[2] = MIN2(coords
[2], bounds
[2]);
715 /* bound x/y + width/height */
716 if ((coords
[0] + coords
[2]) > (bounds
[0] + bounds
[2])) {
717 coords
[2] = (bounds
[0] + bounds
[2]) - coords
[0];
722 static INLINE
void shift_recty(float coords
[4],
729 coords
[3] = MIN2(coords
[3], bounds
[3]);
730 if ((coords
[1] + coords
[3]) > (bounds
[1] + bounds
[3])) {
731 coords
[3] = (bounds
[1] + bounds
[3]) - coords
[1];
736 static INLINE
void bound_rect(float coords
[4],
737 const float bounds
[4],
740 /* if outside the bounds */
741 if (coords
[0] > (bounds
[0] + bounds
[2]) ||
742 coords
[1] > (bounds
[1] + bounds
[3]) ||
743 (coords
[0] + coords
[2]) < bounds
[0] ||
744 (coords
[1] + coords
[3]) < bounds
[1]) {
755 if (coords
[0] < bounds
[0]) {
756 shift
[0] = bounds
[0] - coords
[0];
757 coords
[2] -= shift
[0];
758 coords
[0] = bounds
[0];
763 if (coords
[1] < bounds
[1]) {
764 shift
[1] = bounds
[1] - coords
[1];
765 coords
[3] -= shift
[1];
766 coords
[1] = bounds
[1];
770 shift
[2] = bounds
[2] - coords
[2];
771 shift
[3] = bounds
[3] - coords
[3];
772 /* bound width/height */
773 coords
[2] = MIN2(coords
[2], bounds
[2]);
774 coords
[3] = MIN2(coords
[3], bounds
[3]);
776 /* bound x/y + width/height */
777 if ((coords
[0] + coords
[2]) > (bounds
[0] + bounds
[2])) {
778 coords
[2] = (bounds
[0] + bounds
[2]) - coords
[0];
780 if ((coords
[1] + coords
[3]) > (bounds
[1] + bounds
[3])) {
781 coords
[3] = (bounds
[1] + bounds
[3]) - coords
[1];
784 /* if outside the bounds */
785 if ((coords
[0] + coords
[2]) < bounds
[0] ||
786 (coords
[1] + coords
[3]) < bounds
[1]) {
795 static INLINE
void sync_size(float *src_loc
, float *dst_loc
)
797 src_loc
[2] = MIN2(src_loc
[2], dst_loc
[2]);
798 src_loc
[3] = MIN2(src_loc
[3], dst_loc
[3]);
799 dst_loc
[2] = src_loc
[2];
800 dst_loc
[3] = src_loc
[3];
804 static void renderer_copy_texture(struct exa_context
*exa
,
805 struct pipe_texture
*src
,
806 float sx1
, float sy1
,
807 float sx2
, float sy2
,
808 struct pipe_texture
*dst
,
809 float dx1
, float dy1
,
810 float dx2
, float dy2
)
812 struct pipe_context
*pipe
= exa
->pipe
;
813 struct pipe_screen
*screen
= pipe
->screen
;
814 struct pipe_buffer
*buf
;
815 struct pipe_surface
*dst_surf
= screen
->get_tex_surface(
816 screen
, dst
, 0, 0, 0,
817 PIPE_BUFFER_USAGE_GPU_WRITE
);
818 struct pipe_framebuffer_state fb
;
819 float s0
, t0
, s1
, t1
;
820 struct xorg_shader shader
;
822 assert(src
->width
[0] != 0);
823 assert(src
->height
[0] != 0);
824 assert(dst
->width
[0] != 0);
825 assert(dst
->height
[0] != 0);
828 s0
= sx1
/ src
->width
[0];
829 s1
= sx2
/ src
->width
[0];
830 t0
= sy1
/ src
->height
[0];
831 t1
= sy2
/ src
->height
[0];
840 debug_printf("copy texture src=[%f, %f, %f, %f], dst=[%f, %f, %f, %f], tex=[%f, %f, %f, %f]\n",
841 sx1
, sy1
, sx2
, sy2
, dx1
, dy1
, dx2
, dy2
,
845 assert(screen
->is_format_supported(screen
, dst_surf
->format
,
847 PIPE_TEXTURE_USAGE_RENDER_TARGET
,
850 /* save state (restored below) */
851 cso_save_blend(exa
->cso
);
852 cso_save_samplers(exa
->cso
);
853 cso_save_sampler_textures(exa
->cso
);
854 cso_save_framebuffer(exa
->cso
);
855 cso_save_fragment_shader(exa
->cso
);
856 cso_save_vertex_shader(exa
->cso
);
858 cso_save_viewport(exa
->cso
);
861 /* set misc state we care about */
863 struct pipe_blend_state blend
;
864 memset(&blend
, 0, sizeof(blend
));
865 blend
.rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
866 blend
.alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
867 blend
.rgb_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
868 blend
.alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
869 blend
.colormask
= PIPE_MASK_RGBA
;
870 cso_set_blend(exa
->cso
, &blend
);
875 struct pipe_sampler_state sampler
;
876 memset(&sampler
, 0, sizeof(sampler
));
877 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
878 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
879 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
880 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
881 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
882 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
883 sampler
.normalized_coords
= 1;
884 cso_single_sampler(exa
->cso
, 0, &sampler
);
885 cso_single_sampler_done(exa
->cso
);
888 set_viewport(exa
, dst_surf
->width
, dst_surf
->height
, Y0_TOP
);
891 cso_set_sampler_textures(exa
->cso
, 1, &src
);
894 shader
= xorg_shaders_get(exa
->shaders
,
897 cso_set_vertex_shader_handle(exa
->cso
, shader
.vs
);
898 cso_set_fragment_shader_handle(exa
->cso
, shader
.fs
);
901 memset(&fb
, 0, sizeof(fb
));
902 fb
.width
= dst_surf
->width
;
903 fb
.height
= dst_surf
->height
;
905 fb
.cbufs
[0] = dst_surf
;
908 for (i
= 1; i
< PIPE_MAX_COLOR_BUFS
; ++i
)
911 cso_set_framebuffer(exa
->cso
, &fb
);
912 setup_vs_constant_buffer(exa
, fb
.width
, fb
.height
);
913 setup_fs_constant_buffer(exa
);
916 buf
= setup_vertex_data_tex(exa
,
923 util_draw_vertex_buffer(exa
->pipe
, buf
, 0,
924 PIPE_PRIM_TRIANGLE_FAN
,
926 2); /* attribs/vert */
928 pipe_buffer_reference(&buf
, NULL
);
931 /* restore state we changed */
932 cso_restore_blend(exa
->cso
);
933 cso_restore_samplers(exa
->cso
);
934 cso_restore_sampler_textures(exa
->cso
);
935 cso_restore_framebuffer(exa
->cso
);
936 cso_restore_vertex_shader(exa
->cso
);
937 cso_restore_fragment_shader(exa
->cso
);
938 cso_restore_viewport(exa
->cso
);
940 pipe_surface_reference(&dst_surf
, NULL
);
944 static struct pipe_texture
*
945 create_sampler_texture(struct exa_context
*ctx
,
946 struct pipe_texture
*src
)
948 enum pipe_format format
;
949 struct pipe_context
*pipe
= ctx
->pipe
;
950 struct pipe_screen
*screen
= pipe
->screen
;
951 struct pipe_texture
*pt
;
952 struct pipe_texture templ
;
954 pipe
->flush(pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
956 /* the coming in texture should already have that invariance */
957 debug_assert(screen
->is_format_supported(screen
, src
->format
,
959 PIPE_TEXTURE_USAGE_SAMPLER
, 0));
961 format
= src
->format
;
963 memset(&templ
, 0, sizeof(templ
));
964 templ
.target
= PIPE_TEXTURE_2D
;
965 templ
.format
= format
;
966 templ
.last_level
= 0;
967 templ
.width
[0] = src
->width
[0];
968 templ
.height
[0] = src
->height
[0];
970 pf_get_block(format
, &templ
.block
);
971 templ
.tex_usage
= PIPE_TEXTURE_USAGE_SAMPLER
;
973 pt
= screen
->texture_create(screen
, &templ
);
975 debug_assert(!pt
|| pipe_is_referenced(&pt
->reference
));
981 /* copy source framebuffer surface into texture */
982 struct pipe_surface
*ps_read
= screen
->get_tex_surface(
983 screen
, src
, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ
);
984 struct pipe_surface
*ps_tex
= screen
->get_tex_surface(
985 screen
, pt
, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE
);
986 pipe
->surface_copy(pipe
,
990 0, 0, src
->width
[0], src
->height
[0]);
991 pipe_surface_reference(&ps_read
, NULL
);
992 pipe_surface_reference(&ps_tex
, NULL
);
998 void xorg_copy_pixmap(struct exa_context
*ctx
,
999 struct exa_pixmap_priv
*dst_priv
, int dx
, int dy
,
1000 struct exa_pixmap_priv
*src_priv
, int sx
, int sy
,
1001 int width
, int height
)
1003 float dst_loc
[4], src_loc
[4];
1004 float dst_bounds
[4], src_bounds
[4];
1005 float src_shift
[4], dst_shift
[4], shift
[4];
1006 struct pipe_texture
*dst
= dst_priv
->tex
;
1007 struct pipe_texture
*src
= src_priv
->tex
;
1009 xorg_exa_finish(ctx
);
1014 dst_loc
[3] = height
;
1015 dst_bounds
[0] = 0.f
;
1016 dst_bounds
[1] = 0.f
;
1017 dst_bounds
[2] = dst
->width
[0];
1018 dst_bounds
[3] = dst
->height
[0];
1023 src_loc
[3] = height
;
1024 src_bounds
[0] = 0.f
;
1025 src_bounds
[1] = 0.f
;
1026 src_bounds
[2] = src
->width
[0];
1027 src_bounds
[3] = src
->height
[0];
1029 bound_rect(src_loc
, src_bounds
, src_shift
);
1030 bound_rect(dst_loc
, dst_bounds
, dst_shift
);
1031 shift
[0] = src_shift
[0] - dst_shift
[0];
1032 shift
[1] = src_shift
[1] - dst_shift
[1];
1035 shift_rectx(src_loc
, src_bounds
, -shift
[0]);
1037 shift_rectx(dst_loc
, dst_bounds
, shift
[0]);
1040 shift_recty(src_loc
, src_bounds
, -shift
[1]);
1042 shift_recty(dst_loc
, dst_bounds
, shift
[1]);
1044 sync_size(src_loc
, dst_loc
);
1046 if (src_loc
[2] >= 0 && src_loc
[3] >= 0 &&
1047 dst_loc
[2] >= 0 && dst_loc
[3] >= 0) {
1048 struct pipe_texture
*temp_src
= src
;
1051 temp_src
= create_sampler_texture(ctx
, src
);
1053 renderer_copy_texture(ctx
,
1057 src_loc
[0] + src_loc
[2],
1058 src_loc
[1] + src_loc
[3],
1062 dst_loc
[0] + dst_loc
[2],
1063 dst_loc
[1] + dst_loc
[3]);
1066 pipe_texture_reference(&temp_src
, NULL
);