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_sampler.h"
12 #include "util/u_inlines.h"
13 #include "util/u_box.h"
17 #define floatsEqual(x, y) (fabs(x - y) <= 0.00001f * MIN2(fabs(x), fabs(y)))
18 #define floatIsZero(x) (floatsEqual((x) + 1, 1))
20 #define NUM_COMPONENTS 4
22 static INLINE boolean
is_affine(float *matrix
)
24 return floatIsZero(matrix
[2]) && floatIsZero(matrix
[5])
25 && floatsEqual(matrix
[8], 1);
27 static INLINE
void map_point(float *mat
, float x
, float y
,
28 float *out_x
, float *out_y
)
36 *out_x
= mat
[0]*x
+ mat
[3]*y
+ mat
[6];
37 *out_y
= mat
[1]*x
+ mat
[4]*y
+ mat
[7];
38 if (!is_affine(mat
)) {
39 float w
= 1/(mat
[2]*x
+ mat
[5]*y
+ mat
[8]);
45 static INLINE
struct pipe_resource
*
46 renderer_buffer_create(struct xorg_renderer
*r
)
48 struct pipe_resource
*buf
=
49 pipe_user_buffer_create(r
->pipe
->screen
,
53 /* XXX was: PIPE_BUFFER_USAGE_PIXEL/PIPE_BUFFER_USAGE_GPU_WRITE even though this is a vertex buffer??? */
54 PIPE_BIND_VERTEX_BUFFER
);
61 renderer_draw(struct xorg_renderer
*r
)
63 struct pipe_context
*pipe
= r
->pipe
;
64 struct pipe_resource
*buf
= 0;
65 int num_verts
= r
->buffer_size
/(r
->attrs_per_vertex
* NUM_COMPONENTS
);
70 buf
= renderer_buffer_create(r
);
74 cso_set_vertex_elements(r
->cso
, r
->attrs_per_vertex
, r
->velems
);
76 util_draw_vertex_buffer(pipe
, r
->cso
, buf
, 0,
78 num_verts
, /* verts */
79 r
->attrs_per_vertex
); /* attribs/vert */
81 pipe_resource_reference(&buf
, NULL
);
86 renderer_draw_conditional(struct xorg_renderer
*r
,
89 if (r
->buffer_size
+ next_batch
>= BUF_SIZE
||
90 (next_batch
== 0 && r
->buffer_size
)) {
96 renderer_init_state(struct xorg_renderer
*r
)
98 struct pipe_depth_stencil_alpha_state dsa
;
99 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 raster
.depth_clip
= 1;
111 cso_set_rasterizer(r
->cso
, &raster
);
113 /* vertex elements state */
114 memset(&r
->velems
[0], 0, sizeof(r
->velems
[0]) * 3);
115 for (i
= 0; i
< 3; i
++) {
116 r
->velems
[i
].src_offset
= i
* 4 * sizeof(float);
117 r
->velems
[i
].instance_divisor
= 0;
118 r
->velems
[i
].vertex_buffer_index
= 0;
119 r
->velems
[i
].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
125 add_vertex_color(struct xorg_renderer
*r
,
129 float *vertex
= r
->buffer
+ r
->buffer_size
;
133 vertex
[2] = 0.f
; /*z*/
134 vertex
[3] = 1.f
; /*w*/
136 vertex
[4] = color
[0]; /*r*/
137 vertex
[5] = color
[1]; /*g*/
138 vertex
[6] = color
[2]; /*b*/
139 vertex
[7] = color
[3]; /*a*/
145 add_vertex_1tex(struct xorg_renderer
*r
,
146 float x
, float y
, float s
, float t
)
148 float *vertex
= r
->buffer
+ r
->buffer_size
;
152 vertex
[2] = 0.f
; /*z*/
153 vertex
[3] = 1.f
; /*w*/
157 vertex
[6] = 0.f
; /*r*/
158 vertex
[7] = 1.f
; /*q*/
164 add_vertex_data1(struct xorg_renderer
*r
,
165 float srcX
, float srcY
, float dstX
, float dstY
,
166 float width
, float height
,
167 struct pipe_resource
*src
, float *src_matrix
)
169 float s0
, t0
, s1
, t1
, s2
, t2
, s3
, t3
;
170 float pt0
[2], pt1
[2], pt2
[2], pt3
[2];
174 pt1
[0] = (srcX
+ width
);
176 pt2
[0] = (srcX
+ width
);
177 pt2
[1] = (srcY
+ height
);
179 pt3
[1] = (srcY
+ height
);
182 map_point(src_matrix
, pt0
[0], pt0
[1], &pt0
[0], &pt0
[1]);
183 map_point(src_matrix
, pt1
[0], pt1
[1], &pt1
[0], &pt1
[1]);
184 map_point(src_matrix
, pt2
[0], pt2
[1], &pt2
[0], &pt2
[1]);
185 map_point(src_matrix
, pt3
[0], pt3
[1], &pt3
[0], &pt3
[1]);
188 s0
= pt0
[0] / src
->width0
;
189 s1
= pt1
[0] / src
->width0
;
190 s2
= pt2
[0] / src
->width0
;
191 s3
= pt3
[0] / src
->width0
;
192 t0
= pt0
[1] / src
->height0
;
193 t1
= pt1
[1] / src
->height0
;
194 t2
= pt2
[1] / src
->height0
;
195 t3
= pt3
[1] / src
->height0
;
198 add_vertex_1tex(r
, dstX
, dstY
, s0
, t0
);
200 add_vertex_1tex(r
, dstX
+ width
, dstY
, s1
, t1
);
202 add_vertex_1tex(r
, dstX
+ width
, dstY
+ height
, s2
, t2
);
204 add_vertex_1tex(r
, dstX
, dstY
+ height
, s3
, t3
);
209 add_vertex_2tex(struct xorg_renderer
*r
,
211 float s0
, float t0
, float s1
, float t1
)
213 float *vertex
= r
->buffer
+ r
->buffer_size
;
217 vertex
[2] = 0.f
; /*z*/
218 vertex
[3] = 1.f
; /*w*/
220 vertex
[4] = s0
; /*s*/
221 vertex
[5] = t0
; /*t*/
222 vertex
[6] = 0.f
; /*r*/
223 vertex
[7] = 1.f
; /*q*/
225 vertex
[8] = s1
; /*s*/
226 vertex
[9] = t1
; /*t*/
227 vertex
[10] = 0.f
; /*r*/
228 vertex
[11] = 1.f
; /*q*/
230 r
->buffer_size
+= 12;
234 add_vertex_data2(struct xorg_renderer
*r
,
235 float srcX
, float srcY
, float maskX
, float maskY
,
236 float dstX
, float dstY
, float width
, float height
,
237 struct pipe_resource
*src
,
238 struct pipe_resource
*mask
,
239 float *src_matrix
, float *mask_matrix
)
241 float src_s0
, src_t0
, src_s1
, src_t1
;
242 float mask_s0
, mask_t0
, mask_s1
, mask_t1
;
243 float spt0
[2], spt1
[2];
244 float mpt0
[2], mpt1
[2];
248 spt1
[0] = srcX
+ width
;
249 spt1
[1] = srcY
+ height
;
253 mpt1
[0] = maskX
+ width
;
254 mpt1
[1] = maskY
+ height
;
257 map_point(src_matrix
, spt0
[0], spt0
[1], &spt0
[0], &spt0
[1]);
258 map_point(src_matrix
, spt1
[0], spt1
[1], &spt1
[0], &spt1
[1]);
262 map_point(mask_matrix
, mpt0
[0], mpt0
[1], &mpt0
[0], &mpt0
[1]);
263 map_point(mask_matrix
, mpt1
[0], mpt1
[1], &mpt1
[0], &mpt1
[1]);
266 src_s0
= spt0
[0] / src
->width0
;
267 src_t0
= spt0
[1] / src
->height0
;
268 src_s1
= spt1
[0] / src
->width0
;
269 src_t1
= spt1
[1] / src
->height0
;
271 mask_s0
= mpt0
[0] / mask
->width0
;
272 mask_t0
= mpt0
[1] / mask
->height0
;
273 mask_s1
= mpt1
[0] / mask
->width0
;
274 mask_t1
= mpt1
[1] / mask
->height0
;
277 add_vertex_2tex(r
, dstX
, dstY
,
278 src_s0
, src_t0
, mask_s0
, mask_t0
);
280 add_vertex_2tex(r
, dstX
+ width
, dstY
,
281 src_s1
, src_t0
, mask_s1
, mask_t0
);
283 add_vertex_2tex(r
, dstX
+ width
, dstY
+ height
,
284 src_s1
, src_t1
, mask_s1
, mask_t1
);
286 add_vertex_2tex(r
, dstX
, dstY
+ height
,
287 src_s0
, src_t1
, mask_s0
, mask_t1
);
290 static struct pipe_resource
*
291 setup_vertex_data_yuv(struct xorg_renderer
*r
,
292 float srcX
, float srcY
, float srcW
, float srcH
,
293 float dstX
, float dstY
, float dstW
, float dstH
,
294 struct pipe_resource
**tex
)
296 float s0
, t0
, s1
, t1
;
297 float spt0
[2], spt1
[2];
301 spt1
[0] = srcX
+ srcW
;
302 spt1
[1] = srcY
+ srcH
;
304 s0
= spt0
[0] / tex
[0]->width0
;
305 t0
= spt0
[1] / tex
[0]->height0
;
306 s1
= spt1
[0] / tex
[0]->width0
;
307 t1
= spt1
[1] / tex
[0]->height0
;
310 add_vertex_1tex(r
, dstX
, dstY
, s0
, t0
);
312 add_vertex_1tex(r
, dstX
+ dstW
, dstY
,
315 add_vertex_1tex(r
, dstX
+ dstW
, dstY
+ dstH
,
318 add_vertex_1tex(r
, dstX
, dstY
+ dstH
,
321 return renderer_buffer_create(r
);
326 /* Set up framebuffer, viewport and vertex shader constant buffer
327 * state for a particular destinaton surface. In all our rendering,
328 * these concepts are linked.
330 void renderer_bind_destination(struct xorg_renderer
*r
,
331 struct pipe_surface
*surface
,
336 struct pipe_framebuffer_state fb
;
337 struct pipe_viewport_state viewport
;
339 /* Framebuffer uses actual surface width/height
341 memset(&fb
, 0, sizeof fb
);
342 fb
.width
= surface
->width
;
343 fb
.height
= surface
->height
;
345 fb
.cbufs
[0] = surface
;
348 /* Viewport just touches the bit we're interested in:
350 viewport
.scale
[0] = width
/ 2.f
;
351 viewport
.scale
[1] = height
/ 2.f
;
352 viewport
.scale
[2] = 1.0;
353 viewport
.scale
[3] = 1.0;
354 viewport
.translate
[0] = width
/ 2.f
;
355 viewport
.translate
[1] = height
/ 2.f
;
356 viewport
.translate
[2] = 0.0;
357 viewport
.translate
[3] = 0.0;
359 /* Constant buffer set up to match viewport dimensions:
361 if (r
->fb_width
!= width
||
362 r
->fb_height
!= height
)
364 float vs_consts
[8] = {
365 2.f
/width
, 2.f
/height
, 1, 1,
370 r
->fb_height
= height
;
372 renderer_set_constants(r
, PIPE_SHADER_VERTEX
,
373 vs_consts
, sizeof vs_consts
);
376 cso_set_framebuffer(r
->cso
, &fb
);
377 cso_set_viewport(r
->cso
, &viewport
);
381 struct xorg_renderer
* renderer_create(struct pipe_context
*pipe
)
383 struct xorg_renderer
*renderer
= CALLOC_STRUCT(xorg_renderer
);
385 renderer
->pipe
= pipe
;
386 renderer
->cso
= cso_create_context(pipe
);
387 renderer
->shaders
= xorg_shaders_create(renderer
);
389 renderer_init_state(renderer
);
394 void renderer_destroy(struct xorg_renderer
*r
)
396 struct pipe_resource
**vsbuf
= &r
->vs_const_buffer
;
397 struct pipe_resource
**fsbuf
= &r
->fs_const_buffer
;
400 pipe_resource_reference(vsbuf
, NULL
);
403 pipe_resource_reference(fsbuf
, NULL
);
406 xorg_shaders_destroy(r
->shaders
);
411 cso_release_all(r
->cso
);
412 cso_destroy_context(r
->cso
);
421 void renderer_set_constants(struct xorg_renderer
*r
,
426 struct pipe_resource
**cbuf
=
427 (shader_type
== PIPE_SHADER_VERTEX
) ? &r
->vs_const_buffer
:
430 pipe_resource_reference(cbuf
, NULL
);
431 *cbuf
= pipe_buffer_create(r
->pipe
->screen
,
432 PIPE_BIND_CONSTANT_BUFFER
,
437 pipe_buffer_write(r
->pipe
, *cbuf
,
438 0, param_bytes
, params
);
440 pipe_set_constant_buffer(r
->pipe
, shader_type
, 0, *cbuf
);
444 void renderer_copy_prepare(struct xorg_renderer
*r
,
445 struct pipe_surface
*dst_surface
,
446 struct pipe_resource
*src_texture
)
448 struct pipe_context
*pipe
= r
->pipe
;
449 struct pipe_screen
*screen
= pipe
->screen
;
450 struct xorg_shader shader
;
452 assert(screen
->is_format_supported(screen
, dst_surface
->format
,
454 PIPE_BIND_RENDER_TARGET
));
458 /* set misc state we care about */
460 struct pipe_blend_state blend
;
461 memset(&blend
, 0, sizeof(blend
));
462 blend
.rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
463 blend
.rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
464 blend
.rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
465 blend
.rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
466 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
467 cso_set_blend(r
->cso
, &blend
);
472 struct pipe_sampler_state sampler
;
473 memset(&sampler
, 0, sizeof(sampler
));
474 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
475 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
476 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
477 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
478 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
479 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
480 sampler
.normalized_coords
= 1;
481 cso_single_sampler(r
->cso
, 0, &sampler
);
482 cso_single_sampler_done(r
->cso
);
485 renderer_bind_destination(r
, dst_surface
,
487 dst_surface
->height
);
489 /* texture/sampler view */
491 struct pipe_sampler_view templ
;
492 struct pipe_sampler_view
*src_view
;
493 u_sampler_view_default_template(&templ
,
495 src_texture
->format
);
496 src_view
= pipe
->create_sampler_view(pipe
, src_texture
, &templ
);
497 cso_set_fragment_sampler_views(r
->cso
, 1, &src_view
);
498 pipe_sampler_view_reference(&src_view
, NULL
);
502 shader
= xorg_shaders_get(r
->shaders
,
505 cso_set_vertex_shader_handle(r
->cso
, shader
.vs
);
506 cso_set_fragment_shader_handle(r
->cso
, shader
.fs
);
509 r
->attrs_per_vertex
= 2;
512 struct pipe_resource
*
513 renderer_clone_texture(struct xorg_renderer
*r
,
514 struct pipe_resource
*src
)
516 enum pipe_format format
;
517 struct pipe_context
*pipe
= r
->pipe
;
518 struct pipe_screen
*screen
= pipe
->screen
;
519 struct pipe_resource
*pt
;
520 struct pipe_resource templ
;
522 /* the coming in texture should already have that invariance */
523 debug_assert(screen
->is_format_supported(screen
, src
->format
,
525 PIPE_BIND_SAMPLER_VIEW
));
527 format
= src
->format
;
529 memset(&templ
, 0, sizeof(templ
));
530 templ
.target
= PIPE_TEXTURE_2D
;
531 templ
.format
= format
;
532 templ
.last_level
= 0;
533 templ
.width0
= src
->width0
;
534 templ
.height0
= src
->height0
;
536 templ
.array_size
= 1;
537 templ
.bind
= PIPE_BIND_SAMPLER_VIEW
;
539 pt
= screen
->resource_create(screen
, &templ
);
541 debug_assert(!pt
|| pipe_is_referenced(&pt
->reference
));
547 /* copy source framebuffer surface into texture */
548 struct pipe_box src_box
;
549 u_box_origin_2d(src
->width0
, src
->height0
, &src_box
);
551 pipe
->resource_copy_region(pipe
,
554 0, 0, 0, /* destx/y/z */
563 void renderer_copy_pixmap(struct xorg_renderer
*r
,
566 int width
, int height
,
570 float s0
, t0
, s1
, t1
;
571 float x0
, y0
, x1
, y1
;
574 /* XXX: could put the texcoord scaling calculation into the vertex
578 s1
= (sx
+ width
) / src_width
;
579 t0
= sy
/ src_height
;
580 t1
= (sy
+ height
) / src_height
;
588 renderer_draw_conditional(r
, 4*8);
589 add_vertex_1tex(r
, x0
, y0
, s0
, t0
);
590 add_vertex_1tex(r
, x1
, y0
, s1
, t0
);
591 add_vertex_1tex(r
, x1
, y1
, s1
, t1
);
592 add_vertex_1tex(r
, x0
, y1
, s0
, t1
);
598 void renderer_draw_yuv(struct xorg_renderer
*r
,
599 float src_x
, float src_y
, float src_w
, float src_h
,
600 int dst_x
, int dst_y
, int dst_w
, int dst_h
,
601 struct pipe_resource
**textures
)
603 struct pipe_context
*pipe
= r
->pipe
;
604 struct pipe_resource
*buf
= 0;
606 buf
= setup_vertex_data_yuv(r
,
607 src_x
, src_y
, src_w
, src_h
,
608 dst_x
, dst_y
, dst_w
, dst_h
,
612 const int num_attribs
= 2; /*pos + tex coord*/
614 cso_set_vertex_elements(r
->cso
, num_attribs
, r
->velems
);
616 util_draw_vertex_buffer(pipe
, r
->cso
, buf
, 0,
619 num_attribs
); /* attribs/vert */
621 pipe_resource_reference(&buf
, NULL
);
625 void renderer_begin_solid(struct xorg_renderer
*r
)
628 r
->attrs_per_vertex
= 2;
631 void renderer_solid(struct xorg_renderer
*r
,
637 debug_printf("solid rect[(%d, %d), (%d, %d)], rgba[%f, %f, %f, %f]\n",
638 x0, y0, x1, y1, color[0], color[1], color[2], color[3]);*/
640 renderer_draw_conditional(r
, 4 * 8);
643 add_vertex_color(r
, x0
, y0
, color
);
645 add_vertex_color(r
, x1
, y0
, color
);
647 add_vertex_color(r
, x1
, y1
, color
);
649 add_vertex_color(r
, x0
, y1
, color
);
652 void renderer_draw_flush(struct xorg_renderer
*r
)
654 renderer_draw_conditional(r
, 0);
657 void renderer_begin_textures(struct xorg_renderer
*r
,
660 r
->attrs_per_vertex
= 1 + num_textures
;
664 void renderer_texture(struct xorg_renderer
*r
,
666 int width
, int height
,
667 struct pipe_sampler_view
**sampler_view
,
675 debug_printf("src_matrix = \n");
676 debug_printf("%f, %f, %f\n", src_matrix
[0], src_matrix
[1], src_matrix
[2]);
677 debug_printf("%f, %f, %f\n", src_matrix
[3], src_matrix
[4], src_matrix
[5]);
678 debug_printf("%f, %f, %f\n", src_matrix
[6], src_matrix
[7], src_matrix
[8]);
681 debug_printf("mask_matrix = \n");
682 debug_printf("%f, %f, %f\n", mask_matrix
[0], mask_matrix
[1], mask_matrix
[2]);
683 debug_printf("%f, %f, %f\n", mask_matrix
[3], mask_matrix
[4], mask_matrix
[5]);
684 debug_printf("%f, %f, %f\n", mask_matrix
[6], mask_matrix
[7], mask_matrix
[8]);
688 switch(r
->attrs_per_vertex
) {
690 renderer_draw_conditional(r
, 4 * 8);
692 pos
[0], pos
[1], /* src */
693 pos
[4], pos
[5], /* dst */
695 sampler_view
[0]->texture
, src_matrix
);
698 renderer_draw_conditional(r
, 4 * 12);
700 pos
[0], pos
[1], /* src */
701 pos
[2], pos
[3], /* mask */
702 pos
[4], pos
[5], /* dst */
704 sampler_view
[0]->texture
, sampler_view
[1]->texture
,
705 src_matrix
, mask_matrix
);
708 debug_assert(!"Unsupported number of textures");