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