Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**********************************************************
  2.  * Copyright 2008-2009 VMware, Inc.  All rights reserved.
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person
  5.  * obtaining a copy of this software and associated documentation
  6.  * files (the "Software"), to deal in the Software without
  7.  * restriction, including without limitation the rights to use, copy,
  8.  * modify, merge, publish, distribute, sublicense, and/or sell copies
  9.  * of the Software, and to permit persons to whom the Software is
  10.  * furnished to do so, subject to the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice shall be
  13.  * included in all copies or substantial portions of the Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18.  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  19.  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  20.  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22.  * SOFTWARE.
  23.  *
  24.  **********************************************************/
  25.  
  26. #include "util/u_inlines.h"
  27. #include "pipe/p_defines.h"
  28. #include "util/u_math.h"
  29. #include "util/u_memory.h"
  30. #include "util/u_bitmask.h"
  31. #include "tgsi/tgsi_ureg.h"
  32.  
  33. #include "svga_context.h"
  34. #include "svga_state.h"
  35. #include "svga_cmd.h"
  36. #include "svga_tgsi.h"
  37.  
  38. #include "svga_hw_reg.h"
  39.  
  40.  
  41.  
  42. static INLINE int compare_fs_keys( const struct svga_fs_compile_key *a,
  43.                                    const struct svga_fs_compile_key *b )
  44. {
  45.    unsigned keysize_a = svga_fs_key_size( a );
  46.    unsigned keysize_b = svga_fs_key_size( b );
  47.  
  48.    if (keysize_a != keysize_b) {
  49.       return (int)(keysize_a - keysize_b);
  50.    }
  51.    return memcmp( a, b, keysize_a );
  52. }
  53.  
  54.  
  55. static struct svga_shader_result *search_fs_key( struct svga_fragment_shader *fs,
  56.                                                  const struct svga_fs_compile_key *key )
  57. {
  58.    struct svga_shader_result *result = fs->base.results;
  59.  
  60.    assert(key);
  61.  
  62.    for ( ; result; result = result->next) {
  63.       if (compare_fs_keys( key, &result->key.fkey ) == 0)
  64.          return result;
  65.    }
  66.    
  67.    return NULL;
  68. }
  69.  
  70.  
  71. /**
  72.  * If we fail to compile a fragment shader (because it uses too many
  73.  * registers, for example) we'll use a dummy/fallback shader that
  74.  * simply emits a constant color.
  75.  */
  76. static const struct tgsi_token *
  77. get_dummy_fragment_shader(void)
  78. {
  79.    static const float red[4] = { 1.0, 0.0, 0.0, 0.0 };
  80.    struct ureg_program *ureg;
  81.    const struct tgsi_token *tokens;
  82.    struct ureg_src src;
  83.    struct ureg_dst dst;
  84.    unsigned num_tokens;
  85.  
  86.    ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
  87.    if (!ureg)
  88.       return NULL;
  89.  
  90.    dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
  91.    src = ureg_DECL_immediate(ureg, red, 4);
  92.    ureg_MOV(ureg, dst, src);
  93.    ureg_END(ureg);
  94.  
  95.    tokens = ureg_get_tokens(ureg, &num_tokens);
  96.  
  97.    ureg_destroy(ureg);
  98.  
  99.    return tokens;
  100. }
  101.  
  102.  
  103. static enum pipe_error compile_fs( struct svga_context *svga,
  104.                                    struct svga_fragment_shader *fs,
  105.                                    const struct svga_fs_compile_key *key,
  106.                                    struct svga_shader_result **out_result )
  107. {
  108.    struct svga_shader_result *result;
  109.    enum pipe_error ret = PIPE_ERROR;
  110.  
  111.    result = svga_translate_fragment_program( fs, key );
  112.    if (result == NULL) {
  113.       /* some problem during translation, try the dummy shader */
  114.       const struct tgsi_token *dummy = get_dummy_fragment_shader();
  115.       if (!dummy) {
  116.          ret = PIPE_ERROR_OUT_OF_MEMORY;
  117.          goto fail;
  118.       }
  119.       debug_printf("Failed to compile fragment shader, using dummy shader instead.\n");
  120.       FREE((void *) fs->base.tokens);
  121.       fs->base.tokens = dummy;
  122.       result = svga_translate_fragment_program(fs, key);
  123.       if (result == NULL) {
  124.          ret = PIPE_ERROR;
  125.          goto fail;
  126.       }
  127.    }
  128.  
  129.    result->id = util_bitmask_add(svga->fs_bm);
  130.    if(result->id == UTIL_BITMASK_INVALID_INDEX) {
  131.       ret = PIPE_ERROR_OUT_OF_MEMORY;
  132.       goto fail;
  133.    }
  134.  
  135.    ret = SVGA3D_DefineShader(svga->swc,
  136.                              result->id,
  137.                              SVGA3D_SHADERTYPE_PS,
  138.                              result->tokens,
  139.                              result->nr_tokens * sizeof result->tokens[0]);
  140.    if (ret != PIPE_OK)
  141.       goto fail;
  142.  
  143.    *out_result = result;
  144.    result->next = fs->base.results;
  145.    fs->base.results = result;
  146.    return PIPE_OK;
  147.  
  148. fail:
  149.    if (result) {
  150.       if (result->id != UTIL_BITMASK_INVALID_INDEX)
  151.          util_bitmask_clear( svga->fs_bm, result->id );
  152.       svga_destroy_shader_result( result );
  153.    }
  154.    return ret;
  155. }
  156.  
  157.  
  158. /* SVGA_NEW_TEXTURE_BINDING
  159.  * SVGA_NEW_RAST
  160.  * SVGA_NEW_NEED_SWTNL
  161.  * SVGA_NEW_SAMPLER
  162.  */
  163. static enum pipe_error
  164. make_fs_key(const struct svga_context *svga,
  165.             struct svga_fragment_shader *fs,
  166.             struct svga_fs_compile_key *key)
  167. {
  168.    unsigned i;
  169.    int idx = 0;
  170.  
  171.    memset(key, 0, sizeof *key);
  172.  
  173.    /* Only need fragment shader fixup for twoside lighting if doing
  174.     * hwtnl.  Otherwise the draw module does the whole job for us.
  175.     *
  176.     * SVGA_NEW_SWTNL
  177.     */
  178.    if (!svga->state.sw.need_swtnl) {
  179.       /* SVGA_NEW_RAST
  180.        */
  181.       key->light_twoside = svga->curr.rast->templ.light_twoside;
  182.       key->front_ccw = svga->curr.rast->templ.front_ccw;
  183.    }
  184.  
  185.    /* The blend workaround for simulating logicop xor behaviour
  186.     * requires that the incoming fragment color be white.  This change
  187.     * achieves that by creating a variant of the current fragment
  188.     * shader that overrides all output colors with 1,1,1,1
  189.     *  
  190.     * This will work for most shaders, including those containing
  191.     * TEXKIL and/or depth-write.  However, it will break on the
  192.     * combination of xor-logicop plus alphatest.
  193.     *
  194.     * Ultimately, we could implement alphatest in the shader using
  195.     * texkil prior to overriding the outgoing fragment color.
  196.     *  
  197.     * SVGA_NEW_BLEND
  198.     */
  199.    if (svga->curr.blend->need_white_fragments) {
  200.       key->white_fragments = 1;
  201.    }
  202.    
  203.    /* XXX: want to limit this to the textures that the shader actually
  204.     * refers to.
  205.     *
  206.     * SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER
  207.     */
  208.    for (i = 0; i < svga->curr.num_sampler_views; i++) {
  209.       if (svga->curr.sampler_views[i]) {
  210.          assert(svga->curr.sampler[i]);
  211.          assert(svga->curr.sampler_views[i]->texture);
  212.          key->tex[i].texture_target = svga->curr.sampler_views[i]->texture->target;
  213.          if (!svga->curr.sampler[i]->normalized_coords) {
  214.             key->tex[i].width_height_idx = idx++;
  215.             key->tex[i].unnormalized = TRUE;
  216.             ++key->num_unnormalized_coords;
  217.          }
  218.  
  219.          key->tex[i].swizzle_r = svga->curr.sampler_views[i]->swizzle_r;
  220.          key->tex[i].swizzle_g = svga->curr.sampler_views[i]->swizzle_g;
  221.          key->tex[i].swizzle_b = svga->curr.sampler_views[i]->swizzle_b;
  222.          key->tex[i].swizzle_a = svga->curr.sampler_views[i]->swizzle_a;
  223.       }
  224.    }
  225.    key->num_textures = svga->curr.num_sampler_views;
  226.  
  227.    idx = 0;
  228.    for (i = 0; i < svga->curr.num_samplers; ++i) {
  229.       if (svga->curr.sampler[i]) {
  230.          key->tex[i].compare_mode = svga->curr.sampler[i]->compare_mode;
  231.          key->tex[i].compare_func = svga->curr.sampler[i]->compare_func;
  232.       }
  233.    }
  234.  
  235.    /* sprite coord gen state */
  236.    for (i = 0; i < svga->curr.num_samplers; ++i) {
  237.       key->tex[i].sprite_texgen =
  238.          svga->curr.rast->templ.sprite_coord_enable & (1 << i);
  239.    }
  240.  
  241.    key->sprite_origin_lower_left = (svga->curr.rast->templ.sprite_coord_mode
  242.                                     == PIPE_SPRITE_COORD_LOWER_LEFT);
  243.  
  244.    return PIPE_OK;
  245. }
  246.  
  247.  
  248.  
  249. static enum pipe_error
  250. emit_hw_fs(struct svga_context *svga, unsigned dirty)
  251. {
  252.    struct svga_shader_result *result = NULL;
  253.    unsigned id = SVGA3D_INVALID_ID;
  254.    enum pipe_error ret = PIPE_OK;
  255.  
  256.    struct svga_fragment_shader *fs = svga->curr.fs;
  257.    struct svga_fs_compile_key key;
  258.  
  259.    /* SVGA_NEW_BLEND
  260.     * SVGA_NEW_TEXTURE_BINDING
  261.     * SVGA_NEW_RAST
  262.     * SVGA_NEW_NEED_SWTNL
  263.     * SVGA_NEW_SAMPLER
  264.     */
  265.    ret = make_fs_key( svga, fs, &key );
  266.    if (ret != PIPE_OK)
  267.       return ret;
  268.  
  269.    result = search_fs_key( fs, &key );
  270.    if (!result) {
  271.       ret = compile_fs( svga, fs, &key, &result );
  272.       if (ret != PIPE_OK)
  273.          return ret;
  274.    }
  275.  
  276.    assert (result);
  277.    id = result->id;
  278.  
  279.    assert(id != SVGA3D_INVALID_ID);
  280.  
  281.    if (result != svga->state.hw_draw.fs) {
  282.       ret = SVGA3D_SetShader(svga->swc,
  283.                              SVGA3D_SHADERTYPE_PS,
  284.                              id );
  285.       if (ret != PIPE_OK)
  286.          return ret;
  287.  
  288.       svga->dirty |= SVGA_NEW_FS_RESULT;
  289.       svga->state.hw_draw.fs = result;      
  290.    }
  291.  
  292.    return PIPE_OK;
  293. }
  294.  
  295. struct svga_tracked_state svga_hw_fs =
  296. {
  297.    "fragment shader (hwtnl)",
  298.    (SVGA_NEW_FS |
  299.     SVGA_NEW_TEXTURE_BINDING |
  300.     SVGA_NEW_NEED_SWTNL |
  301.     SVGA_NEW_RAST |
  302.     SVGA_NEW_SAMPLER |
  303.     SVGA_NEW_BLEND),
  304.    emit_hw_fs
  305. };
  306.  
  307.  
  308.  
  309.