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.;
60 struct acceleration_info
{
63 int component_alpha
: 1;
65 static const struct acceleration_info accelerated_ops
[] = {
70 {PictOpOverReverse
, 1, 0},
72 {PictOpInReverse
, 1, 0},
74 {PictOpOutReverse
, 1, 0},
76 {PictOpAtopReverse
, 1, 0},
79 {PictOpSaturate
, 1, 0},
82 static struct xorg_composite_blend
85 const int num_blends
=
86 sizeof(xorg_blends
)/sizeof(struct xorg_composite_blend
);
89 for (i
= 0; i
< num_blends
; ++i
) {
90 if (xorg_blends
[i
].op
== op
)
91 return xorg_blends
[i
];
93 return xorg_blends
[BLEND_OP_OVER
];
97 render_repeat_to_gallium(int mode
)
101 return PIPE_TEX_WRAP_CLAMP
;
103 return PIPE_TEX_WRAP_REPEAT
;
105 return PIPE_TEX_WRAP_MIRROR_REPEAT
;
107 return PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
109 debug_printf("Unsupported repeat mode\n");
111 return PIPE_TEX_WRAP_REPEAT
;
116 setup_vertex0(float vertex
[2][4], float x
, float y
,
121 vertex
[0][2] = 0.f
; /*z*/
122 vertex
[0][3] = 1.f
; /*w*/
124 vertex
[1][0] = color
[0]; /*r*/
125 vertex
[1][1] = color
[1]; /*g*/
126 vertex
[1][2] = color
[2]; /*b*/
127 vertex
[1][3] = color
[3]; /*a*/
130 static struct pipe_buffer
*
131 setup_vertex_data0(struct exa_context
*ctx
,
132 int srcX
, int srcY
, int maskX
, int maskY
,
133 int dstX
, int dstY
, int width
, int height
)
136 setup_vertex0(ctx
->vertices2
[0], dstX
, dstY
,
139 setup_vertex0(ctx
->vertices2
[1], dstX
+ width
, dstY
,
142 setup_vertex0(ctx
->vertices2
[2], dstX
+ width
, dstY
+ height
,
145 setup_vertex0(ctx
->vertices2
[3], dstX
, dstY
+ height
,
148 return pipe_user_buffer_create(ctx
->pipe
->screen
,
150 sizeof(ctx
->vertices2
));
154 setup_vertex1(float vertex
[2][4], float x
, float y
, float s
, float t
)
158 vertex
[0][2] = 0.f
; /*z*/
159 vertex
[0][3] = 1.f
; /*w*/
161 vertex
[1][0] = s
; /*s*/
162 vertex
[1][1] = t
; /*t*/
163 vertex
[1][2] = 0.f
; /*r*/
164 vertex
[1][3] = 1.f
; /*q*/
167 static struct pipe_buffer
*
168 setup_vertex_data1(struct exa_context
*ctx
,
169 int srcX
, int srcY
, int maskX
, int maskY
,
170 int dstX
, int dstY
, int width
, int height
)
172 float s0
, t0
, s1
, t1
;
173 struct pipe_texture
*src
= ctx
->bound_textures
[0];
175 s0
= srcX
/ src
->width
[0];
176 s1
= srcX
+ width
/ src
->width
[0];
177 t0
= srcY
/ src
->height
[0];
178 t1
= srcY
+ height
/ src
->height
[0];
181 setup_vertex1(ctx
->vertices2
[0], dstX
, dstY
,
184 setup_vertex1(ctx
->vertices2
[1], dstX
+ width
, dstY
,
187 setup_vertex1(ctx
->vertices2
[2], dstX
+ width
, dstY
+ height
,
190 setup_vertex1(ctx
->vertices2
[3], dstX
, dstY
+ height
,
193 return pipe_user_buffer_create(ctx
->pipe
->screen
,
195 sizeof(ctx
->vertices2
));
198 static struct pipe_buffer
*
199 setup_vertex_data_tex(struct exa_context
*ctx
,
200 float x0
, float y0
, float x1
, float y1
,
201 float s0
, float t0
, float s1
, float t1
,
205 setup_vertex1(ctx
->vertices2
[0], x0
, y0
,
208 setup_vertex1(ctx
->vertices2
[1], x1
, y0
,
211 setup_vertex1(ctx
->vertices2
[2], x1
, y1
,
214 setup_vertex1(ctx
->vertices2
[3], x0
, y1
,
217 return pipe_user_buffer_create(ctx
->pipe
->screen
,
219 sizeof(ctx
->vertices2
));
225 setup_vertex2(float vertex
[3][4], float x
, float y
,
226 float s0
, float t0
, float s1
, float t1
)
230 vertex
[0][2] = 0.f
; /*z*/
231 vertex
[0][3] = 1.f
; /*w*/
233 vertex
[1][0] = s0
; /*s*/
234 vertex
[1][1] = t0
; /*t*/
235 vertex
[1][2] = 0.f
; /*r*/
236 vertex
[1][3] = 1.f
; /*q*/
238 vertex
[2][0] = s1
; /*s*/
239 vertex
[2][1] = t1
; /*t*/
240 vertex
[2][2] = 0.f
; /*r*/
241 vertex
[2][3] = 1.f
; /*q*/
244 static struct pipe_buffer
*
245 setup_vertex_data2(struct exa_context
*ctx
,
246 int srcX
, int srcY
, int maskX
, int maskY
,
247 int dstX
, int dstY
, int width
, int height
)
249 float st0
[4], st1
[4];
250 struct pipe_texture
*src
= ctx
->bound_textures
[0];
251 struct pipe_texture
*mask
= ctx
->bound_textures
[0];
253 st0
[0] = srcX
/ src
->width
[0];
254 st0
[1] = srcY
/ src
->height
[0];
255 st0
[2] = srcX
+ width
/ src
->width
[0];
256 st0
[3] = srcY
+ height
/ src
->height
[0];
258 st1
[0] = maskX
/ mask
->width
[0];
259 st1
[1] = maskY
/ mask
->height
[0];
260 st1
[2] = maskX
+ width
/ mask
->width
[0];
261 st1
[3] = maskY
+ height
/ mask
->height
[0];
264 setup_vertex2(ctx
->vertices3
[0], dstX
, dstY
,
265 st0
[0], st0
[1], st1
[0], st1
[1]);
267 setup_vertex2(ctx
->vertices3
[1], dstX
+ width
, dstY
,
268 st0
[2], st0
[1], st1
[2], st1
[1]);
270 setup_vertex2(ctx
->vertices3
[2], dstX
+ width
, dstY
+ height
,
271 st0
[2], st0
[3], st1
[2], st1
[3]);
273 setup_vertex2(ctx
->vertices3
[3], dstX
, dstY
+ height
,
274 st0
[0], st0
[3], st1
[0], st1
[3]);
276 return pipe_user_buffer_create(ctx
->pipe
->screen
,
278 sizeof(ctx
->vertices3
));
281 boolean
xorg_composite_accelerated(int op
,
282 PicturePtr pSrcPicture
,
283 PicturePtr pMaskPicture
,
284 PicturePtr pDstPicture
)
287 unsigned accel_ops_count
=
288 sizeof(accelerated_ops
)/sizeof(struct acceleration_info
);
290 if (pSrcPicture
->pSourcePict
) {
291 /* Gradients not yet supported */
292 if (pSrcPicture
->pSourcePict
->type
!= SourcePictTypeSolidFill
)
295 /* Solid source with mask not yet handled properly */
300 for (i
= 0; i
< accel_ops_count
; ++i
) {
301 if (op
== accelerated_ops
[i
].op
) {
302 /* Check for unsupported component alpha */
303 if ((pSrcPicture
->componentAlpha
&&
304 !accelerated_ops
[i
].component_alpha
) ||
306 (!accelerated_ops
[i
].with_mask
||
307 (pMaskPicture
->componentAlpha
&&
308 !accelerated_ops
[i
].component_alpha
))))
317 bind_clip_state(struct exa_context
*exa
)
322 bind_framebuffer_state(struct exa_context
*exa
, struct exa_pixmap_priv
*pDst
)
325 struct pipe_framebuffer_state state
;
326 struct pipe_surface
*surface
= exa_gpu_surface(exa
, pDst
);
327 memset(&state
, 0, sizeof(struct pipe_framebuffer_state
));
329 state
.width
= pDst
->tex
->width
[0];
330 state
.height
= pDst
->tex
->height
[0];
333 state
.cbufs
[0] = surface
;
334 for (i
= 1; i
< PIPE_MAX_COLOR_BUFS
; ++i
)
337 /* currently we don't use depth/stencil */
340 cso_set_framebuffer(exa
->cso
, &state
);
342 /* we do fire and forget for the framebuffer, this is the forget part */
343 pipe_surface_reference(&surface
, NULL
);
346 enum AxisOrientation
{
352 set_viewport(struct exa_context
*exa
, int width
, int height
,
353 enum AxisOrientation orientation
)
355 struct pipe_viewport_state viewport
;
356 float y_scale
= (orientation
== Y0_BOTTOM
) ? -2.f
: 2.f
;
358 viewport
.scale
[0] = width
/ 2.f
;
359 viewport
.scale
[1] = height
/ y_scale
;
360 viewport
.scale
[2] = 1.0;
361 viewport
.scale
[3] = 1.0;
362 viewport
.translate
[0] = width
/ 2.f
;
363 viewport
.translate
[1] = height
/ 2.f
;
364 viewport
.translate
[2] = 0.0;
365 viewport
.translate
[3] = 0.0;
367 cso_set_viewport(exa
->cso
, &viewport
);
371 bind_viewport_state(struct exa_context
*exa
, struct exa_pixmap_priv
*pDst
)
373 int width
= pDst
->tex
->width
[0];
374 int height
= pDst
->tex
->height
[0];
376 /*debug_printf("Bind viewport (%d, %d)\n", width, height);*/
378 set_viewport(exa
, width
, height
, Y0_TOP
);
382 bind_blend_state(struct exa_context
*exa
, int op
,
383 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
385 struct xorg_composite_blend blend_opt
;
386 struct pipe_blend_state blend
;
388 blend_opt
= blend_for_op(op
);
390 memset(&blend
, 0, sizeof(struct pipe_blend_state
));
391 blend
.blend_enable
= 1;
392 blend
.colormask
|= PIPE_MASK_R
;
393 blend
.colormask
|= PIPE_MASK_G
;
394 blend
.colormask
|= PIPE_MASK_B
;
395 blend
.colormask
|= PIPE_MASK_A
;
397 blend
.rgb_src_factor
= blend_opt
.rgb_src_factor
;
398 blend
.alpha_src_factor
= blend_opt
.alpha_src_factor
;
399 blend
.rgb_dst_factor
= blend_opt
.rgb_dst_factor
;
400 blend
.alpha_dst_factor
= blend_opt
.alpha_dst_factor
;
402 cso_set_blend(exa
->cso
, &blend
);
406 bind_rasterizer_state(struct exa_context
*exa
)
408 struct pipe_rasterizer_state raster
;
409 memset(&raster
, 0, sizeof(struct pipe_rasterizer_state
));
410 raster
.gl_rasterization_rules
= 1;
411 cso_set_rasterizer(exa
->cso
, &raster
);
415 bind_shaders(struct exa_context
*exa
, int op
,
416 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
)
418 unsigned vs_traits
= 0, fs_traits
= 0;
419 struct xorg_shader shader
;
421 exa
->has_solid_color
= FALSE
;
424 if (pSrcPicture
->pSourcePict
) {
425 if (pSrcPicture
->pSourcePict
->type
== SourcePictTypeSolidFill
) {
426 fs_traits
|= FS_SOLID_FILL
;
427 vs_traits
|= VS_SOLID_FILL
;
428 debug_assert(pSrcPicture
->format
== PICT_a8r8g8b8
);
429 pixel_to_float4(pSrcPicture
->pSourcePict
->solidFill
.color
,
431 exa
->has_solid_color
= TRUE
;
433 debug_assert("!gradients not supported");
436 fs_traits
|= FS_COMPOSITE
;
437 vs_traits
|= VS_COMPOSITE
;
442 vs_traits
|= VS_MASK
;
443 fs_traits
|= FS_MASK
;
446 shader
= xorg_shaders_get(exa
->shaders
, vs_traits
, fs_traits
);
447 cso_set_vertex_shader_handle(exa
->cso
, shader
.vs
);
448 cso_set_fragment_shader_handle(exa
->cso
, shader
.fs
);
453 bind_samplers(struct exa_context
*exa
, int op
,
454 PicturePtr pSrcPicture
, PicturePtr pMaskPicture
,
455 PicturePtr pDstPicture
,
456 struct exa_pixmap_priv
*pSrc
,
457 struct exa_pixmap_priv
*pMask
,
458 struct exa_pixmap_priv
*pDst
)
460 struct pipe_sampler_state
*samplers
[PIPE_MAX_SAMPLERS
];
461 struct pipe_sampler_state src_sampler
, mask_sampler
;
463 exa
->num_bound_samplers
= 0;
465 memset(&src_sampler
, 0, sizeof(struct pipe_sampler_state
));
466 memset(&mask_sampler
, 0, sizeof(struct pipe_sampler_state
));
468 if ((pSrc
&& exa
->pipe
->is_texture_referenced(exa
->pipe
, pSrc
->tex
, 0, 0) &
469 PIPE_REFERENCED_FOR_WRITE
) ||
470 (pMask
&& exa
->pipe
->is_texture_referenced(exa
->pipe
, pMask
->tex
, 0, 0) &
471 PIPE_REFERENCED_FOR_WRITE
))
472 exa
->pipe
->flush(exa
->pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
474 if (pSrcPicture
&& pSrc
) {
475 unsigned src_wrap
= render_repeat_to_gallium(
476 pSrcPicture
->repeatType
);
477 src_sampler
.wrap_s
= src_wrap
;
478 src_sampler
.wrap_t
= src_wrap
;
479 src_sampler
.min_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
480 src_sampler
.mag_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
481 src_sampler
.normalized_coords
= 1;
482 samplers
[0] = &src_sampler
;
483 exa
->bound_textures
[0] = pSrc
->tex
;
484 ++exa
->num_bound_samplers
;
487 if (pMaskPicture
&& pMask
) {
488 unsigned mask_wrap
= render_repeat_to_gallium(
489 pMaskPicture
->repeatType
);
490 mask_sampler
.wrap_s
= mask_wrap
;
491 mask_sampler
.wrap_t
= mask_wrap
;
492 mask_sampler
.min_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
493 mask_sampler
.mag_img_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
494 mask_sampler
.normalized_coords
= 1;
495 samplers
[1] = &mask_sampler
;
496 exa
->bound_textures
[1] = pMask
->tex
;
497 ++exa
->num_bound_samplers
;
500 cso_set_samplers(exa
->cso
, exa
->num_bound_samplers
,
501 (const struct pipe_sampler_state
**)samplers
);
502 cso_set_sampler_textures(exa
->cso
, exa
->num_bound_samplers
,
503 exa
->bound_textures
);
507 setup_vs_constant_buffer(struct exa_context
*exa
,
508 int width
, int height
)
510 const int param_bytes
= 8 * sizeof(float);
511 float vs_consts
[8] = {
512 2.f
/width
, 2.f
/height
, 1, 1,
515 struct pipe_constant_buffer
*cbuf
= &exa
->vs_const_buffer
;
517 pipe_buffer_reference(&cbuf
->buffer
, NULL
);
518 cbuf
->buffer
= pipe_buffer_create(exa
->pipe
->screen
, 16,
519 PIPE_BUFFER_USAGE_CONSTANT
,
523 pipe_buffer_write(exa
->pipe
->screen
, cbuf
->buffer
,
524 0, param_bytes
, vs_consts
);
526 exa
->pipe
->set_constant_buffer(exa
->pipe
, PIPE_SHADER_VERTEX
, 0, cbuf
);
531 setup_fs_constant_buffer(struct exa_context
*exa
)
533 const int param_bytes
= 4 * sizeof(float);
534 float fs_consts
[8] = {
537 struct pipe_constant_buffer
*cbuf
= &exa
->fs_const_buffer
;
539 pipe_buffer_reference(&cbuf
->buffer
, NULL
);
540 cbuf
->buffer
= pipe_buffer_create(exa
->pipe
->screen
, 16,
541 PIPE_BUFFER_USAGE_CONSTANT
,
545 pipe_buffer_write(exa
->pipe
->screen
, cbuf
->buffer
,
546 0, param_bytes
, fs_consts
);
548 exa
->pipe
->set_constant_buffer(exa
->pipe
, PIPE_SHADER_FRAGMENT
, 0, cbuf
);
552 setup_constant_buffers(struct exa_context
*exa
, struct exa_pixmap_priv
*pDst
)
554 int width
= pDst
->tex
->width
[0];
555 int height
= pDst
->tex
->height
[0];
557 setup_vs_constant_buffer(exa
, width
, height
);
558 setup_fs_constant_buffer(exa
);
561 boolean
xorg_composite_bind_state(struct exa_context
*exa
,
563 PicturePtr pSrcPicture
,
564 PicturePtr pMaskPicture
,
565 PicturePtr pDstPicture
,
566 struct exa_pixmap_priv
*pSrc
,
567 struct exa_pixmap_priv
*pMask
,
568 struct exa_pixmap_priv
*pDst
)
570 bind_framebuffer_state(exa
, pDst
);
571 bind_viewport_state(exa
, pDst
);
572 bind_blend_state(exa
, op
, pSrcPicture
, pMaskPicture
);
573 bind_rasterizer_state(exa
);
574 bind_shaders(exa
, op
, pSrcPicture
, pMaskPicture
);
575 bind_samplers(exa
, op
, pSrcPicture
, pMaskPicture
,
576 pDstPicture
, pSrc
, pMask
, pDst
);
577 bind_clip_state(exa
);
578 setup_constant_buffers(exa
, pDst
);
583 void xorg_composite(struct exa_context
*exa
,
584 struct exa_pixmap_priv
*dst
,
585 int srcX
, int srcY
, int maskX
, int maskY
,
586 int dstX
, int dstY
, int width
, int height
)
588 struct pipe_context
*pipe
= exa
->pipe
;
589 struct pipe_buffer
*buf
= 0;
591 if (exa
->num_bound_samplers
== 0 ) { /* solid fill */
592 buf
= setup_vertex_data0(exa
,
593 srcX
, srcY
, maskX
, maskY
,
594 dstX
, dstY
, width
, height
);
595 } else if (exa
->num_bound_samplers
== 1 ) /* src */
596 buf
= setup_vertex_data1(exa
,
597 srcX
, srcY
, maskX
, maskY
,
598 dstX
, dstY
, width
, height
);
599 else if (exa
->num_bound_samplers
== 2) /* src + mask */
600 buf
= setup_vertex_data2(exa
,
601 srcX
, srcY
, maskX
, maskY
,
602 dstX
, dstY
, width
, height
);
603 else if (exa
->num_bound_samplers
== 3) { /* src + mask + dst */
604 debug_assert(!"src/mask/dst not handled right now");
606 buf
= setup_vertex_data2(exa
,
607 srcX
, srcY
, maskX
, maskY
,
608 dstX
, dstY
, width
, height
);
613 int num_attribs
= 1; /*pos*/
614 num_attribs
+= exa
->num_bound_samplers
;
615 if (exa
->has_solid_color
)
618 util_draw_vertex_buffer(pipe
, buf
, 0,
619 PIPE_PRIM_TRIANGLE_FAN
,
621 num_attribs
); /* attribs/vert */
623 pipe_buffer_reference(&buf
, NULL
);
627 boolean
xorg_solid_bind_state(struct exa_context
*exa
,
628 struct exa_pixmap_priv
*pixmap
,
631 unsigned vs_traits
, fs_traits
;
632 struct xorg_shader shader
;
634 pixel_to_float4(fg
, exa
->solid_color
);
635 exa
->has_solid_color
= TRUE
;
637 exa
->solid_color
[3] = 1.f
;
640 debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
641 (fg
>> 24) & 0xff, (fg
>> 16) & 0xff,
642 (fg
>> 8) & 0xff, (fg
>> 0) & 0xff,
643 exa
->solid_color
[0], exa
->solid_color
[1],
644 exa
->solid_color
[2], exa
->solid_color
[3]);
647 vs_traits
= VS_SOLID_FILL
;
648 fs_traits
= FS_SOLID_FILL
;
650 bind_framebuffer_state(exa
, pixmap
);
651 bind_viewport_state(exa
, pixmap
);
652 bind_rasterizer_state(exa
);
653 bind_blend_state(exa
, PictOpSrc
, NULL
, NULL
);
654 setup_constant_buffers(exa
, pixmap
);
655 bind_clip_state(exa
);
657 shader
= xorg_shaders_get(exa
->shaders
, vs_traits
, fs_traits
);
658 cso_set_vertex_shader_handle(exa
->cso
, shader
.vs
);
659 cso_set_fragment_shader_handle(exa
->cso
, shader
.fs
);
664 void xorg_solid(struct exa_context
*exa
,
665 struct exa_pixmap_priv
*pixmap
,
666 int x0
, int y0
, int x1
, int y1
)
668 struct pipe_context
*pipe
= exa
->pipe
;
669 struct pipe_buffer
*buf
= 0;
672 setup_vertex0(exa
->vertices2
[0], x0
, y0
,
675 setup_vertex0(exa
->vertices2
[1], x1
, y0
,
678 setup_vertex0(exa
->vertices2
[2], x1
, y1
,
681 setup_vertex0(exa
->vertices2
[3], x0
, y1
,
684 buf
= pipe_user_buffer_create(exa
->pipe
->screen
,
686 sizeof(exa
->vertices2
));
690 util_draw_vertex_buffer(pipe
, buf
, 0,
691 PIPE_PRIM_TRIANGLE_FAN
,
693 2); /* attribs/vert */
695 pipe_buffer_reference(&buf
, NULL
);
700 static INLINE
void shift_rectx(float coords
[4],
707 coords
[2] = MIN2(coords
[2], bounds
[2]);
708 /* bound x/y + width/height */
709 if ((coords
[0] + coords
[2]) > (bounds
[0] + bounds
[2])) {
710 coords
[2] = (bounds
[0] + bounds
[2]) - coords
[0];
715 static INLINE
void shift_recty(float coords
[4],
722 coords
[3] = MIN2(coords
[3], bounds
[3]);
723 if ((coords
[1] + coords
[3]) > (bounds
[1] + bounds
[3])) {
724 coords
[3] = (bounds
[1] + bounds
[3]) - coords
[1];
729 static INLINE
void bound_rect(float coords
[4],
730 const float bounds
[4],
733 /* if outside the bounds */
734 if (coords
[0] > (bounds
[0] + bounds
[2]) ||
735 coords
[1] > (bounds
[1] + bounds
[3]) ||
736 (coords
[0] + coords
[2]) < bounds
[0] ||
737 (coords
[1] + coords
[3]) < bounds
[1]) {
748 if (coords
[0] < bounds
[0]) {
749 shift
[0] = bounds
[0] - coords
[0];
750 coords
[2] -= shift
[0];
751 coords
[0] = bounds
[0];
756 if (coords
[1] < bounds
[1]) {
757 shift
[1] = bounds
[1] - coords
[1];
758 coords
[3] -= shift
[1];
759 coords
[1] = bounds
[1];
763 shift
[2] = bounds
[2] - coords
[2];
764 shift
[3] = bounds
[3] - coords
[3];
765 /* bound width/height */
766 coords
[2] = MIN2(coords
[2], bounds
[2]);
767 coords
[3] = MIN2(coords
[3], bounds
[3]);
769 /* bound x/y + width/height */
770 if ((coords
[0] + coords
[2]) > (bounds
[0] + bounds
[2])) {
771 coords
[2] = (bounds
[0] + bounds
[2]) - coords
[0];
773 if ((coords
[1] + coords
[3]) > (bounds
[1] + bounds
[3])) {
774 coords
[3] = (bounds
[1] + bounds
[3]) - coords
[1];
777 /* if outside the bounds */
778 if ((coords
[0] + coords
[2]) < bounds
[0] ||
779 (coords
[1] + coords
[3]) < bounds
[1]) {
788 static INLINE
void sync_size(float *src_loc
, float *dst_loc
)
790 src_loc
[2] = MIN2(src_loc
[2], dst_loc
[2]);
791 src_loc
[3] = MIN2(src_loc
[3], dst_loc
[3]);
792 dst_loc
[2] = src_loc
[2];
793 dst_loc
[3] = src_loc
[3];
797 static void renderer_copy_texture(struct exa_context
*exa
,
798 struct pipe_texture
*src
,
799 float sx1
, float sy1
,
800 float sx2
, float sy2
,
801 struct pipe_texture
*dst
,
802 float dx1
, float dy1
,
803 float dx2
, float dy2
)
805 struct pipe_context
*pipe
= exa
->pipe
;
806 struct pipe_screen
*screen
= pipe
->screen
;
807 struct pipe_buffer
*buf
;
808 struct pipe_surface
*dst_surf
= screen
->get_tex_surface(
809 screen
, dst
, 0, 0, 0,
810 PIPE_BUFFER_USAGE_GPU_WRITE
);
811 struct pipe_framebuffer_state fb
;
812 float s0
, t0
, s1
, t1
;
813 struct xorg_shader shader
;
815 assert(src
->width
[0] != 0);
816 assert(src
->height
[0] != 0);
817 assert(dst
->width
[0] != 0);
818 assert(dst
->height
[0] != 0);
821 s0
= sx1
/ src
->width
[0];
822 s1
= sx2
/ src
->width
[0];
823 t0
= sy1
/ src
->height
[0];
824 t1
= sy2
/ src
->height
[0];
833 debug_printf("copy texture src=[%f, %f, %f, %f], dst=[%f, %f, %f, %f], tex=[%f, %f, %f, %f]\n",
834 sx1
, sy1
, sx2
, sy2
, dx1
, dy1
, dx2
, dy2
,
838 assert(screen
->is_format_supported(screen
, dst_surf
->format
,
840 PIPE_TEXTURE_USAGE_RENDER_TARGET
,
843 /* save state (restored below) */
844 cso_save_blend(exa
->cso
);
845 cso_save_samplers(exa
->cso
);
846 cso_save_sampler_textures(exa
->cso
);
847 cso_save_framebuffer(exa
->cso
);
848 cso_save_fragment_shader(exa
->cso
);
849 cso_save_vertex_shader(exa
->cso
);
851 cso_save_viewport(exa
->cso
);
854 /* set misc state we care about */
856 struct pipe_blend_state blend
;
857 memset(&blend
, 0, sizeof(blend
));
858 blend
.rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
859 blend
.alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
860 blend
.rgb_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
861 blend
.alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
862 blend
.colormask
= PIPE_MASK_RGBA
;
863 cso_set_blend(exa
->cso
, &blend
);
868 struct pipe_sampler_state sampler
;
869 memset(&sampler
, 0, sizeof(sampler
));
870 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
871 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
872 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
873 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
874 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
875 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
876 sampler
.normalized_coords
= 1;
877 cso_single_sampler(exa
->cso
, 0, &sampler
);
878 cso_single_sampler_done(exa
->cso
);
881 set_viewport(exa
, dst_surf
->width
, dst_surf
->height
, Y0_TOP
);
884 cso_set_sampler_textures(exa
->cso
, 1, &src
);
886 bind_rasterizer_state(exa
);
889 shader
= xorg_shaders_get(exa
->shaders
,
892 cso_set_vertex_shader_handle(exa
->cso
, shader
.vs
);
893 cso_set_fragment_shader_handle(exa
->cso
, shader
.fs
);
896 memset(&fb
, 0, sizeof(fb
));
897 fb
.width
= dst_surf
->width
;
898 fb
.height
= dst_surf
->height
;
900 fb
.cbufs
[0] = dst_surf
;
903 for (i
= 1; i
< PIPE_MAX_COLOR_BUFS
; ++i
)
906 cso_set_framebuffer(exa
->cso
, &fb
);
907 setup_vs_constant_buffer(exa
, fb
.width
, fb
.height
);
908 setup_fs_constant_buffer(exa
);
911 buf
= setup_vertex_data_tex(exa
,
918 util_draw_vertex_buffer(exa
->pipe
, buf
, 0,
919 PIPE_PRIM_TRIANGLE_FAN
,
921 2); /* attribs/vert */
923 pipe_buffer_reference(&buf
, NULL
);
926 /* restore state we changed */
927 cso_restore_blend(exa
->cso
);
928 cso_restore_samplers(exa
->cso
);
929 cso_restore_sampler_textures(exa
->cso
);
930 cso_restore_framebuffer(exa
->cso
);
931 cso_restore_vertex_shader(exa
->cso
);
932 cso_restore_fragment_shader(exa
->cso
);
933 cso_restore_viewport(exa
->cso
);
935 pipe_surface_reference(&dst_surf
, NULL
);
939 static struct pipe_texture
*
940 create_sampler_texture(struct exa_context
*ctx
,
941 struct pipe_texture
*src
)
943 enum pipe_format format
;
944 struct pipe_context
*pipe
= ctx
->pipe
;
945 struct pipe_screen
*screen
= pipe
->screen
;
946 struct pipe_texture
*pt
;
947 struct pipe_texture templ
;
949 pipe
->flush(pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
951 /* the coming in texture should already have that invariance */
952 debug_assert(screen
->is_format_supported(screen
, src
->format
,
954 PIPE_TEXTURE_USAGE_SAMPLER
, 0));
956 format
= src
->format
;
958 memset(&templ
, 0, sizeof(templ
));
959 templ
.target
= PIPE_TEXTURE_2D
;
960 templ
.format
= format
;
961 templ
.last_level
= 0;
962 templ
.width
[0] = src
->width
[0];
963 templ
.height
[0] = src
->height
[0];
965 pf_get_block(format
, &templ
.block
);
966 templ
.tex_usage
= PIPE_TEXTURE_USAGE_SAMPLER
;
968 pt
= screen
->texture_create(screen
, &templ
);
970 debug_assert(!pt
|| pipe_is_referenced(&pt
->reference
));
976 /* copy source framebuffer surface into texture */
977 struct pipe_surface
*ps_read
= screen
->get_tex_surface(
978 screen
, src
, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ
);
979 struct pipe_surface
*ps_tex
= screen
->get_tex_surface(
980 screen
, pt
, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE
);
981 pipe
->surface_copy(pipe
,
985 0, 0, src
->width
[0], src
->height
[0]);
986 pipe_surface_reference(&ps_read
, NULL
);
987 pipe_surface_reference(&ps_tex
, NULL
);
993 void xorg_copy_pixmap(struct exa_context
*ctx
,
994 struct exa_pixmap_priv
*dst_priv
, int dx
, int dy
,
995 struct exa_pixmap_priv
*src_priv
, int sx
, int sy
,
996 int width
, int height
)
998 float dst_loc
[4], src_loc
[4];
999 float dst_bounds
[4], src_bounds
[4];
1000 float src_shift
[4], dst_shift
[4], shift
[4];
1001 struct pipe_texture
*dst
= dst_priv
->tex
;
1002 struct pipe_texture
*src
= src_priv
->tex
;
1004 if (ctx
->pipe
->is_texture_referenced(ctx
->pipe
, src
, 0, 0) &
1005 PIPE_REFERENCED_FOR_WRITE
)
1006 ctx
->pipe
->flush(ctx
->pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
1011 dst_loc
[3] = height
;
1012 dst_bounds
[0] = 0.f
;
1013 dst_bounds
[1] = 0.f
;
1014 dst_bounds
[2] = dst
->width
[0];
1015 dst_bounds
[3] = dst
->height
[0];
1020 src_loc
[3] = height
;
1021 src_bounds
[0] = 0.f
;
1022 src_bounds
[1] = 0.f
;
1023 src_bounds
[2] = src
->width
[0];
1024 src_bounds
[3] = src
->height
[0];
1026 bound_rect(src_loc
, src_bounds
, src_shift
);
1027 bound_rect(dst_loc
, dst_bounds
, dst_shift
);
1028 shift
[0] = src_shift
[0] - dst_shift
[0];
1029 shift
[1] = src_shift
[1] - dst_shift
[1];
1032 shift_rectx(src_loc
, src_bounds
, -shift
[0]);
1034 shift_rectx(dst_loc
, dst_bounds
, shift
[0]);
1037 shift_recty(src_loc
, src_bounds
, -shift
[1]);
1039 shift_recty(dst_loc
, dst_bounds
, shift
[1]);
1041 sync_size(src_loc
, dst_loc
);
1043 if (src_loc
[2] >= 0 && src_loc
[3] >= 0 &&
1044 dst_loc
[2] >= 0 && dst_loc
[3] >= 0) {
1045 struct pipe_texture
*temp_src
= src
;
1048 temp_src
= create_sampler_texture(ctx
, src
);
1050 renderer_copy_texture(ctx
,
1054 src_loc
[0] + src_loc
[2],
1055 src_loc
[1] + src_loc
[3],
1059 dst_loc
[0] + dst_loc
[2],
1060 dst_loc
[1] + dst_loc
[3]);
1063 pipe_texture_reference(&temp_src
, NULL
);