Merge branch 'gallium-i915-current' into gallium-0.1
[mesa.git] / src / gallium / drivers / softpipe / sp_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 #include "pipe/p_util.h"
29 #include "pipe/p_shader_tokens.h"
30 #include "draw/draw_context.h"
31 #include "draw/draw_vertex.h"
32 #include "draw/draw_private.h"
33 #include "sp_context.h"
34 #include "sp_state.h"
35
36
37 /**
38 * Mark the current vertex layout as "invalid".
39 * We'll validate the vertex layout later, when we start to actually
40 * render a point or line or tri.
41 */
42 static void
43 invalidate_vertex_layout(struct softpipe_context *softpipe)
44 {
45 softpipe->vertex_info.num_attribs = 0;
46 }
47
48
49 /**
50 * The vertex info describes how to convert the post-transformed vertices
51 * (simple float[][4]) used by the 'draw' module into vertices for
52 * rasterization.
53 *
54 * This function validates the vertex layout and returns a pointer to a
55 * vertex_info object.
56 */
57 struct vertex_info *
58 softpipe_get_vertex_info(struct softpipe_context *softpipe)
59 {
60 struct vertex_info *vinfo = &softpipe->vertex_info;
61
62 if (vinfo->num_attribs == 0) {
63 /* compute vertex layout now */
64 const struct sp_fragment_shader *spfs = softpipe->fs;
65 const enum interp_mode colorInterp
66 = softpipe->rasterizer->flatshade ? INTERP_CONSTANT : INTERP_LINEAR;
67 uint i;
68
69 if (softpipe->vbuf) {
70 /* if using the post-transform vertex buffer, tell draw_vbuf to
71 * simply emit the whole post-xform vertex as-is:
72 */
73 struct vertex_info *vinfo_vbuf = &softpipe->vertex_info_vbuf;
74 const uint num = draw_num_vs_outputs(softpipe->draw);
75 uint i;
76
77 /* No longer any need to try and emit draw vertex_header info.
78 */
79 vinfo_vbuf->num_attribs = 0;
80 for (i = 0; i < num; i++) {
81 draw_emit_vertex_attr(vinfo_vbuf, EMIT_4F, INTERP_PERSPECTIVE, i);
82 }
83 draw_compute_vertex_size(vinfo_vbuf);
84 }
85
86 /*
87 * Loop over fragment shader inputs, searching for the matching output
88 * from the vertex shader.
89 */
90 vinfo->num_attribs = 0;
91 for (i = 0; i < spfs->info.num_inputs; i++) {
92 int src;
93 switch (spfs->info.input_semantic_name[i]) {
94 case TGSI_SEMANTIC_POSITION:
95 src = draw_find_vs_output(softpipe->draw,
96 TGSI_SEMANTIC_POSITION, 0);
97 draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_POS, src);
98 break;
99
100 case TGSI_SEMANTIC_COLOR:
101 src = draw_find_vs_output(softpipe->draw, TGSI_SEMANTIC_COLOR,
102 spfs->info.input_semantic_index[i]);
103 draw_emit_vertex_attr(vinfo, EMIT_4F, colorInterp, src);
104 break;
105
106 case TGSI_SEMANTIC_FOG:
107 src = draw_find_vs_output(softpipe->draw, TGSI_SEMANTIC_FOG, 0);
108 draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
109 break;
110
111 case TGSI_SEMANTIC_GENERIC:
112 /* this includes texcoords and varying vars */
113 src = draw_find_vs_output(softpipe->draw, TGSI_SEMANTIC_GENERIC,
114 spfs->info.input_semantic_index[i]);
115 draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
116 break;
117
118 default:
119 assert(0);
120 }
121 }
122
123 softpipe->psize_slot = draw_find_vs_output(softpipe->draw,
124 TGSI_SEMANTIC_PSIZE, 0);
125 if (softpipe->psize_slot > 0) {
126 draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT,
127 softpipe->psize_slot);
128 }
129
130 draw_compute_vertex_size(vinfo);
131 }
132
133 return vinfo;
134 }
135
136
137 /**
138 * Called from vbuf module.
139 *
140 * Note that there's actually two different vertex layouts in softpipe.
141 *
142 * The normal one is computed in softpipe_get_vertex_info() above and is
143 * used by the point/line/tri "setup" code.
144 *
145 * The other one (this one) is only used by the vbuf module (which is
146 * not normally used by default but used in testing). For the vbuf module,
147 * we basically want to pass-through the draw module's vertex layout as-is.
148 * When the softpipe vbuf code begins drawing, the normal vertex layout
149 * will come into play again.
150 */
151 struct vertex_info *
152 softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe)
153 {
154 (void) softpipe_get_vertex_info(softpipe);
155 return &softpipe->vertex_info_vbuf;
156 }
157
158
159 /**
160 * Recompute cliprect from scissor bounds, scissor enable and surface size.
161 */
162 static void
163 compute_cliprect(struct softpipe_context *sp)
164 {
165 uint surfWidth = sp->framebuffer.width;
166 uint surfHeight = sp->framebuffer.height;
167
168 if (sp->rasterizer->scissor) {
169 /* clip to scissor rect */
170 sp->cliprect.minx = MAX2(sp->scissor.minx, 0);
171 sp->cliprect.miny = MAX2(sp->scissor.miny, 0);
172 sp->cliprect.maxx = MIN2(sp->scissor.maxx, surfWidth);
173 sp->cliprect.maxy = MIN2(sp->scissor.maxy, surfHeight);
174 }
175 else {
176 /* clip to surface bounds */
177 sp->cliprect.minx = 0;
178 sp->cliprect.miny = 0;
179 sp->cliprect.maxx = surfWidth;
180 sp->cliprect.maxy = surfHeight;
181 }
182 }
183
184
185 /* Hopefully this will remain quite simple, otherwise need to pull in
186 * something like the state tracker mechanism.
187 */
188 void softpipe_update_derived( struct softpipe_context *softpipe )
189 {
190 if (softpipe->dirty & (SP_NEW_RASTERIZER |
191 SP_NEW_FS |
192 SP_NEW_VS))
193 invalidate_vertex_layout( softpipe );
194
195 if (softpipe->dirty & (SP_NEW_SCISSOR |
196 SP_NEW_DEPTH_STENCIL_ALPHA |
197 SP_NEW_FRAMEBUFFER))
198 compute_cliprect(softpipe);
199
200 if (softpipe->dirty & (SP_NEW_BLEND |
201 SP_NEW_DEPTH_STENCIL_ALPHA |
202 SP_NEW_FRAMEBUFFER |
203 SP_NEW_RASTERIZER |
204 SP_NEW_FS |
205 SP_NEW_QUERY))
206 sp_build_quad_pipeline(softpipe);
207
208 softpipe->dirty = 0;
209 }