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];
47 create_vert_shader(struct vl_compositor
*c
)
49 struct ureg_program
*shader
;
50 struct ureg_src vpos
, vtex
;
51 struct ureg_dst o_vpos
, o_vtex
;
53 shader
= ureg_create(TGSI_PROCESSOR_VERTEX
);
57 vpos
= ureg_DECL_vs_input(shader
, 0);
58 vtex
= ureg_DECL_vs_input(shader
, 1);
59 o_vpos
= ureg_DECL_output(shader
, TGSI_SEMANTIC_POSITION
, 0);
60 o_vtex
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, 1);
66 ureg_MOV(shader
, o_vpos
, vpos
);
67 ureg_MOV(shader
, o_vtex
, vtex
);
71 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
75 create_frag_shader_video_buffer(struct vl_compositor
*c
, unsigned planes
)
77 struct ureg_program
*shader
;
79 struct ureg_src csc
[3];
80 struct ureg_src sampler
[3];
81 struct ureg_dst texel
;
82 struct ureg_dst fragment
;
85 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
89 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
90 for (i
= 0; i
< 3; ++i
) {
91 csc
[i
] = ureg_DECL_constant(shader
, i
);
93 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
95 texel
= ureg_DECL_temporary(shader
);
96 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
99 * texel.xyz = tex(tc, sampler[i])
100 * fragment = csc * texel
103 ureg_TEX(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_X
), TGSI_TEXTURE_2D
, tc
, sampler
[0]);
104 ureg_TEX(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_YZ
), TGSI_TEXTURE_2D
, tc
, sampler
[1]);
106 for (i
= 0; i
< 3; ++i
)
107 ureg_TEX(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_X
<< i
), TGSI_TEXTURE_2D
, tc
, sampler
[i
]);
110 ureg_MOV(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
112 for (i
= 0; i
< 3; ++i
)
113 ureg_DP4(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_X
<< i
), csc
[i
], ureg_src(texel
));
115 ureg_MOV(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
117 ureg_release_temporary(shader
, texel
);
120 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
123 static struct ureg_dst
124 calc_line(struct ureg_program
*shader
)
129 tmp
= ureg_DECL_temporary(shader
);
131 pos
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_POSITION
, 0, TGSI_INTERPOLATE_LINEAR
);
134 * tmp.y = fraction(pos.y * .5) >= 0.5 ? 1 : 0
136 ureg_MUL(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
), pos
, ureg_imm1f(shader
, 0.5f
));
137 ureg_FRC(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
), ureg_src(tmp
));
138 ureg_SGE(shader
, ureg_writemask(tmp
, TGSI_WRITEMASK_Y
), ureg_src(tmp
), ureg_imm1f(shader
, 0.5f
));
143 /* Deinterlace NV12 or YV12 to a temporary video buffer
147 create_frag_shader_deint_planar_weave(struct vl_compositor
*c
, unsigned luma
, unsigned comps
)
149 struct ureg_program
*shader
;
150 struct ureg_src tc
, sampler
[4];
151 struct ureg_dst field
, fragment
, swizcolor
;
152 unsigned label
, writemask
;
154 writemask
= TGSI_WRITEMASK_X
;
156 writemask
= TGSI_WRITEMASK_YZ
;
158 writemask
= TGSI_WRITEMASK_Y
;
160 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
164 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
165 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
166 sampler
[0] = ureg_DECL_sampler(shader
, 0);
167 sampler
[1] = ureg_DECL_sampler(shader
, 1);
168 if (!luma
&& comps
== 1) {
169 sampler
[2] = ureg_DECL_sampler(shader
, 2);
170 sampler
[3] = ureg_DECL_sampler(shader
, 3);
173 field
= calc_line(shader
);
174 swizcolor
= ureg_DECL_temporary(shader
);
176 /* field.y = fraction(coord/2) >= .5 (from vl_mc.c)
179 * swiz = sampler[bottom];
181 * swiz = sampler[top];
186 * color.xy = swiz.yz;
189 ureg_IF(shader
, ureg_scalar(ureg_src(field
), TGSI_SWIZZLE_Y
), &label
);
190 ureg_TEX(shader
, ureg_writemask(swizcolor
, writemask
), TGSI_TEXTURE_2D
, tc
, sampler
[1]);
191 if (!luma
&& comps
== 1)
192 ureg_TEX(shader
, ureg_writemask(swizcolor
, TGSI_WRITEMASK_Z
), TGSI_TEXTURE_2D
, tc
, sampler
[3]);
193 ureg_fixup_label(shader
, label
, ureg_get_instruction_number(shader
));
194 ureg_ELSE(shader
, &label
);
195 ureg_TEX(shader
, ureg_writemask(swizcolor
, writemask
), TGSI_TEXTURE_2D
, tc
, sampler
[0]);
196 if (!luma
&& comps
== 1)
197 ureg_TEX(shader
, ureg_writemask(swizcolor
, TGSI_WRITEMASK_Z
), TGSI_TEXTURE_2D
, tc
, sampler
[2]);
198 ureg_fixup_label(shader
, label
, ureg_get_instruction_number(shader
));
202 ureg_MOV(shader
, ureg_writemask(fragment
, writemask
), ureg_src(swizcolor
));
204 ureg_MOV(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_XY
),
205 ureg_swizzle(ureg_src(swizcolor
), TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_Z
, TGSI_SWIZZLE_Z
, TGSI_SWIZZLE_Z
));
207 ureg_release_temporary(shader
, swizcolor
);
208 ureg_release_temporary(shader
, field
);
210 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
214 create_frag_shader_palette(struct vl_compositor
*c
, bool include_cc
)
216 struct ureg_program
*shader
;
217 struct ureg_src csc
[3];
219 struct ureg_src sampler
;
220 struct ureg_src palette
;
221 struct ureg_dst texel
;
222 struct ureg_dst fragment
;
225 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
229 for (i
= 0; include_cc
&& i
< 3; ++i
)
230 csc
[i
] = ureg_DECL_constant(shader
, i
);
232 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
233 sampler
= ureg_DECL_sampler(shader
, 0);
234 palette
= ureg_DECL_sampler(shader
, 1);
236 texel
= ureg_DECL_temporary(shader
);
237 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
240 * texel = tex(tc, sampler)
241 * fragment.xyz = tex(texel, palette) * csc
242 * fragment.a = texel.a
244 ureg_TEX(shader
, texel
, TGSI_TEXTURE_2D
, tc
, sampler
);
245 ureg_MOV(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_W
), ureg_src(texel
));
248 ureg_TEX(shader
, texel
, TGSI_TEXTURE_1D
, ureg_src(texel
), palette
);
249 for (i
= 0; i
< 3; ++i
)
250 ureg_DP4(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_X
<< i
), csc
[i
], ureg_src(texel
));
252 ureg_TEX(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_XYZ
),
253 TGSI_TEXTURE_1D
, ureg_src(texel
), palette
);
256 ureg_release_temporary(shader
, texel
);
259 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
263 create_frag_shader_rgba(struct vl_compositor
*c
)
265 struct ureg_program
*shader
;
267 struct ureg_src sampler
;
268 struct ureg_dst fragment
;
270 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
274 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
275 sampler
= ureg_DECL_sampler(shader
, 0);
276 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
279 * fragment = tex(tc, sampler)
281 ureg_TEX(shader
, fragment
, TGSI_TEXTURE_2D
, tc
, sampler
);
284 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
288 init_shaders(struct vl_compositor
*c
)
292 c
->vs
= create_vert_shader(c
);
294 debug_printf("Unable to create vertex shader.\n");
298 c
->fs_palette
.yuv
= create_frag_shader_palette(c
, true);
299 if (!c
->fs_palette
.yuv
) {
300 debug_printf("Unable to create YUV-Palette-to-RGB fragment shader.\n");
304 c
->fs_palette
.rgb
= create_frag_shader_palette(c
, false);
305 if (!c
->fs_palette
.rgb
) {
306 debug_printf("Unable to create RGB-Palette-to-RGB fragment shader.\n");
310 c
->fs_rgba
= create_frag_shader_rgba(c
);
312 debug_printf("Unable to create RGB-to-RGB fragment shader.\n");
319 static void cleanup_shaders(struct vl_compositor
*c
)
323 c
->pipe
->delete_vs_state(c
->pipe
, c
->vs
);
324 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_palette
.yuv
);
325 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_palette
.rgb
);
326 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_rgba
);
330 init_pipe_state(struct vl_compositor
*c
)
332 struct pipe_rasterizer_state rast
;
333 struct pipe_sampler_state sampler
;
334 struct pipe_blend_state blend
;
335 struct pipe_depth_stencil_alpha_state dsa
;
340 c
->fb_state
.nr_cbufs
= 1;
341 c
->fb_state
.zsbuf
= NULL
;
343 c
->viewport
.scale
[2] = 1;
344 c
->viewport
.scale
[3] = 1;
345 c
->viewport
.translate
[2] = 0;
346 c
->viewport
.translate
[3] = 0;
348 memset(&sampler
, 0, sizeof(sampler
));
349 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
350 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
351 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
352 sampler
.min_img_filter
= PIPE_TEX_FILTER_LINEAR
;
353 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
354 sampler
.mag_img_filter
= PIPE_TEX_FILTER_LINEAR
;
355 sampler
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
356 sampler
.compare_func
= PIPE_FUNC_ALWAYS
;
357 sampler
.normalized_coords
= 1;
359 c
->sampler_linear
= c
->pipe
->create_sampler_state(c
->pipe
, &sampler
);
361 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
362 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
363 c
->sampler_nearest
= c
->pipe
->create_sampler_state(c
->pipe
, &sampler
);
365 memset(&blend
, 0, sizeof blend
);
366 blend
.independent_blend_enable
= 0;
367 blend
.rt
[0].blend_enable
= 0;
368 blend
.logicop_enable
= 0;
369 blend
.logicop_func
= PIPE_LOGICOP_CLEAR
;
370 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
372 c
->blend_clear
= c
->pipe
->create_blend_state(c
->pipe
, &blend
);
374 blend
.rt
[0].blend_enable
= 1;
375 blend
.rt
[0].rgb_func
= PIPE_BLEND_ADD
;
376 blend
.rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_SRC_ALPHA
;
377 blend
.rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_INV_SRC_ALPHA
;
378 blend
.rt
[0].alpha_func
= PIPE_BLEND_ADD
;
379 blend
.rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
380 blend
.rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ONE
;
381 c
->blend_add
= c
->pipe
->create_blend_state(c
->pipe
, &blend
);
383 memset(&rast
, 0, sizeof rast
);
386 rast
.cull_face
= PIPE_FACE_NONE
;
387 rast
.fill_back
= PIPE_POLYGON_MODE_FILL
;
388 rast
.fill_front
= PIPE_POLYGON_MODE_FILL
;
391 rast
.point_size_per_vertex
= 1;
392 rast
.offset_units
= 1;
393 rast
.offset_scale
= 1;
394 rast
.gl_rasterization_rules
= 1;
396 c
->rast
= c
->pipe
->create_rasterizer_state(c
->pipe
, &rast
);
398 memset(&dsa
, 0, sizeof dsa
);
399 dsa
.depth
.enabled
= 0;
400 dsa
.depth
.writemask
= 0;
401 dsa
.depth
.func
= PIPE_FUNC_ALWAYS
;
402 for (i
= 0; i
< 2; ++i
) {
403 dsa
.stencil
[i
].enabled
= 0;
404 dsa
.stencil
[i
].func
= PIPE_FUNC_ALWAYS
;
405 dsa
.stencil
[i
].fail_op
= PIPE_STENCIL_OP_KEEP
;
406 dsa
.stencil
[i
].zpass_op
= PIPE_STENCIL_OP_KEEP
;
407 dsa
.stencil
[i
].zfail_op
= PIPE_STENCIL_OP_KEEP
;
408 dsa
.stencil
[i
].valuemask
= 0;
409 dsa
.stencil
[i
].writemask
= 0;
411 dsa
.alpha
.enabled
= 0;
412 dsa
.alpha
.func
= PIPE_FUNC_ALWAYS
;
413 dsa
.alpha
.ref_value
= 0;
414 c
->dsa
= c
->pipe
->create_depth_stencil_alpha_state(c
->pipe
, &dsa
);
415 c
->pipe
->bind_depth_stencil_alpha_state(c
->pipe
, c
->dsa
);
420 static void cleanup_pipe_state(struct vl_compositor
*c
)
424 /* Asserted in softpipe_delete_fs_state() for some reason */
425 c
->pipe
->bind_vs_state(c
->pipe
, NULL
);
426 c
->pipe
->bind_fs_state(c
->pipe
, NULL
);
428 c
->pipe
->delete_depth_stencil_alpha_state(c
->pipe
, c
->dsa
);
429 c
->pipe
->delete_sampler_state(c
->pipe
, c
->sampler_linear
);
430 c
->pipe
->delete_sampler_state(c
->pipe
, c
->sampler_nearest
);
431 c
->pipe
->delete_blend_state(c
->pipe
, c
->blend_clear
);
432 c
->pipe
->delete_blend_state(c
->pipe
, c
->blend_add
);
433 c
->pipe
->delete_rasterizer_state(c
->pipe
, c
->rast
);
437 create_vertex_buffer(struct vl_compositor
*c
)
441 pipe_resource_reference(&c
->vertex_buf
.buffer
, NULL
);
442 c
->vertex_buf
.buffer
= pipe_buffer_create
445 PIPE_BIND_VERTEX_BUFFER
,
447 sizeof(struct vertex4f
) * VL_COMPOSITOR_MAX_LAYERS
* 4
450 return c
->vertex_buf
.buffer
!= NULL
;
454 init_buffers(struct vl_compositor
*c
)
456 struct pipe_vertex_element vertex_elems
[2];
461 * Create our vertex buffer and vertex buffer elements
463 c
->vertex_buf
.stride
= sizeof(struct vertex4f
);
464 c
->vertex_buf
.buffer_offset
= 0;
465 create_vertex_buffer(c
);
467 vertex_elems
[0].src_offset
= 0;
468 vertex_elems
[0].instance_divisor
= 0;
469 vertex_elems
[0].vertex_buffer_index
= 0;
470 vertex_elems
[0].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
471 vertex_elems
[1].src_offset
= sizeof(struct vertex2f
);
472 vertex_elems
[1].instance_divisor
= 0;
473 vertex_elems
[1].vertex_buffer_index
= 0;
474 vertex_elems
[1].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
475 c
->vertex_elems_state
= c
->pipe
->create_vertex_elements_state(c
->pipe
, 2, vertex_elems
);
478 * Create our fragment shader's constant buffer
479 * Const buffer contains the color conversion matrix and bias vectors
481 /* XXX: Create with IMMUTABLE/STATIC... although it does change every once in a long while... */
482 c
->csc_matrix
= pipe_buffer_create
485 PIPE_BIND_CONSTANT_BUFFER
,
494 cleanup_buffers(struct vl_compositor
*c
)
498 c
->pipe
->delete_vertex_elements_state(c
->pipe
, c
->vertex_elems_state
);
499 pipe_resource_reference(&c
->vertex_buf
.buffer
, NULL
);
500 pipe_resource_reference(&c
->csc_matrix
, NULL
);
503 static INLINE
struct pipe_video_rect
504 default_rect(struct vl_compositor_layer
*layer
)
506 struct pipe_resource
*res
= layer
->sampler_views
[0]->texture
;
507 struct pipe_video_rect rect
= { 0, 0, res
->width0
, res
->height0
};
511 static INLINE
struct vertex2f
512 calc_topleft(struct vertex2f size
, struct pipe_video_rect rect
)
514 struct vertex2f res
= { rect
.x
/ size
.x
, rect
.y
/ size
.y
};
518 static INLINE
struct vertex2f
519 calc_bottomright(struct vertex2f size
, struct pipe_video_rect rect
)
521 struct vertex2f res
= { (rect
.x
+ rect
.w
) / size
.x
, (rect
.y
+ rect
.h
) / size
.y
};
526 calc_src_and_dst(struct vl_compositor_layer
*layer
, unsigned width
, unsigned height
,
527 struct pipe_video_rect src
, struct pipe_video_rect
*dst
)
529 struct vertex2f size_in
= { width
, height
};
530 struct vertex2f size_out
= { 1.f
, 1.f
};
532 layer
->src
.tl
= calc_topleft(size_in
, src
);
533 layer
->src
.br
= calc_bottomright(size_in
, src
);
535 layer
->dst
.tl
= calc_topleft(size_out
, *dst
);
536 layer
->dst
.br
= calc_bottomright(size_out
, *dst
);
537 layer
->custom_dest_rect
= 1;
539 layer
->dst
.tl
.x
= layer
->dst
.tl
.y
= 0.f
;
540 layer
->dst
.br
.x
= layer
->dst
.br
.y
= 1.f
;
541 layer
->custom_dest_rect
= 0;
546 gen_rect_verts(struct vertex4f
*vb
, struct vl_compositor_layer
*layer
, float w
, float h
)
550 vb
[0].x
= layer
->dst
.tl
.x
/ w
;
551 vb
[0].y
= layer
->dst
.tl
.y
/ h
;
552 vb
[0].z
= layer
->src
.tl
.x
;
553 vb
[0].w
= layer
->src
.tl
.y
;
555 vb
[1].x
= layer
->dst
.br
.x
/ w
;
556 vb
[1].y
= layer
->dst
.tl
.y
/ h
;
557 vb
[1].z
= layer
->src
.br
.x
;
558 vb
[1].w
= layer
->src
.tl
.y
;
560 vb
[2].x
= layer
->dst
.br
.x
/ w
;
561 vb
[2].y
= layer
->dst
.br
.y
/ h
;
562 vb
[2].z
= layer
->src
.br
.x
;
563 vb
[2].w
= layer
->src
.br
.y
;
565 vb
[3].x
= layer
->dst
.tl
.x
/ w
;
566 vb
[3].y
= layer
->dst
.br
.y
/ h
;
567 vb
[3].z
= layer
->src
.tl
.x
;
568 vb
[3].w
= layer
->src
.br
.y
;
572 gen_vertex_data(struct vl_compositor
*c
, float w
, float h
)
575 struct pipe_transfer
*buf_transfer
;
580 vb
= pipe_buffer_map(c
->pipe
, c
->vertex_buf
.buffer
,
581 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
| PIPE_TRANSFER_DONTBLOCK
,
585 // If buffer is still locked from last draw create a new one
586 create_vertex_buffer(c
);
587 vb
= pipe_buffer_map(c
->pipe
, c
->vertex_buf
.buffer
,
588 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
592 for (i
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; i
++) {
593 if (c
->used_layers
& (1 << i
)) {
594 struct vl_compositor_layer
*layer
= &c
->layers
[i
];
595 if (layer
->custom_dest_rect
)
596 gen_rect_verts(vb
, layer
, w
, h
);
598 gen_rect_verts(vb
, layer
, 1.f
, 1.f
);
601 if (layer
->clearing
&&
602 (!layer
->custom_dest_rect
||
603 (c
->dirty_tl
.x
>= layer
->dst
.tl
.x
/w
&&
604 c
->dirty_tl
.y
>= layer
->dst
.tl
.y
/h
&&
605 c
->dirty_br
.x
<= layer
->dst
.br
.x
/w
&&
606 c
->dirty_br
.y
<= layer
->dst
.br
.y
/h
))) {
607 // We clear the dirty area anyway, no need for clear_render_target
608 c
->dirty_tl
.x
= c
->dirty_tl
.y
= 1.0f
;
609 c
->dirty_br
.x
= c
->dirty_br
.y
= 0.0f
;
614 pipe_buffer_unmap(c
->pipe
, buf_transfer
);
618 draw_layers(struct vl_compositor
*c
, float w
, float h
)
620 unsigned vb_index
, i
;
624 for (i
= 0, vb_index
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; ++i
) {
625 if (c
->used_layers
& (1 << i
)) {
626 struct vl_compositor_layer
*layer
= &c
->layers
[i
];
627 struct pipe_sampler_view
**samplers
= &layer
->sampler_views
[0];
628 unsigned num_sampler_views
= !samplers
[1] ? 1 : !samplers
[2] ? 2 : 3;
630 c
->pipe
->bind_blend_state(c
->pipe
, layer
->blend
);
631 c
->pipe
->bind_fs_state(c
->pipe
, layer
->fs
);
632 c
->pipe
->bind_fragment_sampler_states(c
->pipe
, num_sampler_views
, layer
->samplers
);
633 c
->pipe
->set_fragment_sampler_views(c
->pipe
, num_sampler_views
, samplers
);
634 util_draw_arrays(c
->pipe
, PIPE_PRIM_QUADS
, vb_index
* 4, 4);
637 // Remember the currently drawn area as dirty for the next draw command
638 if (layer
->custom_dest_rect
) {
639 c
->dirty_tl
.x
= MIN2(layer
->dst
.tl
.x
/w
, c
->dirty_tl
.x
);
640 c
->dirty_tl
.y
= MIN2(layer
->dst
.tl
.y
/h
, c
->dirty_tl
.y
);
641 c
->dirty_br
.x
= MAX2(layer
->dst
.br
.x
/w
, c
->dirty_br
.x
);
642 c
->dirty_br
.y
= MAX2(layer
->dst
.br
.y
/h
, c
->dirty_br
.y
);
654 vl_compositor_reset_dirty_area(struct vl_compositor
*c
)
658 c
->dirty_tl
.x
= c
->dirty_tl
.y
= 0.0f
;
659 c
->dirty_br
.x
= c
->dirty_br
.y
= 1.0f
;
663 vl_compositor_set_clear_color(struct vl_compositor
*c
, union pipe_color_union
*color
)
667 c
->clear_color
= *color
;
671 vl_compositor_get_clear_color(struct vl_compositor
*c
, union pipe_color_union
*color
)
676 *color
= c
->clear_color
;
680 vl_compositor_clear_layers(struct vl_compositor
*c
)
687 for ( i
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; ++i
) {
688 c
->layers
[i
].clearing
= i
? false : true;
689 c
->layers
[i
].blend
= i
? c
->blend_add
: c
->blend_clear
;
690 c
->layers
[i
].fs
= NULL
;
691 for ( j
= 0; j
< 3; j
++)
692 pipe_sampler_view_reference(&c
->layers
[i
].sampler_views
[j
], NULL
);
697 cleanup_video(struct vl_compositor
*c
)
700 for (i
= 0; i
< 3; ++i
) {
703 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_weave
[i
]);
705 if (c
->fs_video_buffer2
)
706 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_video_buffer2
);
707 if (c
->fs_video_buffer3
)
708 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_video_buffer3
);
709 pipe_surface_reference(&c
->video_surf
[0], NULL
);
710 pipe_surface_reference(&c
->video_surf
[1], NULL
);
711 pipe_sampler_view_reference(&c
->video_sv
[0], NULL
);
712 pipe_sampler_view_reference(&c
->video_sv
[1], NULL
);
713 pipe_resource_reference(&c
->video_y
, NULL
);
714 pipe_resource_reference(&c
->video_cbcr
, NULL
);
718 vl_compositor_cleanup(struct vl_compositor
*c
)
722 vl_compositor_clear_layers(c
);
725 cleanup_pipe_state(c
);
730 vl_compositor_set_csc_matrix(struct vl_compositor
*c
, const float matrix
[16])
732 struct pipe_transfer
*buf_transfer
;
738 pipe_buffer_map(c
->pipe
, c
->csc_matrix
,
739 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
745 pipe_buffer_unmap(c
->pipe
, buf_transfer
);
749 vl_compositor_set_layer_blend(struct vl_compositor
*c
,
750 unsigned layer
, void *blend
,
755 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
757 c
->layers
[layer
].clearing
= is_clearing
;
758 c
->layers
[layer
].blend
= blend
;
762 static void gen_vertex_data_video(struct vl_compositor
*c
) {
764 struct pipe_transfer
*buf_transfer
;
765 vb
= pipe_buffer_map(c
->pipe
, c
->vertex_buf
.buffer
,
766 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
| PIPE_TRANSFER_DONTBLOCK
,
770 // If buffer is still locked from last draw create a new one
771 create_vertex_buffer(c
);
772 vb
= pipe_buffer_map(c
->pipe
, c
->vertex_buf
.buffer
,
773 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
790 pipe_buffer_unmap(c
->pipe
, buf_transfer
);
794 vl_compositor_render_video(struct vl_compositor
*c
,
795 struct pipe_video_buffer
*buffer
)
797 struct pipe_sampler_view
**sv
;
798 struct pipe_scissor_state scissor
;
799 sv
= buffer
->get_sampler_view_planes(buffer
, 1);
802 for (i
= 0; i
< 4; ++i
)
803 samplers
[i
] = c
->sampler_nearest
;
806 gen_vertex_data_video(c
);
807 for (i
= 0; i
< 2; ++i
) {
808 struct pipe_surface
*dst_surface
= c
->video_surf
[i
];
810 unsigned num_sampler_views
;
812 num_sampler_views
= 2;
814 num_sampler_views
= 2 * (1 + !!sv
[4]);
816 c
->fb_state
.width
= dst_surface
->width
;
817 c
->fb_state
.height
= dst_surface
->height
;
818 c
->fb_state
.cbufs
[0] = dst_surface
;
820 c
->viewport
.scale
[0] = sv
[2*i
]->texture
->width0
;
821 c
->viewport
.scale
[1] = sv
[2*i
]->texture
->height0
* 2;
822 c
->viewport
.translate
[0] = 0;
823 c
->viewport
.translate
[1] = 0;
827 scissor
.maxx
= dst_surface
->width
;
828 scissor
.maxy
= dst_surface
->height
;
830 c
->pipe
->set_scissor_state(c
->pipe
, &scissor
);
831 c
->pipe
->set_framebuffer_state(c
->pipe
, &c
->fb_state
);
832 c
->pipe
->set_viewport_state(c
->pipe
, &c
->viewport
);
833 c
->pipe
->bind_vs_state(c
->pipe
, c
->vs
);
834 c
->pipe
->set_vertex_buffers(c
->pipe
, 1, &c
->vertex_buf
);
835 c
->pipe
->bind_vertex_elements_state(c
->pipe
, c
->vertex_elems_state
);
836 c
->pipe
->bind_rasterizer_state(c
->pipe
, c
->rast
);
838 c
->pipe
->bind_blend_state(c
->pipe
, c
->blend_clear
);
840 c
->pipe
->bind_fs_state(c
->pipe
, c
->fs_weave
[0]);
842 c
->pipe
->bind_fs_state(c
->pipe
, c
->fs_weave
[1 + !!sv
[4]]);
843 c
->pipe
->bind_fragment_sampler_states(c
->pipe
, num_sampler_views
, samplers
);
844 c
->pipe
->set_fragment_sampler_views(c
->pipe
, num_sampler_views
, &sv
[2*i
]);
845 util_draw_arrays(c
->pipe
, PIPE_PRIM_TRIANGLES
, 0, 3);
850 vl_compositor_set_buffer_layer(struct vl_compositor
*c
, unsigned layer
,
851 enum pipe_video_picture_structure field
,
852 struct pipe_video_buffer
*buffer
,
853 struct pipe_video_rect
*src_rect
,
854 struct pipe_video_rect
*dst_rect
,
856 struct pipe_video_buffer
**past
,
857 unsigned future_count
,
858 struct pipe_video_buffer
**future
)
860 struct pipe_sampler_view
**sampler_views
, *sv
[2][3];
861 struct pipe_video_rect rect
;
865 assert(c
->video_w
<= buffer
->width
&& c
->video_h
<= buffer
->height
);
866 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
868 if (field
== PIPE_VIDEO_PICTURE_STRUCTURE_FRAME
) {
869 sampler_views
= buffer
->get_sampler_view_planes(buffer
, 0);
870 if (!sampler_views
) {
871 sampler_views
= c
->video_sv
;
872 vl_compositor_render_video(c
, buffer
);
873 assert(!sampler_views
[2]);
876 int top
= field
== PIPE_VIDEO_PICTURE_STRUCTURE_FIELD_TOP
;
877 sampler_views
= buffer
->get_sampler_view_planes(buffer
, 1);
878 assert(sampler_views
);
883 c
->used_layers
|= 1 << layer
;
890 for (i
= 0; i
< 3; ++i
) {
891 c
->layers
[layer
].samplers
[i
] = c
->sampler_linear
;
892 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[i
], sampler_views
[i
]);
894 if (sampler_views
[2])
895 c
->layers
[layer
].fs
= c
->fs_video_buffer3
;
897 c
->layers
[layer
].fs
= c
->fs_video_buffer2
;
898 assert(sampler_views
[1]);
900 calc_src_and_dst(&c
->layers
[layer
],
901 sampler_views
[0]->texture
->width0
,
902 sampler_views
[0]->texture
->height0
,
903 *src_rect
, dst_rect
);
907 vl_compositor_set_palette_layer(struct vl_compositor
*c
,
909 struct pipe_sampler_view
*indexes
,
910 struct pipe_sampler_view
*palette
,
911 struct pipe_video_rect
*src_rect
,
912 struct pipe_video_rect
*dst_rect
,
913 bool include_color_conversion
)
915 assert(c
&& indexes
&& palette
);
917 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
919 c
->used_layers
|= 1 << layer
;
921 c
->layers
[layer
].fs
= include_color_conversion
?
922 c
->fs_palette
.yuv
: c
->fs_palette
.rgb
;
924 c
->layers
[layer
].samplers
[0] = c
->sampler_linear
;
925 c
->layers
[layer
].samplers
[1] = c
->sampler_nearest
;
926 c
->layers
[layer
].samplers
[2] = NULL
;
927 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[0], indexes
);
928 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[1], palette
);
929 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[2], NULL
);
930 calc_src_and_dst(&c
->layers
[layer
], indexes
->texture
->width0
, indexes
->texture
->height0
,
931 src_rect
? *src_rect
: default_rect(&c
->layers
[layer
]),
936 vl_compositor_set_rgba_layer(struct vl_compositor
*c
,
938 struct pipe_sampler_view
*rgba
,
939 struct pipe_video_rect
*src_rect
,
940 struct pipe_video_rect
*dst_rect
)
944 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
946 c
->used_layers
|= 1 << layer
;
947 c
->layers
[layer
].fs
= c
->fs_rgba
;
948 c
->layers
[layer
].samplers
[0] = c
->sampler_linear
;
949 c
->layers
[layer
].samplers
[1] = NULL
;
950 c
->layers
[layer
].samplers
[2] = NULL
;
951 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[0], rgba
);
952 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[1], NULL
);
953 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[2], NULL
);
954 calc_src_and_dst(&c
->layers
[layer
], rgba
->texture
->width0
, rgba
->texture
->height0
,
955 src_rect
? *src_rect
: default_rect(&c
->layers
[layer
]),
960 vl_compositor_render(struct vl_compositor
*c
,
961 struct pipe_surface
*dst_surface
,
962 struct pipe_video_rect
*dst_area
,
963 struct pipe_video_rect
*dst_clip
,
964 bool clear_dirty_area
)
966 struct pipe_scissor_state scissor
;
971 c
->fb_state
.width
= dst_surface
->width
;
972 c
->fb_state
.height
= dst_surface
->height
;
973 c
->fb_state
.cbufs
[0] = dst_surface
;
976 c
->viewport
.scale
[0] = dst_area
->w
;
977 c
->viewport
.scale
[1] = dst_area
->h
;
978 c
->viewport
.translate
[0] = dst_area
->x
;
979 c
->viewport
.translate
[1] = dst_area
->y
;
981 c
->viewport
.scale
[0] = dst_surface
->width
;
982 c
->viewport
.scale
[1] = dst_surface
->height
;
983 c
->viewport
.translate
[0] = 0;
984 c
->viewport
.translate
[1] = 0;
988 scissor
.minx
= dst_clip
->x
;
989 scissor
.miny
= dst_clip
->y
;
990 scissor
.maxx
= dst_clip
->x
+ dst_clip
->w
;
991 scissor
.maxy
= dst_clip
->y
+ dst_clip
->h
;
995 scissor
.maxx
= dst_surface
->width
;
996 scissor
.maxy
= dst_surface
->height
;
999 gen_vertex_data(c
, dst_surface
->width
, dst_surface
->height
);
1001 if (clear_dirty_area
&& (c
->dirty_tl
.x
< c
->dirty_br
.x
||
1002 c
->dirty_tl
.y
< c
->dirty_br
.y
)) {
1003 util_clear_render_target(c
->pipe
, dst_surface
, &c
->clear_color
,
1004 0, 0, dst_surface
->width
, dst_surface
->height
);
1005 c
->dirty_tl
.x
= c
->dirty_tl
.y
= 1.0f
;
1006 c
->dirty_br
.x
= c
->dirty_br
.y
= 0.0f
;
1009 c
->pipe
->set_scissor_state(c
->pipe
, &scissor
);
1010 c
->pipe
->set_framebuffer_state(c
->pipe
, &c
->fb_state
);
1011 c
->pipe
->set_viewport_state(c
->pipe
, &c
->viewport
);
1012 c
->pipe
->bind_vs_state(c
->pipe
, c
->vs
);
1013 c
->pipe
->set_vertex_buffers(c
->pipe
, 1, &c
->vertex_buf
);
1014 c
->pipe
->bind_vertex_elements_state(c
->pipe
, c
->vertex_elems_state
);
1015 c
->pipe
->set_constant_buffer(c
->pipe
, PIPE_SHADER_FRAGMENT
, 0, c
->csc_matrix
);
1016 c
->pipe
->bind_rasterizer_state(c
->pipe
, c
->rast
);
1018 draw_layers(c
, dst_surface
->width
, dst_surface
->height
);
1022 vl_compositor_init(struct vl_compositor
*c
, struct pipe_context
*pipe
)
1024 csc_matrix csc_matrix
;
1028 if (!init_pipe_state(c
))
1031 if (!init_shaders(c
)) {
1032 cleanup_pipe_state(c
);
1036 if (!init_buffers(c
)) {
1038 cleanup_pipe_state(c
);
1042 vl_compositor_clear_layers(c
);
1044 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY
, NULL
, true, csc_matrix
);
1045 vl_compositor_set_csc_matrix(c
, csc_matrix
);
1047 c
->clear_color
.f
[0] = c
->clear_color
.f
[1] = 0.0f
;
1048 c
->clear_color
.f
[2] = c
->clear_color
.f
[3] = 0.0f
;
1049 vl_compositor_reset_dirty_area(c
);
1055 vl_compositor_init_video(struct vl_compositor
*c
, struct pipe_context
*pipe
,
1056 enum pipe_video_chroma_format chroma
, unsigned w
, unsigned h
)
1058 struct pipe_resource templ
;
1059 struct pipe_sampler_view sv_templ
;
1060 struct pipe_surface surf_templ
;
1061 if (!vl_compositor_init(c
, pipe
))
1066 c
->fs_video_buffer2
= create_frag_shader_video_buffer(c
, 2);
1067 if (!c
->fs_video_buffer2
) {
1068 debug_printf("Unable to create YCbCr-to-RGB fragment shader for 2 planes.\n");
1071 c
->fs_video_buffer3
= create_frag_shader_video_buffer(c
, 3);
1072 if (!c
->fs_video_buffer3
) {
1073 debug_printf("Unable to create YCbCr-to-RGB fragment shader for 3 planes.\n");
1076 c
->fs_weave
[0] = create_frag_shader_deint_planar_weave(c
, 1, 1);
1077 c
->fs_weave
[1] = create_frag_shader_deint_planar_weave(c
, 0, 2); // CbCr woven
1078 c
->fs_weave
[2] = create_frag_shader_deint_planar_weave(c
, 0, 1); // Cb, Cr separate
1079 if (!c
->fs_weave
[0] || !c
->fs_weave
[1] || !c
->fs_weave
[2]) {
1080 debug_printf("Unable to create weave fragment shaders.\n");
1083 memset(&templ
, 0, sizeof(templ
));
1084 templ
.target
= PIPE_TEXTURE_2D
;
1085 templ
.format
= PIPE_FORMAT_R8_UNORM
;
1089 templ
.array_size
= 1;
1090 templ
.bind
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
;
1091 templ
.usage
= PIPE_USAGE_STATIC
;
1092 c
->video_y
= pipe
->screen
->resource_create(pipe
->screen
, &templ
);
1094 debug_printf("Could not create deinterlaced temp frame for luma\n");
1097 if (chroma
!= PIPE_VIDEO_CHROMA_FORMAT_444
)
1099 if (chroma
== PIPE_VIDEO_CHROMA_FORMAT_420
)
1101 templ
.format
= PIPE_FORMAT_R8G8_UNORM
;
1102 c
->video_cbcr
= pipe
->screen
->resource_create(pipe
->screen
, &templ
);
1103 if (!c
->video_cbcr
) {
1104 debug_printf("Could not create deinterlaced temp frame for chroma\n");
1107 memset(&sv_templ
, 0, sizeof(sv_templ
));
1108 u_sampler_view_default_template(&sv_templ
, c
->video_y
, c
->video_y
->format
);
1109 sv_templ
.swizzle_a
= sv_templ
.swizzle_b
= sv_templ
.swizzle_g
= sv_templ
.swizzle_r
;
1110 c
->video_sv
[0] = pipe
->create_sampler_view(pipe
, c
->video_y
, &sv_templ
);
1112 memset(&sv_templ
, 0, sizeof(sv_templ
));
1113 u_sampler_view_default_template(&sv_templ
, c
->video_cbcr
, c
->video_cbcr
->format
);
1114 sv_templ
.swizzle_b
= PIPE_SWIZZLE_GREEN
;
1115 sv_templ
.swizzle_g
= PIPE_SWIZZLE_RED
;
1116 c
->video_sv
[1] = pipe
->create_sampler_view(pipe
, c
->video_cbcr
, &sv_templ
);
1117 if (!c
->video_sv
[0] || !c
->video_sv
[1]) {
1118 debug_printf("Could not create temp video sampler views\n");
1121 memset(&surf_templ
, 0, sizeof(surf_templ
));
1122 surf_templ
.usage
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
;
1123 surf_templ
.format
= c
->video_y
->format
;
1124 c
->video_surf
[0] = pipe
->create_surface(pipe
, c
->video_y
, &surf_templ
);
1125 surf_templ
.format
= c
->video_cbcr
->format
;
1126 c
->video_surf
[1] = pipe
->create_surface(pipe
, c
->video_cbcr
, &surf_templ
);
1127 if (!c
->video_surf
[0] || !c
->video_surf
[1]) {
1128 debug_printf("Could not create temp video surface\n");
1135 vl_compositor_cleanup(c
);