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]);
46 renderer_draw(struct xorg_renderer
*r
)
48 int num_verts
= r
->buffer_size
/(r
->attrs_per_vertex
* NUM_COMPONENTS
);
53 cso_set_vertex_elements(r
->cso
, r
->attrs_per_vertex
, r
->velems
);
54 util_draw_user_vertex_buffer(r
->cso
, r
->buffer
, PIPE_PRIM_QUADS
,
55 num_verts
, r
->attrs_per_vertex
);
61 renderer_draw_conditional(struct xorg_renderer
*r
,
64 if (r
->buffer_size
+ next_batch
>= BUF_SIZE
||
65 (next_batch
== 0 && r
->buffer_size
)) {
71 renderer_init_state(struct xorg_renderer
*r
)
73 struct pipe_depth_stencil_alpha_state dsa
;
74 struct pipe_rasterizer_state raster
;
77 /* set common initial clip state */
78 memset(&dsa
, 0, sizeof(struct pipe_depth_stencil_alpha_state
));
79 cso_set_depth_stencil_alpha(r
->cso
, &dsa
);
82 /* XXX: move to renderer_init_state? */
83 memset(&raster
, 0, sizeof(struct pipe_rasterizer_state
));
84 raster
.gl_rasterization_rules
= 1;
85 raster
.depth_clip
= 1;
86 cso_set_rasterizer(r
->cso
, &raster
);
88 /* vertex elements state */
89 memset(&r
->velems
[0], 0, sizeof(r
->velems
[0]) * 3);
90 for (i
= 0; i
< 3; i
++) {
91 r
->velems
[i
].src_offset
= i
* 4 * sizeof(float);
92 r
->velems
[i
].instance_divisor
= 0;
93 r
->velems
[i
].vertex_buffer_index
= 0;
94 r
->velems
[i
].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
100 add_vertex_color(struct xorg_renderer
*r
,
104 float *vertex
= r
->buffer
+ r
->buffer_size
;
108 vertex
[2] = 0.f
; /*z*/
109 vertex
[3] = 1.f
; /*w*/
111 vertex
[4] = color
[0]; /*r*/
112 vertex
[5] = color
[1]; /*g*/
113 vertex
[6] = color
[2]; /*b*/
114 vertex
[7] = color
[3]; /*a*/
120 add_vertex_1tex(struct xorg_renderer
*r
,
121 float x
, float y
, float s
, float t
)
123 float *vertex
= r
->buffer
+ r
->buffer_size
;
127 vertex
[2] = 0.f
; /*z*/
128 vertex
[3] = 1.f
; /*w*/
132 vertex
[6] = 0.f
; /*r*/
133 vertex
[7] = 1.f
; /*q*/
139 add_vertex_data1(struct xorg_renderer
*r
,
140 float srcX
, float srcY
, float dstX
, float dstY
,
141 float width
, float height
,
142 struct pipe_resource
*src
, float *src_matrix
)
144 float s0
, t0
, s1
, t1
, s2
, t2
, s3
, t3
;
145 float pt0
[2], pt1
[2], pt2
[2], pt3
[2];
149 pt1
[0] = (srcX
+ width
);
151 pt2
[0] = (srcX
+ width
);
152 pt2
[1] = (srcY
+ height
);
154 pt3
[1] = (srcY
+ height
);
157 map_point(src_matrix
, pt0
[0], pt0
[1], &pt0
[0], &pt0
[1]);
158 map_point(src_matrix
, pt1
[0], pt1
[1], &pt1
[0], &pt1
[1]);
159 map_point(src_matrix
, pt2
[0], pt2
[1], &pt2
[0], &pt2
[1]);
160 map_point(src_matrix
, pt3
[0], pt3
[1], &pt3
[0], &pt3
[1]);
163 s0
= pt0
[0] / src
->width0
;
164 s1
= pt1
[0] / src
->width0
;
165 s2
= pt2
[0] / src
->width0
;
166 s3
= pt3
[0] / src
->width0
;
167 t0
= pt0
[1] / src
->height0
;
168 t1
= pt1
[1] / src
->height0
;
169 t2
= pt2
[1] / src
->height0
;
170 t3
= pt3
[1] / src
->height0
;
173 add_vertex_1tex(r
, dstX
, dstY
, s0
, t0
);
175 add_vertex_1tex(r
, dstX
+ width
, dstY
, s1
, t1
);
177 add_vertex_1tex(r
, dstX
+ width
, dstY
+ height
, s2
, t2
);
179 add_vertex_1tex(r
, dstX
, dstY
+ height
, s3
, t3
);
184 add_vertex_2tex(struct xorg_renderer
*r
,
186 float s0
, float t0
, float s1
, float t1
)
188 float *vertex
= r
->buffer
+ r
->buffer_size
;
192 vertex
[2] = 0.f
; /*z*/
193 vertex
[3] = 1.f
; /*w*/
195 vertex
[4] = s0
; /*s*/
196 vertex
[5] = t0
; /*t*/
197 vertex
[6] = 0.f
; /*r*/
198 vertex
[7] = 1.f
; /*q*/
200 vertex
[8] = s1
; /*s*/
201 vertex
[9] = t1
; /*t*/
202 vertex
[10] = 0.f
; /*r*/
203 vertex
[11] = 1.f
; /*q*/
205 r
->buffer_size
+= 12;
209 add_vertex_data2(struct xorg_renderer
*r
,
210 float srcX
, float srcY
, float maskX
, float maskY
,
211 float dstX
, float dstY
, float width
, float height
,
212 struct pipe_resource
*src
,
213 struct pipe_resource
*mask
,
214 float *src_matrix
, float *mask_matrix
)
216 float src_s0
, src_t0
, src_s1
, src_t1
;
217 float mask_s0
, mask_t0
, mask_s1
, mask_t1
;
218 float spt0
[2], spt1
[2];
219 float mpt0
[2], mpt1
[2];
223 spt1
[0] = srcX
+ width
;
224 spt1
[1] = srcY
+ height
;
228 mpt1
[0] = maskX
+ width
;
229 mpt1
[1] = maskY
+ height
;
232 map_point(src_matrix
, spt0
[0], spt0
[1], &spt0
[0], &spt0
[1]);
233 map_point(src_matrix
, spt1
[0], spt1
[1], &spt1
[0], &spt1
[1]);
237 map_point(mask_matrix
, mpt0
[0], mpt0
[1], &mpt0
[0], &mpt0
[1]);
238 map_point(mask_matrix
, mpt1
[0], mpt1
[1], &mpt1
[0], &mpt1
[1]);
241 src_s0
= spt0
[0] / src
->width0
;
242 src_t0
= spt0
[1] / src
->height0
;
243 src_s1
= spt1
[0] / src
->width0
;
244 src_t1
= spt1
[1] / src
->height0
;
246 mask_s0
= mpt0
[0] / mask
->width0
;
247 mask_t0
= mpt0
[1] / mask
->height0
;
248 mask_s1
= mpt1
[0] / mask
->width0
;
249 mask_t1
= mpt1
[1] / mask
->height0
;
252 add_vertex_2tex(r
, dstX
, dstY
,
253 src_s0
, src_t0
, mask_s0
, mask_t0
);
255 add_vertex_2tex(r
, dstX
+ width
, dstY
,
256 src_s1
, src_t0
, mask_s1
, mask_t0
);
258 add_vertex_2tex(r
, dstX
+ width
, dstY
+ height
,
259 src_s1
, src_t1
, mask_s1
, mask_t1
);
261 add_vertex_2tex(r
, dstX
, dstY
+ height
,
262 src_s0
, src_t1
, mask_s0
, mask_t1
);
266 setup_vertex_data_yuv(struct xorg_renderer
*r
,
267 float srcX
, float srcY
, float srcW
, float srcH
,
268 float dstX
, float dstY
, float dstW
, float dstH
,
269 struct pipe_resource
**tex
)
271 float s0
, t0
, s1
, t1
;
272 float spt0
[2], spt1
[2];
276 spt1
[0] = srcX
+ srcW
;
277 spt1
[1] = srcY
+ srcH
;
279 s0
= spt0
[0] / tex
[0]->width0
;
280 t0
= spt0
[1] / tex
[0]->height0
;
281 s1
= spt1
[0] / tex
[0]->width0
;
282 t1
= spt1
[1] / tex
[0]->height0
;
285 add_vertex_1tex(r
, dstX
, dstY
, s0
, t0
);
287 add_vertex_1tex(r
, dstX
+ dstW
, dstY
,
290 add_vertex_1tex(r
, dstX
+ dstW
, dstY
+ dstH
,
293 add_vertex_1tex(r
, dstX
, dstY
+ dstH
,
299 /* Set up framebuffer, viewport and vertex shader constant buffer
300 * state for a particular destinaton surface. In all our rendering,
301 * these concepts are linked.
303 void renderer_bind_destination(struct xorg_renderer
*r
,
304 struct pipe_surface
*surface
,
309 struct pipe_framebuffer_state fb
;
310 struct pipe_viewport_state viewport
;
312 /* Framebuffer uses actual surface width/height
314 memset(&fb
, 0, sizeof fb
);
315 fb
.width
= surface
->width
;
316 fb
.height
= surface
->height
;
318 fb
.cbufs
[0] = surface
;
321 /* Viewport just touches the bit we're interested in:
323 viewport
.scale
[0] = width
/ 2.f
;
324 viewport
.scale
[1] = height
/ 2.f
;
325 viewport
.scale
[2] = 1.0;
326 viewport
.scale
[3] = 1.0;
327 viewport
.translate
[0] = width
/ 2.f
;
328 viewport
.translate
[1] = height
/ 2.f
;
329 viewport
.translate
[2] = 0.0;
330 viewport
.translate
[3] = 0.0;
332 /* Constant buffer set up to match viewport dimensions:
334 if (r
->fb_width
!= width
||
335 r
->fb_height
!= height
)
337 float vs_consts
[8] = {
338 2.f
/width
, 2.f
/height
, 1, 1,
343 r
->fb_height
= height
;
345 renderer_set_constants(r
, PIPE_SHADER_VERTEX
,
346 vs_consts
, sizeof vs_consts
);
349 cso_set_framebuffer(r
->cso
, &fb
);
350 cso_set_viewport(r
->cso
, &viewport
);
354 struct xorg_renderer
* renderer_create(struct pipe_context
*pipe
)
356 struct xorg_renderer
*renderer
= CALLOC_STRUCT(xorg_renderer
);
358 renderer
->pipe
= pipe
;
359 renderer
->cso
= cso_create_context(pipe
);
360 renderer
->shaders
= xorg_shaders_create(renderer
);
362 renderer_init_state(renderer
);
367 void renderer_destroy(struct xorg_renderer
*r
)
369 struct pipe_resource
**vsbuf
= &r
->vs_const_buffer
;
370 struct pipe_resource
**fsbuf
= &r
->fs_const_buffer
;
373 pipe_resource_reference(vsbuf
, NULL
);
376 pipe_resource_reference(fsbuf
, NULL
);
379 xorg_shaders_destroy(r
->shaders
);
384 cso_release_all(r
->cso
);
385 cso_destroy_context(r
->cso
);
394 void renderer_set_constants(struct xorg_renderer
*r
,
399 struct pipe_resource
**cbuf
=
400 (shader_type
== PIPE_SHADER_VERTEX
) ? &r
->vs_const_buffer
:
403 pipe_resource_reference(cbuf
, NULL
);
404 *cbuf
= pipe_buffer_create(r
->pipe
->screen
,
405 PIPE_BIND_CONSTANT_BUFFER
,
410 pipe_buffer_write(r
->pipe
, *cbuf
,
411 0, param_bytes
, params
);
413 pipe_set_constant_buffer(r
->pipe
, shader_type
, 0, *cbuf
);
418 void renderer_draw_yuv(struct xorg_renderer
*r
,
419 float src_x
, float src_y
, float src_w
, float src_h
,
420 int dst_x
, int dst_y
, int dst_w
, int dst_h
,
421 struct pipe_resource
**textures
)
423 const int num_attribs
= 2; /*pos + tex coord*/
425 setup_vertex_data_yuv(r
,
426 src_x
, src_y
, src_w
, src_h
,
427 dst_x
, dst_y
, dst_w
, dst_h
,
430 cso_set_vertex_elements(r
->cso
, num_attribs
, r
->velems
);
432 util_draw_user_vertex_buffer(r
->cso
, r
->buffer
,
435 num_attribs
); /* attribs/vert */
440 void renderer_begin_solid(struct xorg_renderer
*r
)
443 r
->attrs_per_vertex
= 2;
446 void renderer_solid(struct xorg_renderer
*r
,
452 debug_printf("solid rect[(%d, %d), (%d, %d)], rgba[%f, %f, %f, %f]\n",
453 x0, y0, x1, y1, color[0], color[1], color[2], color[3]);*/
455 renderer_draw_conditional(r
, 4 * 8);
458 add_vertex_color(r
, x0
, y0
, color
);
460 add_vertex_color(r
, x1
, y0
, color
);
462 add_vertex_color(r
, x1
, y1
, color
);
464 add_vertex_color(r
, x0
, y1
, color
);
467 void renderer_draw_flush(struct xorg_renderer
*r
)
469 renderer_draw_conditional(r
, 0);
472 void renderer_begin_textures(struct xorg_renderer
*r
,
475 r
->attrs_per_vertex
= 1 + num_textures
;
479 void renderer_texture(struct xorg_renderer
*r
,
481 int width
, int height
,
482 struct pipe_sampler_view
**sampler_view
,
490 debug_printf("src_matrix = \n");
491 debug_printf("%f, %f, %f\n", src_matrix
[0], src_matrix
[1], src_matrix
[2]);
492 debug_printf("%f, %f, %f\n", src_matrix
[3], src_matrix
[4], src_matrix
[5]);
493 debug_printf("%f, %f, %f\n", src_matrix
[6], src_matrix
[7], src_matrix
[8]);
496 debug_printf("mask_matrix = \n");
497 debug_printf("%f, %f, %f\n", mask_matrix
[0], mask_matrix
[1], mask_matrix
[2]);
498 debug_printf("%f, %f, %f\n", mask_matrix
[3], mask_matrix
[4], mask_matrix
[5]);
499 debug_printf("%f, %f, %f\n", mask_matrix
[6], mask_matrix
[7], mask_matrix
[8]);
503 switch(r
->attrs_per_vertex
) {
505 renderer_draw_conditional(r
, 4 * 8);
507 pos
[0], pos
[1], /* src */
508 pos
[4], pos
[5], /* dst */
510 sampler_view
[0]->texture
, src_matrix
);
513 renderer_draw_conditional(r
, 4 * 12);
515 pos
[0], pos
[1], /* src */
516 pos
[2], pos
[3], /* mask */
517 pos
[4], pos
[5], /* dst */
519 sampler_view
[0]->texture
, sampler_view
[1]->texture
,
520 src_matrix
, mask_matrix
);
523 debug_assert(!"Unsupported number of textures");