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.  
  29. #include "svga_screen.h"
  30. #include "svga_context.h"
  31. #include "svga_state.h"
  32. #include "svga_cmd.h"
  33. #include "svga_tgsi.h"
  34. #include "svga_debug.h"
  35.  
  36. #include "svga_hw_reg.h"
  37.  
  38.  
  39. /*
  40.  * Don't try to send more than 4kb of successive constants.
  41.  */
  42. #define MAX_CONST_REG_COUNT 256  /**< number of float[4] constants */
  43.  
  44.  
  45.  
  46. /**
  47.  * Convert from PIPE_SHADER_* to SVGA3D_SHADERTYPE_*
  48.  */
  49. static unsigned
  50. svga_shader_type(unsigned shader)
  51. {
  52.    switch (shader) {
  53.    case PIPE_SHADER_VERTEX:
  54.       return SVGA3D_SHADERTYPE_VS;
  55.    case PIPE_SHADER_FRAGMENT:
  56.       return SVGA3D_SHADERTYPE_PS;
  57.    default:
  58.       assert(!"Unexpected shader type");
  59.       return SVGA3D_SHADERTYPE_VS;
  60.    }
  61. }
  62.  
  63.  
  64. /**
  65.  * Check and emit one shader constant register.
  66.  * \param shader  PIPE_SHADER_FRAGMENT or PIPE_SHADER_VERTEX
  67.  * \param i  which float[4] constant to change
  68.  * \param value  the new float[4] value
  69.  */
  70. static enum pipe_error
  71. emit_const(struct svga_context *svga, unsigned shader, unsigned i,
  72.            const float *value)
  73. {
  74.    enum pipe_error ret = PIPE_OK;
  75.  
  76.    assert(shader < PIPE_SHADER_TYPES);
  77.    assert(i < SVGA3D_CONSTREG_MAX);
  78.  
  79.    if (memcmp(svga->state.hw_draw.cb[shader][i], value,
  80.               4 * sizeof(float)) != 0) {
  81.       if (SVGA_DEBUG & DEBUG_CONSTS)
  82.          debug_printf("%s %s %u: %f %f %f %f\n",
  83.                       __FUNCTION__,
  84.                       shader == PIPE_SHADER_VERTEX ? "VERT" : "FRAG",
  85.                       i,
  86.                       value[0],
  87.                       value[1],
  88.                       value[2],
  89.                       value[3]);
  90.  
  91.       ret = SVGA3D_SetShaderConst( svga->swc,
  92.                                    i,
  93.                                    svga_shader_type(shader),
  94.                                    SVGA3D_CONST_TYPE_FLOAT,
  95.                                    value );
  96.       if (ret != PIPE_OK)
  97.          return ret;
  98.  
  99.       memcpy(svga->state.hw_draw.cb[shader][i], value, 4 * sizeof(float));
  100.    }
  101.  
  102.    return ret;
  103. }
  104.  
  105.  
  106. /*
  107.  * Check and emit a range of shader constant registers, trying to coalesce
  108.  * successive shader constant updates in a single command in order to save
  109.  * space on the command buffer.  This is a HWv8 feature.
  110.  */
  111. static enum pipe_error
  112. emit_const_range(struct svga_context *svga,
  113.                  unsigned shader,
  114.                  unsigned offset,
  115.                  unsigned count,
  116.                  const float (*values)[4])
  117. {
  118.    unsigned i, j;
  119.    enum pipe_error ret;
  120.  
  121. #ifdef DEBUG
  122.    if (offset + count > SVGA3D_CONSTREG_MAX) {
  123.       debug_printf("svga: too many constants (offset + count = %u)\n",
  124.                    offset + count);
  125.    }
  126. #endif
  127.  
  128.    if (offset > SVGA3D_CONSTREG_MAX) {
  129.       /* This isn't OK, but if we propagate an error all the way up we'll
  130.        * just get into more trouble.
  131.        * XXX note that offset is always zero at this time so this is moot.
  132.        */
  133.       return PIPE_OK;
  134.    }
  135.  
  136.    if (offset + count > SVGA3D_CONSTREG_MAX) {
  137.       /* Just drop the extra constants for now.
  138.        * Ideally we should not have allowed the app to create a shader
  139.        * that exceeds our constant buffer size but there's no way to
  140.        * express that in gallium at this time.
  141.        */
  142.       count = SVGA3D_CONSTREG_MAX - offset;
  143.    }
  144.  
  145.    i = 0;
  146.    while (i < count) {
  147.       if (memcmp(svga->state.hw_draw.cb[shader][offset + i],
  148.                  values[i],
  149.                  4 * sizeof(float)) != 0) {
  150.          /* Found one dirty constant
  151.           */
  152.          if (SVGA_DEBUG & DEBUG_CONSTS)
  153.             debug_printf("%s %s %d: %f %f %f %f\n",
  154.                          __FUNCTION__,
  155.                          shader == PIPE_SHADER_VERTEX ? "VERT" : "FRAG",
  156.                          offset + i,
  157.                          values[i][0],
  158.                          values[i][1],
  159.                          values[i][2],
  160.                          values[i][3]);
  161.  
  162.          /* Look for more consecutive dirty constants.
  163.           */
  164.          j = i + 1;
  165.          while (j < count &&
  166.                 j < i + MAX_CONST_REG_COUNT &&
  167.                 memcmp(svga->state.hw_draw.cb[shader][offset + j],
  168.                        values[j],
  169.                        4 * sizeof(float)) != 0) {
  170.  
  171.             if (SVGA_DEBUG & DEBUG_CONSTS)
  172.                debug_printf("%s %s %d: %f %f %f %f\n",
  173.                             __FUNCTION__,
  174.                             shader == PIPE_SHADER_VERTEX ? "VERT" : "FRAG",
  175.                             offset + j,
  176.                             values[j][0],
  177.                             values[j][1],
  178.                             values[j][2],
  179.                             values[j][3]);
  180.  
  181.             ++j;
  182.          }
  183.  
  184.          assert(j >= i + 1);
  185.  
  186.          /* Send them all together.
  187.           */
  188.          ret = SVGA3D_SetShaderConsts(svga->swc,
  189.                                       offset + i, j - i,
  190.                                       svga_shader_type(shader),
  191.                                       SVGA3D_CONST_TYPE_FLOAT,
  192.                                       values + i);
  193.          if (ret != PIPE_OK) {
  194.             return ret;
  195.          }
  196.  
  197.          /*
  198.           * Local copy of the hardware state.
  199.           */
  200.          memcpy(svga->state.hw_draw.cb[shader][offset + i],
  201.                 values[i],
  202.                 (j - i) * 4 * sizeof(float));
  203.  
  204.          i = j + 1;
  205.       } else {
  206.          ++i;
  207.       }
  208.    }
  209.  
  210.    return PIPE_OK;
  211. }
  212.  
  213.  
  214. /**
  215.  * Emit all the constants in a constant buffer for a shader stage.
  216.  */
  217. static enum pipe_error
  218. emit_consts(struct svga_context *svga, unsigned shader)
  219. {
  220.    struct svga_screen *ss = svga_screen(svga->pipe.screen);
  221.    struct pipe_transfer *transfer = NULL;
  222.    unsigned count;
  223.    const float (*data)[4] = NULL;
  224.    unsigned i;
  225.    enum pipe_error ret = PIPE_OK;
  226.    const unsigned offset = 0;
  227.  
  228.    assert(shader < PIPE_SHADER_TYPES);
  229.  
  230.    if (svga->curr.cb[shader] == NULL)
  231.       goto done;
  232.  
  233.    count = svga->curr.cb[shader]->width0 / (4 * sizeof(float));
  234.  
  235.    data = (const float (*)[4])pipe_buffer_map(&svga->pipe,
  236.                                               svga->curr.cb[shader],
  237.                                               PIPE_TRANSFER_READ,
  238.                                               &transfer);
  239.    if (data == NULL) {
  240.       ret = PIPE_ERROR_OUT_OF_MEMORY;
  241.       goto done;
  242.    }
  243.  
  244.    if (ss->hw_version >= SVGA3D_HWVERSION_WS8_B1) {
  245.       ret = emit_const_range( svga, shader, offset, count, data );
  246.       if (ret != PIPE_OK) {
  247.          goto done;
  248.       }
  249.    } else {
  250.       for (i = 0; i < count; i++) {
  251.          ret = emit_const( svga, shader, offset + i, data[i] );
  252.          if (ret != PIPE_OK) {
  253.             goto done;
  254.          }
  255.       }
  256.    }
  257.  
  258. done:
  259.    if (data)
  260.       pipe_buffer_unmap(&svga->pipe, transfer);
  261.  
  262.    return ret;
  263. }
  264.  
  265.  
  266. static enum pipe_error
  267. emit_fs_consts(struct svga_context *svga, unsigned dirty)
  268. {
  269.    const struct svga_shader_result *result = svga->state.hw_draw.fs;
  270.    enum pipe_error ret = PIPE_OK;
  271.  
  272.    ret = emit_consts( svga, PIPE_SHADER_FRAGMENT );
  273.    if (ret != PIPE_OK)
  274.       return ret;
  275.  
  276.    /* The internally generated fragment shader for xor blending
  277.     * doesn't have a 'result' struct.  It should be fixed to avoid
  278.     * this special case, but work around it with a NULL check:
  279.     */
  280.    if (result) {
  281.       const struct svga_fs_compile_key *key = &result->key.fkey;
  282.       if (key->num_unnormalized_coords) {
  283.          const unsigned offset =
  284.             result->shader->info.file_max[TGSI_FILE_CONSTANT] + 1;
  285.          unsigned i;
  286.  
  287.          for (i = 0; i < key->num_textures; i++) {
  288.             if (key->tex[i].unnormalized) {
  289.                struct pipe_resource *tex = svga->curr.sampler_views[i]->texture;
  290.                float data[4];
  291.  
  292.                data[0] = 1.0f / (float) tex->width0;
  293.                data[1] = 1.0f / (float) tex->height0;
  294.                data[2] = 1.0f;
  295.                data[3] = 1.0f;
  296.  
  297.                ret = emit_const(svga,
  298.                                 PIPE_SHADER_FRAGMENT,
  299.                                 key->tex[i].width_height_idx + offset,
  300.                                 data);
  301.                if (ret != PIPE_OK) {
  302.                   return ret;
  303.                }
  304.             }
  305.          }
  306.       }
  307.    }
  308.  
  309.    return PIPE_OK;
  310. }
  311.  
  312.  
  313. struct svga_tracked_state svga_hw_fs_constants =
  314. {
  315.    "hw fs params",
  316.    (SVGA_NEW_FS_CONST_BUFFER |
  317.     SVGA_NEW_FS_RESULT |
  318.     SVGA_NEW_TEXTURE_BINDING),
  319.    emit_fs_consts
  320. };
  321.  
  322.  
  323.  
  324. static enum pipe_error
  325. emit_vs_consts(struct svga_context *svga, unsigned dirty)
  326. {
  327.    const struct svga_shader_result *result = svga->state.hw_draw.vs;
  328.    const struct svga_vs_compile_key *key;
  329.    enum pipe_error ret = PIPE_OK;
  330.    unsigned offset;
  331.  
  332.    /* SVGA_NEW_VS_RESULT
  333.     */
  334.    if (result == NULL)
  335.       return PIPE_OK;
  336.  
  337.    key = &result->key.vkey;
  338.  
  339.    /* SVGA_NEW_VS_CONST_BUFFER
  340.     */
  341.    ret = emit_consts( svga, PIPE_SHADER_VERTEX );
  342.    if (ret != PIPE_OK)
  343.       return ret;
  344.  
  345.    /* offset = number of constants in the VS const buffer */
  346.    offset = result->shader->info.file_max[TGSI_FILE_CONSTANT] + 1;
  347.  
  348.    /* SVGA_NEW_VS_PRESCALE
  349.     * Put the viewport pre-scale/translate values into the const buffer.
  350.     */
  351.    if (key->need_prescale) {
  352.       ret = emit_const( svga, PIPE_SHADER_VERTEX, offset++,
  353.                         svga->state.hw_clear.prescale.scale );
  354.       if (ret != PIPE_OK)
  355.          return ret;
  356.  
  357.       ret = emit_const( svga, PIPE_SHADER_VERTEX, offset++,
  358.                         svga->state.hw_clear.prescale.translate );
  359.       if (ret != PIPE_OK)
  360.          return ret;
  361.    }
  362.  
  363.    return PIPE_OK;
  364. }
  365.  
  366.  
  367. struct svga_tracked_state svga_hw_vs_constants =
  368. {
  369.    "hw vs params",
  370.    (SVGA_NEW_PRESCALE |
  371.     SVGA_NEW_VS_CONST_BUFFER |
  372.     SVGA_NEW_VS_RESULT),
  373.    emit_vs_consts
  374. };
  375.