i915_state_derived.c revision fe306e7ea5e789adc955653d9be8cd7f8af47264
1/**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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
29#include "util/u_memory.h"
30#include "pipe/p_shader_tokens.h"
31#include "draw/draw_context.h"
32#include "draw/draw_vertex.h"
33#include "i915_context.h"
34#include "i915_state.h"
35#include "i915_reg.h"
36
37
38
39/**
40 * Determine the hardware vertex layout.
41 * Depends on vertex/fragment shader state.
42 */
43static void calculate_vertex_layout( struct i915_context *i915 )
44{
45   const struct i915_fragment_shader *fs = i915->fs;
46   const enum interp_mode colorInterp = i915->rasterizer->color_interp;
47   struct vertex_info vinfo;
48   boolean texCoords[8], colors[2], fog, needW;
49   uint i;
50   int src;
51
52   memset(texCoords, 0, sizeof(texCoords));
53   colors[0] = colors[1] = fog = needW = 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         break;
63      case TGSI_SEMANTIC_COLOR:
64         assert(fs->info.input_semantic_index[i] < 2);
65         colors[fs->info.input_semantic_index[i]] = TRUE;
66         break;
67      case TGSI_SEMANTIC_GENERIC:
68         /* usually a texcoord */
69         {
70            const uint unit = fs->info.input_semantic_index[i];
71            assert(unit < 8);
72            texCoords[unit] = TRUE;
73            needW = TRUE;
74         }
75         break;
76      case TGSI_SEMANTIC_FOG:
77         fog = TRUE;
78         break;
79      default:
80         assert(0);
81      }
82   }
83
84
85   /* pos */
86   src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_POSITION, 0);
87   if (needW) {
88      draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src);
89      vinfo.hwfmt[0] |= S4_VFMT_XYZW;
90      vinfo.attrib[0].emit = EMIT_4F;
91   }
92   else {
93      draw_emit_vertex_attr(&vinfo, EMIT_3F, INTERP_LINEAR, src);
94      vinfo.hwfmt[0] |= S4_VFMT_XYZ;
95      vinfo.attrib[0].emit = EMIT_3F;
96   }
97
98   /* hardware point size */
99   /* XXX todo */
100
101   /* primary color */
102   if (colors[0]) {
103      src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_COLOR, 0);
104      draw_emit_vertex_attr(&vinfo, EMIT_4UB_BGRA, colorInterp, src);
105      vinfo.hwfmt[0] |= S4_VFMT_COLOR;
106   }
107
108   /* secondary color */
109   if (colors[1]) {
110      src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_COLOR, 1);
111      draw_emit_vertex_attr(&vinfo, EMIT_4UB_BGRA, colorInterp, src);
112      vinfo.hwfmt[0] |= S4_VFMT_SPEC_FOG;
113   }
114
115   /* fog coord, not fog blend factor */
116   if (fog) {
117      src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_FOG, 0);
118      draw_emit_vertex_attr(&vinfo, EMIT_1F, INTERP_PERSPECTIVE, src);
119      vinfo.hwfmt[0] |= S4_VFMT_FOG_PARAM;
120   }
121
122   /* texcoords */
123   for (i = 0; i < 8; i++) {
124      uint hwtc;
125      if (texCoords[i]) {
126         hwtc = TEXCOORDFMT_4D;
127         src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_GENERIC, i);
128         draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
129      }
130      else {
131         hwtc = TEXCOORDFMT_NOT_PRESENT;
132      }
133      vinfo.hwfmt[1] |= hwtc << (i * 4);
134   }
135
136   draw_compute_vertex_size(&vinfo);
137
138   if (memcmp(&i915->current.vertex_info, &vinfo, sizeof(vinfo))) {
139      /* Need to set this flag so that the LIS2/4 registers get set.
140       * It also means the i915_update_immediate() function must be called
141       * after this one, in i915_update_derived().
142       */
143      i915->dirty |= I915_NEW_VERTEX_FORMAT;
144
145      memcpy(&i915->current.vertex_info, &vinfo, sizeof(vinfo));
146   }
147}
148
149
150
151
152/* Hopefully this will remain quite simple, otherwise need to pull in
153 * something like the state tracker mechanism.
154 */
155void i915_update_derived( struct i915_context *i915 )
156{
157   if (i915->dirty & (I915_NEW_RASTERIZER | I915_NEW_FS | I915_NEW_VS))
158      calculate_vertex_layout( i915 );
159
160   if (i915->dirty & (I915_NEW_SAMPLER | I915_NEW_SAMPLER_VIEW))
161      i915_update_samplers(i915);
162
163   if (i915->dirty & I915_NEW_SAMPLER_VIEW)
164      i915_update_textures(i915);
165
166   if (i915->dirty)
167      i915_update_immediate( i915 );
168
169   if (i915->dirty)
170      i915_update_dynamic( i915 );
171
172   if (i915->dirty & I915_NEW_FS) {
173      i915->hardware_dirty |= I915_HW_PROGRAM; /* XXX right? */
174   }
175
176   /* HW emit currently references framebuffer state directly:
177    */
178   if (i915->dirty & I915_NEW_FRAMEBUFFER)
179      i915->hardware_dirty |= I915_HW_STATIC;
180
181   i915->dirty = 0;
182}
183