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