Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2009 VMware, Inc.  All Rights Reserved.
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining a
  6.  * copy of this software and associated documentation files (the
  7.  * "Software"), to deal in the Software without restriction, including
  8.  * without limitation the rights to use, copy, modify, merge, publish,
  9.  * distribute, sub license, and/or sell copies of the Software, and to
  10.  * permit persons to whom the Software is furnished to do so, subject to
  11.  * the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice (including the
  14.  * next paragraph) shall be included in all copies or substantial portions
  15.  * of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  20.  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  21.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  22.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  23.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24.  *
  25.  **************************************************************************/
  26.  
  27. #include "VG/openvg.h"
  28.  
  29. #include "vg_context.h"
  30. #include "image.h"
  31. #include "api.h"
  32. #include "handle.h"
  33. #include "renderer.h"
  34. #include "shaders_cache.h"
  35.  
  36. #include "pipe/p_context.h"
  37. #include "pipe/p_state.h"
  38. #include "util/u_inlines.h"
  39. #include "pipe/p_screen.h"
  40.  
  41. #include "util/u_format.h"
  42. #include "util/u_sampler.h"
  43. #include "util/u_string.h"
  44.  
  45. #include "asm_filters.h"
  46.  
  47.  
  48. struct filter_info {
  49.    struct vg_image *dst;
  50.    struct vg_image *src;
  51.    struct vg_shader * (*setup_shader)(struct vg_context *, void *);
  52.    void *user_data;
  53.    const void *const_buffer;
  54.    VGint const_buffer_len;
  55.    VGTilingMode tiling_mode;
  56.    struct pipe_sampler_view *extra_texture_view;
  57. };
  58.  
  59. static INLINE struct pipe_resource *create_texture_1d(struct vg_context *ctx,
  60.                                                      const VGuint *color_data,
  61.                                                      const VGint color_data_len)
  62. {
  63.    struct pipe_context *pipe = ctx->pipe;
  64.    struct pipe_screen *screen = pipe->screen;
  65.    struct pipe_resource *tex = 0;
  66.    struct pipe_resource templ;
  67.  
  68.    memset(&templ, 0, sizeof(templ));
  69.    templ.target = PIPE_TEXTURE_1D;
  70.    templ.format = PIPE_FORMAT_B8G8R8A8_UNORM;
  71.    templ.last_level = 0;
  72.    templ.width0 = color_data_len;
  73.    templ.height0 = 1;
  74.    templ.depth0 = 1;
  75.    templ.array_size = 1;
  76.    templ.bind = PIPE_BIND_SAMPLER_VIEW;
  77.  
  78.    tex = screen->resource_create(screen, &templ);
  79.  
  80.    { /* upload color_data */
  81.       struct pipe_transfer *transfer;
  82.       void *map =
  83.          pipe_transfer_map(pipe, tex,
  84.                            0, 0,
  85.                            PIPE_TRANSFER_READ_WRITE ,
  86.                            0, 0, tex->width0, tex->height0,
  87.                            &transfer);
  88.       memcpy(map, color_data, sizeof(VGint)*color_data_len);
  89.       pipe->transfer_unmap(pipe, transfer);
  90.    }
  91.  
  92.    return tex;
  93. }
  94.  
  95. static INLINE struct pipe_sampler_view *create_texture_1d_view(struct vg_context *ctx,
  96.                                                                const VGuint *color_data,
  97.                                                                const VGint color_data_len)
  98. {
  99.    struct pipe_context *pipe = ctx->pipe;
  100.    struct pipe_resource *texture;
  101.    struct pipe_sampler_view view_templ;
  102.    struct pipe_sampler_view *view;
  103.  
  104.    texture = create_texture_1d(ctx, color_data, color_data_len);
  105.  
  106.    if (!texture)
  107.       return NULL;
  108.  
  109.    u_sampler_view_default_template(&view_templ, texture, texture->format);
  110.    view = pipe->create_sampler_view(pipe, texture, &view_templ);
  111.    /* want the texture to go away if the view is freed */
  112.    pipe_resource_reference(&texture, NULL);
  113.  
  114.    return view;
  115. }
  116.  
  117. static struct vg_shader * setup_color_matrix(struct vg_context *ctx, void *user_data)
  118. {
  119.    struct vg_shader *shader =
  120.       shader_create_from_text(ctx->pipe, color_matrix_asm, 200,
  121.          PIPE_SHADER_FRAGMENT);
  122.    return shader;
  123. }
  124.  
  125. static struct vg_shader * setup_convolution(struct vg_context *ctx, void *user_data)
  126. {
  127.    char buffer[1024];
  128.    VGint num_consts = (VGint)(long)(user_data);
  129.    struct vg_shader *shader;
  130.  
  131.    util_snprintf(buffer, 1023, convolution_asm, num_consts, num_consts / 2 + 1);
  132.  
  133.    shader = shader_create_from_text(ctx->pipe, buffer, 200,
  134.                                     PIPE_SHADER_FRAGMENT);
  135.  
  136.    return shader;
  137. }
  138.  
  139. static struct vg_shader * setup_lookup(struct vg_context *ctx, void *user_data)
  140. {
  141.    struct vg_shader *shader =
  142.       shader_create_from_text(ctx->pipe, lookup_asm,
  143.                               200, PIPE_SHADER_FRAGMENT);
  144.  
  145.    return shader;
  146. }
  147.  
  148.  
  149. static struct vg_shader * setup_lookup_single(struct vg_context *ctx, void *user_data)
  150. {
  151.    char buffer[1024];
  152.    VGImageChannel channel = (VGImageChannel)(user_data);
  153.    struct vg_shader *shader;
  154.  
  155.    switch(channel) {
  156.    case VG_RED:
  157.       util_snprintf(buffer, 1023, lookup_single_asm, "xxxx");
  158.       break;
  159.    case VG_GREEN:
  160.       util_snprintf(buffer, 1023, lookup_single_asm, "yyyy");
  161.       break;
  162.    case VG_BLUE:
  163.       util_snprintf(buffer, 1023, lookup_single_asm, "zzzz");
  164.       break;
  165.    case VG_ALPHA:
  166.       util_snprintf(buffer, 1023, lookup_single_asm, "wwww");
  167.       break;
  168.    default:
  169.       debug_assert(!"Unknown color channel");
  170.    }
  171.  
  172.    shader = shader_create_from_text(ctx->pipe, buffer, 200,
  173.                                     PIPE_SHADER_FRAGMENT);
  174.  
  175.    return shader;
  176. }
  177.  
  178. static void execute_filter(struct vg_context *ctx,
  179.                            struct filter_info *info)
  180. {
  181.    struct vg_shader *shader;
  182.    const struct pipe_sampler_state *samplers[2];
  183.    struct pipe_sampler_view *views[2];
  184.    struct pipe_sampler_state sampler;
  185.    uint tex_wrap;
  186.  
  187.    memset(&sampler, 0, sizeof(sampler));
  188.    sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
  189.    sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
  190.    sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
  191.    sampler.normalized_coords = 1;
  192.  
  193.    switch (info->tiling_mode) {
  194.    case VG_TILE_FILL:
  195.       tex_wrap = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
  196.       /* copy border color */
  197.       memcpy(sampler.border_color.f, ctx->state.vg.tile_fill_color,
  198.             sizeof(sampler.border_color));
  199.       break;
  200.    case VG_TILE_PAD:
  201.       tex_wrap = PIPE_TEX_WRAP_CLAMP_TO_EDGE;;
  202.       break;
  203.    case VG_TILE_REPEAT:
  204.       tex_wrap = PIPE_TEX_WRAP_REPEAT;;
  205.       break;
  206.    case VG_TILE_REFLECT:
  207.       tex_wrap = PIPE_TEX_WRAP_MIRROR_REPEAT;
  208.       break;
  209.    default:
  210.       debug_assert(!"Unknown tiling mode");
  211.       tex_wrap = 0;
  212.       break;
  213.    }
  214.  
  215.    sampler.wrap_s = tex_wrap;
  216.    sampler.wrap_t = tex_wrap;
  217.    sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
  218.  
  219.    samplers[0] = samplers[1] = &sampler;
  220.    views[0] = info->src->sampler_view;
  221.    views[1] = info->extra_texture_view;
  222.  
  223.    shader = info->setup_shader(ctx, info->user_data);
  224.  
  225.    if (renderer_filter_begin(ctx->renderer,
  226.             info->dst->sampler_view->texture, VG_TRUE,
  227.             ctx->state.vg.filter_channel_mask,
  228.             samplers, views, (info->extra_texture_view) ? 2 : 1,
  229.             shader->driver, info->const_buffer, info->const_buffer_len)) {
  230.       renderer_filter(ctx->renderer,
  231.             info->dst->x, info->dst->y, info->dst->width, info->dst->height,
  232.             info->src->x, info->src->y, info->src->width, info->src->height);
  233.       renderer_filter_end(ctx->renderer);
  234.    }
  235.  
  236.    vg_shader_destroy(ctx, shader);
  237. }
  238.  
  239. void vegaColorMatrix(VGImage dst, VGImage src,
  240.                      const VGfloat * matrix)
  241. {
  242.    struct vg_context *ctx = vg_current_context();
  243.    struct vg_image *d, *s;
  244.    struct filter_info info;
  245.  
  246.    if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
  247.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  248.       return;
  249.    }
  250.    if (!matrix || !is_aligned(matrix)) {
  251.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  252.       return;
  253.    }
  254.  
  255.    d = handle_to_image(dst);
  256.    s = handle_to_image(src);
  257.  
  258.    if (vg_image_overlaps(d, s)) {
  259.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  260.       return;
  261.    }
  262.  
  263.    info.dst = d;
  264.    info.src = s;
  265.    info.setup_shader = &setup_color_matrix;
  266.    info.user_data = NULL;
  267.    info.const_buffer = matrix;
  268.    info.const_buffer_len = 20 * sizeof(VGfloat);
  269.    info.tiling_mode = VG_TILE_PAD;
  270.    info.extra_texture_view = NULL;
  271.    execute_filter(ctx, &info);
  272. }
  273.  
  274. static VGfloat texture_offset(VGfloat width, VGint kernelSize, VGint current, VGint shift)
  275. {
  276.    VGfloat diff = (VGfloat) (current - shift);
  277.  
  278.    return diff / width;
  279. }
  280.  
  281. void vegaConvolve(VGImage dst, VGImage src,
  282.                   VGint kernelWidth, VGint kernelHeight,
  283.                   VGint shiftX, VGint shiftY,
  284.                   const VGshort * kernel,
  285.                   VGfloat scale,
  286.                   VGfloat bias,
  287.                   VGTilingMode tilingMode)
  288. {
  289.    struct vg_context *ctx = vg_current_context();
  290.    VGfloat *buffer;
  291.    VGint buffer_len;
  292.    VGint i, j;
  293.    VGint idx = 0;
  294.    struct vg_image *d, *s;
  295.    VGint kernel_size = kernelWidth * kernelHeight;
  296.    struct filter_info info;
  297.    const VGint max_kernel_size = vegaGeti(VG_MAX_KERNEL_SIZE);
  298.  
  299.    if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
  300.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  301.       return;
  302.    }
  303.  
  304.    if (kernelWidth <= 0 || kernelHeight <= 0 ||
  305.       kernelWidth > max_kernel_size || kernelHeight > max_kernel_size) {
  306.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  307.       return;
  308.    }
  309.  
  310.    if (!kernel || !is_aligned_to(kernel, 2)) {
  311.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  312.       return;
  313.    }
  314.  
  315.    if (tilingMode < VG_TILE_FILL ||
  316.        tilingMode > VG_TILE_REFLECT) {
  317.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  318.       return;
  319.    }
  320.  
  321.    d = handle_to_image(dst);
  322.    s = handle_to_image(src);
  323.  
  324.    if (vg_image_overlaps(d, s)) {
  325.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  326.       return;
  327.    }
  328.  
  329.    vg_validate_state(ctx);
  330.  
  331.    buffer_len = 8 + 2 * 4 * kernel_size;
  332.    buffer = malloc(buffer_len * sizeof(VGfloat));
  333.  
  334.    buffer[0] = 0.f;
  335.    buffer[1] = 1.f;
  336.    buffer[2] = 2.f; /*unused*/
  337.    buffer[3] = 4.f; /*unused*/
  338.  
  339.    buffer[4] = (VGfloat) (kernelWidth * kernelHeight);
  340.    buffer[5] = scale;
  341.    buffer[6] = bias;
  342.    buffer[7] = 0.f;
  343.  
  344.    idx = 8;
  345.    for (j = 0; j < kernelHeight; ++j) {
  346.       for (i = 0; i < kernelWidth; ++i) {
  347.          VGint index = j * kernelWidth + i;
  348.          VGfloat x, y;
  349.  
  350.          x = (VGfloat) texture_offset(s->width, kernelWidth, i, shiftX);
  351.          y = (VGfloat) texture_offset(s->height, kernelHeight, j, shiftY);
  352.  
  353.          buffer[idx + index*4 + 0] = x;
  354.          buffer[idx + index*4 + 1] = y;
  355.          buffer[idx + index*4 + 2] = 0.f;
  356.          buffer[idx + index*4 + 3] = 0.f;
  357.       }
  358.    }
  359.    idx += kernel_size * 4;
  360.  
  361.    for (j = 0; j < kernelHeight; ++j) {
  362.       for (i = 0; i < kernelWidth; ++i) {
  363.          /* transpose the kernel */
  364.          VGint index = j * kernelWidth + i;
  365.          VGint kindex = (kernelWidth - i - 1) * kernelHeight + (kernelHeight - j - 1);
  366.          buffer[idx + index*4 + 0] = kernel[kindex];
  367.          buffer[idx + index*4 + 1] = kernel[kindex];
  368.          buffer[idx + index*4 + 2] = kernel[kindex];
  369.          buffer[idx + index*4 + 3] = kernel[kindex];
  370.       }
  371.    }
  372.  
  373.    info.dst = d;
  374.    info.src = s;
  375.    info.setup_shader = &setup_convolution;
  376.    info.user_data = (void*)(long)(buffer_len/4);
  377.    info.const_buffer = buffer;
  378.    info.const_buffer_len = buffer_len * sizeof(VGfloat);
  379.    info.tiling_mode = tilingMode;
  380.    info.extra_texture_view = NULL;
  381.    execute_filter(ctx, &info);
  382.  
  383.    free(buffer);
  384. }
  385.  
  386. void vegaSeparableConvolve(VGImage dst, VGImage src,
  387.                            VGint kernelWidth,
  388.                            VGint kernelHeight,
  389.                            VGint shiftX, VGint shiftY,
  390.                            const VGshort * kernelX,
  391.                            const VGshort * kernelY,
  392.                            VGfloat scale,
  393.                            VGfloat bias,
  394.                            VGTilingMode tilingMode)
  395. {
  396.    struct vg_context *ctx = vg_current_context();
  397.    VGshort *kernel;
  398.    VGint i, j, idx = 0;
  399.    const VGint max_kernel_size = vegaGeti(VG_MAX_SEPARABLE_KERNEL_SIZE);
  400.  
  401.    if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
  402.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  403.       return;
  404.    }
  405.  
  406.    if (kernelWidth <= 0 || kernelHeight <= 0 ||
  407.        kernelWidth > max_kernel_size || kernelHeight > max_kernel_size) {
  408.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  409.       return;
  410.    }
  411.  
  412.    if (!kernelX || !kernelY ||
  413.        !is_aligned_to(kernelX, 2) || !is_aligned_to(kernelY, 2)) {
  414.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  415.       return;
  416.    }
  417.    if (tilingMode < VG_TILE_FILL ||
  418.        tilingMode > VG_TILE_REFLECT) {
  419.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  420.       return;
  421.    }
  422.    kernel = malloc(sizeof(VGshort)*kernelWidth*kernelHeight);
  423.    for (i = 0; i < kernelWidth; ++i) {
  424.       for (j = 0; j < kernelHeight; ++j) {
  425.          kernel[idx] = kernelX[i] * kernelY[j];
  426.          ++idx;
  427.       }
  428.    }
  429.    vegaConvolve(dst, src, kernelWidth, kernelHeight, shiftX, shiftY,
  430.                 kernel, scale, bias, tilingMode);
  431.    free(kernel);
  432. }
  433.  
  434. static INLINE VGfloat compute_gaussian_componenet(VGfloat x, VGfloat y,
  435.                                                   VGfloat stdDeviationX,
  436.                                                   VGfloat stdDeviationY)
  437. {
  438.    VGfloat mult = 1 / ( 2 * M_PI * stdDeviationX * stdDeviationY);
  439.    VGfloat e = exp( - ( pow(x, 2)/(2*pow(stdDeviationX, 2)) +
  440.                         pow(y, 2)/(2*pow(stdDeviationY, 2)) ) );
  441.    return mult * e;
  442. }
  443.  
  444. static INLINE VGint compute_kernel_size(VGfloat deviation)
  445. {
  446.    VGint size = ceil(2.146 * deviation);
  447.    if (size > 11)
  448.       return 11;
  449.    return size;
  450. }
  451.  
  452. static void compute_gaussian_kernel(VGfloat *kernel,
  453.                                     VGint width, VGint height,
  454.                                     VGfloat stdDeviationX,
  455.                                     VGfloat stdDeviationY)
  456. {
  457.    VGint i, j;
  458.    VGfloat scale = 0.0f;
  459.  
  460.    for (j = 0; j < height; ++j) {
  461.       for (i = 0; i < width; ++i) {
  462.          VGint idx =  (height - j -1) * width + (width - i -1);
  463.          kernel[idx] = compute_gaussian_componenet(i-(ceil(width/2))-1,
  464.                                                    j-ceil(height/2)-1,
  465.                                                    stdDeviationX, stdDeviationY);
  466.          scale += kernel[idx];
  467.       }
  468.    }
  469.  
  470.    for (j = 0; j < height; ++j) {
  471.       for (i = 0; i < width; ++i) {
  472.          VGint idx = j * width + i;
  473.          kernel[idx] /= scale;
  474.       }
  475.    }
  476. }
  477.  
  478. void vegaGaussianBlur(VGImage dst, VGImage src,
  479.                       VGfloat stdDeviationX,
  480.                       VGfloat stdDeviationY,
  481.                       VGTilingMode tilingMode)
  482. {
  483.    struct vg_context *ctx = vg_current_context();
  484.    struct vg_image *d, *s;
  485.    VGfloat *buffer, *kernel;
  486.    VGint kernel_width, kernel_height, kernel_size;
  487.    VGint buffer_len;
  488.    VGint idx, i, j;
  489.    struct filter_info info;
  490.  
  491.    if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
  492.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  493.       return;
  494.    }
  495.    if (stdDeviationX <= 0 || stdDeviationY <= 0) {
  496.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  497.       return;
  498.    }
  499.  
  500.    if (tilingMode < VG_TILE_FILL ||
  501.        tilingMode > VG_TILE_REFLECT) {
  502.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  503.       return;
  504.    }
  505.  
  506.    d = handle_to_image(dst);
  507.    s = handle_to_image(src);
  508.  
  509.    if (vg_image_overlaps(d, s)) {
  510.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  511.       return;
  512.    }
  513.  
  514.    kernel_width = compute_kernel_size(stdDeviationX);
  515.    kernel_height = compute_kernel_size(stdDeviationY);
  516.    kernel_size = kernel_width * kernel_height;
  517.    kernel = malloc(sizeof(VGfloat)*kernel_size);
  518.    compute_gaussian_kernel(kernel, kernel_width, kernel_height,
  519.                            stdDeviationX, stdDeviationY);
  520.  
  521.    buffer_len = 8 + 2 * 4 * kernel_size;
  522.    buffer = malloc(buffer_len * sizeof(VGfloat));
  523.  
  524.    buffer[0] = 0.f;
  525.    buffer[1] = 1.f;
  526.    buffer[2] = 2.f; /*unused*/
  527.    buffer[3] = 4.f; /*unused*/
  528.  
  529.    buffer[4] = kernel_width * kernel_height;
  530.    buffer[5] = 1.f;/*scale*/
  531.    buffer[6] = 0.f;/*bias*/
  532.    buffer[7] = 0.f;
  533.  
  534.    idx = 8;
  535.    for (j = 0; j < kernel_height; ++j) {
  536.       for (i = 0; i < kernel_width; ++i) {
  537.          VGint index = j * kernel_width + i;
  538.          VGfloat x, y;
  539.  
  540.          x = texture_offset(s->width, kernel_width, i, kernel_width/2);
  541.          y = texture_offset(s->height, kernel_height, j, kernel_height/2);
  542.  
  543.          buffer[idx + index*4 + 0] = x;
  544.          buffer[idx + index*4 + 1] = y;
  545.          buffer[idx + index*4 + 2] = 0.f;
  546.          buffer[idx + index*4 + 3] = 0.f;
  547.       }
  548.    }
  549.    idx += kernel_size * 4;
  550.  
  551.    for (j = 0; j < kernel_height; ++j) {
  552.       for (i = 0; i < kernel_width; ++i) {
  553.          /* transpose the kernel */
  554.          VGint index = j * kernel_width + i;
  555.          VGint kindex = (kernel_width - i - 1) * kernel_height + (kernel_height - j - 1);
  556.          buffer[idx + index*4 + 0] = kernel[kindex];
  557.          buffer[idx + index*4 + 1] = kernel[kindex];
  558.          buffer[idx + index*4 + 2] = kernel[kindex];
  559.          buffer[idx + index*4 + 3] = kernel[kindex];
  560.       }
  561.    }
  562.  
  563.    info.dst = d;
  564.    info.src = s;
  565.    info.setup_shader = &setup_convolution;
  566.    info.user_data = (void*)(long)(buffer_len/4);
  567.    info.const_buffer = buffer;
  568.    info.const_buffer_len = buffer_len * sizeof(VGfloat);
  569.    info.tiling_mode = tilingMode;
  570.    info.extra_texture_view = NULL;
  571.    execute_filter(ctx, &info);
  572.  
  573.    free(buffer);
  574.    free(kernel);
  575. }
  576.  
  577. void vegaLookup(VGImage dst, VGImage src,
  578.                 const VGubyte * redLUT,
  579.                 const VGubyte * greenLUT,
  580.                 const VGubyte * blueLUT,
  581.                 const VGubyte * alphaLUT,
  582.                 VGboolean outputLinear,
  583.                 VGboolean outputPremultiplied)
  584. {
  585.    struct vg_context *ctx = vg_current_context();
  586.    struct vg_image *d, *s;
  587.    VGuint color_data[256];
  588.    VGint i;
  589.    struct pipe_sampler_view *lut_texture_view;
  590.    VGfloat buffer[4];
  591.    struct filter_info info;
  592.  
  593.    if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
  594.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  595.       return;
  596.    }
  597.  
  598.    if (!redLUT || !greenLUT || !blueLUT || !alphaLUT) {
  599.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  600.       return;
  601.    }
  602.  
  603.    d = handle_to_image(dst);
  604.    s = handle_to_image(src);
  605.  
  606.    if (vg_image_overlaps(d, s)) {
  607.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  608.       return;
  609.    }
  610.  
  611.    for (i = 0; i < 256; ++i) {
  612.       color_data[i] = blueLUT[i] << 24 | greenLUT[i] << 16 |
  613.                       redLUT[i]  <<  8 | alphaLUT[i];
  614.    }
  615.    lut_texture_view = create_texture_1d_view(ctx, color_data, 255);
  616.  
  617.    buffer[0] = 0.f;
  618.    buffer[1] = 0.f;
  619.    buffer[2] = 1.f;
  620.    buffer[3] = 1.f;
  621.  
  622.    info.dst = d;
  623.    info.src = s;
  624.    info.setup_shader = &setup_lookup;
  625.    info.user_data = NULL;
  626.    info.const_buffer = buffer;
  627.    info.const_buffer_len = 4 * sizeof(VGfloat);
  628.    info.tiling_mode = VG_TILE_PAD;
  629.    info.extra_texture_view = lut_texture_view;
  630.  
  631.    execute_filter(ctx, &info);
  632.  
  633.    pipe_sampler_view_reference(&lut_texture_view, NULL);
  634. }
  635.  
  636. void vegaLookupSingle(VGImage dst, VGImage src,
  637.                       const VGuint * lookupTable,
  638.                       VGImageChannel sourceChannel,
  639.                       VGboolean outputLinear,
  640.                       VGboolean outputPremultiplied)
  641. {
  642.    struct vg_context *ctx = vg_current_context();
  643.    struct vg_image *d, *s;
  644.    struct pipe_sampler_view *lut_texture_view;
  645.    VGfloat buffer[4];
  646.    struct filter_info info;
  647.    VGuint color_data[256];
  648.    VGint i;
  649.  
  650.    if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) {
  651.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  652.       return;
  653.    }
  654.  
  655.    if (!lookupTable || !is_aligned(lookupTable)) {
  656.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  657.       return;
  658.    }
  659.  
  660.    if (sourceChannel != VG_RED && sourceChannel != VG_GREEN &&
  661.        sourceChannel != VG_BLUE && sourceChannel != VG_ALPHA) {
  662.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  663.       return;
  664.    }
  665.  
  666.    d = handle_to_image(dst);
  667.    s = handle_to_image(src);
  668.  
  669.    if (vg_image_overlaps(d, s)) {
  670.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  671.       return;
  672.    }
  673.  
  674.    vg_validate_state(ctx);
  675.  
  676.    for (i = 0; i < 256; ++i) {
  677.       VGuint rgba = lookupTable[i];
  678.       VGubyte blue, green, red, alpha;
  679.       red   = (rgba & 0xff000000)>>24;
  680.       green = (rgba & 0x00ff0000)>>16;
  681.       blue  = (rgba & 0x0000ff00)>> 8;
  682.       alpha = (rgba & 0x000000ff)>> 0;
  683.       color_data[i] = blue << 24 | green << 16 |
  684.                       red  <<  8 | alpha;
  685.    }
  686.    lut_texture_view = create_texture_1d_view(ctx, color_data, 256);
  687.  
  688.    buffer[0] = 0.f;
  689.    buffer[1] = 0.f;
  690.    buffer[2] = 1.f;
  691.    buffer[3] = 1.f;
  692.  
  693.    info.dst = d;
  694.    info.src = s;
  695.    info.setup_shader = &setup_lookup_single;
  696.    info.user_data = (void*)sourceChannel;
  697.    info.const_buffer = buffer;
  698.    info.const_buffer_len = 4 * sizeof(VGfloat);
  699.    info.tiling_mode = VG_TILE_PAD;
  700.    info.extra_texture_view = lut_texture_view;
  701.  
  702.    execute_filter(ctx, &info);
  703.  
  704.    pipe_sampler_view_reference(&lut_texture_view, NULL);
  705. }
  706.