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 "shaders_cache.h"
  28.  
  29. #include "vg_context.h"
  30.  
  31. #include "pipe/p_context.h"
  32. #include "pipe/p_defines.h"
  33. #include "pipe/p_shader_tokens.h"
  34.  
  35. #include "tgsi/tgsi_build.h"
  36. #include "tgsi/tgsi_dump.h"
  37. #include "tgsi/tgsi_parse.h"
  38. #include "tgsi/tgsi_util.h"
  39. #include "tgsi/tgsi_text.h"
  40.  
  41. #include "util/u_memory.h"
  42. #include "util/u_math.h"
  43. #include "util/u_debug.h"
  44. #include "cso_cache/cso_hash.h"
  45. #include "cso_cache/cso_context.h"
  46.  
  47. #include "VG/openvg.h"
  48.  
  49. #include "asm_fill.h"
  50.  
  51. /* Essentially we construct an ubber-shader based on the state
  52.  * of the pipeline. The stages are:
  53.  * 1) Paint generation (color/gradient/pattern)
  54.  * 2) Image composition (normal/multiply/stencil)
  55.  * 3) Color transform
  56.  * 4) Per-channel alpha generation
  57.  * 5) Extended blend (multiply/screen/darken/lighten)
  58.  * 6) Mask
  59.  * 7) Premultiply/Unpremultiply
  60.  * 8) Color transform (to black and white)
  61.  */
  62. #define SHADER_STAGES 8
  63.  
  64. struct cached_shader {
  65.    void *driver_shader;
  66.    struct pipe_shader_state state;
  67. };
  68.  
  69. struct shaders_cache {
  70.    struct vg_context *pipe;
  71.  
  72.    struct cso_hash *hash;
  73. };
  74.  
  75.  
  76. static INLINE struct tgsi_token *tokens_from_assembly(const char *txt, int num_tokens)
  77. {
  78.    struct tgsi_token *tokens;
  79.  
  80.    tokens = (struct tgsi_token *) MALLOC(num_tokens * sizeof(tokens[0]));
  81.  
  82.    tgsi_text_translate(txt, tokens, num_tokens);
  83.  
  84. #if DEBUG_SHADERS
  85.    tgsi_dump(tokens, 0);
  86. #endif
  87.  
  88.    return tokens;
  89. }
  90.  
  91. /*
  92. static const char max_shader_preamble[] =
  93.    "FRAG\n"
  94.    "DCL IN[0], POSITION, LINEAR\n"
  95.    "DCL IN[1], GENERIC[0], PERSPECTIVE\n"
  96.    "DCL OUT[0], COLOR, CONSTANT\n"
  97.    "DCL CONST[0..9], CONSTANT\n"
  98.    "DCL TEMP[0..9], CONSTANT\n"
  99.    "DCL SAMP[0..9], CONSTANT\n";
  100.  
  101.    max_shader_preamble strlen == 175
  102. */
  103. #define MAX_PREAMBLE 175
  104.  
  105. static INLINE VGint range_min(VGint min, VGint current)
  106. {
  107.    if (min < 0)
  108.       min = current;
  109.    else
  110.       min = MIN2(min, current);
  111.    return min;
  112. }
  113.  
  114. static INLINE VGint range_max(VGint max, VGint current)
  115. {
  116.    return MAX2(max, current);
  117. }
  118.  
  119. static void *
  120. combine_shaders(const struct shader_asm_info *shaders[SHADER_STAGES], int num_shaders,
  121.                 struct pipe_context *pipe,
  122.                 struct pipe_shader_state *shader)
  123. {
  124.    VGboolean declare_input = VG_FALSE;
  125.    VGint start_const   = -1, end_const   = 0;
  126.    VGint start_temp    = -1, end_temp    = 0;
  127.    VGint start_sampler = -1, end_sampler = 0;
  128.    VGint i, current_shader = 0;
  129.    VGint num_consts, num_temps, num_samplers;
  130.    struct ureg_program *ureg;
  131.    struct ureg_src in[2];
  132.    struct ureg_src *sampler = NULL;
  133.    struct ureg_src *constant = NULL;
  134.    struct ureg_dst out, *temp = NULL;
  135.    void *p = NULL;
  136.  
  137.    for (i = 0; i < num_shaders; ++i) {
  138.       if (shaders[i]->num_consts)
  139.          start_const = range_min(start_const, shaders[i]->start_const);
  140.       if (shaders[i]->num_temps)
  141.          start_temp = range_min(start_temp, shaders[i]->start_temp);
  142.       if (shaders[i]->num_samplers)
  143.          start_sampler = range_min(start_sampler, shaders[i]->start_sampler);
  144.  
  145.       end_const = range_max(end_const, shaders[i]->start_const +
  146.                             shaders[i]->num_consts);
  147.       end_temp = range_max(end_temp, shaders[i]->start_temp +
  148.                             shaders[i]->num_temps);
  149.       end_sampler = range_max(end_sampler, shaders[i]->start_sampler +
  150.                             shaders[i]->num_samplers);
  151.       if (shaders[i]->needs_position)
  152.          declare_input = VG_TRUE;
  153.    }
  154.    /* if they're still unitialized, initialize them */
  155.    if (start_const < 0)
  156.       start_const = 0;
  157.    if (start_temp < 0)
  158.       start_temp = 0;
  159.    if (start_sampler < 0)
  160.        start_sampler = 0;
  161.  
  162.    num_consts   = end_const   - start_const;
  163.    num_temps    = end_temp    - start_temp;
  164.    num_samplers = end_sampler - start_sampler;
  165.  
  166.    ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
  167.    if (!ureg)
  168.        return NULL;
  169.  
  170.    if (declare_input) {
  171.       in[0] = ureg_DECL_fs_input(ureg,
  172.                                  TGSI_SEMANTIC_POSITION,
  173.                                  0,
  174.                                  TGSI_INTERPOLATE_LINEAR);
  175.       in[1] = ureg_DECL_fs_input(ureg,
  176.                                  TGSI_SEMANTIC_GENERIC,
  177.                                  0,
  178.                                  TGSI_INTERPOLATE_PERSPECTIVE);
  179.    }
  180.  
  181.    /* we always have a color output */
  182.    out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
  183.  
  184.    if (num_consts >= 1) {
  185.       constant = malloc(sizeof(struct ureg_src) * end_const);
  186.       for (i = start_const; i < end_const; i++) {
  187.          constant[i] = ureg_DECL_constant(ureg, i);
  188.       }
  189.  
  190.    }
  191.  
  192.    if (num_temps >= 1) {
  193.       temp = malloc(sizeof(struct ureg_dst) * end_temp);
  194.       for (i = start_temp; i < end_temp; i++) {
  195.          temp[i] = ureg_DECL_temporary(ureg);
  196.       }
  197.    }
  198.  
  199.    if (num_samplers >= 1) {
  200.       sampler = malloc(sizeof(struct ureg_src) * end_sampler);
  201.       for (i = start_sampler; i < end_sampler; i++) {
  202.          sampler[i] = ureg_DECL_sampler(ureg, i);
  203.       }
  204.    }
  205.  
  206.    while (current_shader < num_shaders) {
  207.       if ((current_shader + 1) == num_shaders) {
  208.          shaders[current_shader]->func(ureg,
  209.                                        &out,
  210.                                        in,
  211.                                        sampler,
  212.                                        temp,
  213.                                        constant);
  214.       } else {
  215.          shaders[current_shader]->func(ureg,
  216.                                       &temp[0],
  217.                                       in,
  218.                                       sampler,
  219.                                       temp,
  220.                                       constant);
  221.       }
  222.       current_shader++;
  223.    }
  224.  
  225.    ureg_END(ureg);
  226.  
  227.    shader->tokens = ureg_finalize(ureg);
  228.    if (!shader->tokens) {
  229.       ureg_destroy(ureg);
  230.       return NULL;
  231.    }
  232.  
  233.    p = pipe->create_fs_state(pipe, shader);
  234.  
  235.    if (num_temps >= 1) {
  236.       for (i = start_temp; i < end_temp; i++) {
  237.          ureg_release_temporary(ureg, temp[i]);
  238.       }
  239.    }
  240.  
  241.    ureg_destroy(ureg);
  242.  
  243.    free(temp);
  244.    free(constant);
  245.    free(sampler);
  246.  
  247.    return p;
  248. }
  249.  
  250. static void *
  251. create_shader(struct pipe_context *pipe,
  252.               int id,
  253.               struct pipe_shader_state *shader)
  254. {
  255.    int idx = 0, sh;
  256.    const struct shader_asm_info * shaders[SHADER_STAGES];
  257.  
  258.    /* first stage */
  259.    sh = SHADERS_GET_PAINT_SHADER(id);
  260.    switch (sh << SHADERS_PAINT_SHIFT) {
  261.    case VEGA_SOLID_FILL_SHADER:
  262.    case VEGA_LINEAR_GRADIENT_SHADER:
  263.    case VEGA_RADIAL_GRADIENT_SHADER:
  264.    case VEGA_PATTERN_SHADER:
  265.    case VEGA_PAINT_DEGENERATE_SHADER:
  266.       shaders[idx] = &shaders_paint_asm[(sh >> SHADERS_PAINT_SHIFT) - 1];
  267.       assert(shaders[idx]->id == sh);
  268.       idx++;
  269.       break;
  270.    default:
  271.       break;
  272.    }
  273.  
  274.    /* second stage */
  275.    sh = SHADERS_GET_IMAGE_SHADER(id);
  276.    switch (sh) {
  277.    case VEGA_IMAGE_NORMAL_SHADER:
  278.    case VEGA_IMAGE_MULTIPLY_SHADER:
  279.    case VEGA_IMAGE_STENCIL_SHADER:
  280.       shaders[idx] = &shaders_image_asm[(sh >> SHADERS_IMAGE_SHIFT) - 1];
  281.       assert(shaders[idx]->id == sh);
  282.       idx++;
  283.       break;
  284.    default:
  285.       break;
  286.    }
  287.  
  288.    /* sanity check */
  289.    assert(idx == ((!sh || sh == VEGA_IMAGE_NORMAL_SHADER) ? 1 : 2));
  290.  
  291.    /* third stage */
  292.    sh = SHADERS_GET_COLOR_TRANSFORM_SHADER(id);
  293.    switch (sh) {
  294.    case VEGA_COLOR_TRANSFORM_SHADER:
  295.       shaders[idx] = &shaders_color_transform_asm[
  296.          (sh >> SHADERS_COLOR_TRANSFORM_SHIFT) - 1];
  297.       assert(shaders[idx]->id == sh);
  298.       idx++;
  299.       break;
  300.    default:
  301.       break;
  302.    }
  303.  
  304.    /* fourth stage */
  305.    sh = SHADERS_GET_ALPHA_SHADER(id);
  306.    switch (sh) {
  307.    case VEGA_ALPHA_NORMAL_SHADER:
  308.    case VEGA_ALPHA_PER_CHANNEL_SHADER:
  309.       shaders[idx] = &shaders_alpha_asm[
  310.          (sh >> SHADERS_ALPHA_SHIFT) - 1];
  311.       assert(shaders[idx]->id == sh);
  312.       idx++;
  313.       break;
  314.    default:
  315.       break;
  316.    }
  317.  
  318.    /* fifth stage */
  319.    sh = SHADERS_GET_BLEND_SHADER(id);
  320.    switch (sh) {
  321.    case VEGA_BLEND_SRC_SHADER:
  322.    case VEGA_BLEND_SRC_OVER_SHADER:
  323.    case VEGA_BLEND_DST_OVER_SHADER:
  324.    case VEGA_BLEND_SRC_IN_SHADER:
  325.    case VEGA_BLEND_DST_IN_SHADER:
  326.    case VEGA_BLEND_MULTIPLY_SHADER:
  327.    case VEGA_BLEND_SCREEN_SHADER:
  328.    case VEGA_BLEND_DARKEN_SHADER:
  329.    case VEGA_BLEND_LIGHTEN_SHADER:
  330.    case VEGA_BLEND_ADDITIVE_SHADER:
  331.       shaders[idx] = &shaders_blend_asm[(sh >> SHADERS_BLEND_SHIFT) - 1];
  332.       assert(shaders[idx]->id == sh);
  333.       idx++;
  334.       break;
  335.    default:
  336.       break;
  337.    }
  338.  
  339.    /* sixth stage */
  340.    sh = SHADERS_GET_MASK_SHADER(id);
  341.    switch (sh) {
  342.    case VEGA_MASK_SHADER:
  343.       shaders[idx] = &shaders_mask_asm[(sh >> SHADERS_MASK_SHIFT) - 1];
  344.       assert(shaders[idx]->id == sh);
  345.       idx++;
  346.       break;
  347.    default:
  348.       break;
  349.    }
  350.  
  351.    /* seventh stage */
  352.    sh = SHADERS_GET_PREMULTIPLY_SHADER(id);
  353.    switch (sh) {
  354.    case VEGA_PREMULTIPLY_SHADER:
  355.    case VEGA_UNPREMULTIPLY_SHADER:
  356.       shaders[idx] = &shaders_premultiply_asm[
  357.          (sh >> SHADERS_PREMULTIPLY_SHIFT) - 1];
  358.       assert(shaders[idx]->id == sh);
  359.       idx++;
  360.       break;
  361.    default:
  362.       break;
  363.    }
  364.  
  365.    /* eighth stage */
  366.    sh = SHADERS_GET_BW_SHADER(id);
  367.    switch (sh) {
  368.    case VEGA_BW_SHADER:
  369.       shaders[idx] = &shaders_bw_asm[(sh >> SHADERS_BW_SHIFT) - 1];
  370.       assert(shaders[idx]->id == sh);
  371.       idx++;
  372.       break;
  373.    default:
  374.       break;
  375.    }
  376.  
  377.    return combine_shaders(shaders, idx, pipe, shader);
  378. }
  379.  
  380. /*************************************************/
  381.  
  382. struct shaders_cache * shaders_cache_create(struct vg_context *vg)
  383. {
  384.    struct shaders_cache *sc = CALLOC_STRUCT(shaders_cache);
  385.  
  386.    sc->pipe = vg;
  387.    sc->hash = cso_hash_create();
  388.  
  389.    return sc;
  390. }
  391.  
  392. void shaders_cache_destroy(struct shaders_cache *sc)
  393. {
  394.    struct cso_hash_iter iter = cso_hash_first_node(sc->hash);
  395.  
  396.    while (!cso_hash_iter_is_null(iter)) {
  397.       struct cached_shader *cached =
  398.          (struct cached_shader *)cso_hash_iter_data(iter);
  399.       cso_delete_fragment_shader(sc->pipe->cso_context,
  400.                                  cached->driver_shader);
  401.       iter = cso_hash_erase(sc->hash, iter);
  402.    }
  403.  
  404.    cso_hash_delete(sc->hash);
  405.    FREE(sc);
  406. }
  407.  
  408. void * shaders_cache_fill(struct shaders_cache *sc,
  409.                           int shader_key)
  410. {
  411.    VGint key = shader_key;
  412.    struct cached_shader *cached;
  413.    struct cso_hash_iter iter = cso_hash_find(sc->hash, key);
  414.  
  415.    if (cso_hash_iter_is_null(iter)) {
  416.       cached = CALLOC_STRUCT(cached_shader);
  417.       cached->driver_shader = create_shader(sc->pipe->pipe, key, &cached->state);
  418.  
  419.       cso_hash_insert(sc->hash, key, cached);
  420.  
  421.       return cached->driver_shader;
  422.    }
  423.  
  424.    cached = (struct cached_shader *)cso_hash_iter_data(iter);
  425.  
  426.    assert(cached->driver_shader);
  427.    return cached->driver_shader;
  428. }
  429.  
  430. struct vg_shader * shader_create_from_text(struct pipe_context *pipe,
  431.                                            const char *txt, int num_tokens,
  432.                                            int type)
  433. {
  434.    struct vg_shader *shader = (struct vg_shader *)MALLOC(
  435.       sizeof(struct vg_shader));
  436.    struct tgsi_token *tokens = tokens_from_assembly(txt, num_tokens);
  437.    struct pipe_shader_state state;
  438.  
  439.    debug_assert(type == PIPE_SHADER_VERTEX ||
  440.                 type == PIPE_SHADER_FRAGMENT);
  441.  
  442.    state.tokens = tokens;
  443.    memset(&state.stream_output, 0, sizeof(state.stream_output));
  444.    shader->type = type;
  445.    shader->tokens = tokens;
  446.  
  447.    if (type == PIPE_SHADER_FRAGMENT)
  448.       shader->driver = pipe->create_fs_state(pipe, &state);
  449.    else
  450.       shader->driver = pipe->create_vs_state(pipe, &state);
  451.    return shader;
  452. }
  453.  
  454. void vg_shader_destroy(struct vg_context *ctx, struct vg_shader *shader)
  455. {
  456.    if (shader->type == PIPE_SHADER_FRAGMENT)
  457.       cso_delete_fragment_shader(ctx->cso_context, shader->driver);
  458.    else
  459.       cso_delete_vertex_shader(ctx->cso_context, shader->driver);
  460.    FREE(shader->tokens);
  461.    FREE(shader);
  462. }
  463.