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 **************************************************************************/
28 #include "vl_compositor.h"
29 #include "util/u_draw.h"
31 #include <pipe/p_context.h>
32 #include <util/u_inlines.h>
33 #include <util/u_memory.h>
34 #include <util/u_keymap.h>
35 #include <util/u_draw.h>
36 #include <util/u_sampler.h>
37 #include <tgsi/tgsi_ureg.h>
41 typedef float csc_matrix
[16];
44 create_vert_shader(struct vl_compositor
*c
)
46 struct ureg_program
*shader
;
47 struct ureg_src vpos
, vtex
;
48 struct ureg_dst o_vpos
, o_vtex
;
50 shader
= ureg_create(TGSI_PROCESSOR_VERTEX
);
54 vpos
= ureg_DECL_vs_input(shader
, 0);
55 vtex
= ureg_DECL_vs_input(shader
, 1);
56 o_vpos
= ureg_DECL_output(shader
, TGSI_SEMANTIC_POSITION
, 0);
57 o_vtex
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, 1);
63 ureg_MOV(shader
, o_vpos
, vpos
);
64 ureg_MOV(shader
, o_vtex
, vtex
);
68 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
72 create_frag_shader_video_buffer(struct vl_compositor
*c
)
74 struct ureg_program
*shader
;
76 struct ureg_src csc
[3];
77 struct ureg_src sampler
[3];
78 struct ureg_dst texel
;
79 struct ureg_dst fragment
;
82 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
86 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
87 for (i
= 0; i
< 3; ++i
) {
88 csc
[i
] = ureg_DECL_constant(shader
, i
);
89 sampler
[i
] = ureg_DECL_sampler(shader
, i
);
91 texel
= ureg_DECL_temporary(shader
);
92 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
95 * texel.xyz = tex(tc, sampler[i])
96 * fragment = csc * texel
98 for (i
= 0; i
< 3; ++i
)
99 ureg_TEX(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_X
<< i
), TGSI_TEXTURE_2D
, tc
, sampler
[i
]);
101 ureg_MOV(shader
, ureg_writemask(texel
, TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
103 for (i
= 0; i
< 3; ++i
)
104 ureg_DP4(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_X
<< i
), csc
[i
], ureg_src(texel
));
106 ureg_MOV(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_W
), ureg_imm1f(shader
, 1.0f
));
108 ureg_release_temporary(shader
, texel
);
111 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
115 create_frag_shader_palette(struct vl_compositor
*c
)
117 struct ureg_program
*shader
;
119 struct ureg_src sampler
;
120 struct ureg_src palette
;
121 struct ureg_dst texel
;
122 struct ureg_dst fragment
;
124 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
128 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
129 sampler
= ureg_DECL_sampler(shader
, 0);
130 palette
= ureg_DECL_sampler(shader
, 1);
131 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
132 texel
= ureg_DECL_temporary(shader
);
135 * texel = tex(tc, sampler)
136 * fragment.xyz = tex(texel, palette)
137 * fragment.a = texel.a
139 ureg_TEX(shader
, texel
, TGSI_TEXTURE_2D
, tc
, sampler
);
140 ureg_TEX(shader
, fragment
, TGSI_TEXTURE_1D
, ureg_src(texel
), palette
);
141 ureg_MOV(shader
, ureg_writemask(fragment
, TGSI_WRITEMASK_W
), ureg_src(texel
));
143 ureg_release_temporary(shader
, texel
);
146 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
150 create_frag_shader_rgba(struct vl_compositor
*c
)
152 struct ureg_program
*shader
;
154 struct ureg_src sampler
;
155 struct ureg_dst fragment
;
157 shader
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
161 tc
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, 1, TGSI_INTERPOLATE_LINEAR
);
162 sampler
= ureg_DECL_sampler(shader
, 0);
163 fragment
= ureg_DECL_output(shader
, TGSI_SEMANTIC_COLOR
, 0);
166 * fragment = tex(tc, sampler)
168 ureg_TEX(shader
, fragment
, TGSI_TEXTURE_2D
, tc
, sampler
);
171 return ureg_create_shader_and_destroy(shader
, c
->pipe
);
175 init_shaders(struct vl_compositor
*c
)
179 c
->vs
= create_vert_shader(c
);
181 debug_printf("Unable to create vertex shader.\n");
185 c
->fs_video_buffer
= create_frag_shader_video_buffer(c
);
186 if (!c
->fs_video_buffer
) {
187 debug_printf("Unable to create YCbCr-to-RGB fragment shader.\n");
191 c
->fs_palette
= create_frag_shader_palette(c
);
192 if (!c
->fs_palette
) {
193 debug_printf("Unable to create Palette-to-RGB fragment shader.\n");
197 c
->fs_rgba
= create_frag_shader_rgba(c
);
199 debug_printf("Unable to create RGB-to-RGB fragment shader.\n");
206 static void cleanup_shaders(struct vl_compositor
*c
)
210 c
->pipe
->delete_vs_state(c
->pipe
, c
->vs
);
211 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_video_buffer
);
212 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_palette
);
213 c
->pipe
->delete_fs_state(c
->pipe
, c
->fs_rgba
);
217 init_pipe_state(struct vl_compositor
*c
)
219 struct pipe_rasterizer_state rast
;
220 struct pipe_sampler_state sampler
;
221 struct pipe_blend_state blend
;
225 c
->fb_state
.nr_cbufs
= 1;
226 c
->fb_state
.zsbuf
= NULL
;
228 c
->viewport
.scale
[2] = 1;
229 c
->viewport
.scale
[3] = 1;
230 c
->viewport
.translate
[0] = 0;
231 c
->viewport
.translate
[1] = 0;
232 c
->viewport
.translate
[2] = 0;
233 c
->viewport
.translate
[3] = 0;
235 memset(&sampler
, 0, sizeof(sampler
));
236 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
237 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
238 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
239 sampler
.min_img_filter
= PIPE_TEX_FILTER_LINEAR
;
240 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
241 sampler
.mag_img_filter
= PIPE_TEX_FILTER_LINEAR
;
242 sampler
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
243 sampler
.compare_func
= PIPE_FUNC_ALWAYS
;
244 sampler
.normalized_coords
= 1;
245 /*sampler.lod_bias = ;*/
246 /*sampler.min_lod = ;*/
247 /*sampler.max_lod = ;*/
248 /*sampler.border_color[i] = ;*/
249 /*sampler.max_anisotropy = ;*/
250 c
->sampler
= c
->pipe
->create_sampler_state(c
->pipe
, &sampler
);
252 memset(&blend
, 0, sizeof blend
);
253 blend
.independent_blend_enable
= 0;
254 blend
.rt
[0].blend_enable
= 1;
255 blend
.rt
[0].rgb_func
= PIPE_BLEND_ADD
;
256 blend
.rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_SRC_ALPHA
;
257 blend
.rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_INV_SRC_ALPHA
;
258 blend
.rt
[0].alpha_func
= PIPE_BLEND_ADD
;
259 blend
.rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
260 blend
.rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ONE
;
261 blend
.logicop_enable
= 0;
262 blend
.logicop_func
= PIPE_LOGICOP_CLEAR
;
263 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
265 c
->blend
= c
->pipe
->create_blend_state(c
->pipe
, &blend
);
267 memset(&rast
, 0, sizeof rast
);
270 rast
.cull_face
= PIPE_FACE_NONE
;
271 rast
.fill_back
= PIPE_POLYGON_MODE_FILL
;
272 rast
.fill_front
= PIPE_POLYGON_MODE_FILL
;
275 rast
.point_size_per_vertex
= 1;
276 rast
.offset_units
= 1;
277 rast
.offset_scale
= 1;
278 rast
.gl_rasterization_rules
= 1;
280 c
->rast
= c
->pipe
->create_rasterizer_state(c
->pipe
, &rast
);
285 static void cleanup_pipe_state(struct vl_compositor
*c
)
289 c
->pipe
->delete_sampler_state(c
->pipe
, c
->sampler
);
290 c
->pipe
->delete_blend_state(c
->pipe
, c
->blend
);
291 c
->pipe
->delete_rasterizer_state(c
->pipe
, c
->rast
);
295 init_buffers(struct vl_compositor
*c
)
297 struct pipe_vertex_element vertex_elems
[2];
302 * Create our vertex buffer and vertex buffer elements
304 c
->vertex_buf
.stride
= sizeof(struct vertex4f
);
305 c
->vertex_buf
.buffer_offset
= 0;
306 c
->vertex_buf
.buffer
= pipe_buffer_create
309 PIPE_BIND_VERTEX_BUFFER
,
311 sizeof(struct vertex4f
) * (VL_COMPOSITOR_MAX_LAYERS
+ 1) * 4
314 vertex_elems
[0].src_offset
= 0;
315 vertex_elems
[0].instance_divisor
= 0;
316 vertex_elems
[0].vertex_buffer_index
= 0;
317 vertex_elems
[0].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
318 vertex_elems
[1].src_offset
= sizeof(struct vertex2f
);
319 vertex_elems
[1].instance_divisor
= 0;
320 vertex_elems
[1].vertex_buffer_index
= 0;
321 vertex_elems
[1].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
322 c
->vertex_elems_state
= c
->pipe
->create_vertex_elements_state(c
->pipe
, 2, vertex_elems
);
325 * Create our fragment shader's constant buffer
326 * Const buffer contains the color conversion matrix and bias vectors
328 /* XXX: Create with IMMUTABLE/STATIC... although it does change every once in a long while... */
329 c
->csc_matrix
= pipe_buffer_create
332 PIPE_BIND_CONSTANT_BUFFER
,
341 cleanup_buffers(struct vl_compositor
*c
)
345 c
->pipe
->delete_vertex_elements_state(c
->pipe
, c
->vertex_elems_state
);
346 pipe_resource_reference(&c
->vertex_buf
.buffer
, NULL
);
347 pipe_resource_reference(&c
->csc_matrix
, NULL
);
350 static inline struct pipe_video_rect
351 default_rect(struct vl_compositor_layer
*layer
)
353 struct pipe_resource
*res
= layer
->sampler_views
[0]->texture
;
354 struct pipe_video_rect rect
= { 0, 0, res
->width0
, res
->height0
};
359 gen_rect_verts(struct vertex4f
*vb
,
360 struct pipe_video_rect
*src_rect
,
361 struct vertex2f
*src_inv_size
,
362 struct pipe_video_rect
*dst_rect
,
363 struct vertex2f
*dst_inv_size
)
366 assert(src_rect
&& src_inv_size
);
367 assert(dst_rect
&& dst_inv_size
);
369 vb
[0].x
= dst_rect
->x
* dst_inv_size
->x
;
370 vb
[0].y
= dst_rect
->y
* dst_inv_size
->y
;
371 vb
[0].z
= src_rect
->x
* src_inv_size
->x
;
372 vb
[0].w
= src_rect
->y
* src_inv_size
->y
;
374 vb
[1].x
= (dst_rect
->x
+ dst_rect
->w
) * dst_inv_size
->x
;
375 vb
[1].y
= dst_rect
->y
* dst_inv_size
->y
;
376 vb
[1].z
= (src_rect
->x
+ src_rect
->w
) * src_inv_size
->x
;
377 vb
[1].w
= src_rect
->y
* src_inv_size
->y
;
379 vb
[2].x
= (dst_rect
->x
+ dst_rect
->w
) * dst_inv_size
->x
;
380 vb
[2].y
= (dst_rect
->y
+ dst_rect
->h
) * dst_inv_size
->y
;
381 vb
[2].z
= (src_rect
->x
+ src_rect
->w
) * src_inv_size
->x
;
382 vb
[2].w
= (src_rect
->y
+ src_rect
->h
) * src_inv_size
->y
;
384 vb
[3].x
= dst_rect
->x
* dst_inv_size
->x
;
385 vb
[3].y
= (dst_rect
->y
+ dst_rect
->h
) * dst_inv_size
->y
;
386 vb
[3].z
= src_rect
->x
* src_inv_size
->x
;
387 vb
[3].w
= (src_rect
->y
+ src_rect
->h
) * src_inv_size
->y
;
391 gen_vertex_data(struct vl_compositor
*c
)
394 struct pipe_transfer
*buf_transfer
;
399 vb
= pipe_buffer_map(c
->pipe
, c
->vertex_buf
.buffer
,
400 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
| PIPE_TRANSFER_DONTBLOCK
,
406 for (i
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; i
++) {
407 if (c
->used_layers
& (1 << i
)) {
408 struct pipe_sampler_view
*sv
= c
->layers
[i
].sampler_views
[0];
409 struct vertex2f src_inv_size
= {1.0f
/ sv
->texture
->width0
, 1.0f
/ sv
->texture
->height0
};
411 gen_rect_verts(vb
, &c
->layers
[i
].src_rect
, &src_inv_size
, &c
->layers
[i
].dst_rect
, &src_inv_size
);
417 pipe_buffer_unmap(c
->pipe
, buf_transfer
);
421 draw_layers(struct vl_compositor
*c
)
423 unsigned vb_index
, i
;
427 for (i
= 0, vb_index
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; ++i
) {
428 if (c
->used_layers
& (1 << i
)) {
429 struct pipe_sampler_view
**samplers
= &c
->layers
[i
].sampler_views
[0];
430 unsigned num_sampler_views
= !samplers
[1] ? 1 : !samplers
[2] ? 2 : 3;
432 c
->pipe
->bind_fs_state(c
->pipe
, c
->layers
[i
].fs
);
433 c
->pipe
->set_fragment_sampler_views(c
->pipe
, num_sampler_views
, samplers
);
434 util_draw_arrays(c
->pipe
, PIPE_PRIM_QUADS
, vb_index
* 4, 4);
441 vl_compositor_clear_layers(struct pipe_video_compositor
*compositor
)
443 struct vl_compositor
*c
= (struct vl_compositor
*)compositor
;
449 for ( i
= 0; i
< VL_COMPOSITOR_MAX_LAYERS
; ++i
) {
450 c
->layers
[i
].fs
= NULL
;
451 for ( j
= 0; j
< 3; j
++)
452 pipe_sampler_view_reference(&c
->layers
[i
].sampler_views
[j
], NULL
);
457 vl_compositor_destroy(struct pipe_video_compositor
*compositor
)
459 struct vl_compositor
*c
= (struct vl_compositor
*)compositor
;
462 vl_compositor_clear_layers(compositor
);
466 cleanup_pipe_state(c
);
472 vl_compositor_set_csc_matrix(struct pipe_video_compositor
*compositor
, const float matrix
[16])
474 struct vl_compositor
*c
= (struct vl_compositor
*)compositor
;
475 struct pipe_transfer
*buf_transfer
;
481 pipe_buffer_map(c
->pipe
, c
->csc_matrix
,
482 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
488 pipe_buffer_unmap(c
->pipe
, buf_transfer
);
492 vl_compositor_set_buffer_layer(struct pipe_video_compositor
*compositor
,
494 struct pipe_video_buffer
*buffer
,
495 struct pipe_video_rect
*src_rect
,
496 struct pipe_video_rect
*dst_rect
)
498 struct vl_compositor
*c
= (struct vl_compositor
*)compositor
;
499 struct pipe_sampler_view
**sampler_views
;
502 assert(compositor
&& buffer
);
504 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
506 c
->used_layers
|= 1 << layer
;
507 c
->layers
[layer
].fs
= c
->fs_video_buffer
;
509 sampler_views
= buffer
->get_sampler_views(buffer
);
510 for (i
= 0; i
< 3; ++i
)
511 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[i
], sampler_views
[i
]);
513 c
->layers
[layer
].src_rect
= src_rect
? *src_rect
: default_rect(&c
->layers
[layer
]);
514 c
->layers
[layer
].dst_rect
= dst_rect
? *dst_rect
: default_rect(&c
->layers
[layer
]);
518 vl_compositor_set_palette_layer(struct pipe_video_compositor
*compositor
,
520 struct pipe_sampler_view
*indexes
,
521 struct pipe_sampler_view
*palette
,
522 struct pipe_video_rect
*src_rect
,
523 struct pipe_video_rect
*dst_rect
)
525 struct vl_compositor
*c
= (struct vl_compositor
*)compositor
;
526 assert(compositor
&& indexes
&& palette
);
528 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
530 c
->used_layers
|= 1 << layer
;
531 c
->layers
[layer
].fs
= c
->fs_palette
;
532 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[0], indexes
);
533 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[1], palette
);
534 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[2], NULL
);
535 c
->layers
[layer
].src_rect
= src_rect
? *src_rect
: default_rect(&c
->layers
[layer
]);
536 c
->layers
[layer
].dst_rect
= dst_rect
? *dst_rect
: default_rect(&c
->layers
[layer
]);
540 vl_compositor_set_rgba_layer(struct pipe_video_compositor
*compositor
,
542 struct pipe_sampler_view
*rgba
,
543 struct pipe_video_rect
*src_rect
,
544 struct pipe_video_rect
*dst_rect
)
546 struct vl_compositor
*c
= (struct vl_compositor
*)compositor
;
547 assert(compositor
&& rgba
);
549 assert(layer
< VL_COMPOSITOR_MAX_LAYERS
);
551 c
->used_layers
|= 1 << layer
;
552 c
->layers
[layer
].fs
= c
->fs_rgba
;
553 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[0], rgba
);
554 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[1], NULL
);
555 pipe_sampler_view_reference(&c
->layers
[layer
].sampler_views
[2], NULL
);
556 c
->layers
[layer
].src_rect
= src_rect
? *src_rect
: default_rect(&c
->layers
[layer
]);
557 c
->layers
[layer
].dst_rect
= dst_rect
? *dst_rect
: default_rect(&c
->layers
[layer
]);
561 vl_compositor_render(struct pipe_video_compositor
*compositor
,
562 enum pipe_mpeg12_picture_type picture_type
,
563 struct pipe_surface
*dst_surface
,
564 struct pipe_video_rect
*dst_area
,
565 struct pipe_fence_handle
**fence
)
567 struct vl_compositor
*c
= (struct vl_compositor
*)compositor
;
568 struct pipe_scissor_state scissor
;
574 c
->fb_state
.width
= dst_surface
->width
;
575 c
->fb_state
.height
= dst_surface
->height
;
576 c
->fb_state
.cbufs
[0] = dst_surface
;
578 c
->viewport
.scale
[0] = dst_surface
->width
;
579 c
->viewport
.scale
[1] = dst_surface
->height
;
582 scissor
.minx
= dst_area
->x
;
583 scissor
.miny
= dst_area
->y
;
584 scissor
.maxx
= dst_area
->x
+ dst_area
->w
;
585 scissor
.maxy
= dst_area
->y
+ dst_area
->h
;
589 scissor
.maxx
= dst_surface
->width
;
590 scissor
.maxy
= dst_surface
->height
;
593 samplers
[0] = samplers
[1] = samplers
[2] = c
->sampler
;
597 c
->pipe
->set_scissor_state(c
->pipe
, &scissor
);
598 c
->pipe
->set_framebuffer_state(c
->pipe
, &c
->fb_state
);
599 c
->pipe
->set_viewport_state(c
->pipe
, &c
->viewport
);
600 c
->pipe
->bind_fragment_sampler_states(c
->pipe
, 3, &samplers
[0]);
601 c
->pipe
->bind_vs_state(c
->pipe
, c
->vs
);
602 c
->pipe
->set_vertex_buffers(c
->pipe
, 1, &c
->vertex_buf
);
603 c
->pipe
->bind_vertex_elements_state(c
->pipe
, c
->vertex_elems_state
);
604 c
->pipe
->set_constant_buffer(c
->pipe
, PIPE_SHADER_FRAGMENT
, 0, c
->csc_matrix
);
605 c
->pipe
->bind_blend_state(c
->pipe
, c
->blend
);
606 c
->pipe
->bind_rasterizer_state(c
->pipe
, c
->rast
);
610 c
->pipe
->flush(c
->pipe
, fence
);
613 struct pipe_video_compositor
*
614 vl_compositor_init(struct pipe_video_context
*vpipe
, struct pipe_context
*pipe
)
616 csc_matrix csc_matrix
;
617 struct vl_compositor
*compositor
;
619 compositor
= CALLOC_STRUCT(vl_compositor
);
621 compositor
->base
.context
= vpipe
;
622 compositor
->base
.destroy
= vl_compositor_destroy
;
623 compositor
->base
.set_csc_matrix
= vl_compositor_set_csc_matrix
;
624 compositor
->base
.clear_layers
= vl_compositor_clear_layers
;
625 compositor
->base
.set_buffer_layer
= vl_compositor_set_buffer_layer
;
626 compositor
->base
.set_palette_layer
= vl_compositor_set_palette_layer
;
627 compositor
->base
.set_rgba_layer
= vl_compositor_set_rgba_layer
;
628 compositor
->base
.render_picture
= vl_compositor_render
;
630 compositor
->pipe
= pipe
;
632 if (!init_pipe_state(compositor
))
635 if (!init_shaders(compositor
)) {
636 cleanup_pipe_state(compositor
);
639 if (!init_buffers(compositor
)) {
640 cleanup_shaders(compositor
);
641 cleanup_pipe_state(compositor
);
645 vl_compositor_clear_layers(&compositor
->base
);
647 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY
, NULL
, true, csc_matrix
);
648 vl_compositor_set_csc_matrix(&compositor
->base
, csc_matrix
);
650 return &compositor
->base
;