1 /**************************************************************************
3 * Copyright 2009 Younes Manton.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 #include "pipe/p_compiler.h"
31 #include "pipe/p_context.h"
33 #include "util/u_memory.h"
34 #include "util/u_draw.h"
35 #include "util/u_surface.h"
37 #include "tgsi/tgsi_ureg.h"
41 #include "vl_compositor.h"
44 #define MAX_DIRTY (1 << 15)
54 typedef float csc_matrix
[16];
57 create_vert_shader(struct vl_compositor
*c
)
59 struct ureg_program
*shader
;
60 struct ureg_src vpos
, vtex
;
62 struct ureg_dst o_vpos
, o_vtex
;
63 struct ureg_dst o_vtop
, o_vbottom
;
65 shader
= ureg_create(TGSI_PROCESSOR_VERTEX
);
69 vpos
= ureg_DECL_vs_input(shader
, 0);
70 vtex
= ureg_DECL_vs_input(shader
, 1);
71 tmp
= ureg_DECL_temporary(shader
);
72 o_vpos
= ureg_DECL_output(shader
, TGSI_SEMANTIC_POSITION
, VS_O_VPOS
);
73 o_vtex
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_VTEX
);
74 o_vtop
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_VTOP
);
75 o_vbottom
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_VBOTTOM
);
81 ureg_MOV(shader
, o_vpos
, vpos
);
82 ureg_MOV(shader
, o_vtex
, vtex
);
84 ureg_MUL(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_X
),
85 ureg_scalar(vtex
, TGSI_SWIZZLE_W
), ureg_imm1f(shader
, 0.5f
));
86 ureg_MUL(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
),
87 ureg_scalar(vtex
, TGSI_SWIZZLE_W
), ureg_imm1f(shader
, 0.25f
));
89 ureg_MOV(shader
, ureg_writemask(o_vtop
, TGSI_WRITEMASK_X
), vtex
);
90 ureg_MAD(shader
, ureg_writemask(o_vtop
, TGSI_WRITEMASK_Y
), ureg_scalar(vtex
, TGSI_SWIZZLE_Y
),
91 ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_X
), ureg_imm1f(shader
, 0.25f
));
92 ureg_MAD(shader
, ureg_writemask(o_vtop
, TGSI_WRITEMASK_Z
), ureg_scalar(vtex
, TGSI_SWIZZLE_Y
),
93 ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_Y
), ureg_imm1f(shader
, 0.25f
));
94 ureg_RCP(shader
, ureg_writemask(o_vtop
, TGSI_WRITEMASK_W
),
95 ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_X
));
97 ureg_MOV(shader
, ureg_writemask(o_vbottom
, TGSI_WRITEMASK_X
), vtex
);
98 ureg_MAD(shader
, ureg_writemask(o_vbottom
, TGSI_WRITEMASK_Y
), ureg_scalar(vtex
, TGSI_SWIZZLE_Y
),
99 ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_X
), ureg_imm1f(shader
, -0.25f
));
100 ureg_MAD(shader
, ureg_writemask(o_vbottom
, TGSI_WRITEMASK_Z
), ureg_scalar(vtex
, TGSI_SWIZZLE_Y
),
101 ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_Y
), ureg_imm1f(shader
, -0.25f
));
102 ureg_RCP(shader
, ureg_writemask(o_vbottom
, TGSI_WRITEMASK_W
),
103 ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_Y
));
107 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
111 create_frag_shader_video_buffer(struct vl_compositor
*c
)
113 struct ureg_program
*shader
;
115 struct ureg_src csc
[3];
116 struct ureg_src sampler
[3];
117 struct ureg_dst texel
;
118 struct ureg_dst fragment
;
121 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
125 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
126 for (i
= 0; i
< 3; ++i
) {
127 csc
[i
] = ureg_DECL_constant(shader
, i
);
128 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
130 texel
= ureg_DECL_temporary(shader
);
131 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
134 * texel.xyz = tex(tc, sampler[i])
135 * fragment = csc * texel
137 for (i
= 0; i
< 3; ++i
)
138 ureg_TEX(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_X
<< i
), TGSI_TEXTURE_3D
, tc
, sampler
[i
]);
140 ureg_MOV(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
142 for (i
= 0; i
< 3; ++i
)
143 ureg_DP4(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_X
<< i
), csc
[i
], ureg_src(texel
));
145 ureg_MOV(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
147 ureg_release_temporary(shader
, texel
);
150 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
154 create_frag_shader_weave(struct vl_compositor
*c
)
156 struct ureg_program
*shader
;
157 struct ureg_src i_tc
[2];
158 struct ureg_src csc
[3];
159 struct ureg_src sampler
[3];
160 struct ureg_dst t_tc
[2];
161 struct ureg_dst t_texel
[2];
162 struct ureg_dst o_fragment
;
165 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
169 i_tc
[0] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_VTOP
, TGSI_INTERPOLATE_LINEAR
);
170 i_tc
[1] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_VBOTTOM
, TGSI_INTERPOLATE_LINEAR
);
172 for (i
= 0; i
< 3; ++i
) {
173 csc
[i
] = ureg_DECL_constant(shader
, i
);
174 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
177 for (i
= 0; i
< 2; ++i
) {
178 t_tc
[i
] = ureg_DECL_temporary(shader
);
179 t_texel
[i
] = ureg_DECL_temporary(shader
);
181 o_fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
183 /* calculate the texture offsets
185 * t_tc.y = (round(i_tc.y) + 0.5) / height * 2
187 for (i
= 0; i
< 2; ++i
) {
188 ureg_MOV(shader
, ureg_writemask(t_tc
[i
], TGSI_WRITEMASK_X
), i_tc
[i
]);
189 ureg_ROUND(shader
, ureg_writemask(t_tc
[i
], TGSI_WRITEMASK_YZ
), i_tc
[i
]);
190 ureg_MOV(shader
, ureg_writemask(t_tc
[i
], TGSI_WRITEMASK_W
),
191 ureg_imm1f(shader
, i
? 0.75f
: 0.25f
));
192 ureg_ADD(shader
, ureg_writemask(t_tc
[i
], TGSI_WRITEMASK_YZ
),
193 ureg_src(t_tc
[i
]), ureg_imm1f(shader
, 0.5f
));
194 ureg_MUL(shader
, ureg_writemask(t_tc
[i
], TGSI_WRITEMASK_Y
),
195 ureg_src(t_tc
[i
]), ureg_scalar(i_tc
[0], TGSI_SWIZZLE_W
));
196 ureg_MUL(shader
, ureg_writemask(t_tc
[i
], TGSI_WRITEMASK_Z
),
197 ureg_src(t_tc
[i
]), ureg_scalar(i_tc
[1], TGSI_SWIZZLE_W
));
201 * texel[0..1].x = tex(t_tc[0..1][0])
202 * texel[0..1].y = tex(t_tc[0..1][1])
203 * texel[0..1].z = tex(t_tc[0..1][2])
205 for (i
= 0; i
< 2; ++i
)
206 for (j
= 0; j
< 3; ++j
) {
207 struct ureg_src src
= ureg_swizzle(ureg_src(t_tc
[i
]),
208 TGSI_SWIZZLE_X
, j
? TGSI_SWIZZLE_Z
: TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_W
, TGSI_SWIZZLE_W
);
210 ureg_TEX(shader
, ureg_writemask(t_texel
[i
], TGSI_WRITEMASK_X
<< j
),
211 TGSI_TEXTURE_3D
, src
, sampler
[j
]);
214 /* calculate linear interpolation factor
215 * factor = |round(i_tc.y) - i_tc.y| * 2
217 ureg_ROUND(shader
, ureg_writemask(t_tc
[0], TGSI_WRITEMASK_YZ
), i_tc
[0]);
218 ureg_ADD(shader
, ureg_writemask(t_tc
[0], TGSI_WRITEMASK_YZ
),
219 ureg_src(t_tc
[0]), ureg_negate(i_tc
[0]));
220 ureg_MUL(shader
, ureg_writemask(t_tc
[0], TGSI_WRITEMASK_XY
),
221 ureg_abs(ureg_src(t_tc
[0])), ureg_imm1f(shader
, 2.0f
));
222 ureg_LRP(shader
, t_texel
[0], ureg_swizzle(ureg_src(t_tc
[0]),
223 TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_Z
, TGSI_SWIZZLE_Z
, TGSI_SWIZZLE_Z
),
224 ureg_src(t_texel
[1]), ureg_src(t_texel
[0]));
226 /* and finally do colour space transformation
227 * fragment = csc * texel
229 ureg_MOV(shader
, ureg_writemask(t_texel
[0], TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
230 for (i
= 0; i
< 3; ++i
)
231 ureg_DP4(shader
, ureg_writemask(o_fragment
, TGSI_WRITEMASK_X
<< i
), csc
[i
], ureg_src(t_texel
[0]));
233 ureg_MOV(shader
, ureg_writemask(o_fragment
, TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
235 for (i
= 0; i
< 2; ++i
) {
236 ureg_release_temporary(shader
, t_texel
[i
]);
237 ureg_release_temporary(shader
, t_tc
[i
]);
242 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
246 create_frag_shader_palette(struct vl_compositor
*c
, bool include_cc
)
248 struct ureg_program
*shader
;
249 struct ureg_src csc
[3];
251 struct ureg_src sampler
;
252 struct ureg_src palette
;
253 struct ureg_dst texel
;
254 struct ureg_dst fragment
;
257 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
261 for (i
= 0; include_cc
&& i
< 3; ++i
)
262 csc
[i
] = ureg_DECL_constant(shader
, i
);
264 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_VTEX
, TGSI_INTERPOLATE_LINEAR
);
265 sampler
= ureg_DECL_sampler(shader
, 0);
266 palette
= ureg_DECL_sampler(shader
, 1);
268 texel
= ureg_DECL_temporary(shader
);
269 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
272 * texel = tex(tc, sampler)
273 * fragment.xyz = tex(texel, palette) * csc
274 * fragment.a = texel.a
276 ureg_TEX(shader
, texel
, TGSI_TEXTURE_2D
, tc
, sampler
);
277 ureg_MOV(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_W
), ureg_src(texel
));
280 ureg_TEX(shader
, texel
, TGSI_TEXTURE_1D
, ureg_src(texel
), palette
);
281 for (i
= 0; i
< 3; ++i
)
282 ureg_DP4(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_X
<< i
), csc
[i
], ureg_src(texel
));
284 ureg_TEX(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_XYZ
),
285 TGSI_TEXTURE_1D
, ureg_src(texel
), palette
);
288 ureg_release_temporary(shader
, texel
);
291 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
295 create_frag_shader_rgba(struct vl_compositor
*c
)
297 struct ureg_program
*shader
;
299 struct ureg_src sampler
;
300 struct ureg_dst fragment
;
302 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
306 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_VTEX
, TGSI_INTERPOLATE_LINEAR
);
307 sampler
= ureg_DECL_sampler(shader
, 0);
308 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
311 * fragment = tex(tc, sampler)
313 ureg_TEX(shader
, fragment
, TGSI_TEXTURE_2D
, tc
, sampler
);
316 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
320 init_shaders(struct vl_compositor
*c
)
324 c
->vs
= create_vert_shader(c
);
326 debug_printf("Unable to create vertex shader.\n");
330 c
->fs_video_buffer
= create_frag_shader_video_buffer(c
);
331 if (!c
->fs_video_buffer
) {
332 debug_printf("Unable to create YCbCr-to-RGB fragment shader.\n");
336 c
->fs_weave
= create_frag_shader_weave(c
);
338 debug_printf("Unable to create YCbCr-to-RGB weave fragment shader.\n");
342 c
->fs_palette
.yuv
= create_frag_shader_palette(c
, true);
343 if (!c
->fs_palette
.yuv
) {
344 debug_printf("Unable to create YUV-Palette-to-RGB fragment shader.\n");
348 c
->fs_palette
.rgb
= create_frag_shader_palette(c
, false);
349 if (!c
->fs_palette
.rgb
) {
350 debug_printf("Unable to create RGB-Palette-to-RGB fragment shader.\n");
354 c
->fs_rgba
= create_frag_shader_rgba(c
);
356 debug_printf("Unable to create RGB-to-RGB fragment shader.\n");
363 static void cleanup_shaders(struct vl_compositor
*c
)
367 c
->pipe
->delete_vs_state(c
->pipe
, c
->vs
);
368 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_video_buffer
);
369 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_weave
);
370 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_palette
.yuv
);
371 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_palette
.rgb
);
372 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_rgba
);
376 init_pipe_state(struct vl_compositor
*c
)
378 struct pipe_rasterizer_state rast
;
379 struct pipe_sampler_state sampler
;
380 struct pipe_blend_state blend
;
381 struct pipe_depth_stencil_alpha_state dsa
;
386 c
->fb_state
.nr_cbufs
= 1;
387 c
->fb_state
.zsbuf
= NULL
;
389 c
->viewport
.scale
[2] = 1;
390 c
->viewport
.scale
[3] = 1;
391 c
->viewport
.translate
[2] = 0;
392 c
->viewport
.translate
[3] = 0;
394 memset(&sampler
, 0, sizeof(sampler
));
395 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
396 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
397 sampler
.wrap_r
= PIPE_TEX_WRAP_REPEAT
;
398 sampler
.min_img_filter
= PIPE_TEX_FILTER_LINEAR
;
399 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
400 sampler
.mag_img_filter
= PIPE_TEX_FILTER_LINEAR
;
401 sampler
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
402 sampler
.compare_func
= PIPE_FUNC_ALWAYS
;
403 sampler
.normalized_coords
= 1;
405 c
->sampler_linear
= c
->pipe
->create_sampler_state(c
->pipe
, &sampler
);
407 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
408 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
409 c
->sampler_nearest
= c
->pipe
->create_sampler_state(c
->pipe
, &sampler
);
411 memset(&blend
, 0, sizeof blend
);
412 blend
.independent_blend_enable
= 0;
413 blend
.rt
[0].blend_enable
= 0;
414 blend
.logicop_enable
= 0;
415 blend
.logicop_func
= PIPE_LOGICOP_CLEAR
;
416 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
418 c
->blend_clear
= c
->pipe
->create_blend_state(c
->pipe
, &blend
);
420 blend
.rt
[0].blend_enable
= 1;
421 blend
.rt
[0].rgb_func
= PIPE_BLEND_ADD
;
422 blend
.rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_SRC_ALPHA
;
423 blend
.rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_INV_SRC_ALPHA
;
424 blend
.rt
[0].alpha_func
= PIPE_BLEND_ADD
;
425 blend
.rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
426 blend
.rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ONE
;
427 c
->blend_add
= c
->pipe
->create_blend_state(c
->pipe
, &blend
);
429 memset(&rast
, 0, sizeof rast
);
432 rast
.cull_face
= PIPE_FACE_NONE
;
433 rast
.fill_back
= PIPE_POLYGON_MODE_FILL
;
434 rast
.fill_front
= PIPE_POLYGON_MODE_FILL
;
437 rast
.point_size_per_vertex
= 1;
438 rast
.offset_units
= 1;
439 rast
.offset_scale
= 1;
440 rast
.gl_rasterization_rules
= 1;
443 c
->rast
= c
->pipe
->create_rasterizer_state(c
->pipe
, &rast
);
445 memset(&dsa
, 0, sizeof dsa
);
446 dsa
.depth
.enabled
= 0;
447 dsa
.depth
.writemask
= 0;
448 dsa
.depth
.func
= PIPE_FUNC_ALWAYS
;
449 for (i
= 0; i
< 2; ++i
) {
450 dsa
.stencil
[i
].enabled
= 0;
451 dsa
.stencil
[i
].func
= PIPE_FUNC_ALWAYS
;
452 dsa
.stencil
[i
].fail_op
= PIPE_STENCIL_OP_KEEP
;
453 dsa
.stencil
[i
].zpass_op
= PIPE_STENCIL_OP_KEEP
;
454 dsa
.stencil
[i
].zfail_op
= PIPE_STENCIL_OP_KEEP
;
455 dsa
.stencil
[i
].valuemask
= 0;
456 dsa
.stencil
[i
].writemask
= 0;
458 dsa
.alpha
.enabled
= 0;
459 dsa
.alpha
.func
= PIPE_FUNC_ALWAYS
;
460 dsa
.alpha
.ref_value
= 0;
461 c
->dsa
= c
->pipe
->create_depth_stencil_alpha_state(c
->pipe
, &dsa
);
462 c
->pipe
->bind_depth_stencil_alpha_state(c
->pipe
, c
->dsa
);
467 static void cleanup_pipe_state(struct vl_compositor
*c
)
471 /* Asserted in softpipe_delete_fs_state() for some reason */
472 c
->pipe
->bind_vs_state(c
->pipe
, NULL
);
473 c
->pipe
->bind_fs_state(c
->pipe
, NULL
);
475 c
->pipe
->delete_depth_stencil_alpha_state(c
->pipe
, c
->dsa
);
476 c
->pipe
->delete_sampler_state(c
->pipe
, c
->sampler_linear
);
477 c
->pipe
->delete_sampler_state(c
->pipe
, c
->sampler_nearest
);
478 c
->pipe
->delete_blend_state(c
->pipe
, c
->blend_clear
);
479 c
->pipe
->delete_blend_state(c
->pipe
, c
->blend_add
);
480 c
->pipe
->delete_rasterizer_state(c
->pipe
, c
->rast
);
484 create_vertex_buffer(struct vl_compositor
*c
)
488 pipe_resource_reference(&c
->vertex_buf
.buffer
, NULL
);
489 c
->vertex_buf
.buffer
= pipe_buffer_create
492 PIPE_BIND_VERTEX_BUFFER
,
494 c
->vertex_buf
.stride
* VL_COMPOSITOR_MAX_LAYERS
* 4
497 return c
->vertex_buf
.buffer
!= NULL
;
501 init_buffers(struct vl_compositor
*c
)
503 struct pipe_vertex_element vertex_elems
[2];
508 * Create our vertex buffer and vertex buffer elements
510 c
->vertex_buf
.stride
= sizeof(struct vertex2f
) + sizeof(struct vertex4f
);
511 c
->vertex_buf
.buffer_offset
= 0;
512 create_vertex_buffer(c
);
514 vertex_elems
[0].src_offset
= 0;
515 vertex_elems
[0].instance_divisor
= 0;
516 vertex_elems
[0].vertex_buffer_index
= 0;
517 vertex_elems
[0].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
518 vertex_elems
[1].src_offset
= sizeof(struct vertex2f
);
519 vertex_elems
[1].instance_divisor
= 0;
520 vertex_elems
[1].vertex_buffer_index
= 0;
521 vertex_elems
[1].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
522 c
->vertex_elems_state
= c
->pipe
->create_vertex_elements_state(c
->pipe
, 2, vertex_elems
);
525 * Create our fragment shader's constant buffer
526 * Const buffer contains the color conversion matrix and bias vectors
528 /* XXX: Create with IMMUTABLE/STATIC... although it does change every once in a long while... */
529 c
->csc_matrix
= pipe_buffer_create
532 PIPE_BIND_CONSTANT_BUFFER
,
541 cleanup_buffers(struct vl_compositor
*c
)
545 c
->pipe
->delete_vertex_elements_state(c
->pipe
, c
->vertex_elems_state
);
546 pipe_resource_reference(&c
->vertex_buf
.buffer
, NULL
);
547 pipe_resource_reference(&c
->csc_matrix
, NULL
);
550 static INLINE
struct pipe_video_rect
551 default_rect(struct vl_compositor_layer
*layer
)
553 struct pipe_resource
*res
= layer
->sampler_views
[0]->texture
;
554 struct pipe_video_rect rect
= { 0, 0, res
->width0
, res
->height0
* res
->depth0
};
558 static INLINE
struct vertex2f
559 calc_topleft(struct vertex2f size
, struct pipe_video_rect rect
)
561 struct vertex2f res
= { rect
.x
/ size
.x
, rect
.y
/ size
.y
};
565 static INLINE
struct vertex2f
566 calc_bottomright(struct vertex2f size
, struct pipe_video_rect rect
)
568 struct vertex2f res
= { (rect
.x
+ rect
.w
) / size
.x
, (rect
.y
+ rect
.h
) / size
.y
};
573 calc_src_and_dst(struct vl_compositor_layer
*layer
, unsigned width
, unsigned height
,
574 struct pipe_video_rect src
, struct pipe_video_rect dst
)
576 struct vertex2f size
= { width
, height
};
578 layer
->src
.tl
= calc_topleft(size
, src
);
579 layer
->src
.br
= calc_bottomright(size
, src
);
580 layer
->dst
.tl
= calc_topleft(size
, dst
);
581 layer
->dst
.br
= calc_bottomright(size
, dst
);
586 gen_rect_verts(struct vertex2f
*vb
, struct vl_compositor_layer
*layer
)
590 vb
[ 0].x
= layer
->dst
.tl
.x
;
591 vb
[ 0].y
= layer
->dst
.tl
.y
;
592 vb
[ 1].x
= layer
->src
.tl
.x
;
593 vb
[ 1].y
= layer
->src
.tl
.y
;
594 vb
[ 2] = layer
->size
;
596 vb
[ 3].x
= layer
->dst
.br
.x
;
597 vb
[ 3].y
= layer
->dst
.tl
.y
;
598 vb
[ 4].x
= layer
->src
.br
.x
;
599 vb
[ 4].y
= layer
->src
.tl
.y
;
600 vb
[ 5] = layer
->size
;
602 vb
[ 6].x
= layer
->dst
.br
.x
;
603 vb
[ 6].y
= layer
->dst
.br
.y
;
604 vb
[ 7].x
= layer
->src
.br
.x
;
605 vb
[ 7].y
= layer
->src
.br
.y
;
606 vb
[ 8] = layer
->size
;
608 vb
[ 9].x
= layer
->dst
.tl
.x
;
609 vb
[ 9].y
= layer
->dst
.br
.y
;
610 vb
[10].x
= layer
->src
.tl
.x
;
611 vb
[10].y
= layer
->src
.br
.y
;
612 vb
[11] = layer
->size
;
615 static INLINE
struct u_rect
616 calc_drawn_area(struct vl_compositor
*c
, struct vl_compositor_layer
*layer
)
618 struct u_rect result
;
621 result
.x0
= layer
->dst
.tl
.x
* c
->viewport
.scale
[0] + c
->viewport
.translate
[0];
622 result
.y0
= layer
->dst
.tl
.y
* c
->viewport
.scale
[1] + c
->viewport
.translate
[1];
623 result
.x1
= layer
->dst
.br
.x
* c
->viewport
.scale
[0] + c
->viewport
.translate
[0];
624 result
.y1
= layer
->dst
.br
.y
* c
->viewport
.scale
[1] + c
->viewport
.translate
[1];
627 result
.x0
= MAX2(result
.x0
, c
->scissor
.minx
);
628 result
.y0
= MAX2(result
.y0
, c
->scissor
.miny
);
629 result
.x1
= MIN2(result
.x1
, c
->scissor
.maxx
);
630 result
.y1
= MIN2(result
.y1
, c
->scissor
.maxy
);
635 gen_vertex_data(struct vl_compositor
*c
, struct u_rect
*dirty
)
638 struct pipe_transfer
*buf_transfer
;
643 vb
= pipe_buffer_map(c
->pipe
, c
->vertex_buf
.buffer
,
644 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD_RANGE
| PIPE_TRANSFER_DONTBLOCK
,
648 // If buffer is still locked from last draw create a new one
649 create_vertex_buffer(c
);
650 vb
= pipe_buffer_map(c
->pipe
, c
->vertex_buf
.buffer
,
651 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD_RANGE
,
655 for (i
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; i
++) {
656 if (c
->used_layers
& (1 << i
)) {
657 struct vl_compositor_layer
*layer
= &c
->layers
[i
];
658 gen_rect_verts(vb
, layer
);
661 if (dirty
&& layer
->clearing
) {
662 struct u_rect drawn
= calc_drawn_area(c
, layer
);
664 dirty
->x0
>= drawn
.x0
&&
665 dirty
->y0
>= drawn
.y0
&&
666 dirty
->x1
<= drawn
.x1
&&
667 dirty
->y1
<= drawn
.y1
) {
669 // We clear the dirty area anyway, no need for clear_render_target
670 dirty
->x0
= dirty
->y0
= MAX_DIRTY
;
671 dirty
->x1
= dirty
->y1
= MIN_DIRTY
;
677 pipe_buffer_unmap(c
->pipe
, buf_transfer
);
681 draw_layers(struct vl_compositor
*c
, struct u_rect
*dirty
)
683 unsigned vb_index
, i
;
687 for (i
= 0, vb_index
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; ++i
) {
688 if (c
->used_layers
& (1 << i
)) {
689 struct vl_compositor_layer
*layer
= &c
->layers
[i
];
690 struct pipe_sampler_view
**samplers
= &layer
->sampler_views
[0];
691 unsigned num_sampler_views
= !samplers
[1] ? 1 : !samplers
[2] ? 2 : 3;
693 c
->pipe
->bind_blend_state(c
->pipe
, layer
->blend
);
694 c
->pipe
->bind_fs_state(c
->pipe
, layer
->fs
);
695 c
->pipe
->bind_fragment_sampler_states(c
->pipe
, num_sampler_views
, layer
->samplers
);
696 c
->pipe
->set_fragment_sampler_views(c
->pipe
, num_sampler_views
, samplers
);
697 util_draw_arrays(c
->pipe
, PIPE_PRIM_QUADS
, vb_index
* 4, 4);
701 // Remember the currently drawn area as dirty for the next draw command
702 struct u_rect drawn
= calc_drawn_area(c
, layer
);
703 dirty
->x0
= MIN2(drawn
.x0
, dirty
->x0
);
704 dirty
->y0
= MIN2(drawn
.y0
, dirty
->y0
);
705 dirty
->x1
= MAX2(drawn
.x1
, dirty
->x1
);
706 dirty
->y1
= MAX2(drawn
.y1
, dirty
->y1
);
713 vl_compositor_reset_dirty_area(struct u_rect
*dirty
)
717 dirty
->x0
= dirty
->y0
= MIN_DIRTY
;
718 dirty
->x1
= dirty
->y1
= MAX_DIRTY
;
722 vl_compositor_set_clear_color(struct vl_compositor
*c
, union pipe_color_union
*color
)
726 c
->clear_color
= *color
;
730 vl_compositor_get_clear_color(struct vl_compositor
*c
, union pipe_color_union
*color
)
735 *color
= c
->clear_color
;
739 vl_compositor_clear_layers(struct vl_compositor
*c
)
746 for ( i
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; ++i
) {
747 c
->layers
[i
].clearing
= i
? false : true;
748 c
->layers
[i
].blend
= i
? c
->blend_add
: c
->blend_clear
;
749 c
->layers
[i
].fs
= NULL
;
750 for ( j
= 0; j
< 3; j
++)
751 pipe_sampler_view_reference(&c
->layers
[i
].sampler_views
[j
], NULL
);
756 vl_compositor_cleanup(struct vl_compositor
*c
)
760 vl_compositor_clear_layers(c
);
764 cleanup_pipe_state(c
);
768 vl_compositor_set_csc_matrix(struct vl_compositor
*c
, const float matrix
[16])
770 struct pipe_transfer
*buf_transfer
;
776 pipe_buffer_map(c
->pipe
, c
->csc_matrix
,
777 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD_RANGE
,
783 pipe_buffer_unmap(c
->pipe
, buf_transfer
);
787 vl_compositor_set_layer_blend(struct vl_compositor
*c
,
788 unsigned layer
, void *blend
,
793 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
795 c
->layers
[layer
].clearing
= is_clearing
;
796 c
->layers
[layer
].blend
= blend
;
800 vl_compositor_set_buffer_layer(struct vl_compositor
*c
,
802 struct pipe_video_buffer
*buffer
,
803 struct pipe_video_rect
*src_rect
,
804 struct pipe_video_rect
*dst_rect
)
806 struct pipe_sampler_view
**sampler_views
;
811 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
813 c
->used_layers
|= 1 << layer
;
814 c
->layers
[layer
].fs
= buffer
->interlaced
? c
->fs_weave
: c
->fs_video_buffer
;
816 sampler_views
= buffer
->get_sampler_view_components(buffer
);
817 for (i
= 0; i
< 3; ++i
) {
818 c
->layers
[layer
].samplers
[i
] = c
->sampler_linear
;
819 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[i
], sampler_views
[i
]);
822 calc_src_and_dst(&c
->layers
[layer
], buffer
->width
, buffer
->height
,
823 src_rect
? *src_rect
: default_rect(&c
->layers
[layer
]),
824 dst_rect
? *dst_rect
: default_rect(&c
->layers
[layer
]));
828 vl_compositor_set_palette_layer(struct vl_compositor
*c
,
830 struct pipe_sampler_view
*indexes
,
831 struct pipe_sampler_view
*palette
,
832 struct pipe_video_rect
*src_rect
,
833 struct pipe_video_rect
*dst_rect
,
834 bool include_color_conversion
)
836 assert(c
&& indexes
&& palette
);
838 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
840 c
->used_layers
|= 1 << layer
;
842 c
->layers
[layer
].fs
= include_color_conversion
?
843 c
->fs_palette
.yuv
: c
->fs_palette
.rgb
;
845 c
->layers
[layer
].samplers
[0] = c
->sampler_linear
;
846 c
->layers
[layer
].samplers
[1] = c
->sampler_nearest
;
847 c
->layers
[layer
].samplers
[2] = NULL
;
848 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[0], indexes
);
849 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[1], palette
);
850 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[2], NULL
);
851 calc_src_and_dst(&c
->layers
[layer
], indexes
->texture
->width0
, indexes
->texture
->height0
,
852 src_rect
? *src_rect
: default_rect(&c
->layers
[layer
]),
853 dst_rect
? *dst_rect
: default_rect(&c
->layers
[layer
]));
857 vl_compositor_set_rgba_layer(struct vl_compositor
*c
,
859 struct pipe_sampler_view
*rgba
,
860 struct pipe_video_rect
*src_rect
,
861 struct pipe_video_rect
*dst_rect
)
865 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
867 c
->used_layers
|= 1 << layer
;
868 c
->layers
[layer
].fs
= c
->fs_rgba
;
869 c
->layers
[layer
].samplers
[0] = c
->sampler_linear
;
870 c
->layers
[layer
].samplers
[1] = NULL
;
871 c
->layers
[layer
].samplers
[2] = NULL
;
872 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[0], rgba
);
873 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[1], NULL
);
874 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[2], NULL
);
875 calc_src_and_dst(&c
->layers
[layer
], rgba
->texture
->width0
, rgba
->texture
->height0
,
876 src_rect
? *src_rect
: default_rect(&c
->layers
[layer
]),
877 dst_rect
? *dst_rect
: default_rect(&c
->layers
[layer
]));
881 vl_compositor_render(struct vl_compositor
*c
,
882 struct pipe_surface
*dst_surface
,
883 struct pipe_video_rect
*dst_area
,
884 struct pipe_video_rect
*dst_clip
,
885 struct u_rect
*dirty_area
)
890 c
->fb_state
.width
= dst_surface
->width
;
891 c
->fb_state
.height
= dst_surface
->height
;
892 c
->fb_state
.cbufs
[0] = dst_surface
;
895 c
->viewport
.scale
[0] = dst_area
->w
;
896 c
->viewport
.scale
[1] = dst_area
->h
;
897 c
->viewport
.translate
[0] = dst_area
->x
;
898 c
->viewport
.translate
[1] = dst_area
->y
;
900 c
->viewport
.scale
[0] = dst_surface
->width
;
901 c
->viewport
.scale
[1] = dst_surface
->height
;
902 c
->viewport
.translate
[0] = 0;
903 c
->viewport
.translate
[1] = 0;
907 c
->scissor
.minx
= dst_clip
->x
;
908 c
->scissor
.miny
= dst_clip
->y
;
909 c
->scissor
.maxx
= dst_clip
->x
+ dst_clip
->w
;
910 c
->scissor
.maxy
= dst_clip
->y
+ dst_clip
->h
;
914 c
->scissor
.maxx
= dst_surface
->width
;
915 c
->scissor
.maxy
= dst_surface
->height
;
918 gen_vertex_data(c
, dirty_area
);
920 if (dirty_area
&& (dirty_area
->x0
< dirty_area
->x1
||
921 dirty_area
->y0
< dirty_area
->y1
)) {
923 c
->pipe
->clear_render_target(c
->pipe
, dst_surface
, &c
->clear_color
,
924 0, 0, dst_surface
->width
, dst_surface
->height
);
925 dirty_area
->x0
= dirty_area
->y0
= MAX_DIRTY
;
926 dirty_area
->x0
= dirty_area
->y1
= MIN_DIRTY
;
929 c
->pipe
->set_scissor_state(c
->pipe
, &c
->scissor
);
930 c
->pipe
->set_framebuffer_state(c
->pipe
, &c
->fb_state
);
931 c
->pipe
->set_viewport_state(c
->pipe
, &c
->viewport
);
932 c
->pipe
->bind_vs_state(c
->pipe
, c
->vs
);
933 c
->pipe
->set_vertex_buffers(c
->pipe
, 1, &c
->vertex_buf
);
934 c
->pipe
->bind_vertex_elements_state(c
->pipe
, c
->vertex_elems_state
);
935 c
->pipe
->set_constant_buffer(c
->pipe
, PIPE_SHADER_FRAGMENT
, 0, c
->csc_matrix
);
936 c
->pipe
->bind_rasterizer_state(c
->pipe
, c
->rast
);
938 draw_layers(c
, dirty_area
);
942 vl_compositor_init(struct vl_compositor
*c
, struct pipe_context
*pipe
)
944 csc_matrix csc_matrix
;
948 if (!init_pipe_state(c
))
951 if (!init_shaders(c
)) {
952 cleanup_pipe_state(c
);
956 if (!init_buffers(c
)) {
958 cleanup_pipe_state(c
);
962 vl_compositor_clear_layers(c
);
964 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY
, NULL
, true, csc_matrix
);
965 vl_compositor_set_csc_matrix(c
, csc_matrix
);
967 c
->clear_color
.f
[0] = c
->clear_color
.f
[1] = 0.0f
;
968 c
->clear_color
.f
[2] = c
->clear_color
.f
[3] = 0.0f
;