Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
57 | pj | 1 | /* $Id: s_triangle.c,v 1.1 2003-02-28 11:49:43 pj Exp $ */ |
2 | |||
3 | /* |
||
4 | * Mesa 3-D graphics library |
||
5 | * Version: 5.0 |
||
6 | * |
||
7 | * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. |
||
8 | * |
||
9 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
10 | * copy of this software and associated documentation files (the "Software"), |
||
11 | * to deal in the Software without restriction, including without limitation |
||
12 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
13 | * and/or sell copies of the Software, and to permit persons to whom the |
||
14 | * Software is furnished to do so, subject to the following conditions: |
||
15 | * |
||
16 | * The above copyright notice and this permission notice shall be included |
||
17 | * in all copies or substantial portions of the Software. |
||
18 | * |
||
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||
20 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
22 | * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
||
23 | * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
||
24 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||
25 | */ |
||
26 | |||
27 | |||
28 | /* |
||
29 | * When the device driver doesn't implement triangle rasterization it |
||
30 | * can hook in _swrast_Triangle, which eventually calls one of these |
||
31 | * functions to draw triangles. |
||
32 | */ |
||
33 | |||
34 | #include "glheader.h" |
||
35 | #include "context.h" |
||
36 | #include "colormac.h" |
||
37 | #include "imports.h" |
||
38 | #include "macros.h" |
||
39 | #include "mmath.h" |
||
40 | #include "texformat.h" |
||
41 | #include "teximage.h" |
||
42 | #include "texstate.h" |
||
43 | |||
44 | #include "s_aatriangle.h" |
||
45 | #include "s_context.h" |
||
46 | #include "s_depth.h" |
||
47 | #include "s_feedback.h" |
||
48 | #include "s_span.h" |
||
49 | #include "s_triangle.h" |
||
50 | |||
51 | |||
52 | /* |
||
53 | * Just used for feedback mode. |
||
54 | */ |
||
55 | GLboolean _mesa_cull_triangle( GLcontext *ctx, |
||
56 | const SWvertex *v0, |
||
57 | const SWvertex *v1, |
||
58 | const SWvertex *v2 ) |
||
59 | { |
||
60 | GLfloat ex = v1->win[0] - v0->win[0]; |
||
61 | GLfloat ey = v1->win[1] - v0->win[1]; |
||
62 | GLfloat fx = v2->win[0] - v0->win[0]; |
||
63 | GLfloat fy = v2->win[1] - v0->win[1]; |
||
64 | GLfloat c = ex*fy-ey*fx; |
||
65 | |||
66 | if (c * SWRAST_CONTEXT(ctx)->_backface_sign > 0) |
||
67 | return 0; |
||
68 | |||
69 | return 1; |
||
70 | } |
||
71 | |||
72 | |||
73 | |||
74 | /* |
||
75 | * Render a flat-shaded color index triangle. |
||
76 | */ |
||
77 | static void flat_ci_triangle( GLcontext *ctx, |
||
78 | const SWvertex *v0, |
||
79 | const SWvertex *v1, |
||
80 | const SWvertex *v2 ) |
||
81 | { |
||
82 | #define INTERP_Z 1 |
||
83 | #define INTERP_FOG 1 |
||
84 | |||
85 | #define SETUP_CODE \ |
||
86 | span.interpMask |= SPAN_INDEX; \ |
||
87 | span.index = IntToFixed(v2->index); \ |
||
88 | span.indexStep = 0; |
||
89 | |||
90 | #define RENDER_SPAN( span ) _mesa_write_index_span(ctx, &span); |
||
91 | |||
92 | #include "s_tritemp.h" |
||
93 | } |
||
94 | |||
95 | |||
96 | |||
97 | /* |
||
98 | * Render a smooth-shaded color index triangle. |
||
99 | */ |
||
100 | static void smooth_ci_triangle( GLcontext *ctx, |
||
101 | const SWvertex *v0, |
||
102 | const SWvertex *v1, |
||
103 | const SWvertex *v2 ) |
||
104 | { |
||
105 | #define INTERP_Z 1 |
||
106 | #define INTERP_FOG 1 |
||
107 | #define INTERP_INDEX 1 |
||
108 | |||
109 | #define RENDER_SPAN( span ) _mesa_write_index_span(ctx, &span); |
||
110 | |||
111 | #include "s_tritemp.h" |
||
112 | } |
||
113 | |||
114 | |||
115 | |||
116 | /* |
||
117 | * Render a flat-shaded RGBA triangle. |
||
118 | */ |
||
119 | static void flat_rgba_triangle( GLcontext *ctx, |
||
120 | const SWvertex *v0, |
||
121 | const SWvertex *v1, |
||
122 | const SWvertex *v2 ) |
||
123 | { |
||
124 | #define INTERP_Z 1 |
||
125 | #define INTERP_FOG 1 |
||
126 | #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE |
||
127 | |||
128 | #define SETUP_CODE \ |
||
129 | ASSERT(ctx->Texture._EnabledUnits == 0); \ |
||
130 | ASSERT(ctx->Light.ShadeModel==GL_FLAT); \ |
||
131 | span.interpMask |= SPAN_RGBA; \ |
||
132 | span.red = ChanToFixed(v2->color[0]); \ |
||
133 | span.green = ChanToFixed(v2->color[1]); \ |
||
134 | span.blue = ChanToFixed(v2->color[2]); \ |
||
135 | span.alpha = ChanToFixed(v2->color[3]); \ |
||
136 | span.redStep = 0; \ |
||
137 | span.greenStep = 0; \ |
||
138 | span.blueStep = 0; \ |
||
139 | span.alphaStep = 0; |
||
140 | |||
141 | #define RENDER_SPAN( span ) _mesa_write_rgba_span(ctx, &span); |
||
142 | |||
143 | #include "s_tritemp.h" |
||
144 | } |
||
145 | |||
146 | |||
147 | |||
148 | /* |
||
149 | * Render a smooth-shaded RGBA triangle. |
||
150 | */ |
||
151 | static void smooth_rgba_triangle( GLcontext *ctx, |
||
152 | const SWvertex *v0, |
||
153 | const SWvertex *v1, |
||
154 | const SWvertex *v2 ) |
||
155 | { |
||
156 | |||
157 | #define INTERP_Z 1 |
||
158 | #define INTERP_FOG 1 |
||
159 | #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE |
||
160 | #define INTERP_RGB 1 |
||
161 | #define INTERP_ALPHA 1 |
||
162 | |||
163 | #define SETUP_CODE \ |
||
164 | { \ |
||
165 | /* texturing must be off */ \ |
||
166 | ASSERT(ctx->Texture._EnabledUnits == 0); \ |
||
167 | ASSERT(ctx->Light.ShadeModel==GL_SMOOTH); \ |
||
168 | } |
||
169 | |||
170 | #define RENDER_SPAN( span ) _mesa_write_rgba_span(ctx, &span); |
||
171 | |||
172 | #include "s_tritemp.h" |
||
173 | |||
174 | } |
||
175 | |||
176 | |||
177 | /* |
||
178 | * Render an RGB, GL_DECAL, textured triangle. |
||
179 | * Interpolate S,T only w/out mipmapping or perspective correction. |
||
180 | * |
||
181 | * No fog. |
||
182 | */ |
||
183 | static void simple_textured_triangle( GLcontext *ctx, |
||
184 | const SWvertex *v0, |
||
185 | const SWvertex *v1, |
||
186 | const SWvertex *v2 ) |
||
187 | { |
||
188 | #define INTERP_INT_TEX 1 |
||
189 | #define S_SCALE twidth |
||
190 | #define T_SCALE theight |
||
191 | |||
192 | #define SETUP_CODE \ |
||
193 | SWcontext *swrast = SWRAST_CONTEXT(ctx); \ |
||
194 | struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \ |
||
195 | const GLint b = obj->BaseLevel; \ |
||
196 | const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ |
||
197 | const GLfloat theight = (GLfloat) obj->Image[b]->Height; \ |
||
198 | const GLint twidth_log2 = obj->Image[b]->WidthLog2; \ |
||
199 | const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \ |
||
200 | const GLint smask = obj->Image[b]->Width - 1; \ |
||
201 | const GLint tmask = obj->Image[b]->Height - 1; \ |
||
202 | if (!texture) { \ |
||
203 | /* this shouldn't happen */ \ |
||
204 | return; \ |
||
205 | } |
||
206 | |||
207 | #define RENDER_SPAN( span ) \ |
||
208 | GLuint i; \ |
||
209 | span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \ |
||
210 | span.intTex[1] -= FIXED_HALF; \ |
||
211 | for (i = 0; i < span.end; i++) { \ |
||
212 | GLint s = FixedToInt(span.intTex[0]) & smask; \ |
||
213 | GLint t = FixedToInt(span.intTex[1]) & tmask; \ |
||
214 | GLint pos = (t << twidth_log2) + s; \ |
||
215 | pos = pos + pos + pos; /* multiply by 3 */ \ |
||
216 | span.array->rgb[i][RCOMP] = texture[pos]; \ |
||
217 | span.array->rgb[i][GCOMP] = texture[pos+1]; \ |
||
218 | span.array->rgb[i][BCOMP] = texture[pos+2]; \ |
||
219 | span.intTex[0] += span.intTexStep[0]; \ |
||
220 | span.intTex[1] += span.intTexStep[1]; \ |
||
221 | } \ |
||
222 | (*swrast->Driver.WriteRGBSpan)(ctx, span.end, span.x, span.y, \ |
||
223 | (CONST GLchan (*)[3]) span.array->rgb,\ |
||
224 | NULL ); |
||
225 | |||
226 | #include "s_tritemp.h" |
||
227 | } |
||
228 | |||
229 | |||
230 | /* |
||
231 | * Render an RGB, GL_DECAL, textured triangle. |
||
232 | * Interpolate S,T, GL_LESS depth test, w/out mipmapping or |
||
233 | * perspective correction. |
||
234 | * |
||
235 | * No fog. |
||
236 | */ |
||
237 | static void simple_z_textured_triangle( GLcontext *ctx, |
||
238 | const SWvertex *v0, |
||
239 | const SWvertex *v1, |
||
240 | const SWvertex *v2 ) |
||
241 | { |
||
242 | #define INTERP_Z 1 |
||
243 | #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE |
||
244 | #define INTERP_INT_TEX 1 |
||
245 | #define S_SCALE twidth |
||
246 | #define T_SCALE theight |
||
247 | |||
248 | #define SETUP_CODE \ |
||
249 | SWcontext *swrast = SWRAST_CONTEXT(ctx); \ |
||
250 | struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \ |
||
251 | const GLint b = obj->BaseLevel; \ |
||
252 | const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ |
||
253 | const GLfloat theight = (GLfloat) obj->Image[b]->Height; \ |
||
254 | const GLint twidth_log2 = obj->Image[b]->WidthLog2; \ |
||
255 | const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \ |
||
256 | const GLint smask = obj->Image[b]->Width - 1; \ |
||
257 | const GLint tmask = obj->Image[b]->Height - 1; \ |
||
258 | if (!texture) { \ |
||
259 | /* this shouldn't happen */ \ |
||
260 | return; \ |
||
261 | } |
||
262 | |||
263 | #define RENDER_SPAN( span ) \ |
||
264 | GLuint i; \ |
||
265 | span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \ |
||
266 | span.intTex[1] -= FIXED_HALF; \ |
||
267 | for (i = 0; i < span.end; i++) { \ |
||
268 | const GLdepth z = FixedToDepth(span.z); \ |
||
269 | if (z < zRow[i]) { \ |
||
270 | GLint s = FixedToInt(span.intTex[0]) & smask; \ |
||
271 | GLint t = FixedToInt(span.intTex[1]) & tmask; \ |
||
272 | GLint pos = (t << twidth_log2) + s; \ |
||
273 | pos = pos + pos + pos; /* multiply by 3 */ \ |
||
274 | span.array->rgb[i][RCOMP] = texture[pos]; \ |
||
275 | span.array->rgb[i][GCOMP] = texture[pos+1]; \ |
||
276 | span.array->rgb[i][BCOMP] = texture[pos+2]; \ |
||
277 | zRow[i] = z; \ |
||
278 | span.array->mask[i] = 1; \ |
||
279 | } \ |
||
280 | else { \ |
||
281 | span.array->mask[i] = 0; \ |
||
282 | } \ |
||
283 | span.intTex[0] += span.intTexStep[0]; \ |
||
284 | span.intTex[1] += span.intTexStep[1]; \ |
||
285 | span.z += span.zStep; \ |
||
286 | } \ |
||
287 | (*swrast->Driver.WriteRGBSpan)(ctx, span.end, span.x, span.y, \ |
||
288 | (CONST GLchan (*)[3]) span.array->rgb,\ |
||
289 | span.array->mask ); |
||
290 | |||
291 | #include "s_tritemp.h" |
||
292 | } |
||
293 | |||
294 | |||
295 | #if CHAN_TYPE != GL_FLOAT |
||
296 | |||
297 | struct affine_info |
||
298 | { |
||
299 | GLenum filter; |
||
300 | GLenum format; |
||
301 | GLenum envmode; |
||
302 | GLint smask, tmask; |
||
303 | GLint twidth_log2; |
||
304 | const GLchan *texture; |
||
305 | GLfixed er, eg, eb, ea; |
||
306 | GLint tbytesline, tsize; |
||
307 | }; |
||
308 | |||
309 | |||
310 | /* This function can handle GL_NEAREST or GL_LINEAR sampling of 2D RGB or RGBA |
||
311 | * textures with GL_REPLACE, GL_MODULATE, GL_BLEND, GL_DECAL or GL_ADD |
||
312 | * texture env modes. |
||
313 | */ |
||
314 | static INLINE void |
||
315 | affine_span(GLcontext *ctx, struct sw_span *span, |
||
316 | struct affine_info *info) |
||
317 | { |
||
318 | GLchan sample[4]; /* the filtered texture sample */ |
||
319 | |||
320 | /* Instead of defining a function for each mode, a test is done |
||
321 | * between the outer and inner loops. This is to reduce code size |
||
322 | * and complexity. Observe that an optimizing compiler kills |
||
323 | * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST). |
||
324 | */ |
||
325 | |||
326 | #define NEAREST_RGB \ |
||
327 | sample[RCOMP] = tex00[RCOMP]; \ |
||
328 | sample[GCOMP] = tex00[GCOMP]; \ |
||
329 | sample[BCOMP] = tex00[BCOMP]; \ |
||
330 | sample[ACOMP] = CHAN_MAX |
||
331 | |||
332 | #define LINEAR_RGB \ |
||
333 | sample[RCOMP] = (ti * (si * tex00[0] + sf * tex01[0]) + \ |
||
334 | tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \ |
||
335 | sample[GCOMP] = (ti * (si * tex00[1] + sf * tex01[1]) + \ |
||
336 | tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \ |
||
337 | sample[BCOMP] = (ti * (si * tex00[2] + sf * tex01[2]) + \ |
||
338 | tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \ |
||
339 | sample[ACOMP] = CHAN_MAX |
||
340 | |||
341 | #define NEAREST_RGBA COPY_CHAN4(sample, tex00) |
||
342 | |||
343 | #define LINEAR_RGBA \ |
||
344 | sample[RCOMP] = (ti * (si * tex00[0] + sf * tex01[0]) + \ |
||
345 | tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT;\ |
||
346 | sample[GCOMP] = (ti * (si * tex00[1] + sf * tex01[1]) + \ |
||
347 | tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT;\ |
||
348 | sample[BCOMP] = (ti * (si * tex00[2] + sf * tex01[2]) + \ |
||
349 | tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT;\ |
||
350 | sample[ACOMP] = (ti * (si * tex00[3] + sf * tex01[3]) + \ |
||
351 | tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT |
||
352 | |||
353 | #define MODULATE \ |
||
354 | dest[RCOMP] = span->red * (sample[RCOMP] + 1u) >> (FIXED_SHIFT + 8); \ |
||
355 | dest[GCOMP] = span->green * (sample[GCOMP] + 1u) >> (FIXED_SHIFT + 8); \ |
||
356 | dest[BCOMP] = span->blue * (sample[BCOMP] + 1u) >> (FIXED_SHIFT + 8); \ |
||
357 | dest[ACOMP] = span->alpha * (sample[ACOMP] + 1u) >> (FIXED_SHIFT + 8) |
||
358 | |||
359 | #define DECAL \ |
||
360 | dest[RCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->red + \ |
||
361 | ((sample[ACOMP] + 1) * sample[RCOMP] << FIXED_SHIFT)) \ |
||
362 | >> (FIXED_SHIFT + 8); \ |
||
363 | dest[GCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->green + \ |
||
364 | ((sample[ACOMP] + 1) * sample[GCOMP] << FIXED_SHIFT)) \ |
||
365 | >> (FIXED_SHIFT + 8); \ |
||
366 | dest[BCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->blue + \ |
||
367 | ((sample[ACOMP] + 1) * sample[BCOMP] << FIXED_SHIFT)) \ |
||
368 | >> (FIXED_SHIFT + 8); \ |
||
369 | dest[ACOMP] = FixedToInt(span->alpha) |
||
370 | |||
371 | #define BLEND \ |
||
372 | dest[RCOMP] = ((CHAN_MAX - sample[RCOMP]) * span->red \ |
||
373 | + (sample[RCOMP] + 1) * info->er) >> (FIXED_SHIFT + 8); \ |
||
374 | dest[GCOMP] = ((CHAN_MAX - sample[GCOMP]) * span->green \ |
||
375 | + (sample[GCOMP] + 1) * info->eg) >> (FIXED_SHIFT + 8); \ |
||
376 | dest[BCOMP] = ((CHAN_MAX - sample[BCOMP]) * span->blue \ |
||
377 | + (sample[BCOMP] + 1) * info->eb) >> (FIXED_SHIFT + 8); \ |
||
378 | dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8) |
||
379 | |||
380 | #define REPLACE COPY_CHAN4(dest, sample) |
||
381 | |||
382 | #define ADD \ |
||
383 | { \ |
||
384 | GLint rSum = FixedToInt(span->red) + (GLint) sample[RCOMP]; \ |
||
385 | GLint gSum = FixedToInt(span->green) + (GLint) sample[GCOMP]; \ |
||
386 | GLint bSum = FixedToInt(span->blue) + (GLint) sample[BCOMP]; \ |
||
387 | dest[RCOMP] = MIN2(rSum, CHAN_MAX); \ |
||
388 | dest[GCOMP] = MIN2(gSum, CHAN_MAX); \ |
||
389 | dest[BCOMP] = MIN2(bSum, CHAN_MAX); \ |
||
390 | dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8); \ |
||
391 | } |
||
392 | |||
393 | /* shortcuts */ |
||
394 | |||
395 | #define NEAREST_RGB_REPLACE \ |
||
396 | NEAREST_RGB; \ |
||
397 | dest[0] = sample[0]; \ |
||
398 | dest[1] = sample[1]; \ |
||
399 | dest[2] = sample[2]; \ |
||
400 | dest[3] = FixedToInt(span->alpha); |
||
401 | |||
402 | #define NEAREST_RGBA_REPLACE COPY_CHAN4(dest, tex00) |
||
403 | |||
404 | #define SPAN_NEAREST(DO_TEX,COMP) \ |
||
405 | for (i = 0; i < span->end; i++) { \ |
||
406 | /* Isn't it necessary to use FixedFloor below?? */ \ |
||
407 | GLint s = FixedToInt(span->intTex[0]) & info->smask; \ |
||
408 | GLint t = FixedToInt(span->intTex[1]) & info->tmask; \ |
||
409 | GLint pos = (t << info->twidth_log2) + s; \ |
||
410 | const GLchan *tex00 = info->texture + COMP * pos; \ |
||
411 | DO_TEX; \ |
||
412 | span->red += span->redStep; \ |
||
413 | span->green += span->greenStep; \ |
||
414 | span->blue += span->blueStep; \ |
||
415 | span->alpha += span->alphaStep; \ |
||
416 | span->intTex[0] += span->intTexStep[0]; \ |
||
417 | span->intTex[1] += span->intTexStep[1]; \ |
||
418 | dest += 4; \ |
||
419 | } |
||
420 | |||
421 | #define SPAN_LINEAR(DO_TEX,COMP) \ |
||
422 | for (i = 0; i < span->end; i++) { \ |
||
423 | /* Isn't it necessary to use FixedFloor below?? */ \ |
||
424 | GLint s = FixedToInt(span->intTex[0]) & info->smask; \ |
||
425 | GLint t = FixedToInt(span->intTex[1]) & info->tmask; \ |
||
426 | GLfixed sf = span->intTex[0] & FIXED_FRAC_MASK; \ |
||
427 | GLfixed tf = span->intTex[1] & FIXED_FRAC_MASK; \ |
||
428 | GLfixed si = FIXED_FRAC_MASK - sf; \ |
||
429 | GLfixed ti = FIXED_FRAC_MASK - tf; \ |
||
430 | GLint pos = (t << info->twidth_log2) + s; \ |
||
431 | const GLchan *tex00 = info->texture + COMP * pos; \ |
||
432 | const GLchan *tex10 = tex00 + info->tbytesline; \ |
||
433 | const GLchan *tex01 = tex00 + COMP; \ |
||
434 | const GLchan *tex11 = tex10 + COMP; \ |
||
435 | (void) ti; \ |
||
436 | (void) si; \ |
||
437 | if (t == info->tmask) { \ |
||
438 | tex10 -= info->tsize; \ |
||
439 | tex11 -= info->tsize; \ |
||
440 | } \ |
||
441 | if (s == info->smask) { \ |
||
442 | tex01 -= info->tbytesline; \ |
||
443 | tex11 -= info->tbytesline; \ |
||
444 | } \ |
||
445 | DO_TEX; \ |
||
446 | span->red += span->redStep; \ |
||
447 | span->green += span->greenStep; \ |
||
448 | span->blue += span->blueStep; \ |
||
449 | span->alpha += span->alphaStep; \ |
||
450 | span->intTex[0] += span->intTexStep[0]; \ |
||
451 | span->intTex[1] += span->intTexStep[1]; \ |
||
452 | dest += 4; \ |
||
453 | } |
||
454 | |||
455 | |||
456 | GLuint i; |
||
457 | GLchan *dest = span->array->rgba[0]; |
||
458 | |||
459 | span->intTex[0] -= FIXED_HALF; |
||
460 | span->intTex[1] -= FIXED_HALF; |
||
461 | switch (info->filter) { |
||
462 | case GL_NEAREST: |
||
463 | switch (info->format) { |
||
464 | case GL_RGB: |
||
465 | switch (info->envmode) { |
||
466 | case GL_MODULATE: |
||
467 | SPAN_NEAREST(NEAREST_RGB;MODULATE,3); |
||
468 | break; |
||
469 | case GL_DECAL: |
||
470 | case GL_REPLACE: |
||
471 | SPAN_NEAREST(NEAREST_RGB_REPLACE,3); |
||
472 | break; |
||
473 | case GL_BLEND: |
||
474 | SPAN_NEAREST(NEAREST_RGB;BLEND,3); |
||
475 | break; |
||
476 | case GL_ADD: |
||
477 | SPAN_NEAREST(NEAREST_RGB;ADD,3); |
||
478 | break; |
||
479 | default: |
||
480 | _mesa_problem(ctx, "bad tex env mode in SPAN_LINEAR"); |
||
481 | return; |
||
482 | } |
||
483 | break; |
||
484 | case GL_RGBA: |
||
485 | switch(info->envmode) { |
||
486 | case GL_MODULATE: |
||
487 | SPAN_NEAREST(NEAREST_RGBA;MODULATE,4); |
||
488 | break; |
||
489 | case GL_DECAL: |
||
490 | SPAN_NEAREST(NEAREST_RGBA;DECAL,4); |
||
491 | break; |
||
492 | case GL_BLEND: |
||
493 | SPAN_NEAREST(NEAREST_RGBA;BLEND,4); |
||
494 | break; |
||
495 | case GL_ADD: |
||
496 | SPAN_NEAREST(NEAREST_RGBA;ADD,4); |
||
497 | break; |
||
498 | case GL_REPLACE: |
||
499 | SPAN_NEAREST(NEAREST_RGBA_REPLACE,4); |
||
500 | break; |
||
501 | default: |
||
502 | _mesa_problem(ctx, "bad tex env mode (2) in SPAN_LINEAR"); |
||
503 | return; |
||
504 | } |
||
505 | break; |
||
506 | } |
||
507 | break; |
||
508 | |||
509 | case GL_LINEAR: |
||
510 | span->intTex[0] -= FIXED_HALF; |
||
511 | span->intTex[1] -= FIXED_HALF; |
||
512 | switch (info->format) { |
||
513 | case GL_RGB: |
||
514 | switch (info->envmode) { |
||
515 | case GL_MODULATE: |
||
516 | SPAN_LINEAR(LINEAR_RGB;MODULATE,3); |
||
517 | break; |
||
518 | case GL_DECAL: |
||
519 | case GL_REPLACE: |
||
520 | SPAN_LINEAR(LINEAR_RGB;REPLACE,3); |
||
521 | break; |
||
522 | case GL_BLEND: |
||
523 | SPAN_LINEAR(LINEAR_RGB;BLEND,3); |
||
524 | break; |
||
525 | case GL_ADD: |
||
526 | SPAN_LINEAR(LINEAR_RGB;ADD,3); |
||
527 | break; |
||
528 | default: |
||
529 | _mesa_problem(ctx, "bad tex env mode (3) in SPAN_LINEAR"); |
||
530 | return; |
||
531 | } |
||
532 | break; |
||
533 | case GL_RGBA: |
||
534 | switch (info->envmode) { |
||
535 | case GL_MODULATE: |
||
536 | SPAN_LINEAR(LINEAR_RGBA;MODULATE,4); |
||
537 | break; |
||
538 | case GL_DECAL: |
||
539 | SPAN_LINEAR(LINEAR_RGBA;DECAL,4); |
||
540 | break; |
||
541 | case GL_BLEND: |
||
542 | SPAN_LINEAR(LINEAR_RGBA;BLEND,4); |
||
543 | break; |
||
544 | case GL_ADD: |
||
545 | SPAN_LINEAR(LINEAR_RGBA;ADD,4); |
||
546 | break; |
||
547 | case GL_REPLACE: |
||
548 | SPAN_LINEAR(LINEAR_RGBA;REPLACE,4); |
||
549 | break; |
||
550 | default: |
||
551 | _mesa_problem(ctx, "bad tex env mode (4) in SPAN_LINEAR"); |
||
552 | return; |
||
553 | } |
||
554 | break; |
||
555 | } |
||
556 | break; |
||
557 | } |
||
558 | span->interpMask &= ~SPAN_RGBA; |
||
559 | ASSERT(span->arrayMask & SPAN_RGBA); |
||
560 | _mesa_write_rgba_span(ctx, span); |
||
561 | |||
562 | #undef SPAN_NEAREST |
||
563 | #undef SPAN_LINEAR |
||
564 | } |
||
565 | |||
566 | |||
567 | |||
568 | /* |
||
569 | * Render an RGB/RGBA textured triangle without perspective correction. |
||
570 | */ |
||
571 | static void affine_textured_triangle( GLcontext *ctx, |
||
572 | const SWvertex *v0, |
||
573 | const SWvertex *v1, |
||
574 | const SWvertex *v2 ) |
||
575 | { |
||
576 | #define INTERP_Z 1 |
||
577 | #define INTERP_FOG 1 |
||
578 | #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE |
||
579 | #define INTERP_RGB 1 |
||
580 | #define INTERP_ALPHA 1 |
||
581 | #define INTERP_INT_TEX 1 |
||
582 | #define S_SCALE twidth |
||
583 | #define T_SCALE theight |
||
584 | |||
585 | #define SETUP_CODE \ |
||
586 | struct affine_info info; \ |
||
587 | struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ |
||
588 | struct gl_texture_object *obj = unit->Current2D; \ |
||
589 | const GLint b = obj->BaseLevel; \ |
||
590 | const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ |
||
591 | const GLfloat theight = (GLfloat) obj->Image[b]->Height; \ |
||
592 | info.texture = (const GLchan *) obj->Image[b]->Data; \ |
||
593 | info.twidth_log2 = obj->Image[b]->WidthLog2; \ |
||
594 | info.smask = obj->Image[b]->Width - 1; \ |
||
595 | info.tmask = obj->Image[b]->Height - 1; \ |
||
596 | info.format = obj->Image[b]->Format; \ |
||
597 | info.filter = obj->MinFilter; \ |
||
598 | info.envmode = unit->EnvMode; \ |
||
599 | span.arrayMask |= SPAN_RGBA; \ |
||
600 | \ |
||
601 | if (info.envmode == GL_BLEND) { \ |
||
602 | /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \ |
||
603 | info.er = FloatToFixed(unit->EnvColor[RCOMP] * CHAN_MAXF); \ |
||
604 | info.eg = FloatToFixed(unit->EnvColor[GCOMP] * CHAN_MAXF); \ |
||
605 | info.eb = FloatToFixed(unit->EnvColor[BCOMP] * CHAN_MAXF); \ |
||
606 | info.ea = FloatToFixed(unit->EnvColor[ACOMP] * CHAN_MAXF); \ |
||
607 | } \ |
||
608 | if (!info.texture) { \ |
||
609 | /* this shouldn't happen */ \ |
||
610 | return; \ |
||
611 | } \ |
||
612 | \ |
||
613 | switch (info.format) { \ |
||
614 | case GL_ALPHA: \ |
||
615 | case GL_LUMINANCE: \ |
||
616 | case GL_INTENSITY: \ |
||
617 | info.tbytesline = obj->Image[b]->Width; \ |
||
618 | break; \ |
||
619 | case GL_LUMINANCE_ALPHA: \ |
||
620 | info.tbytesline = obj->Image[b]->Width * 2; \ |
||
621 | break; \ |
||
622 | case GL_RGB: \ |
||
623 | info.tbytesline = obj->Image[b]->Width * 3; \ |
||
624 | break; \ |
||
625 | case GL_RGBA: \ |
||
626 | info.tbytesline = obj->Image[b]->Width * 4; \ |
||
627 | break; \ |
||
628 | default: \ |
||
629 | _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\ |
||
630 | return; \ |
||
631 | } \ |
||
632 | info.tsize = obj->Image[b]->Height * info.tbytesline; |
||
633 | |||
634 | #define RENDER_SPAN( span ) affine_span(ctx, &span, &info); |
||
635 | |||
636 | #include "s_tritemp.h" |
||
637 | |||
638 | } |
||
639 | |||
640 | |||
641 | |||
642 | struct persp_info |
||
643 | { |
||
644 | GLenum filter; |
||
645 | GLenum format; |
||
646 | GLenum envmode; |
||
647 | GLint smask, tmask; |
||
648 | GLint twidth_log2; |
||
649 | const GLchan *texture; |
||
650 | GLfixed er, eg, eb, ea; /* texture env color */ |
||
651 | GLint tbytesline, tsize; |
||
652 | }; |
||
653 | |||
654 | |||
655 | static INLINE void |
||
656 | fast_persp_span(GLcontext *ctx, struct sw_span *span, |
||
657 | struct persp_info *info) |
||
658 | { |
||
659 | GLchan sample[4]; /* the filtered texture sample */ |
||
660 | |||
661 | /* Instead of defining a function for each mode, a test is done |
||
662 | * between the outer and inner loops. This is to reduce code size |
||
663 | * and complexity. Observe that an optimizing compiler kills |
||
664 | * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST). |
||
665 | */ |
||
666 | #define SPAN_NEAREST(DO_TEX,COMP) \ |
||
667 | for (i = 0; i < span->end; i++) { \ |
||
668 | GLdouble invQ = tex_coord[2] ? \ |
||
669 | (1.0 / tex_coord[2]) : 1.0; \ |
||
670 | GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ); \ |
||
671 | GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ); \ |
||
672 | GLint s = IFLOOR(s_tmp) & info->smask; \ |
||
673 | GLint t = IFLOOR(t_tmp) & info->tmask; \ |
||
674 | GLint pos = (t << info->twidth_log2) + s; \ |
||
675 | const GLchan *tex00 = info->texture + COMP * pos; \ |
||
676 | DO_TEX; \ |
||
677 | span->red += span->redStep; \ |
||
678 | span->green += span->greenStep; \ |
||
679 | span->blue += span->blueStep; \ |
||
680 | span->alpha += span->alphaStep; \ |
||
681 | tex_coord[0] += tex_step[0]; \ |
||
682 | tex_coord[1] += tex_step[1]; \ |
||
683 | tex_coord[2] += tex_step[2]; \ |
||
684 | dest += 4; \ |
||
685 | } |
||
686 | |||
687 | #define SPAN_LINEAR(DO_TEX,COMP) \ |
||
688 | for (i = 0; i < span->end; i++) { \ |
||
689 | GLdouble invQ = tex_coord[2] ? \ |
||
690 | (1.0 / tex_coord[2]) : 1.0; \ |
||
691 | GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ); \ |
||
692 | GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ); \ |
||
693 | GLfixed s_fix = FloatToFixed(s_tmp) - FIXED_HALF; \ |
||
694 | GLfixed t_fix = FloatToFixed(t_tmp) - FIXED_HALF; \ |
||
695 | GLint s = FixedToInt(FixedFloor(s_fix)) & info->smask; \ |
||
696 | GLint t = FixedToInt(FixedFloor(t_fix)) & info->tmask; \ |
||
697 | GLfixed sf = s_fix & FIXED_FRAC_MASK; \ |
||
698 | GLfixed tf = t_fix & FIXED_FRAC_MASK; \ |
||
699 | GLfixed si = FIXED_FRAC_MASK - sf; \ |
||
700 | GLfixed ti = FIXED_FRAC_MASK - tf; \ |
||
701 | GLint pos = (t << info->twidth_log2) + s; \ |
||
702 | const GLchan *tex00 = info->texture + COMP * pos; \ |
||
703 | const GLchan *tex10 = tex00 + info->tbytesline; \ |
||
704 | const GLchan *tex01 = tex00 + COMP; \ |
||
705 | const GLchan *tex11 = tex10 + COMP; \ |
||
706 | (void) ti; \ |
||
707 | (void) si; \ |
||
708 | if (t == info->tmask) { \ |
||
709 | tex10 -= info->tsize; \ |
||
710 | tex11 -= info->tsize; \ |
||
711 | } \ |
||
712 | if (s == info->smask) { \ |
||
713 | tex01 -= info->tbytesline; \ |
||
714 | tex11 -= info->tbytesline; \ |
||
715 | } \ |
||
716 | DO_TEX; \ |
||
717 | span->red += span->redStep; \ |
||
718 | span->green += span->greenStep; \ |
||
719 | span->blue += span->blueStep; \ |
||
720 | span->alpha += span->alphaStep; \ |
||
721 | tex_coord[0] += tex_step[0]; \ |
||
722 | tex_coord[1] += tex_step[1]; \ |
||
723 | tex_coord[2] += tex_step[2]; \ |
||
724 | dest += 4; \ |
||
725 | } |
||
726 | |||
727 | GLuint i; |
||
728 | GLfloat tex_coord[3], tex_step[3]; |
||
729 | GLchan *dest = span->array->rgba[0]; |
||
730 | |||
731 | tex_coord[0] = span->tex[0][0] * (info->smask + 1); |
||
732 | tex_step[0] = span->texStepX[0][0] * (info->smask + 1); |
||
733 | tex_coord[1] = span->tex[0][1] * (info->tmask + 1); |
||
734 | tex_step[1] = span->texStepX[0][1] * (info->tmask + 1); |
||
735 | /* span->tex[0][2] only if 3D-texturing, here only 2D */ |
||
736 | tex_coord[2] = span->tex[0][3]; |
||
737 | tex_step[2] = span->texStepX[0][3]; |
||
738 | |||
739 | switch (info->filter) { |
||
740 | case GL_NEAREST: |
||
741 | switch (info->format) { |
||
742 | case GL_RGB: |
||
743 | switch (info->envmode) { |
||
744 | case GL_MODULATE: |
||
745 | SPAN_NEAREST(NEAREST_RGB;MODULATE,3); |
||
746 | break; |
||
747 | case GL_DECAL: |
||
748 | case GL_REPLACE: |
||
749 | SPAN_NEAREST(NEAREST_RGB_REPLACE,3); |
||
750 | break; |
||
751 | case GL_BLEND: |
||
752 | SPAN_NEAREST(NEAREST_RGB;BLEND,3); |
||
753 | break; |
||
754 | case GL_ADD: |
||
755 | SPAN_NEAREST(NEAREST_RGB;ADD,3); |
||
756 | break; |
||
757 | default: |
||
758 | _mesa_problem(ctx, "bad tex env mode (5) in SPAN_LINEAR"); |
||
759 | return; |
||
760 | } |
||
761 | break; |
||
762 | case GL_RGBA: |
||
763 | switch(info->envmode) { |
||
764 | case GL_MODULATE: |
||
765 | SPAN_NEAREST(NEAREST_RGBA;MODULATE,4); |
||
766 | break; |
||
767 | case GL_DECAL: |
||
768 | SPAN_NEAREST(NEAREST_RGBA;DECAL,4); |
||
769 | break; |
||
770 | case GL_BLEND: |
||
771 | SPAN_NEAREST(NEAREST_RGBA;BLEND,4); |
||
772 | break; |
||
773 | case GL_ADD: |
||
774 | SPAN_NEAREST(NEAREST_RGBA;ADD,4); |
||
775 | break; |
||
776 | case GL_REPLACE: |
||
777 | SPAN_NEAREST(NEAREST_RGBA_REPLACE,4); |
||
778 | break; |
||
779 | default: |
||
780 | _mesa_problem(ctx, "bad tex env mode (6) in SPAN_LINEAR"); |
||
781 | return; |
||
782 | } |
||
783 | break; |
||
784 | } |
||
785 | break; |
||
786 | |||
787 | case GL_LINEAR: |
||
788 | switch (info->format) { |
||
789 | case GL_RGB: |
||
790 | switch (info->envmode) { |
||
791 | case GL_MODULATE: |
||
792 | SPAN_LINEAR(LINEAR_RGB;MODULATE,3); |
||
793 | break; |
||
794 | case GL_DECAL: |
||
795 | case GL_REPLACE: |
||
796 | SPAN_LINEAR(LINEAR_RGB;REPLACE,3); |
||
797 | break; |
||
798 | case GL_BLEND: |
||
799 | SPAN_LINEAR(LINEAR_RGB;BLEND,3); |
||
800 | break; |
||
801 | case GL_ADD: |
||
802 | SPAN_LINEAR(LINEAR_RGB;ADD,3); |
||
803 | break; |
||
804 | default: |
||
805 | _mesa_problem(ctx, "bad tex env mode (7) in SPAN_LINEAR"); |
||
806 | return; |
||
807 | } |
||
808 | break; |
||
809 | case GL_RGBA: |
||
810 | switch (info->envmode) { |
||
811 | case GL_MODULATE: |
||
812 | SPAN_LINEAR(LINEAR_RGBA;MODULATE,4); |
||
813 | break; |
||
814 | case GL_DECAL: |
||
815 | SPAN_LINEAR(LINEAR_RGBA;DECAL,4); |
||
816 | break; |
||
817 | case GL_BLEND: |
||
818 | SPAN_LINEAR(LINEAR_RGBA;BLEND,4); |
||
819 | break; |
||
820 | case GL_ADD: |
||
821 | SPAN_LINEAR(LINEAR_RGBA;ADD,4); |
||
822 | break; |
||
823 | case GL_REPLACE: |
||
824 | SPAN_LINEAR(LINEAR_RGBA;REPLACE,4); |
||
825 | break; |
||
826 | default: |
||
827 | _mesa_problem(ctx, "bad tex env mode (8) in SPAN_LINEAR"); |
||
828 | return; |
||
829 | } |
||
830 | break; |
||
831 | } |
||
832 | break; |
||
833 | } |
||
834 | |||
835 | ASSERT(span->arrayMask & SPAN_RGBA); |
||
836 | _mesa_write_rgba_span(ctx, span); |
||
837 | |||
838 | #undef SPAN_NEAREST |
||
839 | #undef SPAN_LINEAR |
||
840 | } |
||
841 | |||
842 | |||
843 | /* |
||
844 | * Render an perspective corrected RGB/RGBA textured triangle. |
||
845 | * The Q (aka V in Mesa) coordinate must be zero such that the divide |
||
846 | * by interpolated Q/W comes out right. |
||
847 | * |
||
848 | */ |
||
849 | static void persp_textured_triangle( GLcontext *ctx, |
||
850 | const SWvertex *v0, |
||
851 | const SWvertex *v1, |
||
852 | const SWvertex *v2 ) |
||
853 | { |
||
854 | #define INTERP_Z 1 |
||
855 | #define INTERP_FOG 1 |
||
856 | #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE |
||
857 | #define INTERP_RGB 1 |
||
858 | #define INTERP_ALPHA 1 |
||
859 | #define INTERP_TEX 1 |
||
860 | |||
861 | #define SETUP_CODE \ |
||
862 | struct persp_info info; \ |
||
863 | const struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ |
||
864 | const struct gl_texture_object *obj = unit->Current2D; \ |
||
865 | const GLint b = obj->BaseLevel; \ |
||
866 | info.texture = (const GLchan *) obj->Image[b]->Data; \ |
||
867 | info.twidth_log2 = obj->Image[b]->WidthLog2; \ |
||
868 | info.smask = obj->Image[b]->Width - 1; \ |
||
869 | info.tmask = obj->Image[b]->Height - 1; \ |
||
870 | info.format = obj->Image[b]->Format; \ |
||
871 | info.filter = obj->MinFilter; \ |
||
872 | info.envmode = unit->EnvMode; \ |
||
873 | \ |
||
874 | if (info.envmode == GL_BLEND) { \ |
||
875 | /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \ |
||
876 | info.er = FloatToFixed(unit->EnvColor[RCOMP] * CHAN_MAXF); \ |
||
877 | info.eg = FloatToFixed(unit->EnvColor[GCOMP] * CHAN_MAXF); \ |
||
878 | info.eb = FloatToFixed(unit->EnvColor[BCOMP] * CHAN_MAXF); \ |
||
879 | info.ea = FloatToFixed(unit->EnvColor[ACOMP] * CHAN_MAXF); \ |
||
880 | } \ |
||
881 | if (!info.texture) { \ |
||
882 | /* this shouldn't happen */ \ |
||
883 | return; \ |
||
884 | } \ |
||
885 | \ |
||
886 | switch (info.format) { \ |
||
887 | case GL_ALPHA: \ |
||
888 | case GL_LUMINANCE: \ |
||
889 | case GL_INTENSITY: \ |
||
890 | info.tbytesline = obj->Image[b]->Width; \ |
||
891 | break; \ |
||
892 | case GL_LUMINANCE_ALPHA: \ |
||
893 | info.tbytesline = obj->Image[b]->Width * 2; \ |
||
894 | break; \ |
||
895 | case GL_RGB: \ |
||
896 | info.tbytesline = obj->Image[b]->Width * 3; \ |
||
897 | break; \ |
||
898 | case GL_RGBA: \ |
||
899 | info.tbytesline = obj->Image[b]->Width * 4; \ |
||
900 | break; \ |
||
901 | default: \ |
||
902 | _mesa_problem(NULL, "Bad texture format in persp_textured_triangle");\ |
||
903 | return; \ |
||
904 | } \ |
||
905 | info.tsize = obj->Image[b]->Height * info.tbytesline; |
||
906 | |||
907 | #define RENDER_SPAN( span ) \ |
||
908 | span.interpMask &= ~SPAN_RGBA; \ |
||
909 | span.arrayMask |= SPAN_RGBA; \ |
||
910 | fast_persp_span(ctx, &span, &info); |
||
911 | |||
912 | #include "s_tritemp.h" |
||
913 | |||
914 | } |
||
915 | |||
916 | |||
917 | #endif /* CHAN_BITS != GL_FLOAT */ |
||
918 | |||
919 | |||
920 | |||
921 | |||
922 | /* |
||
923 | * Render a smooth-shaded, textured, RGBA triangle. |
||
924 | * Interpolate S,T,R with perspective correction, w/out mipmapping. |
||
925 | */ |
||
926 | static void general_textured_triangle( GLcontext *ctx, |
||
927 | const SWvertex *v0, |
||
928 | const SWvertex *v1, |
||
929 | const SWvertex *v2 ) |
||
930 | { |
||
931 | #define INTERP_Z 1 |
||
932 | #define INTERP_FOG 1 |
||
933 | #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE |
||
934 | #define INTERP_RGB 1 |
||
935 | #define INTERP_SPEC 1 |
||
936 | #define INTERP_ALPHA 1 |
||
937 | #define INTERP_TEX 1 |
||
938 | |||
939 | #define RENDER_SPAN( span ) _mesa_write_texture_span(ctx, &span); |
||
940 | |||
941 | #include "s_tritemp.h" |
||
942 | } |
||
943 | |||
944 | |||
945 | |||
946 | /* |
||
947 | * This is the big one! |
||
948 | * Interpolate Z, RGB, Alpha, specular, fog, and N sets of texture coordinates. |
||
949 | * Yup, it's slow. |
||
950 | */ |
||
951 | static void |
||
952 | multitextured_triangle( GLcontext *ctx, |
||
953 | const SWvertex *v0, |
||
954 | const SWvertex *v1, |
||
955 | const SWvertex *v2 ) |
||
956 | { |
||
957 | |||
958 | #define INTERP_Z 1 |
||
959 | #define INTERP_FOG 1 |
||
960 | #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE |
||
961 | #define INTERP_RGB 1 |
||
962 | #define INTERP_ALPHA 1 |
||
963 | #define INTERP_SPEC 1 |
||
964 | #define INTERP_MULTITEX 1 |
||
965 | |||
966 | #define RENDER_SPAN( span ) _mesa_write_texture_span(ctx, &span); |
||
967 | |||
968 | #include "s_tritemp.h" |
||
969 | |||
970 | } |
||
971 | |||
972 | |||
973 | static void occlusion_zless_triangle( GLcontext *ctx, |
||
974 | const SWvertex *v0, |
||
975 | const SWvertex *v1, |
||
976 | const SWvertex *v2 ) |
||
977 | { |
||
978 | if (ctx->OcclusionResult) { |
||
979 | return; |
||
980 | } |
||
981 | |||
982 | #define DO_OCCLUSION_TEST |
||
983 | #define INTERP_Z 1 |
||
984 | #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE |
||
985 | |||
986 | #define RENDER_SPAN( span ) \ |
||
987 | GLuint i; \ |
||
988 | for (i = 0; i < span.end; i++) { \ |
||
989 | GLdepth z = FixedToDepth(span.z); \ |
||
990 | if (z < zRow[i]) { \ |
||
991 | ctx->OcclusionResult = GL_TRUE; \ |
||
992 | return; \ |
||
993 | } \ |
||
994 | span.z += span.zStep; \ |
||
995 | } |
||
996 | |||
997 | #include "s_tritemp.h" |
||
998 | } |
||
999 | |||
1000 | static void nodraw_triangle( GLcontext *ctx, |
||
1001 | const SWvertex *v0, |
||
1002 | const SWvertex *v1, |
||
1003 | const SWvertex *v2 ) |
||
1004 | { |
||
1005 | (void) (ctx && v0 && v1 && v2); |
||
1006 | } |
||
1007 | |||
1008 | |||
1009 | /* |
||
1010 | * This is used when separate specular color is enabled, but not |
||
1011 | * texturing. We add the specular color to the primary color, |
||
1012 | * draw the triangle, then restore the original primary color. |
||
1013 | * Inefficient, but seldom needed. |
||
1014 | */ |
||
1015 | void _swrast_add_spec_terms_triangle( GLcontext *ctx, |
||
1016 | const SWvertex *v0, |
||
1017 | const SWvertex *v1, |
||
1018 | const SWvertex *v2 ) |
||
1019 | { |
||
1020 | SWvertex *ncv0 = (SWvertex *)v0; /* drop const qualifier */ |
||
1021 | SWvertex *ncv1 = (SWvertex *)v1; |
||
1022 | SWvertex *ncv2 = (SWvertex *)v2; |
||
1023 | #if CHAN_TYPE == GL_FLOAT |
||
1024 | GLfloat rSum, gSum, bSum; |
||
1025 | #else |
||
1026 | GLint rSum, gSum, bSum; |
||
1027 | #endif |
||
1028 | GLchan c[3][4]; |
||
1029 | /* save original colors */ |
||
1030 | COPY_CHAN4( c[0], ncv0->color ); |
||
1031 | COPY_CHAN4( c[1], ncv1->color ); |
||
1032 | COPY_CHAN4( c[2], ncv2->color ); |
||
1033 | /* sum v0 */ |
||
1034 | rSum = ncv0->color[0] + ncv0->specular[0]; |
||
1035 | gSum = ncv0->color[1] + ncv0->specular[1]; |
||
1036 | bSum = ncv0->color[2] + ncv0->specular[2]; |
||
1037 | ncv0->color[0] = MIN2(rSum, CHAN_MAX); |
||
1038 | ncv0->color[1] = MIN2(gSum, CHAN_MAX); |
||
1039 | ncv0->color[2] = MIN2(bSum, CHAN_MAX); |
||
1040 | /* sum v1 */ |
||
1041 | rSum = ncv1->color[0] + ncv1->specular[0]; |
||
1042 | gSum = ncv1->color[1] + ncv1->specular[1]; |
||
1043 | bSum = ncv1->color[2] + ncv1->specular[2]; |
||
1044 | ncv1->color[0] = MIN2(rSum, CHAN_MAX); |
||
1045 | ncv1->color[1] = MIN2(gSum, CHAN_MAX); |
||
1046 | ncv1->color[2] = MIN2(bSum, CHAN_MAX); |
||
1047 | /* sum v2 */ |
||
1048 | rSum = ncv2->color[0] + ncv2->specular[0]; |
||
1049 | gSum = ncv2->color[1] + ncv2->specular[1]; |
||
1050 | bSum = ncv2->color[2] + ncv2->specular[2]; |
||
1051 | ncv2->color[0] = MIN2(rSum, CHAN_MAX); |
||
1052 | ncv2->color[1] = MIN2(gSum, CHAN_MAX); |
||
1053 | ncv2->color[2] = MIN2(bSum, CHAN_MAX); |
||
1054 | /* draw */ |
||
1055 | SWRAST_CONTEXT(ctx)->SpecTriangle( ctx, ncv0, ncv1, ncv2 ); |
||
1056 | /* restore original colors */ |
||
1057 | COPY_CHAN4( ncv0->color, c[0] ); |
||
1058 | COPY_CHAN4( ncv1->color, c[1] ); |
||
1059 | COPY_CHAN4( ncv2->color, c[2] ); |
||
1060 | } |
||
1061 | |||
1062 | |||
1063 | |||
1064 | #ifdef DEBUG |
||
1065 | |||
1066 | /* record the current triangle function name */ |
||
1067 | const char *_mesa_triFuncName = NULL; |
||
1068 | |||
1069 | #define USE(triFunc) \ |
||
1070 | do { \ |
||
1071 | _mesa_triFuncName = #triFunc; \ |
||
1072 | /*printf("%s\n", _mesa_triFuncName);*/ \ |
||
1073 | swrast->Triangle = triFunc; \ |
||
1074 | } while (0) |
||
1075 | |||
1076 | #else |
||
1077 | |||
1078 | #define USE(triFunc) swrast->Triangle = triFunc; |
||
1079 | |||
1080 | #endif |
||
1081 | |||
1082 | |||
1083 | |||
1084 | |||
1085 | /* |
||
1086 | * Determine which triangle rendering function to use given the current |
||
1087 | * rendering context. |
||
1088 | * |
||
1089 | * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or |
||
1090 | * remove tests to this code. |
||
1091 | */ |
||
1092 | void |
||
1093 | _swrast_choose_triangle( GLcontext *ctx ) |
||
1094 | { |
||
1095 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
1096 | const GLboolean rgbmode = ctx->Visual.rgbMode; |
||
1097 | |||
1098 | if (ctx->Polygon.CullFlag && |
||
1099 | ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) { |
||
1100 | USE(nodraw_triangle); |
||
1101 | return; |
||
1102 | } |
||
1103 | |||
1104 | if (ctx->RenderMode==GL_RENDER) { |
||
1105 | |||
1106 | if (ctx->Polygon.SmoothFlag) { |
||
1107 | _mesa_set_aa_triangle_function(ctx); |
||
1108 | ASSERT(swrast->Triangle); |
||
1109 | return; |
||
1110 | } |
||
1111 | |||
1112 | if (ctx->Depth.OcclusionTest && |
||
1113 | ctx->Depth.Test && |
||
1114 | ctx->Depth.Mask == GL_FALSE && |
||
1115 | ctx->Depth.Func == GL_LESS && |
||
1116 | !ctx->Stencil.Enabled) { |
||
1117 | if ((rgbmode && |
||
1118 | ctx->Color.ColorMask[0] == 0 && |
||
1119 | ctx->Color.ColorMask[1] == 0 && |
||
1120 | ctx->Color.ColorMask[2] == 0 && |
||
1121 | ctx->Color.ColorMask[3] == 0) |
||
1122 | || |
||
1123 | (!rgbmode && ctx->Color.IndexMask == 0)) { |
||
1124 | USE(occlusion_zless_triangle); |
||
1125 | return; |
||
1126 | } |
||
1127 | } |
||
1128 | |||
1129 | if (ctx->Texture._EnabledUnits) { |
||
1130 | /* Ugh, we do a _lot_ of tests to pick the best textured tri func */ |
||
1131 | const struct gl_texture_object *texObj2D; |
||
1132 | const struct gl_texture_image *texImg; |
||
1133 | GLenum minFilter, magFilter, envMode; |
||
1134 | GLint format; |
||
1135 | texObj2D = ctx->Texture.Unit[0].Current2D; |
||
1136 | texImg = texObj2D ? texObj2D->Image[texObj2D->BaseLevel] : NULL; |
||
1137 | format = texImg ? texImg->TexFormat->MesaFormat : -1; |
||
1138 | minFilter = texObj2D ? texObj2D->MinFilter : (GLenum) 0; |
||
1139 | magFilter = texObj2D ? texObj2D->MagFilter : (GLenum) 0; |
||
1140 | envMode = ctx->Texture.Unit[0].EnvMode; |
||
1141 | |||
1142 | /* First see if we can used an optimized 2-D texture function */ |
||
1143 | if (ctx->Texture._EnabledUnits == 1 |
||
1144 | && ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT |
||
1145 | && texObj2D->WrapS==GL_REPEAT |
||
1146 | && texObj2D->WrapT==GL_REPEAT |
||
1147 | && texImg->Border==0 |
||
1148 | && texImg->Width == texImg->RowStride |
||
1149 | && (format == MESA_FORMAT_RGB || format == MESA_FORMAT_RGBA) |
||
1150 | && minFilter == magFilter |
||
1151 | && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR |
||
1152 | && ctx->Texture.Unit[0].EnvMode != GL_COMBINE_EXT) { |
||
1153 | if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) { |
||
1154 | if (minFilter == GL_NEAREST |
||
1155 | && format == MESA_FORMAT_RGB |
||
1156 | && (envMode == GL_REPLACE || envMode == GL_DECAL) |
||
1157 | && ((swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT) |
||
1158 | && ctx->Depth.Func == GL_LESS |
||
1159 | && ctx->Depth.Mask == GL_TRUE) |
||
1160 | || swrast->_RasterMask == TEXTURE_BIT) |
||
1161 | && ctx->Polygon.StippleFlag == GL_FALSE) { |
||
1162 | if (swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)) { |
||
1163 | USE(simple_z_textured_triangle); |
||
1164 | } |
||
1165 | else { |
||
1166 | USE(simple_textured_triangle); |
||
1167 | } |
||
1168 | } |
||
1169 | else { |
||
1170 | #if (CHAN_BITS == 16 || CHAN_BITS == 32) |
||
1171 | USE(general_textured_triangle); |
||
1172 | #else |
||
1173 | USE(affine_textured_triangle); |
||
1174 | #endif |
||
1175 | } |
||
1176 | } |
||
1177 | else { |
||
1178 | #if (CHAN_BITS == 16 || CHAN_BITS == 32) |
||
1179 | USE(general_textured_triangle); |
||
1180 | #else |
||
1181 | USE(persp_textured_triangle); |
||
1182 | #endif |
||
1183 | } |
||
1184 | } |
||
1185 | else { |
||
1186 | /* general case textured triangles */ |
||
1187 | if (ctx->Texture._EnabledUnits > 1) { |
||
1188 | USE(multitextured_triangle); |
||
1189 | } |
||
1190 | else { |
||
1191 | USE(general_textured_triangle); |
||
1192 | } |
||
1193 | } |
||
1194 | } |
||
1195 | else { |
||
1196 | ASSERT(!ctx->Texture._EnabledUnits); |
||
1197 | if (ctx->Light.ShadeModel==GL_SMOOTH) { |
||
1198 | /* smooth shaded, no texturing, stippled or some raster ops */ |
||
1199 | if (rgbmode) { |
||
1200 | USE(smooth_rgba_triangle); |
||
1201 | } |
||
1202 | else { |
||
1203 | USE(smooth_ci_triangle); |
||
1204 | } |
||
1205 | } |
||
1206 | else { |
||
1207 | /* flat shaded, no texturing, stippled or some raster ops */ |
||
1208 | if (rgbmode) { |
||
1209 | USE(flat_rgba_triangle); |
||
1210 | } |
||
1211 | else { |
||
1212 | USE(flat_ci_triangle); |
||
1213 | } |
||
1214 | } |
||
1215 | } |
||
1216 | } |
||
1217 | else if (ctx->RenderMode==GL_FEEDBACK) { |
||
1218 | USE(_mesa_feedback_triangle); |
||
1219 | } |
||
1220 | else { |
||
1221 | /* GL_SELECT mode */ |
||
1222 | USE(_mesa_select_triangle); |
||
1223 | } |
||
1224 | } |