1/**************************************************************************
2 *
3 * Copyright 2003 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28#include "draw/draw_context.h"
29#include "draw/draw_vertex.h"
30#include "pipe/p_shader_tokens.h"
31#include "util/log.h"
32#include "util/u_memory.h"
33#include "i915_context.h"
34#include "i915_debug.h"
35#include "i915_fpc.h"
36#include "i915_reg.h"
37#include "i915_state.h"
38
39
40/***********************************************************************
41 * Determine the hardware vertex layout.
42 * Depends on vertex/fragment shader state.
43 */
44static void
45calculate_vertex_layout(struct i915_context *i915)
46{
47   const struct i915_fragment_shader *fs = i915->fs;
48   struct vertex_info vinfo;
49   bool colors[2], fog, needW, face;
50   uint32_t i;
51   int src;
52
53   colors[0] = colors[1] = fog = needW = face = false;
54   memset(&vinfo, 0, sizeof(vinfo));
55
56   /* Determine which fragment program inputs are needed.  Setup HW vertex
57    * layout below, in the HW-specific attribute order.
58    */
59   for (i = 0; i < fs->info.num_inputs; i++) {
60      switch (fs->info.input_semantic_name[i]) {
61      case TGSI_SEMANTIC_POSITION:
62      case TGSI_SEMANTIC_PCOORD:
63      case TGSI_SEMANTIC_FACE:
64         /* Handled as texcoord inputs below */
65         break;
66      case TGSI_SEMANTIC_COLOR:
67         assert(fs->info.input_semantic_index[i] < 2);
68         colors[fs->info.input_semantic_index[i]] = true;
69         break;
70      case TGSI_SEMANTIC_TEXCOORD:
71      case TGSI_SEMANTIC_GENERIC:
72         needW = true;
73         break;
74      case TGSI_SEMANTIC_FOG:
75         fog = true;
76         break;
77      default:
78         debug_printf("Unknown input type %d\n",
79                      fs->info.input_semantic_name[i]);
80         assert(0);
81      }
82   }
83
84   /* pos */
85   src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_POSITION, 0);
86   if (needW) {
87      draw_emit_vertex_attr(&vinfo, EMIT_4F, src);
88      vinfo.hwfmt[0] |= S4_VFMT_XYZW;
89      vinfo.attrib[0].emit = EMIT_4F;
90   } else {
91      draw_emit_vertex_attr(&vinfo, EMIT_3F, src);
92      vinfo.hwfmt[0] |= S4_VFMT_XYZ;
93      vinfo.attrib[0].emit = EMIT_3F;
94   }
95
96   /* point size.  if not emitted here, then point size comes from LIS4. */
97   if (i915->rasterizer->templ.point_size_per_vertex) {
98      src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_PSIZE, 0);
99      if (src != -1) {
100         draw_emit_vertex_attr(&vinfo, EMIT_1F, src);
101         vinfo.hwfmt[0] |= S4_VFMT_POINT_WIDTH;
102      }
103   }
104
105   /* primary color */
106   if (colors[0]) {
107      src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_COLOR, 0);
108      draw_emit_vertex_attr(&vinfo, EMIT_4UB_BGRA, src);
109      vinfo.hwfmt[0] |= S4_VFMT_COLOR;
110   }
111
112   /* secondary color */
113   if (colors[1]) {
114      src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_COLOR, 1);
115      draw_emit_vertex_attr(&vinfo, EMIT_4UB_BGRA, src);
116      vinfo.hwfmt[0] |= S4_VFMT_SPEC_FOG;
117   }
118
119   /* fog coord, not fog blend factor */
120   if (fog) {
121      src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_FOG, 0);
122      draw_emit_vertex_attr(&vinfo, EMIT_1F, src);
123      vinfo.hwfmt[0] |= S4_VFMT_FOG_PARAM;
124   }
125
126   /* texcoords/varyings */
127   for (i = 0; i < I915_TEX_UNITS; i++) {
128      uint32_t hwtc;
129      if (fs->texcoords[i].semantic != -1) {
130         src = draw_find_shader_output(i915->draw, fs->texcoords[i].semantic,
131                                       fs->texcoords[i].index);
132         if (fs->texcoords[i].semantic == TGSI_SEMANTIC_FACE) {
133            /* XXX Because of limitations in the draw module, currently src will
134             * be 0 for SEMANTIC_FACE, so this aliases to POS. We need to fix in
135             * the draw module by adding an extra shader output.
136             */
137            mesa_loge("Front/back face is broken\n");
138            draw_emit_vertex_attr(&vinfo, EMIT_1F, src);
139            hwtc = TEXCOORDFMT_1D;
140         } else {
141            hwtc = TEXCOORDFMT_4D;
142            draw_emit_vertex_attr(&vinfo, EMIT_4F, src);
143         }
144      } else {
145         hwtc = TEXCOORDFMT_NOT_PRESENT;
146      }
147      vinfo.hwfmt[1] |= hwtc << (i * 4);
148   }
149
150   draw_compute_vertex_size(&vinfo);
151
152   if (memcmp(&i915->current.vertex_info, &vinfo, sizeof(vinfo))) {
153      /* Need to set this flag so that the LIS2/4 registers get set.
154       * It also means the i915_update_immediate() function must be called
155       * after this one, in i915_update_derived().
156       */
157      i915->dirty |= I915_NEW_VERTEX_FORMAT;
158
159      memcpy(&i915->current.vertex_info, &vinfo, sizeof(vinfo));
160   }
161}
162
163struct i915_tracked_state i915_update_vertex_layout = {
164   "vertex_layout", calculate_vertex_layout,
165   I915_NEW_RASTERIZER | I915_NEW_FS | I915_NEW_VS};
166
167/***********************************************************************
168 */
169static struct i915_tracked_state *atoms[] = {
170   &i915_update_vertex_layout, &i915_hw_samplers,  &i915_hw_immediate,
171   &i915_hw_dynamic,           &i915_hw_fs,        &i915_hw_framebuffer,
172   &i915_hw_dst_buf_vars,      &i915_hw_constants, NULL,
173};
174
175void
176i915_update_derived(struct i915_context *i915)
177{
178   int i;
179
180   if (I915_DBG_ON(DBG_ATOMS))
181      i915_dump_dirty(i915, __FUNCTION__);
182
183   if (!i915->fs) {
184      i915->dirty &= ~(I915_NEW_FS_CONSTANTS | I915_NEW_FS);
185      i915->hardware_dirty &= ~(I915_HW_PROGRAM | I915_HW_CONSTANTS);
186   }
187
188   if (!i915->vs)
189      i915->dirty &= ~I915_NEW_VS;
190
191   if (!i915->blend)
192      i915->dirty &= ~I915_NEW_BLEND;
193
194   if (!i915->rasterizer)
195      i915->dirty &= ~I915_NEW_RASTERIZER;
196
197   if (!i915->depth_stencil)
198      i915->dirty &= ~I915_NEW_DEPTH_STENCIL;
199
200   for (i = 0; atoms[i]; i++)
201      if (atoms[i]->dirty & i915->dirty)
202         atoms[i]->update(i915);
203
204   i915->dirty = 0;
205}
206