Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2011 Christian König
  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_screen.h"
  31. #include "pipe/p_context.h"
  32.  
  33. #include "util/u_draw.h"
  34. #include "util/u_sampler.h"
  35. #include "util/u_inlines.h"
  36. #include "util/u_memory.h"
  37.  
  38. #include "tgsi/tgsi_ureg.h"
  39.  
  40. #include "vl_defines.h"
  41. #include "vl_types.h"
  42.  
  43. #include "vl_zscan.h"
  44. #include "vl_vertex_buffers.h"
  45.  
  46. enum VS_OUTPUT
  47. {
  48.    VS_O_VPOS = 0,
  49.    VS_O_VTEX = 0
  50. };
  51.  
  52. const int vl_zscan_linear[] =
  53. {
  54.    /* Linear scan pattern */
  55.     0, 1, 2, 3, 4, 5, 6, 7,
  56.     8, 9,10,11,12,13,14,15,
  57.    16,17,18,19,20,21,22,23,
  58.    24,25,26,27,28,29,30,31,
  59.    32,33,34,35,36,37,38,39,
  60.    40,41,42,43,44,45,46,47,
  61.    48,49,50,51,52,53,54,55,
  62.    56,57,58,59,60,61,62,63
  63. };
  64.  
  65. const int vl_zscan_normal[] =
  66. {
  67.    /* Zig-Zag scan pattern */
  68.     0, 1, 8,16, 9, 2, 3,10,
  69.    17,24,32,25,18,11, 4, 5,
  70.    12,19,26,33,40,48,41,34,
  71.    27,20,13, 6, 7,14,21,28,
  72.    35,42,49,56,57,50,43,36,
  73.    29,22,15,23,30,37,44,51,
  74.    58,59,52,45,38,31,39,46,
  75.    53,60,61,54,47,55,62,63
  76. };
  77.  
  78. const int vl_zscan_alternate[] =
  79. {
  80.    /* Alternate scan pattern */
  81.     0, 8,16,24, 1, 9, 2,10,
  82.    17,25,32,40,48,56,57,49,
  83.    41,33,26,18, 3,11, 4,12,
  84.    19,27,34,42,50,58,35,43,
  85.    51,59,20,28, 5,13, 6,14,
  86.    21,29,36,44,52,60,37,45,
  87.    53,61,22,30, 7,15,23,31,
  88.    38,46,54,62,39,47,55,63
  89. };
  90.  
  91. static void *
  92. create_vert_shader(struct vl_zscan *zscan)
  93. {
  94.    struct ureg_program *shader;
  95.  
  96.    struct ureg_src scale;
  97.    struct ureg_src vrect, vpos, block_num;
  98.  
  99.    struct ureg_dst tmp;
  100.    struct ureg_dst o_vpos;
  101.    struct ureg_dst *o_vtex;
  102.  
  103.    signed i;
  104.  
  105.    shader = ureg_create(TGSI_PROCESSOR_VERTEX);
  106.    if (!shader)
  107.       return NULL;
  108.  
  109.    o_vtex = MALLOC(zscan->num_channels * sizeof(struct ureg_dst));
  110.  
  111.    scale = ureg_imm2f(shader,
  112.       (float)VL_BLOCK_WIDTH / zscan->buffer_width,
  113.       (float)VL_BLOCK_HEIGHT / zscan->buffer_height);
  114.  
  115.    vrect = ureg_DECL_vs_input(shader, VS_I_RECT);
  116.    vpos = ureg_DECL_vs_input(shader, VS_I_VPOS);
  117.    block_num = ureg_DECL_vs_input(shader, VS_I_BLOCK_NUM);
  118.  
  119.    tmp = ureg_DECL_temporary(shader);
  120.  
  121.    o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);
  122.  
  123.    for (i = 0; i < zscan->num_channels; ++i)
  124.       o_vtex[i] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX + i);
  125.  
  126.    /*
  127.     * o_vpos.xy = (vpos + vrect) * scale
  128.     * o_vpos.zw = 1.0f
  129.     *
  130.     * tmp.xy = InstanceID / blocks_per_line
  131.     * tmp.x = frac(tmp.x)
  132.     * tmp.y = floor(tmp.y)
  133.     *
  134.     * o_vtex.x = vrect.x / blocks_per_line + tmp.x
  135.     * o_vtex.y = vrect.y
  136.     * o_vtex.z = tmp.z * blocks_per_line / blocks_total
  137.     */
  138.    ureg_ADD(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XY), vpos, vrect);
  139.    ureg_MUL(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_XY), ureg_src(tmp), scale);
  140.    ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_ZW), ureg_imm1f(shader, 1.0f));
  141.  
  142.    ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XW), ureg_scalar(block_num, TGSI_SWIZZLE_X),
  143.             ureg_imm1f(shader, 1.0f / zscan->blocks_per_line));
  144.  
  145.    ureg_FRC(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X));
  146.    ureg_FLR(shader, ureg_writemask(tmp, TGSI_WRITEMASK_W), ureg_src(tmp));
  147.  
  148.    for (i = 0; i < zscan->num_channels; ++i) {
  149.       ureg_ADD(shader, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y),
  150.                ureg_imm1f(shader, 1.0f / (zscan->blocks_per_line * VL_BLOCK_WIDTH)
  151.                 * (i - (signed)zscan->num_channels / 2)));
  152.  
  153.       ureg_MAD(shader, ureg_writemask(o_vtex[i], TGSI_WRITEMASK_X), vrect,
  154.                ureg_imm1f(shader, 1.0f / zscan->blocks_per_line), ureg_src(tmp));
  155.       ureg_MOV(shader, ureg_writemask(o_vtex[i], TGSI_WRITEMASK_Y), vrect);
  156.       ureg_MOV(shader, ureg_writemask(o_vtex[i], TGSI_WRITEMASK_Z), vpos);
  157.       ureg_MUL(shader, ureg_writemask(o_vtex[i], TGSI_WRITEMASK_W), ureg_src(tmp),
  158.                ureg_imm1f(shader, (float)zscan->blocks_per_line / zscan->blocks_total));
  159.    }
  160.  
  161.    ureg_release_temporary(shader, tmp);
  162.    ureg_END(shader);
  163.  
  164.    FREE(o_vtex);
  165.  
  166.    return ureg_create_shader_and_destroy(shader, zscan->pipe);
  167. }
  168.  
  169. static void *
  170. create_frag_shader(struct vl_zscan *zscan)
  171. {
  172.    struct ureg_program *shader;
  173.    struct ureg_src *vtex;
  174.  
  175.    struct ureg_src samp_src, samp_scan, samp_quant;
  176.  
  177.    struct ureg_dst *tmp;
  178.    struct ureg_dst quant, fragment;
  179.  
  180.    unsigned i;
  181.  
  182.    shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
  183.    if (!shader)
  184.       return NULL;
  185.  
  186.    vtex = MALLOC(zscan->num_channels * sizeof(struct ureg_src));
  187.    tmp = MALLOC(zscan->num_channels * sizeof(struct ureg_dst));
  188.  
  189.    for (i = 0; i < zscan->num_channels; ++i)
  190.       vtex[i] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX + i, TGSI_INTERPOLATE_LINEAR);
  191.  
  192.    samp_src = ureg_DECL_sampler(shader, 0);
  193.    samp_scan = ureg_DECL_sampler(shader, 1);
  194.    samp_quant = ureg_DECL_sampler(shader, 2);
  195.  
  196.    for (i = 0; i < zscan->num_channels; ++i)
  197.       tmp[i] = ureg_DECL_temporary(shader);
  198.    quant = ureg_DECL_temporary(shader);
  199.  
  200.    fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
  201.  
  202.    /*
  203.     * tmp.x = tex(vtex, 1)
  204.     * tmp.y = vtex.z
  205.     * fragment = tex(tmp, 0) * quant
  206.     */
  207.    for (i = 0; i < zscan->num_channels; ++i)
  208.       ureg_TEX(shader, ureg_writemask(tmp[i], TGSI_WRITEMASK_X), TGSI_TEXTURE_2D, vtex[i], samp_scan);
  209.  
  210.    for (i = 0; i < zscan->num_channels; ++i)
  211.       ureg_MOV(shader, ureg_writemask(tmp[i], TGSI_WRITEMASK_Y), ureg_scalar(vtex[i], TGSI_SWIZZLE_W));
  212.  
  213.    for (i = 0; i < zscan->num_channels; ++i) {
  214.       ureg_TEX(shader, ureg_writemask(tmp[0], TGSI_WRITEMASK_X << i), TGSI_TEXTURE_2D, ureg_src(tmp[i]), samp_src);
  215.       ureg_TEX(shader, ureg_writemask(quant, TGSI_WRITEMASK_X << i), TGSI_TEXTURE_3D, vtex[i], samp_quant);
  216.    }
  217.  
  218.    ureg_MUL(shader, quant, ureg_src(quant), ureg_imm1f(shader, 16.0f));
  219.    ureg_MUL(shader, fragment, ureg_src(tmp[0]), ureg_src(quant));
  220.  
  221.    for (i = 0; i < zscan->num_channels; ++i)
  222.       ureg_release_temporary(shader, tmp[i]);
  223.    ureg_END(shader);
  224.  
  225.    FREE(vtex);
  226.    FREE(tmp);
  227.  
  228.    return ureg_create_shader_and_destroy(shader, zscan->pipe);
  229. }
  230.  
  231. static bool
  232. init_shaders(struct vl_zscan *zscan)
  233. {
  234.    assert(zscan);
  235.  
  236.    zscan->vs = create_vert_shader(zscan);
  237.    if (!zscan->vs)
  238.       goto error_vs;
  239.  
  240.    zscan->fs = create_frag_shader(zscan);
  241.    if (!zscan->fs)
  242.       goto error_fs;
  243.  
  244.    return true;
  245.  
  246. error_fs:
  247.    zscan->pipe->delete_vs_state(zscan->pipe, zscan->vs);
  248.  
  249. error_vs:
  250.    return false;
  251. }
  252.  
  253. static void
  254. cleanup_shaders(struct vl_zscan *zscan)
  255. {
  256.    assert(zscan);
  257.  
  258.    zscan->pipe->delete_vs_state(zscan->pipe, zscan->vs);
  259.    zscan->pipe->delete_fs_state(zscan->pipe, zscan->fs);
  260. }
  261.  
  262. static bool
  263. init_state(struct vl_zscan *zscan)
  264. {
  265.    struct pipe_blend_state blend;
  266.    struct pipe_rasterizer_state rs_state;
  267.    struct pipe_sampler_state sampler;
  268.    unsigned i;
  269.  
  270.    assert(zscan);
  271.  
  272.    memset(&rs_state, 0, sizeof(rs_state));
  273.    rs_state.half_pixel_center = true;
  274.    rs_state.bottom_edge_rule = true;
  275.    rs_state.depth_clip = 1;
  276.    zscan->rs_state = zscan->pipe->create_rasterizer_state(zscan->pipe, &rs_state);
  277.    if (!zscan->rs_state)
  278.       goto error_rs_state;
  279.  
  280.    memset(&blend, 0, sizeof blend);
  281.  
  282.    blend.independent_blend_enable = 0;
  283.    blend.rt[0].blend_enable = 0;
  284.    blend.rt[0].rgb_func = PIPE_BLEND_ADD;
  285.    blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
  286.    blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
  287.    blend.rt[0].alpha_func = PIPE_BLEND_ADD;
  288.    blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
  289.    blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
  290.    blend.logicop_enable = 0;
  291.    blend.logicop_func = PIPE_LOGICOP_CLEAR;
  292.    /* Needed to allow color writes to FB, even if blending disabled */
  293.    blend.rt[0].colormask = PIPE_MASK_RGBA;
  294.    blend.dither = 0;
  295.    zscan->blend = zscan->pipe->create_blend_state(zscan->pipe, &blend);
  296.    if (!zscan->blend)
  297.       goto error_blend;
  298.  
  299.    for (i = 0; i < 3; ++i) {
  300.       memset(&sampler, 0, sizeof(sampler));
  301.       sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
  302.       sampler.wrap_t = PIPE_TEX_WRAP_REPEAT;
  303.       sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
  304.       sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
  305.       sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
  306.       sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
  307.       sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
  308.       sampler.compare_func = PIPE_FUNC_ALWAYS;
  309.       sampler.normalized_coords = 1;
  310.       zscan->samplers[i] = zscan->pipe->create_sampler_state(zscan->pipe, &sampler);
  311.       if (!zscan->samplers[i])
  312.          goto error_samplers;
  313.    }
  314.  
  315.    return true;
  316.  
  317. error_samplers:
  318.    for (i = 0; i < 2; ++i)
  319.       if (zscan->samplers[i])
  320.          zscan->pipe->delete_sampler_state(zscan->pipe, zscan->samplers[i]);
  321.  
  322.    zscan->pipe->delete_rasterizer_state(zscan->pipe, zscan->rs_state);
  323.  
  324. error_blend:
  325.    zscan->pipe->delete_blend_state(zscan->pipe, zscan->blend);
  326.  
  327. error_rs_state:
  328.    return false;
  329. }
  330.  
  331. static void
  332. cleanup_state(struct vl_zscan *zscan)
  333. {
  334.    unsigned i;
  335.  
  336.    assert(zscan);
  337.  
  338.    for (i = 0; i < 3; ++i)
  339.       zscan->pipe->delete_sampler_state(zscan->pipe, zscan->samplers[i]);
  340.  
  341.    zscan->pipe->delete_rasterizer_state(zscan->pipe, zscan->rs_state);
  342.    zscan->pipe->delete_blend_state(zscan->pipe, zscan->blend);
  343. }
  344.  
  345. struct pipe_sampler_view *
  346. vl_zscan_layout(struct pipe_context *pipe, const int layout[64], unsigned blocks_per_line)
  347. {
  348.    const unsigned total_size = blocks_per_line * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
  349.  
  350.    int patched_layout[64];
  351.  
  352.    struct pipe_resource res_tmpl, *res;
  353.    struct pipe_sampler_view sv_tmpl, *sv;
  354.    struct pipe_transfer *buf_transfer;
  355.    unsigned x, y, i, pitch;
  356.    float *f;
  357.  
  358.    struct pipe_box rect =
  359.    {
  360.       0, 0, 0,
  361.       VL_BLOCK_WIDTH * blocks_per_line,
  362.       VL_BLOCK_HEIGHT,
  363.       1
  364.    };
  365.  
  366.    assert(pipe && layout && blocks_per_line);
  367.  
  368.    for (i = 0; i < 64; ++i)
  369.       patched_layout[layout[i]] = i;
  370.  
  371.    memset(&res_tmpl, 0, sizeof(res_tmpl));
  372.    res_tmpl.target = PIPE_TEXTURE_2D;
  373.    res_tmpl.format = PIPE_FORMAT_R32_FLOAT;
  374.    res_tmpl.width0 = VL_BLOCK_WIDTH * blocks_per_line;
  375.    res_tmpl.height0 = VL_BLOCK_HEIGHT;
  376.    res_tmpl.depth0 = 1;
  377.    res_tmpl.array_size = 1;
  378.    res_tmpl.usage = PIPE_USAGE_IMMUTABLE;
  379.    res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
  380.  
  381.    res = pipe->screen->resource_create(pipe->screen, &res_tmpl);
  382.    if (!res)
  383.       goto error_resource;
  384.  
  385.    f = pipe->transfer_map(pipe, res,
  386.                           0, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE,
  387.                           &rect, &buf_transfer);
  388.    if (!f)
  389.       goto error_map;
  390.  
  391.    pitch = buf_transfer->stride / sizeof(float);
  392.  
  393.    for (i = 0; i < blocks_per_line; ++i)
  394.       for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
  395.          for (x = 0; x < VL_BLOCK_WIDTH; ++x) {
  396.             float addr = patched_layout[x + y * VL_BLOCK_WIDTH] +
  397.                i * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
  398.  
  399.             addr /= total_size;
  400.  
  401.             f[i * VL_BLOCK_WIDTH + y * pitch + x] = addr;
  402.          }
  403.  
  404.    pipe->transfer_unmap(pipe, buf_transfer);
  405.  
  406.    memset(&sv_tmpl, 0, sizeof(sv_tmpl));
  407.    u_sampler_view_default_template(&sv_tmpl, res, res->format);
  408.    sv = pipe->create_sampler_view(pipe, res, &sv_tmpl);
  409.    pipe_resource_reference(&res, NULL);
  410.    if (!sv)
  411.       goto error_map;
  412.  
  413.    return sv;
  414.  
  415. error_map:
  416.    pipe_resource_reference(&res, NULL);
  417.  
  418. error_resource:
  419.    return NULL;
  420. }
  421.  
  422. bool
  423. vl_zscan_init(struct vl_zscan *zscan, struct pipe_context *pipe,
  424.               unsigned buffer_width, unsigned buffer_height,
  425.               unsigned blocks_per_line, unsigned blocks_total,
  426.               unsigned num_channels)
  427. {
  428.    assert(zscan && pipe);
  429.  
  430.    zscan->pipe = pipe;
  431.    zscan->buffer_width = buffer_width;
  432.    zscan->buffer_height = buffer_height;
  433.    zscan->num_channels = num_channels;
  434.    zscan->blocks_per_line = blocks_per_line;
  435.    zscan->blocks_total = blocks_total;
  436.  
  437.    if(!init_shaders(zscan))
  438.       return false;
  439.  
  440.    if(!init_state(zscan)) {
  441.       cleanup_shaders(zscan);
  442.       return false;
  443.    }
  444.  
  445.    return true;
  446. }
  447.  
  448. void
  449. vl_zscan_cleanup(struct vl_zscan *zscan)
  450. {
  451.    assert(zscan);
  452.  
  453.    cleanup_shaders(zscan);
  454.    cleanup_state(zscan);
  455. }
  456.  
  457. bool
  458. vl_zscan_init_buffer(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer,
  459.                      struct pipe_sampler_view *src, struct pipe_surface *dst)
  460. {
  461.    struct pipe_resource res_tmpl, *res;
  462.    struct pipe_sampler_view sv_tmpl;
  463.  
  464.    assert(zscan && buffer);
  465.  
  466.    memset(buffer, 0, sizeof(struct vl_zscan_buffer));
  467.  
  468.    pipe_sampler_view_reference(&buffer->src, src);
  469.  
  470.    buffer->viewport.scale[0] = dst->width;
  471.    buffer->viewport.scale[1] = dst->height;
  472.    buffer->viewport.scale[2] = 1;
  473.    buffer->viewport.scale[3] = 1;
  474.    buffer->viewport.translate[0] = 0;
  475.    buffer->viewport.translate[1] = 0;
  476.    buffer->viewport.translate[2] = 0;
  477.    buffer->viewport.translate[3] = 0;
  478.  
  479.    buffer->fb_state.width = dst->width;
  480.    buffer->fb_state.height = dst->height;
  481.    buffer->fb_state.nr_cbufs = 1;
  482.    pipe_surface_reference(&buffer->fb_state.cbufs[0], dst);
  483.  
  484.    memset(&res_tmpl, 0, sizeof(res_tmpl));
  485.    res_tmpl.target = PIPE_TEXTURE_3D;
  486.    res_tmpl.format = PIPE_FORMAT_R8_UNORM;
  487.    res_tmpl.width0 = VL_BLOCK_WIDTH * zscan->blocks_per_line;
  488.    res_tmpl.height0 = VL_BLOCK_HEIGHT;
  489.    res_tmpl.depth0 = 2;
  490.    res_tmpl.array_size = 1;
  491.    res_tmpl.usage = PIPE_USAGE_IMMUTABLE;
  492.    res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
  493.  
  494.    res = zscan->pipe->screen->resource_create(zscan->pipe->screen, &res_tmpl);
  495.    if (!res)
  496.       return false;
  497.  
  498.    memset(&sv_tmpl, 0, sizeof(sv_tmpl));
  499.    u_sampler_view_default_template(&sv_tmpl, res, res->format);
  500.    sv_tmpl.swizzle_r = sv_tmpl.swizzle_g = sv_tmpl.swizzle_b = sv_tmpl.swizzle_a = TGSI_SWIZZLE_X;
  501.    buffer->quant = zscan->pipe->create_sampler_view(zscan->pipe, res, &sv_tmpl);
  502.    pipe_resource_reference(&res, NULL);
  503.    if (!buffer->quant)
  504.       return false;
  505.  
  506.    return true;
  507. }
  508.  
  509. void
  510. vl_zscan_cleanup_buffer(struct vl_zscan_buffer *buffer)
  511. {
  512.    assert(buffer);
  513.  
  514.    pipe_sampler_view_reference(&buffer->src, NULL);
  515.    pipe_sampler_view_reference(&buffer->layout, NULL);
  516.    pipe_sampler_view_reference(&buffer->quant, NULL);
  517.    pipe_surface_reference(&buffer->fb_state.cbufs[0], NULL);
  518. }
  519.  
  520. void
  521. vl_zscan_set_layout(struct vl_zscan_buffer *buffer, struct pipe_sampler_view *layout)
  522. {
  523.    assert(buffer);
  524.    assert(layout);
  525.  
  526.    pipe_sampler_view_reference(&buffer->layout, layout);
  527. }
  528.  
  529. void
  530. vl_zscan_upload_quant(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer,
  531.                       const uint8_t matrix[64], bool intra)
  532. {
  533.    struct pipe_context *pipe;
  534.    struct pipe_transfer *buf_transfer;
  535.    unsigned x, y, i, pitch;
  536.    uint8_t *data;
  537.  
  538.    struct pipe_box rect =
  539.    {
  540.       0, 0, intra ? 1 : 0,
  541.       VL_BLOCK_WIDTH,
  542.       VL_BLOCK_HEIGHT,
  543.       1
  544.    };
  545.  
  546.    assert(buffer);
  547.    assert(matrix);
  548.  
  549.    pipe = zscan->pipe;
  550.  
  551.    rect.width *= zscan->blocks_per_line;
  552.  
  553.    data = pipe->transfer_map(pipe, buffer->quant->texture,
  554.                              0, PIPE_TRANSFER_WRITE |
  555.                              PIPE_TRANSFER_DISCARD_RANGE,
  556.                              &rect, &buf_transfer);
  557.    if (!data)
  558.       return;
  559.  
  560.    pitch = buf_transfer->stride;
  561.  
  562.    for (i = 0; i < zscan->blocks_per_line; ++i)
  563.       for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
  564.          for (x = 0; x < VL_BLOCK_WIDTH; ++x)
  565.             data[i * VL_BLOCK_WIDTH + y * pitch + x] = matrix[x + y * VL_BLOCK_WIDTH];
  566.  
  567.    pipe->transfer_unmap(pipe, buf_transfer);
  568. }
  569.  
  570. void
  571. vl_zscan_render(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer, unsigned num_instances)
  572. {
  573.    assert(buffer);
  574.  
  575.    zscan->pipe->bind_rasterizer_state(zscan->pipe, zscan->rs_state);
  576.    zscan->pipe->bind_blend_state(zscan->pipe, zscan->blend);
  577.    zscan->pipe->bind_fragment_sampler_states(zscan->pipe, 3, zscan->samplers);
  578.    zscan->pipe->set_framebuffer_state(zscan->pipe, &buffer->fb_state);
  579.    zscan->pipe->set_viewport_states(zscan->pipe, 0, 1, &buffer->viewport);
  580.    zscan->pipe->set_fragment_sampler_views(zscan->pipe, 3, &buffer->src);
  581.    zscan->pipe->bind_vs_state(zscan->pipe, zscan->vs);
  582.    zscan->pipe->bind_fs_state(zscan->pipe, zscan->fs);
  583.    util_draw_arrays_instanced(zscan->pipe, PIPE_PRIM_QUADS, 0, 4, 0, num_instances);
  584. }
  585.