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_context.h"
  28.  
  29. #include "paint.h"
  30. #include "renderer.h"
  31. #include "shaders_cache.h"
  32. #include "shader.h"
  33. #include "vg_manager.h"
  34. #include "api.h"
  35. #include "mask.h"
  36. #include "handle.h"
  37.  
  38. #include "pipe/p_context.h"
  39. #include "util/u_inlines.h"
  40.  
  41. #include "cso_cache/cso_context.h"
  42.  
  43. #include "util/u_memory.h"
  44. #include "util/u_blit.h"
  45. #include "util/u_sampler.h"
  46. #include "util/u_surface.h"
  47. #include "util/u_format.h"
  48.  
  49. struct vg_context *_vg_context = 0;
  50.  
  51. struct vg_context * vg_current_context(void)
  52. {
  53.    return _vg_context;
  54. }
  55.  
  56. /**
  57.  * A depth/stencil rb will be needed regardless of what the visual says.
  58.  */
  59. static boolean
  60. choose_depth_stencil_format(struct vg_context *ctx)
  61. {
  62.    struct pipe_screen *screen = ctx->pipe->screen;
  63.    enum pipe_format formats[] = {
  64.       PIPE_FORMAT_Z24_UNORM_S8_UINT,
  65.       PIPE_FORMAT_S8_UINT_Z24_UNORM,
  66.       PIPE_FORMAT_NONE
  67.    };
  68.    enum pipe_format *fmt;
  69.  
  70.    for (fmt = formats; *fmt != PIPE_FORMAT_NONE; fmt++) {
  71.       if (screen->is_format_supported(screen, *fmt,
  72.                PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL))
  73.          break;
  74.    }
  75.  
  76.    ctx->ds_format = *fmt;
  77.  
  78.    return (ctx->ds_format != PIPE_FORMAT_NONE);
  79. }
  80.  
  81. void vg_set_current_context(struct vg_context *ctx)
  82. {
  83.    _vg_context = ctx;
  84.    api_make_dispatch_current((ctx) ? ctx->dispatch : NULL);
  85. }
  86.  
  87. struct vg_context * vg_create_context(struct pipe_context *pipe,
  88.                                       const void *visual,
  89.                                       struct vg_context *share)
  90. {
  91.    struct vg_context *ctx;
  92.  
  93.    ctx = CALLOC_STRUCT(vg_context);
  94.  
  95.    ctx->pipe = pipe;
  96.    if (!choose_depth_stencil_format(ctx)) {
  97.       FREE(ctx);
  98.       return NULL;
  99.    }
  100.  
  101.    ctx->dispatch = api_create_dispatch();
  102.  
  103.    vg_init_state(&ctx->state.vg);
  104.    ctx->state.dirty = ALL_DIRTY;
  105.  
  106.    ctx->cso_context = cso_create_context(pipe);
  107.  
  108.    ctx->default_paint = paint_create(ctx);
  109.    ctx->state.vg.stroke_paint = ctx->default_paint;
  110.    ctx->state.vg.fill_paint = ctx->default_paint;
  111.  
  112.  
  113.    ctx->mask.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
  114.    ctx->mask.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
  115.    ctx->mask.sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
  116.    ctx->mask.sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
  117.    ctx->mask.sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
  118.    ctx->mask.sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
  119.    ctx->mask.sampler.normalized_coords = 0;
  120.  
  121.    ctx->blend_sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
  122.    ctx->blend_sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
  123.    ctx->blend_sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
  124.    ctx->blend_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
  125.    ctx->blend_sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
  126.    ctx->blend_sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
  127.    ctx->blend_sampler.normalized_coords = 0;
  128.  
  129.    vg_set_error(ctx, VG_NO_ERROR);
  130.  
  131.    ctx->owned_objects[VG_OBJECT_PAINT] = cso_hash_create();
  132.    ctx->owned_objects[VG_OBJECT_IMAGE] = cso_hash_create();
  133.    ctx->owned_objects[VG_OBJECT_MASK] = cso_hash_create();
  134.    ctx->owned_objects[VG_OBJECT_FONT] = cso_hash_create();
  135.    ctx->owned_objects[VG_OBJECT_PATH] = cso_hash_create();
  136.  
  137.    ctx->renderer = renderer_create(ctx);
  138.    ctx->sc = shaders_cache_create(ctx);
  139.    ctx->shader = shader_create(ctx);
  140.  
  141.    ctx->blit = util_create_blit(ctx->pipe, ctx->cso_context);
  142.  
  143.    return ctx;
  144. }
  145.  
  146. void vg_destroy_context(struct vg_context *ctx)
  147. {
  148.    struct pipe_resource **cbuf = &ctx->mask.cbuf;
  149.  
  150.    util_destroy_blit(ctx->blit);
  151.    renderer_destroy(ctx->renderer);
  152.    shaders_cache_destroy(ctx->sc);
  153.    shader_destroy(ctx->shader);
  154.    paint_destroy(ctx->default_paint);
  155.  
  156.    if (*cbuf)
  157.       pipe_resource_reference(cbuf, NULL);
  158.  
  159.    if (ctx->mask.union_fs)
  160.       vg_shader_destroy(ctx, ctx->mask.union_fs);
  161.    if (ctx->mask.intersect_fs)
  162.       vg_shader_destroy(ctx, ctx->mask.intersect_fs);
  163.    if (ctx->mask.subtract_fs)
  164.       vg_shader_destroy(ctx, ctx->mask.subtract_fs);
  165.    if (ctx->mask.set_fs)
  166.       vg_shader_destroy(ctx, ctx->mask.set_fs);
  167.  
  168.    cso_release_all(ctx->cso_context);
  169.    cso_destroy_context(ctx->cso_context);
  170.  
  171.    cso_hash_delete(ctx->owned_objects[VG_OBJECT_PAINT]);
  172.    cso_hash_delete(ctx->owned_objects[VG_OBJECT_IMAGE]);
  173.    cso_hash_delete(ctx->owned_objects[VG_OBJECT_MASK]);
  174.    cso_hash_delete(ctx->owned_objects[VG_OBJECT_FONT]);
  175.    cso_hash_delete(ctx->owned_objects[VG_OBJECT_PATH]);
  176.  
  177.    api_destroy_dispatch(ctx->dispatch);
  178.  
  179.    FREE(ctx);
  180. }
  181.  
  182. void vg_init_object(struct vg_object *obj, struct vg_context *ctx, enum vg_object_type type)
  183. {
  184.    obj->type = type;
  185.    obj->ctx = ctx;
  186.    obj->handle = create_handle(obj);
  187. }
  188.  
  189. /** free object resources, but not the object itself */
  190. void vg_free_object(struct vg_object *obj)
  191. {
  192.    obj->type = 0;
  193.    obj->ctx = NULL;
  194.    destroy_handle(obj->handle);
  195. }
  196.  
  197. VGboolean vg_context_is_object_valid(struct vg_context *ctx,
  198.                                 enum vg_object_type type,
  199.                                 VGHandle handle)
  200. {
  201.     if (ctx) {
  202.        struct cso_hash *hash = ctx->owned_objects[type];
  203.        if (!hash)
  204.           return VG_FALSE;
  205.        return cso_hash_contains(hash, (unsigned) handle);
  206.     }
  207.     return VG_FALSE;
  208. }
  209.  
  210. void vg_context_add_object(struct vg_context *ctx,
  211.                            struct vg_object *obj)
  212. {
  213.     if (ctx) {
  214.        struct cso_hash *hash = ctx->owned_objects[obj->type];
  215.        if (!hash)
  216.           return;
  217.        cso_hash_insert(hash, (unsigned) obj->handle, obj);
  218.     }
  219. }
  220.  
  221. void vg_context_remove_object(struct vg_context *ctx,
  222.                               struct vg_object *obj)
  223. {
  224.    if (ctx) {
  225.       struct cso_hash *hash = ctx->owned_objects[obj->type];
  226.       if (!hash)
  227.          return;
  228.       cso_hash_take(hash, (unsigned) obj->handle);
  229.    }
  230. }
  231.  
  232. static struct pipe_resource *
  233. create_texture(struct pipe_context *pipe, enum pipe_format format,
  234.                     VGint width, VGint height)
  235. {
  236.    struct pipe_resource templ;
  237.  
  238.    memset(&templ, 0, sizeof(templ));
  239.  
  240.    if (format != PIPE_FORMAT_NONE) {
  241.       templ.format = format;
  242.    }
  243.    else {
  244.       templ.format = PIPE_FORMAT_B8G8R8A8_UNORM;
  245.    }
  246.  
  247.    templ.target = PIPE_TEXTURE_2D;
  248.    templ.width0 = width;
  249.    templ.height0 = height;
  250.    templ.depth0 = 1;
  251.    templ.array_size = 1;
  252.    templ.last_level = 0;
  253.  
  254.    if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) {
  255.       templ.bind = PIPE_BIND_DEPTH_STENCIL;
  256.    } else {
  257.       templ.bind = (PIPE_BIND_DISPLAY_TARGET |
  258.                     PIPE_BIND_RENDER_TARGET |
  259.                     PIPE_BIND_SAMPLER_VIEW);
  260.    }
  261.  
  262.    return pipe->screen->resource_create(pipe->screen, &templ);
  263. }
  264.  
  265. static struct pipe_sampler_view *
  266. create_tex_and_view(struct pipe_context *pipe, enum pipe_format format,
  267.                     VGint width, VGint height)
  268. {
  269.    struct pipe_resource *texture;
  270.    struct pipe_sampler_view view_templ;
  271.    struct pipe_sampler_view *view;
  272.  
  273.    texture = create_texture(pipe, format, width, height);
  274.  
  275.    if (!texture)
  276.       return NULL;
  277.  
  278.    u_sampler_view_default_template(&view_templ, texture, texture->format);
  279.    view = pipe->create_sampler_view(pipe, texture, &view_templ);
  280.    /* want the texture to go away if the view is freed */
  281.    pipe_resource_reference(&texture, NULL);
  282.  
  283.    return view;
  284. }
  285.  
  286. static void
  287. vg_context_update_surface_mask_view(struct vg_context *ctx,
  288.                                     uint width, uint height)
  289. {
  290.    struct st_framebuffer *stfb = ctx->draw_buffer;
  291.    struct pipe_sampler_view *old_sampler_view = stfb->surface_mask_view;
  292.    struct pipe_context *pipe = ctx->pipe;
  293.  
  294.    if (old_sampler_view &&
  295.        old_sampler_view->texture->width0 == width &&
  296.        old_sampler_view->texture->height0 == height)
  297.       return;
  298.  
  299.    /*
  300.      we use PIPE_FORMAT_B8G8R8A8_UNORM because we want to render to
  301.      this texture and use it as a sampler, so while this wastes some
  302.      space it makes both of those a lot simpler
  303.    */
  304.    stfb->surface_mask_view = create_tex_and_view(pipe,
  305.          PIPE_FORMAT_B8G8R8A8_UNORM, width, height);
  306.  
  307.    if (!stfb->surface_mask_view) {
  308.       if (old_sampler_view)
  309.          pipe_sampler_view_reference(&old_sampler_view, NULL);
  310.       return;
  311.    }
  312.  
  313.    /* XXX could this call be avoided? */
  314.    vg_validate_state(ctx);
  315.  
  316.    /* alpha mask starts with 1.f alpha */
  317.    mask_fill(0, 0, width, height, 1.f);
  318.  
  319.    /* if we had an old surface copy it over */
  320.    if (old_sampler_view) {
  321.       struct pipe_box src_box;
  322.       u_box_origin_2d(MIN2(old_sampler_view->texture->width0,
  323.                            stfb->surface_mask_view->texture->width0),
  324.                       MIN2(old_sampler_view->texture->height0,
  325.                            stfb->surface_mask_view->texture->height0),
  326.                       &src_box);
  327.  
  328.       pipe->resource_copy_region(pipe,
  329.                                  stfb->surface_mask_view->texture,
  330.                                  0, 0, 0, 0,
  331.                                  old_sampler_view->texture,
  332.                                  0, &src_box);
  333.    }
  334.  
  335.    /* Free the old texture
  336.     */
  337.    if (old_sampler_view)
  338.       pipe_sampler_view_reference(&old_sampler_view, NULL);
  339. }
  340.  
  341. static void
  342. vg_context_update_blend_texture_view(struct vg_context *ctx,
  343.                                      uint width, uint height)
  344. {
  345.    struct pipe_context *pipe = ctx->pipe;
  346.    struct st_framebuffer *stfb = ctx->draw_buffer;
  347.    struct pipe_sampler_view *old = stfb->blend_texture_view;
  348.  
  349.    if (old &&
  350.        old->texture->width0 == width &&
  351.        old->texture->height0 == height)
  352.       return;
  353.  
  354.    stfb->blend_texture_view = create_tex_and_view(pipe,
  355.          PIPE_FORMAT_B8G8R8A8_UNORM, width, height);
  356.  
  357.    pipe_sampler_view_reference(&old, NULL);
  358. }
  359.  
  360. static boolean
  361. vg_context_update_depth_stencil_rb(struct vg_context * ctx,
  362.                                    uint width, uint height)
  363. {
  364.    struct st_renderbuffer *dsrb = ctx->draw_buffer->dsrb;
  365.    struct pipe_context *pipe = ctx->pipe;
  366.    struct pipe_surface surf_tmpl;
  367.  
  368.    if ((dsrb->width == width && dsrb->height == height) && dsrb->texture)
  369.       return FALSE;
  370.  
  371.    /* unreference existing ones */
  372.    pipe_surface_reference(&dsrb->surface, NULL);
  373.    pipe_resource_reference(&dsrb->texture, NULL);
  374.    dsrb->width = dsrb->height = 0;
  375.  
  376.    dsrb->texture = create_texture(pipe, dsrb->format, width, height);
  377.    if (!dsrb->texture)
  378.       return TRUE;
  379.  
  380.    u_surface_default_template(&surf_tmpl, dsrb->texture);
  381.    dsrb->surface = pipe->create_surface(pipe,
  382.                                         dsrb->texture,
  383.                                         &surf_tmpl);
  384.    if (!dsrb->surface) {
  385.       pipe_resource_reference(&dsrb->texture, NULL);
  386.       return TRUE;
  387.    }
  388.  
  389.    dsrb->width = width;
  390.    dsrb->height = height;
  391.  
  392.    assert(dsrb->surface->width == width);
  393.    assert(dsrb->surface->height == height);
  394.  
  395.    return TRUE;
  396. }
  397.  
  398. void vg_validate_state(struct vg_context *ctx)
  399. {
  400.    struct st_framebuffer *stfb = ctx->draw_buffer;
  401.  
  402.    vg_manager_validate_framebuffer(ctx);
  403.  
  404.    if (vg_context_update_depth_stencil_rb(ctx, stfb->width, stfb->height))
  405.       ctx->state.dirty |= DEPTH_STENCIL_DIRTY;
  406.  
  407.    /* blend state depends on fb format and paint color */
  408.    if ((ctx->state.dirty & FRAMEBUFFER_DIRTY) ||
  409.        (ctx->state.dirty & PAINT_DIRTY))
  410.       ctx->state.dirty |= BLEND_DIRTY;
  411.  
  412.    renderer_validate(ctx->renderer, ctx->state.dirty,
  413.          ctx->draw_buffer, &ctx->state.vg);
  414.  
  415.    ctx->state.dirty = 0;
  416.  
  417.    shader_set_masking(ctx->shader, ctx->state.vg.masking);
  418.    shader_set_image_mode(ctx->shader, ctx->state.vg.image_mode);
  419.    shader_set_color_transform(ctx->shader, ctx->state.vg.color_transform);
  420. }
  421.  
  422. VGboolean vg_object_is_valid(VGHandle object, enum vg_object_type type)
  423. {
  424.    struct vg_object *obj = handle_to_object(object);
  425.    if (obj && is_aligned(obj) && obj->type == type)
  426.       return VG_TRUE;
  427.    else
  428.       return VG_FALSE;
  429. }
  430.  
  431. void vg_set_error(struct vg_context *ctx,
  432.                   VGErrorCode code)
  433. {
  434.    /*vgGetError returns the oldest error code provided by
  435.     * an API call on the current context since the previous
  436.     * call to vgGetError on that context (or since the creation
  437.     of the context).*/
  438.    if (ctx->_error == VG_NO_ERROR)
  439.       ctx->_error = code;
  440. }
  441.  
  442. static void vg_prepare_blend_texture(struct vg_context *ctx,
  443.                                      struct pipe_sampler_view *src)
  444. {
  445.    struct st_framebuffer *stfb = ctx->draw_buffer;
  446.    struct pipe_surface *surf;
  447.    struct pipe_surface surf_tmpl;
  448.  
  449.    vg_context_update_blend_texture_view(ctx, stfb->width, stfb->height);
  450.  
  451.    u_surface_default_template(&surf_tmpl, stfb->blend_texture_view->texture);
  452.    surf = ctx->pipe->create_surface(ctx->pipe,
  453.                                     stfb->blend_texture_view->texture,
  454.                                     &surf_tmpl);
  455.    if (surf) {
  456.       util_blit_pixels_tex(ctx->blit,
  457.                            src, 0, 0, stfb->width, stfb->height,
  458.                            surf, 0, 0, stfb->width, stfb->height,
  459.                            0.0, PIPE_TEX_MIPFILTER_NEAREST);
  460.  
  461.       pipe_surface_reference(&surf, NULL);
  462.    }
  463. }
  464.  
  465. struct pipe_sampler_view *vg_prepare_blend_surface(struct vg_context *ctx)
  466. {
  467.    struct pipe_context *pipe = ctx->pipe;
  468.    struct pipe_sampler_view *view;
  469.    struct pipe_sampler_view view_templ;
  470.    struct st_framebuffer *stfb = ctx->draw_buffer;
  471.    struct st_renderbuffer *strb = stfb->strb;
  472.  
  473.    vg_validate_state(ctx);
  474.  
  475.    u_sampler_view_default_template(&view_templ, strb->texture, strb->texture->format);
  476.    view = pipe->create_sampler_view(pipe, strb->texture, &view_templ);
  477.  
  478.    vg_prepare_blend_texture(ctx, view);
  479.  
  480.    pipe_sampler_view_reference(&view, NULL);
  481.  
  482.    return stfb->blend_texture_view;
  483. }
  484.  
  485.  
  486. struct pipe_sampler_view *vg_prepare_blend_surface_from_mask(struct vg_context *ctx)
  487. {
  488.    struct st_framebuffer *stfb = ctx->draw_buffer;
  489.  
  490.    vg_validate_state(ctx);
  491.  
  492.    vg_context_update_surface_mask_view(ctx, stfb->width, stfb->height);
  493.    vg_prepare_blend_texture(ctx, stfb->surface_mask_view);
  494.  
  495.    return stfb->blend_texture_view;
  496. }
  497.  
  498. struct pipe_sampler_view *vg_get_surface_mask(struct vg_context *ctx)
  499. {
  500.    struct st_framebuffer *stfb = ctx->draw_buffer;
  501.  
  502.    vg_context_update_surface_mask_view(ctx, stfb->width, stfb->height);
  503.  
  504.    return stfb->surface_mask_view;
  505. }
  506.  
  507. /**
  508.  * A transformation from window coordinates to paint coordinates.
  509.  */
  510. VGboolean vg_get_paint_matrix(struct vg_context *ctx,
  511.                               const struct matrix *paint_to_user,
  512.                               const struct matrix *user_to_surface,
  513.                               struct matrix *mat)
  514. {
  515.    struct matrix tmp;
  516.  
  517.    /* get user-to-paint matrix */
  518.    memcpy(mat, paint_to_user, sizeof(*paint_to_user));
  519.    if (!matrix_invert(mat))
  520.       return VG_FALSE;
  521.  
  522.    /* get surface-to-user matrix */
  523.    memcpy(&tmp, user_to_surface, sizeof(*user_to_surface));
  524.    if (!matrix_invert(&tmp))
  525.       return VG_FALSE;
  526.  
  527.    matrix_mult(mat, &tmp);
  528.  
  529.    return VG_TRUE;
  530. }
  531.