Home | History | Annotate | Download | only in vl
      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 
     46 enum VS_OUTPUT
     47 {
     48    VS_O_VPOS = 0,
     49    VS_O_COLOR = 0,
     50    VS_O_VTEX = 0,
     51    VS_O_VTOP,
     52    VS_O_VBOTTOM,
     53 };
     54 
     55 static void *
     56 create_vert_shader(struct vl_compositor *c)
     57 {
     58    struct ureg_program *shader;
     59    struct ureg_src vpos, vtex, color;
     60    struct ureg_dst tmp;
     61    struct ureg_dst o_vpos, o_vtex, o_color;
     62    struct ureg_dst o_vtop, o_vbottom;
     63 
     64    shader = ureg_create(TGSI_PROCESSOR_VERTEX);
     65    if (!shader)
     66       return false;
     67 
     68    vpos = ureg_DECL_vs_input(shader, 0);
     69    vtex = ureg_DECL_vs_input(shader, 1);
     70    color = ureg_DECL_vs_input(shader, 2);
     71    tmp = ureg_DECL_temporary(shader);
     72    o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);
     73    o_color = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, VS_O_COLOR);
     74    o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX);
     75    o_vtop = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP);
     76    o_vbottom = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM);
     77 
     78    /*
     79     * o_vpos = vpos
     80     * o_vtex = vtex
     81     * o_color = color
     82     */
     83    ureg_MOV(shader, o_vpos, vpos);
     84    ureg_MOV(shader, o_vtex, vtex);
     85    ureg_MOV(shader, o_color, color);
     86 
     87    /*
     88     * tmp.x = vtex.w / 2
     89     * tmp.y = vtex.w / 4
     90     *
     91     * o_vtop.x = vtex.x
     92     * o_vtop.y = vtex.y * tmp.x + 0.25f
     93     * o_vtop.z = vtex.y * tmp.y + 0.25f
     94     * o_vtop.w = 1 / tmp.x
     95     *
     96     * o_vbottom.x = vtex.x
     97     * o_vbottom.y = vtex.y * tmp.x - 0.25f
     98     * o_vbottom.z = vtex.y * tmp.y - 0.25f
     99     * o_vbottom.w = 1 / tmp.y
    100     */
    101    ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_X),
    102             ureg_scalar(vtex, TGSI_SWIZZLE_W), ureg_imm1f(shader, 0.5f));
    103    ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y),
    104             ureg_scalar(vtex, TGSI_SWIZZLE_W), ureg_imm1f(shader, 0.25f));
    105 
    106    ureg_MOV(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_X), vtex);
    107    ureg_MAD(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_Y), ureg_scalar(vtex, TGSI_SWIZZLE_Y),
    108             ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_imm1f(shader, 0.25f));
    109    ureg_MAD(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_Z), ureg_scalar(vtex, TGSI_SWIZZLE_Y),
    110             ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y), ureg_imm1f(shader, 0.25f));
    111    ureg_RCP(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_W),
    112             ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X));
    113 
    114    ureg_MOV(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_X), vtex);
    115    ureg_MAD(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_Y), ureg_scalar(vtex, TGSI_SWIZZLE_Y),
    116             ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_imm1f(shader, -0.25f));
    117    ureg_MAD(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_Z), ureg_scalar(vtex, TGSI_SWIZZLE_Y),
    118             ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y), ureg_imm1f(shader, -0.25f));
    119    ureg_RCP(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_W),
    120             ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y));
    121 
    122    ureg_END(shader);
    123 
    124    return ureg_create_shader_and_destroy(shader, c->pipe);
    125 }
    126 
    127 static void *
    128 create_frag_shader_video_buffer(struct vl_compositor *c)
    129 {
    130    struct ureg_program *shader;
    131    struct ureg_src tc;
    132    struct ureg_src csc[3];
    133    struct ureg_src sampler[3];
    134    struct ureg_dst texel;
    135    struct ureg_dst fragment;
    136    unsigned i;
    137 
    138    shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
    139    if (!shader)
    140       return false;
    141 
    142    tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR);
    143    for (i = 0; i < 3; ++i) {
    144       csc[i] = ureg_DECL_constant(shader, i);
    145       sampler[i] = ureg_DECL_sampler(shader, i);
    146    }
    147    texel = ureg_DECL_temporary(shader);
    148    fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
    149 
    150    /*
    151     * texel.xyz = tex(tc, sampler[i])
    152     * fragment = csc * texel
    153     */
    154    for (i = 0; i < 3; ++i)
    155       ureg_TEX(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), TGSI_TEXTURE_3D, tc, sampler[i]);
    156 
    157    ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f));
    158 
    159    for (i = 0; i < 3; ++i)
    160       ureg_DP4(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(texel));
    161 
    162    ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f));
    163 
    164    ureg_release_temporary(shader, texel);
    165    ureg_END(shader);
    166 
    167    return ureg_create_shader_and_destroy(shader, c->pipe);
    168 }
    169 
    170 static void *
    171 create_frag_shader_weave(struct vl_compositor *c)
    172 {
    173    struct ureg_program *shader;
    174    struct ureg_src i_tc[2];
    175    struct ureg_src csc[3];
    176    struct ureg_src sampler[3];
    177    struct ureg_dst t_tc[2];
    178    struct ureg_dst t_texel[2];
    179    struct ureg_dst o_fragment;
    180    unsigned i, j;
    181 
    182    shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
    183    if (!shader)
    184       return false;
    185 
    186    i_tc[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP, TGSI_INTERPOLATE_LINEAR);
    187    i_tc[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM, TGSI_INTERPOLATE_LINEAR);
    188 
    189    for (i = 0; i < 3; ++i) {
    190       csc[i] = ureg_DECL_constant(shader, i);
    191       sampler[i] = ureg_DECL_sampler(shader, i);
    192    }
    193 
    194    for (i = 0; i < 2; ++i) {
    195       t_tc[i] = ureg_DECL_temporary(shader);
    196       t_texel[i] = ureg_DECL_temporary(shader);
    197    }
    198    o_fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
    199 
    200    /* calculate the texture offsets
    201     * t_tc.x = i_tc.x
    202     * t_tc.y = (round(i_tc.y) + 0.5) / height * 2
    203     */
    204    for (i = 0; i < 2; ++i) {
    205       ureg_MOV(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_X), i_tc[i]);
    206       ureg_ROUND(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_YZ), i_tc[i]);
    207       ureg_MOV(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_W),
    208                ureg_imm1f(shader, i ? 0.75f : 0.25f));
    209       ureg_ADD(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_YZ),
    210                ureg_src(t_tc[i]), ureg_imm1f(shader, 0.5f));
    211       ureg_MUL(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_Y),
    212                ureg_src(t_tc[i]), ureg_scalar(i_tc[0], TGSI_SWIZZLE_W));
    213       ureg_MUL(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_Z),
    214                ureg_src(t_tc[i]), ureg_scalar(i_tc[1], TGSI_SWIZZLE_W));
    215    }
    216 
    217    /* fetch the texels
    218     * texel[0..1].x = tex(t_tc[0..1][0])
    219     * texel[0..1].y = tex(t_tc[0..1][1])
    220     * texel[0..1].z = tex(t_tc[0..1][2])
    221     */
    222    for (i = 0; i < 2; ++i)
    223       for (j = 0; j < 3; ++j) {
    224          struct ureg_src src = ureg_swizzle(ureg_src(t_tc[i]),
    225             TGSI_SWIZZLE_X, j ? TGSI_SWIZZLE_Z : TGSI_SWIZZLE_Y, TGSI_SWIZZLE_W, TGSI_SWIZZLE_W);
    226 
    227          ureg_TEX(shader, ureg_writemask(t_texel[i], TGSI_WRITEMASK_X << j),
    228                   TGSI_TEXTURE_3D, src, sampler[j]);
    229       }
    230 
    231    /* calculate linear interpolation factor
    232     * factor = |round(i_tc.y) - i_tc.y| * 2
    233     */
    234    ureg_ROUND(shader, ureg_writemask(t_tc[0], TGSI_WRITEMASK_YZ), i_tc[0]);
    235    ureg_ADD(shader, ureg_writemask(t_tc[0], TGSI_WRITEMASK_YZ),
    236             ureg_src(t_tc[0]), ureg_negate(i_tc[0]));
    237    ureg_MUL(shader, ureg_writemask(t_tc[0], TGSI_WRITEMASK_XY),
    238             ureg_abs(ureg_src(t_tc[0])), ureg_imm1f(shader, 2.0f));
    239    ureg_LRP(shader, t_texel[0], ureg_swizzle(ureg_src(t_tc[0]),
    240             TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z),
    241             ureg_src(t_texel[1]), ureg_src(t_texel[0]));
    242 
    243    /* and finally do colour space transformation
    244     * fragment = csc * texel
    245     */
    246    ureg_MOV(shader, ureg_writemask(t_texel[0], TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f));
    247    for (i = 0; i < 3; ++i)
    248       ureg_DP4(shader, ureg_writemask(o_fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(t_texel[0]));
    249 
    250    ureg_MOV(shader, ureg_writemask(o_fragment, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f));
    251 
    252    for (i = 0; i < 2; ++i) {
    253       ureg_release_temporary(shader, t_texel[i]);
    254       ureg_release_temporary(shader, t_tc[i]);
    255    }
    256 
    257    ureg_END(shader);
    258 
    259    return ureg_create_shader_and_destroy(shader, c->pipe);
    260 }
    261 
    262 static void *
    263 create_frag_shader_palette(struct vl_compositor *c, bool include_cc)
    264 {
    265    struct ureg_program *shader;
    266    struct ureg_src csc[3];
    267    struct ureg_src tc;
    268    struct ureg_src sampler;
    269    struct ureg_src palette;
    270    struct ureg_dst texel;
    271    struct ureg_dst fragment;
    272    unsigned i;
    273 
    274    shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
    275    if (!shader)
    276       return false;
    277 
    278    for (i = 0; include_cc && i < 3; ++i)
    279       csc[i] = ureg_DECL_constant(shader, i);
    280 
    281    tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR);
    282    sampler = ureg_DECL_sampler(shader, 0);
    283    palette = ureg_DECL_sampler(shader, 1);
    284 
    285    texel = ureg_DECL_temporary(shader);
    286    fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
    287 
    288    /*
    289     * texel = tex(tc, sampler)
    290     * fragment.xyz = tex(texel, palette) * csc
    291     * fragment.a = texel.a
    292     */
    293    ureg_TEX(shader, texel, TGSI_TEXTURE_2D, tc, sampler);
    294    ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), ureg_src(texel));
    295 
    296    if (include_cc) {
    297       ureg_TEX(shader, texel, TGSI_TEXTURE_1D, ureg_src(texel), palette);
    298       for (i = 0; i < 3; ++i)
    299          ureg_DP4(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(texel));
    300    } else {
    301       ureg_TEX(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XYZ),
    302                TGSI_TEXTURE_1D, ureg_src(texel), palette);
    303    }
    304 
    305    ureg_release_temporary(shader, texel);
    306    ureg_END(shader);
    307 
    308    return ureg_create_shader_and_destroy(shader, c->pipe);
    309 }
    310 
    311 static void *
    312 create_frag_shader_rgba(struct vl_compositor *c)
    313 {
    314    struct ureg_program *shader;
    315    struct ureg_src tc, color, sampler;
    316    struct ureg_dst texel, fragment;
    317 
    318    shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
    319    if (!shader)
    320       return false;
    321 
    322    tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR);
    323    color = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_COLOR, VS_O_COLOR, TGSI_INTERPOLATE_LINEAR);
    324    sampler = ureg_DECL_sampler(shader, 0);
    325    texel = ureg_DECL_temporary(shader);
    326    fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
    327 
    328    /*
    329     * fragment = tex(tc, sampler)
    330     */
    331    ureg_TEX(shader, texel, TGSI_TEXTURE_2D, tc, sampler);
    332    ureg_MUL(shader, fragment, ureg_src(texel), color);
    333    ureg_END(shader);
    334 
    335    return ureg_create_shader_and_destroy(shader, c->pipe);
    336 }
    337 
    338 static bool
    339 init_shaders(struct vl_compositor *c)
    340 {
    341    assert(c);
    342 
    343    c->vs = create_vert_shader(c);
    344    if (!c->vs) {
    345       debug_printf("Unable to create vertex shader.\n");
    346       return false;
    347    }
    348 
    349    c->fs_video_buffer = create_frag_shader_video_buffer(c);
    350    if (!c->fs_video_buffer) {
    351       debug_printf("Unable to create YCbCr-to-RGB fragment shader.\n");
    352       return false;
    353    }
    354 
    355    c->fs_weave = create_frag_shader_weave(c);
    356    if (!c->fs_weave) {
    357       debug_printf("Unable to create YCbCr-to-RGB weave fragment shader.\n");
    358       return false;
    359    }
    360 
    361    c->fs_palette.yuv = create_frag_shader_palette(c, true);
    362    if (!c->fs_palette.yuv) {
    363       debug_printf("Unable to create YUV-Palette-to-RGB fragment shader.\n");
    364       return false;
    365    }
    366 
    367    c->fs_palette.rgb = create_frag_shader_palette(c, false);
    368    if (!c->fs_palette.rgb) {
    369       debug_printf("Unable to create RGB-Palette-to-RGB fragment shader.\n");
    370       return false;
    371    }
    372 
    373    c->fs_rgba = create_frag_shader_rgba(c);
    374    if (!c->fs_rgba) {
    375       debug_printf("Unable to create RGB-to-RGB fragment shader.\n");
    376       return false;
    377    }
    378 
    379    return true;
    380 }
    381 
    382 static void cleanup_shaders(struct vl_compositor *c)
    383 {
    384    assert(c);
    385 
    386    c->pipe->delete_vs_state(c->pipe, c->vs);
    387    c->pipe->delete_fs_state(c->pipe, c->fs_video_buffer);
    388    c->pipe->delete_fs_state(c->pipe, c->fs_weave);
    389    c->pipe->delete_fs_state(c->pipe, c->fs_palette.yuv);
    390    c->pipe->delete_fs_state(c->pipe, c->fs_palette.rgb);
    391    c->pipe->delete_fs_state(c->pipe, c->fs_rgba);
    392 }
    393 
    394 static bool
    395 init_pipe_state(struct vl_compositor *c)
    396 {
    397    struct pipe_rasterizer_state rast;
    398    struct pipe_sampler_state sampler;
    399    struct pipe_blend_state blend;
    400    struct pipe_depth_stencil_alpha_state dsa;
    401    unsigned i;
    402 
    403    assert(c);
    404 
    405    c->fb_state.nr_cbufs = 1;
    406    c->fb_state.zsbuf = NULL;
    407 
    408    memset(&sampler, 0, sizeof(sampler));
    409    sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
    410    sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
    411    sampler.wrap_r = PIPE_TEX_WRAP_REPEAT;
    412    sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
    413    sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
    414    sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
    415    sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
    416    sampler.compare_func = PIPE_FUNC_ALWAYS;
    417    sampler.normalized_coords = 1;
    418 
    419    c->sampler_linear = c->pipe->create_sampler_state(c->pipe, &sampler);
    420 
    421    sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
    422    sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
    423    c->sampler_nearest = c->pipe->create_sampler_state(c->pipe, &sampler);
    424 
    425    memset(&blend, 0, sizeof blend);
    426    blend.independent_blend_enable = 0;
    427    blend.rt[0].blend_enable = 0;
    428    blend.logicop_enable = 0;
    429    blend.logicop_func = PIPE_LOGICOP_CLEAR;
    430    blend.rt[0].colormask = PIPE_MASK_RGBA;
    431    blend.dither = 0;
    432    c->blend_clear = c->pipe->create_blend_state(c->pipe, &blend);
    433 
    434    blend.rt[0].blend_enable = 1;
    435    blend.rt[0].rgb_func = PIPE_BLEND_ADD;
    436    blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
    437    blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
    438    blend.rt[0].alpha_func = PIPE_BLEND_ADD;
    439    blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
    440    blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
    441    c->blend_add = c->pipe->create_blend_state(c->pipe, &blend);
    442 
    443    memset(&rast, 0, sizeof rast);
    444    rast.flatshade = 0;
    445    rast.front_ccw = 1;
    446    rast.cull_face = PIPE_FACE_NONE;
    447    rast.fill_back = PIPE_POLYGON_MODE_FILL;
    448    rast.fill_front = PIPE_POLYGON_MODE_FILL;
    449    rast.scissor = 1;
    450    rast.line_width = 1;
    451    rast.point_size_per_vertex = 1;
    452    rast.offset_units = 1;
    453    rast.offset_scale = 1;
    454    rast.gl_rasterization_rules = 1;
    455    rast.depth_clip = 1;
    456 
    457    c->rast = c->pipe->create_rasterizer_state(c->pipe, &rast);
    458 
    459    memset(&dsa, 0, sizeof dsa);
    460    dsa.depth.enabled = 0;
    461    dsa.depth.writemask = 0;
    462    dsa.depth.func = PIPE_FUNC_ALWAYS;
    463    for (i = 0; i < 2; ++i) {
    464       dsa.stencil[i].enabled = 0;
    465       dsa.stencil[i].func = PIPE_FUNC_ALWAYS;
    466       dsa.stencil[i].fail_op = PIPE_STENCIL_OP_KEEP;
    467       dsa.stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP;
    468       dsa.stencil[i].zfail_op = PIPE_STENCIL_OP_KEEP;
    469       dsa.stencil[i].valuemask = 0;
    470       dsa.stencil[i].writemask = 0;
    471    }
    472    dsa.alpha.enabled = 0;
    473    dsa.alpha.func = PIPE_FUNC_ALWAYS;
    474    dsa.alpha.ref_value = 0;
    475    c->dsa = c->pipe->create_depth_stencil_alpha_state(c->pipe, &dsa);
    476    c->pipe->bind_depth_stencil_alpha_state(c->pipe, c->dsa);
    477 
    478    return true;
    479 }
    480 
    481 static void cleanup_pipe_state(struct vl_compositor *c)
    482 {
    483    assert(c);
    484 
    485    /* Asserted in softpipe_delete_fs_state() for some reason */
    486    c->pipe->bind_vs_state(c->pipe, NULL);
    487    c->pipe->bind_fs_state(c->pipe, NULL);
    488 
    489    c->pipe->delete_depth_stencil_alpha_state(c->pipe, c->dsa);
    490    c->pipe->delete_sampler_state(c->pipe, c->sampler_linear);
    491    c->pipe->delete_sampler_state(c->pipe, c->sampler_nearest);
    492    c->pipe->delete_blend_state(c->pipe, c->blend_clear);
    493    c->pipe->delete_blend_state(c->pipe, c->blend_add);
    494    c->pipe->delete_rasterizer_state(c->pipe, c->rast);
    495 }
    496 
    497 static bool
    498 create_vertex_buffer(struct vl_compositor *c)
    499 {
    500    assert(c);
    501 
    502    pipe_resource_reference(&c->vertex_buf.buffer, NULL);
    503    c->vertex_buf.buffer = pipe_buffer_create
    504    (
    505       c->pipe->screen,
    506       PIPE_BIND_VERTEX_BUFFER,
    507       PIPE_USAGE_STREAM,
    508       c->vertex_buf.stride * VL_COMPOSITOR_MAX_LAYERS * 4
    509    );
    510 
    511    return c->vertex_buf.buffer != NULL;
    512 }
    513 
    514 static bool
    515 init_buffers(struct vl_compositor *c)
    516 {
    517    struct pipe_vertex_element vertex_elems[3];
    518 
    519    assert(c);
    520 
    521    /*
    522     * Create our vertex buffer and vertex buffer elements
    523     */
    524    c->vertex_buf.stride = sizeof(struct vertex2f) + sizeof(struct vertex4f) * 2;
    525    c->vertex_buf.buffer_offset = 0;
    526    create_vertex_buffer(c);
    527 
    528    vertex_elems[0].src_offset = 0;
    529    vertex_elems[0].instance_divisor = 0;
    530    vertex_elems[0].vertex_buffer_index = 0;
    531    vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
    532    vertex_elems[1].src_offset = sizeof(struct vertex2f);
    533    vertex_elems[1].instance_divisor = 0;
    534    vertex_elems[1].vertex_buffer_index = 0;
    535    vertex_elems[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
    536    vertex_elems[2].src_offset = sizeof(struct vertex2f) + sizeof(struct vertex4f);
    537    vertex_elems[2].instance_divisor = 0;
    538    vertex_elems[2].vertex_buffer_index = 0;
    539    vertex_elems[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
    540    c->vertex_elems_state = c->pipe->create_vertex_elements_state(c->pipe, 3, vertex_elems);
    541 
    542    return true;
    543 }
    544 
    545 static void
    546 cleanup_buffers(struct vl_compositor *c)
    547 {
    548    assert(c);
    549 
    550    c->pipe->delete_vertex_elements_state(c->pipe, c->vertex_elems_state);
    551    pipe_resource_reference(&c->vertex_buf.buffer, NULL);
    552 }
    553 
    554 static INLINE struct u_rect
    555 default_rect(struct vl_compositor_layer *layer)
    556 {
    557    struct pipe_resource *res = layer->sampler_views[0]->texture;
    558    struct u_rect rect = { 0, res->width0, 0, res->height0 * res->depth0 };
    559    return rect;
    560 }
    561 
    562 static INLINE struct vertex2f
    563 calc_topleft(struct vertex2f size, struct u_rect rect)
    564 {
    565    struct vertex2f res = { rect.x0 / size.x, rect.y0 / size.y };
    566    return res;
    567 }
    568 
    569 static INLINE struct vertex2f
    570 calc_bottomright(struct vertex2f size, struct u_rect rect)
    571 {
    572    struct vertex2f res = { rect.x1 / size.x, rect.y1 / size.y };
    573    return res;
    574 }
    575 
    576 static INLINE void
    577 calc_src_and_dst(struct vl_compositor_layer *layer, unsigned width, unsigned height,
    578                  struct u_rect src, struct u_rect dst)
    579 {
    580    struct vertex2f size =  { width, height };
    581 
    582    layer->src.tl = calc_topleft(size, src);
    583    layer->src.br = calc_bottomright(size, src);
    584    layer->dst.tl = calc_topleft(size, dst);
    585    layer->dst.br = calc_bottomright(size, dst);
    586    layer->zw.x = 0.0f;
    587    layer->zw.y = size.y;
    588 }
    589 
    590 static void
    591 gen_rect_verts(struct vertex2f *vb, struct vl_compositor_layer *layer)
    592 {
    593    assert(vb && layer);
    594 
    595    vb[ 0].x = layer->dst.tl.x;
    596    vb[ 0].y = layer->dst.tl.y;
    597    vb[ 1].x = layer->src.tl.x;
    598    vb[ 1].y = layer->src.tl.y;
    599    vb[ 2] = layer->zw;
    600    vb[ 3].x = layer->colors[0].x;
    601    vb[ 3].y = layer->colors[0].y;
    602    vb[ 4].x = layer->colors[0].z;
    603    vb[ 4].y = layer->colors[0].w;
    604 
    605    vb[ 5].x = layer->dst.br.x;
    606    vb[ 5].y = layer->dst.tl.y;
    607    vb[ 6].x = layer->src.br.x;
    608    vb[ 6].y = layer->src.tl.y;
    609    vb[ 7] = layer->zw;
    610    vb[ 8].x = layer->colors[1].x;
    611    vb[ 8].y = layer->colors[1].y;
    612    vb[ 9].x = layer->colors[1].z;
    613    vb[ 9].y = layer->colors[1].w;
    614 
    615    vb[10].x = layer->dst.br.x;
    616    vb[10].y = layer->dst.br.y;
    617    vb[11].x = layer->src.br.x;
    618    vb[11].y = layer->src.br.y;
    619    vb[12] = layer->zw;
    620    vb[13].x = layer->colors[2].x;
    621    vb[13].y = layer->colors[2].y;
    622    vb[14].x = layer->colors[2].z;
    623    vb[14].y = layer->colors[2].w;
    624 
    625    vb[15].x = layer->dst.tl.x;
    626    vb[15].y = layer->dst.br.y;
    627    vb[16].x = layer->src.tl.x;
    628    vb[16].y = layer->src.br.y;
    629    vb[17] = layer->zw;
    630    vb[18].x = layer->colors[3].x;
    631    vb[18].y = layer->colors[3].y;
    632    vb[19].x = layer->colors[3].z;
    633    vb[19].y = layer->colors[3].w;
    634 }
    635 
    636 static INLINE struct u_rect
    637 calc_drawn_area(struct vl_compositor_state *s, struct vl_compositor_layer *layer)
    638 {
    639    struct u_rect result;
    640 
    641    // scale
    642    result.x0 = layer->dst.tl.x * layer->viewport.scale[0] + layer->viewport.translate[0];
    643    result.y0 = layer->dst.tl.y * layer->viewport.scale[1] + layer->viewport.translate[1];
    644    result.x1 = layer->dst.br.x * layer->viewport.scale[0] + layer->viewport.translate[0];
    645    result.y1 = layer->dst.br.y * layer->viewport.scale[1] + layer->viewport.translate[1];
    646 
    647    // and clip
    648    result.x0 = MAX2(result.x0, s->scissor.minx);
    649    result.y0 = MAX2(result.y0, s->scissor.miny);
    650    result.x1 = MIN2(result.x1, s->scissor.maxx);
    651    result.y1 = MIN2(result.y1, s->scissor.maxy);
    652    return result;
    653 }
    654 
    655 static void
    656 gen_vertex_data(struct vl_compositor *c, struct vl_compositor_state *s, struct u_rect *dirty)
    657 {
    658    struct vertex2f *vb;
    659    struct pipe_transfer *buf_transfer;
    660    unsigned i;
    661 
    662    assert(c);
    663 
    664    vb = pipe_buffer_map(c->pipe, c->vertex_buf.buffer,
    665                         PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE | PIPE_TRANSFER_DONTBLOCK,
    666                         &buf_transfer);
    667 
    668    if (!vb) {
    669       // If buffer is still locked from last draw create a new one
    670       create_vertex_buffer(c);
    671       vb = pipe_buffer_map(c->pipe, c->vertex_buf.buffer,
    672                            PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE,
    673                            &buf_transfer);
    674    }
    675 
    676    for (i = 0; i < VL_COMPOSITOR_MAX_LAYERS; i++) {
    677       if (s->used_layers & (1 << i)) {
    678          struct vl_compositor_layer *layer = &s->layers[i];
    679          gen_rect_verts(vb, layer);
    680          vb += 20;
    681 
    682          if (!layer->viewport_valid) {
    683             layer->viewport.scale[0] = c->fb_state.width;
    684             layer->viewport.scale[1] = c->fb_state.height;
    685             layer->viewport.translate[0] = 0;
    686             layer->viewport.translate[1] = 0;
    687          }
    688 
    689          if (dirty && layer->clearing) {
    690             struct u_rect drawn = calc_drawn_area(s, layer);
    691             if (
    692              dirty->x0 >= drawn.x0 &&
    693              dirty->y0 >= drawn.y0 &&
    694              dirty->x1 <= drawn.x1 &&
    695              dirty->y1 <= drawn.y1) {
    696 
    697                // We clear the dirty area anyway, no need for clear_render_target
    698                dirty->x0 = dirty->y0 = MAX_DIRTY;
    699                dirty->x1 = dirty->y1 = MIN_DIRTY;
    700             }
    701          }
    702       }
    703    }
    704 
    705    pipe_buffer_unmap(c->pipe, buf_transfer);
    706 }
    707 
    708 static void
    709 draw_layers(struct vl_compositor *c, struct vl_compositor_state *s, struct u_rect *dirty)
    710 {
    711    unsigned vb_index, i;
    712 
    713    assert(c);
    714 
    715    for (i = 0, vb_index = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) {
    716       if (s->used_layers & (1 << i)) {
    717          struct vl_compositor_layer *layer = &s->layers[i];
    718          struct pipe_sampler_view **samplers = &layer->sampler_views[0];
    719          unsigned num_sampler_views = !samplers[1] ? 1 : !samplers[2] ? 2 : 3;
    720          void *blend = layer->blend ? layer->blend : i ? c->blend_add : c->blend_clear;
    721 
    722          c->pipe->bind_blend_state(c->pipe, blend);
    723          c->pipe->set_viewport_state(c->pipe, &layer->viewport);
    724          c->pipe->bind_fs_state(c->pipe, layer->fs);
    725          c->pipe->bind_fragment_sampler_states(c->pipe, num_sampler_views, layer->samplers);
    726          c->pipe->set_fragment_sampler_views(c->pipe, num_sampler_views, samplers);
    727          util_draw_arrays(c->pipe, PIPE_PRIM_QUADS, vb_index * 4, 4);
    728          vb_index++;
    729 
    730          if (dirty) {
    731             // Remember the currently drawn area as dirty for the next draw command
    732             struct u_rect drawn = calc_drawn_area(s, layer);
    733             dirty->x0 = MIN2(drawn.x0, dirty->x0);
    734             dirty->y0 = MIN2(drawn.y0, dirty->y0);
    735             dirty->x1 = MAX2(drawn.x1, dirty->x1);
    736             dirty->y1 = MAX2(drawn.y1, dirty->y1);
    737          }
    738       }
    739    }
    740 }
    741 
    742 void
    743 vl_compositor_reset_dirty_area(struct u_rect *dirty)
    744 {
    745    assert(dirty);
    746 
    747    dirty->x0 = dirty->y0 = MIN_DIRTY;
    748    dirty->x1 = dirty->y1 = MAX_DIRTY;
    749 }
    750 
    751 void
    752 vl_compositor_set_clear_color(struct vl_compositor_state *s, union pipe_color_union *color)
    753 {
    754    assert(s);
    755    assert(color);
    756 
    757    s->clear_color = *color;
    758 }
    759 
    760 void
    761 vl_compositor_get_clear_color(struct vl_compositor_state *s, union pipe_color_union *color)
    762 {
    763    assert(s);
    764    assert(color);
    765 
    766    *color = s->clear_color;
    767 }
    768 
    769 void
    770 vl_compositor_clear_layers(struct vl_compositor_state *s)
    771 {
    772    unsigned i, j;
    773 
    774    assert(s);
    775 
    776    s->used_layers = 0;
    777    for ( i = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) {
    778       struct vertex4f v_one = { 1.0f, 1.0f, 1.0f, 1.0f };
    779       s->layers[i].clearing = i ? false : true;
    780       s->layers[i].blend = NULL;
    781       s->layers[i].fs = NULL;
    782       s->layers[i].viewport.scale[2] = 1;
    783       s->layers[i].viewport.scale[3] = 1;
    784       s->layers[i].viewport.translate[2] = 0;
    785       s->layers[i].viewport.translate[3] = 0;
    786 
    787       for ( j = 0; j < 3; j++)
    788          pipe_sampler_view_reference(&s->layers[i].sampler_views[j], NULL);
    789       for ( j = 0; j < 4; ++j)
    790          s->layers[i].colors[j] = v_one;
    791    }
    792 }
    793 
    794 void
    795 vl_compositor_cleanup(struct vl_compositor *c)
    796 {
    797    assert(c);
    798 
    799    cleanup_buffers(c);
    800    cleanup_shaders(c);
    801    cleanup_pipe_state(c);
    802 }
    803 
    804 void
    805 vl_compositor_set_csc_matrix(struct vl_compositor_state *s, vl_csc_matrix const *matrix)
    806 {
    807    struct pipe_transfer *buf_transfer;
    808 
    809    assert(s);
    810 
    811    memcpy
    812    (
    813       pipe_buffer_map(s->pipe, s->csc_matrix,
    814                       PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE,
    815                       &buf_transfer),
    816       matrix,
    817       sizeof(vl_csc_matrix)
    818    );
    819 
    820    pipe_buffer_unmap(s->pipe, buf_transfer);
    821 }
    822 
    823 void
    824 vl_compositor_set_dst_clip(struct vl_compositor_state *s, struct u_rect *dst_clip)
    825 {
    826    assert(s);
    827 
    828    s->scissor_valid = dst_clip != NULL;
    829    if (dst_clip) {
    830       s->scissor.minx = dst_clip->x0;
    831       s->scissor.miny = dst_clip->y0;
    832       s->scissor.maxx = dst_clip->x1;
    833       s->scissor.maxy = dst_clip->y1;
    834    }
    835 }
    836 
    837 void
    838 vl_compositor_set_layer_blend(struct vl_compositor_state *s,
    839                               unsigned layer, void *blend,
    840                               bool is_clearing)
    841 {
    842    assert(s && blend);
    843 
    844    assert(layer < VL_COMPOSITOR_MAX_LAYERS);
    845 
    846    s->layers[layer].clearing = is_clearing;
    847    s->layers[layer].blend = blend;
    848 }
    849 
    850 void
    851 vl_compositor_set_layer_dst_area(struct vl_compositor_state *s,
    852                                  unsigned layer, struct u_rect *dst_area)
    853 {
    854    assert(s);
    855 
    856    assert(layer < VL_COMPOSITOR_MAX_LAYERS);
    857 
    858    s->layers[layer].viewport_valid = dst_area != NULL;
    859    if (dst_area) {
    860       s->layers[layer].viewport.scale[0] = dst_area->x1 - dst_area->x0;
    861       s->layers[layer].viewport.scale[1] = dst_area->y1 - dst_area->y0;
    862       s->layers[layer].viewport.translate[0] = dst_area->x0;
    863       s->layers[layer].viewport.translate[1] = dst_area->y0;
    864    }
    865 }
    866 
    867 void
    868 vl_compositor_set_buffer_layer(struct vl_compositor_state *s,
    869                                struct vl_compositor *c,
    870                                unsigned layer,
    871                                struct pipe_video_buffer *buffer,
    872                                struct u_rect *src_rect,
    873                                struct u_rect *dst_rect,
    874                                enum vl_compositor_deinterlace deinterlace)
    875 {
    876    struct pipe_sampler_view **sampler_views;
    877    unsigned i;
    878 
    879    assert(s && c && buffer);
    880 
    881    assert(layer < VL_COMPOSITOR_MAX_LAYERS);
    882 
    883    s->used_layers |= 1 << layer;
    884    sampler_views = buffer->get_sampler_view_components(buffer);
    885    for (i = 0; i < 3; ++i) {
    886       s->layers[layer].samplers[i] = c->sampler_linear;
    887       pipe_sampler_view_reference(&s->layers[layer].sampler_views[i], sampler_views[i]);
    888    }
    889 
    890    calc_src_and_dst(&s->layers[layer], buffer->width, buffer->height,
    891                     src_rect ? *src_rect : default_rect(&s->layers[layer]),
    892                     dst_rect ? *dst_rect : default_rect(&s->layers[layer]));
    893 
    894    if (buffer->interlaced) {
    895       float half_a_line = 0.5f / s->layers[layer].zw.y;
    896       switch(deinterlace) {
    897       case VL_COMPOSITOR_WEAVE:
    898          s->layers[layer].fs = c->fs_weave;
    899          break;
    900 
    901       case VL_COMPOSITOR_BOB_TOP:
    902          s->layers[layer].zw.x = 0.25f;
    903          s->layers[layer].src.tl.y += half_a_line;
    904          s->layers[layer].src.br.y += half_a_line;
    905          s->layers[layer].fs = c->fs_video_buffer;
    906          break;
    907 
    908       case VL_COMPOSITOR_BOB_BOTTOM:
    909          s->layers[layer].zw.x = 0.75f;
    910          s->layers[layer].src.tl.y -= half_a_line;
    911          s->layers[layer].src.br.y -= half_a_line;
    912          s->layers[layer].fs = c->fs_video_buffer;
    913          break;
    914       }
    915 
    916    } else
    917       s->layers[layer].fs = c->fs_video_buffer;
    918 }
    919 
    920 void
    921 vl_compositor_set_palette_layer(struct vl_compositor_state *s,
    922                                 struct vl_compositor *c,
    923                                 unsigned layer,
    924                                 struct pipe_sampler_view *indexes,
    925                                 struct pipe_sampler_view *palette,
    926                                 struct u_rect *src_rect,
    927                                 struct u_rect *dst_rect,
    928                                 bool include_color_conversion)
    929 {
    930    assert(s && c && indexes && palette);
    931 
    932    assert(layer < VL_COMPOSITOR_MAX_LAYERS);
    933 
    934    s->used_layers |= 1 << layer;
    935 
    936    s->layers[layer].fs = include_color_conversion ?
    937       c->fs_palette.yuv : c->fs_palette.rgb;
    938 
    939    s->layers[layer].samplers[0] = c->sampler_linear;
    940    s->layers[layer].samplers[1] = c->sampler_nearest;
    941    s->layers[layer].samplers[2] = NULL;
    942    pipe_sampler_view_reference(&s->layers[layer].sampler_views[0], indexes);
    943    pipe_sampler_view_reference(&s->layers[layer].sampler_views[1], palette);
    944    pipe_sampler_view_reference(&s->layers[layer].sampler_views[2], NULL);
    945    calc_src_and_dst(&s->layers[layer], indexes->texture->width0, indexes->texture->height0,
    946                     src_rect ? *src_rect : default_rect(&s->layers[layer]),
    947                     dst_rect ? *dst_rect : default_rect(&s->layers[layer]));
    948 }
    949 
    950 void
    951 vl_compositor_set_rgba_layer(struct vl_compositor_state *s,
    952                              struct vl_compositor *c,
    953                              unsigned layer,
    954                              struct pipe_sampler_view *rgba,
    955                              struct u_rect *src_rect,
    956                              struct u_rect *dst_rect,
    957                              struct vertex4f *colors)
    958 {
    959    unsigned i;
    960 
    961    assert(s && c && rgba);
    962 
    963    assert(layer < VL_COMPOSITOR_MAX_LAYERS);
    964 
    965    s->used_layers |= 1 << layer;
    966    s->layers[layer].fs = c->fs_rgba;
    967    s->layers[layer].samplers[0] = c->sampler_linear;
    968    s->layers[layer].samplers[1] = NULL;
    969    s->layers[layer].samplers[2] = NULL;
    970    pipe_sampler_view_reference(&s->layers[layer].sampler_views[0], rgba);
    971    pipe_sampler_view_reference(&s->layers[layer].sampler_views[1], NULL);
    972    pipe_sampler_view_reference(&s->layers[layer].sampler_views[2], NULL);
    973    calc_src_and_dst(&s->layers[layer], rgba->texture->width0, rgba->texture->height0,
    974                     src_rect ? *src_rect : default_rect(&s->layers[layer]),
    975                     dst_rect ? *dst_rect : default_rect(&s->layers[layer]));
    976 
    977    if (colors)
    978       for (i = 0; i < 4; ++i)
    979          s->layers[layer].colors[i] = colors[i];
    980 }
    981 
    982 void
    983 vl_compositor_render(struct vl_compositor_state *s,
    984                      struct vl_compositor       *c,
    985                      struct pipe_surface        *dst_surface,
    986                      struct u_rect              *dirty_area)
    987 {
    988    assert(c);
    989    assert(dst_surface);
    990 
    991    c->fb_state.width = dst_surface->width;
    992    c->fb_state.height = dst_surface->height;
    993    c->fb_state.cbufs[0] = dst_surface;
    994 
    995    if (!s->scissor_valid) {
    996       s->scissor.minx = 0;
    997       s->scissor.miny = 0;
    998       s->scissor.maxx = dst_surface->width;
    999       s->scissor.maxy = dst_surface->height;
   1000    }
   1001 
   1002    gen_vertex_data(c, s, dirty_area);
   1003 
   1004    if (dirty_area && (dirty_area->x0 < dirty_area->x1 ||
   1005                       dirty_area->y0 < dirty_area->y1)) {
   1006 
   1007       c->pipe->clear_render_target(c->pipe, dst_surface, &s->clear_color,
   1008                                    0, 0, dst_surface->width, dst_surface->height);
   1009       dirty_area->x0 = dirty_area->y0 = MAX_DIRTY;
   1010       dirty_area->x1 = dirty_area->y1 = MIN_DIRTY;
   1011    }
   1012 
   1013    c->pipe->set_scissor_state(c->pipe, &s->scissor);
   1014    c->pipe->set_framebuffer_state(c->pipe, &c->fb_state);
   1015    c->pipe->bind_vs_state(c->pipe, c->vs);
   1016    c->pipe->set_vertex_buffers(c->pipe, 1, &c->vertex_buf);
   1017    c->pipe->bind_vertex_elements_state(c->pipe, c->vertex_elems_state);
   1018    pipe_set_constant_buffer(c->pipe, PIPE_SHADER_FRAGMENT, 0, s->csc_matrix);
   1019    c->pipe->bind_rasterizer_state(c->pipe, c->rast);
   1020 
   1021    draw_layers(c, s, dirty_area);
   1022 }
   1023 
   1024 bool
   1025 vl_compositor_init(struct vl_compositor *c, struct pipe_context *pipe)
   1026 {
   1027    assert(c);
   1028 
   1029    memset(c, 0, sizeof(*c));
   1030 
   1031    c->pipe = pipe;
   1032 
   1033    if (!init_pipe_state(c))
   1034       return false;
   1035 
   1036    if (!init_shaders(c)) {
   1037       cleanup_pipe_state(c);
   1038       return false;
   1039    }
   1040 
   1041    if (!init_buffers(c)) {
   1042       cleanup_shaders(c);
   1043       cleanup_pipe_state(c);
   1044       return false;
   1045    }
   1046 
   1047    return true;
   1048 }
   1049 
   1050 bool
   1051 vl_compositor_init_state(struct vl_compositor_state *s, struct pipe_context *pipe)
   1052 {
   1053    vl_csc_matrix csc_matrix;
   1054 
   1055    assert(s);
   1056 
   1057    memset(s, 0, sizeof(*s));
   1058 
   1059    s->pipe = pipe;
   1060 
   1061    s->clear_color.f[0] = s->clear_color.f[1] = 0.0f;
   1062    s->clear_color.f[2] = s->clear_color.f[3] = 0.0f;
   1063 
   1064    /*
   1065     * Create our fragment shader's constant buffer
   1066     * Const buffer contains the color conversion matrix and bias vectors
   1067     */
   1068    /* XXX: Create with IMMUTABLE/STATIC... although it does change every once in a long while... */
   1069    s->csc_matrix = pipe_buffer_create
   1070    (
   1071       pipe->screen,
   1072       PIPE_BIND_CONSTANT_BUFFER,
   1073       PIPE_USAGE_STATIC,
   1074       sizeof(csc_matrix)
   1075    );
   1076 
   1077    vl_compositor_clear_layers(s);
   1078 
   1079    vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY, NULL, true, &csc_matrix);
   1080    vl_compositor_set_csc_matrix(s, (const vl_csc_matrix *)&csc_matrix);
   1081 
   1082    return true;
   1083 }
   1084 
   1085 void
   1086 vl_compositor_cleanup_state(struct vl_compositor_state *s)
   1087 {
   1088    assert(s);
   1089 
   1090    vl_compositor_clear_layers(s);
   1091    pipe_resource_reference(&s->csc_matrix, NULL);
   1092 }
   1093