draw: added array element debug / bounds checking code (disabled)
[mesa.git] / src / gallium / auxiliary / draw / draw_pt_post_vs.c
1 /**************************************************************************
2 *
3 * Copyright 2008 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 "util/u_memory.h"
29 #include "pipe/p_context.h"
30 #include "draw/draw_context.h"
31 #include "draw/draw_private.h"
32 #include "draw/draw_pt.h"
33
34 struct pt_post_vs {
35 struct draw_context *draw;
36
37 boolean (*run)( struct pt_post_vs *pvs,
38 struct draw_vertex_info *info );
39 };
40
41 static INLINE void
42 initialize_vertex_header(struct vertex_header *header)
43 {
44 header->clipmask = 0;
45 header->edgeflag = 1;
46 header->pad = 0;
47 header->vertex_id = UNDEFINED_VERTEX_ID;
48 }
49
50 static INLINE float
51 dot4(const float *a, const float *b)
52 {
53 return (a[0]*b[0] +
54 a[1]*b[1] +
55 a[2]*b[2] +
56 a[3]*b[3]);
57 }
58
59 static INLINE unsigned
60 compute_clipmask_gl(const float *clip, /*const*/ float plane[][4], unsigned nr)
61 {
62 unsigned mask = 0x0;
63 unsigned i;
64
65 #if 0
66 debug_printf("compute clipmask %f %f %f %f\n",
67 clip[0], clip[1], clip[2], clip[3]);
68 assert(clip[3] != 0.0);
69 #endif
70
71 /* Do the hardwired planes first:
72 */
73 if (-clip[0] + clip[3] < 0) mask |= (1<<0);
74 if ( clip[0] + clip[3] < 0) mask |= (1<<1);
75 if (-clip[1] + clip[3] < 0) mask |= (1<<2);
76 if ( clip[1] + clip[3] < 0) mask |= (1<<3);
77 if ( clip[2] + clip[3] < 0) mask |= (1<<4); /* match mesa clipplane numbering - for now */
78 if (-clip[2] + clip[3] < 0) mask |= (1<<5); /* match mesa clipplane numbering - for now */
79
80 /* Followed by any remaining ones:
81 */
82 for (i = 6; i < nr; i++) {
83 if (dot4(clip, plane[i]) < 0)
84 mask |= (1<<i);
85 }
86
87 return mask;
88 }
89
90
91 /* The normal case - cliptest, rhw divide, viewport transform.
92 *
93 * Also handle identity viewport here at the expense of a few wasted
94 * instructions
95 */
96 static boolean post_vs_cliptest_viewport_gl( struct pt_post_vs *pvs,
97 struct draw_vertex_info *info )
98 {
99 struct vertex_header *out = info->verts;
100 const float *scale = pvs->draw->viewport.scale;
101 const float *trans = pvs->draw->viewport.translate;
102 const unsigned pos = draw_current_shader_position_output(pvs->draw);
103 unsigned clipped = 0;
104 unsigned j;
105
106 if (0) debug_printf("%s count, %d\n", __FUNCTION__, info->count);
107
108 for (j = 0; j < info->count; j++) {
109 float *position = out->data[pos];
110
111 initialize_vertex_header(out);
112 #if 0
113 debug_printf("%d) io = %p, data = %p = [%f, %f, %f, %f]\n",
114 j, out, position, position[0], position[1], position[2], position[3]);
115 #endif
116
117 out->clip[0] = position[0];
118 out->clip[1] = position[1];
119 out->clip[2] = position[2];
120 out->clip[3] = position[3];
121
122 out->vertex_id = 0xffff;
123 out->clipmask = compute_clipmask_gl(out->clip,
124 pvs->draw->plane,
125 pvs->draw->nr_planes);
126 clipped += out->clipmask;
127
128 if (out->clipmask == 0)
129 {
130 /* divide by w */
131 float w = 1.0f / position[3];
132
133 /* Viewport mapping */
134 position[0] = position[0] * w * scale[0] + trans[0];
135 position[1] = position[1] * w * scale[1] + trans[1];
136 position[2] = position[2] * w * scale[2] + trans[2];
137 position[3] = w;
138 #if 0
139 debug_printf("post viewport: %f %f %f %f\n",
140 position[0],
141 position[1],
142 position[2],
143 position[3]);
144 #endif
145 }
146
147 out = (struct vertex_header *)( (char *)out + info->stride );
148 }
149
150 return clipped != 0;
151 }
152
153
154
155 /* As above plus edgeflags
156 */
157 static boolean
158 post_vs_cliptest_viewport_gl_edgeflag(struct pt_post_vs *pvs,
159 struct draw_vertex_info *info)
160 {
161 unsigned j;
162 boolean needpipe;
163
164 needpipe = post_vs_cliptest_viewport_gl(pvs, info);
165
166 /* If present, copy edgeflag VS output into vertex header.
167 * Otherwise, leave header as is.
168 */
169 if (pvs->draw->vs.edgeflag_output) {
170 struct vertex_header *out = info->verts;
171 int ef = pvs->draw->vs.edgeflag_output;
172
173 for (j = 0; j < info->count; j++) {
174 const float *edgeflag = out->data[ef];
175 out->edgeflag = !(edgeflag[0] != 1.0f);
176 needpipe |= !out->edgeflag;
177 out = (struct vertex_header *)( (char *)out + info->stride );
178 }
179 }
180 return needpipe;
181 }
182
183
184
185
186 /* If bypass_clipping is set, skip cliptest and rhw divide.
187 */
188 static boolean post_vs_viewport( struct pt_post_vs *pvs,
189 struct draw_vertex_info *info )
190 {
191 struct vertex_header *out = info->verts;
192 const float *scale = pvs->draw->viewport.scale;
193 const float *trans = pvs->draw->viewport.translate;
194 const unsigned pos = draw_current_shader_position_output(pvs->draw);
195 unsigned j;
196
197 if (0) debug_printf("%s\n", __FUNCTION__);
198 for (j = 0; j < info->count; j++) {
199 float *position = out->data[pos];
200
201 initialize_vertex_header(out);
202 /* Viewport mapping only, no cliptest/rhw divide
203 */
204 position[0] = position[0] * scale[0] + trans[0];
205 position[1] = position[1] * scale[1] + trans[1];
206 position[2] = position[2] * scale[2] + trans[2];
207
208 out = (struct vertex_header *)((char *)out + info->stride);
209 }
210
211 return FALSE;
212 }
213
214
215 /* If bypass_clipping is set and we have an identity viewport, nothing
216 * to do.
217 */
218 static boolean post_vs_none( struct pt_post_vs *pvs,
219 struct draw_vertex_info *info )
220 {
221 struct vertex_header *out = info->verts;
222 unsigned j;
223
224 if (0) debug_printf("%s\n", __FUNCTION__);
225 /* just initialize the vertex_id in all headers */
226 for (j = 0; j < info->count; j++) {
227 initialize_vertex_header(out);
228
229 out = (struct vertex_header *)((char *)out + info->stride);
230 }
231 return FALSE;
232 }
233
234 boolean draw_pt_post_vs_run( struct pt_post_vs *pvs,
235 struct draw_vertex_info *info )
236 {
237 return pvs->run( pvs, info );
238 }
239
240
241 void draw_pt_post_vs_prepare( struct pt_post_vs *pvs,
242 boolean bypass_clipping,
243 boolean bypass_viewport,
244 boolean opengl,
245 boolean need_edgeflags )
246 {
247 if (!need_edgeflags) {
248 if (bypass_clipping) {
249 if (bypass_viewport)
250 pvs->run = post_vs_none;
251 else
252 pvs->run = post_vs_viewport;
253 }
254 else {
255 /* if (opengl) */
256 pvs->run = post_vs_cliptest_viewport_gl;
257 }
258 }
259 else {
260 /* If we need to copy edgeflags to the vertex header, it should
261 * mean we're running the primitive pipeline. Hence the bypass
262 * flags should be false.
263 */
264 assert(!bypass_clipping);
265 assert(!bypass_viewport);
266 pvs->run = post_vs_cliptest_viewport_gl_edgeflag;
267 }
268 }
269
270
271 struct pt_post_vs *draw_pt_post_vs_create( struct draw_context *draw )
272 {
273 struct pt_post_vs *pvs = CALLOC_STRUCT( pt_post_vs );
274 if (!pvs)
275 return NULL;
276
277 pvs->draw = draw;
278
279 return pvs;
280 }
281
282 void draw_pt_post_vs_destroy( struct pt_post_vs *pvs )
283 {
284 FREE(pvs);
285 }