g3dvl: stash interlaced
[mesa/nouveau-pmpeg.git] / src / gallium / auxiliary / vl / vl_compositor.c
blob23e12d01f154e2691a3e0d964bee2b4555df49b6
1 /**************************************************************************
3 * Copyright 2009 Younes Manton.
4 * All Rights Reserved.
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
16 * of the Software.
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 <assert.h>
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"
40 #include "vl_csc.h"
41 #include "vl_types.h"
42 #include "vl_compositor.h"
44 typedef float csc_matrix[16];
46 static void *
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);
54 if (!shader)
55 return false;
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);
63 * o_vpos = vpos
64 * o_vtex = vtex
66 ureg_MOV(shader, o_vpos, vpos);
67 ureg_MOV(shader, o_vtex, vtex);
69 ureg_END(shader);
71 return ureg_create_shader_and_destroy(shader, c->pipe);
74 static void *
75 create_frag_shader_video_buffer(struct vl_compositor *c, unsigned planes)
77 struct ureg_program *shader;
78 struct ureg_src tc;
79 struct ureg_src csc[3];
80 struct ureg_src sampler[3];
81 struct ureg_dst texel;
82 struct ureg_dst fragment;
83 unsigned i;
85 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
86 if (!shader)
87 return false;
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);
92 if (i < planes)
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
102 if (planes == 2) {
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]);
105 } else {
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);
118 ureg_END(shader);
120 return ureg_create_shader_and_destroy(shader, c->pipe);
123 static struct ureg_dst
124 calc_line(struct ureg_program *shader)
126 struct ureg_dst tmp;
127 struct ureg_src pos;
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));
140 return tmp;
143 /* Deinterlace NV12 or YV12 to a temporary video buffer
146 static void *
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;
153 if (luma)
154 writemask = TGSI_WRITEMASK_X;
155 else if (comps == 2)
156 writemask = TGSI_WRITEMASK_YZ;
157 else
158 writemask = TGSI_WRITEMASK_Y;
160 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
161 if (!shader)
162 return false;
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)
178 * if (field.y)
179 * swiz = sampler[bottom];
180 * else
181 * swiz = sampler[top];
183 * if (LUMA)
184 * color.x = swiz;
185 * else
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));
199 ureg_ENDIF(shader);
201 if (luma)
202 ureg_MOV(shader, ureg_writemask(fragment, writemask), ureg_src(swizcolor));
203 else
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);
209 ureg_END(shader);
210 return ureg_create_shader_and_destroy(shader, c->pipe);
213 static void *
214 create_frag_shader_palette(struct vl_compositor *c, bool include_cc)
216 struct ureg_program *shader;
217 struct ureg_src csc[3];
218 struct ureg_src tc;
219 struct ureg_src sampler;
220 struct ureg_src palette;
221 struct ureg_dst texel;
222 struct ureg_dst fragment;
223 unsigned i;
225 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
226 if (!shader)
227 return false;
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));
247 if (include_cc) {
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));
251 } else {
252 ureg_TEX(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XYZ),
253 TGSI_TEXTURE_1D, ureg_src(texel), palette);
256 ureg_release_temporary(shader, texel);
257 ureg_END(shader);
259 return ureg_create_shader_and_destroy(shader, c->pipe);
262 static void *
263 create_frag_shader_rgba(struct vl_compositor *c)
265 struct ureg_program *shader;
266 struct ureg_src tc;
267 struct ureg_src sampler;
268 struct ureg_dst fragment;
270 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
271 if (!shader)
272 return false;
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);
282 ureg_END(shader);
284 return ureg_create_shader_and_destroy(shader, c->pipe);
287 static bool
288 init_shaders(struct vl_compositor *c)
290 assert(c);
292 c->vs = create_vert_shader(c);
293 if (!c->vs) {
294 debug_printf("Unable to create vertex shader.\n");
295 return false;
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");
301 return false;
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");
307 return false;
310 c->fs_rgba = create_frag_shader_rgba(c);
311 if (!c->fs_rgba) {
312 debug_printf("Unable to create RGB-to-RGB fragment shader.\n");
313 return false;
316 return true;
319 static void cleanup_shaders(struct vl_compositor *c)
321 assert(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);
329 static bool
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;
336 unsigned i;
338 assert(c);
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;
371 blend.dither = 0;
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);
384 rast.flatshade = 1;
385 rast.front_ccw = 1;
386 rast.cull_face = PIPE_FACE_NONE;
387 rast.fill_back = PIPE_POLYGON_MODE_FILL;
388 rast.fill_front = PIPE_POLYGON_MODE_FILL;
389 rast.scissor = 1;
390 rast.line_width = 1;
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);
417 return true;
420 static void cleanup_pipe_state(struct vl_compositor *c)
422 assert(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);
436 static bool
437 create_vertex_buffer(struct vl_compositor *c)
439 assert(c);
441 pipe_resource_reference(&c->vertex_buf.buffer, NULL);
442 c->vertex_buf.buffer = pipe_buffer_create
444 c->pipe->screen,
445 PIPE_BIND_VERTEX_BUFFER,
446 PIPE_USAGE_STREAM,
447 sizeof(struct vertex4f) * VL_COMPOSITOR_MAX_LAYERS * 4
450 return c->vertex_buf.buffer != NULL;
453 static bool
454 init_buffers(struct vl_compositor *c)
456 struct pipe_vertex_element vertex_elems[2];
458 assert(c);
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
484 c->pipe->screen,
485 PIPE_BIND_CONSTANT_BUFFER,
486 PIPE_USAGE_STATIC,
487 sizeof(csc_matrix)
490 return true;
493 static void
494 cleanup_buffers(struct vl_compositor *c)
496 assert(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 };
508 return rect;
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 };
515 return res;
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 };
522 return res;
525 static INLINE void
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);
534 if (dst) {
535 layer->dst.tl = calc_topleft(size_out, *dst);
536 layer->dst.br = calc_bottomright(size_out, *dst);
537 layer->custom_dest_rect = 1;
538 } else {
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;
545 static void
546 gen_rect_verts(struct vertex4f *vb, struct vl_compositor_layer *layer, float w, float h)
548 assert(vb && layer);
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;
571 static void
572 gen_vertex_data(struct vl_compositor *c, float w, float h)
574 struct vertex4f *vb;
575 struct pipe_transfer *buf_transfer;
576 unsigned i;
578 assert(c);
580 vb = pipe_buffer_map(c->pipe, c->vertex_buf.buffer,
581 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD | PIPE_TRANSFER_DONTBLOCK,
582 &buf_transfer);
584 if (!vb) {
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,
589 &buf_transfer);
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);
597 else
598 gen_rect_verts(vb, layer, 1.f, 1.f);
599 vb += 4;
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);
617 static void
618 draw_layers(struct vl_compositor *c, float w, float h)
620 unsigned vb_index, i;
622 assert(c);
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);
635 vb_index++;
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);
643 } else {
644 c->dirty_tl.x = 0.f;
645 c->dirty_tl.y = 0.f;
646 c->dirty_br.x = 1.f;
647 c->dirty_br.y = 1.f;
653 void
654 vl_compositor_reset_dirty_area(struct vl_compositor *c)
656 assert(c);
658 c->dirty_tl.x = c->dirty_tl.y = 0.0f;
659 c->dirty_br.x = c->dirty_br.y = 1.0f;
662 void
663 vl_compositor_set_clear_color(struct vl_compositor *c, union pipe_color_union *color)
665 assert(c);
667 c->clear_color = *color;
670 void
671 vl_compositor_get_clear_color(struct vl_compositor *c, union pipe_color_union *color)
673 assert(c);
674 assert(color);
676 *color = c->clear_color;
679 void
680 vl_compositor_clear_layers(struct vl_compositor *c)
682 unsigned i, j;
684 assert(c);
686 c->used_layers = 0;
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);
696 static void
697 cleanup_video(struct vl_compositor *c)
699 unsigned i;
700 for (i = 0; i < 3; ++i) {
701 if (!c->fs_weave[i])
702 continue;
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);
717 void
718 vl_compositor_cleanup(struct vl_compositor *c)
720 assert(c);
722 vl_compositor_clear_layers(c);
723 cleanup_buffers(c);
724 cleanup_shaders(c);
725 cleanup_pipe_state(c);
726 cleanup_video(c);
729 void
730 vl_compositor_set_csc_matrix(struct vl_compositor *c, const float matrix[16])
732 struct pipe_transfer *buf_transfer;
734 assert(c);
736 memcpy
738 pipe_buffer_map(c->pipe, c->csc_matrix,
739 PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
740 &buf_transfer),
741 matrix,
742 sizeof(csc_matrix)
745 pipe_buffer_unmap(c->pipe, buf_transfer);
748 void
749 vl_compositor_set_layer_blend(struct vl_compositor *c,
750 unsigned layer, void *blend,
751 bool is_clearing)
753 assert(c && 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) {
763 struct vertex4f *vb;
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,
767 &buf_transfer);
769 if (!vb) {
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,
774 &buf_transfer);
776 vb[0].x = 0.f;
777 vb[0].y = 0.f;
778 vb[0].z = 0.f;
779 vb[0].w = 0.f;
781 vb[1].x = 0.f;
782 vb[1].y = 65535.f;
783 vb[1].z = 0.f;
784 vb[1].w = 65535.f;
786 vb[2].x = 65535.f;
787 vb[2].y = 0.f;
788 vb[2].z = 65535.f;
789 vb[2].w = 0.f;
790 pipe_buffer_unmap(c->pipe, buf_transfer);
793 static void
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);
800 void *samplers[4];
801 unsigned i;
802 for (i = 0; i < 4; ++i)
803 samplers[i] = c->sampler_nearest;
805 assert(c);
806 gen_vertex_data_video(c);
807 for (i = 0; i < 2; ++i) {
808 struct pipe_surface *dst_surface = c->video_surf[i];
809 assert(dst_surface);
810 unsigned num_sampler_views;
811 if (i == 0)
812 num_sampler_views = 2;
813 else
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;
825 scissor.minx = 0;
826 scissor.miny = 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);
839 if (i == 0)
840 c->pipe->bind_fs_state(c->pipe, c->fs_weave[0]);
841 else
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);
849 void
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,
855 unsigned past_count,
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;
862 unsigned i;
864 assert(c && buffer);
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]);
875 } else {
876 int top = field == PIPE_VIDEO_PICTURE_STRUCTURE_FIELD_TOP;
877 sampler_views = buffer->get_sampler_view_planes(buffer, 1);
878 assert(sampler_views);
879 // NO GAMES!
880 assert(0);
883 c->used_layers |= 1 << layer;
884 if (!src_rect) {
885 src_rect = &rect;
886 rect.x = rect.y = 0;
887 rect.w = c->video_w;
888 rect.h = c->video_h;
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;
896 else
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);
906 void
907 vl_compositor_set_palette_layer(struct vl_compositor *c,
908 unsigned layer,
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]),
932 dst_rect);
935 void
936 vl_compositor_set_rgba_layer(struct vl_compositor *c,
937 unsigned layer,
938 struct pipe_sampler_view *rgba,
939 struct pipe_video_rect *src_rect,
940 struct pipe_video_rect *dst_rect)
942 assert(c && rgba);
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]),
956 dst_rect);
959 void
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;
968 assert(c);
969 assert(dst_surface);
971 c->fb_state.width = dst_surface->width;
972 c->fb_state.height = dst_surface->height;
973 c->fb_state.cbufs[0] = dst_surface;
975 if (dst_area) {
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;
980 } else {
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;
987 if (dst_clip) {
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;
992 } else {
993 scissor.minx = 0;
994 scissor.miny = 0;
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);
1021 bool
1022 vl_compositor_init(struct vl_compositor *c, struct pipe_context *pipe)
1024 csc_matrix csc_matrix;
1026 c->pipe = pipe;
1028 if (!init_pipe_state(c))
1029 return false;
1031 if (!init_shaders(c)) {
1032 cleanup_pipe_state(c);
1033 return false;
1036 if (!init_buffers(c)) {
1037 cleanup_shaders(c);
1038 cleanup_pipe_state(c);
1039 return false;
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);
1051 return true;
1054 bool
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))
1062 return false;
1063 c->video_w = w;
1064 c->video_h = h;
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");
1069 goto fail;
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");
1074 goto fail;
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");
1081 goto fail;
1083 memset(&templ, 0, sizeof(templ));
1084 templ.target = PIPE_TEXTURE_2D;
1085 templ.format = PIPE_FORMAT_R8_UNORM;
1086 templ.width0 = w;
1087 templ.height0 = h;
1088 templ.depth0 = 1;
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);
1093 if (!c->video_y) {
1094 debug_printf("Could not create deinterlaced temp frame for luma\n");
1095 goto fail;
1097 if (chroma != PIPE_VIDEO_CHROMA_FORMAT_444)
1098 templ.height0 /= 2;
1099 if (chroma == PIPE_VIDEO_CHROMA_FORMAT_420)
1100 templ.width0 /= 2;
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");
1105 goto fail;
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");
1119 goto fail;
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");
1129 goto fail;
1132 return true;
1134 fail:
1135 vl_compositor_cleanup(c);
1136 return false;