2 #include "xorg_renderer.h"
4 #include "xorg_exa_tgsi.h"
6 #include "cso_cache/cso_context.h"
7 #include "util/u_draw_quad.h"
8 #include "util/u_math.h"
9 #include "util/u_memory.h"
10 #include "util/u_rect.h"
12 #include "pipe/p_inlines.h"
16 enum AxisOrientation
{
21 #define floatsEqual(x, y) (fabs(x - y) <= 0.00001f * MIN2(fabs(x), fabs(y)))
22 #define floatIsZero(x) (floatsEqual((x) + 1, 1))
24 #define NUM_COMPONENTS 4
26 static INLINE boolean
is_affine(float *matrix
)
28 return floatIsZero(matrix
[2]) && floatIsZero(matrix
[5])
29 && floatsEqual(matrix
[8], 1);
31 static INLINE
void map_point(float *mat
, float x
, float y
,
32 float *out_x
, float *out_y
)
40 *out_x
= mat
[0]*x
+ mat
[3]*y
+ mat
[6];
41 *out_y
= mat
[1]*x
+ mat
[4]*y
+ mat
[7];
42 if (!is_affine(mat
)) {
43 float w
= 1/(mat
[2]*x
+ mat
[5]*y
+ mat
[8]);
49 static INLINE
struct pipe_buffer
*
50 renderer_buffer_create(struct xorg_renderer
*r
)
52 struct pipe_buffer
*buf
=
53 pipe_user_buffer_create(r
->pipe
->screen
,
63 renderer_draw(struct xorg_renderer
*r
)
65 struct pipe_context
*pipe
= r
->pipe
;
66 struct pipe_buffer
*buf
= 0;
67 int num_verts
= r
->buffer_size
/(r
->attrs_per_vertex
* NUM_COMPONENTS
);
72 buf
= renderer_buffer_create(r
);
76 util_draw_vertex_buffer(pipe
, buf
, 0,
78 num_verts
, /* verts */
79 r
->attrs_per_vertex
); /* attribs/vert */
81 pipe_buffer_reference(&buf
, NULL
);
82 pipe
->flush(pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
87 renderer_draw_conditional(struct xorg_renderer
*r
,
90 if (r
->buffer_size
+ next_batch
>= BUF_SIZE
||
91 (next_batch
== 0 && r
->buffer_size
)) {
97 renderer_init_state(struct xorg_renderer
*r
)
99 struct pipe_depth_stencil_alpha_state dsa
;
100 struct pipe_rasterizer_state raster
;
102 /* set common initial clip state */
103 memset(&dsa
, 0, sizeof(struct pipe_depth_stencil_alpha_state
));
104 cso_set_depth_stencil_alpha(r
->cso
, &dsa
);
107 /* XXX: move to renderer_init_state? */
108 memset(&raster
, 0, sizeof(struct pipe_rasterizer_state
));
109 raster
.gl_rasterization_rules
= 1;
110 cso_set_rasterizer(r
->cso
, &raster
);
116 add_vertex_color(struct xorg_renderer
*r
,
120 float *vertex
= r
->buffer
+ r
->buffer_size
;
124 vertex
[2] = 0.f
; /*z*/
125 vertex
[3] = 1.f
; /*w*/
127 vertex
[4] = color
[0]; /*r*/
128 vertex
[5] = color
[1]; /*g*/
129 vertex
[6] = color
[2]; /*b*/
130 vertex
[7] = color
[3]; /*a*/
136 add_vertex_1tex(struct xorg_renderer
*r
,
137 float x
, float y
, float s
, float t
)
139 float *vertex
= r
->buffer
+ r
->buffer_size
;
143 vertex
[2] = 0.f
; /*z*/
144 vertex
[3] = 1.f
; /*w*/
148 vertex
[6] = 0.f
; /*r*/
149 vertex
[7] = 1.f
; /*q*/
155 add_vertex_data1(struct xorg_renderer
*r
,
156 float srcX
, float srcY
, float dstX
, float dstY
,
157 float width
, float height
,
158 struct pipe_texture
*src
, float *src_matrix
)
160 float s0
, t0
, s1
, t1
, s2
, t2
, s3
, t3
;
161 float pt0
[2], pt1
[2], pt2
[2], pt3
[2];
165 pt1
[0] = (srcX
+ width
);
167 pt2
[0] = (srcX
+ width
);
168 pt2
[1] = (srcY
+ height
);
170 pt3
[1] = (srcY
+ height
);
173 map_point(src_matrix
, pt0
[0], pt0
[1], &pt0
[0], &pt0
[1]);
174 map_point(src_matrix
, pt1
[0], pt1
[1], &pt1
[0], &pt1
[1]);
175 map_point(src_matrix
, pt2
[0], pt2
[1], &pt2
[0], &pt2
[1]);
176 map_point(src_matrix
, pt3
[0], pt3
[1], &pt3
[0], &pt3
[1]);
179 s0
= pt0
[0] / src
->width
[0];
180 s1
= pt1
[0] / src
->width
[0];
181 s2
= pt2
[0] / src
->width
[0];
182 s3
= pt3
[0] / src
->width
[0];
183 t0
= pt0
[1] / src
->height
[0];
184 t1
= pt1
[1] / src
->height
[0];
185 t2
= pt2
[1] / src
->height
[0];
186 t3
= pt3
[1] / src
->height
[0];
189 add_vertex_1tex(r
, dstX
, dstY
, s0
, t0
);
191 add_vertex_1tex(r
, dstX
+ width
, dstY
, s1
, t1
);
193 add_vertex_1tex(r
, dstX
+ width
, dstY
+ height
, s2
, t2
);
195 add_vertex_1tex(r
, dstX
, dstY
+ height
, s3
, t3
);
198 static struct pipe_buffer
*
199 setup_vertex_data_tex(struct xorg_renderer
*r
,
200 float x0
, float y0
, float x1
, float y1
,
201 float s0
, float t0
, float s1
, float t1
,
205 add_vertex_1tex(r
, x0
, y0
, s0
, t0
);
207 add_vertex_1tex(r
, x1
, y0
, s1
, t0
);
209 add_vertex_1tex(r
, x1
, y1
, s1
, t1
);
211 add_vertex_1tex(r
, x0
, y1
, s0
, t1
);
213 return renderer_buffer_create(r
);
217 add_vertex_2tex(struct xorg_renderer
*r
,
219 float s0
, float t0
, float s1
, float t1
)
221 float *vertex
= r
->buffer
+ r
->buffer_size
;
225 vertex
[2] = 0.f
; /*z*/
226 vertex
[3] = 1.f
; /*w*/
228 vertex
[4] = s0
; /*s*/
229 vertex
[5] = t0
; /*t*/
230 vertex
[6] = 0.f
; /*r*/
231 vertex
[7] = 1.f
; /*q*/
233 vertex
[8] = s1
; /*s*/
234 vertex
[9] = t1
; /*t*/
235 vertex
[10] = 0.f
; /*r*/
236 vertex
[11] = 1.f
; /*q*/
238 r
->buffer_size
+= 12;
242 add_vertex_data2(struct xorg_renderer
*r
,
243 float srcX
, float srcY
, float maskX
, float maskY
,
244 float dstX
, float dstY
, float width
, float height
,
245 struct pipe_texture
*src
,
246 struct pipe_texture
*mask
,
247 float *src_matrix
, float *mask_matrix
)
249 float src_s0
, src_t0
, src_s1
, src_t1
;
250 float mask_s0
, mask_t0
, mask_s1
, mask_t1
;
251 float spt0
[2], spt1
[2];
252 float mpt0
[2], mpt1
[2];
256 spt1
[0] = srcX
+ width
;
257 spt1
[1] = srcY
+ height
;
261 mpt1
[0] = maskX
+ width
;
262 mpt1
[1] = maskY
+ height
;
265 map_point(src_matrix
, spt0
[0], spt0
[1], &spt0
[0], &spt0
[1]);
266 map_point(src_matrix
, spt1
[0], spt1
[1], &spt1
[0], &spt1
[1]);
270 map_point(mask_matrix
, mpt0
[0], mpt0
[1], &mpt0
[0], &mpt0
[1]);
271 map_point(mask_matrix
, mpt1
[0], mpt1
[1], &mpt1
[0], &mpt1
[1]);
274 src_s0
= spt0
[0] / src
->width
[0];
275 src_t0
= spt0
[1] / src
->height
[0];
276 src_s1
= spt1
[0] / src
->width
[0];
277 src_t1
= spt1
[1] / src
->height
[0];
279 mask_s0
= mpt0
[0] / mask
->width
[0];
280 mask_t0
= mpt0
[1] / mask
->height
[0];
281 mask_s1
= mpt1
[0] / mask
->width
[0];
282 mask_t1
= mpt1
[1] / mask
->height
[0];
285 add_vertex_2tex(r
, dstX
, dstY
,
286 src_s0
, src_t0
, mask_s0
, mask_t0
);
288 add_vertex_2tex(r
, dstX
+ width
, dstY
,
289 src_s1
, src_t0
, mask_s1
, mask_t0
);
291 add_vertex_2tex(r
, dstX
+ width
, dstY
+ height
,
292 src_s1
, src_t1
, mask_s1
, mask_t1
);
294 add_vertex_2tex(r
, dstX
, dstY
+ height
,
295 src_s0
, src_t1
, mask_s0
, mask_t1
);
298 static struct pipe_buffer
*
299 setup_vertex_data_yuv(struct xorg_renderer
*r
,
300 float srcX
, float srcY
, float srcW
, float srcH
,
301 float dstX
, float dstY
, float dstW
, float dstH
,
302 struct pipe_texture
**tex
)
304 float s0
, t0
, s1
, t1
;
305 float spt0
[2], spt1
[2];
309 spt1
[0] = srcX
+ srcW
;
310 spt1
[1] = srcY
+ srcH
;
312 s0
= spt0
[0] / tex
[0]->width
[0];
313 t0
= spt0
[1] / tex
[0]->height
[0];
314 s1
= spt1
[0] / tex
[0]->width
[0];
315 t1
= spt1
[1] / tex
[0]->height
[0];
318 add_vertex_1tex(r
, dstX
, dstY
, s0
, t0
);
320 add_vertex_1tex(r
, dstX
+ dstW
, dstY
,
323 add_vertex_1tex(r
, dstX
+ dstW
, dstY
+ dstH
,
326 add_vertex_1tex(r
, dstX
, dstY
+ dstH
,
329 return renderer_buffer_create(r
);
334 /* Set up framebuffer, viewport and vertex shader constant buffer
335 * state for a particular destinaton surface. In all our rendering,
336 * these concepts are linked.
338 void renderer_bind_destination(struct xorg_renderer
*r
,
339 struct pipe_surface
*surface
)
342 struct pipe_framebuffer_state fb
;
343 struct pipe_viewport_state viewport
;
344 int width
= surface
->width
;
345 int height
= surface
->height
;
347 memset(&fb
, 0, sizeof fb
);
351 fb
.cbufs
[0] = surface
;
354 viewport
.scale
[0] = width
/ 2.f
;
355 viewport
.scale
[1] = height
/ 2.f
;
356 viewport
.scale
[2] = 1.0;
357 viewport
.scale
[3] = 1.0;
358 viewport
.translate
[0] = width
/ 2.f
;
359 viewport
.translate
[1] = height
/ 2.f
;
360 viewport
.translate
[2] = 0.0;
361 viewport
.translate
[3] = 0.0;
363 if (r
->fb_width
!= width
||
364 r
->fb_height
!= height
)
366 float vs_consts
[8] = {
367 2.f
/width
, 2.f
/height
, 1, 1,
372 r
->fb_height
= height
;
374 renderer_set_constants(r
, PIPE_SHADER_VERTEX
,
375 vs_consts
, sizeof vs_consts
);
378 cso_set_framebuffer(r
->cso
, &fb
);
379 cso_set_viewport(r
->cso
, &viewport
);
383 struct xorg_renderer
* renderer_create(struct pipe_context
*pipe
)
385 struct xorg_renderer
*renderer
= CALLOC_STRUCT(xorg_renderer
);
387 renderer
->pipe
= pipe
;
388 renderer
->cso
= cso_create_context(pipe
);
389 renderer
->shaders
= xorg_shaders_create(renderer
);
391 renderer_init_state(renderer
);
396 void renderer_destroy(struct xorg_renderer
*r
)
398 struct pipe_constant_buffer
*vsbuf
= &r
->vs_const_buffer
;
399 struct pipe_constant_buffer
*fsbuf
= &r
->fs_const_buffer
;
401 if (vsbuf
&& vsbuf
->buffer
)
402 pipe_buffer_reference(&vsbuf
->buffer
, NULL
);
404 if (fsbuf
&& fsbuf
->buffer
)
405 pipe_buffer_reference(&fsbuf
->buffer
, NULL
);
408 xorg_shaders_destroy(r
->shaders
);
413 cso_release_all(r
->cso
);
414 cso_destroy_context(r
->cso
);
423 void renderer_set_constants(struct xorg_renderer
*r
,
428 struct pipe_constant_buffer
*cbuf
=
429 (shader_type
== PIPE_SHADER_VERTEX
) ? &r
->vs_const_buffer
:
432 pipe_buffer_reference(&cbuf
->buffer
, NULL
);
433 cbuf
->buffer
= pipe_buffer_create(r
->pipe
->screen
, 16,
434 PIPE_BUFFER_USAGE_CONSTANT
,
438 pipe_buffer_write(r
->pipe
->screen
, cbuf
->buffer
,
439 0, param_bytes
, params
);
441 r
->pipe
->set_constant_buffer(r
->pipe
, shader_type
, 0, cbuf
);
445 static void renderer_copy_texture(struct xorg_renderer
*r
,
446 struct pipe_texture
*src
,
447 float sx1
, float sy1
,
448 float sx2
, float sy2
,
449 struct pipe_texture
*dst
,
450 float dx1
, float dy1
,
451 float dx2
, float dy2
)
453 struct pipe_context
*pipe
= r
->pipe
;
454 struct pipe_screen
*screen
= pipe
->screen
;
455 struct pipe_buffer
*buf
;
456 struct pipe_surface
*dst_surf
= screen
->get_tex_surface(
457 screen
, dst
, 0, 0, 0,
458 PIPE_BUFFER_USAGE_GPU_WRITE
);
459 float s0
, t0
, s1
, t1
;
460 struct xorg_shader shader
;
462 assert(src
->width
[0] != 0);
463 assert(src
->height
[0] != 0);
464 assert(dst
->width
[0] != 0);
465 assert(dst
->height
[0] != 0);
468 s0
= sx1
/ src
->width
[0];
469 s1
= sx2
/ src
->width
[0];
470 t0
= sy1
/ src
->height
[0];
471 t1
= sy2
/ src
->height
[0];
480 debug_printf("copy texture src=[%f, %f, %f, %f], dst=[%f, %f, %f, %f], tex=[%f, %f, %f, %f]\n",
481 sx1
, sy1
, sx2
, sy2
, dx1
, dy1
, dx2
, dy2
,
485 assert(screen
->is_format_supported(screen
, dst_surf
->format
,
487 PIPE_TEXTURE_USAGE_RENDER_TARGET
,
491 /* set misc state we care about */
493 struct pipe_blend_state blend
;
494 memset(&blend
, 0, sizeof(blend
));
495 blend
.rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
496 blend
.alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
497 blend
.rgb_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
498 blend
.alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
499 blend
.colormask
= PIPE_MASK_RGBA
;
500 cso_set_blend(r
->cso
, &blend
);
505 struct pipe_sampler_state sampler
;
506 memset(&sampler
, 0, sizeof(sampler
));
507 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
508 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
509 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
510 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
511 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
512 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
513 sampler
.normalized_coords
= 1;
514 cso_single_sampler(r
->cso
, 0, &sampler
);
515 cso_single_sampler_done(r
->cso
);
518 renderer_bind_destination(r
, dst_surf
);
521 cso_set_sampler_textures(r
->cso
, 1, &src
);
524 shader
= xorg_shaders_get(r
->shaders
,
527 cso_set_vertex_shader_handle(r
->cso
, shader
.vs
);
528 cso_set_fragment_shader_handle(r
->cso
, shader
.fs
);
531 buf
= setup_vertex_data_tex(r
,
538 util_draw_vertex_buffer(r
->pipe
, buf
, 0,
541 2); /* attribs/vert */
543 pipe_buffer_reference(&buf
, NULL
);
546 pipe_surface_reference(&dst_surf
, NULL
);
549 static struct pipe_texture
*
550 create_sampler_texture(struct xorg_renderer
*r
,
551 struct pipe_texture
*src
)
553 enum pipe_format format
;
554 struct pipe_context
*pipe
= r
->pipe
;
555 struct pipe_screen
*screen
= pipe
->screen
;
556 struct pipe_texture
*pt
;
557 struct pipe_texture templ
;
559 pipe
->flush(pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
561 /* the coming in texture should already have that invariance */
562 debug_assert(screen
->is_format_supported(screen
, src
->format
,
564 PIPE_TEXTURE_USAGE_SAMPLER
, 0));
566 format
= src
->format
;
568 memset(&templ
, 0, sizeof(templ
));
569 templ
.target
= PIPE_TEXTURE_2D
;
570 templ
.format
= format
;
571 templ
.last_level
= 0;
572 templ
.width
[0] = src
->width
[0];
573 templ
.height
[0] = src
->height
[0];
575 pf_get_block(format
, &templ
.block
);
576 templ
.tex_usage
= PIPE_TEXTURE_USAGE_SAMPLER
;
578 pt
= screen
->texture_create(screen
, &templ
);
580 debug_assert(!pt
|| pipe_is_referenced(&pt
->reference
));
586 /* copy source framebuffer surface into texture */
587 struct pipe_surface
*ps_read
= screen
->get_tex_surface(
588 screen
, src
, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ
);
589 struct pipe_surface
*ps_tex
= screen
->get_tex_surface(
590 screen
, pt
, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE
);
591 if (pipe
->surface_copy
) {
592 pipe
->surface_copy(pipe
,
596 0, 0, src
->width
[0], src
->height
[0]);
598 util_surface_copy(pipe
, FALSE
,
602 0, 0, src
->width
[0], src
->height
[0]);
604 pipe_surface_reference(&ps_read
, NULL
);
605 pipe_surface_reference(&ps_tex
, NULL
);
612 void renderer_copy_pixmap(struct xorg_renderer
*r
,
613 struct exa_pixmap_priv
*dst_priv
, int dx
, int dy
,
614 struct exa_pixmap_priv
*src_priv
, int sx
, int sy
,
615 int width
, int height
)
617 float dst_loc
[4], src_loc
[4];
618 struct pipe_texture
*dst
= dst_priv
->tex
;
619 struct pipe_texture
*src
= src_priv
->tex
;
621 if (r
->pipe
->is_texture_referenced(r
->pipe
, src
, 0, 0) &
622 PIPE_REFERENCED_FOR_WRITE
)
623 r
->pipe
->flush(r
->pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
635 if (src_loc
[2] >= 0 && src_loc
[3] >= 0 &&
636 dst_loc
[2] >= 0 && dst_loc
[3] >= 0) {
637 struct pipe_texture
*temp_src
= src
;
640 temp_src
= create_sampler_texture(r
, src
);
642 renderer_copy_texture(r
,
646 src_loc
[0] + src_loc
[2],
647 src_loc
[1] + src_loc
[3],
651 dst_loc
[0] + dst_loc
[2],
652 dst_loc
[1] + dst_loc
[3]);
655 pipe_texture_reference(&temp_src
, NULL
);
659 void renderer_draw_yuv(struct xorg_renderer
*r
,
660 int src_x
, int src_y
, int src_w
, int src_h
,
661 int dst_x
, int dst_y
, int dst_w
, int dst_h
,
662 struct pipe_texture
**textures
)
664 struct pipe_context
*pipe
= r
->pipe
;
665 struct pipe_buffer
*buf
= 0;
667 buf
= setup_vertex_data_yuv(r
,
668 src_x
, src_y
, src_w
, src_h
,
669 dst_x
, dst_y
, dst_w
, dst_h
,
673 const int num_attribs
= 2; /*pos + tex coord*/
675 util_draw_vertex_buffer(pipe
, buf
, 0,
678 num_attribs
); /* attribs/vert */
680 pipe_buffer_reference(&buf
, NULL
);
684 void renderer_begin_solid(struct xorg_renderer
*r
)
687 r
->attrs_per_vertex
= 2;
690 void renderer_solid(struct xorg_renderer
*r
,
696 debug_printf("solid rect[(%d, %d), (%d, %d)], rgba[%f, %f, %f, %f]\n",
697 x0, y0, x1, y1, color[0], color[1], color[2], color[3]);*/
699 renderer_draw_conditional(r
, 4 * 8);
702 add_vertex_color(r
, x0
, y0
, color
);
704 add_vertex_color(r
, x1
, y0
, color
);
706 add_vertex_color(r
, x1
, y1
, color
);
708 add_vertex_color(r
, x0
, y1
, color
);
711 void renderer_draw_flush(struct xorg_renderer
*r
)
713 renderer_draw_conditional(r
, 0);
716 void renderer_begin_textures(struct xorg_renderer
*r
,
717 struct pipe_texture
**textures
,
720 r
->attrs_per_vertex
= 1 + num_textures
;
724 void renderer_texture(struct xorg_renderer
*r
,
726 int width
, int height
,
727 struct pipe_texture
**textures
,
735 debug_printf("src_matrix = \n");
736 debug_printf("%f, %f, %f\n", src_matrix
[0], src_matrix
[1], src_matrix
[2]);
737 debug_printf("%f, %f, %f\n", src_matrix
[3], src_matrix
[4], src_matrix
[5]);
738 debug_printf("%f, %f, %f\n", src_matrix
[6], src_matrix
[7], src_matrix
[8]);
741 debug_printf("mask_matrix = \n");
742 debug_printf("%f, %f, %f\n", mask_matrix
[0], mask_matrix
[1], mask_matrix
[2]);
743 debug_printf("%f, %f, %f\n", mask_matrix
[3], mask_matrix
[4], mask_matrix
[5]);
744 debug_printf("%f, %f, %f\n", mask_matrix
[6], mask_matrix
[7], mask_matrix
[8]);
748 switch(r
->attrs_per_vertex
) {
750 renderer_draw_conditional(r
, 4 * 8);
752 pos
[0], pos
[1], /* src */
753 pos
[4], pos
[5], /* dst */
755 textures
[0], src_matrix
);
758 renderer_draw_conditional(r
, 4 * 12);
760 pos
[0], pos
[1], /* src */
761 pos
[2], pos
[3], /* mask */
762 pos
[4], pos
[5], /* dst */
764 textures
[0], textures
[1],
765 src_matrix
, mask_matrix
);
768 debug_assert(!"Unsupported number of textures");