vl_compositor.c revision d9ad3aa3b9647f1ede2568600978af956ff32fff
1/************************************************************************** 2 * 3 * Copyright 2009 Younes Manton. 4 * All Rights Reserved. 5 * 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: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 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. 25 * 26 **************************************************************************/ 27 28#include "vl_compositor.h" 29#include "util/u_draw.h" 30#include <assert.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> 38#include "vl_csc.h" 39#include "vl_types.h" 40 41typedef float csc_matrix[16]; 42 43static void * 44create_vert_shader(struct vl_compositor *c) 45{ 46 struct ureg_program *shader; 47 struct ureg_src vpos, vtex; 48 struct ureg_dst o_vpos, o_vtex; 49 50 shader = ureg_create(TGSI_PROCESSOR_VERTEX); 51 if (!shader) 52 return false; 53 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); 58 59 /* 60 * o_vpos = vpos 61 * o_vtex = vtex 62 */ 63 ureg_MOV(shader, o_vpos, vpos); 64 ureg_MOV(shader, o_vtex, vtex); 65 66 ureg_END(shader); 67 68 return ureg_create_shader_and_destroy(shader, c->pipe); 69} 70 71static void * 72create_frag_shader_video_buffer(struct vl_compositor *c) 73{ 74 struct ureg_program *shader; 75 struct ureg_src tc; 76 struct ureg_src csc[3]; 77 struct ureg_src sampler[3]; 78 struct ureg_dst texel; 79 struct ureg_dst fragment; 80 unsigned i; 81 82 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); 83 if (!shader) 84 return false; 85 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); 90 } 91 texel = ureg_DECL_temporary(shader); 92 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); 93 94 /* 95 * texel.xyz = tex(tc, sampler[i]) 96 * fragment = csc * texel 97 */ 98 for (i = 0; i < 3; ++i) 99 ureg_TEX(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), TGSI_TEXTURE_2D, tc, sampler[i]); 100 101 ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f)); 102 103 for (i = 0; i < 3; ++i) 104 ureg_DP4(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(texel)); 105 106 ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f)); 107 108 ureg_release_temporary(shader, texel); 109 ureg_END(shader); 110 111 return ureg_create_shader_and_destroy(shader, c->pipe); 112} 113 114static void * 115create_frag_shader_palette(struct vl_compositor *c) 116{ 117 struct ureg_program *shader; 118 struct ureg_src tc; 119 struct ureg_src sampler; 120 struct ureg_src palette; 121 struct ureg_dst texel; 122 struct ureg_dst fragment; 123 124 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); 125 if (!shader) 126 return false; 127 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); 133 134 /* 135 * texel = tex(tc, sampler) 136 * fragment.xyz = tex(texel, palette) 137 * fragment.a = texel.a 138 */ 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)); 142 143 ureg_release_temporary(shader, texel); 144 ureg_END(shader); 145 146 return ureg_create_shader_and_destroy(shader, c->pipe); 147} 148 149static void * 150create_frag_shader_rgba(struct vl_compositor *c) 151{ 152 struct ureg_program *shader; 153 struct ureg_src tc; 154 struct ureg_src sampler; 155 struct ureg_dst fragment; 156 157 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); 158 if (!shader) 159 return false; 160 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); 164 165 /* 166 * fragment = tex(tc, sampler) 167 */ 168 ureg_TEX(shader, fragment, TGSI_TEXTURE_2D, tc, sampler); 169 ureg_END(shader); 170 171 return ureg_create_shader_and_destroy(shader, c->pipe); 172} 173 174static bool 175init_shaders(struct vl_compositor *c) 176{ 177 assert(c); 178 179 c->vs = create_vert_shader(c); 180 if (!c->vs) { 181 debug_printf("Unable to create vertex shader.\n"); 182 return false; 183 } 184 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"); 188 return false; 189 } 190 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"); 194 return false; 195 } 196 197 c->fs_rgba = create_frag_shader_rgba(c); 198 if (!c->fs_rgba) { 199 debug_printf("Unable to create RGB-to-RGB fragment shader.\n"); 200 return false; 201 } 202 203 return true; 204} 205 206static void cleanup_shaders(struct vl_compositor *c) 207{ 208 assert(c); 209 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); 214} 215 216static bool 217init_pipe_state(struct vl_compositor *c) 218{ 219 struct pipe_sampler_state sampler; 220 struct pipe_blend_state blend; 221 222 assert(c); 223 224 c->fb_state.nr_cbufs = 1; 225 c->fb_state.zsbuf = NULL; 226 227 c->viewport.scale[2] = 1; 228 c->viewport.scale[3] = 1; 229 c->viewport.translate[0] = 0; 230 c->viewport.translate[1] = 0; 231 c->viewport.translate[2] = 0; 232 c->viewport.translate[3] = 0; 233 234 memset(&sampler, 0, sizeof(sampler)); 235 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 236 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 237 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 238 sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR; 239 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 240 sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR; 241 sampler.compare_mode = PIPE_TEX_COMPARE_NONE; 242 sampler.compare_func = PIPE_FUNC_ALWAYS; 243 sampler.normalized_coords = 1; 244 /*sampler.lod_bias = ;*/ 245 /*sampler.min_lod = ;*/ 246 /*sampler.max_lod = ;*/ 247 /*sampler.border_color[i] = ;*/ 248 /*sampler.max_anisotropy = ;*/ 249 c->sampler = c->pipe->create_sampler_state(c->pipe, &sampler); 250 251 memset(&blend, 0, sizeof blend); 252 blend.independent_blend_enable = 0; 253 blend.rt[0].blend_enable = 1; 254 blend.rt[0].rgb_func = PIPE_BLEND_ADD; 255 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; 256 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; 257 blend.rt[0].alpha_func = PIPE_BLEND_ADD; 258 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 259 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; 260 blend.logicop_enable = 0; 261 blend.logicop_func = PIPE_LOGICOP_CLEAR; 262 blend.rt[0].colormask = PIPE_MASK_RGBA; 263 blend.dither = 0; 264 c->blend = c->pipe->create_blend_state(c->pipe, &blend); 265 266 return true; 267} 268 269static void cleanup_pipe_state(struct vl_compositor *c) 270{ 271 assert(c); 272 273 c->pipe->delete_sampler_state(c->pipe, c->sampler); 274 c->pipe->delete_blend_state(c->pipe, c->blend); 275} 276 277static bool 278init_buffers(struct vl_compositor *c) 279{ 280 struct pipe_vertex_element vertex_elems[2]; 281 282 assert(c); 283 284 /* 285 * Create our vertex buffer and vertex buffer elements 286 */ 287 c->vertex_buf.stride = sizeof(struct vertex4f); 288 c->vertex_buf.buffer_offset = 0; 289 /* XXX: Create with DYNAMIC or STREAM */ 290 c->vertex_buf.buffer = pipe_buffer_create 291 ( 292 c->pipe->screen, 293 PIPE_BIND_VERTEX_BUFFER, 294 PIPE_USAGE_STATIC, 295 sizeof(struct vertex4f) * (VL_COMPOSITOR_MAX_LAYERS + 1) * 4 296 ); 297 298 vertex_elems[0].src_offset = 0; 299 vertex_elems[0].instance_divisor = 0; 300 vertex_elems[0].vertex_buffer_index = 0; 301 vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT; 302 vertex_elems[1].src_offset = sizeof(struct vertex2f); 303 vertex_elems[1].instance_divisor = 0; 304 vertex_elems[1].vertex_buffer_index = 0; 305 vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT; 306 c->vertex_elems_state = c->pipe->create_vertex_elements_state(c->pipe, 2, vertex_elems); 307 308 /* 309 * Create our fragment shader's constant buffer 310 * Const buffer contains the color conversion matrix and bias vectors 311 */ 312 /* XXX: Create with IMMUTABLE/STATIC... although it does change every once in a long while... */ 313 c->csc_matrix = pipe_buffer_create 314 ( 315 c->pipe->screen, 316 PIPE_BIND_CONSTANT_BUFFER, 317 PIPE_USAGE_STATIC, 318 sizeof(csc_matrix) 319 ); 320 321 return true; 322} 323 324static void 325cleanup_buffers(struct vl_compositor *c) 326{ 327 assert(c); 328 329 c->pipe->delete_vertex_elements_state(c->pipe, c->vertex_elems_state); 330 pipe_resource_reference(&c->vertex_buf.buffer, NULL); 331 pipe_resource_reference(&c->csc_matrix, NULL); 332} 333 334static inline struct pipe_video_rect 335default_rect(struct vl_compositor_layer *layer) 336{ 337 struct pipe_resource *res = layer->sampler_views[0]->texture; 338 struct pipe_video_rect rect = { 0, 0, res->width0, res->height0 }; 339 return rect; 340} 341 342static void 343gen_rect_verts(struct vertex4f *vb, 344 struct pipe_video_rect *src_rect, 345 struct vertex2f *src_inv_size, 346 struct pipe_video_rect *dst_rect, 347 struct vertex2f *dst_inv_size) 348{ 349 assert(vb); 350 assert(src_rect && src_inv_size); 351 assert(dst_rect && dst_inv_size); 352 353 vb[0].x = dst_rect->x * dst_inv_size->x; 354 vb[0].y = dst_rect->y * dst_inv_size->y; 355 vb[0].z = src_rect->x * src_inv_size->x; 356 vb[0].w = src_rect->y * src_inv_size->y; 357 358 vb[1].x = (dst_rect->x + dst_rect->w) * dst_inv_size->x; 359 vb[1].y = dst_rect->y * dst_inv_size->y; 360 vb[1].z = (src_rect->x + src_rect->w) * src_inv_size->x; 361 vb[1].w = src_rect->y * src_inv_size->y; 362 363 vb[2].x = (dst_rect->x + dst_rect->w) * dst_inv_size->x; 364 vb[2].y = (dst_rect->y + dst_rect->h) * dst_inv_size->y; 365 vb[2].z = (src_rect->x + src_rect->w) * src_inv_size->x; 366 vb[2].w = (src_rect->y + src_rect->h) * src_inv_size->y; 367 368 vb[3].x = dst_rect->x * dst_inv_size->x; 369 vb[3].y = (dst_rect->y + dst_rect->h) * dst_inv_size->y; 370 vb[3].z = src_rect->x * src_inv_size->x; 371 vb[3].w = (src_rect->y + src_rect->h) * src_inv_size->y; 372} 373 374static void 375gen_vertex_data(struct vl_compositor *c, struct pipe_video_rect *dst_rect, struct vertex2f *dst_inv_size) 376{ 377 struct vertex4f *vb; 378 struct pipe_transfer *buf_transfer; 379 unsigned i; 380 381 assert(c); 382 assert(dst_rect); 383 384 vb = pipe_buffer_map(c->pipe, c->vertex_buf.buffer, 385 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, 386 &buf_transfer); 387 388 if (!vb) 389 return; 390 391 for (i = 0; i < VL_COMPOSITOR_MAX_LAYERS; i++) { 392 if (c->used_layers & (1 << i)) { 393 struct pipe_sampler_view *sv = c->layers[i].sampler_views[0]; 394 struct vertex2f src_inv_size = {1.0f / sv->texture->width0, 1.0f / sv->texture->height0}; 395 396 if (&c->layers[i].fs == c->fs_video_buffer) 397 gen_rect_verts(vb, &c->layers[i].src_rect, &src_inv_size, dst_rect, dst_inv_size); 398 else 399 gen_rect_verts(vb, &c->layers[i].src_rect, &src_inv_size, &c->layers[i].dst_rect, &src_inv_size); 400 401 vb += 4; 402 } 403 } 404 405 pipe_buffer_unmap(c->pipe, buf_transfer); 406} 407 408static void 409draw_layers(struct vl_compositor *c) 410{ 411 unsigned vb_index, i; 412 413 assert(c); 414 415 for (i = 0, vb_index = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) { 416 if (c->used_layers & (1 << i)) { 417 struct pipe_sampler_view **samplers = &c->layers[i].sampler_views[0]; 418 unsigned num_sampler_views = !samplers[1] ? 1 : !samplers[2] ? 2 : 3; 419 420 c->pipe->bind_fs_state(c->pipe, c->layers[i].fs); 421 c->pipe->set_fragment_sampler_views(c->pipe, num_sampler_views, samplers); 422 util_draw_arrays(c->pipe, PIPE_PRIM_QUADS, vb_index * 4, 4); 423 vb_index++; 424 } 425 } 426} 427 428static void 429vl_compositor_clear_layers(struct pipe_video_compositor *compositor) 430{ 431 struct vl_compositor *c = (struct vl_compositor *)compositor; 432 unsigned i, j; 433 434 assert(compositor); 435 436 c->used_layers = 0; 437 for ( i = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) { 438 c->layers[i].fs = NULL; 439 for ( j = 0; j < 3; j++) 440 pipe_sampler_view_reference(&c->layers[i].sampler_views[j], NULL); 441 } 442} 443 444static void 445vl_compositor_destroy(struct pipe_video_compositor *compositor) 446{ 447 struct vl_compositor *c = (struct vl_compositor *)compositor; 448 assert(compositor); 449 450 vl_compositor_clear_layers(compositor); 451 452 cleanup_buffers(c); 453 cleanup_shaders(c); 454 cleanup_pipe_state(c); 455 456 FREE(compositor); 457} 458 459static void 460vl_compositor_set_csc_matrix(struct pipe_video_compositor *compositor, const float matrix[16]) 461{ 462 struct vl_compositor *c = (struct vl_compositor *)compositor; 463 struct pipe_transfer *buf_transfer; 464 465 assert(compositor); 466 467 memcpy 468 ( 469 pipe_buffer_map(c->pipe, c->csc_matrix, 470 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, 471 &buf_transfer), 472 matrix, 473 sizeof(csc_matrix) 474 ); 475 476 pipe_buffer_unmap(c->pipe, buf_transfer); 477} 478 479static void 480vl_compositor_set_buffer_layer(struct pipe_video_compositor *compositor, 481 unsigned layer, 482 struct pipe_video_buffer *buffer, 483 struct pipe_video_rect *src_rect, 484 struct pipe_video_rect *dst_rect) 485{ 486 struct vl_compositor *c = (struct vl_compositor *)compositor; 487 struct pipe_sampler_view **sampler_views; 488 unsigned i; 489 490 assert(compositor && buffer); 491 492 assert(layer < VL_COMPOSITOR_MAX_LAYERS); 493 494 c->used_layers |= 1 << layer; 495 c->layers[layer].fs = c->fs_video_buffer; 496 497 sampler_views = buffer->get_sampler_views(buffer); 498 for (i = 0; i < 3; ++i) 499 pipe_sampler_view_reference(&c->layers[layer].sampler_views[i], sampler_views[i]); 500 501 c->layers[layer].src_rect = src_rect ? *src_rect : default_rect(&c->layers[layer]); 502 c->layers[layer].dst_rect = dst_rect ? *dst_rect : default_rect(&c->layers[layer]); 503} 504 505static void 506vl_compositor_set_palette_layer(struct pipe_video_compositor *compositor, 507 unsigned layer, 508 struct pipe_sampler_view *indexes, 509 struct pipe_sampler_view *palette, 510 struct pipe_video_rect *src_rect, 511 struct pipe_video_rect *dst_rect) 512{ 513 struct vl_compositor *c = (struct vl_compositor *)compositor; 514 assert(compositor && indexes && palette); 515 516 assert(layer < VL_COMPOSITOR_MAX_LAYERS); 517 518 c->used_layers |= 1 << layer; 519 c->layers[layer].fs = c->fs_palette; 520 pipe_sampler_view_reference(&c->layers[layer].sampler_views[0], indexes); 521 pipe_sampler_view_reference(&c->layers[layer].sampler_views[1], palette); 522 pipe_sampler_view_reference(&c->layers[layer].sampler_views[2], NULL); 523 c->layers[layer].src_rect = src_rect ? *src_rect : default_rect(&c->layers[layer]); 524 c->layers[layer].dst_rect = dst_rect ? *dst_rect : default_rect(&c->layers[layer]); 525} 526 527static void 528vl_compositor_set_rgba_layer(struct pipe_video_compositor *compositor, 529 unsigned layer, 530 struct pipe_sampler_view *rgba, 531 struct pipe_video_rect *src_rect, 532 struct pipe_video_rect *dst_rect) 533{ 534 struct vl_compositor *c = (struct vl_compositor *)compositor; 535 assert(compositor && rgba); 536 537 assert(layer < VL_COMPOSITOR_MAX_LAYERS); 538 539 c->used_layers |= 1 << layer; 540 c->layers[layer].fs = c->fs_rgba; 541 pipe_sampler_view_reference(&c->layers[layer].sampler_views[0], rgba); 542 pipe_sampler_view_reference(&c->layers[layer].sampler_views[1], NULL); 543 pipe_sampler_view_reference(&c->layers[layer].sampler_views[2], NULL); 544 c->layers[layer].src_rect = src_rect ? *src_rect : default_rect(&c->layers[layer]); 545 c->layers[layer].dst_rect = dst_rect ? *dst_rect : default_rect(&c->layers[layer]); 546} 547 548static void 549vl_compositor_render(struct pipe_video_compositor *compositor, 550 enum pipe_mpeg12_picture_type picture_type, 551 struct pipe_surface *dst_surface, 552 struct pipe_video_rect *dst_area, 553 struct pipe_fence_handle **fence) 554{ 555 struct vl_compositor *c = (struct vl_compositor *)compositor; 556 struct vertex2f dst_inv_size; 557 void *samplers[3]; 558 559 assert(compositor); 560 assert(dst_surface); 561 assert(dst_area); 562 563 c->fb_state.width = dst_surface->width; 564 c->fb_state.height = dst_surface->height; 565 c->fb_state.cbufs[0] = dst_surface; 566 567 c->viewport.scale[0] = dst_surface->width; 568 c->viewport.scale[1] = dst_surface->height; 569 570 dst_inv_size.x = 1.0f / dst_surface->width; 571 dst_inv_size.y = 1.0f / dst_surface->height; 572 573 samplers[0] = samplers[1] = samplers[2] = c->sampler; 574 575 gen_vertex_data(c, dst_area, &dst_inv_size); 576 577 c->pipe->set_framebuffer_state(c->pipe, &c->fb_state); 578 c->pipe->set_viewport_state(c->pipe, &c->viewport); 579 c->pipe->bind_fragment_sampler_states(c->pipe, 3, &samplers[0]); 580 c->pipe->bind_vs_state(c->pipe, c->vs); 581 c->pipe->set_vertex_buffers(c->pipe, 1, &c->vertex_buf); 582 c->pipe->bind_vertex_elements_state(c->pipe, c->vertex_elems_state); 583 c->pipe->set_constant_buffer(c->pipe, PIPE_SHADER_FRAGMENT, 0, c->csc_matrix); 584 c->pipe->bind_blend_state(c->pipe, c->blend); 585 586 draw_layers(c); 587 588 c->pipe->flush(c->pipe, fence); 589} 590 591struct pipe_video_compositor * 592vl_compositor_init(struct pipe_video_context *vpipe, struct pipe_context *pipe) 593{ 594 csc_matrix csc_matrix; 595 struct vl_compositor *compositor; 596 597 compositor = CALLOC_STRUCT(vl_compositor); 598 599 compositor->base.context = vpipe; 600 compositor->base.destroy = vl_compositor_destroy; 601 compositor->base.set_csc_matrix = vl_compositor_set_csc_matrix; 602 compositor->base.clear_layers = vl_compositor_clear_layers; 603 compositor->base.set_buffer_layer = vl_compositor_set_buffer_layer; 604 compositor->base.set_palette_layer = vl_compositor_set_palette_layer; 605 compositor->base.set_rgba_layer = vl_compositor_set_rgba_layer; 606 compositor->base.render_picture = vl_compositor_render; 607 608 compositor->pipe = pipe; 609 610 if (!init_pipe_state(compositor)) 611 return false; 612 613 if (!init_shaders(compositor)) { 614 cleanup_pipe_state(compositor); 615 return false; 616 } 617 if (!init_buffers(compositor)) { 618 cleanup_shaders(compositor); 619 cleanup_pipe_state(compositor); 620 return false; 621 } 622 623 vl_compositor_clear_layers(&compositor->base); 624 625 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY, NULL, true, csc_matrix); 626 vl_compositor_set_csc_matrix(&compositor->base, csc_matrix); 627 628 return &compositor->base; 629} 630