1 /**********************************************************
2 * Copyright 2009-2011 VMware, Inc. All rights reserved.
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 *********************************************************
26 * Zack Rusin <zackr-at-vmware-dot-com>
29 #include "xa_context.h"
32 #include "cso_cache/cso_context.h"
33 #include "util/u_inlines.h"
34 #include "util/u_sampler.h"
35 #include "util/u_draw_quad.h"
37 #define floatsEqual(x, y) (fabs(x - y) <= 0.00001f * MIN2(fabs(x), fabs(y)))
38 #define floatIsZero(x) (floatsEqual((x) + 1, 1))
40 #define NUM_COMPONENTS 4
45 renderer_set_constants(struct xa_context
*r
,
46 int shader_type
, const float *params
, int param_bytes
);
49 is_affine(float *matrix
)
51 return floatIsZero(matrix
[2]) && floatIsZero(matrix
[5])
52 && floatsEqual(matrix
[8], 1);
56 map_point(float *mat
, float x
, float y
, float *out_x
, float *out_y
)
64 *out_x
= mat
[0] * x
+ mat
[3] * y
+ mat
[6];
65 *out_y
= mat
[1] * x
+ mat
[4] * y
+ mat
[7];
66 if (!is_affine(mat
)) {
67 float w
= 1 / (mat
[2] * x
+ mat
[5] * y
+ mat
[8]);
74 static INLINE
struct pipe_resource
*
75 renderer_buffer_create(struct xa_context
*r
)
77 struct pipe_resource
*buf
= pipe_user_buffer_create(r
->pipe
->screen
,
81 PIPE_BIND_VERTEX_BUFFER
);
89 renderer_draw(struct xa_context
*r
)
91 struct pipe_context
*pipe
= r
->pipe
;
92 struct pipe_resource
*buf
= 0;
93 int num_verts
= r
->buffer_size
/ (r
->attrs_per_vertex
* NUM_COMPONENTS
);
98 buf
= renderer_buffer_create(r
);
101 cso_set_vertex_elements(r
->cso
, r
->attrs_per_vertex
, r
->velems
);
103 util_draw_vertex_buffer(pipe
, r
->cso
, buf
, 0, PIPE_PRIM_QUADS
, num_verts
, /* verts */
104 r
->attrs_per_vertex
); /* attribs/vert */
106 pipe_resource_reference(&buf
, NULL
);
111 renderer_draw_conditional(struct xa_context
*r
, int next_batch
)
113 if (r
->buffer_size
+ next_batch
>= XA_VB_SIZE
||
114 (next_batch
== 0 && r
->buffer_size
)) {
120 renderer_init_state(struct xa_context
*r
)
122 struct pipe_depth_stencil_alpha_state dsa
;
123 struct pipe_rasterizer_state raster
;
126 /* set common initial clip state */
127 memset(&dsa
, 0, sizeof(struct pipe_depth_stencil_alpha_state
));
128 cso_set_depth_stencil_alpha(r
->cso
, &dsa
);
130 /* XXX: move to renderer_init_state? */
131 memset(&raster
, 0, sizeof(struct pipe_rasterizer_state
));
132 raster
.gl_rasterization_rules
= 1;
133 cso_set_rasterizer(r
->cso
, &raster
);
135 /* vertex elements state */
136 memset(&r
->velems
[0], 0, sizeof(r
->velems
[0]) * 3);
137 for (i
= 0; i
< 3; i
++) {
138 r
->velems
[i
].src_offset
= i
* 4 * sizeof(float);
139 r
->velems
[i
].instance_divisor
= 0;
140 r
->velems
[i
].vertex_buffer_index
= 0;
141 r
->velems
[i
].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
146 add_vertex_color(struct xa_context
*r
, float x
, float y
, float color
[4])
148 float *vertex
= r
->buffer
+ r
->buffer_size
;
152 vertex
[2] = 0.f
; /*z */
153 vertex
[3] = 1.f
; /*w */
155 vertex
[4] = color
[0]; /*r */
156 vertex
[5] = color
[1]; /*g */
157 vertex
[6] = color
[2]; /*b */
158 vertex
[7] = color
[3]; /*a */
164 add_vertex_1tex(struct xa_context
*r
, float x
, float y
, float s
, float t
)
166 float *vertex
= r
->buffer
+ r
->buffer_size
;
170 vertex
[2] = 0.f
; /*z */
171 vertex
[3] = 1.f
; /*w */
173 vertex
[4] = s
; /*s */
174 vertex
[5] = t
; /*t */
175 vertex
[6] = 0.f
; /*r */
176 vertex
[7] = 1.f
; /*q */
182 add_vertex_2tex(struct xa_context
*r
,
183 float x
, float y
, float s0
, float t0
, float s1
, float t1
)
185 float *vertex
= r
->buffer
+ r
->buffer_size
;
189 vertex
[2] = 0.f
; /*z */
190 vertex
[3] = 1.f
; /*w */
192 vertex
[4] = s0
; /*s */
193 vertex
[5] = t0
; /*t */
194 vertex
[6] = 0.f
; /*r */
195 vertex
[7] = 1.f
; /*q */
197 vertex
[8] = s1
; /*s */
198 vertex
[9] = t1
; /*t */
199 vertex
[10] = 0.f
; /*r */
200 vertex
[11] = 1.f
; /*q */
202 r
->buffer_size
+= 12;
206 add_vertex_data1(struct xa_context
*r
,
207 float srcX
, float srcY
, float dstX
, float dstY
,
208 float width
, float height
,
209 struct pipe_resource
*src
, const float *src_matrix
)
211 float s0
, t0
, s1
, t1
, s2
, t2
, s3
, t3
;
212 float pt0
[2], pt1
[2], pt2
[2], pt3
[2];
216 pt1
[0] = (srcX
+ width
);
218 pt2
[0] = (srcX
+ width
);
219 pt2
[1] = (srcY
+ height
);
221 pt3
[1] = (srcY
+ height
);
224 map_point((float *)src_matrix
, pt0
[0], pt0
[1], &pt0
[0], &pt0
[1]);
225 map_point((float *)src_matrix
, pt1
[0], pt1
[1], &pt1
[0], &pt1
[1]);
226 map_point((float *)src_matrix
, pt2
[0], pt2
[1], &pt2
[0], &pt2
[1]);
227 map_point((float *)src_matrix
, pt3
[0], pt3
[1], &pt3
[0], &pt3
[1]);
230 s0
= pt0
[0] / src
->width0
;
231 s1
= pt1
[0] / src
->width0
;
232 s2
= pt2
[0] / src
->width0
;
233 s3
= pt3
[0] / src
->width0
;
234 t0
= pt0
[1] / src
->height0
;
235 t1
= pt1
[1] / src
->height0
;
236 t2
= pt2
[1] / src
->height0
;
237 t3
= pt3
[1] / src
->height0
;
240 add_vertex_1tex(r
, dstX
, dstY
, s0
, t0
);
242 add_vertex_1tex(r
, dstX
+ width
, dstY
, s1
, t1
);
244 add_vertex_1tex(r
, dstX
+ width
, dstY
+ height
, s2
, t2
);
246 add_vertex_1tex(r
, dstX
, dstY
+ height
, s3
, t3
);
250 add_vertex_data2(struct xa_context
*r
,
251 float srcX
, float srcY
, float maskX
, float maskY
,
252 float dstX
, float dstY
, float width
, float height
,
253 struct pipe_resource
*src
,
254 struct pipe_resource
*mask
,
255 const float *src_matrix
, const float *mask_matrix
)
257 float src_s0
, src_t0
, src_s1
, src_t1
;
258 float mask_s0
, mask_t0
, mask_s1
, mask_t1
;
259 float spt0
[2], spt1
[2];
260 float mpt0
[2], mpt1
[2];
264 spt1
[0] = srcX
+ width
;
265 spt1
[1] = srcY
+ height
;
269 mpt1
[0] = maskX
+ width
;
270 mpt1
[1] = maskY
+ height
;
273 map_point((float *)src_matrix
, spt0
[0], spt0
[1], &spt0
[0], &spt0
[1]);
274 map_point((float *)src_matrix
, spt1
[0], spt1
[1], &spt1
[0], &spt1
[1]);
278 map_point((float *)mask_matrix
, mpt0
[0], mpt0
[1], &mpt0
[0], &mpt0
[1]);
279 map_point((float *)mask_matrix
, mpt1
[0], mpt1
[1], &mpt1
[0], &mpt1
[1]);
282 src_s0
= spt0
[0] / src
->width0
;
283 src_t0
= spt0
[1] / src
->height0
;
284 src_s1
= spt1
[0] / src
->width0
;
285 src_t1
= spt1
[1] / src
->height0
;
287 mask_s0
= mpt0
[0] / mask
->width0
;
288 mask_t0
= mpt0
[1] / mask
->height0
;
289 mask_s1
= mpt1
[0] / mask
->width0
;
290 mask_t1
= mpt1
[1] / mask
->height0
;
293 add_vertex_2tex(r
, dstX
, dstY
,
294 src_s0
, src_t0
, mask_s0
, mask_t0
);
296 add_vertex_2tex(r
, dstX
+ width
, dstY
,
297 src_s1
, src_t0
, mask_s1
, mask_t0
);
299 add_vertex_2tex(r
, dstX
+ width
, dstY
+ height
,
300 src_s1
, src_t1
, mask_s1
, mask_t1
);
302 add_vertex_2tex(r
, dstX
, dstY
+ height
,
303 src_s0
, src_t1
, mask_s0
, mask_t1
);
306 static struct pipe_resource
*
307 setup_vertex_data_yuv(struct xa_context
*r
,
314 float dstW
, float dstH
, struct xa_surface
*srf
[])
316 float s0
, t0
, s1
, t1
;
317 float spt0
[2], spt1
[2];
318 struct pipe_resource
*tex
;
322 spt1
[0] = srcX
+ srcW
;
323 spt1
[1] = srcY
+ srcH
;
326 s0
= spt0
[0] / tex
->width0
;
327 t0
= spt0
[1] / tex
->height0
;
328 s1
= spt1
[0] / tex
->width0
;
329 t1
= spt1
[1] / tex
->height0
;
332 add_vertex_1tex(r
, dstX
, dstY
, s0
, t0
);
334 add_vertex_1tex(r
, dstX
+ dstW
, dstY
, s1
, t0
);
336 add_vertex_1tex(r
, dstX
+ dstW
, dstY
+ dstH
, s1
, t1
);
338 add_vertex_1tex(r
, dstX
, dstY
+ dstH
, s0
, t1
);
340 return renderer_buffer_create(r
);
343 /* Set up framebuffer, viewport and vertex shader constant buffer
344 * state for a particular destinaton surface. In all our rendering,
345 * these concepts are linked.
348 renderer_bind_destination(struct xa_context
*r
,
349 struct pipe_surface
*surface
, int width
, int height
)
352 struct pipe_framebuffer_state fb
;
353 struct pipe_viewport_state viewport
;
355 /* Framebuffer uses actual surface width/height
357 memset(&fb
, 0, sizeof fb
);
358 fb
.width
= surface
->width
;
359 fb
.height
= surface
->height
;
361 fb
.cbufs
[0] = surface
;
364 /* Viewport just touches the bit we're interested in:
366 viewport
.scale
[0] = width
/ 2.f
;
367 viewport
.scale
[1] = height
/ 2.f
;
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 /* Constant buffer set up to match viewport dimensions:
377 if (r
->fb_width
!= width
|| r
->fb_height
!= height
) {
378 float vs_consts
[8] = {
379 2.f
/ width
, 2.f
/ height
, 1, 1,
384 r
->fb_height
= height
;
386 renderer_set_constants(r
, PIPE_SHADER_VERTEX
,
387 vs_consts
, sizeof vs_consts
);
390 cso_set_framebuffer(r
->cso
, &fb
);
391 cso_set_viewport(r
->cso
, &viewport
);
395 renderer_set_constants(struct xa_context
*r
,
396 int shader_type
, const float *params
, int param_bytes
)
398 struct pipe_resource
**cbuf
=
399 (shader_type
== PIPE_SHADER_VERTEX
) ? &r
->vs_const_buffer
:
402 pipe_resource_reference(cbuf
, NULL
);
403 *cbuf
= pipe_buffer_create(r
->pipe
->screen
,
404 PIPE_BIND_CONSTANT_BUFFER
, PIPE_USAGE_STATIC
,
408 pipe_buffer_write(r
->pipe
, *cbuf
, 0, param_bytes
, params
);
410 r
->pipe
->set_constant_buffer(r
->pipe
, shader_type
, 0, *cbuf
);
414 renderer_copy_prepare(struct xa_context
*r
,
415 struct pipe_surface
*dst_surface
,
416 struct pipe_resource
*src_texture
)
418 struct pipe_context
*pipe
= r
->pipe
;
419 struct pipe_screen
*screen
= pipe
->screen
;
420 struct xa_shader shader
;
422 assert(screen
->is_format_supported(screen
, dst_surface
->format
,
424 PIPE_BIND_RENDER_TARGET
));
427 /* set misc state we care about */
429 struct pipe_blend_state blend
;
431 memset(&blend
, 0, sizeof(blend
));
432 blend
.rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
433 blend
.rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
434 blend
.rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
435 blend
.rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
436 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
437 cso_set_blend(r
->cso
, &blend
);
442 struct pipe_sampler_state sampler
;
444 memset(&sampler
, 0, sizeof(sampler
));
445 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
446 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
447 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
448 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
449 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
450 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
451 sampler
.normalized_coords
= 1;
452 cso_single_sampler(r
->cso
, 0, &sampler
);
453 cso_single_sampler_done(r
->cso
);
456 renderer_bind_destination(r
, dst_surface
,
457 dst_surface
->width
, dst_surface
->height
);
459 /* texture/sampler view */
461 struct pipe_sampler_view templ
;
462 struct pipe_sampler_view
*src_view
;
464 u_sampler_view_default_template(&templ
,
465 src_texture
, src_texture
->format
);
466 src_view
= pipe
->create_sampler_view(pipe
, src_texture
, &templ
);
467 cso_set_fragment_sampler_views(r
->cso
, 1, &src_view
);
468 pipe_sampler_view_reference(&src_view
, NULL
);
472 shader
= xa_shaders_get(r
->shaders
, VS_COMPOSITE
, FS_COMPOSITE
);
473 cso_set_vertex_shader_handle(r
->cso
, shader
.vs
);
474 cso_set_fragment_shader_handle(r
->cso
, shader
.fs
);
477 r
->attrs_per_vertex
= 2;
481 renderer_copy(struct xa_context
*r
,
486 int width
, int height
, float src_width
, float src_height
)
488 float s0
, t0
, s1
, t1
;
489 float x0
, y0
, x1
, y1
;
491 /* XXX: could put the texcoord scaling calculation into the vertex
495 s1
= (sx
+ width
) / src_width
;
496 t0
= sy
/ src_height
;
497 t1
= (sy
+ height
) / src_height
;
505 renderer_draw_conditional(r
, 4 * 8);
506 add_vertex_1tex(r
, x0
, y0
, s0
, t0
);
507 add_vertex_1tex(r
, x1
, y0
, s1
, t0
);
508 add_vertex_1tex(r
, x1
, y1
, s1
, t1
);
509 add_vertex_1tex(r
, x0
, y1
, s0
, t1
);
513 renderer_draw_yuv(struct xa_context
*r
,
519 int dst_y
, int dst_w
, int dst_h
, struct xa_surface
*srf
[])
521 struct pipe_context
*pipe
= r
->pipe
;
522 struct pipe_resource
*buf
= 0;
524 buf
= setup_vertex_data_yuv(r
,
525 src_x
, src_y
, src_w
, src_h
, dst_x
, dst_y
, dst_w
,
529 const int num_attribs
= 2; /*pos + tex coord */
531 cso_set_vertex_elements(r
->cso
, num_attribs
, r
->velems
);
533 util_draw_vertex_buffer(pipe
, r
->cso
, buf
, 0, PIPE_PRIM_QUADS
, 4, /* verts */
534 num_attribs
); /* attribs/vert */
536 pipe_resource_reference(&buf
, NULL
);
541 renderer_begin_solid(struct xa_context
*r
)
544 r
->attrs_per_vertex
= 2;
548 renderer_solid(struct xa_context
*r
,
549 int x0
, int y0
, int x1
, int y1
, float *color
)
552 * debug_printf("solid rect[(%d, %d), (%d, %d)], rgba[%f, %f, %f, %f]\n",
553 * x0, y0, x1, y1, color[0], color[1], color[2], color[3]); */
555 renderer_draw_conditional(r
, 4 * 8);
558 add_vertex_color(r
, x0
, y0
, color
);
560 add_vertex_color(r
, x1
, y0
, color
);
562 add_vertex_color(r
, x1
, y1
, color
);
564 add_vertex_color(r
, x0
, y1
, color
);
568 renderer_draw_flush(struct xa_context
*r
)
570 renderer_draw_conditional(r
, 0);
574 renderer_begin_textures(struct xa_context
*r
)
576 r
->attrs_per_vertex
= 1 + r
->num_bound_samplers
;
581 renderer_texture(struct xa_context
*r
,
583 int width
, int height
,
584 const float *src_matrix
,
585 const float *mask_matrix
)
587 struct pipe_sampler_view
**sampler_view
= r
->bound_sampler_views
;
591 debug_printf("src_matrix = \n");
592 debug_printf("%f, %f, %f\n", src_matrix
[0], src_matrix
[1], src_matrix
[2]);
593 debug_printf("%f, %f, %f\n", src_matrix
[3], src_matrix
[4], src_matrix
[5]);
594 debug_printf("%f, %f, %f\n", src_matrix
[6], src_matrix
[7], src_matrix
[8]);
597 debug_printf("mask_matrix = \n");
598 debug_printf("%f, %f, %f\n", mask_matrix
[0], mask_matrix
[1], mask_matrix
[2]);
599 debug_printf("%f, %f, %f\n", mask_matrix
[3], mask_matrix
[4], mask_matrix
[5]);
600 debug_printf("%f, %f, %f\n", mask_matrix
[6], mask_matrix
[7], mask_matrix
[8]);
604 switch(r
->attrs_per_vertex
) {
606 renderer_draw_conditional(r
, 4 * 8);
608 pos
[0], pos
[1], /* src */
609 pos
[4], pos
[5], /* dst */
611 sampler_view
[0]->texture
, src_matrix
);
614 renderer_draw_conditional(r
, 4 * 12);
616 pos
[0], pos
[1], /* src */
617 pos
[2], pos
[3], /* mask */
618 pos
[4], pos
[5], /* dst */
620 sampler_view
[0]->texture
, sampler_view
[1]->texture
,
621 src_matrix
, mask_matrix
);