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 "shader.h"
  28.  
  29. #include "vg_context.h"
  30. #include "shaders_cache.h"
  31. #include "paint.h"
  32. #include "mask.h"
  33. #include "image.h"
  34. #include "renderer.h"
  35.  
  36. #include "pipe/p_context.h"
  37. #include "pipe/p_state.h"
  38. #include "util/u_memory.h"
  39. #include "util/u_math.h"
  40. #include "util/u_format.h"
  41.  
  42. #define MAX_CONSTANTS 28
  43.  
  44. struct shader {
  45.    struct vg_context *context;
  46.  
  47.    VGboolean color_transform;
  48.    VGboolean masking;
  49.    struct vg_paint *paint;
  50.    struct vg_image *image;
  51.  
  52.    struct matrix modelview;
  53.    struct matrix paint_matrix;
  54.  
  55.    VGboolean drawing_image;
  56.    VGImageMode image_mode;
  57.  
  58.    float constants[MAX_CONSTANTS];
  59.    struct pipe_resource *cbuf;
  60.    struct pipe_shader_state fs_state;
  61.    void *fs;
  62. };
  63.  
  64. struct shader * shader_create(struct vg_context *ctx)
  65. {
  66.    struct shader *shader = 0;
  67.  
  68.    shader = CALLOC_STRUCT(shader);
  69.    shader->context = ctx;
  70.  
  71.    return shader;
  72. }
  73.  
  74. void shader_destroy(struct shader *shader)
  75. {
  76.    FREE(shader);
  77. }
  78.  
  79. void shader_set_color_transform(struct shader *shader, VGboolean set)
  80. {
  81.    shader->color_transform = set;
  82. }
  83.  
  84. void shader_set_masking(struct shader *shader, VGboolean set)
  85. {
  86.    shader->masking = set;
  87. }
  88.  
  89. VGboolean shader_is_masking(struct shader *shader)
  90. {
  91.    return shader->masking;
  92. }
  93.  
  94. void shader_set_paint(struct shader *shader, struct vg_paint *paint)
  95. {
  96.    shader->paint = paint;
  97. }
  98.  
  99. struct vg_paint * shader_paint(struct shader *shader)
  100. {
  101.    return shader->paint;
  102. }
  103.  
  104. static VGint setup_constant_buffer(struct shader *shader)
  105. {
  106.    const struct vg_state *state = &shader->context->state.vg;
  107.    VGint param_bytes = paint_constant_buffer_size(shader->paint);
  108.    VGint i;
  109.  
  110.    param_bytes += sizeof(VGfloat) * 8;
  111.    assert(param_bytes <= sizeof(shader->constants));
  112.  
  113.    if (state->color_transform) {
  114.       for (i = 0; i < 8; i++) {
  115.          VGfloat val = (i < 4) ? 127.0f : 1.0f;
  116.          shader->constants[i] =
  117.             CLAMP(state->color_transform_values[i], -val, val);
  118.       }
  119.    }
  120.    else {
  121.       memset(shader->constants, 0, sizeof(VGfloat) * 8);
  122.    }
  123.  
  124.    paint_fill_constant_buffer(shader->paint,
  125.          &shader->paint_matrix, shader->constants + 8);
  126.  
  127.    return param_bytes;
  128. }
  129.  
  130. static VGboolean blend_use_shader(struct shader *shader)
  131. {
  132.    struct vg_context *ctx = shader->context;
  133.    VGboolean advanced_blending;
  134.  
  135.    switch (ctx->state.vg.blend_mode) {
  136.    case VG_BLEND_DST_OVER:
  137.    case VG_BLEND_MULTIPLY:
  138.    case VG_BLEND_SCREEN:
  139.    case VG_BLEND_DARKEN:
  140.    case VG_BLEND_LIGHTEN:
  141.    case VG_BLEND_ADDITIVE:
  142.       advanced_blending = VG_TRUE;
  143.       break;
  144.    case VG_BLEND_SRC_OVER:
  145.       if (util_format_has_alpha(ctx->draw_buffer->strb->format)) {
  146.          /* no blending is required if the paints and the image are opaque */
  147.          advanced_blending = !paint_is_opaque(ctx->state.vg.fill_paint) ||
  148.                              !paint_is_opaque(ctx->state.vg.stroke_paint);
  149.          if (!advanced_blending && shader->drawing_image) {
  150.             advanced_blending =
  151.                util_format_has_alpha(shader->image->sampler_view->format);
  152.          }
  153.          break;
  154.       }
  155.       /* fall through */
  156.    default:
  157.       advanced_blending = VG_FALSE;
  158.       break;
  159.    }
  160.  
  161.    return advanced_blending;
  162. }
  163.  
  164. static VGint blend_bind_samplers(struct shader *shader,
  165.                                  struct pipe_sampler_state **samplers,
  166.                                  struct pipe_sampler_view **sampler_views)
  167. {
  168.    if (blend_use_shader(shader)) {
  169.       struct vg_context *ctx = shader->context;
  170.  
  171.       samplers[2] = &ctx->blend_sampler;
  172.       sampler_views[2] = vg_prepare_blend_surface(ctx);
  173.  
  174.       if (!samplers[0] || !sampler_views[0]) {
  175.          samplers[0] = samplers[2];
  176.          sampler_views[0] = sampler_views[2];
  177.       }
  178.       if (!samplers[1] || !sampler_views[1]) {
  179.          samplers[1] = samplers[0];
  180.          sampler_views[1] = sampler_views[0];
  181.       }
  182.  
  183.       return 1;
  184.    }
  185.    return 0;
  186. }
  187.  
  188. static VGint setup_samplers(struct shader *shader,
  189.                             struct pipe_sampler_state **samplers,
  190.                             struct pipe_sampler_view **sampler_views)
  191. {
  192.    /* a little wonky: we use the num as a boolean that just says
  193.     * whether any sampler/textures have been set. the actual numbering
  194.     * for samplers is always the same:
  195.     * 0 - paint sampler/texture for gradient/pattern
  196.     * 1 - mask sampler/texture
  197.     * 2 - blend sampler/texture
  198.     * 3 - image sampler/texture
  199.     * */
  200.    VGint num = 0;
  201.  
  202.    samplers[0] = NULL;
  203.    samplers[1] = NULL;
  204.    samplers[2] = NULL;
  205.    samplers[3] = NULL;
  206.    sampler_views[0] = NULL;
  207.    sampler_views[1] = NULL;
  208.    sampler_views[2] = NULL;
  209.    sampler_views[3] = NULL;
  210.  
  211.    num += paint_bind_samplers(shader->paint, samplers, sampler_views);
  212.    num += mask_bind_samplers(samplers, sampler_views);
  213.    num += blend_bind_samplers(shader, samplers, sampler_views);
  214.    if (shader->drawing_image && shader->image)
  215.       num += image_bind_samplers(shader->image, samplers, sampler_views);
  216.  
  217.    return (num) ? 4 : 0;
  218. }
  219.  
  220. static INLINE VGboolean is_format_bw(struct shader *shader)
  221. {
  222. #if 0
  223.    struct vg_context *ctx = shader->context;
  224.    struct st_framebuffer *stfb = ctx->draw_buffer;
  225. #endif
  226.  
  227.    if (shader->drawing_image && shader->image) {
  228.       if (shader->image->format == VG_BW_1)
  229.          return VG_TRUE;
  230.    }
  231.  
  232.    return VG_FALSE;
  233. }
  234.  
  235. static void setup_shader_program(struct shader *shader)
  236. {
  237.    struct vg_context *ctx = shader->context;
  238.    VGint shader_id = 0;
  239.    VGBlendMode blend_mode = ctx->state.vg.blend_mode;
  240.    VGboolean black_white = is_format_bw(shader);
  241.  
  242.    /* 1st stage: fill */
  243.    if (!shader->drawing_image ||
  244.        (shader->image_mode == VG_DRAW_IMAGE_MULTIPLY || shader->image_mode == VG_DRAW_IMAGE_STENCIL)) {
  245.       switch(paint_type(shader->paint)) {
  246.       case VG_PAINT_TYPE_COLOR:
  247.          shader_id |= VEGA_SOLID_FILL_SHADER;
  248.          break;
  249.       case VG_PAINT_TYPE_LINEAR_GRADIENT:
  250.          shader_id |= VEGA_LINEAR_GRADIENT_SHADER;
  251.          break;
  252.       case VG_PAINT_TYPE_RADIAL_GRADIENT:
  253.          shader_id |= VEGA_RADIAL_GRADIENT_SHADER;
  254.          break;
  255.       case VG_PAINT_TYPE_PATTERN:
  256.          shader_id |= VEGA_PATTERN_SHADER;
  257.          break;
  258.  
  259.       default:
  260.          abort();
  261.       }
  262.  
  263.       if (paint_is_degenerate(shader->paint))
  264.          shader_id = VEGA_PAINT_DEGENERATE_SHADER;
  265.    }
  266.  
  267.    /* second stage image */
  268.    if (shader->drawing_image) {
  269.       switch(shader->image_mode) {
  270.       case VG_DRAW_IMAGE_NORMAL:
  271.          shader_id |= VEGA_IMAGE_NORMAL_SHADER;
  272.          break;
  273.       case VG_DRAW_IMAGE_MULTIPLY:
  274.          shader_id |= VEGA_IMAGE_MULTIPLY_SHADER;
  275.          break;
  276.       case VG_DRAW_IMAGE_STENCIL:
  277.          shader_id |= VEGA_IMAGE_STENCIL_SHADER;
  278.          break;
  279.       default:
  280.          debug_printf("Unknown image mode!");
  281.       }
  282.    }
  283.  
  284.    if (shader->color_transform)
  285.       shader_id |= VEGA_COLOR_TRANSFORM_SHADER;
  286.  
  287.    if (blend_use_shader(shader)) {
  288.       if (shader->drawing_image && shader->image_mode == VG_DRAW_IMAGE_STENCIL)
  289.          shader_id |= VEGA_ALPHA_PER_CHANNEL_SHADER;
  290.       else
  291.          shader_id |= VEGA_ALPHA_NORMAL_SHADER;
  292.  
  293.       switch(blend_mode) {
  294.       case VG_BLEND_SRC:
  295.          shader_id |= VEGA_BLEND_SRC_SHADER;
  296.          break;
  297.       case VG_BLEND_SRC_OVER:
  298.          shader_id |= VEGA_BLEND_SRC_OVER_SHADER;
  299.          break;
  300.       case VG_BLEND_DST_OVER:
  301.          shader_id |= VEGA_BLEND_DST_OVER_SHADER;
  302.          break;
  303.       case VG_BLEND_SRC_IN:
  304.          shader_id |= VEGA_BLEND_SRC_IN_SHADER;
  305.          break;
  306.       case VG_BLEND_DST_IN:
  307.          shader_id |= VEGA_BLEND_DST_IN_SHADER;
  308.          break;
  309.       case VG_BLEND_MULTIPLY:
  310.          shader_id |= VEGA_BLEND_MULTIPLY_SHADER;
  311.          break;
  312.       case VG_BLEND_SCREEN:
  313.          shader_id |= VEGA_BLEND_SCREEN_SHADER;
  314.          break;
  315.       case VG_BLEND_DARKEN:
  316.          shader_id |= VEGA_BLEND_DARKEN_SHADER;
  317.          break;
  318.       case VG_BLEND_LIGHTEN:
  319.          shader_id |= VEGA_BLEND_LIGHTEN_SHADER;
  320.          break;
  321.       case VG_BLEND_ADDITIVE:
  322.          shader_id |= VEGA_BLEND_ADDITIVE_SHADER;
  323.          break;
  324.       default:
  325.          assert(0);
  326.          break;
  327.       }
  328.    }
  329.    else {
  330.       /* update alpha of the source */
  331.       if (shader->drawing_image && shader->image_mode == VG_DRAW_IMAGE_STENCIL)
  332.          shader_id |= VEGA_ALPHA_PER_CHANNEL_SHADER;
  333.    }
  334.  
  335.    if (shader->masking)
  336.       shader_id |= VEGA_MASK_SHADER;
  337.  
  338.    if (black_white)
  339.       shader_id |= VEGA_BW_SHADER;
  340.  
  341.    shader->fs = shaders_cache_fill(ctx->sc, shader_id);
  342. }
  343.  
  344.  
  345. void shader_bind(struct shader *shader)
  346. {
  347.    struct vg_context *ctx = shader->context;
  348.    struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
  349.    struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
  350.    VGint num_samplers, param_bytes;
  351.  
  352.    /* first resolve the real paint type */
  353.    paint_resolve_type(shader->paint);
  354.  
  355.    num_samplers = setup_samplers(shader, samplers, sampler_views);
  356.    param_bytes = setup_constant_buffer(shader);
  357.    setup_shader_program(shader);
  358.  
  359.    renderer_validate_for_shader(ctx->renderer,
  360.          (const struct pipe_sampler_state **) samplers,
  361.          sampler_views, num_samplers,
  362.          &shader->modelview,
  363.          shader->fs, (const void *) shader->constants, param_bytes);
  364. }
  365.  
  366. void shader_set_image_mode(struct shader *shader, VGImageMode image_mode)
  367. {
  368.    shader->image_mode = image_mode;
  369. }
  370.  
  371. VGImageMode shader_image_mode(struct shader *shader)
  372. {
  373.    return shader->image_mode;
  374. }
  375.  
  376. void shader_set_drawing_image(struct shader *shader, VGboolean drawing_image)
  377. {
  378.    shader->drawing_image = drawing_image;
  379. }
  380.  
  381. VGboolean shader_drawing_image(struct shader *shader)
  382. {
  383.    return shader->drawing_image;
  384. }
  385.  
  386. void shader_set_image(struct shader *shader, struct vg_image *img)
  387. {
  388.    shader->image = img;
  389. }
  390.  
  391. /**
  392.  * Set the transformation to map a vertex to the surface coordinates.
  393.  */
  394. void shader_set_surface_matrix(struct shader *shader,
  395.                                const struct matrix *mat)
  396. {
  397.    shader->modelview = *mat;
  398. }
  399.  
  400. /**
  401.  * Set the transformation to map a pixel to the paint coordinates.
  402.  */
  403. void shader_set_paint_matrix(struct shader *shader, const struct matrix *mat)
  404. {
  405.    const struct st_framebuffer *stfb = shader->context->draw_buffer;
  406.    const VGfloat px_center_offset = 0.5f;
  407.  
  408.    memcpy(&shader->paint_matrix, mat, sizeof(*mat));
  409.  
  410.    /* make it window-to-paint for the shaders */
  411.    matrix_translate(&shader->paint_matrix, px_center_offset,
  412.          stfb->height - 1.0f + px_center_offset);
  413.    matrix_scale(&shader->paint_matrix, 1.0f, -1.0f);
  414. }
  415.