vl_compositor.c revision 72325ee6e35fc3941dc04a87e14e0ba0c9eec52e
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 <assert.h>
29
30#include "pipe/p_compiler.h"
31#include "pipe/p_context.h"
32
33#include "util/u_memory.h"
34#include "util/u_draw.h"
35#include "util/u_surface.h"
36
37#include "tgsi/tgsi_ureg.h"
38
39#include "vl_csc.h"
40#include "vl_types.h"
41#include "vl_compositor.h"
42
43#define MIN_DIRTY (0)
44#define MAX_DIRTY (1 << 15)
45
46typedef float csc_matrix[16];
47
48static void *
49create_vert_shader(struct vl_compositor *c)
50{
51   struct ureg_program *shader;
52   struct ureg_src vpos, vtex;
53   struct ureg_dst o_vpos, o_vtex;
54
55   shader = ureg_create(TGSI_PROCESSOR_VERTEX);
56   if (!shader)
57      return false;
58
59   vpos = ureg_DECL_vs_input(shader, 0);
60   vtex = ureg_DECL_vs_input(shader, 1);
61   o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, 0);
62   o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, 1);
63
64   /*
65    * o_vpos = vpos
66    * o_vtex = vtex
67    */
68   ureg_MOV(shader, o_vpos, vpos);
69   ureg_MOV(shader, o_vtex, vtex);
70
71   ureg_END(shader);
72
73   return ureg_create_shader_and_destroy(shader, c->pipe);
74}
75
76static void *
77create_frag_shader_video_buffer(struct vl_compositor *c)
78{
79   struct ureg_program *shader;
80   struct ureg_src tc;
81   struct ureg_src csc[3];
82   struct ureg_src sampler[3];
83   struct ureg_dst texel;
84   struct ureg_dst fragment;
85   unsigned i;
86
87   shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
88   if (!shader)
89      return false;
90
91   tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, 1, TGSI_INTERPOLATE_LINEAR);
92   for (i = 0; i < 3; ++i) {
93      csc[i] = ureg_DECL_constant(shader, i);
94      sampler[i] = ureg_DECL_sampler(shader, i);
95   }
96   texel = ureg_DECL_temporary(shader);
97   fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
98
99   /*
100    * texel.xyz = tex(tc, sampler[i])
101    * fragment = csc * texel
102    */
103   for (i = 0; i < 3; ++i)
104      ureg_TEX(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), TGSI_TEXTURE_2D, tc, sampler[i]);
105
106   ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f));
107
108   for (i = 0; i < 3; ++i)
109      ureg_DP4(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(texel));
110
111   ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f));
112
113   ureg_release_temporary(shader, texel);
114   ureg_END(shader);
115
116   return ureg_create_shader_and_destroy(shader, c->pipe);
117}
118
119static void *
120create_frag_shader_palette(struct vl_compositor *c, bool include_cc)
121{
122   struct ureg_program *shader;
123   struct ureg_src csc[3];
124   struct ureg_src tc;
125   struct ureg_src sampler;
126   struct ureg_src palette;
127   struct ureg_dst texel;
128   struct ureg_dst fragment;
129   unsigned i;
130
131   shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
132   if (!shader)
133      return false;
134
135   for (i = 0; i < 3; ++i)
136      csc[i] = ureg_DECL_constant(shader, i);
137
138   tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, 1, TGSI_INTERPOLATE_LINEAR);
139   sampler = ureg_DECL_sampler(shader, 0);
140   palette = ureg_DECL_sampler(shader, 1);
141
142   texel = ureg_DECL_temporary(shader);
143   fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
144
145   /*
146    * texel = tex(tc, sampler)
147    * fragment.xyz = tex(texel, palette) * csc
148    * fragment.a = texel.a
149    */
150   ureg_TEX(shader, texel, TGSI_TEXTURE_2D, tc, sampler);
151   ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), ureg_src(texel));
152
153   if (include_cc) {
154      ureg_TEX(shader, texel, TGSI_TEXTURE_1D, ureg_src(texel), palette);
155      for (i = 0; i < 3; ++i)
156         ureg_DP4(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(texel));
157   } else {
158      ureg_TEX(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XYZ),
159               TGSI_TEXTURE_1D, ureg_src(texel), palette);
160   }
161
162   ureg_release_temporary(shader, texel);
163   ureg_END(shader);
164
165   return ureg_create_shader_and_destroy(shader, c->pipe);
166}
167
168static void *
169create_frag_shader_rgba(struct vl_compositor *c)
170{
171   struct ureg_program *shader;
172   struct ureg_src tc;
173   struct ureg_src sampler;
174   struct ureg_dst fragment;
175
176   shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
177   if (!shader)
178      return false;
179
180   tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, 1, TGSI_INTERPOLATE_LINEAR);
181   sampler = ureg_DECL_sampler(shader, 0);
182   fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
183
184   /*
185    * fragment = tex(tc, sampler)
186    */
187   ureg_TEX(shader, fragment, TGSI_TEXTURE_2D, tc, sampler);
188   ureg_END(shader);
189
190   return ureg_create_shader_and_destroy(shader, c->pipe);
191}
192
193static bool
194init_shaders(struct vl_compositor *c)
195{
196   assert(c);
197
198   c->vs = create_vert_shader(c);
199   if (!c->vs) {
200      debug_printf("Unable to create vertex shader.\n");
201      return false;
202   }
203
204   c->fs_video_buffer = create_frag_shader_video_buffer(c);
205   if (!c->fs_video_buffer) {
206      debug_printf("Unable to create YCbCr-to-RGB fragment shader.\n");
207      return false;
208   }
209
210   c->fs_palette.yuv = create_frag_shader_palette(c, true);
211   if (!c->fs_palette.yuv) {
212      debug_printf("Unable to create YUV-Palette-to-RGB fragment shader.\n");
213      return false;
214   }
215
216   c->fs_palette.rgb = create_frag_shader_palette(c, false);
217   if (!c->fs_palette.rgb) {
218      debug_printf("Unable to create RGB-Palette-to-RGB fragment shader.\n");
219      return false;
220   }
221
222   c->fs_rgba = create_frag_shader_rgba(c);
223   if (!c->fs_rgba) {
224      debug_printf("Unable to create RGB-to-RGB fragment shader.\n");
225      return false;
226   }
227
228   return true;
229}
230
231static void cleanup_shaders(struct vl_compositor *c)
232{
233   assert(c);
234
235   c->pipe->delete_vs_state(c->pipe, c->vs);
236   c->pipe->delete_fs_state(c->pipe, c->fs_video_buffer);
237   c->pipe->delete_fs_state(c->pipe, c->fs_palette.yuv);
238   c->pipe->delete_fs_state(c->pipe, c->fs_palette.rgb);
239   c->pipe->delete_fs_state(c->pipe, c->fs_rgba);
240}
241
242static bool
243init_pipe_state(struct vl_compositor *c)
244{
245   struct pipe_rasterizer_state rast;
246   struct pipe_sampler_state sampler;
247   struct pipe_blend_state blend;
248   struct pipe_depth_stencil_alpha_state dsa;
249   unsigned i;
250
251   assert(c);
252
253   c->fb_state.nr_cbufs = 1;
254   c->fb_state.zsbuf = NULL;
255
256   c->viewport.scale[2] = 1;
257   c->viewport.scale[3] = 1;
258   c->viewport.translate[2] = 0;
259   c->viewport.translate[3] = 0;
260
261   memset(&sampler, 0, sizeof(sampler));
262   sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
263   sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
264   sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
265   sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
266   sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
267   sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
268   sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
269   sampler.compare_func = PIPE_FUNC_ALWAYS;
270   sampler.normalized_coords = 1;
271
272   c->sampler_linear = c->pipe->create_sampler_state(c->pipe, &sampler);
273
274   sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
275   sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
276   c->sampler_nearest = c->pipe->create_sampler_state(c->pipe, &sampler);
277
278   memset(&blend, 0, sizeof blend);
279   blend.independent_blend_enable = 0;
280   blend.rt[0].blend_enable = 0;
281   blend.logicop_enable = 0;
282   blend.logicop_func = PIPE_LOGICOP_CLEAR;
283   blend.rt[0].colormask = PIPE_MASK_RGBA;
284   blend.dither = 0;
285   c->blend_clear = c->pipe->create_blend_state(c->pipe, &blend);
286
287   blend.rt[0].blend_enable = 1;
288   blend.rt[0].rgb_func = PIPE_BLEND_ADD;
289   blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
290   blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
291   blend.rt[0].alpha_func = PIPE_BLEND_ADD;
292   blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
293   blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
294   c->blend_add = c->pipe->create_blend_state(c->pipe, &blend);
295
296   memset(&rast, 0, sizeof rast);
297   rast.flatshade = 1;
298   rast.front_ccw = 1;
299   rast.cull_face = PIPE_FACE_NONE;
300   rast.fill_back = PIPE_POLYGON_MODE_FILL;
301   rast.fill_front = PIPE_POLYGON_MODE_FILL;
302   rast.scissor = 1;
303   rast.line_width = 1;
304   rast.point_size_per_vertex = 1;
305   rast.offset_units = 1;
306   rast.offset_scale = 1;
307   rast.gl_rasterization_rules = 1;
308
309   c->rast = c->pipe->create_rasterizer_state(c->pipe, &rast);
310
311   memset(&dsa, 0, sizeof dsa);
312   dsa.depth.enabled = 0;
313   dsa.depth.writemask = 0;
314   dsa.depth.func = PIPE_FUNC_ALWAYS;
315   for (i = 0; i < 2; ++i) {
316      dsa.stencil[i].enabled = 0;
317      dsa.stencil[i].func = PIPE_FUNC_ALWAYS;
318      dsa.stencil[i].fail_op = PIPE_STENCIL_OP_KEEP;
319      dsa.stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP;
320      dsa.stencil[i].zfail_op = PIPE_STENCIL_OP_KEEP;
321      dsa.stencil[i].valuemask = 0;
322      dsa.stencil[i].writemask = 0;
323   }
324   dsa.alpha.enabled = 0;
325   dsa.alpha.func = PIPE_FUNC_ALWAYS;
326   dsa.alpha.ref_value = 0;
327   c->dsa = c->pipe->create_depth_stencil_alpha_state(c->pipe, &dsa);
328   c->pipe->bind_depth_stencil_alpha_state(c->pipe, c->dsa);
329
330   return true;
331}
332
333static void cleanup_pipe_state(struct vl_compositor *c)
334{
335   assert(c);
336
337   /* Asserted in softpipe_delete_fs_state() for some reason */
338   c->pipe->bind_vs_state(c->pipe, NULL);
339   c->pipe->bind_fs_state(c->pipe, NULL);
340
341   c->pipe->delete_depth_stencil_alpha_state(c->pipe, c->dsa);
342   c->pipe->delete_sampler_state(c->pipe, c->sampler_linear);
343   c->pipe->delete_sampler_state(c->pipe, c->sampler_nearest);
344   c->pipe->delete_blend_state(c->pipe, c->blend_clear);
345   c->pipe->delete_blend_state(c->pipe, c->blend_add);
346   c->pipe->delete_rasterizer_state(c->pipe, c->rast);
347}
348
349static bool
350create_vertex_buffer(struct vl_compositor *c)
351{
352   assert(c);
353
354   pipe_resource_reference(&c->vertex_buf.buffer, NULL);
355   c->vertex_buf.buffer = pipe_buffer_create
356   (
357      c->pipe->screen,
358      PIPE_BIND_VERTEX_BUFFER,
359      PIPE_USAGE_STREAM,
360      sizeof(struct vertex4f) * VL_COMPOSITOR_MAX_LAYERS * 4
361   );
362
363   return c->vertex_buf.buffer != NULL;
364}
365
366static bool
367init_buffers(struct vl_compositor *c)
368{
369   struct pipe_vertex_element vertex_elems[2];
370
371   assert(c);
372
373   /*
374    * Create our vertex buffer and vertex buffer elements
375    */
376   c->vertex_buf.stride = sizeof(struct vertex4f);
377   c->vertex_buf.buffer_offset = 0;
378   create_vertex_buffer(c);
379
380   vertex_elems[0].src_offset = 0;
381   vertex_elems[0].instance_divisor = 0;
382   vertex_elems[0].vertex_buffer_index = 0;
383   vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
384   vertex_elems[1].src_offset = sizeof(struct vertex2f);
385   vertex_elems[1].instance_divisor = 0;
386   vertex_elems[1].vertex_buffer_index = 0;
387   vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
388   c->vertex_elems_state = c->pipe->create_vertex_elements_state(c->pipe, 2, vertex_elems);
389
390   /*
391    * Create our fragment shader's constant buffer
392    * Const buffer contains the color conversion matrix and bias vectors
393    */
394   /* XXX: Create with IMMUTABLE/STATIC... although it does change every once in a long while... */
395   c->csc_matrix = pipe_buffer_create
396   (
397      c->pipe->screen,
398      PIPE_BIND_CONSTANT_BUFFER,
399      PIPE_USAGE_STATIC,
400      sizeof(csc_matrix)
401   );
402
403   return true;
404}
405
406static void
407cleanup_buffers(struct vl_compositor *c)
408{
409   assert(c);
410
411   c->pipe->delete_vertex_elements_state(c->pipe, c->vertex_elems_state);
412   pipe_resource_reference(&c->vertex_buf.buffer, NULL);
413   pipe_resource_reference(&c->csc_matrix, NULL);
414}
415
416static INLINE struct pipe_video_rect
417default_rect(struct vl_compositor_layer *layer)
418{
419   struct pipe_resource *res = layer->sampler_views[0]->texture;
420   struct pipe_video_rect rect = { 0, 0, res->width0, res->height0 };
421   return rect;
422}
423
424static INLINE struct vertex2f
425calc_topleft(struct vertex2f size, struct pipe_video_rect rect)
426{
427   struct vertex2f res = { rect.x / size.x, rect.y / size.y };
428   return res;
429}
430
431static INLINE struct vertex2f
432calc_bottomright(struct vertex2f size, struct pipe_video_rect rect)
433{
434   struct vertex2f res = { (rect.x + rect.w) / size.x, (rect.y + rect.h) / size.y };
435   return res;
436}
437
438static INLINE void
439calc_src_and_dst(struct vl_compositor_layer *layer, unsigned width, unsigned height,
440                 struct pipe_video_rect src, struct pipe_video_rect dst)
441{
442   struct vertex2f size =  { width, height };
443
444   layer->src.tl = calc_topleft(size, src);
445   layer->src.br = calc_bottomright(size, src);
446   layer->dst.tl = calc_topleft(size, dst);
447   layer->dst.br = calc_bottomright(size, dst);
448}
449
450static void
451gen_rect_verts(struct vertex4f *vb, struct vl_compositor_layer *layer)
452{
453   assert(vb && layer);
454
455   vb[0].x = layer->dst.tl.x;
456   vb[0].y = layer->dst.tl.y;
457   vb[0].z = layer->src.tl.x;
458   vb[0].w = layer->src.tl.y;
459
460   vb[1].x = layer->dst.br.x;
461   vb[1].y = layer->dst.tl.y;
462   vb[1].z = layer->src.br.x;
463   vb[1].w = layer->src.tl.y;
464
465   vb[2].x = layer->dst.br.x;
466   vb[2].y = layer->dst.br.y;
467   vb[2].z = layer->src.br.x;
468   vb[2].w = layer->src.br.y;
469
470   vb[3].x = layer->dst.tl.x;
471   vb[3].y = layer->dst.br.y;
472   vb[3].z = layer->src.tl.x;
473   vb[3].w = layer->src.br.y;
474}
475
476static INLINE struct u_rect
477calc_drawn_area(struct vl_compositor *c, struct vl_compositor_layer *layer)
478{
479   struct u_rect result;
480
481   // scale
482   result.x0 = layer->dst.tl.x * c->viewport.scale[0] + c->viewport.translate[0];
483   result.y0 = layer->dst.tl.y * c->viewport.scale[1] + c->viewport.translate[1];
484   result.x1 = layer->dst.br.x * c->viewport.scale[0] + c->viewport.translate[0];
485   result.y1 = layer->dst.br.y * c->viewport.scale[1] + c->viewport.translate[1];
486
487   // and clip
488   result.x0 = MAX2(result.x0, c->scissor.minx);
489   result.y0 = MAX2(result.y0, c->scissor.miny);
490   result.x1 = MIN2(result.x1, c->scissor.maxx);
491   result.y1 = MIN2(result.y1, c->scissor.maxy);
492   return result;
493}
494
495static void
496gen_vertex_data(struct vl_compositor *c, struct u_rect *dirty)
497{
498   struct vertex4f *vb;
499   struct pipe_transfer *buf_transfer;
500   unsigned i;
501
502   assert(c);
503
504   vb = pipe_buffer_map(c->pipe, c->vertex_buf.buffer,
505                        PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD | PIPE_TRANSFER_DONTBLOCK,
506                        &buf_transfer);
507
508   if (!vb) {
509      // If buffer is still locked from last draw create a new one
510      create_vertex_buffer(c);
511      vb = pipe_buffer_map(c->pipe, c->vertex_buf.buffer,
512                           PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
513                           &buf_transfer);
514   }
515
516   for (i = 0; i < VL_COMPOSITOR_MAX_LAYERS; i++) {
517      if (c->used_layers & (1 << i)) {
518         struct vl_compositor_layer *layer = &c->layers[i];
519         gen_rect_verts(vb, layer);
520         vb += 4;
521
522         if (dirty && layer->clearing) {
523            struct u_rect drawn = calc_drawn_area(c, layer);
524            if (
525             dirty->x0 >= drawn.x0 &&
526             dirty->y0 >= drawn.y0 &&
527             dirty->x1 <= drawn.x1 &&
528             dirty->y1 <= drawn.y1) {
529
530               // We clear the dirty area anyway, no need for clear_render_target
531               dirty->x0 = dirty->y0 = MAX_DIRTY;
532               dirty->x1 = dirty->y1 = MIN_DIRTY;
533            }
534         }
535      }
536   }
537
538   pipe_buffer_unmap(c->pipe, buf_transfer);
539}
540
541static void
542draw_layers(struct vl_compositor *c, struct u_rect *dirty)
543{
544   unsigned vb_index, i;
545
546   assert(c);
547
548   for (i = 0, vb_index = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) {
549      if (c->used_layers & (1 << i)) {
550         struct vl_compositor_layer *layer = &c->layers[i];
551         struct pipe_sampler_view **samplers = &layer->sampler_views[0];
552         unsigned num_sampler_views = !samplers[1] ? 1 : !samplers[2] ? 2 : 3;
553
554         c->pipe->bind_blend_state(c->pipe, layer->blend);
555         c->pipe->bind_fs_state(c->pipe, layer->fs);
556         c->pipe->bind_fragment_sampler_states(c->pipe, num_sampler_views, layer->samplers);
557         c->pipe->set_fragment_sampler_views(c->pipe, num_sampler_views, samplers);
558         util_draw_arrays(c->pipe, PIPE_PRIM_QUADS, vb_index * 4, 4);
559         vb_index++;
560
561         if (dirty) {
562            // Remember the currently drawn area as dirty for the next draw command
563            struct u_rect drawn = calc_drawn_area(c, layer);
564            dirty->x0 = MIN2(drawn.x0, dirty->x0);
565            dirty->y0 = MIN2(drawn.y0, dirty->y0);
566            dirty->x1 = MAX2(drawn.x1, dirty->x1);
567            dirty->y1 = MAX2(drawn.y1, dirty->y1);
568         }
569      }
570   }
571}
572
573void
574vl_compositor_reset_dirty_area(struct u_rect *dirty)
575{
576   assert(dirty);
577
578   dirty->x0 = dirty->y0 = MIN_DIRTY;
579   dirty->x1 = dirty->y1 = MAX_DIRTY;
580}
581
582void
583vl_compositor_set_clear_color(struct vl_compositor *c, union pipe_color_union *color)
584{
585   assert(c);
586
587   c->clear_color = *color;
588}
589
590void
591vl_compositor_get_clear_color(struct vl_compositor *c, union pipe_color_union *color)
592{
593   assert(c);
594   assert(color);
595
596   *color = c->clear_color;
597}
598
599void
600vl_compositor_clear_layers(struct vl_compositor *c)
601{
602   unsigned i, j;
603
604   assert(c);
605
606   c->used_layers = 0;
607   for ( i = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) {
608      c->layers[i].clearing = i ? false : true;
609      c->layers[i].blend = i ? c->blend_add : c->blend_clear;
610      c->layers[i].fs = NULL;
611      for ( j = 0; j < 3; j++)
612         pipe_sampler_view_reference(&c->layers[i].sampler_views[j], NULL);
613   }
614}
615
616void
617vl_compositor_cleanup(struct vl_compositor *c)
618{
619   assert(c);
620
621   vl_compositor_clear_layers(c);
622
623   cleanup_buffers(c);
624   cleanup_shaders(c);
625   cleanup_pipe_state(c);
626}
627
628void
629vl_compositor_set_csc_matrix(struct vl_compositor *c, const float matrix[16])
630{
631   struct pipe_transfer *buf_transfer;
632
633   assert(c);
634
635   memcpy
636   (
637      pipe_buffer_map(c->pipe, c->csc_matrix,
638                      PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
639                      &buf_transfer),
640      matrix,
641      sizeof(csc_matrix)
642   );
643
644   pipe_buffer_unmap(c->pipe, buf_transfer);
645}
646
647void
648vl_compositor_set_layer_blend(struct vl_compositor *c,
649                              unsigned layer, void *blend,
650                              bool is_clearing)
651{
652   assert(c && blend);
653
654   assert(layer < VL_COMPOSITOR_MAX_LAYERS);
655
656   c->layers[layer].clearing = is_clearing;
657   c->layers[layer].blend = blend;
658}
659
660void
661vl_compositor_set_buffer_layer(struct vl_compositor *c,
662                               unsigned layer,
663                               struct pipe_video_buffer *buffer,
664                               struct pipe_video_rect *src_rect,
665                               struct pipe_video_rect *dst_rect)
666{
667   struct pipe_sampler_view **sampler_views;
668   unsigned i;
669
670   assert(c && buffer);
671
672   assert(layer < VL_COMPOSITOR_MAX_LAYERS);
673
674   c->used_layers |= 1 << layer;
675   c->layers[layer].fs = c->fs_video_buffer;
676
677   sampler_views = buffer->get_sampler_view_components(buffer);
678   for (i = 0; i < 3; ++i) {
679      c->layers[layer].samplers[i] = c->sampler_linear;
680      pipe_sampler_view_reference(&c->layers[layer].sampler_views[i], sampler_views[i]);
681   }
682
683   calc_src_and_dst(&c->layers[layer], buffer->width, buffer->height,
684                    src_rect ? *src_rect : default_rect(&c->layers[layer]),
685                    dst_rect ? *dst_rect : default_rect(&c->layers[layer]));
686}
687
688void
689vl_compositor_set_palette_layer(struct vl_compositor *c,
690                                unsigned layer,
691                                struct pipe_sampler_view *indexes,
692                                struct pipe_sampler_view *palette,
693                                struct pipe_video_rect *src_rect,
694                                struct pipe_video_rect *dst_rect,
695                                bool include_color_conversion)
696{
697   assert(c && indexes && palette);
698
699   assert(layer < VL_COMPOSITOR_MAX_LAYERS);
700
701   c->used_layers |= 1 << layer;
702
703   c->layers[layer].fs = include_color_conversion ?
704      c->fs_palette.yuv : c->fs_palette.rgb;
705
706   c->layers[layer].samplers[0] = c->sampler_linear;
707   c->layers[layer].samplers[1] = c->sampler_nearest;
708   c->layers[layer].samplers[2] = NULL;
709   pipe_sampler_view_reference(&c->layers[layer].sampler_views[0], indexes);
710   pipe_sampler_view_reference(&c->layers[layer].sampler_views[1], palette);
711   pipe_sampler_view_reference(&c->layers[layer].sampler_views[2], NULL);
712   calc_src_and_dst(&c->layers[layer], indexes->texture->width0, indexes->texture->height0,
713                    src_rect ? *src_rect : default_rect(&c->layers[layer]),
714                    dst_rect ? *dst_rect : default_rect(&c->layers[layer]));
715}
716
717void
718vl_compositor_set_rgba_layer(struct vl_compositor *c,
719                             unsigned layer,
720                             struct pipe_sampler_view *rgba,
721                             struct pipe_video_rect *src_rect,
722                             struct pipe_video_rect *dst_rect)
723{
724   assert(c && rgba);
725
726   assert(layer < VL_COMPOSITOR_MAX_LAYERS);
727
728   c->used_layers |= 1 << layer;
729   c->layers[layer].fs = c->fs_rgba;
730   c->layers[layer].samplers[0] = c->sampler_linear;
731   c->layers[layer].samplers[1] = NULL;
732   c->layers[layer].samplers[2] = NULL;
733   pipe_sampler_view_reference(&c->layers[layer].sampler_views[0], rgba);
734   pipe_sampler_view_reference(&c->layers[layer].sampler_views[1], NULL);
735   pipe_sampler_view_reference(&c->layers[layer].sampler_views[2], NULL);
736   calc_src_and_dst(&c->layers[layer], rgba->texture->width0, rgba->texture->height0,
737                    src_rect ? *src_rect : default_rect(&c->layers[layer]),
738                    dst_rect ? *dst_rect : default_rect(&c->layers[layer]));
739}
740
741void
742vl_compositor_render(struct vl_compositor   *c,
743                     struct pipe_surface    *dst_surface,
744                     struct pipe_video_rect *dst_area,
745                     struct pipe_video_rect *dst_clip,
746                     struct u_rect          *dirty_area)
747{
748   assert(c);
749   assert(dst_surface);
750
751   c->fb_state.width = dst_surface->width;
752   c->fb_state.height = dst_surface->height;
753   c->fb_state.cbufs[0] = dst_surface;
754
755   if (dst_area) {
756      c->viewport.scale[0] = dst_area->w;
757      c->viewport.scale[1] = dst_area->h;
758      c->viewport.translate[0] = dst_area->x;
759      c->viewport.translate[1] = dst_area->y;
760   } else {
761      c->viewport.scale[0] = dst_surface->width;
762      c->viewport.scale[1] = dst_surface->height;
763      c->viewport.translate[0] = 0;
764      c->viewport.translate[1] = 0;
765   }
766
767   if (dst_clip) {
768      c->scissor.minx = dst_clip->x;
769      c->scissor.miny = dst_clip->y;
770      c->scissor.maxx = dst_clip->x + dst_clip->w;
771      c->scissor.maxy = dst_clip->y + dst_clip->h;
772   } else {
773      c->scissor.minx = 0;
774      c->scissor.miny = 0;
775      c->scissor.maxx = dst_surface->width;
776      c->scissor.maxy = dst_surface->height;
777   }
778
779   gen_vertex_data(c, dirty_area);
780
781   if (dirty_area && (dirty_area->x0 < dirty_area->x1 ||
782                      dirty_area->y0 < dirty_area->y1)) {
783
784      c->pipe->clear_render_target(c->pipe, dst_surface, &c->clear_color,
785                                   0, 0, dst_surface->width, dst_surface->height);
786      dirty_area->x0 = dirty_area->y0 = MAX_DIRTY;
787      dirty_area->x0 = dirty_area->y1 = MIN_DIRTY;
788   }
789
790   c->pipe->set_scissor_state(c->pipe, &c->scissor);
791   c->pipe->set_framebuffer_state(c->pipe, &c->fb_state);
792   c->pipe->set_viewport_state(c->pipe, &c->viewport);
793   c->pipe->bind_vs_state(c->pipe, c->vs);
794   c->pipe->set_vertex_buffers(c->pipe, 1, &c->vertex_buf);
795   c->pipe->bind_vertex_elements_state(c->pipe, c->vertex_elems_state);
796   c->pipe->set_constant_buffer(c->pipe, PIPE_SHADER_FRAGMENT, 0, c->csc_matrix);
797   c->pipe->bind_rasterizer_state(c->pipe, c->rast);
798
799   draw_layers(c, dirty_area);
800}
801
802bool
803vl_compositor_init(struct vl_compositor *c, struct pipe_context *pipe)
804{
805   csc_matrix csc_matrix;
806
807   c->pipe = pipe;
808
809   if (!init_pipe_state(c))
810      return false;
811
812   if (!init_shaders(c)) {
813      cleanup_pipe_state(c);
814      return false;
815   }
816
817   if (!init_buffers(c)) {
818      cleanup_shaders(c);
819      cleanup_pipe_state(c);
820      return false;
821   }
822
823   vl_compositor_clear_layers(c);
824
825   vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY, NULL, true, csc_matrix);
826   vl_compositor_set_csc_matrix(c, csc_matrix);
827
828   c->clear_color.f[0] = c->clear_color.f[1] = 0.0f;
829   c->clear_color.f[2] = c->clear_color.f[3] = 0.0f;
830
831   return true;
832}
833