svga_pipe_vs.c 6.63 KB
Newer Older
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/**********************************************************
 * Copyright 2008-2009 VMware, Inc.  All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 **********************************************************/

#include "draw/draw_context.h"
27
#include "util/u_inlines.h"
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
28 29
#include "util/u_math.h"
#include "util/u_memory.h"
30
#include "util/u_bitmask.h"
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
31 32 33 34 35 36 37
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_text.h"

#include "svga_context.h"
#include "svga_hw_reg.h"
#include "svga_cmd.h"
#include "svga_debug.h"
Brian Paul's avatar
Brian Paul committed
38
#include "svga_shader.h"
39
#include "svga_streamout.h"
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
40 41


42 43 44 45 46
/**
 * Substitute a debug shader.
 */
static const struct tgsi_token *
substitute_vs(unsigned shader_id, const struct tgsi_token *old_tokens)
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
47 48 49 50 51
{
#if 0
   if (shader_id == 12) {
   static struct tgsi_token tokens[300];

52
   const char *text =
53
      "VERT\n"
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
      "DCL IN[0]\n"
      "DCL IN[1]\n"
      "DCL IN[2]\n"
      "DCL OUT[0], POSITION\n"
      "DCL TEMP[0..4]\n"
      "IMM FLT32 {     1.0000,     1.0000,     1.0000,     1.0000 }\n"
      "IMM FLT32 {     0.45,     1.0000,     1.0000,     1.0000 }\n"
      "IMM FLT32 { 1.297863, 0.039245, 0.035993, 0.035976}\n"
      "IMM FLT32 { -0.019398, 1.696131, -0.202151, -0.202050  }\n"
      "IMM FLT32 { 0.051711, -0.348713, -0.979204, -0.978714  }\n"
      "IMM FLT32 { 0.000000, 0.000003, 139.491577, 141.421356 }\n"
      "DCL CONST[0..7]\n"
      "DCL CONST[9..16]\n"
      "  MOV TEMP[2], IMM[0]\n"

      "  MOV TEMP[2].xyz, IN[2]\n"
      "  MOV TEMP[2].xyz, IN[0]\n"
      "  MOV TEMP[2].xyz, IN[1]\n"

      "  MUL TEMP[1], IMM[3], TEMP[2].yyyy\n"
      "  MAD TEMP[3], IMM[2],  TEMP[2].xxxx, TEMP[1]\n"
      "  MAD TEMP[1], IMM[4], TEMP[2].zzzz, TEMP[3]\n"
      "  MAD TEMP[4], IMM[5], TEMP[2].wwww, TEMP[1]\n"

      "  MOV OUT[0], TEMP[4]\n"
      "  END\n";

81
   if (!tgsi_text_translate(text,
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
82
                             tokens,
Brian Paul's avatar
Brian Paul committed
83
                             ARRAY_SIZE(tokens)))
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
   {
      assert(0);
      return NULL;
   }

   return tokens;
   }
#endif

   return old_tokens;
}


static void *
svga_create_vs_state(struct pipe_context *pipe,
                     const struct pipe_shader_state *templ)
{
   struct svga_context *svga = svga_context(pipe);
   struct svga_vertex_shader *vs = CALLOC_STRUCT(svga_vertex_shader);
103

Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
   if (!vs)
      return NULL;

   /* substitute a debug shader?
    */
   vs->base.tokens = tgsi_dup_tokens(substitute_vs(svga->debug.shader_id,
                                                   templ->tokens));

   /* Collect basic info that we'll need later:
    */
   tgsi_scan_shader(vs->base.tokens, &vs->base.info);

   {
      /* Need to do construct a new template in case we substitued a
       * debug shader.
       */
      struct pipe_shader_state tmp2 = *templ;
      tmp2.tokens = vs->base.tokens;
      vs->draw_shader = draw_create_vertex_shader(svga->swtnl.draw, &tmp2);
   }

   vs->base.id = svga->debug.shader_id++;

127 128 129 130 131 132
   vs->generic_outputs = svga_get_generic_outputs_mask(&vs->base.info);

   /* check for any stream output declarations */
   if (templ->stream_output.num_outputs) {
      vs->base.stream_output = svga_create_stream_output(svga, &vs->base,
                                                         &templ->stream_output);
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
133 134 135 136 137
   }

   return vs;
}

138 139 140

static void
svga_bind_vs_state(struct pipe_context *pipe, void *shader)
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
141 142 143 144
{
   struct svga_vertex_shader *vs = (struct svga_vertex_shader *)shader;
   struct svga_context *svga = svga_context(pipe);

145 146 147 148 149 150 151 152 153 154 155
   if (vs == svga->curr.vs)
      return;

   /* If the currently bound vertex shader has a generated geometry shader,
    * then unbind the geometry shader before binding a new vertex shader.
    * We need to unbind the geometry shader here because there is no
    * pipe_shader associated with the generated geometry shader.
    */
   if (svga->curr.vs != NULL && svga->curr.vs->gs != NULL)
      svga->pipe.bind_gs_state(&svga->pipe, NULL);

Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
156 157 158 159 160
   svga->curr.vs = vs;
   svga->dirty |= SVGA_NEW_VS;
}


161 162
static void
svga_delete_vs_state(struct pipe_context *pipe, void *shader)
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
163 164 165
{
   struct svga_context *svga = svga_context(pipe);
   struct svga_vertex_shader *vs = (struct svga_vertex_shader *)shader;
166
   struct svga_shader_variant *variant, *tmp;
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
167 168
   enum pipe_error ret;

169
   svga_hwtnl_flush_retry(svga);
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
170

171 172 173 174 175 176 177 178 179 180 181 182
   assert(vs->base.parent == NULL);

   /* Check if there is a generated geometry shader to go with this
    * vertex shader. If there is, then delete the geometry shader as well.
    */
   if (vs->gs != NULL) {
      svga->pipe.delete_gs_state(&svga->pipe, vs->gs);
   }

   if (vs->base.stream_output != NULL)
      svga_delete_stream_output(svga, vs->base.stream_output);

Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
183
   draw_delete_vertex_shader(svga->swtnl.draw, vs->draw_shader);
184

185 186
   for (variant = vs->base.variants; variant; variant = tmp) {
      tmp = variant->next;
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
187

188 189 190 191 192 193 194 195
      /* Check if deleting currently bound shader */
      if (variant == svga->state.hw_draw.vs) {
         ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_VS, NULL);
         if (ret != PIPE_OK) {
            svga_context_flush(svga, NULL);
            ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_VS, NULL);
            assert(ret == PIPE_OK);
         }
196
         svga->state.hw_draw.vs = NULL;
197 198 199 200 201 202 203 204
      }

      ret = svga_destroy_shader_variant(svga, SVGA3D_SHADERTYPE_VS, variant);
      if (ret != PIPE_OK) {
         svga_context_flush(svga, NULL);
         ret = svga_destroy_shader_variant(svga, SVGA3D_SHADERTYPE_VS, variant);
         assert(ret == PIPE_OK);
      }
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
205 206 207 208 209 210 211
   }

   FREE((void *)vs->base.tokens);
   FREE(vs);
}


212 213
void
svga_init_vs_functions(struct svga_context *svga)
Jakob Bornecrantz's avatar
Jakob Bornecrantz committed
214 215 216 217 218 219
{
   svga->pipe.create_vs_state = svga_create_vs_state;
   svga->pipe.bind_vs_state = svga_bind_vs_state;
   svga->pipe.delete_vs_state = svga_delete_vs_state;
}