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 "image.h"
  28.  
  29. #include "vg_translate.h"
  30. #include "vg_context.h"
  31. #include "matrix.h"
  32. #include "renderer.h"
  33. #include "util_array.h"
  34. #include "api_consts.h"
  35. #include "shader.h"
  36.  
  37. #include "pipe/p_context.h"
  38. #include "pipe/p_screen.h"
  39. #include "util/u_inlines.h"
  40. #include "util/u_format.h"
  41. #include "util/u_tile.h"
  42. #include "util/u_memory.h"
  43. #include "util/u_math.h"
  44. #include "util/u_sampler.h"
  45. #include "util/u_surface.h"
  46.  
  47. static enum pipe_format vg_format_to_pipe(VGImageFormat format)
  48. {
  49.    switch(format) {
  50.    case VG_sRGB_565:
  51.       return PIPE_FORMAT_B5G6R5_UNORM;
  52.    case VG_sRGBA_5551:
  53.       return PIPE_FORMAT_B5G5R5A1_UNORM;
  54.    case VG_sRGBA_4444:
  55.       return PIPE_FORMAT_B4G4R4A4_UNORM;
  56.    case VG_sL_8:
  57.    case VG_lL_8:
  58.       return PIPE_FORMAT_L8_UNORM;
  59.    case VG_BW_1:
  60.       return PIPE_FORMAT_B8G8R8A8_UNORM;
  61.    case VG_A_8:
  62.       return PIPE_FORMAT_A8_UNORM;
  63. #ifdef OPENVG_VERSION_1_1
  64.    case VG_A_1:
  65.    case VG_A_4:
  66.       return PIPE_FORMAT_A8_UNORM;
  67. #endif
  68.    default:
  69.       return PIPE_FORMAT_B8G8R8A8_UNORM;
  70.    }
  71. }
  72.  
  73. static INLINE void vg_sync_size(VGfloat *src_loc, VGfloat *dst_loc)
  74. {
  75.    src_loc[2] = MIN2(src_loc[2], dst_loc[2]);
  76.    src_loc[3] = MIN2(src_loc[3], dst_loc[3]);
  77.    dst_loc[2] = src_loc[2];
  78.    dst_loc[3] = src_loc[3];
  79. }
  80.  
  81. static void vg_get_copy_coords(VGfloat *src_loc,
  82.                                VGfloat src_width, VGfloat src_height,
  83.                                VGfloat *dst_loc,
  84.                                VGfloat dst_width, VGfloat dst_height)
  85. {
  86.    VGfloat dst_bounds[4], src_bounds[4];
  87.    VGfloat src_shift[4], dst_shift[4], shift[4];
  88.  
  89.    dst_bounds[0] = 0.f;
  90.    dst_bounds[1] = 0.f;
  91.    dst_bounds[2] = dst_width;
  92.    dst_bounds[3] = dst_height;
  93.  
  94.    src_bounds[0] = 0.f;
  95.    src_bounds[1] = 0.f;
  96.    src_bounds[2] = src_width;
  97.    src_bounds[3] = src_height;
  98.  
  99.    vg_bound_rect(src_loc, src_bounds, src_shift);
  100.    vg_bound_rect(dst_loc, dst_bounds, dst_shift);
  101.    shift[0] = src_shift[0] - dst_shift[0];
  102.    shift[1] = src_shift[1] - dst_shift[1];
  103.  
  104.    if (shift[0] < 0)
  105.       vg_shift_rectx(src_loc, src_bounds, -shift[0]);
  106.    else
  107.       vg_shift_rectx(dst_loc, dst_bounds, shift[0]);
  108.  
  109.    if (shift[1] < 0)
  110.       vg_shift_recty(src_loc, src_bounds, -shift[1]);
  111.    else
  112.       vg_shift_recty(dst_loc, dst_bounds, shift[1]);
  113.  
  114.    vg_sync_size(src_loc, dst_loc);
  115. }
  116.  
  117. static void vg_copy_texture(struct vg_context *ctx,
  118.                             struct pipe_resource *dst, VGint dx, VGint dy,
  119.                             struct pipe_sampler_view *src, VGint sx, VGint sy,
  120.                             VGint width, VGint height)
  121. {
  122.    VGfloat dst_loc[4], src_loc[4];
  123.  
  124.    dst_loc[0] = dx;
  125.    dst_loc[1] = dy;
  126.    dst_loc[2] = width;
  127.    dst_loc[3] = height;
  128.  
  129.    src_loc[0] = sx;
  130.    src_loc[1] = sy;
  131.    src_loc[2] = width;
  132.    src_loc[3] = height;
  133.  
  134.    vg_get_copy_coords(src_loc, src->texture->width0, src->texture->height0,
  135.                       dst_loc, dst->width0, dst->height0);
  136.  
  137.    if (src_loc[2] >= 0 && src_loc[3] >= 0 &&
  138.        dst_loc[2] >= 0 && dst_loc[3] >= 0) {
  139.       struct pipe_surface *surf, surf_tmpl;
  140.  
  141.       /* get the destination surface */
  142.       u_surface_default_template(&surf_tmpl, dst);
  143.       surf = ctx->pipe->create_surface(ctx->pipe, dst, &surf_tmpl);
  144.       if (surf && renderer_copy_begin(ctx->renderer, surf, VG_TRUE, src)) {
  145.          renderer_copy(ctx->renderer,
  146.                dst_loc[0], dst_loc[1], dst_loc[2], dst_loc[3],
  147.                src_loc[0], src_loc[1], src_loc[2], src_loc[3]);
  148.          renderer_copy_end(ctx->renderer);
  149.       }
  150.  
  151.       pipe_surface_reference(&surf, NULL);
  152.    }
  153. }
  154.  
  155. void vg_copy_surface(struct vg_context *ctx,
  156.                      struct pipe_surface *dst, VGint dx, VGint dy,
  157.                      struct pipe_surface *src, VGint sx, VGint sy,
  158.                      VGint width, VGint height)
  159. {
  160.    VGfloat dst_loc[4], src_loc[4];
  161.  
  162.    dst_loc[0] = dx;
  163.    dst_loc[1] = dy;
  164.    dst_loc[2] = width;
  165.    dst_loc[3] = height;
  166.  
  167.    src_loc[0] = sx;
  168.    src_loc[1] = sy;
  169.    src_loc[2] = width;
  170.    src_loc[3] = height;
  171.  
  172.    vg_get_copy_coords(src_loc, src->width, src->height,
  173.                       dst_loc, dst->width, dst->height);
  174.  
  175.    if (src_loc[2] > 0 && src_loc[3] > 0 &&
  176.        dst_loc[2] > 0 && dst_loc[3] > 0) {
  177.       if (src == dst)
  178.          renderer_copy_surface(ctx->renderer,
  179.                                src,
  180.                                src_loc[0],
  181.                                src->height - (src_loc[1] + src_loc[3]),
  182.                                src_loc[0] + src_loc[2],
  183.                                src->height - src_loc[1],
  184.                                dst,
  185.                                dst_loc[0],
  186.                                dst->height - (dst_loc[1] + dst_loc[3]),
  187.                                dst_loc[0] + dst_loc[2],
  188.                                dst->height - dst_loc[1],
  189.                                0, 0);
  190.       else
  191.          renderer_copy_surface(ctx->renderer,
  192.                                src,
  193.                                src_loc[0],
  194.                                src->height - src_loc[1],
  195.                                src_loc[0] + src_loc[2],
  196.                                src->height - (src_loc[1] + src_loc[3]),
  197.                                dst,
  198.                                dst_loc[0],
  199.                                dst->height - (dst_loc[1] + dst_loc[3]),
  200.                                dst_loc[0] + dst_loc[2],
  201.                                dst->height - dst_loc[1],
  202.                                0, 0);
  203.    }
  204.  
  205. }
  206.  
  207. static struct pipe_resource *image_texture(struct vg_image *img)
  208. {
  209.    struct pipe_resource *tex = img->sampler_view->texture;
  210.    return tex;
  211. }
  212.  
  213.  
  214. static void image_cleari(struct vg_image *img, VGint clear_colori,
  215.                          VGint x, VGint y, VGint width, VGint height)
  216. {
  217.    VGint *clearbuf;
  218.    VGint i;
  219.    VGfloat dwidth, dheight;
  220.  
  221.    clearbuf = malloc(sizeof(VGint)*width*height);
  222.    for (i = 0; i < width*height; ++i)
  223.       clearbuf[i] = clear_colori;
  224.  
  225.    dwidth = MIN2(width, img->width);
  226.    dheight = MIN2(height, img->height);
  227.  
  228.    image_sub_data(img, clearbuf, width * sizeof(VGint),
  229.                   VG_sRGBA_8888,
  230.                   x, y, dwidth, dheight);
  231.    free(clearbuf);
  232. }
  233.  
  234. struct vg_image * image_create(VGImageFormat format,
  235.                                VGint width, VGint height)
  236. {
  237.    struct vg_context *ctx = vg_current_context();
  238.    struct pipe_context *pipe = ctx->pipe;
  239.    struct vg_image *image = CALLOC_STRUCT(vg_image);
  240.    enum pipe_format pformat = vg_format_to_pipe(format);
  241.    struct pipe_resource pt, *newtex;
  242.    struct pipe_sampler_view view_templ;
  243.    struct pipe_sampler_view *view;
  244.    struct pipe_screen *screen = ctx->pipe->screen;
  245.  
  246.    vg_init_object(&image->base, ctx, VG_OBJECT_IMAGE);
  247.  
  248.    image->format = format;
  249.    image->width = width;
  250.    image->height = height;
  251.  
  252.    image->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
  253.    image->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
  254.    image->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
  255.    image->sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
  256.    image->sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
  257.    image->sampler.normalized_coords = 1;
  258.  
  259.    assert(screen->is_format_supported(screen, pformat, PIPE_TEXTURE_2D,
  260.                                       0, PIPE_BIND_SAMPLER_VIEW));
  261.  
  262.    memset(&pt, 0, sizeof(pt));
  263.    pt.target = PIPE_TEXTURE_2D;
  264.    pt.format = pformat;
  265.    pt.last_level = 0;
  266.    pt.width0 = width;
  267.    pt.height0 = height;
  268.    pt.depth0 = 1;
  269.    pt.array_size = 1;
  270.    pt.bind = PIPE_BIND_SAMPLER_VIEW;
  271.  
  272.    newtex = screen->resource_create(screen, &pt);
  273.  
  274.    debug_assert(newtex);
  275.  
  276.    u_sampler_view_default_template(&view_templ, newtex, newtex->format);
  277.    /* R, G, and B are treated as 1.0 for alpha-only formats in OpenVG */
  278.    if (newtex->format == PIPE_FORMAT_A8_UNORM) {
  279.       view_templ.swizzle_r = PIPE_SWIZZLE_ONE;
  280.       view_templ.swizzle_g = PIPE_SWIZZLE_ONE;
  281.       view_templ.swizzle_b = PIPE_SWIZZLE_ONE;
  282.    }
  283.  
  284.    view = pipe->create_sampler_view(pipe, newtex, &view_templ);
  285.    /* want the texture to go away if the view is freed */
  286.    pipe_resource_reference(&newtex, NULL);
  287.  
  288.    image->sampler_view = view;
  289.  
  290.    vg_context_add_object(ctx, &image->base);
  291.  
  292.    image_cleari(image, 0, 0, 0, image->width, image->height);
  293.    return image;
  294. }
  295.  
  296. void image_destroy(struct vg_image *img)
  297. {
  298.    struct vg_context *ctx = vg_current_context();
  299.    vg_context_remove_object(ctx, &img->base);
  300.  
  301.  
  302.    if (img->parent) {
  303.       /* remove img from the parent child array */
  304.       int idx;
  305.       struct vg_image **array =
  306.          (struct vg_image **)img->parent->children_array->data;
  307.  
  308.       for (idx = 0; idx < img->parent->children_array->num_elements; ++idx) {
  309.          struct vg_image *child = array[idx];
  310.          if (child == img) {
  311.             break;
  312.          }
  313.       }
  314.       debug_assert(idx < img->parent->children_array->num_elements);
  315.       array_remove_element(img->parent->children_array, idx);
  316.    }
  317.  
  318.    if (img->children_array && img->children_array->num_elements) {
  319.       /* reparent the children */
  320.       VGint i;
  321.       struct vg_image *parent = img->parent;
  322.       struct vg_image **children =
  323.          (struct vg_image **)img->children_array->data;
  324.       if (!parent) {
  325.          VGint min_x = children[0]->x;
  326.          parent = children[0];
  327.  
  328.          for (i = 1; i < img->children_array->num_elements; ++i) {
  329.             struct vg_image *child = children[i];
  330.             if (child->x < min_x) {
  331.                parent = child;
  332.             }
  333.          }
  334.       }
  335.  
  336.       for (i = 0; i < img->children_array->num_elements; ++i) {
  337.          struct vg_image *child = children[i];
  338.          if (child != parent) {
  339.             child->parent = parent;
  340.             if (!parent->children_array) {
  341.                parent->children_array = array_create(
  342.                   sizeof(struct vg_image*));
  343.             }
  344.             array_append_data(parent->children_array,
  345.                               &child, 1);
  346.          } else
  347.             child->parent = NULL;
  348.       }
  349.       array_destroy(img->children_array);
  350.    }
  351.  
  352.    vg_free_object(&img->base);
  353.  
  354.    pipe_sampler_view_reference(&img->sampler_view, NULL);
  355.    FREE(img);
  356. }
  357.  
  358. void image_clear(struct vg_image *img,
  359.                  VGint x, VGint y, VGint width, VGint height)
  360. {
  361.    struct vg_context *ctx = vg_current_context();
  362.    VGfloat *clear_colorf = ctx->state.vg.clear_color;
  363.    VGubyte r, g, b ,a;
  364.    VGint clear_colori;
  365.    /* FIXME: this is very nasty */
  366.    r = float_to_ubyte(clear_colorf[0]);
  367.    g = float_to_ubyte(clear_colorf[1]);
  368.    b = float_to_ubyte(clear_colorf[2]);
  369.    a = float_to_ubyte(clear_colorf[3]);
  370.    clear_colori = r << 24 | g << 16 | b << 8 | a;
  371.    image_cleari(img, clear_colori, x, y, width, height);
  372. }
  373.  
  374. void image_sub_data(struct vg_image *image,
  375.                     const void * data,
  376.                     VGint dataStride,
  377.                     VGImageFormat dataFormat,
  378.                     VGint x, VGint y,
  379.                     VGint width, VGint height)
  380. {
  381.    const VGint yStep = 1;
  382.    VGubyte *src = (VGubyte *)data;
  383.    VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4];
  384.    VGfloat *df = (VGfloat*)temp;
  385.    VGint i;
  386.    struct vg_context *ctx = vg_current_context();
  387.    struct pipe_context *pipe = ctx->pipe;
  388.    struct pipe_resource *texture = image_texture(image);
  389.    VGint xoffset = 0, yoffset = 0;
  390.  
  391.    if (x < 0) {
  392.       xoffset -= x;
  393.       width += x;
  394.       x = 0;
  395.    }
  396.    if (y < 0) {
  397.       yoffset -= y;
  398.       height += y;
  399.       y = 0;
  400.    }
  401.  
  402.    if (width <= 0 || height <= 0) {
  403.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  404.       return;
  405.    }
  406.  
  407.    if (x > image->width || y > image->width) {
  408.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  409.       return;
  410.    }
  411.  
  412.    if (x + width > image->width) {
  413.       width = image->width - x;
  414.    }
  415.  
  416.    if (y + height > image->height) {
  417.       height = image->height - y;
  418.    }
  419.  
  420.    { /* upload color_data */
  421.       struct pipe_transfer *transfer;
  422.       void *map = pipe_transfer_map(pipe, texture, 0, 0,
  423.                                     PIPE_TRANSFER_WRITE, 0, 0,
  424.                                     texture->width0, texture->height0,
  425.                                     &transfer);
  426.       src += (dataStride * yoffset);
  427.       for (i = 0; i < height; i++) {
  428.          _vega_unpack_float_span_rgba(ctx, width, xoffset, src, dataFormat, temp);
  429.          pipe_put_tile_rgba(transfer, map, x+image->x, y+image->y, width, 1, df);
  430.          y += yStep;
  431.          src += dataStride;
  432.       }
  433.       pipe->transfer_unmap(pipe, transfer);
  434.    }
  435. }
  436.  
  437. void image_get_sub_data(struct vg_image * image,
  438.                         void * data,
  439.                         VGint dataStride,
  440.                         VGImageFormat dataFormat,
  441.                         VGint sx, VGint sy,
  442.                         VGint width, VGint height)
  443. {
  444.    struct vg_context *ctx = vg_current_context();
  445.    struct pipe_context *pipe = ctx->pipe;
  446.    VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4];
  447.    VGfloat *df = (VGfloat*)temp;
  448.    VGint y = 0, yStep = 1;
  449.    VGint i;
  450.    VGubyte *dst = (VGubyte *)data;
  451.  
  452.    {
  453.       struct pipe_transfer *transfer;
  454.       void *map =
  455.          pipe_transfer_map(pipe,
  456.                            image->sampler_view->texture,  0, 0,
  457.                            PIPE_TRANSFER_READ,
  458.                            0, 0,
  459.                            image->x + image->width,
  460.                            image->y + image->height, &transfer);
  461.       /* Do a row at a time to flip image data vertically */
  462.       for (i = 0; i < height; i++) {
  463. #if 0
  464.          debug_printf("%d-%d  == %d\n", sy, height, y);
  465. #endif
  466.          pipe_get_tile_rgba(transfer, map, sx+image->x, y, width, 1, df);
  467.          y += yStep;
  468.          _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, dst);
  469.          dst += dataStride;
  470.       }
  471.  
  472.       pipe->transfer_unmap(pipe, transfer);
  473.    }
  474. }
  475.  
  476. struct vg_image * image_child_image(struct vg_image *parent,
  477.                                     VGint x, VGint y,
  478.                                     VGint width, VGint height)
  479. {
  480.    struct vg_context *ctx = vg_current_context();
  481.    struct vg_image *image = CALLOC_STRUCT(vg_image);
  482.  
  483.    vg_init_object(&image->base, ctx, VG_OBJECT_IMAGE);
  484.  
  485.    image->x = parent->x + x;
  486.    image->y = parent->y + y;
  487.    image->width = width;
  488.    image->height = height;
  489.    image->parent = parent;
  490.    image->sampler_view = NULL;
  491.    pipe_sampler_view_reference(&image->sampler_view,
  492.                                parent->sampler_view);
  493.  
  494.    image->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
  495.    image->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
  496.    image->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
  497.    image->sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
  498.    image->sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
  499.    image->sampler.normalized_coords = 1;
  500.  
  501.    if (!parent->children_array)
  502.       parent->children_array = array_create(
  503.          sizeof(struct vg_image*));
  504.  
  505.    array_append_data(parent->children_array,
  506.                      &image, 1);
  507.  
  508.    vg_context_add_object(ctx, &image->base);
  509.  
  510.    return image;
  511. }
  512.  
  513. void image_copy(struct vg_image *dst, VGint dx, VGint dy,
  514.                 struct vg_image *src, VGint sx, VGint sy,
  515.                 VGint width, VGint height,
  516.                 VGboolean dither)
  517. {
  518.    struct vg_context *ctx = vg_current_context();
  519.  
  520.    if (width <= 0 || height <= 0) {
  521.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  522.       return;
  523.    }
  524.    vg_copy_texture(ctx, dst->sampler_view->texture, dst->x + dx, dst->y + dy,
  525.                    src->sampler_view, src->x + sx, src->y + sy, width, height);
  526. }
  527.  
  528. void image_draw(struct vg_image *img, struct matrix *matrix)
  529. {
  530.    struct vg_context *ctx = vg_current_context();
  531.    struct matrix paint_matrix;
  532.    VGfloat x1, y1;
  533.    VGfloat x2, y2;
  534.    VGfloat x3, y3;
  535.    VGfloat x4, y4;
  536.  
  537.    if (!vg_get_paint_matrix(ctx,
  538.                             &ctx->state.vg.fill_paint_to_user_matrix,
  539.                             matrix,
  540.                             &paint_matrix))
  541.       return;
  542.  
  543.    x1 = 0;
  544.    y1 = 0;
  545.    x2 = img->width;
  546.    y2 = 0;
  547.    x3 = img->width;
  548.    y3 = img->height;
  549.    x4 = 0;
  550.    y4 = img->height;
  551.  
  552.    shader_set_surface_matrix(ctx->shader, matrix);
  553.    shader_set_drawing_image(ctx->shader, VG_TRUE);
  554.    shader_set_paint(ctx->shader, ctx->state.vg.fill_paint);
  555.    shader_set_paint_matrix(ctx->shader, &paint_matrix);
  556.    shader_set_image(ctx->shader, img);
  557.    shader_bind(ctx->shader);
  558.  
  559.    renderer_texture_quad(ctx->renderer, image_texture(img),
  560.                          img->x, img->y, img->x + img->width, img->y + img->height,
  561.                          x1, y1, x2, y2, x3, y3, x4, y4);
  562. }
  563.  
  564. void image_set_pixels(VGint dx, VGint dy,
  565.                       struct vg_image *src, VGint sx, VGint sy,
  566.                       VGint width, VGint height)
  567. {
  568.    struct vg_context *ctx = vg_current_context();
  569.    struct pipe_context *pipe = ctx->pipe;
  570.    struct pipe_surface *surf, surf_tmpl;
  571.    struct st_renderbuffer *strb = ctx->draw_buffer->strb;
  572.  
  573.    u_surface_default_template(&surf_tmpl, image_texture(src));
  574.    surf = pipe->create_surface(pipe, image_texture(src), &surf_tmpl);
  575.  
  576.    vg_copy_surface(ctx, strb->surface, dx, dy,
  577.                    surf, sx+src->x, sy+src->y, width, height);
  578.  
  579.    pipe->surface_destroy(pipe, surf);
  580. }
  581.  
  582. void image_get_pixels(struct vg_image *dst, VGint dx, VGint dy,
  583.                       VGint sx, VGint sy,
  584.                       VGint width, VGint height)
  585. {
  586.    struct vg_context *ctx = vg_current_context();
  587.    struct pipe_context *pipe = ctx->pipe;
  588.    struct pipe_surface *surf, surf_tmpl;
  589.    struct st_renderbuffer *strb = ctx->draw_buffer->strb;
  590.  
  591.    /* flip the y coordinates */
  592.    /*dy = dst->height - dy - height;*/
  593.  
  594.    u_surface_default_template(&surf_tmpl, image_texture(dst));
  595.    surf = pipe->create_surface(pipe, image_texture(dst), &surf_tmpl);
  596.  
  597.    vg_copy_surface(ctx, surf, dst->x + dx, dst->y + dy,
  598.                    strb->surface, sx, sy, width, height);
  599.  
  600.    pipe_surface_reference(&surf, NULL);
  601. }
  602.  
  603.  
  604. VGboolean vg_image_overlaps(struct vg_image *dst,
  605.                             struct vg_image *src)
  606. {
  607.    if (dst == src || dst->parent == src ||
  608.        dst == src->parent)
  609.       return VG_TRUE;
  610.    if (dst->parent && dst->parent == src->parent) {
  611.       VGfloat left1 = dst->x;
  612.       VGfloat left2 = src->x;
  613.       VGfloat right1 = dst->x + dst->width;
  614.       VGfloat right2 = src->x + src->width;
  615.       VGfloat bottom1 = dst->y;
  616.       VGfloat bottom2 = src->y;
  617.       VGfloat top1 = dst->y + dst->height;
  618.       VGfloat top2 = src->y + src->height;
  619.  
  620.       return !(left2 > right1 || right2 < left1 ||
  621.                top2 > bottom1 || bottom2 < top1);
  622.    }
  623.    return VG_FALSE;
  624. }
  625.  
  626. VGint image_bind_samplers(struct vg_image *img, struct pipe_sampler_state **samplers,
  627.                           struct pipe_sampler_view **sampler_views)
  628. {
  629.    img->sampler.min_img_filter = image_sampler_filter(img->base.ctx);
  630.    img->sampler.mag_img_filter = image_sampler_filter(img->base.ctx);
  631.    samplers[3] = &img->sampler;
  632.    sampler_views[3] = img->sampler_view;
  633.    return 1;
  634. }
  635.  
  636. VGint image_sampler_filter(struct vg_context *ctx)
  637. {
  638.     switch(ctx->state.vg.image_quality) {
  639.     case VG_IMAGE_QUALITY_NONANTIALIASED:
  640.        return PIPE_TEX_FILTER_NEAREST;
  641.        break;
  642.     case VG_IMAGE_QUALITY_FASTER:
  643.        return PIPE_TEX_FILTER_NEAREST;
  644.        break;
  645.     case VG_IMAGE_QUALITY_BETTER:
  646.        /* possibly use anisotropic filtering */
  647.        return PIPE_TEX_FILTER_LINEAR;
  648.        break;
  649.     default:
  650.        debug_printf("Unknown image quality");
  651.     }
  652.     return PIPE_TEX_FILTER_NEAREST;
  653. }
  654.