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)
56 create_vert_shader(struct vl_compositor
*c
)
58 struct ureg_program
*shader
;
59 struct ureg_src vpos
, vtex
, color
;
61 struct ureg_dst o_vpos
, o_vtex
, o_color
;
62 struct ureg_dst o_vtop
, o_vbottom
;
64 shader
= ureg_create(TGSI_PROCESSOR_VERTEX
);
68 vpos
= ureg_DECL_vs_input(shader
, 0);
69 vtex
= ureg_DECL_vs_input(shader
, 1);
70 color
= ureg_DECL_vs_input(shader
, 2);
71 tmp
= ureg_DECL_temporary(shader
);
72 o_vpos
= ureg_DECL_output(shader
, TGSI_SEMANTIC_POSITION
, VS_O_VPOS
);
73 o_color
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, VS_O_COLOR
);
74 o_vtex
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_VTEX
);
75 o_vtop
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_VTOP
);
76 o_vbottom
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_VBOTTOM
);
83 ureg_MOV(shader
, o_vpos
, vpos
);
84 ureg_MOV(shader
, o_vtex
, vtex
);
85 ureg_MOV(shader
, o_color
, color
);
92 * o_vtop.y = vtex.y * tmp.x + 0.25f
93 * o_vtop.z = vtex.y * tmp.y + 0.25f
94 * o_vtop.w = 1 / tmp.x
96 * o_vbottom.x = vtex.x
97 * o_vbottom.y = vtex.y * tmp.x - 0.25f
98 * o_vbottom.z = vtex.y * tmp.y - 0.25f
99 * o_vbottom.w = 1 / tmp.y
101 ureg_MUL(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_X
),
102 ureg_scalar(vtex
, TGSI_SWIZZLE_W
), ureg_imm1f(shader
, 0.5f
));
103 ureg_MUL(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
),
104 ureg_scalar(vtex
, TGSI_SWIZZLE_W
), ureg_imm1f(shader
, 0.25f
));
106 ureg_MOV(shader
, ureg_writemask(o_vtop
, TGSI_WRITEMASK_X
), vtex
);
107 ureg_MAD(shader
, ureg_writemask(o_vtop
, TGSI_WRITEMASK_Y
), ureg_scalar(vtex
, TGSI_SWIZZLE_Y
),
108 ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_X
), ureg_imm1f(shader
, 0.25f
));
109 ureg_MAD(shader
, ureg_writemask(o_vtop
, TGSI_WRITEMASK_Z
), ureg_scalar(vtex
, TGSI_SWIZZLE_Y
),
110 ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_Y
), ureg_imm1f(shader
, 0.25f
));
111 ureg_RCP(shader
, ureg_writemask(o_vtop
, TGSI_WRITEMASK_W
),
112 ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_X
));
114 ureg_MOV(shader
, ureg_writemask(o_vbottom
, TGSI_WRITEMASK_X
), vtex
);
115 ureg_MAD(shader
, ureg_writemask(o_vbottom
, TGSI_WRITEMASK_Y
), ureg_scalar(vtex
, TGSI_SWIZZLE_Y
),
116 ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_X
), ureg_imm1f(shader
, -0.25f
));
117 ureg_MAD(shader
, ureg_writemask(o_vbottom
, TGSI_WRITEMASK_Z
), ureg_scalar(vtex
, TGSI_SWIZZLE_Y
),
118 ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_Y
), ureg_imm1f(shader
, -0.25f
));
119 ureg_RCP(shader
, ureg_writemask(o_vbottom
, TGSI_WRITEMASK_W
),
120 ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_Y
));
124 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
128 create_frag_shader_video_buffer(struct vl_compositor
*c
)
130 struct ureg_program
*shader
;
132 struct ureg_src csc
[3];
133 struct ureg_src sampler
[3];
134 struct ureg_dst texel
;
135 struct ureg_dst fragment
;
138 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
142 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_VTEX
, TGSI_INTERPOLATE_LINEAR
);
143 for (i
= 0; i
< 3; ++i
) {
144 csc
[i
] = ureg_DECL_constant(shader
, i
);
145 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
147 texel
= ureg_DECL_temporary(shader
);
148 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
151 * texel.xyz = tex(tc, sampler[i])
152 * fragment = csc * texel
154 for (i
= 0; i
< 3; ++i
)
155 ureg_TEX(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_X
<< i
), TGSI_TEXTURE_3D
, tc
, sampler
[i
]);
157 ureg_MOV(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
159 for (i
= 0; i
< 3; ++i
)
160 ureg_DP4(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_X
<< i
), csc
[i
], ureg_src(texel
));
162 ureg_MOV(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
164 ureg_release_temporary(shader
, texel
);
167 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
171 create_frag_shader_weave(struct vl_compositor
*c
)
173 struct ureg_program
*shader
;
174 struct ureg_src i_tc
[2];
175 struct ureg_src csc
[3];
176 struct ureg_src sampler
[3];
177 struct ureg_dst t_tc
[2];
178 struct ureg_dst t_texel
[2];
179 struct ureg_dst o_fragment
;
182 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
186 i_tc
[0] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_VTOP
, TGSI_INTERPOLATE_LINEAR
);
187 i_tc
[1] = ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_VBOTTOM
, TGSI_INTERPOLATE_LINEAR
);
189 for (i
= 0; i
< 3; ++i
) {
190 csc
[i
] = ureg_DECL_constant(shader
, i
);
191 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
194 for (i
= 0; i
< 2; ++i
) {
195 t_tc
[i
] = ureg_DECL_temporary(shader
);
196 t_texel
[i
] = ureg_DECL_temporary(shader
);
198 o_fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
200 /* calculate the texture offsets
202 * t_tc.y = (round(i_tc.y) + 0.5) / height * 2
204 for (i
= 0; i
< 2; ++i
) {
205 ureg_MOV(shader
, ureg_writemask(t_tc
[i
], TGSI_WRITEMASK_X
), i_tc
[i
]);
206 ureg_ROUND(shader
, ureg_writemask(t_tc
[i
], TGSI_WRITEMASK_YZ
), i_tc
[i
]);
207 ureg_MOV(shader
, ureg_writemask(t_tc
[i
], TGSI_WRITEMASK_W
),
208 ureg_imm1f(shader
, i
? 0.75f
: 0.25f
));
209 ureg_ADD(shader
, ureg_writemask(t_tc
[i
], TGSI_WRITEMASK_YZ
),
210 ureg_src(t_tc
[i
]), ureg_imm1f(shader
, 0.5f
));
211 ureg_MUL(shader
, ureg_writemask(t_tc
[i
], TGSI_WRITEMASK_Y
),
212 ureg_src(t_tc
[i
]), ureg_scalar(i_tc
[0], TGSI_SWIZZLE_W
));
213 ureg_MUL(shader
, ureg_writemask(t_tc
[i
], TGSI_WRITEMASK_Z
),
214 ureg_src(t_tc
[i
]), ureg_scalar(i_tc
[1], TGSI_SWIZZLE_W
));
218 * texel[0..1].x = tex(t_tc[0..1][0])
219 * texel[0..1].y = tex(t_tc[0..1][1])
220 * texel[0..1].z = tex(t_tc[0..1][2])
222 for (i
= 0; i
< 2; ++i
)
223 for (j
= 0; j
< 3; ++j
) {
224 struct ureg_src src
= ureg_swizzle(ureg_src(t_tc
[i
]),
225 TGSI_SWIZZLE_X
, j
? TGSI_SWIZZLE_Z
: TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_W
, TGSI_SWIZZLE_W
);
227 ureg_TEX(shader
, ureg_writemask(t_texel
[i
], TGSI_WRITEMASK_X
<< j
),
228 TGSI_TEXTURE_3D
, src
, sampler
[j
]);
231 /* calculate linear interpolation factor
232 * factor = |round(i_tc.y) - i_tc.y| * 2
234 ureg_ROUND(shader
, ureg_writemask(t_tc
[0], TGSI_WRITEMASK_YZ
), i_tc
[0]);
235 ureg_ADD(shader
, ureg_writemask(t_tc
[0], TGSI_WRITEMASK_YZ
),
236 ureg_src(t_tc
[0]), ureg_negate(i_tc
[0]));
237 ureg_MUL(shader
, ureg_writemask(t_tc
[0], TGSI_WRITEMASK_XY
),
238 ureg_abs(ureg_src(t_tc
[0])), ureg_imm1f(shader
, 2.0f
));
239 ureg_LRP(shader
, t_texel
[0], ureg_swizzle(ureg_src(t_tc
[0]),
240 TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_Z
, TGSI_SWIZZLE_Z
, TGSI_SWIZZLE_Z
),
241 ureg_src(t_texel
[1]), ureg_src(t_texel
[0]));
243 /* and finally do colour space transformation
244 * fragment = csc * texel
246 ureg_MOV(shader
, ureg_writemask(t_texel
[0], TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
247 for (i
= 0; i
< 3; ++i
)
248 ureg_DP4(shader
, ureg_writemask(o_fragment
, TGSI_WRITEMASK_X
<< i
), csc
[i
], ureg_src(t_texel
[0]));
250 ureg_MOV(shader
, ureg_writemask(o_fragment
, TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
252 for (i
= 0; i
< 2; ++i
) {
253 ureg_release_temporary(shader
, t_texel
[i
]);
254 ureg_release_temporary(shader
, t_tc
[i
]);
259 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
263 create_frag_shader_palette(struct vl_compositor
*c
, bool include_cc
)
265 struct ureg_program
*shader
;
266 struct ureg_src csc
[3];
268 struct ureg_src sampler
;
269 struct ureg_src palette
;
270 struct ureg_dst texel
;
271 struct ureg_dst fragment
;
274 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
278 for (i
= 0; include_cc
&& i
< 3; ++i
)
279 csc
[i
] = ureg_DECL_constant(shader
, i
);
281 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_VTEX
, TGSI_INTERPOLATE_LINEAR
);
282 sampler
= ureg_DECL_sampler(shader
, 0);
283 palette
= ureg_DECL_sampler(shader
, 1);
285 texel
= ureg_DECL_temporary(shader
);
286 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
289 * texel = tex(tc, sampler)
290 * fragment.xyz = tex(texel, palette) * csc
291 * fragment.a = texel.a
293 ureg_TEX(shader
, texel
, TGSI_TEXTURE_2D
, tc
, sampler
);
294 ureg_MOV(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_W
), ureg_src(texel
));
297 ureg_TEX(shader
, texel
, TGSI_TEXTURE_1D
, ureg_src(texel
), palette
);
298 for (i
= 0; i
< 3; ++i
)
299 ureg_DP4(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_X
<< i
), csc
[i
], ureg_src(texel
));
301 ureg_TEX(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_XYZ
),
302 TGSI_TEXTURE_1D
, ureg_src(texel
), palette
);
305 ureg_release_temporary(shader
, texel
);
308 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
312 create_frag_shader_rgba(struct vl_compositor
*c
)
314 struct ureg_program
*shader
;
315 struct ureg_src tc
, color
, sampler
;
316 struct ureg_dst texel
, fragment
;
318 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
322 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, VS_O_VTEX
, TGSI_INTERPOLATE_LINEAR
);
323 color
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_COLOR
, VS_O_COLOR
, TGSI_INTERPOLATE_LINEAR
);
324 sampler
= ureg_DECL_sampler(shader
, 0);
325 texel
= ureg_DECL_temporary(shader
);
326 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
329 * fragment = tex(tc, sampler)
331 ureg_TEX(shader
, texel
, TGSI_TEXTURE_2D
, tc
, sampler
);
332 ureg_MUL(shader
, fragment
, ureg_src(texel
), color
);
335 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
339 init_shaders(struct vl_compositor
*c
)
343 c
->vs
= create_vert_shader(c
);
345 debug_printf("Unable to create vertex shader.\n");
349 c
->fs_video_buffer
= create_frag_shader_video_buffer(c
);
350 if (!c
->fs_video_buffer
) {
351 debug_printf("Unable to create YCbCr-to-RGB fragment shader.\n");
355 c
->fs_weave
= create_frag_shader_weave(c
);
357 debug_printf("Unable to create YCbCr-to-RGB weave fragment shader.\n");
361 c
->fs_palette
.yuv
= create_frag_shader_palette(c
, true);
362 if (!c
->fs_palette
.yuv
) {
363 debug_printf("Unable to create YUV-Palette-to-RGB fragment shader.\n");
367 c
->fs_palette
.rgb
= create_frag_shader_palette(c
, false);
368 if (!c
->fs_palette
.rgb
) {
369 debug_printf("Unable to create RGB-Palette-to-RGB fragment shader.\n");
373 c
->fs_rgba
= create_frag_shader_rgba(c
);
375 debug_printf("Unable to create RGB-to-RGB fragment shader.\n");
382 static void cleanup_shaders(struct vl_compositor
*c
)
386 c
->pipe
->delete_vs_state(c
->pipe
, c
->vs
);
387 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_video_buffer
);
388 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_weave
);
389 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_palette
.yuv
);
390 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_palette
.rgb
);
391 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_rgba
);
395 init_pipe_state(struct vl_compositor
*c
)
397 struct pipe_rasterizer_state rast
;
398 struct pipe_sampler_state sampler
;
399 struct pipe_blend_state blend
;
400 struct pipe_depth_stencil_alpha_state dsa
;
405 c
->fb_state
.nr_cbufs
= 1;
406 c
->fb_state
.zsbuf
= NULL
;
408 memset(&sampler
, 0, sizeof(sampler
));
409 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
410 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
411 sampler
.wrap_r
= PIPE_TEX_WRAP_REPEAT
;
412 sampler
.min_img_filter
= PIPE_TEX_FILTER_LINEAR
;
413 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
414 sampler
.mag_img_filter
= PIPE_TEX_FILTER_LINEAR
;
415 sampler
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
416 sampler
.compare_func
= PIPE_FUNC_ALWAYS
;
417 sampler
.normalized_coords
= 1;
419 c
->sampler_linear
= c
->pipe
->create_sampler_state(c
->pipe
, &sampler
);
421 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
422 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
423 c
->sampler_nearest
= c
->pipe
->create_sampler_state(c
->pipe
, &sampler
);
425 memset(&blend
, 0, sizeof blend
);
426 blend
.independent_blend_enable
= 0;
427 blend
.rt
[0].blend_enable
= 0;
428 blend
.logicop_enable
= 0;
429 blend
.logicop_func
= PIPE_LOGICOP_CLEAR
;
430 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
432 c
->blend_clear
= c
->pipe
->create_blend_state(c
->pipe
, &blend
);
434 blend
.rt
[0].blend_enable
= 1;
435 blend
.rt
[0].rgb_func
= PIPE_BLEND_ADD
;
436 blend
.rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_SRC_ALPHA
;
437 blend
.rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_INV_SRC_ALPHA
;
438 blend
.rt
[0].alpha_func
= PIPE_BLEND_ADD
;
439 blend
.rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
440 blend
.rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ONE
;
441 c
->blend_add
= c
->pipe
->create_blend_state(c
->pipe
, &blend
);
443 memset(&rast
, 0, sizeof rast
);
446 rast
.cull_face
= PIPE_FACE_NONE
;
447 rast
.fill_back
= PIPE_POLYGON_MODE_FILL
;
448 rast
.fill_front
= PIPE_POLYGON_MODE_FILL
;
451 rast
.point_size_per_vertex
= 1;
452 rast
.offset_units
= 1;
453 rast
.offset_scale
= 1;
454 rast
.gl_rasterization_rules
= 1;
457 c
->rast
= c
->pipe
->create_rasterizer_state(c
->pipe
, &rast
);
459 memset(&dsa
, 0, sizeof dsa
);
460 dsa
.depth
.enabled
= 0;
461 dsa
.depth
.writemask
= 0;
462 dsa
.depth
.func
= PIPE_FUNC_ALWAYS
;
463 for (i
= 0; i
< 2; ++i
) {
464 dsa
.stencil
[i
].enabled
= 0;
465 dsa
.stencil
[i
].func
= PIPE_FUNC_ALWAYS
;
466 dsa
.stencil
[i
].fail_op
= PIPE_STENCIL_OP_KEEP
;
467 dsa
.stencil
[i
].zpass_op
= PIPE_STENCIL_OP_KEEP
;
468 dsa
.stencil
[i
].zfail_op
= PIPE_STENCIL_OP_KEEP
;
469 dsa
.stencil
[i
].valuemask
= 0;
470 dsa
.stencil
[i
].writemask
= 0;
472 dsa
.alpha
.enabled
= 0;
473 dsa
.alpha
.func
= PIPE_FUNC_ALWAYS
;
474 dsa
.alpha
.ref_value
= 0;
475 c
->dsa
= c
->pipe
->create_depth_stencil_alpha_state(c
->pipe
, &dsa
);
476 c
->pipe
->bind_depth_stencil_alpha_state(c
->pipe
, c
->dsa
);
481 static void cleanup_pipe_state(struct vl_compositor
*c
)
485 /* Asserted in softpipe_delete_fs_state() for some reason */
486 c
->pipe
->bind_vs_state(c
->pipe
, NULL
);
487 c
->pipe
->bind_fs_state(c
->pipe
, NULL
);
489 c
->pipe
->delete_depth_stencil_alpha_state(c
->pipe
, c
->dsa
);
490 c
->pipe
->delete_sampler_state(c
->pipe
, c
->sampler_linear
);
491 c
->pipe
->delete_sampler_state(c
->pipe
, c
->sampler_nearest
);
492 c
->pipe
->delete_blend_state(c
->pipe
, c
->blend_clear
);
493 c
->pipe
->delete_blend_state(c
->pipe
, c
->blend_add
);
494 c
->pipe
->delete_rasterizer_state(c
->pipe
, c
->rast
);
498 create_vertex_buffer(struct vl_compositor
*c
)
502 pipe_resource_reference(&c
->vertex_buf
.buffer
, NULL
);
503 c
->vertex_buf
.buffer
= pipe_buffer_create
506 PIPE_BIND_VERTEX_BUFFER
,
508 c
->vertex_buf
.stride
* VL_COMPOSITOR_MAX_LAYERS
* 4
511 return c
->vertex_buf
.buffer
!= NULL
;
515 init_buffers(struct vl_compositor
*c
)
517 struct pipe_vertex_element vertex_elems
[3];
522 * Create our vertex buffer and vertex buffer elements
524 c
->vertex_buf
.stride
= sizeof(struct vertex2f
) + sizeof(struct vertex4f
) * 2;
525 c
->vertex_buf
.buffer_offset
= 0;
526 create_vertex_buffer(c
);
528 vertex_elems
[0].src_offset
= 0;
529 vertex_elems
[0].instance_divisor
= 0;
530 vertex_elems
[0].vertex_buffer_index
= 0;
531 vertex_elems
[0].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
532 vertex_elems
[1].src_offset
= sizeof(struct vertex2f
);
533 vertex_elems
[1].instance_divisor
= 0;
534 vertex_elems
[1].vertex_buffer_index
= 0;
535 vertex_elems
[1].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
536 vertex_elems
[2].src_offset
= sizeof(struct vertex2f
) + sizeof(struct vertex4f
);
537 vertex_elems
[2].instance_divisor
= 0;
538 vertex_elems
[2].vertex_buffer_index
= 0;
539 vertex_elems
[2].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
540 c
->vertex_elems_state
= c
->pipe
->create_vertex_elements_state(c
->pipe
, 3, vertex_elems
);
546 cleanup_buffers(struct vl_compositor
*c
)
550 c
->pipe
->delete_vertex_elements_state(c
->pipe
, c
->vertex_elems_state
);
551 pipe_resource_reference(&c
->vertex_buf
.buffer
, NULL
);
554 static INLINE
struct u_rect
555 default_rect(struct vl_compositor_layer
*layer
)
557 struct pipe_resource
*res
= layer
->sampler_views
[0]->texture
;
558 struct u_rect rect
= { 0, res
->width0
, 0, res
->height0
* res
->depth0
};
562 static INLINE
struct vertex2f
563 calc_topleft(struct vertex2f size
, struct u_rect rect
)
565 struct vertex2f res
= { rect
.x0
/ size
.x
, rect
.y0
/ size
.y
};
569 static INLINE
struct vertex2f
570 calc_bottomright(struct vertex2f size
, struct u_rect rect
)
572 struct vertex2f res
= { rect
.x1
/ size
.x
, rect
.y1
/ size
.y
};
577 calc_src_and_dst(struct vl_compositor_layer
*layer
, unsigned width
, unsigned height
,
578 struct u_rect src
, struct u_rect dst
)
580 struct vertex2f size
= { width
, height
};
582 layer
->src
.tl
= calc_topleft(size
, src
);
583 layer
->src
.br
= calc_bottomright(size
, src
);
584 layer
->dst
.tl
= calc_topleft(size
, dst
);
585 layer
->dst
.br
= calc_bottomright(size
, dst
);
587 layer
->zw
.y
= size
.y
;
591 gen_rect_verts(struct vertex2f
*vb
, struct vl_compositor_layer
*layer
)
595 vb
[ 0].x
= layer
->dst
.tl
.x
;
596 vb
[ 0].y
= layer
->dst
.tl
.y
;
597 vb
[ 1].x
= layer
->src
.tl
.x
;
598 vb
[ 1].y
= layer
->src
.tl
.y
;
600 vb
[ 3].x
= layer
->colors
[0].x
;
601 vb
[ 3].y
= layer
->colors
[0].y
;
602 vb
[ 4].x
= layer
->colors
[0].z
;
603 vb
[ 4].y
= layer
->colors
[0].w
;
605 vb
[ 5].x
= layer
->dst
.br
.x
;
606 vb
[ 5].y
= layer
->dst
.tl
.y
;
607 vb
[ 6].x
= layer
->src
.br
.x
;
608 vb
[ 6].y
= layer
->src
.tl
.y
;
610 vb
[ 8].x
= layer
->colors
[1].x
;
611 vb
[ 8].y
= layer
->colors
[1].y
;
612 vb
[ 9].x
= layer
->colors
[1].z
;
613 vb
[ 9].y
= layer
->colors
[1].w
;
615 vb
[10].x
= layer
->dst
.br
.x
;
616 vb
[10].y
= layer
->dst
.br
.y
;
617 vb
[11].x
= layer
->src
.br
.x
;
618 vb
[11].y
= layer
->src
.br
.y
;
620 vb
[13].x
= layer
->colors
[2].x
;
621 vb
[13].y
= layer
->colors
[2].y
;
622 vb
[14].x
= layer
->colors
[2].z
;
623 vb
[14].y
= layer
->colors
[2].w
;
625 vb
[15].x
= layer
->dst
.tl
.x
;
626 vb
[15].y
= layer
->dst
.br
.y
;
627 vb
[16].x
= layer
->src
.tl
.x
;
628 vb
[16].y
= layer
->src
.br
.y
;
630 vb
[18].x
= layer
->colors
[3].x
;
631 vb
[18].y
= layer
->colors
[3].y
;
632 vb
[19].x
= layer
->colors
[3].z
;
633 vb
[19].y
= layer
->colors
[3].w
;
636 static INLINE
struct u_rect
637 calc_drawn_area(struct vl_compositor_state
*s
, struct vl_compositor_layer
*layer
)
639 struct u_rect result
;
642 result
.x0
= layer
->dst
.tl
.x
* layer
->viewport
.scale
[0] + layer
->viewport
.translate
[0];
643 result
.y0
= layer
->dst
.tl
.y
* layer
->viewport
.scale
[1] + layer
->viewport
.translate
[1];
644 result
.x1
= layer
->dst
.br
.x
* layer
->viewport
.scale
[0] + layer
->viewport
.translate
[0];
645 result
.y1
= layer
->dst
.br
.y
* layer
->viewport
.scale
[1] + layer
->viewport
.translate
[1];
648 result
.x0
= MAX2(result
.x0
, s
->scissor
.minx
);
649 result
.y0
= MAX2(result
.y0
, s
->scissor
.miny
);
650 result
.x1
= MIN2(result
.x1
, s
->scissor
.maxx
);
651 result
.y1
= MIN2(result
.y1
, s
->scissor
.maxy
);
656 gen_vertex_data(struct vl_compositor
*c
, struct vl_compositor_state
*s
, struct u_rect
*dirty
)
659 struct pipe_transfer
*buf_transfer
;
664 vb
= pipe_buffer_map(c
->pipe
, c
->vertex_buf
.buffer
,
665 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD_RANGE
| PIPE_TRANSFER_DONTBLOCK
,
669 // If buffer is still locked from last draw create a new one
670 create_vertex_buffer(c
);
671 vb
= pipe_buffer_map(c
->pipe
, c
->vertex_buf
.buffer
,
672 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD_RANGE
,
676 for (i
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; i
++) {
677 if (s
->used_layers
& (1 << i
)) {
678 struct vl_compositor_layer
*layer
= &s
->layers
[i
];
679 gen_rect_verts(vb
, layer
);
682 if (!layer
->viewport_valid
) {
683 layer
->viewport
.scale
[0] = c
->fb_state
.width
;
684 layer
->viewport
.scale
[1] = c
->fb_state
.height
;
685 layer
->viewport
.translate
[0] = 0;
686 layer
->viewport
.translate
[1] = 0;
689 if (dirty
&& layer
->clearing
) {
690 struct u_rect drawn
= calc_drawn_area(s
, layer
);
692 dirty
->x0
>= drawn
.x0
&&
693 dirty
->y0
>= drawn
.y0
&&
694 dirty
->x1
<= drawn
.x1
&&
695 dirty
->y1
<= drawn
.y1
) {
697 // We clear the dirty area anyway, no need for clear_render_target
698 dirty
->x0
= dirty
->y0
= MAX_DIRTY
;
699 dirty
->x1
= dirty
->y1
= MIN_DIRTY
;
705 pipe_buffer_unmap(c
->pipe
, buf_transfer
);
709 draw_layers(struct vl_compositor
*c
, struct vl_compositor_state
*s
, struct u_rect
*dirty
)
711 unsigned vb_index
, i
;
715 for (i
= 0, vb_index
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; ++i
) {
716 if (s
->used_layers
& (1 << i
)) {
717 struct vl_compositor_layer
*layer
= &s
->layers
[i
];
718 struct pipe_sampler_view
**samplers
= &layer
->sampler_views
[0];
719 unsigned num_sampler_views
= !samplers
[1] ? 1 : !samplers
[2] ? 2 : 3;
720 void *blend
= layer
->blend
? layer
->blend
: i
? c
->blend_add
: c
->blend_clear
;
722 c
->pipe
->bind_blend_state(c
->pipe
, blend
);
723 c
->pipe
->set_viewport_state(c
->pipe
, &layer
->viewport
);
724 c
->pipe
->bind_fs_state(c
->pipe
, layer
->fs
);
725 c
->pipe
->bind_fragment_sampler_states(c
->pipe
, num_sampler_views
, layer
->samplers
);
726 c
->pipe
->set_fragment_sampler_views(c
->pipe
, num_sampler_views
, samplers
);
727 util_draw_arrays(c
->pipe
, PIPE_PRIM_QUADS
, vb_index
* 4, 4);
731 // Remember the currently drawn area as dirty for the next draw command
732 struct u_rect drawn
= calc_drawn_area(s
, layer
);
733 dirty
->x0
= MIN2(drawn
.x0
, dirty
->x0
);
734 dirty
->y0
= MIN2(drawn
.y0
, dirty
->y0
);
735 dirty
->x1
= MAX2(drawn
.x1
, dirty
->x1
);
736 dirty
->y1
= MAX2(drawn
.y1
, dirty
->y1
);
743 vl_compositor_reset_dirty_area(struct u_rect
*dirty
)
747 dirty
->x0
= dirty
->y0
= MIN_DIRTY
;
748 dirty
->x1
= dirty
->y1
= MAX_DIRTY
;
752 vl_compositor_set_clear_color(struct vl_compositor_state
*s
, union pipe_color_union
*color
)
757 s
->clear_color
= *color
;
761 vl_compositor_get_clear_color(struct vl_compositor_state
*s
, union pipe_color_union
*color
)
766 *color
= s
->clear_color
;
770 vl_compositor_clear_layers(struct vl_compositor_state
*s
)
777 for ( i
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; ++i
) {
778 struct vertex4f v_one
= { 1.0f
, 1.0f
, 1.0f
, 1.0f
};
779 s
->layers
[i
].clearing
= i
? false : true;
780 s
->layers
[i
].blend
= NULL
;
781 s
->layers
[i
].fs
= NULL
;
782 s
->layers
[i
].viewport
.scale
[2] = 1;
783 s
->layers
[i
].viewport
.scale
[3] = 1;
784 s
->layers
[i
].viewport
.translate
[2] = 0;
785 s
->layers
[i
].viewport
.translate
[3] = 0;
787 for ( j
= 0; j
< 3; j
++)
788 pipe_sampler_view_reference(&s
->layers
[i
].sampler_views
[j
], NULL
);
789 for ( j
= 0; j
< 4; ++j
)
790 s
->layers
[i
].colors
[j
] = v_one
;
795 vl_compositor_cleanup(struct vl_compositor
*c
)
801 cleanup_pipe_state(c
);
805 vl_compositor_set_csc_matrix(struct vl_compositor_state
*s
, vl_csc_matrix
const *matrix
)
807 struct pipe_transfer
*buf_transfer
;
813 pipe_buffer_map(s
->pipe
, s
->csc_matrix
,
814 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD_RANGE
,
817 sizeof(vl_csc_matrix
)
820 pipe_buffer_unmap(s
->pipe
, buf_transfer
);
824 vl_compositor_set_dst_clip(struct vl_compositor_state
*s
, struct u_rect
*dst_clip
)
828 s
->scissor_valid
= dst_clip
!= NULL
;
830 s
->scissor
.minx
= dst_clip
->x0
;
831 s
->scissor
.miny
= dst_clip
->y0
;
832 s
->scissor
.maxx
= dst_clip
->x1
;
833 s
->scissor
.maxy
= dst_clip
->y1
;
838 vl_compositor_set_layer_blend(struct vl_compositor_state
*s
,
839 unsigned layer
, void *blend
,
844 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
846 s
->layers
[layer
].clearing
= is_clearing
;
847 s
->layers
[layer
].blend
= blend
;
851 vl_compositor_set_layer_dst_area(struct vl_compositor_state
*s
,
852 unsigned layer
, struct u_rect
*dst_area
)
856 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
858 s
->layers
[layer
].viewport_valid
= dst_area
!= NULL
;
860 s
->layers
[layer
].viewport
.scale
[0] = dst_area
->x1
- dst_area
->x0
;
861 s
->layers
[layer
].viewport
.scale
[1] = dst_area
->y1
- dst_area
->y0
;
862 s
->layers
[layer
].viewport
.translate
[0] = dst_area
->x0
;
863 s
->layers
[layer
].viewport
.translate
[1] = dst_area
->y0
;
868 vl_compositor_set_buffer_layer(struct vl_compositor_state
*s
,
869 struct vl_compositor
*c
,
871 struct pipe_video_buffer
*buffer
,
872 struct u_rect
*src_rect
,
873 struct u_rect
*dst_rect
,
874 enum vl_compositor_deinterlace deinterlace
)
876 struct pipe_sampler_view
**sampler_views
;
879 assert(s
&& c
&& buffer
);
881 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
883 s
->used_layers
|= 1 << layer
;
884 sampler_views
= buffer
->get_sampler_view_components(buffer
);
885 for (i
= 0; i
< 3; ++i
) {
886 s
->layers
[layer
].samplers
[i
] = c
->sampler_linear
;
887 pipe_sampler_view_reference(&s
->layers
[layer
].sampler_views
[i
], sampler_views
[i
]);
890 calc_src_and_dst(&s
->layers
[layer
], buffer
->width
, buffer
->height
,
891 src_rect
? *src_rect
: default_rect(&s
->layers
[layer
]),
892 dst_rect
? *dst_rect
: default_rect(&s
->layers
[layer
]));
894 if (buffer
->interlaced
) {
895 float half_a_line
= 0.5f
/ s
->layers
[layer
].zw
.y
;
896 switch(deinterlace
) {
897 case VL_COMPOSITOR_WEAVE
:
898 s
->layers
[layer
].fs
= c
->fs_weave
;
901 case VL_COMPOSITOR_BOB_TOP
:
902 s
->layers
[layer
].zw
.x
= 0.25f
;
903 s
->layers
[layer
].src
.tl
.y
+= half_a_line
;
904 s
->layers
[layer
].src
.br
.y
+= half_a_line
;
905 s
->layers
[layer
].fs
= c
->fs_video_buffer
;
908 case VL_COMPOSITOR_BOB_BOTTOM
:
909 s
->layers
[layer
].zw
.x
= 0.75f
;
910 s
->layers
[layer
].src
.tl
.y
-= half_a_line
;
911 s
->layers
[layer
].src
.br
.y
-= half_a_line
;
912 s
->layers
[layer
].fs
= c
->fs_video_buffer
;
917 s
->layers
[layer
].fs
= c
->fs_video_buffer
;
921 vl_compositor_set_palette_layer(struct vl_compositor_state
*s
,
922 struct vl_compositor
*c
,
924 struct pipe_sampler_view
*indexes
,
925 struct pipe_sampler_view
*palette
,
926 struct u_rect
*src_rect
,
927 struct u_rect
*dst_rect
,
928 bool include_color_conversion
)
930 assert(s
&& c
&& indexes
&& palette
);
932 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
934 s
->used_layers
|= 1 << layer
;
936 s
->layers
[layer
].fs
= include_color_conversion
?
937 c
->fs_palette
.yuv
: c
->fs_palette
.rgb
;
939 s
->layers
[layer
].samplers
[0] = c
->sampler_linear
;
940 s
->layers
[layer
].samplers
[1] = c
->sampler_nearest
;
941 s
->layers
[layer
].samplers
[2] = NULL
;
942 pipe_sampler_view_reference(&s
->layers
[layer
].sampler_views
[0], indexes
);
943 pipe_sampler_view_reference(&s
->layers
[layer
].sampler_views
[1], palette
);
944 pipe_sampler_view_reference(&s
->layers
[layer
].sampler_views
[2], NULL
);
945 calc_src_and_dst(&s
->layers
[layer
], indexes
->texture
->width0
, indexes
->texture
->height0
,
946 src_rect
? *src_rect
: default_rect(&s
->layers
[layer
]),
947 dst_rect
? *dst_rect
: default_rect(&s
->layers
[layer
]));
951 vl_compositor_set_rgba_layer(struct vl_compositor_state
*s
,
952 struct vl_compositor
*c
,
954 struct pipe_sampler_view
*rgba
,
955 struct u_rect
*src_rect
,
956 struct u_rect
*dst_rect
,
957 struct vertex4f
*colors
)
961 assert(s
&& c
&& rgba
);
963 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
965 s
->used_layers
|= 1 << layer
;
966 s
->layers
[layer
].fs
= c
->fs_rgba
;
967 s
->layers
[layer
].samplers
[0] = c
->sampler_linear
;
968 s
->layers
[layer
].samplers
[1] = NULL
;
969 s
->layers
[layer
].samplers
[2] = NULL
;
970 pipe_sampler_view_reference(&s
->layers
[layer
].sampler_views
[0], rgba
);
971 pipe_sampler_view_reference(&s
->layers
[layer
].sampler_views
[1], NULL
);
972 pipe_sampler_view_reference(&s
->layers
[layer
].sampler_views
[2], NULL
);
973 calc_src_and_dst(&s
->layers
[layer
], rgba
->texture
->width0
, rgba
->texture
->height0
,
974 src_rect
? *src_rect
: default_rect(&s
->layers
[layer
]),
975 dst_rect
? *dst_rect
: default_rect(&s
->layers
[layer
]));
978 for (i
= 0; i
< 4; ++i
)
979 s
->layers
[layer
].colors
[i
] = colors
[i
];
983 vl_compositor_render(struct vl_compositor_state
*s
,
984 struct vl_compositor
*c
,
985 struct pipe_surface
*dst_surface
,
986 struct u_rect
*dirty_area
)
991 c
->fb_state
.width
= dst_surface
->width
;
992 c
->fb_state
.height
= dst_surface
->height
;
993 c
->fb_state
.cbufs
[0] = dst_surface
;
995 if (!s
->scissor_valid
) {
998 s
->scissor
.maxx
= dst_surface
->width
;
999 s
->scissor
.maxy
= dst_surface
->height
;
1002 gen_vertex_data(c
, s
, dirty_area
);
1004 if (dirty_area
&& (dirty_area
->x0
< dirty_area
->x1
||
1005 dirty_area
->y0
< dirty_area
->y1
)) {
1007 c
->pipe
->clear_render_target(c
->pipe
, dst_surface
, &s
->clear_color
,
1008 0, 0, dst_surface
->width
, dst_surface
->height
);
1009 dirty_area
->x0
= dirty_area
->y0
= MAX_DIRTY
;
1010 dirty_area
->x1
= dirty_area
->y1
= MIN_DIRTY
;
1013 c
->pipe
->set_scissor_state(c
->pipe
, &s
->scissor
);
1014 c
->pipe
->set_framebuffer_state(c
->pipe
, &c
->fb_state
);
1015 c
->pipe
->bind_vs_state(c
->pipe
, c
->vs
);
1016 c
->pipe
->set_vertex_buffers(c
->pipe
, 1, &c
->vertex_buf
);
1017 c
->pipe
->bind_vertex_elements_state(c
->pipe
, c
->vertex_elems_state
);
1018 pipe_set_constant_buffer(c
->pipe
, PIPE_SHADER_FRAGMENT
, 0, s
->csc_matrix
);
1019 c
->pipe
->bind_rasterizer_state(c
->pipe
, c
->rast
);
1021 draw_layers(c
, s
, dirty_area
);
1025 vl_compositor_init(struct vl_compositor
*c
, struct pipe_context
*pipe
)
1029 memset(c
, 0, sizeof(*c
));
1033 if (!init_pipe_state(c
))
1036 if (!init_shaders(c
)) {
1037 cleanup_pipe_state(c
);
1041 if (!init_buffers(c
)) {
1043 cleanup_pipe_state(c
);
1051 vl_compositor_init_state(struct vl_compositor_state
*s
, struct pipe_context
*pipe
)
1053 vl_csc_matrix csc_matrix
;
1057 memset(s
, 0, sizeof(*s
));
1061 s
->clear_color
.f
[0] = s
->clear_color
.f
[1] = 0.0f
;
1062 s
->clear_color
.f
[2] = s
->clear_color
.f
[3] = 0.0f
;
1065 * Create our fragment shader's constant buffer
1066 * Const buffer contains the color conversion matrix and bias vectors
1068 /* XXX: Create with IMMUTABLE/STATIC... although it does change every once in a long while... */
1069 s
->csc_matrix
= pipe_buffer_create
1072 PIPE_BIND_CONSTANT_BUFFER
,
1077 vl_compositor_clear_layers(s
);
1079 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY
, NULL
, true, &csc_matrix
);
1080 vl_compositor_set_csc_matrix(s
, (const vl_csc_matrix
*)&csc_matrix
);
1086 vl_compositor_cleanup_state(struct vl_compositor_state
*s
)
1090 vl_compositor_clear_layers(s
);
1091 pipe_resource_reference(&s
->csc_matrix
, NULL
);