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) (fabsf(x - y) <= 0.00001f * MIN2(fabsf(x), fabsf(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(const float *matrix
)
51 return floatIsZero(matrix
[2]) && floatIsZero(matrix
[5])
52 && floatsEqual(matrix
[8], 1);
56 map_point(const 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]);
75 renderer_draw(struct xa_context
*r
)
77 int num_verts
= r
->buffer_size
/ (r
->attrs_per_vertex
* NUM_COMPONENTS
);
82 if (!r
->scissor_valid
) {
85 r
->scissor
.maxx
= r
->dst
->tex
->width0
;
86 r
->scissor
.maxy
= r
->dst
->tex
->height0
;
89 r
->pipe
->set_scissor_states(r
->pipe
, 0, 1, &r
->scissor
);
91 struct cso_velems_state velems
;
92 velems
.count
= r
->attrs_per_vertex
;
93 memcpy(velems
.velems
, r
->velems
, sizeof(r
->velems
[0]) * velems
.count
);
95 cso_set_vertex_elements(r
->cso
, &velems
);
96 util_draw_user_vertex_buffer(r
->cso
, r
->buffer
, PIPE_PRIM_QUADS
,
97 num_verts
, /* verts */
98 r
->attrs_per_vertex
); /* attribs/vert */
105 renderer_draw_conditional(struct xa_context
*r
, int next_batch
)
107 if (r
->buffer_size
+ next_batch
>= XA_VB_SIZE
||
108 (next_batch
== 0 && r
->buffer_size
)) {
114 renderer_init_state(struct xa_context
*r
)
116 struct pipe_depth_stencil_alpha_state dsa
;
117 struct pipe_rasterizer_state raster
;
120 /* set common initial clip state */
121 memset(&dsa
, 0, sizeof(struct pipe_depth_stencil_alpha_state
));
122 cso_set_depth_stencil_alpha(r
->cso
, &dsa
);
124 /* XXX: move to renderer_init_state? */
125 memset(&raster
, 0, sizeof(struct pipe_rasterizer_state
));
126 raster
.half_pixel_center
= 1;
127 raster
.bottom_edge_rule
= 1;
128 raster
.depth_clip_near
= 1;
129 raster
.depth_clip_far
= 1;
131 cso_set_rasterizer(r
->cso
, &raster
);
133 /* vertex elements state */
134 memset(&r
->velems
[0], 0, sizeof(r
->velems
[0]) * 3);
135 for (i
= 0; i
< 3; i
++) {
136 r
->velems
[i
].src_offset
= i
* 4 * sizeof(float);
137 r
->velems
[i
].instance_divisor
= 0;
138 r
->velems
[i
].vertex_buffer_index
= 0;
139 r
->velems
[i
].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
144 add_vertex_none(struct xa_context
*r
, float x
, float y
)
146 float *vertex
= r
->buffer
+ r
->buffer_size
;
150 vertex
[2] = 0.f
; /*z */
151 vertex
[3] = 1.f
; /*w */
157 add_vertex_1tex(struct xa_context
*r
, float x
, float y
, float s
, float t
)
159 float *vertex
= r
->buffer
+ r
->buffer_size
;
163 vertex
[2] = 0.f
; /*z */
164 vertex
[3] = 1.f
; /*w */
166 vertex
[4] = s
; /*s */
167 vertex
[5] = t
; /*t */
168 vertex
[6] = 0.f
; /*r */
169 vertex
[7] = 1.f
; /*q */
175 add_vertex_2tex(struct xa_context
*r
,
176 float x
, float y
, float s0
, float t0
, float s1
, float t1
)
178 float *vertex
= r
->buffer
+ r
->buffer_size
;
182 vertex
[2] = 0.f
; /*z */
183 vertex
[3] = 1.f
; /*w */
185 vertex
[4] = s0
; /*s */
186 vertex
[5] = t0
; /*t */
187 vertex
[6] = 0.f
; /*r */
188 vertex
[7] = 1.f
; /*q */
190 vertex
[8] = s1
; /*s */
191 vertex
[9] = t1
; /*t */
192 vertex
[10] = 0.f
; /*r */
193 vertex
[11] = 1.f
; /*q */
195 r
->buffer_size
+= 12;
199 compute_src_coords(float sx
, float sy
, const struct pipe_resource
*src
,
200 const float *src_matrix
,
201 float width
, float height
,
202 float tc0
[2], float tc1
[2], float tc2
[2], float tc3
[2])
209 tc2
[1] = sy
+ height
;
211 tc3
[1] = sy
+ height
;
214 map_point(src_matrix
, tc0
[0], tc0
[1], &tc0
[0], &tc0
[1]);
215 map_point(src_matrix
, tc1
[0], tc1
[1], &tc1
[0], &tc1
[1]);
216 map_point(src_matrix
, tc2
[0], tc2
[1], &tc2
[0], &tc2
[1]);
217 map_point(src_matrix
, tc3
[0], tc3
[1], &tc3
[0], &tc3
[1]);
220 tc0
[0] /= src
->width0
;
221 tc1
[0] /= src
->width0
;
222 tc2
[0] /= src
->width0
;
223 tc3
[0] /= src
->width0
;
224 tc0
[1] /= src
->height0
;
225 tc1
[1] /= src
->height0
;
226 tc2
[1] /= src
->height0
;
227 tc3
[1] /= src
->height0
;
231 add_vertex_data1(struct xa_context
*r
,
232 float srcX
, float srcY
, float dstX
, float dstY
,
233 float width
, float height
,
234 const struct pipe_resource
*src
, const float *src_matrix
)
236 float tc0
[2], tc1
[2], tc2
[2], tc3
[2];
238 compute_src_coords(srcX
, srcY
, src
, src_matrix
, width
, height
,
241 add_vertex_1tex(r
, dstX
, dstY
, tc0
[0], tc0
[1]);
243 add_vertex_1tex(r
, dstX
+ width
, dstY
, tc1
[0], tc1
[1]);
245 add_vertex_1tex(r
, dstX
+ width
, dstY
+ height
, tc2
[0], tc2
[1]);
247 add_vertex_1tex(r
, dstX
, dstY
+ height
, tc3
[0], tc3
[1]);
251 add_vertex_data2(struct xa_context
*r
,
252 float srcX
, float srcY
, float maskX
, float maskY
,
253 float dstX
, float dstY
, float width
, float height
,
254 struct pipe_resource
*src
,
255 struct pipe_resource
*mask
,
256 const float *src_matrix
, const float *mask_matrix
)
258 float spt0
[2], spt1
[2], spt2
[2], spt3
[2];
259 float mpt0
[2], mpt1
[2], mpt2
[2], mpt3
[2];
261 compute_src_coords(srcX
, srcY
, src
, src_matrix
, width
, height
,
262 spt0
, spt1
, spt2
, spt3
);
263 compute_src_coords(maskX
, maskY
, mask
, mask_matrix
, width
, height
,
264 mpt0
, mpt1
, mpt2
, mpt3
);
267 add_vertex_2tex(r
, dstX
, dstY
,
268 spt0
[0], spt0
[1], mpt0
[0], mpt0
[1]);
270 add_vertex_2tex(r
, dstX
+ width
, dstY
,
271 spt1
[0], spt1
[1], mpt1
[0], mpt1
[1]);
273 add_vertex_2tex(r
, dstX
+ width
, dstY
+ height
,
274 spt2
[0], spt2
[1], mpt2
[0], mpt2
[1]);
276 add_vertex_2tex(r
, dstX
, dstY
+ height
,
277 spt3
[0], spt3
[1], mpt3
[0], mpt3
[1]);
281 setup_vertex_data_yuv(struct xa_context
*r
,
288 float dstW
, float dstH
, struct xa_surface
*srf
[])
290 float s0
, t0
, s1
, t1
;
291 float spt0
[2], spt1
[2];
292 struct pipe_resource
*tex
;
296 spt1
[0] = srcX
+ srcW
;
297 spt1
[1] = srcY
+ srcH
;
300 s0
= spt0
[0] / tex
->width0
;
301 t0
= spt0
[1] / tex
->height0
;
302 s1
= spt1
[0] / tex
->width0
;
303 t1
= spt1
[1] / tex
->height0
;
306 add_vertex_1tex(r
, dstX
, dstY
, s0
, t0
);
308 add_vertex_1tex(r
, dstX
+ dstW
, dstY
, s1
, t0
);
310 add_vertex_1tex(r
, dstX
+ dstW
, dstY
+ dstH
, s1
, t1
);
312 add_vertex_1tex(r
, dstX
, dstY
+ dstH
, s0
, t1
);
315 /* Set up framebuffer, viewport and vertex shader constant buffer
316 * state for a particular destinaton surface. In all our rendering,
317 * these concepts are linked.
320 renderer_bind_destination(struct xa_context
*r
,
321 struct pipe_surface
*surface
)
323 int width
= surface
->width
;
324 int height
= surface
->height
;
326 struct pipe_framebuffer_state fb
;
327 struct pipe_viewport_state viewport
;
331 /* Framebuffer uses actual surface width/height
333 memset(&fb
, 0, sizeof fb
);
334 fb
.width
= surface
->width
;
335 fb
.height
= surface
->height
;
337 fb
.cbufs
[0] = surface
;
340 /* Viewport just touches the bit we're interested in:
342 viewport
.scale
[0] = width
/ 2.f
;
343 viewport
.scale
[1] = height
/ 2.f
;
344 viewport
.scale
[2] = 1.0;
345 viewport
.translate
[0] = width
/ 2.f
;
346 viewport
.translate
[1] = height
/ 2.f
;
347 viewport
.translate
[2] = 0.0;
349 /* Constant buffer set up to match viewport dimensions:
351 if (r
->fb_width
!= width
|| r
->fb_height
!= height
) {
352 float vs_consts
[8] = {
353 2.f
/ width
, 2.f
/ height
, 1, 1,
358 r
->fb_height
= height
;
360 renderer_set_constants(r
, PIPE_SHADER_VERTEX
,
361 vs_consts
, sizeof vs_consts
);
364 cso_set_framebuffer(r
->cso
, &fb
);
365 cso_set_viewport(r
->cso
, &viewport
);
369 renderer_set_constants(struct xa_context
*r
,
370 int shader_type
, const float *params
, int param_bytes
)
372 struct pipe_resource
**cbuf
=
373 (shader_type
== PIPE_SHADER_VERTEX
) ? &r
->vs_const_buffer
:
376 pipe_resource_reference(cbuf
, NULL
);
377 *cbuf
= pipe_buffer_create_const0(r
->pipe
->screen
,
378 PIPE_BIND_CONSTANT_BUFFER
,
383 pipe_buffer_write(r
->pipe
, *cbuf
, 0, param_bytes
, params
);
385 pipe_set_constant_buffer(r
->pipe
, shader_type
, 0, *cbuf
);
389 renderer_copy_prepare(struct xa_context
*r
,
390 struct pipe_surface
*dst_surface
,
391 struct pipe_resource
*src_texture
,
392 const enum xa_formats src_xa_format
,
393 const enum xa_formats dst_xa_format
)
395 struct pipe_context
*pipe
= r
->pipe
;
396 struct pipe_screen
*screen
= pipe
->screen
;
397 struct xa_shader shader
;
398 uint32_t fs_traits
= FS_COMPOSITE
;
400 assert(screen
->is_format_supported(screen
, dst_surface
->format
,
401 PIPE_TEXTURE_2D
, 0, 0,
402 PIPE_BIND_RENDER_TARGET
));
405 renderer_bind_destination(r
, dst_surface
);
407 /* set misc state we care about */
409 struct pipe_blend_state blend
;
411 memset(&blend
, 0, sizeof(blend
));
412 blend
.rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
413 blend
.rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
414 blend
.rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
415 blend
.rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
416 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
417 cso_set_blend(r
->cso
, &blend
);
422 struct pipe_sampler_state sampler
;
423 const struct pipe_sampler_state
*p_sampler
= &sampler
;
425 memset(&sampler
, 0, sizeof(sampler
));
426 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
427 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
428 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
429 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
430 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
431 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
432 sampler
.normalized_coords
= 1;
433 cso_set_samplers(r
->cso
, PIPE_SHADER_FRAGMENT
, 1, &p_sampler
);
434 r
->num_bound_samplers
= 1;
437 /* texture/sampler view */
439 struct pipe_sampler_view templ
;
440 struct pipe_sampler_view
*src_view
;
442 u_sampler_view_default_template(&templ
,
443 src_texture
, src_texture
->format
);
444 src_view
= pipe
->create_sampler_view(pipe
, src_texture
, &templ
);
445 cso_set_sampler_views(r
->cso
, PIPE_SHADER_FRAGMENT
, 1, &src_view
);
446 pipe_sampler_view_reference(&src_view
, NULL
);
450 if (src_texture
->format
== PIPE_FORMAT_L8_UNORM
||
451 src_texture
->format
== PIPE_FORMAT_R8_UNORM
)
452 fs_traits
|= FS_SRC_LUMINANCE
;
453 if (dst_surface
->format
== PIPE_FORMAT_L8_UNORM
||
454 dst_surface
->format
== PIPE_FORMAT_R8_UNORM
)
455 fs_traits
|= FS_DST_LUMINANCE
;
456 if (xa_format_a(dst_xa_format
) != 0 &&
457 xa_format_a(src_xa_format
) == 0)
458 fs_traits
|= FS_SRC_SET_ALPHA
;
460 shader
= xa_shaders_get(r
->shaders
, VS_COMPOSITE
, fs_traits
);
461 cso_set_vertex_shader_handle(r
->cso
, shader
.vs
);
462 cso_set_fragment_shader_handle(r
->cso
, shader
.fs
);
465 r
->attrs_per_vertex
= 2;
469 renderer_copy(struct xa_context
*r
,
474 int width
, int height
, float src_width
, float src_height
)
476 float s0
, t0
, s1
, t1
;
477 float x0
, y0
, x1
, y1
;
479 /* XXX: could put the texcoord scaling calculation into the vertex
483 s1
= (sx
+ width
) / src_width
;
484 t0
= sy
/ src_height
;
485 t1
= (sy
+ height
) / src_height
;
493 renderer_draw_conditional(r
, 4 * 8);
494 add_vertex_1tex(r
, x0
, y0
, s0
, t0
);
495 add_vertex_1tex(r
, x1
, y0
, s1
, t0
);
496 add_vertex_1tex(r
, x1
, y1
, s1
, t1
);
497 add_vertex_1tex(r
, x0
, y1
, s0
, t1
);
501 renderer_draw_yuv(struct xa_context
*r
,
507 int dst_y
, int dst_w
, int dst_h
, struct xa_surface
*srf
[])
509 const int num_attribs
= 2; /*pos + tex coord */
511 setup_vertex_data_yuv(r
,
512 src_x
, src_y
, src_w
, src_h
,
513 dst_x
, dst_y
, dst_w
, dst_h
, srf
);
515 if (!r
->scissor_valid
) {
518 r
->scissor
.maxx
= r
->dst
->tex
->width0
;
519 r
->scissor
.maxy
= r
->dst
->tex
->height0
;
522 r
->pipe
->set_scissor_states(r
->pipe
, 0, 1, &r
->scissor
);
524 struct cso_velems_state velems
;
525 velems
.count
= num_attribs
;
526 memcpy(velems
.velems
, r
->velems
, sizeof(r
->velems
[0]) * velems
.count
);
528 cso_set_vertex_elements(r
->cso
, &velems
);
529 util_draw_user_vertex_buffer(r
->cso
, r
->buffer
, PIPE_PRIM_QUADS
,
531 num_attribs
); /* attribs/vert */
538 renderer_begin_solid(struct xa_context
*r
)
541 r
->attrs_per_vertex
= 1;
542 renderer_set_constants(r
, PIPE_SHADER_FRAGMENT
, r
->solid_color
,
547 renderer_solid(struct xa_context
*r
,
548 int x0
, int y0
, int x1
, int y1
)
551 * debug_printf("solid rect[(%d, %d), (%d, %d)], rgba[%f, %f, %f, %f]\n",
552 * x0, y0, x1, y1, color[0], color[1], color[2], color[3]); */
554 renderer_draw_conditional(r
, 4 * 4);
557 add_vertex_none(r
, x0
, y0
);
559 add_vertex_none(r
, x1
, y0
);
561 add_vertex_none(r
, x1
, y1
);
563 add_vertex_none(r
, x0
, y1
);
567 renderer_draw_flush(struct xa_context
*r
)
569 renderer_draw_conditional(r
, 0);
573 renderer_begin_textures(struct xa_context
*r
)
575 r
->attrs_per_vertex
= 1 + r
->num_bound_samplers
;
577 if (r
->has_solid_src
|| r
->has_solid_mask
)
578 renderer_set_constants(r
, PIPE_SHADER_FRAGMENT
, r
->solid_color
,
583 renderer_texture(struct xa_context
*r
,
585 int width
, int height
,
586 const float *src_matrix
,
587 const float *mask_matrix
)
589 struct pipe_sampler_view
**sampler_view
= r
->bound_sampler_views
;
593 debug_printf("src_matrix = \n");
594 debug_printf("%f, %f, %f\n", src_matrix
[0], src_matrix
[1], src_matrix
[2]);
595 debug_printf("%f, %f, %f\n", src_matrix
[3], src_matrix
[4], src_matrix
[5]);
596 debug_printf("%f, %f, %f\n", src_matrix
[6], src_matrix
[7], src_matrix
[8]);
599 debug_printf("mask_matrix = \n");
600 debug_printf("%f, %f, %f\n", mask_matrix
[0], mask_matrix
[1], mask_matrix
[2]);
601 debug_printf("%f, %f, %f\n", mask_matrix
[3], mask_matrix
[4], mask_matrix
[5]);
602 debug_printf("%f, %f, %f\n", mask_matrix
[6], mask_matrix
[7], mask_matrix
[8]);
606 switch(r
->attrs_per_vertex
) {
608 renderer_draw_conditional(r
, 4 * 8);
609 if (!r
->has_solid_src
) {
611 pos
[0], pos
[1], /* src */
612 pos
[4], pos
[5], /* dst */
614 sampler_view
[0]->texture
, src_matrix
);
617 pos
[2], pos
[3], /* mask */
618 pos
[4], pos
[5], /* dst */
620 sampler_view
[0]->texture
, mask_matrix
);
624 renderer_draw_conditional(r
, 4 * 12);
626 pos
[0], pos
[1], /* src */
627 pos
[2], pos
[3], /* mask */
628 pos
[4], pos
[5], /* dst */
630 sampler_view
[0]->texture
, sampler_view
[1]->texture
,
631 src_matrix
, mask_matrix
);