Merge remote branch 'origin/7.8'
[mesa.git] / src / gallium / drivers / i915 / i915_state_derived.c
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 */
43 static 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 */
155 void 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 }