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"
36 #include "util/u_sampler.h"
38 #include "tgsi/tgsi_ureg.h"
42 #include "vl_compositor.h"
44 typedef float csc_matrix
[16];
46 /* Set to 1 to run a contour shader */
47 #define DEBUG_CONTOUR 0
50 create_vert_shader(struct vl_compositor
*c
)
52 struct ureg_program
*shader
;
53 struct ureg_src vpos
, vtex
;
54 struct ureg_dst o_vpos
, o_vtex
;
56 shader
= ureg_create(TGSI_PROCESSOR_VERTEX
);
60 vpos
= ureg_DECL_vs_input(shader
, 0);
61 vtex
= ureg_DECL_vs_input(shader
, 1);
62 o_vpos
= ureg_DECL_output(shader
, TGSI_SEMANTIC_POSITION
, 0);
63 o_vtex
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, 1);
69 ureg_MOV(shader
, o_vpos
, vpos
);
70 ureg_MOV(shader
, o_vtex
, vtex
);
74 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
78 create_frag_shader_video_buffer(struct vl_compositor
*c
, unsigned planes
)
80 struct ureg_program
*shader
;
82 struct ureg_src csc
[3];
83 struct ureg_src sampler
[3];
84 struct ureg_dst texel
;
85 struct ureg_dst fragment
;
88 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
92 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
93 for (i
= 0; i
< 3; ++i
) {
94 csc
[i
] = ureg_DECL_constant(shader
, i
);
96 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
98 texel
= ureg_DECL_temporary(shader
);
99 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
102 * texel.xyz = tex(tc, sampler[i])
103 * fragment = csc * texel
106 ureg_TEX(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_X
), TGSI_TEXTURE_2D
, tc
, sampler
[0]);
107 ureg_TEX(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_YZ
), TGSI_TEXTURE_2D
, tc
, sampler
[1]);
109 for (i
= 0; i
< 3; ++i
)
110 ureg_TEX(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_X
<< i
), TGSI_TEXTURE_2D
, tc
, sampler
[i
]);
113 ureg_MOV(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
115 for (i
= 0; i
< 3; ++i
)
116 ureg_DP4(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_X
<< i
), csc
[i
], ureg_src(texel
));
118 ureg_MOV(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
120 ureg_release_temporary(shader
, texel
);
123 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
126 static struct ureg_dst
127 calc_line(struct ureg_program
*shader
, unsigned nearest
)
132 tmp
= ureg_DECL_temporary(shader
);
134 pos
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_POSITION
, 0, TGSI_INTERPOLATE_LINEAR
);
137 * tmp.y = fraction(pos.y * .5) >= 0.5 ? 1 : 0
138 * however, for linear interpolation (chroma deinterlace) 2 pixels are required..
141 ureg_MUL(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
), pos
, ureg_imm1f(shader
, 0.5f
));
143 ureg_MUL(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
), pos
, ureg_imm1f(shader
, 0.25f
));
144 ureg_FRC(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
), ureg_src(tmp
));
145 ureg_SGE(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
), ureg_src(tmp
), ureg_imm1f(shader
, 0.5f
));
150 /* Deinterlace or weave NV12 or YV12 to a temporary video buffer
154 create_frag_shader_weave(struct vl_compositor
*c
, unsigned luma
, unsigned interlaced
, unsigned comps
)
156 struct ureg_program
*shader
;
157 struct ureg_src tc
, sampler
[4];
158 struct ureg_dst field
, fragment
, swizcolor
;
159 unsigned label
, writemask
, nearest
;
161 writemask
= TGSI_WRITEMASK_X
;
163 writemask
= TGSI_WRITEMASK_YZ
;
165 writemask
= TGSI_WRITEMASK_Y
;
167 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
171 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
172 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
173 sampler
[0] = ureg_DECL_sampler(shader
, 0);
174 sampler
[1] = ureg_DECL_sampler(shader
, 1);
175 if (!luma
&& comps
== 1) {
176 sampler
[2] = ureg_DECL_sampler(shader
, 2);
177 sampler
[3] = ureg_DECL_sampler(shader
, 3);
180 nearest
= luma
|| c
->chroma
== PIPE_VIDEO_CHROMA_FORMAT_444
|| !interlaced
;
181 field
= calc_line(shader
, nearest
);
182 swizcolor
= ureg_DECL_temporary(shader
);
184 /* field.y = fraction(coord/2) >= .5 (from vl_mc.c)
187 * swiz = sampler[bottom];
189 * swiz = sampler[top];
194 * color.xy = swiz.yz;
197 ureg_IF(shader
, ureg_scalar(ureg_src(field
), TGSI_SWIZZLE_Y
), &label
);
199 struct ureg_dst adjtc
= ureg_DECL_temporary(shader
);
201 /* -2.0 / c->video_h (1 pixel up, chroma = half height, full height wouldn't need this)
202 * + .5 / c->video_h (.25 pixel down, since interlaced first pixel = .75 first
204 ureg_MOV(shader
, ureg_writemask(adjtc
, TGSI_WRITEMASK_X
), tc
);
205 ureg_SUB(shader
, ureg_writemask(adjtc
, TGSI_WRITEMASK_Y
), ureg_scalar(tc
, TGSI_SWIZZLE_Y
),
206 ureg_imm1f(shader
, 1.5f
/ c
->video_h
));
208 ureg_MOV(shader
, ureg_writemask(adjtc
, TGSI_WRITEMASK_XY
), tc
);
209 ureg_TEX(shader
, ureg_writemask(swizcolor
, writemask
), TGSI_TEXTURE_2D
, ureg_src(adjtc
), sampler
[1]);
210 if (!luma
&& comps
== 1)
211 ureg_TEX(shader
, ureg_writemask(swizcolor
, TGSI_WRITEMASK_Z
), TGSI_TEXTURE_2D
, ureg_src(adjtc
), sampler
[3]);
212 ureg_release_temporary(shader
, adjtc
);
213 ureg_fixup_label(shader
, label
, ureg_get_instruction_number(shader
));
215 ureg_ELSE(shader
, &label
);
217 struct ureg_dst adjtc
= ureg_DECL_temporary(shader
);
219 ureg_MOV(shader
, ureg_writemask(adjtc
, TGSI_WRITEMASK_X
), tc
);
220 ureg_ADD(shader
, ureg_writemask(adjtc
, TGSI_WRITEMASK_Y
), ureg_scalar(tc
, TGSI_SWIZZLE_Y
),
221 ureg_imm1f(shader
, .5f
/ c
->video_h
));
223 ureg_MOV(shader
, ureg_writemask(adjtc
, TGSI_WRITEMASK_XY
), tc
);
224 ureg_TEX(shader
, ureg_writemask(swizcolor
, writemask
), TGSI_TEXTURE_2D
, ureg_src(adjtc
), sampler
[0]);
225 if (!luma
&& comps
== 1)
226 ureg_TEX(shader
, ureg_writemask(swizcolor
, TGSI_WRITEMASK_Z
), TGSI_TEXTURE_2D
, ureg_src(adjtc
), sampler
[2]);
227 ureg_release_temporary(shader
, adjtc
);
228 ureg_fixup_label(shader
, label
, ureg_get_instruction_number(shader
));
233 ureg_MOV(shader
, ureg_writemask(fragment
, writemask
), ureg_src(swizcolor
));
235 ureg_MOV(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_XY
),
236 ureg_swizzle(ureg_src(swizcolor
), TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_Z
, TGSI_SWIZZLE_Z
, TGSI_SWIZZLE_Z
));
238 ureg_release_temporary(shader
, swizcolor
);
239 ureg_release_temporary(shader
, field
);
241 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
245 create_frag_shader_sobel(struct vl_compositor
*c
)
247 struct ureg_program
*shader
;
248 struct ureg_src tc
, sampler
;
249 struct ureg_dst fragment
, color
[9], tctmp
;
250 float v
[3] = { -1.f
, 0.f
, 1.f
};
253 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
257 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
258 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
259 sampler
= ureg_DECL_sampler(shader
, 0);
261 tctmp
= ureg_DECL_temporary(shader
);
262 for (i
= 0; i
< Elements(color
); ++i
)
263 color
[i
] = ureg_DECL_temporary(shader
);
265 for (i
= 0; i
< 9; ++i
) {
266 ureg_ADD(shader
, ureg_writemask(tctmp
, TGSI_WRITEMASK_XY
), tc
, ureg_imm2f(shader
, v
[i
%3]/(float)c
->video_w
, v
[i
/3]/(float)c
->video_h
));
267 ureg_TEX(shader
, ureg_writemask(color
[i
], TGSI_WRITEMASK_X
), TGSI_TEXTURE_2D
, ureg_src(tctmp
), sampler
);
270 /* tmp.x = P1 + P3 + 2 * P2 */
271 ureg_ADD(shader
, ureg_writemask(tctmp
, TGSI_WRITEMASK_X
), ureg_src(color
[0]), ureg_src(color
[2]));
272 ureg_MAD(shader
, ureg_writemask(tctmp
, TGSI_WRITEMASK_X
), ureg_src(color
[1]), ureg_imm1f(shader
, 2.f
), ureg_src(tctmp
));
274 /* tmp.y = P7 + P9 + 2 * P8 */
275 ureg_ADD(shader
, ureg_writemask(tctmp
, TGSI_WRITEMASK_Y
),
276 ureg_scalar(ureg_src(color
[6]), TGSI_SWIZZLE_X
),
277 ureg_scalar(ureg_src(color
[8]), TGSI_SWIZZLE_X
));
278 ureg_MAD(shader
, ureg_writemask(tctmp
, TGSI_WRITEMASK_Y
),
279 ureg_scalar(ureg_src(color
[7]), TGSI_SWIZZLE_X
),
280 ureg_imm1f(shader
, 2.f
), ureg_src(tctmp
));
282 /* tmp.z = | tmp.x - tmp.y | */
283 ureg_SUB(shader
, ureg_writemask(tctmp
, TGSI_WRITEMASK_Z
),
284 ureg_scalar(ureg_src(tctmp
), TGSI_SWIZZLE_X
),
285 ureg_scalar(ureg_src(tctmp
), TGSI_SWIZZLE_Y
));
286 ureg_ABS(shader
, ureg_writemask(tctmp
, TGSI_WRITEMASK_Z
), ureg_scalar(ureg_src(tctmp
), TGSI_SWIZZLE_Z
));
288 /* tmp.x = P3 + P9 + 2 * P6 */
289 ureg_ADD(shader
, ureg_writemask(tctmp
, TGSI_WRITEMASK_X
), ureg_src(color
[2]), ureg_src(color
[8]));
290 ureg_MAD(shader
, ureg_writemask(tctmp
, TGSI_WRITEMASK_X
), ureg_src(color
[5]), ureg_imm1f(shader
, 2.f
), ureg_src(tctmp
));
292 /* tmp.y = P1 + P7 + 2 * P4 */
293 ureg_ADD(shader
, ureg_writemask(tctmp
, TGSI_WRITEMASK_Y
),
294 ureg_scalar(ureg_src(color
[0]), TGSI_SWIZZLE_X
),
295 ureg_scalar(ureg_src(color
[6]), TGSI_SWIZZLE_X
));
296 ureg_MAD(shader
, ureg_writemask(tctmp
, TGSI_WRITEMASK_Y
),
297 ureg_scalar(ureg_src(color
[3]), TGSI_SWIZZLE_X
),
298 ureg_imm1f(shader
, 2.f
), ureg_src(tctmp
));
300 /* tmp.x = | tmp.x - tmp.y | */
301 ureg_SUB(shader
, ureg_writemask(tctmp
, TGSI_WRITEMASK_X
),
302 ureg_scalar(ureg_src(tctmp
), TGSI_SWIZZLE_X
),
303 ureg_scalar(ureg_src(tctmp
), TGSI_SWIZZLE_Y
));
304 ureg_ABS(shader
, ureg_writemask(tctmp
, TGSI_WRITEMASK_X
), ureg_src(tctmp
));
307 ureg_ADD(shader
, ureg_writemask(tctmp
, TGSI_WRITEMASK_X
),
308 ureg_scalar(ureg_src(tctmp
), TGSI_SWIZZLE_X
),
309 ureg_scalar(ureg_src(tctmp
), TGSI_SWIZZLE_Z
));
311 /* color = color + tmp.x >= .5f */
312 ureg_SGE(shader
, ureg_writemask(tctmp
, TGSI_WRITEMASK_X
), ureg_src(tctmp
), ureg_imm1f(shader
, 0.4f
));
313 ureg_MAD(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_X
), ureg_src(color
[4]), ureg_imm1f(shader
, .25f
), ureg_src(tctmp
));
315 for (i
= 0; i
< Elements(color
); ++i
)
316 ureg_release_temporary(shader
, color
[i
]);
318 ureg_release_temporary(shader
, tctmp
);
320 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
324 create_frag_shader_palette(struct vl_compositor
*c
, bool include_cc
)
326 struct ureg_program
*shader
;
327 struct ureg_src csc
[3];
329 struct ureg_src sampler
;
330 struct ureg_src palette
;
331 struct ureg_dst texel
;
332 struct ureg_dst fragment
;
335 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
339 for (i
= 0; include_cc
&& i
< 3; ++i
)
340 csc
[i
] = ureg_DECL_constant(shader
, i
);
342 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
343 sampler
= ureg_DECL_sampler(shader
, 0);
344 palette
= ureg_DECL_sampler(shader
, 1);
346 texel
= ureg_DECL_temporary(shader
);
347 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
350 * texel = tex(tc, sampler)
351 * fragment.xyz = tex(texel, palette) * csc
352 * fragment.a = texel.a
354 ureg_TEX(shader
, texel
, TGSI_TEXTURE_2D
, tc
, sampler
);
355 ureg_MOV(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_W
), ureg_src(texel
));
358 ureg_TEX(shader
, texel
, TGSI_TEXTURE_1D
, ureg_src(texel
), palette
);
359 for (i
= 0; i
< 3; ++i
)
360 ureg_DP4(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_X
<< i
), csc
[i
], ureg_src(texel
));
362 ureg_TEX(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_XYZ
),
363 TGSI_TEXTURE_1D
, ureg_src(texel
), palette
);
366 ureg_release_temporary(shader
, texel
);
369 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
373 create_frag_shader_rgba(struct vl_compositor
*c
)
375 struct ureg_program
*shader
;
377 struct ureg_src sampler
;
378 struct ureg_dst fragment
;
380 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
384 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
385 sampler
= ureg_DECL_sampler(shader
, 0);
386 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
389 * fragment = tex(tc, sampler)
391 ureg_TEX(shader
, fragment
, TGSI_TEXTURE_2D
, tc
, sampler
);
394 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
398 init_shaders(struct vl_compositor
*c
)
402 c
->vs
= create_vert_shader(c
);
404 debug_printf("Unable to create vertex shader.\n");
408 c
->fs_palette
.yuv
= create_frag_shader_palette(c
, true);
409 if (!c
->fs_palette
.yuv
) {
410 debug_printf("Unable to create YUV-Palette-to-RGB fragment shader.\n");
414 c
->fs_palette
.rgb
= create_frag_shader_palette(c
, false);
415 if (!c
->fs_palette
.rgb
) {
416 debug_printf("Unable to create RGB-Palette-to-RGB fragment shader.\n");
420 c
->fs_rgba
= create_frag_shader_rgba(c
);
422 debug_printf("Unable to create RGB-to-RGB fragment shader.\n");
429 static void cleanup_shaders(struct vl_compositor
*c
)
433 c
->pipe
->delete_vs_state(c
->pipe
, c
->vs
);
434 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_palette
.yuv
);
435 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_palette
.rgb
);
436 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_rgba
);
440 init_pipe_state(struct vl_compositor
*c
)
442 struct pipe_rasterizer_state rast
;
443 struct pipe_sampler_state sampler
;
444 struct pipe_blend_state blend
;
445 struct pipe_depth_stencil_alpha_state dsa
;
450 c
->fb_state
.nr_cbufs
= 1;
451 c
->fb_state
.zsbuf
= NULL
;
453 c
->viewport
.scale
[2] = 1;
454 c
->viewport
.scale
[3] = 1;
455 c
->viewport
.translate
[2] = 0;
456 c
->viewport
.translate
[3] = 0;
458 memset(&sampler
, 0, sizeof(sampler
));
459 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
460 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
461 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
462 sampler
.min_img_filter
= PIPE_TEX_FILTER_LINEAR
;
463 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
464 sampler
.mag_img_filter
= PIPE_TEX_FILTER_LINEAR
;
465 sampler
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
466 sampler
.compare_func
= PIPE_FUNC_ALWAYS
;
467 sampler
.normalized_coords
= 1;
469 c
->sampler_linear
= c
->pipe
->create_sampler_state(c
->pipe
, &sampler
);
471 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
472 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
473 c
->sampler_nearest
= c
->pipe
->create_sampler_state(c
->pipe
, &sampler
);
475 memset(&blend
, 0, sizeof blend
);
476 blend
.independent_blend_enable
= 0;
477 blend
.rt
[0].blend_enable
= 0;
478 blend
.logicop_enable
= 0;
479 blend
.logicop_func
= PIPE_LOGICOP_CLEAR
;
480 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
482 c
->blend_clear
= c
->pipe
->create_blend_state(c
->pipe
, &blend
);
484 blend
.rt
[0].blend_enable
= 1;
485 blend
.rt
[0].rgb_func
= PIPE_BLEND_ADD
;
486 blend
.rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_SRC_ALPHA
;
487 blend
.rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_INV_SRC_ALPHA
;
488 blend
.rt
[0].alpha_func
= PIPE_BLEND_ADD
;
489 blend
.rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
490 blend
.rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ONE
;
491 c
->blend_add
= c
->pipe
->create_blend_state(c
->pipe
, &blend
);
493 memset(&rast
, 0, sizeof rast
);
496 rast
.cull_face
= PIPE_FACE_NONE
;
497 rast
.fill_back
= PIPE_POLYGON_MODE_FILL
;
498 rast
.fill_front
= PIPE_POLYGON_MODE_FILL
;
501 rast
.point_size_per_vertex
= 1;
502 rast
.offset_units
= 1;
503 rast
.offset_scale
= 1;
504 rast
.gl_rasterization_rules
= 1;
506 c
->rast
= c
->pipe
->create_rasterizer_state(c
->pipe
, &rast
);
508 memset(&dsa
, 0, sizeof dsa
);
509 dsa
.depth
.enabled
= 0;
510 dsa
.depth
.writemask
= 0;
511 dsa
.depth
.func
= PIPE_FUNC_ALWAYS
;
512 for (i
= 0; i
< 2; ++i
) {
513 dsa
.stencil
[i
].enabled
= 0;
514 dsa
.stencil
[i
].func
= PIPE_FUNC_ALWAYS
;
515 dsa
.stencil
[i
].fail_op
= PIPE_STENCIL_OP_KEEP
;
516 dsa
.stencil
[i
].zpass_op
= PIPE_STENCIL_OP_KEEP
;
517 dsa
.stencil
[i
].zfail_op
= PIPE_STENCIL_OP_KEEP
;
518 dsa
.stencil
[i
].valuemask
= 0;
519 dsa
.stencil
[i
].writemask
= 0;
521 dsa
.alpha
.enabled
= 0;
522 dsa
.alpha
.func
= PIPE_FUNC_ALWAYS
;
523 dsa
.alpha
.ref_value
= 0;
524 c
->dsa
= c
->pipe
->create_depth_stencil_alpha_state(c
->pipe
, &dsa
);
525 c
->pipe
->bind_depth_stencil_alpha_state(c
->pipe
, c
->dsa
);
530 static void cleanup_pipe_state(struct vl_compositor
*c
)
534 /* Asserted in softpipe_delete_fs_state() for some reason */
535 c
->pipe
->bind_vs_state(c
->pipe
, NULL
);
536 c
->pipe
->bind_fs_state(c
->pipe
, NULL
);
538 c
->pipe
->delete_depth_stencil_alpha_state(c
->pipe
, c
->dsa
);
539 c
->pipe
->delete_sampler_state(c
->pipe
, c
->sampler_linear
);
540 c
->pipe
->delete_sampler_state(c
->pipe
, c
->sampler_nearest
);
541 c
->pipe
->delete_blend_state(c
->pipe
, c
->blend_clear
);
542 c
->pipe
->delete_blend_state(c
->pipe
, c
->blend_add
);
543 c
->pipe
->delete_rasterizer_state(c
->pipe
, c
->rast
);
547 create_vertex_buffer(struct vl_compositor
*c
)
551 pipe_resource_reference(&c
->vertex_buf
.buffer
, NULL
);
552 c
->vertex_buf
.buffer
= pipe_buffer_create
555 PIPE_BIND_VERTEX_BUFFER
,
557 sizeof(struct vertex4f
) * VL_COMPOSITOR_MAX_LAYERS
* 4
560 return c
->vertex_buf
.buffer
!= NULL
;
564 init_buffers(struct vl_compositor
*c
)
566 struct pipe_vertex_element vertex_elems
[2];
571 * Create our vertex buffer and vertex buffer elements
573 c
->vertex_buf
.stride
= sizeof(struct vertex4f
);
574 c
->vertex_buf
.buffer_offset
= 0;
575 create_vertex_buffer(c
);
577 vertex_elems
[0].src_offset
= 0;
578 vertex_elems
[0].instance_divisor
= 0;
579 vertex_elems
[0].vertex_buffer_index
= 0;
580 vertex_elems
[0].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
581 vertex_elems
[1].src_offset
= sizeof(struct vertex2f
);
582 vertex_elems
[1].instance_divisor
= 0;
583 vertex_elems
[1].vertex_buffer_index
= 0;
584 vertex_elems
[1].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
585 c
->vertex_elems_state
= c
->pipe
->create_vertex_elements_state(c
->pipe
, 2, vertex_elems
);
588 * Create our fragment shader's constant buffer
589 * Const buffer contains the color conversion matrix and bias vectors
591 /* XXX: Create with IMMUTABLE/STATIC... although it does change every once in a long while... */
592 c
->csc_matrix
= pipe_buffer_create
595 PIPE_BIND_CONSTANT_BUFFER
,
604 cleanup_buffers(struct vl_compositor
*c
)
608 c
->pipe
->delete_vertex_elements_state(c
->pipe
, c
->vertex_elems_state
);
609 pipe_resource_reference(&c
->vertex_buf
.buffer
, NULL
);
610 pipe_resource_reference(&c
->csc_matrix
, NULL
);
613 static INLINE
struct pipe_video_rect
614 default_rect(struct vl_compositor_layer
*layer
)
616 struct pipe_resource
*res
= layer
->sampler_views
[0]->texture
;
617 struct pipe_video_rect rect
= { 0, 0, res
->width0
, res
->height0
};
621 static INLINE
struct vertex2f
622 calc_topleft(struct vertex2f size
, struct pipe_video_rect rect
)
624 struct vertex2f res
= { rect
.x
/ size
.x
, rect
.y
/ size
.y
};
628 static INLINE
struct vertex2f
629 calc_bottomright(struct vertex2f size
, struct pipe_video_rect rect
)
631 struct vertex2f res
= { (rect
.x
+ rect
.w
) / size
.x
, (rect
.y
+ rect
.h
) / size
.y
};
636 calc_src_and_dst(struct vl_compositor_layer
*layer
, unsigned width
, unsigned height
,
637 struct pipe_video_rect src
, struct pipe_video_rect
*dst
)
639 struct vertex2f size_in
= { width
, height
};
640 struct vertex2f size_out
= { 1.f
, 1.f
};
642 layer
->src
.tl
= calc_topleft(size_in
, src
);
643 layer
->src
.br
= calc_bottomright(size_in
, src
);
645 layer
->dst
.tl
= calc_topleft(size_out
, *dst
);
646 layer
->dst
.br
= calc_bottomright(size_out
, *dst
);
647 layer
->custom_dest_rect
= 1;
649 layer
->dst
.tl
.x
= layer
->dst
.tl
.y
= 0.f
;
650 layer
->dst
.br
.x
= layer
->dst
.br
.y
= 1.f
;
651 layer
->custom_dest_rect
= 0;
656 gen_rect_verts(struct vertex4f
*vb
, struct vl_compositor_layer
*layer
, float w
, float h
)
660 vb
[0].x
= layer
->dst
.tl
.x
/ w
;
661 vb
[0].y
= layer
->dst
.tl
.y
/ h
;
662 vb
[0].z
= layer
->src
.tl
.x
;
663 vb
[0].w
= layer
->src
.tl
.y
;
665 vb
[1].x
= layer
->dst
.br
.x
/ w
;
666 vb
[1].y
= layer
->dst
.tl
.y
/ h
;
667 vb
[1].z
= layer
->src
.br
.x
;
668 vb
[1].w
= layer
->src
.tl
.y
;
670 vb
[2].x
= layer
->dst
.br
.x
/ w
;
671 vb
[2].y
= layer
->dst
.br
.y
/ h
;
672 vb
[2].z
= layer
->src
.br
.x
;
673 vb
[2].w
= layer
->src
.br
.y
;
675 vb
[3].x
= layer
->dst
.tl
.x
/ w
;
676 vb
[3].y
= layer
->dst
.br
.y
/ h
;
677 vb
[3].z
= layer
->src
.tl
.x
;
678 vb
[3].w
= layer
->src
.br
.y
;
682 gen_vertex_data(struct vl_compositor
*c
, float w
, float h
)
685 struct pipe_transfer
*buf_transfer
;
690 vb
= pipe_buffer_map(c
->pipe
, c
->vertex_buf
.buffer
,
691 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
| PIPE_TRANSFER_DONTBLOCK
,
695 // If buffer is still locked from last draw create a new one
696 create_vertex_buffer(c
);
697 vb
= pipe_buffer_map(c
->pipe
, c
->vertex_buf
.buffer
,
698 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
702 for (i
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; i
++) {
703 if (c
->used_layers
& (1 << i
)) {
704 struct vl_compositor_layer
*layer
= &c
->layers
[i
];
705 if (layer
->custom_dest_rect
)
706 gen_rect_verts(vb
, layer
, w
, h
);
708 gen_rect_verts(vb
, layer
, 1.f
, 1.f
);
711 if (layer
->clearing
&&
712 (!layer
->custom_dest_rect
||
713 (c
->dirty_tl
.x
>= layer
->dst
.tl
.x
/w
&&
714 c
->dirty_tl
.y
>= layer
->dst
.tl
.y
/h
&&
715 c
->dirty_br
.x
<= layer
->dst
.br
.x
/w
&&
716 c
->dirty_br
.y
<= layer
->dst
.br
.y
/h
))) {
717 // We clear the dirty area anyway, no need for clear_render_target
718 c
->dirty_tl
.x
= c
->dirty_tl
.y
= 1.0f
;
719 c
->dirty_br
.x
= c
->dirty_br
.y
= 0.0f
;
724 pipe_buffer_unmap(c
->pipe
, buf_transfer
);
728 draw_layers(struct vl_compositor
*c
, float w
, float h
)
730 unsigned vb_index
, i
;
734 for (i
= 0, vb_index
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; ++i
) {
735 if (c
->used_layers
& (1 << i
)) {
736 struct vl_compositor_layer
*layer
= &c
->layers
[i
];
737 struct pipe_sampler_view
**samplers
= &layer
->sampler_views
[0];
738 unsigned num_sampler_views
= !samplers
[1] ? 1 : !samplers
[2] ? 2 : 3;
740 c
->pipe
->bind_blend_state(c
->pipe
, layer
->blend
);
741 c
->pipe
->bind_fs_state(c
->pipe
, layer
->fs
);
742 c
->pipe
->bind_fragment_sampler_states(c
->pipe
, num_sampler_views
, layer
->samplers
);
743 c
->pipe
->set_fragment_sampler_views(c
->pipe
, num_sampler_views
, samplers
);
744 util_draw_arrays(c
->pipe
, PIPE_PRIM_QUADS
, vb_index
* 4, 4);
747 // Remember the currently drawn area as dirty for the next draw command
748 if (layer
->custom_dest_rect
) {
749 c
->dirty_tl
.x
= MIN2(layer
->dst
.tl
.x
/w
, c
->dirty_tl
.x
);
750 c
->dirty_tl
.y
= MIN2(layer
->dst
.tl
.y
/h
, c
->dirty_tl
.y
);
751 c
->dirty_br
.x
= MAX2(layer
->dst
.br
.x
/w
, c
->dirty_br
.x
);
752 c
->dirty_br
.y
= MAX2(layer
->dst
.br
.y
/h
, c
->dirty_br
.y
);
764 vl_compositor_reset_dirty_area(struct vl_compositor
*c
)
768 c
->dirty_tl
.x
= c
->dirty_tl
.y
= 0.0f
;
769 c
->dirty_br
.x
= c
->dirty_br
.y
= 1.0f
;
773 vl_compositor_set_clear_color(struct vl_compositor
*c
, union pipe_color_union
*color
)
777 c
->clear_color
= *color
;
781 vl_compositor_get_clear_color(struct vl_compositor
*c
, union pipe_color_union
*color
)
786 *color
= c
->clear_color
;
790 vl_compositor_clear_layers(struct vl_compositor
*c
)
797 for ( i
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; ++i
) {
798 c
->layers
[i
].clearing
= i
? false : true;
799 c
->layers
[i
].blend
= i
? c
->blend_add
: c
->blend_clear
;
800 c
->layers
[i
].fs
= NULL
;
801 for ( j
= 0; j
< 3; j
++)
802 pipe_sampler_view_reference(&c
->layers
[i
].sampler_views
[j
], NULL
);
807 cleanup_video(struct vl_compositor
*c
)
810 for (i
= 0; i
< Elements(c
->video_res
); ++i
) {
811 pipe_sampler_view_reference(&c
->video_sv
[i
], NULL
);
812 pipe_surface_reference(&c
->video_surf
[i
], NULL
);
813 pipe_resource_reference(&c
->video_res
[i
], NULL
);
815 for (i
= 0; i
< Elements(c
->fs_weave
); ++i
) {
818 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_weave
[i
]);
819 c
->fs_weave
[i
] = NULL
;
821 if (c
->fs_video_buffer2
)
822 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_video_buffer2
);
823 if (c
->fs_video_buffer3
)
824 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_video_buffer3
);
825 c
->fs_video_buffer2
= c
->fs_video_buffer3
= NULL
;
829 vl_compositor_cleanup(struct vl_compositor
*c
)
833 vl_compositor_clear_layers(c
);
836 cleanup_pipe_state(c
);
841 vl_compositor_set_csc_matrix(struct vl_compositor
*c
, const float matrix
[16])
843 struct pipe_transfer
*buf_transfer
;
849 pipe_buffer_map(c
->pipe
, c
->csc_matrix
,
850 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
856 pipe_buffer_unmap(c
->pipe
, buf_transfer
);
860 vl_compositor_set_layer_blend(struct vl_compositor
*c
,
861 unsigned layer
, void *blend
,
866 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
868 c
->layers
[layer
].clearing
= is_clearing
;
869 c
->layers
[layer
].blend
= blend
;
873 static void gen_vertex_data_video(struct vl_compositor
*c
) {
875 struct pipe_transfer
*buf_transfer
;
876 vb
= pipe_buffer_map(c
->pipe
, c
->vertex_buf
.buffer
,
877 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
| PIPE_TRANSFER_DONTBLOCK
,
881 // If buffer is still locked from last draw create a new one
882 create_vertex_buffer(c
);
883 vb
= pipe_buffer_map(c
->pipe
, c
->vertex_buf
.buffer
,
884 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
901 pipe_buffer_unmap(c
->pipe
, buf_transfer
);
905 vl_compositor_render_sobel(struct vl_compositor
*c
)
907 struct pipe_scissor_state scissor
;
908 struct pipe_sampler_view
*sv
= c
->video_sv
[0];
909 struct pipe_surface
*dst_surface
;
914 gen_vertex_data_video(c
);
916 dst_surface
= c
->video_surf
[3];
919 c
->fb_state
.width
= dst_surface
->width
;
920 c
->fb_state
.height
= dst_surface
->height
;
921 c
->fb_state
.cbufs
[0] = dst_surface
;
923 c
->viewport
.scale
[0] = sv
->texture
->width0
;
924 c
->viewport
.scale
[1] = sv
->texture
->height0
;
925 c
->viewport
.translate
[0] = 0;
926 c
->viewport
.translate
[1] = 0;
930 scissor
.maxx
= dst_surface
->width
;
931 scissor
.maxy
= dst_surface
->height
;
933 c
->pipe
->set_scissor_state(c
->pipe
, &scissor
);
934 c
->pipe
->set_framebuffer_state(c
->pipe
, &c
->fb_state
);
935 c
->pipe
->set_viewport_state(c
->pipe
, &c
->viewport
);
936 c
->pipe
->bind_vs_state(c
->pipe
, c
->vs
);
937 c
->pipe
->set_vertex_buffers(c
->pipe
, 1, &c
->vertex_buf
);
938 c
->pipe
->bind_vertex_elements_state(c
->pipe
, c
->vertex_elems_state
);
939 c
->pipe
->bind_rasterizer_state(c
->pipe
, c
->rast
);
941 c
->pipe
->bind_blend_state(c
->pipe
, c
->blend_clear
);
942 c
->pipe
->bind_fs_state(c
->pipe
, fs
);
943 c
->pipe
->bind_fragment_sampler_states(c
->pipe
, 1, &c
->sampler_nearest
);
944 c
->pipe
->set_fragment_sampler_views(c
->pipe
, 1, &sv
);
945 util_draw_arrays(c
->pipe
, PIPE_PRIM_TRIANGLES
, 0, 3);
949 vl_compositor_render_video(struct vl_compositor
*c
,
950 struct pipe_sampler_view
**sv
,
953 struct pipe_scissor_state scissor
;
956 for (i
= 0; i
< 4; ++i
) {
957 if (!interlaced
|| i
< 2 || c
->chroma
== PIPE_VIDEO_CHROMA_FORMAT_444
)
958 samplers
[i
] = c
->sampler_nearest
;
960 samplers
[i
] = c
->sampler_linear
;
963 gen_vertex_data_video(c
);
964 for (i
= 0; i
< 2; ++i
) {
965 struct pipe_surface
*dst_surface
;
966 unsigned num_sampler_views
;
969 num_sampler_views
= 2;
970 dst_surface
= c
->video_surf
[0];
973 num_sampler_views
= 2 + 2 * !!sv
[2];
975 dst_surface
= c
->video_surf
[1];
976 fs
= c
->fs_weave
[1 + !!sv
[2]];
978 dst_surface
= c
->video_surf
[2];
979 fs
= c
->fs_weave
[3 + !!sv
[2]];
984 c
->fb_state
.width
= dst_surface
->width
;
985 c
->fb_state
.height
= dst_surface
->height
;
986 c
->fb_state
.cbufs
[0] = dst_surface
;
988 c
->viewport
.scale
[0] = sv
[0]->texture
->width0
;
989 c
->viewport
.scale
[1] = sv
[0]->texture
->height0
* 2;
990 if (i
&& c
->chroma
!= PIPE_VIDEO_CHROMA_FORMAT_444
&& interlaced
)
991 c
->viewport
.scale
[1] *= 2;
992 c
->viewport
.translate
[0] = 0;
993 c
->viewport
.translate
[1] = 0;
997 scissor
.maxx
= dst_surface
->width
;
998 scissor
.maxy
= dst_surface
->height
;
1000 c
->pipe
->set_scissor_state(c
->pipe
, &scissor
);
1001 c
->pipe
->set_framebuffer_state(c
->pipe
, &c
->fb_state
);
1002 c
->pipe
->set_viewport_state(c
->pipe
, &c
->viewport
);
1003 c
->pipe
->bind_vs_state(c
->pipe
, c
->vs
);
1004 c
->pipe
->set_vertex_buffers(c
->pipe
, 1, &c
->vertex_buf
);
1005 c
->pipe
->bind_vertex_elements_state(c
->pipe
, c
->vertex_elems_state
);
1006 c
->pipe
->bind_rasterizer_state(c
->pipe
, c
->rast
);
1008 c
->pipe
->bind_blend_state(c
->pipe
, c
->blend_clear
);
1009 c
->pipe
->bind_fs_state(c
->pipe
, fs
);
1010 c
->pipe
->bind_fragment_sampler_states(c
->pipe
, num_sampler_views
, samplers
);
1011 c
->pipe
->set_fragment_sampler_views(c
->pipe
, num_sampler_views
, sv
);
1012 sv
+= num_sampler_views
;
1013 util_draw_arrays(c
->pipe
, PIPE_PRIM_TRIANGLES
, 0, 3);
1018 vl_compositor_set_buffer_layer(struct vl_compositor
*c
, unsigned layer
,
1019 enum pipe_video_picture_structure field
,
1020 struct pipe_video_buffer
*buffer
,
1021 struct pipe_video_rect
*src_rect
,
1022 struct pipe_video_rect
*dst_rect
,
1023 unsigned past_count
,
1024 struct pipe_video_buffer
**past
,
1025 unsigned future_count
,
1026 struct pipe_video_buffer
**future
)
1028 struct pipe_sampler_view
**sampler_views
, *sv
[3];
1029 struct pipe_video_rect rect
;
1030 unsigned i
, half_h
= 0;
1032 assert(c
&& buffer
);
1033 assert(c
->video_w
<= buffer
->width
&& c
->video_h
<= buffer
->height
);
1034 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
1036 if (field
== PIPE_VIDEO_PICTURE_STRUCTURE_FRAME
) {
1037 sampler_views
= buffer
->get_sampler_view_planes(buffer
, 0);
1038 if (!sampler_views
) {
1039 sampler_views
= buffer
->get_sampler_view_planes(buffer
, 1);
1040 vl_compositor_render_video(c
, sampler_views
, 0);
1041 sv
[0] = c
->video_sv
[0];
1042 if (DEBUG_CONTOUR
) {
1043 sv
[0] = c
->video_sv
[3];
1044 vl_compositor_render_sobel(c
);
1046 sv
[1] = c
->video_sv
[2];
1051 struct pipe_sampler_view
**sv_cur
, **sv_prev
= NULL
, *sv_weave
[6];
1052 int top
= field
== PIPE_VIDEO_PICTURE_STRUCTURE_FIELD_TOP
;
1053 sv_cur
= buffer
->get_sampler_view_planes(buffer
, 1);
1054 if (past_count
&& past
[0])
1055 sv_prev
= buffer
->get_sampler_view_planes(past
[0], 1);
1057 for (i
= 0; i
< 6; i
+= 2) {
1059 sv_weave
[i
] = sv_cur
[i
];
1060 sv_weave
[i
+1] = sv_prev
[i
+1];
1062 sv_weave
[i
] = sv_prev
[i
];
1063 sv_weave
[i
+1] = sv_cur
[i
+1];
1066 vl_compositor_render_video(c
, sv_weave
, 1);
1067 sv
[0] = c
->video_sv
[0];
1068 sv
[1] = c
->video_sv
[1];
1071 for (i
= 0; i
< 3; ++i
)
1072 sv
[i
] = sv_cur
[2*i
+!top
];
1078 c
->used_layers
|= 1 << layer
;
1081 rect
.x
= rect
.y
= 0;
1082 rect
.w
= c
->video_w
;
1083 rect
.h
= c
->video_h
;
1085 for (i
= 0; i
< 3; ++i
) {
1086 c
->layers
[layer
].samplers
[i
] = c
->sampler_linear
;
1087 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[i
], sampler_views
[i
]);
1089 if (sampler_views
[2])
1090 c
->layers
[layer
].fs
= c
->fs_video_buffer3
;
1092 c
->layers
[layer
].fs
= c
->fs_video_buffer2
;
1093 assert(sampler_views
[1]);
1095 calc_src_and_dst(&c
->layers
[layer
],
1096 sampler_views
[0]->texture
->width0
,
1097 sampler_views
[0]->texture
->height0
<< half_h
,
1098 *src_rect
, dst_rect
);
1102 vl_compositor_set_palette_layer(struct vl_compositor
*c
,
1104 struct pipe_sampler_view
*indexes
,
1105 struct pipe_sampler_view
*palette
,
1106 struct pipe_video_rect
*src_rect
,
1107 struct pipe_video_rect
*dst_rect
,
1108 bool include_color_conversion
)
1110 assert(c
&& indexes
&& palette
);
1112 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
1114 c
->used_layers
|= 1 << layer
;
1116 c
->layers
[layer
].fs
= include_color_conversion
?
1117 c
->fs_palette
.yuv
: c
->fs_palette
.rgb
;
1119 c
->layers
[layer
].samplers
[0] = c
->sampler_linear
;
1120 c
->layers
[layer
].samplers
[1] = c
->sampler_nearest
;
1121 c
->layers
[layer
].samplers
[2] = NULL
;
1122 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[0], indexes
);
1123 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[1], palette
);
1124 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[2], NULL
);
1125 calc_src_and_dst(&c
->layers
[layer
], indexes
->texture
->width0
, indexes
->texture
->height0
,
1126 src_rect
? *src_rect
: default_rect(&c
->layers
[layer
]),
1131 vl_compositor_set_rgba_layer(struct vl_compositor
*c
,
1133 struct pipe_sampler_view
*rgba
,
1134 struct pipe_video_rect
*src_rect
,
1135 struct pipe_video_rect
*dst_rect
)
1139 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
1141 c
->used_layers
|= 1 << layer
;
1142 c
->layers
[layer
].fs
= c
->fs_rgba
;
1143 c
->layers
[layer
].samplers
[0] = c
->sampler_linear
;
1144 c
->layers
[layer
].samplers
[1] = NULL
;
1145 c
->layers
[layer
].samplers
[2] = NULL
;
1146 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[0], rgba
);
1147 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[1], NULL
);
1148 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[2], NULL
);
1149 calc_src_and_dst(&c
->layers
[layer
], rgba
->texture
->width0
, rgba
->texture
->height0
,
1150 src_rect
? *src_rect
: default_rect(&c
->layers
[layer
]),
1155 vl_compositor_render(struct vl_compositor
*c
,
1156 struct pipe_surface
*dst_surface
,
1157 struct pipe_video_rect
*dst_area
,
1158 struct pipe_video_rect
*dst_clip
,
1159 bool clear_dirty_area
)
1161 struct pipe_scissor_state scissor
;
1164 assert(dst_surface
);
1166 c
->fb_state
.width
= dst_surface
->width
;
1167 c
->fb_state
.height
= dst_surface
->height
;
1168 c
->fb_state
.cbufs
[0] = dst_surface
;
1171 c
->viewport
.scale
[0] = dst_area
->w
;
1172 c
->viewport
.scale
[1] = dst_area
->h
;
1173 c
->viewport
.translate
[0] = dst_area
->x
;
1174 c
->viewport
.translate
[1] = dst_area
->y
;
1176 c
->viewport
.scale
[0] = dst_surface
->width
;
1177 c
->viewport
.scale
[1] = dst_surface
->height
;
1178 c
->viewport
.translate
[0] = 0;
1179 c
->viewport
.translate
[1] = 0;
1183 scissor
.minx
= dst_clip
->x
;
1184 scissor
.miny
= dst_clip
->y
;
1185 scissor
.maxx
= dst_clip
->x
+ dst_clip
->w
;
1186 scissor
.maxy
= dst_clip
->y
+ dst_clip
->h
;
1190 scissor
.maxx
= dst_surface
->width
;
1191 scissor
.maxy
= dst_surface
->height
;
1194 gen_vertex_data(c
, dst_surface
->width
, dst_surface
->height
);
1196 if (clear_dirty_area
&& (c
->dirty_tl
.x
< c
->dirty_br
.x
||
1197 c
->dirty_tl
.y
< c
->dirty_br
.y
)) {
1198 util_clear_render_target(c
->pipe
, dst_surface
, &c
->clear_color
,
1199 0, 0, dst_surface
->width
, dst_surface
->height
);
1200 c
->dirty_tl
.x
= c
->dirty_tl
.y
= 1.0f
;
1201 c
->dirty_br
.x
= c
->dirty_br
.y
= 0.0f
;
1204 c
->pipe
->set_scissor_state(c
->pipe
, &scissor
);
1205 c
->pipe
->set_framebuffer_state(c
->pipe
, &c
->fb_state
);
1206 c
->pipe
->set_viewport_state(c
->pipe
, &c
->viewport
);
1207 c
->pipe
->bind_vs_state(c
->pipe
, c
->vs
);
1208 c
->pipe
->set_vertex_buffers(c
->pipe
, 1, &c
->vertex_buf
);
1209 c
->pipe
->bind_vertex_elements_state(c
->pipe
, c
->vertex_elems_state
);
1210 c
->pipe
->set_constant_buffer(c
->pipe
, PIPE_SHADER_FRAGMENT
, 0, c
->csc_matrix
);
1211 c
->pipe
->bind_rasterizer_state(c
->pipe
, c
->rast
);
1213 draw_layers(c
, dst_surface
->width
, dst_surface
->height
);
1217 vl_compositor_init(struct vl_compositor
*c
, struct pipe_context
*pipe
)
1219 csc_matrix csc_matrix
;
1223 if (!init_pipe_state(c
))
1226 if (!init_shaders(c
)) {
1227 cleanup_pipe_state(c
);
1231 if (!init_buffers(c
)) {
1233 cleanup_pipe_state(c
);
1237 vl_compositor_clear_layers(c
);
1239 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY
, NULL
, true, csc_matrix
);
1240 vl_compositor_set_csc_matrix(c
, csc_matrix
);
1242 c
->clear_color
.f
[0] = c
->clear_color
.f
[1] = 0.0f
;
1243 c
->clear_color
.f
[2] = c
->clear_color
.f
[3] = 0.0f
;
1244 vl_compositor_reset_dirty_area(c
);
1250 vl_compositor_init_video(struct vl_compositor
*c
, struct pipe_context
*pipe
,
1251 enum pipe_video_chroma_format chroma
, unsigned w
, unsigned h
)
1253 struct pipe_resource templ
;
1255 if (!vl_compositor_init(c
, pipe
))
1260 c
->fs_video_buffer2
= create_frag_shader_video_buffer(c
, 2);
1261 if (!c
->fs_video_buffer2
) {
1262 debug_printf("Unable to create YCbCr-to-RGB fragment shader for 2 planes.\n");
1265 c
->fs_video_buffer3
= create_frag_shader_video_buffer(c
, 3);
1266 if (!c
->fs_video_buffer3
) {
1267 debug_printf("Unable to create YCbCr-to-RGB fragment shader for 3 planes.\n");
1270 c
->fs_weave
[0] = create_frag_shader_weave(c
, 1, 0, 1);
1271 c
->fs_weave
[1] = create_frag_shader_weave(c
, 0, 1, 2); // CbCr woven interlaced
1272 c
->fs_weave
[2] = create_frag_shader_weave(c
, 0, 1, 1); // Cb, Cr separate interlaced
1273 c
->fs_weave
[3] = create_frag_shader_weave(c
, 0, 0, 2); // CbCr woven progressive
1274 c
->fs_weave
[4] = create_frag_shader_weave(c
, 0, 0, 1); // Cb, Cr separate progressive
1276 c
->fs_weave
[5] = create_frag_shader_sobel(c
);
1277 for (i
= 0; i
< Elements(c
->fs_weave
) - !DEBUG_CONTOUR
; ++i
) {
1278 if (!c
->fs_weave
[i
]) {
1279 debug_printf("Unable to create weave fragment shaders [%i].\n", i
);
1283 memset(&templ
, 0, sizeof(templ
));
1284 templ
.target
= PIPE_TEXTURE_2D
;
1285 templ
.format
= PIPE_FORMAT_R8_UNORM
;
1289 templ
.array_size
= 1;
1290 templ
.bind
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
;
1291 templ
.usage
= PIPE_USAGE_STATIC
;
1292 c
->video_res
[0] = pipe
->screen
->resource_create(pipe
->screen
, &templ
);
1293 if (!c
->video_res
[0]) {
1294 debug_printf("Could not create weave temp frame for luma\n");
1298 if (chroma
== PIPE_VIDEO_CHROMA_FORMAT_420
)
1300 templ
.format
= PIPE_FORMAT_R8G8_UNORM
;
1301 c
->video_res
[1] = pipe
->screen
->resource_create(pipe
->screen
, &templ
);
1302 if (!c
->video_res
[1]) {
1303 debug_printf("Could not create interlaced temp frame for chroma\n");
1307 if (chroma
!= PIPE_VIDEO_CHROMA_FORMAT_444
)
1308 templ
.height0
= h
/ 2;
1309 c
->video_res
[2] = pipe
->screen
->resource_create(pipe
->screen
, &templ
);
1310 if (!c
->video_res
[2]) {
1311 debug_printf("Could not create deinterlaced temp frame for chroma\n");
1315 if (DEBUG_CONTOUR
) {
1316 c
->video_res
[3] = pipe
->screen
->resource_create(pipe
->screen
, c
->video_res
[0]);
1317 if (!c
->video_res
[3]) {
1318 debug_printf("Could not create sobel temp frame for luma\n");
1323 for (i
= 0; i
< Elements(c
->video_res
) - !DEBUG_CONTOUR
; ++i
) {
1324 struct pipe_sampler_view sv_templ
;
1325 struct pipe_surface surf_templ
;
1327 memset(&sv_templ
, 0, sizeof(sv_templ
));
1328 u_sampler_view_default_template(&sv_templ
, c
->video_res
[i
], c
->video_res
[i
]->format
);
1329 if (c
->video_res
[i
]->format
== PIPE_FORMAT_R8_UNORM
)
1330 sv_templ
.swizzle_a
= sv_templ
.swizzle_b
= sv_templ
.swizzle_g
= sv_templ
.swizzle_r
;
1331 else if (c
->video_res
[i
]->format
== PIPE_FORMAT_R8G8_UNORM
) {
1332 sv_templ
.swizzle_b
= PIPE_SWIZZLE_GREEN
;
1333 sv_templ
.swizzle_g
= PIPE_SWIZZLE_RED
;
1335 c
->video_sv
[i
] = pipe
->create_sampler_view(pipe
, c
->video_res
[i
], &sv_templ
);
1337 if (!c
->video_sv
[i
]) {
1338 debug_printf("Could not create temp video sampler views\n");
1342 memset(&surf_templ
, 0, sizeof(surf_templ
));
1343 surf_templ
.usage
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
;
1344 surf_templ
.format
= c
->video_res
[i
]->format
;
1345 c
->video_surf
[i
] = pipe
->create_surface(pipe
, c
->video_res
[i
], &surf_templ
);
1346 if (!c
->video_surf
[i
]) {
1347 debug_printf("Could not create temp video surface\n");
1355 vl_compositor_cleanup(c
);