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