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 "mask.h"
  28.  
  29. #include "path.h"
  30. #include "image.h"
  31. #include "shaders_cache.h"
  32. #include "renderer.h"
  33. #include "asm_util.h"
  34.  
  35. #include "pipe/p_context.h"
  36. #include "pipe/p_screen.h"
  37. #include "util/u_inlines.h"
  38. #include "util/u_format.h"
  39. #include "util/u_memory.h"
  40. #include "util/u_surface.h"
  41. #include "util/u_sampler.h"
  42.  
  43. struct vg_mask_layer {
  44.    struct vg_object base;
  45.  
  46.    VGint width;
  47.    VGint height;
  48.  
  49.    struct pipe_sampler_view *sampler_view;
  50. };
  51.  
  52. static INLINE VGboolean
  53. intersect_rectangles(VGint dwidth, VGint dheight,
  54.                      VGint swidth, VGint sheight,
  55.                      VGint tx, VGint ty,
  56.                      VGint twidth, VGint theight,
  57.                      VGint *offsets,
  58.                      VGint *location)
  59. {
  60.    if (tx + twidth <= 0 || tx >= dwidth)
  61.       return VG_FALSE;
  62.    if (ty + theight <= 0 || ty >= dheight)
  63.       return VG_FALSE;
  64.  
  65.    offsets[0] = 0;
  66.    offsets[1] = 0;
  67.    location[0] = tx;
  68.    location[1] = ty;
  69.  
  70.    if (tx < 0) {
  71.       offsets[0] -= tx;
  72.       location[0] = 0;
  73.  
  74.       location[2] = MIN2(tx + swidth, MIN2(dwidth, tx + twidth));
  75.       offsets[2] = location[2];
  76.    } else {
  77.       offsets[2] = MIN2(twidth, MIN2(dwidth - tx, swidth ));
  78.       location[2] = offsets[2];
  79.    }
  80.  
  81.    if (ty < 0) {
  82.       offsets[1] -= ty;
  83.       location[1] = 0;
  84.  
  85.       location[3] = MIN2(ty + sheight, MIN2(dheight, ty + theight));
  86.       offsets[3] = location[3];
  87.    } else {
  88.       offsets[3] = MIN2(theight, MIN2(dheight - ty, sheight));
  89.       location[3] = offsets[3];
  90.    }
  91.  
  92.    return VG_TRUE;
  93. }
  94.  
  95. #if DEBUG_MASKS
  96. static void read_alpha_mask(void * data, VGint dataStride,
  97.                             VGImageFormat dataFormat,
  98.                             VGint sx, VGint sy,
  99.                             VGint width, VGint height)
  100. {
  101.    struct vg_context *ctx = vg_current_context();
  102.    struct pipe_context *pipe = ctx->pipe;
  103.  
  104.    struct st_framebuffer *stfb = ctx->draw_buffer;
  105.    struct st_renderbuffer *strb = stfb->alpha_mask;
  106.  
  107.    VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4];
  108.    VGfloat *df = (VGfloat*)temp;
  109.    VGint y = (stfb->height - sy) - 1, yStep = -1;
  110.    VGint i;
  111.    VGubyte *dst = (VGubyte *)data;
  112.    VGint xoffset = 0, yoffset = 0;
  113.  
  114.    if (sx < 0) {
  115.       xoffset = -sx;
  116.       xoffset *= _vega_size_for_format(dataFormat);
  117.       width += sx;
  118.       sx = 0;
  119.    }
  120.    if (sy < 0) {
  121.       yoffset = -sy;
  122.       height += sy;
  123.       sy = 0;
  124.       y = (stfb->height - sy) - 1;
  125.       yoffset *= dataStride;
  126.    }
  127.  
  128.    {
  129.       struct pipe_surface *surf;
  130.  
  131.       surf = pipe->create_surface(pipe, strb->texture,  0, 0, 0,
  132.                                   PIPE_BIND_TRANSFER_READ);
  133.  
  134.       /* Do a row at a time to flip image data vertically */
  135.       for (i = 0; i < height; i++) {
  136. #if 0
  137.          debug_printf("%d-%d  == %d\n", sy, height, y);
  138. #endif
  139.          pipe_get_tile_rgba(surf, sx, y, width, 1, df);
  140.          y += yStep;
  141.          _vega_pack_rgba_span_float(ctx, width, temp, dataFormat,
  142.                                     dst + yoffset + xoffset);
  143.          dst += dataStride;
  144.       }
  145.  
  146.       pipe_surface_reference(&surf, NULL);
  147.    }
  148. }
  149.  
  150. void save_alpha_to_file(const char *filename)
  151. {
  152.    struct vg_context *ctx = vg_current_context();
  153.    struct st_framebuffer *stfb = ctx->draw_buffer;
  154.    VGint *data;
  155.    int i, j;
  156.  
  157.    data = malloc(sizeof(int) * stfb->width * stfb->height);
  158.    read_alpha_mask(data, stfb->width * sizeof(int),
  159.                    VG_sRGBA_8888,
  160.                    0, 0, stfb->width, stfb->height);
  161.    fprintf(stderr, "/*---------- start */\n");
  162.    fprintf(stderr, "const int image_width = %d;\n",
  163.            stfb->width);
  164.    fprintf(stderr, "const int image_height = %d;\n",
  165.            stfb->height);
  166.    fprintf(stderr, "const int image_data = {\n");
  167.    for (i = 0; i < stfb->height; ++i) {
  168.       for (j = 0; j < stfb->width; ++j) {
  169.          int rgba = data[i * stfb->height + j];
  170.          int argb = 0;
  171.          argb = (rgba >> 8);
  172.          argb |= ((rgba & 0xff) << 24);
  173.          fprintf(stderr, "0x%x, ", argb);
  174.       }
  175.       fprintf(stderr, "\n");
  176.    }
  177.    fprintf(stderr, "};\n");
  178.    fprintf(stderr, "/*---------- end */\n");
  179. }
  180. #endif
  181.  
  182. /* setup mask shader */
  183. static void *setup_mask_operation(VGMaskOperation operation)
  184. {
  185.    struct vg_context *ctx = vg_current_context();
  186.    void *shader = 0;
  187.  
  188.    switch (operation) {
  189.    case VG_UNION_MASK: {
  190.       if (!ctx->mask.union_fs) {
  191.          ctx->mask.union_fs = shader_create_from_text(ctx->pipe,
  192.                                                       union_mask_asm,
  193.                                                       200,
  194.                                                       PIPE_SHADER_FRAGMENT);
  195.       }
  196.       shader = ctx->mask.union_fs->driver;
  197.    }
  198.       break;
  199.    case VG_INTERSECT_MASK: {
  200.       if (!ctx->mask.intersect_fs) {
  201.          ctx->mask.intersect_fs = shader_create_from_text(ctx->pipe,
  202.                                                           intersect_mask_asm,
  203.                                                           200,
  204.                                                           PIPE_SHADER_FRAGMENT);
  205.       }
  206.       shader = ctx->mask.intersect_fs->driver;
  207.    }
  208.       break;
  209.    case VG_SUBTRACT_MASK: {
  210.       if (!ctx->mask.subtract_fs) {
  211.          ctx->mask.subtract_fs = shader_create_from_text(ctx->pipe,
  212.                                                          subtract_mask_asm,
  213.                                                          200,
  214.                                                          PIPE_SHADER_FRAGMENT);
  215.       }
  216.       shader = ctx->mask.subtract_fs->driver;
  217.    }
  218.       break;
  219.    case VG_SET_MASK: {
  220.       if (!ctx->mask.set_fs) {
  221.          ctx->mask.set_fs = shader_create_from_text(ctx->pipe,
  222.                                                     set_mask_asm,
  223.                                                     200,
  224.                                                     PIPE_SHADER_FRAGMENT);
  225.       }
  226.       shader = ctx->mask.set_fs->driver;
  227.    }
  228.       break;
  229.    default:
  230.          assert(0);
  231.       break;
  232.    }
  233.  
  234.    return shader;
  235. }
  236.  
  237. static void mask_resource_fill(struct pipe_resource *dst,
  238.                                int x, int y, int width, int height,
  239.                                VGfloat coverage)
  240. {
  241.    struct vg_context *ctx = vg_current_context();
  242.    VGfloat fs_consts[12] = {
  243.       0.0f, 0.0f, 0.0f, 0.0f, /* not used */
  244.       0.0f, 0.0f, 0.0f, 0.0f, /* not used */
  245.       0.0f, 0.0f, 0.0f, coverage /* color */
  246.    };
  247.    void *fs;
  248.  
  249.    if (x < 0) {
  250.       width += x;
  251.       x = 0;
  252.    }
  253.    if (y < 0) {
  254.       height += y;
  255.       y = 0;
  256.    }
  257.  
  258.    fs = shaders_cache_fill(ctx->sc, VEGA_SOLID_FILL_SHADER);
  259.  
  260.    if (renderer_filter_begin(ctx->renderer, dst, VG_FALSE, ~0,
  261.             NULL, NULL, 0, fs, (const void *) fs_consts, sizeof(fs_consts))) {
  262.       renderer_filter(ctx->renderer, x, y, width, height, 0, 0, 0, 0);
  263.       renderer_filter_end(ctx->renderer);
  264.    }
  265.  
  266. #if DEBUG_MASKS
  267.    save_alpha_to_file(0);
  268. #endif
  269. }
  270.  
  271.  
  272. static void mask_using_texture(struct pipe_sampler_view *sampler_view,
  273.                                VGboolean is_layer,
  274.                                VGMaskOperation operation,
  275.                                VGint x, VGint y,
  276.                                VGint width, VGint height)
  277. {
  278.    struct vg_context *ctx = vg_current_context();
  279.    struct pipe_sampler_view *dst_view = vg_get_surface_mask(ctx);
  280.    struct pipe_resource *dst = dst_view->texture;
  281.    struct pipe_resource *texture = sampler_view->texture;
  282.    const struct pipe_sampler_state *samplers[2];
  283.    struct pipe_sampler_view *views[2];
  284.    struct pipe_sampler_state sampler;
  285.    VGint offsets[4], loc[4];
  286.    const VGfloat ones[4] = {1.f, 1.f, 1.f, 1.f};
  287.    void *fs;
  288.  
  289.    if (!intersect_rectangles(dst->width0, dst->height0,
  290.                              texture->width0, texture->height0,
  291.                              x, y, width, height,
  292.                              offsets, loc))
  293.       return;
  294. #if 0
  295.    debug_printf("Offset = [%d, %d, %d, %d]\n", offsets[0],
  296.                 offsets[1], offsets[2], offsets[3]);
  297.    debug_printf("Locati = [%d, %d, %d, %d]\n", loc[0],
  298.                 loc[1], loc[2], loc[3]);
  299. #endif
  300.  
  301.  
  302.    sampler = ctx->mask.sampler;
  303.    sampler.normalized_coords = 1;
  304.    samplers[0] = &sampler;
  305.    views[0] = sampler_view;
  306.  
  307.    /* prepare our blend surface */
  308.    samplers[1] = &ctx->mask.sampler;
  309.    views[1] = vg_prepare_blend_surface_from_mask(ctx);
  310.  
  311.    fs = setup_mask_operation(operation);
  312.  
  313.    if (renderer_filter_begin(ctx->renderer, dst, VG_FALSE,
  314.             ~0, samplers, views, 2, fs, (const void *) ones, sizeof(ones))) {
  315.       /* layer should be flipped when used as a texture */
  316.       if (is_layer) {
  317.          offsets[1] += offsets[3];
  318.          offsets[3] = -offsets[3];
  319.       }
  320.       renderer_filter(ctx->renderer,
  321.             loc[0], loc[1], loc[2], loc[3],
  322.             offsets[0], offsets[1], offsets[2], offsets[3]);
  323.       renderer_filter_end(ctx->renderer);
  324.    }
  325. }
  326.  
  327.  
  328. #ifdef OPENVG_VERSION_1_1
  329.  
  330. struct vg_mask_layer * mask_layer_create(VGint width, VGint height)
  331. {
  332.    struct vg_context *ctx = vg_current_context();
  333.    struct vg_mask_layer *mask = 0;
  334.  
  335.    mask = CALLOC_STRUCT(vg_mask_layer);
  336.    vg_init_object(&mask->base, ctx, VG_OBJECT_MASK);
  337.    mask->width = width;
  338.    mask->height = height;
  339.  
  340.    {
  341.       struct pipe_resource pt;
  342.       struct pipe_context *pipe = ctx->pipe;
  343.       struct pipe_screen *screen = ctx->pipe->screen;
  344.       struct pipe_sampler_view view_templ;
  345.       struct pipe_sampler_view *view = NULL;
  346.       struct pipe_resource *texture;
  347.  
  348.       memset(&pt, 0, sizeof(pt));
  349.       pt.target = PIPE_TEXTURE_2D;
  350.       pt.format = PIPE_FORMAT_B8G8R8A8_UNORM;
  351.       pt.last_level = 0;
  352.       pt.width0 = width;
  353.       pt.height0 = height;
  354.       pt.depth0 = 1;
  355.       pt.array_size = 1;
  356.       pt.bind = PIPE_BIND_SAMPLER_VIEW;
  357.  
  358.       texture = screen->resource_create(screen, &pt);
  359.  
  360.       if (texture) {
  361.          u_sampler_view_default_template(&view_templ, texture, texture->format);
  362.          view = pipe->create_sampler_view(pipe, texture, &view_templ);
  363.       }
  364.       pipe_resource_reference(&texture, NULL);
  365.       mask->sampler_view = view;
  366.    }
  367.  
  368.    vg_context_add_object(ctx, &mask->base);
  369.  
  370.    return mask;
  371. }
  372.  
  373. void mask_layer_destroy(struct vg_mask_layer *layer)
  374. {
  375.    struct vg_context *ctx = vg_current_context();
  376.  
  377.    vg_context_remove_object(ctx, &layer->base);
  378.    pipe_sampler_view_reference(&layer->sampler_view, NULL);
  379.    vg_free_object(&layer->base);
  380.    FREE(layer);
  381. }
  382.  
  383. void mask_layer_fill(struct vg_mask_layer *layer,
  384.                      VGint x, VGint y,
  385.                      VGint width, VGint height,
  386.                      VGfloat value)
  387. {
  388.    mask_resource_fill(layer->sampler_view->texture,
  389.                       x, y, width, height, value);
  390. }
  391.  
  392. void mask_copy(struct vg_mask_layer *layer,
  393.                VGint sx, VGint sy,
  394.                VGint dx, VGint dy,
  395.                VGint width, VGint height)
  396. {
  397.    struct vg_context *ctx = vg_current_context();
  398.    struct pipe_sampler_view *src = vg_get_surface_mask(ctx);
  399.    struct pipe_surface *surf, surf_tmpl;
  400.  
  401.    /* get the destination surface */
  402.    u_surface_default_template(&surf_tmpl, layer->sampler_view->texture);
  403.    surf = ctx->pipe->create_surface(ctx->pipe, layer->sampler_view->texture,
  404.                                     &surf_tmpl);
  405.    if (surf && renderer_copy_begin(ctx->renderer, surf, VG_FALSE, src)) {
  406.       /* layer should be flipped when used as a texture */
  407.       sy += height;
  408.       height = -height;
  409.  
  410.       renderer_copy(ctx->renderer,
  411.             dx, dy, width, height,
  412.             sx, sy, width, height);
  413.       renderer_copy_end(ctx->renderer);
  414.    }
  415.  
  416.    pipe_surface_reference(&surf, NULL);
  417. }
  418.  
  419. static void mask_layer_render_to(struct vg_mask_layer *layer,
  420.                                  struct path *path,
  421.                                  VGbitfield paint_modes)
  422. {
  423.    struct vg_context *ctx = vg_current_context();
  424.    struct pipe_context *pipe = ctx->pipe;
  425.    struct pipe_sampler_view *view = vg_get_surface_mask(ctx);
  426.    struct matrix *mat = &ctx->state.vg.path_user_to_surface_matrix;
  427.    struct pipe_surface *surf, surf_tmpl;
  428.    u_surface_default_template(&surf_tmpl, view->texture);
  429.    surf = pipe->create_surface(pipe, view->texture, &surf_tmpl);
  430.  
  431.    renderer_validate_for_mask_rendering(ctx->renderer, surf, mat);
  432.  
  433.    if (paint_modes & VG_FILL_PATH) {
  434.       path_fill(path);
  435.    }
  436.  
  437.    if (paint_modes & VG_STROKE_PATH){
  438.       path_stroke(path);
  439.    }
  440.  
  441.    pipe_surface_reference(&surf, NULL);
  442. }
  443.  
  444. void mask_render_to(struct path *path,
  445.                     VGbitfield paint_modes,
  446.                     VGMaskOperation operation)
  447. {
  448.    struct vg_context *ctx = vg_current_context();
  449.    struct st_framebuffer *stfb = ctx->draw_buffer;
  450.    struct vg_mask_layer *temp_layer;
  451.    VGint width, height;
  452.  
  453.    width = stfb->width;
  454.    height = stfb->height;
  455.  
  456.    temp_layer = mask_layer_create(width, height);
  457.    mask_layer_fill(temp_layer, 0, 0, width, height, 0.0f);
  458.  
  459.    mask_layer_render_to(temp_layer, path, paint_modes);
  460.  
  461.    mask_using_layer(temp_layer, operation, 0, 0, width, height);
  462.  
  463.    mask_layer_destroy(temp_layer);
  464. }
  465.  
  466. void mask_using_layer(struct vg_mask_layer *layer,
  467.                       VGMaskOperation operation,
  468.                       VGint x, VGint y,
  469.                       VGint width, VGint height)
  470. {
  471.    mask_using_texture(layer->sampler_view, VG_TRUE, operation,
  472.                       x, y, width, height);
  473. }
  474.  
  475. VGint mask_layer_width(struct vg_mask_layer *layer)
  476. {
  477.    return layer->width;
  478. }
  479.  
  480. VGint mask_layer_height(struct vg_mask_layer *layer)
  481. {
  482.    return layer->height;
  483. }
  484.  
  485.  
  486. #endif
  487.  
  488. void mask_using_image(struct vg_image *image,
  489.                       VGMaskOperation operation,
  490.                       VGint x, VGint y,
  491.                       VGint width, VGint height)
  492. {
  493.    mask_using_texture(image->sampler_view, VG_FALSE, operation,
  494.                       x, y, width, height);
  495. }
  496.  
  497. void mask_fill(VGint x, VGint y, VGint width, VGint height,
  498.                VGfloat value)
  499. {
  500.    struct vg_context *ctx = vg_current_context();
  501.    struct pipe_sampler_view *view = vg_get_surface_mask(ctx);
  502.  
  503. #if DEBUG_MASKS
  504.    debug_printf("mask_fill(%d, %d, %d, %d) with  rgba(%f, %f, %f, %f)\n",
  505.                 x, y, width, height,
  506.                 0.0f, 0.0f, 0.0f, value);
  507. #endif
  508.  
  509.    mask_resource_fill(view->texture, x, y, width, height, value);
  510. }
  511.  
  512. VGint mask_bind_samplers(struct pipe_sampler_state **samplers,
  513.                          struct pipe_sampler_view **sampler_views)
  514. {
  515.    struct vg_context *ctx = vg_current_context();
  516.  
  517.    if (ctx->state.vg.masking) {
  518.       samplers[1] = &ctx->mask.sampler;
  519.       sampler_views[1] = vg_get_surface_mask(ctx);
  520.       return 1;
  521.    } else
  522.       return 0;
  523. }
  524.