Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
57 | pj | 1 | /* $Id: s_texture.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 | #include "glheader.h" |
||
29 | #include "context.h" |
||
30 | #include "colormac.h" |
||
31 | #include "macros.h" |
||
32 | #include "mmath.h" |
||
33 | #include "imports.h" |
||
34 | #include "texformat.h" |
||
35 | #include "teximage.h" |
||
36 | |||
37 | #include "s_context.h" |
||
38 | #include "s_texture.h" |
||
39 | |||
40 | |||
41 | /* |
||
42 | * These values are used in the fixed-point arithmetic used |
||
43 | * for linear filtering. |
||
44 | */ |
||
45 | #define WEIGHT_SCALE 65536.0F |
||
46 | #define WEIGHT_SHIFT 16 |
||
47 | |||
48 | |||
49 | /* |
||
50 | * Used to compute texel locations for linear sampling. |
||
51 | * Input: |
||
52 | * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER_ARB |
||
53 | * S = texcoord in [0,1] |
||
54 | * SIZE = width (or height or depth) of texture |
||
55 | * Output: |
||
56 | * U = texcoord in [0, width] |
||
57 | * I0, I1 = two nearest texel indexes |
||
58 | */ |
||
59 | #define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1) \ |
||
60 | { \ |
||
61 | if (wrapMode == GL_REPEAT) { \ |
||
62 | U = S * SIZE - 0.5F; \ |
||
63 | I0 = IFLOOR(U) & (SIZE - 1); \ |
||
64 | I1 = (I0 + 1) & (SIZE - 1); \ |
||
65 | } \ |
||
66 | else if (wrapMode == GL_CLAMP_TO_EDGE) { \ |
||
67 | if (S <= 0.0F) \ |
||
68 | U = 0.0F; \ |
||
69 | else if (S >= 1.0F) \ |
||
70 | U = (GLfloat) SIZE; \ |
||
71 | else \ |
||
72 | U = S * SIZE; \ |
||
73 | U -= 0.5F; \ |
||
74 | I0 = IFLOOR(U); \ |
||
75 | I1 = I0 + 1; \ |
||
76 | if (I0 < 0) \ |
||
77 | I0 = 0; \ |
||
78 | if (I1 >= (GLint) SIZE) \ |
||
79 | I1 = SIZE - 1; \ |
||
80 | } \ |
||
81 | else if (wrapMode == GL_CLAMP_TO_BORDER_ARB) { \ |
||
82 | const GLfloat min = -1.0F / (2.0F * SIZE); \ |
||
83 | const GLfloat max = 1.0F - min; \ |
||
84 | if (S <= min) \ |
||
85 | U = min * SIZE; \ |
||
86 | else if (S >= max) \ |
||
87 | U = max * SIZE; \ |
||
88 | else \ |
||
89 | U = S * SIZE; \ |
||
90 | U -= 0.5F; \ |
||
91 | I0 = IFLOOR(U); \ |
||
92 | I1 = I0 + 1; \ |
||
93 | } \ |
||
94 | else if (wrapMode == GL_MIRRORED_REPEAT_ARB) { \ |
||
95 | const GLint flr = IFLOOR(S); \ |
||
96 | if (flr & 1) \ |
||
97 | U = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \ |
||
98 | else \ |
||
99 | U = S - (GLfloat) flr; /* flr is even */ \ |
||
100 | U = (U * SIZE) - 0.5F; \ |
||
101 | I0 = IFLOOR(U); \ |
||
102 | I1 = I0 + 1; \ |
||
103 | if (I0 < 0) \ |
||
104 | I0 = 0; \ |
||
105 | if (I1 >= (GLint) SIZE) \ |
||
106 | I1 = SIZE - 1; \ |
||
107 | } \ |
||
108 | else if (wrapMode == GL_MIRROR_CLAMP_ATI) { \ |
||
109 | U = (GLfloat) fabs(S); \ |
||
110 | if (U >= 1.0F) \ |
||
111 | U = (GLfloat) SIZE; \ |
||
112 | else \ |
||
113 | U *= SIZE; \ |
||
114 | U -= 0.5F; \ |
||
115 | I0 = IFLOOR(U); \ |
||
116 | I1 = I0 + 1; \ |
||
117 | } \ |
||
118 | else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_ATI) { \ |
||
119 | U = (GLfloat) fabs(S); \ |
||
120 | if (U >= 1.0F) \ |
||
121 | U = (GLfloat) SIZE; \ |
||
122 | else \ |
||
123 | U *= SIZE; \ |
||
124 | U -= 0.5F; \ |
||
125 | I0 = IFLOOR(U); \ |
||
126 | I1 = I0 + 1; \ |
||
127 | if (I0 < 0) \ |
||
128 | I0 = 0; \ |
||
129 | if (I1 >= (GLint) SIZE) \ |
||
130 | I1 = SIZE - 1; \ |
||
131 | } \ |
||
132 | else { \ |
||
133 | ASSERT(wrapMode == GL_CLAMP); \ |
||
134 | if (S <= 0.0F) \ |
||
135 | U = 0.0F; \ |
||
136 | else if (S >= 1.0F) \ |
||
137 | U = (GLfloat) SIZE; \ |
||
138 | else \ |
||
139 | U = S * SIZE; \ |
||
140 | U -= 0.5F; \ |
||
141 | I0 = IFLOOR(U); \ |
||
142 | I1 = I0 + 1; \ |
||
143 | } \ |
||
144 | } |
||
145 | |||
146 | |||
147 | /* |
||
148 | * Used to compute texel location for nearest sampling. |
||
149 | */ |
||
150 | #define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I) \ |
||
151 | { \ |
||
152 | if (wrapMode == GL_REPEAT) { \ |
||
153 | /* s limited to [0,1) */ \ |
||
154 | /* i limited to [0,size-1] */ \ |
||
155 | I = IFLOOR(S * SIZE); \ |
||
156 | I &= (SIZE - 1); \ |
||
157 | } \ |
||
158 | else if (wrapMode == GL_CLAMP_TO_EDGE) { \ |
||
159 | /* s limited to [min,max] */ \ |
||
160 | /* i limited to [0, size-1] */ \ |
||
161 | const GLfloat min = 1.0F / (2.0F * SIZE); \ |
||
162 | const GLfloat max = 1.0F - min; \ |
||
163 | if (S < min) \ |
||
164 | I = 0; \ |
||
165 | else if (S > max) \ |
||
166 | I = SIZE - 1; \ |
||
167 | else \ |
||
168 | I = IFLOOR(S * SIZE); \ |
||
169 | } \ |
||
170 | else if (wrapMode == GL_CLAMP_TO_BORDER_ARB) { \ |
||
171 | /* s limited to [min,max] */ \ |
||
172 | /* i limited to [-1, size] */ \ |
||
173 | const GLfloat min = -1.0F / (2.0F * SIZE); \ |
||
174 | const GLfloat max = 1.0F - min; \ |
||
175 | if (S <= min) \ |
||
176 | I = -1; \ |
||
177 | else if (S >= max) \ |
||
178 | I = SIZE; \ |
||
179 | else \ |
||
180 | I = IFLOOR(S * SIZE); \ |
||
181 | } \ |
||
182 | else if (wrapMode == GL_MIRRORED_REPEAT_ARB) { \ |
||
183 | const GLfloat min = 1.0F / (2.0F * SIZE); \ |
||
184 | const GLfloat max = 1.0F - min; \ |
||
185 | const GLint flr = IFLOOR(S); \ |
||
186 | GLfloat u; \ |
||
187 | if (flr & 1) \ |
||
188 | u = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \ |
||
189 | else \ |
||
190 | u = S - (GLfloat) flr; /* flr is even */ \ |
||
191 | if (u < min) \ |
||
192 | I = 0; \ |
||
193 | else if (u > max) \ |
||
194 | I = SIZE - 1; \ |
||
195 | else \ |
||
196 | I = IFLOOR(u * SIZE); \ |
||
197 | } \ |
||
198 | else if (wrapMode == GL_MIRROR_CLAMP_ATI) { \ |
||
199 | /* s limited to [0,1] */ \ |
||
200 | /* i limited to [0,size-1] */ \ |
||
201 | const GLfloat u = (GLfloat) fabs(S); \ |
||
202 | if (u <= 0.0F) \ |
||
203 | I = 0; \ |
||
204 | else if (u >= 1.0F) \ |
||
205 | I = SIZE - 1; \ |
||
206 | else \ |
||
207 | I = IFLOOR(u * SIZE); \ |
||
208 | } \ |
||
209 | else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_ATI) { \ |
||
210 | /* s limited to [min,max] */ \ |
||
211 | /* i limited to [0, size-1] */ \ |
||
212 | const GLfloat min = 1.0F / (2.0F * SIZE); \ |
||
213 | const GLfloat max = 1.0F - min; \ |
||
214 | const GLfloat u = (GLfloat) fabs(S); \ |
||
215 | if (u < min) \ |
||
216 | I = 0; \ |
||
217 | else if (u > max) \ |
||
218 | I = SIZE - 1; \ |
||
219 | else \ |
||
220 | I = IFLOOR(u * SIZE); \ |
||
221 | } \ |
||
222 | else { \ |
||
223 | ASSERT(wrapMode == GL_CLAMP); \ |
||
224 | /* s limited to [0,1] */ \ |
||
225 | /* i limited to [0,size-1] */ \ |
||
226 | if (S <= 0.0F) \ |
||
227 | I = 0; \ |
||
228 | else if (S >= 1.0F) \ |
||
229 | I = SIZE - 1; \ |
||
230 | else \ |
||
231 | I = IFLOOR(S * SIZE); \ |
||
232 | } \ |
||
233 | } |
||
234 | |||
235 | |||
236 | #define COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(S, U, SIZE, I0, I1) \ |
||
237 | { \ |
||
238 | U = S * SIZE - 0.5F; \ |
||
239 | I0 = IFLOOR(U) & (SIZE - 1); \ |
||
240 | I1 = (I0 + 1) & (SIZE - 1); \ |
||
241 | } |
||
242 | |||
243 | |||
244 | /* |
||
245 | * Compute linear mipmap levels for given lambda. |
||
246 | */ |
||
247 | #define COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level) \ |
||
248 | { \ |
||
249 | if (lambda < 0.0F) \ |
||
250 | level = tObj->BaseLevel; \ |
||
251 | else if (lambda > tObj->_MaxLambda) \ |
||
252 | level = (GLint) (tObj->BaseLevel + tObj->_MaxLambda); \ |
||
253 | else \ |
||
254 | level = (GLint) (tObj->BaseLevel + lambda); \ |
||
255 | } |
||
256 | |||
257 | |||
258 | /* |
||
259 | * Compute nearest mipmap level for given lambda. |
||
260 | */ |
||
261 | #define COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level) \ |
||
262 | { \ |
||
263 | GLfloat l; \ |
||
264 | if (lambda <= 0.5F) \ |
||
265 | l = 0.0F; \ |
||
266 | else if (lambda > tObj->_MaxLambda + 0.4999F) \ |
||
267 | l = tObj->_MaxLambda + 0.4999F; \ |
||
268 | else \ |
||
269 | l = lambda; \ |
||
270 | level = (GLint) (tObj->BaseLevel + l + 0.5F); \ |
||
271 | if (level > tObj->_MaxLevel) \ |
||
272 | level = tObj->_MaxLevel; \ |
||
273 | } |
||
274 | |||
275 | |||
276 | |||
277 | /* |
||
278 | * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes |
||
279 | * see 1-pixel bands of improperly weighted linear-sampled texels. The |
||
280 | * tests/texwrap.c demo is a good test. |
||
281 | * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0. |
||
282 | * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x). |
||
283 | */ |
||
284 | #define FRAC(f) ((f) - IFLOOR(f)) |
||
285 | |||
286 | |||
287 | |||
288 | /* |
||
289 | * Bitflags for texture border color sampling. |
||
290 | */ |
||
291 | #define I0BIT 1 |
||
292 | #define I1BIT 2 |
||
293 | #define J0BIT 4 |
||
294 | #define J1BIT 8 |
||
295 | #define K0BIT 16 |
||
296 | #define K1BIT 32 |
||
297 | |||
298 | |||
299 | |||
300 | /* |
||
301 | * Get texture palette entry. |
||
302 | */ |
||
303 | static void |
||
304 | palette_sample(const GLcontext *ctx, |
||
305 | const struct gl_texture_object *tObj, |
||
306 | GLint index, GLchan rgba[4] ) |
||
307 | { |
||
308 | const GLchan *palette; |
||
309 | GLenum format; |
||
310 | |||
311 | if (ctx->Texture.SharedPalette) { |
||
312 | ASSERT(!ctx->Texture.Palette.FloatTable); |
||
313 | palette = (const GLchan *) ctx->Texture.Palette.Table; |
||
314 | format = ctx->Texture.Palette.Format; |
||
315 | } |
||
316 | else { |
||
317 | ASSERT(!tObj->Palette.FloatTable); |
||
318 | palette = (const GLchan *) tObj->Palette.Table; |
||
319 | format = tObj->Palette.Format; |
||
320 | } |
||
321 | |||
322 | switch (format) { |
||
323 | case GL_ALPHA: |
||
324 | rgba[ACOMP] = palette[index]; |
||
325 | return; |
||
326 | case GL_LUMINANCE: |
||
327 | case GL_INTENSITY: |
||
328 | rgba[RCOMP] = palette[index]; |
||
329 | return; |
||
330 | case GL_LUMINANCE_ALPHA: |
||
331 | rgba[RCOMP] = palette[(index << 1) + 0]; |
||
332 | rgba[ACOMP] = palette[(index << 1) + 1]; |
||
333 | return; |
||
334 | case GL_RGB: |
||
335 | rgba[RCOMP] = palette[index * 3 + 0]; |
||
336 | rgba[GCOMP] = palette[index * 3 + 1]; |
||
337 | rgba[BCOMP] = palette[index * 3 + 2]; |
||
338 | return; |
||
339 | case GL_RGBA: |
||
340 | rgba[RCOMP] = palette[(index << 2) + 0]; |
||
341 | rgba[GCOMP] = palette[(index << 2) + 1]; |
||
342 | rgba[BCOMP] = palette[(index << 2) + 2]; |
||
343 | rgba[ACOMP] = palette[(index << 2) + 3]; |
||
344 | return; |
||
345 | default: |
||
346 | _mesa_problem(ctx, "Bad palette format in palette_sample"); |
||
347 | } |
||
348 | } |
||
349 | |||
350 | |||
351 | /* |
||
352 | * The lambda[] array values are always monotonic. Either the whole span |
||
353 | * will be minified, magnified, or split between the two. This function |
||
354 | * determines the subranges in [0, n-1] that are to be minified or magnified. |
||
355 | */ |
||
356 | static INLINE void |
||
357 | compute_min_mag_ranges( GLfloat minMagThresh, GLuint n, const GLfloat lambda[], |
||
358 | GLuint *minStart, GLuint *minEnd, |
||
359 | GLuint *magStart, GLuint *magEnd ) |
||
360 | { |
||
361 | ASSERT(lambda != NULL); |
||
362 | #if 0 |
||
363 | /* Verify that lambda[] is monotonous. |
||
364 | * We can't really use this because the inaccuracy in the LOG2 function |
||
365 | * causes this test to fail, yet the resulting texturing is correct. |
||
366 | */ |
||
367 | if (n > 1) { |
||
368 | GLuint i; |
||
369 | printf("lambda delta = %g\n", lambda[0] - lambda[n-1]); |
||
370 | if (lambda[0] >= lambda[n-1]) { /* decreasing */ |
||
371 | for (i = 0; i < n - 1; i++) { |
||
372 | ASSERT((GLint) (lambda[i] * 10) >= (GLint) (lambda[i+1] * 10)); |
||
373 | } |
||
374 | } |
||
375 | else { /* increasing */ |
||
376 | for (i = 0; i < n - 1; i++) { |
||
377 | ASSERT((GLint) (lambda[i] * 10) <= (GLint) (lambda[i+1] * 10)); |
||
378 | } |
||
379 | } |
||
380 | } |
||
381 | #endif /* DEBUG */ |
||
382 | |||
383 | /* since lambda is monotonous-array use this check first */ |
||
384 | if (lambda[0] <= minMagThresh && lambda[n-1] <= minMagThresh) { |
||
385 | /* magnification for whole span */ |
||
386 | *magStart = 0; |
||
387 | *magEnd = n; |
||
388 | *minStart = *minEnd = 0; |
||
389 | } |
||
390 | else if (lambda[0] > minMagThresh && lambda[n-1] > minMagThresh) { |
||
391 | /* minification for whole span */ |
||
392 | *minStart = 0; |
||
393 | *minEnd = n; |
||
394 | *magStart = *magEnd = 0; |
||
395 | } |
||
396 | else { |
||
397 | /* a mix of minification and magnification */ |
||
398 | GLuint i; |
||
399 | if (lambda[0] > minMagThresh) { |
||
400 | /* start with minification */ |
||
401 | for (i = 1; i < n; i++) { |
||
402 | if (lambda[i] <= minMagThresh) |
||
403 | break; |
||
404 | } |
||
405 | *minStart = 0; |
||
406 | *minEnd = i; |
||
407 | *magStart = i; |
||
408 | *magEnd = n; |
||
409 | } |
||
410 | else { |
||
411 | /* start with magnification */ |
||
412 | for (i = 1; i < n; i++) { |
||
413 | if (lambda[i] > minMagThresh) |
||
414 | break; |
||
415 | } |
||
416 | *magStart = 0; |
||
417 | *magEnd = i; |
||
418 | *minStart = i; |
||
419 | *minEnd = n; |
||
420 | } |
||
421 | } |
||
422 | |||
423 | #if 0 |
||
424 | /* Verify the min/mag Start/End values |
||
425 | * We don't use this either (see above) |
||
426 | */ |
||
427 | { |
||
428 | GLint i; |
||
429 | for (i = 0; i < n; i++) { |
||
430 | if (lambda[i] > minMagThresh) { |
||
431 | /* minification */ |
||
432 | ASSERT(i >= *minStart); |
||
433 | ASSERT(i < *minEnd); |
||
434 | } |
||
435 | else { |
||
436 | /* magnification */ |
||
437 | ASSERT(i >= *magStart); |
||
438 | ASSERT(i < *magEnd); |
||
439 | } |
||
440 | } |
||
441 | } |
||
442 | #endif |
||
443 | } |
||
444 | |||
445 | |||
446 | /**********************************************************************/ |
||
447 | /* 1-D Texture Sampling Functions */ |
||
448 | /**********************************************************************/ |
||
449 | |||
450 | /* |
||
451 | * Return the texture sample for coordinate (s) using GL_NEAREST filter. |
||
452 | */ |
||
453 | static void |
||
454 | sample_1d_nearest(GLcontext *ctx, |
||
455 | const struct gl_texture_object *tObj, |
||
456 | const struct gl_texture_image *img, |
||
457 | const GLfloat texcoord[4], GLchan rgba[4]) |
||
458 | { |
||
459 | const GLint width = img->Width2; /* without border, power of two */ |
||
460 | GLint i; |
||
461 | |||
462 | COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoord[0], width, i); |
||
463 | |||
464 | /* skip over the border, if any */ |
||
465 | i += img->Border; |
||
466 | |||
467 | if (i < 0 || i >= (GLint) img->Width) { |
||
468 | /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */ |
||
469 | COPY_CHAN4(rgba, tObj->_BorderChan); |
||
470 | } |
||
471 | else { |
||
472 | (*img->FetchTexel)(img, i, 0, 0, (GLvoid *) rgba); |
||
473 | if (img->Format == GL_COLOR_INDEX) { |
||
474 | palette_sample(ctx, tObj, rgba[0], rgba); |
||
475 | } |
||
476 | } |
||
477 | } |
||
478 | |||
479 | |||
480 | |||
481 | /* |
||
482 | * Return the texture sample for coordinate (s) using GL_LINEAR filter. |
||
483 | */ |
||
484 | static void |
||
485 | sample_1d_linear(GLcontext *ctx, |
||
486 | const struct gl_texture_object *tObj, |
||
487 | const struct gl_texture_image *img, |
||
488 | const GLfloat texcoord[4], GLchan rgba[4]) |
||
489 | { |
||
490 | const GLint width = img->Width2; |
||
491 | GLint i0, i1; |
||
492 | GLfloat u; |
||
493 | GLuint useBorderColor; |
||
494 | |||
495 | COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoord[0], u, width, i0, i1); |
||
496 | |||
497 | useBorderColor = 0; |
||
498 | if (img->Border) { |
||
499 | i0 += img->Border; |
||
500 | i1 += img->Border; |
||
501 | } |
||
502 | else { |
||
503 | if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT; |
||
504 | if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT; |
||
505 | } |
||
506 | |||
507 | { |
||
508 | const GLfloat a = FRAC(u); |
||
509 | |||
510 | #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT |
||
511 | const GLfloat w0 = (1.0F-a); |
||
512 | const GLfloat w1 = a ; |
||
513 | #else /* CHAN_BITS == 8 */ |
||
514 | /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */ |
||
515 | const GLint w0 = IROUND_POS((1.0F - a) * WEIGHT_SCALE); |
||
516 | const GLint w1 = IROUND_POS( a * WEIGHT_SCALE); |
||
517 | #endif |
||
518 | GLchan t0[4], t1[4]; /* texels */ |
||
519 | |||
520 | if (useBorderColor & I0BIT) { |
||
521 | COPY_CHAN4(t0, tObj->_BorderChan); |
||
522 | } |
||
523 | else { |
||
524 | (*img->FetchTexel)(img, i0, 0, 0, (GLvoid *) t0); |
||
525 | if (img->Format == GL_COLOR_INDEX) { |
||
526 | palette_sample(ctx, tObj, t0[0], t0); |
||
527 | } |
||
528 | } |
||
529 | if (useBorderColor & I1BIT) { |
||
530 | COPY_CHAN4(t1, tObj->_BorderChan); |
||
531 | } |
||
532 | else { |
||
533 | (*img->FetchTexel)(img, i1, 0, 0, (GLvoid *) t1); |
||
534 | if (img->Format == GL_COLOR_INDEX) { |
||
535 | palette_sample(ctx, tObj, t1[0], t1); |
||
536 | } |
||
537 | } |
||
538 | |||
539 | #if CHAN_TYPE == GL_FLOAT |
||
540 | rgba[0] = w0 * t0[0] + w1 * t1[0]; |
||
541 | rgba[1] = w0 * t0[1] + w1 * t1[1]; |
||
542 | rgba[2] = w0 * t0[2] + w1 * t1[2]; |
||
543 | rgba[3] = w0 * t0[3] + w1 * t1[3]; |
||
544 | #elif CHAN_TYPE == GL_UNSIGNED_SHORT |
||
545 | rgba[0] = (GLchan) (w0 * t0[0] + w1 * t1[0] + 0.5); |
||
546 | rgba[1] = (GLchan) (w0 * t0[1] + w1 * t1[1] + 0.5); |
||
547 | rgba[2] = (GLchan) (w0 * t0[2] + w1 * t1[2] + 0.5); |
||
548 | rgba[3] = (GLchan) (w0 * t0[3] + w1 * t1[3] + 0.5); |
||
549 | #else /* CHAN_BITS == 8 */ |
||
550 | rgba[0] = (GLchan) ((w0 * t0[0] + w1 * t1[0]) >> WEIGHT_SHIFT); |
||
551 | rgba[1] = (GLchan) ((w0 * t0[1] + w1 * t1[1]) >> WEIGHT_SHIFT); |
||
552 | rgba[2] = (GLchan) ((w0 * t0[2] + w1 * t1[2]) >> WEIGHT_SHIFT); |
||
553 | rgba[3] = (GLchan) ((w0 * t0[3] + w1 * t1[3]) >> WEIGHT_SHIFT); |
||
554 | #endif |
||
555 | |||
556 | } |
||
557 | } |
||
558 | |||
559 | |||
560 | static void |
||
561 | sample_1d_nearest_mipmap_nearest(GLcontext *ctx, |
||
562 | const struct gl_texture_object *tObj, |
||
563 | GLuint n, GLfloat texcoord[][4], |
||
564 | const GLfloat lambda[], GLchan rgba[][4]) |
||
565 | { |
||
566 | GLuint i; |
||
567 | ASSERT(lambda != NULL); |
||
568 | for (i = 0; i < n; i++) { |
||
569 | GLint level; |
||
570 | COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level); |
||
571 | sample_1d_nearest(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]); |
||
572 | } |
||
573 | } |
||
574 | |||
575 | |||
576 | static void |
||
577 | sample_1d_linear_mipmap_nearest(GLcontext *ctx, |
||
578 | const struct gl_texture_object *tObj, |
||
579 | GLuint n, GLfloat texcoord[][4], |
||
580 | const GLfloat lambda[], GLchan rgba[][4]) |
||
581 | { |
||
582 | GLuint i; |
||
583 | ASSERT(lambda != NULL); |
||
584 | for (i = 0; i < n; i++) { |
||
585 | GLint level; |
||
586 | COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level); |
||
587 | sample_1d_linear(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]); |
||
588 | } |
||
589 | } |
||
590 | |||
591 | |||
592 | |||
593 | /* |
||
594 | * This is really just needed in order to prevent warnings with some compilers. |
||
595 | */ |
||
596 | #if CHAN_TYPE == GL_FLOAT |
||
597 | #define CHAN_CAST |
||
598 | #else |
||
599 | #define CHAN_CAST (GLchan) (GLint) |
||
600 | #endif |
||
601 | |||
602 | |||
603 | static void |
||
604 | sample_1d_nearest_mipmap_linear(GLcontext *ctx, |
||
605 | const struct gl_texture_object *tObj, |
||
606 | GLuint n, GLfloat texcoord[][4], |
||
607 | const GLfloat lambda[], GLchan rgba[][4]) |
||
608 | { |
||
609 | GLuint i; |
||
610 | ASSERT(lambda != NULL); |
||
611 | for (i = 0; i < n; i++) { |
||
612 | GLint level; |
||
613 | COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level); |
||
614 | if (level >= tObj->_MaxLevel) { |
||
615 | sample_1d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel], |
||
616 | texcoord[i], rgba[i]); |
||
617 | } |
||
618 | else { |
||
619 | GLchan t0[4], t1[4]; |
||
620 | const GLfloat f = FRAC(lambda[i]); |
||
621 | sample_1d_nearest(ctx, tObj, tObj->Image[level ], texcoord[i], t0); |
||
622 | sample_1d_nearest(ctx, tObj, tObj->Image[level+1], texcoord[i], t1); |
||
623 | rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); |
||
624 | rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); |
||
625 | rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); |
||
626 | rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); |
||
627 | } |
||
628 | } |
||
629 | } |
||
630 | |||
631 | |||
632 | |||
633 | static void |
||
634 | sample_1d_linear_mipmap_linear(GLcontext *ctx, |
||
635 | const struct gl_texture_object *tObj, |
||
636 | GLuint n, GLfloat texcoord[][4], |
||
637 | const GLfloat lambda[], GLchan rgba[][4]) |
||
638 | { |
||
639 | GLuint i; |
||
640 | ASSERT(lambda != NULL); |
||
641 | for (i = 0; i < n; i++) { |
||
642 | GLint level; |
||
643 | COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level); |
||
644 | if (level >= tObj->_MaxLevel) { |
||
645 | sample_1d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel], |
||
646 | texcoord[i], rgba[i]); |
||
647 | } |
||
648 | else { |
||
649 | GLchan t0[4], t1[4]; |
||
650 | const GLfloat f = FRAC(lambda[i]); |
||
651 | sample_1d_linear(ctx, tObj, tObj->Image[level ], texcoord[i], t0); |
||
652 | sample_1d_linear(ctx, tObj, tObj->Image[level+1], texcoord[i], t1); |
||
653 | rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); |
||
654 | rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); |
||
655 | rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); |
||
656 | rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); |
||
657 | } |
||
658 | } |
||
659 | } |
||
660 | |||
661 | |||
662 | |||
663 | static void |
||
664 | sample_nearest_1d( GLcontext *ctx, GLuint texUnit, |
||
665 | const struct gl_texture_object *tObj, GLuint n, |
||
666 | GLfloat texcoords[][4], const GLfloat lambda[], |
||
667 | GLchan rgba[][4] ) |
||
668 | { |
||
669 | GLuint i; |
||
670 | struct gl_texture_image *image = tObj->Image[tObj->BaseLevel]; |
||
671 | (void) lambda; |
||
672 | for (i=0;i<n;i++) { |
||
673 | sample_1d_nearest(ctx, tObj, image, texcoords[i], rgba[i]); |
||
674 | } |
||
675 | } |
||
676 | |||
677 | |||
678 | |||
679 | static void |
||
680 | sample_linear_1d( GLcontext *ctx, GLuint texUnit, |
||
681 | const struct gl_texture_object *tObj, GLuint n, |
||
682 | GLfloat texcoords[][4], const GLfloat lambda[], |
||
683 | GLchan rgba[][4] ) |
||
684 | { |
||
685 | GLuint i; |
||
686 | struct gl_texture_image *image = tObj->Image[tObj->BaseLevel]; |
||
687 | (void) lambda; |
||
688 | for (i=0;i<n;i++) { |
||
689 | sample_1d_linear(ctx, tObj, image, texcoords[i], rgba[i]); |
||
690 | } |
||
691 | } |
||
692 | |||
693 | |||
694 | /* |
||
695 | * Given an (s) texture coordinate and lambda (level of detail) value, |
||
696 | * return a texture sample. |
||
697 | * |
||
698 | */ |
||
699 | static void |
||
700 | sample_lambda_1d( GLcontext *ctx, GLuint texUnit, |
||
701 | const struct gl_texture_object *tObj, GLuint n, |
||
702 | GLfloat texcoords[][4], |
||
703 | const GLfloat lambda[], GLchan rgba[][4] ) |
||
704 | { |
||
705 | GLuint minStart, minEnd; /* texels with minification */ |
||
706 | GLuint magStart, magEnd; /* texels with magnification */ |
||
707 | GLuint i; |
||
708 | |||
709 | ASSERT(lambda != NULL); |
||
710 | compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit], |
||
711 | n, lambda, &minStart, &minEnd, &magStart, &magEnd); |
||
712 | |||
713 | if (minStart < minEnd) { |
||
714 | /* do the minified texels */ |
||
715 | const GLuint m = minEnd - minStart; |
||
716 | switch (tObj->MinFilter) { |
||
717 | case GL_NEAREST: |
||
718 | for (i = minStart; i < minEnd; i++) |
||
719 | sample_1d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel], |
||
720 | texcoords[i], rgba[i]); |
||
721 | break; |
||
722 | case GL_LINEAR: |
||
723 | for (i = minStart; i < minEnd; i++) |
||
724 | sample_1d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel], |
||
725 | texcoords[i], rgba[i]); |
||
726 | break; |
||
727 | case GL_NEAREST_MIPMAP_NEAREST: |
||
728 | sample_1d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart, |
||
729 | lambda + minStart, rgba + minStart); |
||
730 | break; |
||
731 | case GL_LINEAR_MIPMAP_NEAREST: |
||
732 | sample_1d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart, |
||
733 | lambda + minStart, rgba + minStart); |
||
734 | break; |
||
735 | case GL_NEAREST_MIPMAP_LINEAR: |
||
736 | sample_1d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart, |
||
737 | lambda + minStart, rgba + minStart); |
||
738 | break; |
||
739 | case GL_LINEAR_MIPMAP_LINEAR: |
||
740 | sample_1d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart, |
||
741 | lambda + minStart, rgba + minStart); |
||
742 | break; |
||
743 | default: |
||
744 | _mesa_problem(ctx, "Bad min filter in sample_1d_texture"); |
||
745 | return; |
||
746 | } |
||
747 | } |
||
748 | |||
749 | if (magStart < magEnd) { |
||
750 | /* do the magnified texels */ |
||
751 | switch (tObj->MagFilter) { |
||
752 | case GL_NEAREST: |
||
753 | for (i = magStart; i < magEnd; i++) |
||
754 | sample_1d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel], |
||
755 | texcoords[i], rgba[i]); |
||
756 | break; |
||
757 | case GL_LINEAR: |
||
758 | for (i = magStart; i < magEnd; i++) |
||
759 | sample_1d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel], |
||
760 | texcoords[i], rgba[i]); |
||
761 | break; |
||
762 | default: |
||
763 | _mesa_problem(ctx, "Bad mag filter in sample_1d_texture"); |
||
764 | return; |
||
765 | } |
||
766 | } |
||
767 | } |
||
768 | |||
769 | |||
770 | /**********************************************************************/ |
||
771 | /* 2-D Texture Sampling Functions */ |
||
772 | /**********************************************************************/ |
||
773 | |||
774 | |||
775 | /* |
||
776 | * Return the texture sample for coordinate (s,t) using GL_NEAREST filter. |
||
777 | */ |
||
778 | static INLINE void |
||
779 | sample_2d_nearest(GLcontext *ctx, |
||
780 | const struct gl_texture_object *tObj, |
||
781 | const struct gl_texture_image *img, |
||
782 | const GLfloat texcoord[4], |
||
783 | GLchan rgba[]) |
||
784 | { |
||
785 | const GLint width = img->Width2; /* without border, power of two */ |
||
786 | const GLint height = img->Height2; /* without border, power of two */ |
||
787 | GLint i, j; |
||
788 | |||
789 | COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoord[0], width, i); |
||
790 | COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, texcoord[1], height, j); |
||
791 | |||
792 | /* skip over the border, if any */ |
||
793 | i += img->Border; |
||
794 | j += img->Border; |
||
795 | |||
796 | if (i < 0 || i >= (GLint) img->Width || j < 0 || j >= (GLint) img->Height) { |
||
797 | /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */ |
||
798 | COPY_CHAN4(rgba, tObj->_BorderChan); |
||
799 | } |
||
800 | else { |
||
801 | (*img->FetchTexel)(img, i, j, 0, (GLvoid *) rgba); |
||
802 | if (img->Format == GL_COLOR_INDEX) { |
||
803 | palette_sample(ctx, tObj, rgba[0], rgba); |
||
804 | } |
||
805 | } |
||
806 | } |
||
807 | |||
808 | |||
809 | |||
810 | /* |
||
811 | * Return the texture sample for coordinate (s,t) using GL_LINEAR filter. |
||
812 | * New sampling code contributed by Lynn Quam <quam@ai.sri.com>. |
||
813 | */ |
||
814 | static INLINE void |
||
815 | sample_2d_linear(GLcontext *ctx, |
||
816 | const struct gl_texture_object *tObj, |
||
817 | const struct gl_texture_image *img, |
||
818 | const GLfloat texcoord[4], |
||
819 | GLchan rgba[]) |
||
820 | { |
||
821 | const GLint width = img->Width2; |
||
822 | const GLint height = img->Height2; |
||
823 | GLint i0, j0, i1, j1; |
||
824 | GLuint useBorderColor; |
||
825 | GLfloat u, v; |
||
826 | |||
827 | COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoord[0], u, width, i0, i1); |
||
828 | COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, texcoord[1], v, height, j0, j1); |
||
829 | |||
830 | useBorderColor = 0; |
||
831 | if (img->Border) { |
||
832 | i0 += img->Border; |
||
833 | i1 += img->Border; |
||
834 | j0 += img->Border; |
||
835 | j1 += img->Border; |
||
836 | } |
||
837 | else { |
||
838 | if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT; |
||
839 | if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT; |
||
840 | if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT; |
||
841 | if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT; |
||
842 | } |
||
843 | |||
844 | { |
||
845 | const GLfloat a = FRAC(u); |
||
846 | const GLfloat b = FRAC(v); |
||
847 | |||
848 | #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT |
||
849 | const GLfloat w00 = (1.0F-a) * (1.0F-b); |
||
850 | const GLfloat w10 = a * (1.0F-b); |
||
851 | const GLfloat w01 = (1.0F-a) * b ; |
||
852 | const GLfloat w11 = a * b ; |
||
853 | #else /* CHAN_BITS == 8 */ |
||
854 | /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */ |
||
855 | const GLint w00 = IROUND_POS((1.0F-a) * (1.0F-b) * WEIGHT_SCALE); |
||
856 | const GLint w10 = IROUND_POS( a * (1.0F-b) * WEIGHT_SCALE); |
||
857 | const GLint w01 = IROUND_POS((1.0F-a) * b * WEIGHT_SCALE); |
||
858 | const GLint w11 = IROUND_POS( a * b * WEIGHT_SCALE); |
||
859 | #endif |
||
860 | GLchan t00[4]; |
||
861 | GLchan t10[4]; |
||
862 | GLchan t01[4]; |
||
863 | GLchan t11[4]; |
||
864 | |||
865 | if (useBorderColor & (I0BIT | J0BIT)) { |
||
866 | COPY_CHAN4(t00, tObj->_BorderChan); |
||
867 | } |
||
868 | else { |
||
869 | (*img->FetchTexel)(img, i0, j0, 0, (GLvoid *) t00); |
||
870 | if (img->Format == GL_COLOR_INDEX) { |
||
871 | palette_sample(ctx, tObj, t00[0], t00); |
||
872 | } |
||
873 | } |
||
874 | if (useBorderColor & (I1BIT | J0BIT)) { |
||
875 | COPY_CHAN4(t10, tObj->_BorderChan); |
||
876 | } |
||
877 | else { |
||
878 | (*img->FetchTexel)(img, i1, j0, 0, (GLvoid *) t10); |
||
879 | if (img->Format == GL_COLOR_INDEX) { |
||
880 | palette_sample(ctx, tObj, t10[0], t10); |
||
881 | } |
||
882 | } |
||
883 | if (useBorderColor & (I0BIT | J1BIT)) { |
||
884 | COPY_CHAN4(t01, tObj->_BorderChan); |
||
885 | } |
||
886 | else { |
||
887 | (*img->FetchTexel)(img, i0, j1, 0, (GLvoid *) t01); |
||
888 | if (img->Format == GL_COLOR_INDEX) { |
||
889 | palette_sample(ctx, tObj, t01[0], t01); |
||
890 | } |
||
891 | } |
||
892 | if (useBorderColor & (I1BIT | J1BIT)) { |
||
893 | COPY_CHAN4(t11, tObj->_BorderChan); |
||
894 | } |
||
895 | else { |
||
896 | (*img->FetchTexel)(img, i1, j1, 0, (GLvoid *) t11); |
||
897 | if (img->Format == GL_COLOR_INDEX) { |
||
898 | palette_sample(ctx, tObj, t11[0], t11); |
||
899 | } |
||
900 | } |
||
901 | #if CHAN_TYPE == GL_FLOAT |
||
902 | rgba[0] = w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0]; |
||
903 | rgba[1] = w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1]; |
||
904 | rgba[2] = w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2]; |
||
905 | rgba[3] = w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3]; |
||
906 | #elif CHAN_TYPE == GL_UNSIGNED_SHORT |
||
907 | rgba[0] = (GLchan) (w00 * t00[0] + w10 * t10[0] + |
||
908 | w01 * t01[0] + w11 * t11[0] + 0.5); |
||
909 | rgba[1] = (GLchan) (w00 * t00[1] + w10 * t10[1] + |
||
910 | w01 * t01[1] + w11 * t11[1] + 0.5); |
||
911 | rgba[2] = (GLchan) (w00 * t00[2] + w10 * t10[2] + |
||
912 | w01 * t01[2] + w11 * t11[2] + 0.5); |
||
913 | rgba[3] = (GLchan) (w00 * t00[3] + w10 * t10[3] + |
||
914 | w01 * t01[3] + w11 * t11[3] + 0.5); |
||
915 | #else /* CHAN_BITS == 8 */ |
||
916 | rgba[0] = (GLchan) ((w00 * t00[0] + w10 * t10[0] + |
||
917 | w01 * t01[0] + w11 * t11[0]) >> WEIGHT_SHIFT); |
||
918 | rgba[1] = (GLchan) ((w00 * t00[1] + w10 * t10[1] + |
||
919 | w01 * t01[1] + w11 * t11[1]) >> WEIGHT_SHIFT); |
||
920 | rgba[2] = (GLchan) ((w00 * t00[2] + w10 * t10[2] + |
||
921 | w01 * t01[2] + w11 * t11[2]) >> WEIGHT_SHIFT); |
||
922 | rgba[3] = (GLchan) ((w00 * t00[3] + w10 * t10[3] + |
||
923 | w01 * t01[3] + w11 * t11[3]) >> WEIGHT_SHIFT); |
||
924 | #endif |
||
925 | |||
926 | } |
||
927 | |||
928 | } |
||
929 | |||
930 | |||
931 | /* |
||
932 | * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT |
||
933 | * and we're not using a paletted texture. |
||
934 | */ |
||
935 | static INLINE void |
||
936 | sample_2d_linear_repeat(GLcontext *ctx, |
||
937 | const struct gl_texture_object *tObj, |
||
938 | const struct gl_texture_image *img, |
||
939 | const GLfloat texcoord[4], |
||
940 | GLchan rgba[]) |
||
941 | { |
||
942 | const GLint width = img->Width2; |
||
943 | const GLint height = img->Height2; |
||
944 | GLint i0, j0, i1, j1; |
||
945 | GLfloat u, v; |
||
946 | |||
947 | ASSERT(tObj->WrapS == GL_REPEAT); |
||
948 | ASSERT(tObj->WrapT == GL_REPEAT); |
||
949 | ASSERT(img->Border == 0); |
||
950 | ASSERT(img->Format != GL_COLOR_INDEX); |
||
951 | |||
952 | COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord[0], u, width, i0, i1); |
||
953 | COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord[1], v, height, j0, j1); |
||
954 | |||
955 | { |
||
956 | const GLfloat a = FRAC(u); |
||
957 | const GLfloat b = FRAC(v); |
||
958 | |||
959 | #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT |
||
960 | const GLfloat w00 = (1.0F-a) * (1.0F-b); |
||
961 | const GLfloat w10 = a * (1.0F-b); |
||
962 | const GLfloat w01 = (1.0F-a) * b ; |
||
963 | const GLfloat w11 = a * b ; |
||
964 | #else /* CHAN_BITS == 8 */ |
||
965 | /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */ |
||
966 | const GLint w00 = IROUND_POS((1.0F-a) * (1.0F-b) * WEIGHT_SCALE); |
||
967 | const GLint w10 = IROUND_POS( a * (1.0F-b) * WEIGHT_SCALE); |
||
968 | const GLint w01 = IROUND_POS((1.0F-a) * b * WEIGHT_SCALE); |
||
969 | const GLint w11 = IROUND_POS( a * b * WEIGHT_SCALE); |
||
970 | #endif |
||
971 | GLchan t00[4]; |
||
972 | GLchan t10[4]; |
||
973 | GLchan t01[4]; |
||
974 | GLchan t11[4]; |
||
975 | |||
976 | (*img->FetchTexel)(img, i0, j0, 0, (GLvoid *) t00); |
||
977 | (*img->FetchTexel)(img, i1, j0, 0, (GLvoid *) t10); |
||
978 | (*img->FetchTexel)(img, i0, j1, 0, (GLvoid *) t01); |
||
979 | (*img->FetchTexel)(img, i1, j1, 0, (GLvoid *) t11); |
||
980 | |||
981 | #if CHAN_TYPE == GL_FLOAT |
||
982 | rgba[0] = w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0]; |
||
983 | rgba[1] = w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1]; |
||
984 | rgba[2] = w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2]; |
||
985 | rgba[3] = w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3]; |
||
986 | #elif CHAN_TYPE == GL_UNSIGNED_SHORT |
||
987 | rgba[0] = (GLchan) (w00 * t00[0] + w10 * t10[0] + |
||
988 | w01 * t01[0] + w11 * t11[0] + 0.5); |
||
989 | rgba[1] = (GLchan) (w00 * t00[1] + w10 * t10[1] + |
||
990 | w01 * t01[1] + w11 * t11[1] + 0.5); |
||
991 | rgba[2] = (GLchan) (w00 * t00[2] + w10 * t10[2] + |
||
992 | w01 * t01[2] + w11 * t11[2] + 0.5); |
||
993 | rgba[3] = (GLchan) (w00 * t00[3] + w10 * t10[3] + |
||
994 | w01 * t01[3] + w11 * t11[3] + 0.5); |
||
995 | #else /* CHAN_BITS == 8 */ |
||
996 | rgba[0] = (GLchan) ((w00 * t00[0] + w10 * t10[0] + |
||
997 | w01 * t01[0] + w11 * t11[0]) >> WEIGHT_SHIFT); |
||
998 | rgba[1] = (GLchan) ((w00 * t00[1] + w10 * t10[1] + |
||
999 | w01 * t01[1] + w11 * t11[1]) >> WEIGHT_SHIFT); |
||
1000 | rgba[2] = (GLchan) ((w00 * t00[2] + w10 * t10[2] + |
||
1001 | w01 * t01[2] + w11 * t11[2]) >> WEIGHT_SHIFT); |
||
1002 | rgba[3] = (GLchan) ((w00 * t00[3] + w10 * t10[3] + |
||
1003 | w01 * t01[3] + w11 * t11[3]) >> WEIGHT_SHIFT); |
||
1004 | #endif |
||
1005 | |||
1006 | } |
||
1007 | |||
1008 | } |
||
1009 | |||
1010 | |||
1011 | |||
1012 | static void |
||
1013 | sample_2d_nearest_mipmap_nearest(GLcontext *ctx, |
||
1014 | const struct gl_texture_object *tObj, |
||
1015 | GLuint n, GLfloat texcoord[][4], |
||
1016 | const GLfloat lambda[], GLchan rgba[][4]) |
||
1017 | { |
||
1018 | GLuint i; |
||
1019 | for (i = 0; i < n; i++) { |
||
1020 | GLint level; |
||
1021 | COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level); |
||
1022 | sample_2d_nearest(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]); |
||
1023 | } |
||
1024 | } |
||
1025 | |||
1026 | |||
1027 | |||
1028 | static void |
||
1029 | sample_2d_linear_mipmap_nearest(GLcontext *ctx, |
||
1030 | const struct gl_texture_object *tObj, |
||
1031 | GLuint n, GLfloat texcoord[][4], |
||
1032 | const GLfloat lambda[], GLchan rgba[][4]) |
||
1033 | { |
||
1034 | GLuint i; |
||
1035 | ASSERT(lambda != NULL); |
||
1036 | for (i = 0; i < n; i++) { |
||
1037 | GLint level; |
||
1038 | COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level); |
||
1039 | sample_2d_linear(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]); |
||
1040 | } |
||
1041 | } |
||
1042 | |||
1043 | |||
1044 | |||
1045 | static void |
||
1046 | sample_2d_nearest_mipmap_linear(GLcontext *ctx, |
||
1047 | const struct gl_texture_object *tObj, |
||
1048 | GLuint n, GLfloat texcoord[][4], |
||
1049 | const GLfloat lambda[], GLchan rgba[][4]) |
||
1050 | { |
||
1051 | GLuint i; |
||
1052 | ASSERT(lambda != NULL); |
||
1053 | for (i = 0; i < n; i++) { |
||
1054 | GLint level; |
||
1055 | COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level); |
||
1056 | if (level >= tObj->_MaxLevel) { |
||
1057 | sample_2d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel], |
||
1058 | texcoord[i], rgba[i]); |
||
1059 | } |
||
1060 | else { |
||
1061 | GLchan t0[4], t1[4]; /* texels */ |
||
1062 | const GLfloat f = FRAC(lambda[i]); |
||
1063 | sample_2d_nearest(ctx, tObj, tObj->Image[level ], texcoord[i], t0); |
||
1064 | sample_2d_nearest(ctx, tObj, tObj->Image[level+1], texcoord[i], t1); |
||
1065 | rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); |
||
1066 | rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); |
||
1067 | rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); |
||
1068 | rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); |
||
1069 | } |
||
1070 | } |
||
1071 | } |
||
1072 | |||
1073 | |||
1074 | |||
1075 | /* Trilinear filtering */ |
||
1076 | static void |
||
1077 | sample_2d_linear_mipmap_linear( GLcontext *ctx, |
||
1078 | const struct gl_texture_object *tObj, |
||
1079 | GLuint n, GLfloat texcoord[][4], |
||
1080 | const GLfloat lambda[], GLchan rgba[][4] ) |
||
1081 | { |
||
1082 | GLuint i; |
||
1083 | ASSERT(lambda != NULL); |
||
1084 | for (i = 0; i < n; i++) { |
||
1085 | GLint level; |
||
1086 | COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level); |
||
1087 | if (level >= tObj->_MaxLevel) { |
||
1088 | sample_2d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel], |
||
1089 | texcoord[i], rgba[i]); |
||
1090 | } |
||
1091 | else { |
||
1092 | GLchan t0[4], t1[4]; /* texels */ |
||
1093 | const GLfloat f = FRAC(lambda[i]); |
||
1094 | sample_2d_linear(ctx, tObj, tObj->Image[level ], texcoord[i], t0); |
||
1095 | sample_2d_linear(ctx, tObj, tObj->Image[level+1], texcoord[i], t1); |
||
1096 | rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); |
||
1097 | rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); |
||
1098 | rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); |
||
1099 | rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); |
||
1100 | } |
||
1101 | } |
||
1102 | } |
||
1103 | |||
1104 | |||
1105 | static void |
||
1106 | sample_2d_linear_mipmap_linear_repeat( GLcontext *ctx, |
||
1107 | const struct gl_texture_object *tObj, |
||
1108 | GLuint n, GLfloat texcoord[][4], |
||
1109 | const GLfloat lambda[], GLchan rgba[][4] ) |
||
1110 | { |
||
1111 | GLuint i; |
||
1112 | ASSERT(lambda != NULL); |
||
1113 | ASSERT(tObj->WrapS == GL_REPEAT); |
||
1114 | ASSERT(tObj->WrapT == GL_REPEAT); |
||
1115 | for (i = 0; i < n; i++) { |
||
1116 | GLint level; |
||
1117 | COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level); |
||
1118 | if (level >= tObj->_MaxLevel) { |
||
1119 | sample_2d_linear_repeat(ctx, tObj, tObj->Image[tObj->_MaxLevel], |
||
1120 | texcoord[i], rgba[i]); |
||
1121 | } |
||
1122 | else { |
||
1123 | GLchan t0[4], t1[4]; /* texels */ |
||
1124 | const GLfloat f = FRAC(lambda[i]); |
||
1125 | sample_2d_linear_repeat(ctx, tObj, tObj->Image[level ], texcoord[i], t0); |
||
1126 | sample_2d_linear_repeat(ctx, tObj, tObj->Image[level+1], texcoord[i], t1); |
||
1127 | rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); |
||
1128 | rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); |
||
1129 | rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); |
||
1130 | rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); |
||
1131 | } |
||
1132 | } |
||
1133 | } |
||
1134 | |||
1135 | |||
1136 | static void |
||
1137 | sample_nearest_2d( GLcontext *ctx, GLuint texUnit, |
||
1138 | const struct gl_texture_object *tObj, GLuint n, |
||
1139 | GLfloat texcoords[][4], |
||
1140 | const GLfloat lambda[], GLchan rgba[][4] ) |
||
1141 | { |
||
1142 | GLuint i; |
||
1143 | struct gl_texture_image *image = tObj->Image[tObj->BaseLevel]; |
||
1144 | (void) lambda; |
||
1145 | for (i=0;i<n;i++) { |
||
1146 | sample_2d_nearest(ctx, tObj, image, texcoords[i], rgba[i]); |
||
1147 | } |
||
1148 | } |
||
1149 | |||
1150 | |||
1151 | |||
1152 | static void |
||
1153 | sample_linear_2d( GLcontext *ctx, GLuint texUnit, |
||
1154 | const struct gl_texture_object *tObj, GLuint n, |
||
1155 | GLfloat texcoords[][4], |
||
1156 | const GLfloat lambda[], GLchan rgba[][4] ) |
||
1157 | { |
||
1158 | GLuint i; |
||
1159 | struct gl_texture_image *image = tObj->Image[tObj->BaseLevel]; |
||
1160 | (void) lambda; |
||
1161 | for (i=0;i<n;i++) { |
||
1162 | sample_2d_linear(ctx, tObj, image, texcoords[i], rgba[i]); |
||
1163 | } |
||
1164 | } |
||
1165 | |||
1166 | |||
1167 | /* |
||
1168 | * Optimized 2-D texture sampling: |
||
1169 | * S and T wrap mode == GL_REPEAT |
||
1170 | * GL_NEAREST min/mag filter |
||
1171 | * No border, |
||
1172 | * RowStride == Width, |
||
1173 | * Format = GL_RGB |
||
1174 | */ |
||
1175 | static void |
||
1176 | opt_sample_rgb_2d( GLcontext *ctx, GLuint texUnit, |
||
1177 | const struct gl_texture_object *tObj, |
||
1178 | GLuint n, GLfloat texcoords[][4], |
||
1179 | const GLfloat lambda[], GLchan rgba[][4] ) |
||
1180 | { |
||
1181 | const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel]; |
||
1182 | const GLfloat width = (GLfloat) img->Width; |
||
1183 | const GLfloat height = (GLfloat) img->Height; |
||
1184 | const GLint colMask = img->Width - 1; |
||
1185 | const GLint rowMask = img->Height - 1; |
||
1186 | const GLint shift = img->WidthLog2; |
||
1187 | GLuint k; |
||
1188 | (void) lambda; |
||
1189 | ASSERT(tObj->WrapS==GL_REPEAT); |
||
1190 | ASSERT(tObj->WrapT==GL_REPEAT); |
||
1191 | ASSERT(img->Border==0); |
||
1192 | ASSERT(img->Format==GL_RGB); |
||
1193 | |||
1194 | for (k=0; k<n; k++) { |
||
1195 | GLint i = IFLOOR(texcoords[k][0] * width) & colMask; |
||
1196 | GLint j = IFLOOR(texcoords[k][1] * height) & rowMask; |
||
1197 | GLint pos = (j << shift) | i; |
||
1198 | GLchan *texel = ((GLchan *) img->Data) + 3*pos; |
||
1199 | rgba[k][RCOMP] = texel[0]; |
||
1200 | rgba[k][GCOMP] = texel[1]; |
||
1201 | rgba[k][BCOMP] = texel[2]; |
||
1202 | } |
||
1203 | } |
||
1204 | |||
1205 | |||
1206 | /* |
||
1207 | * Optimized 2-D texture sampling: |
||
1208 | * S and T wrap mode == GL_REPEAT |
||
1209 | * GL_NEAREST min/mag filter |
||
1210 | * No border |
||
1211 | * RowStride == Width, |
||
1212 | * Format = GL_RGBA |
||
1213 | */ |
||
1214 | static void |
||
1215 | opt_sample_rgba_2d( GLcontext *ctx, GLuint texUnit, |
||
1216 | const struct gl_texture_object *tObj, |
||
1217 | GLuint n, GLfloat texcoords[][4], |
||
1218 | const GLfloat lambda[], GLchan rgba[][4] ) |
||
1219 | { |
||
1220 | const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel]; |
||
1221 | const GLfloat width = (GLfloat) img->Width; |
||
1222 | const GLfloat height = (GLfloat) img->Height; |
||
1223 | const GLint colMask = img->Width - 1; |
||
1224 | const GLint rowMask = img->Height - 1; |
||
1225 | const GLint shift = img->WidthLog2; |
||
1226 | GLuint i; |
||
1227 | (void) lambda; |
||
1228 | ASSERT(tObj->WrapS==GL_REPEAT); |
||
1229 | ASSERT(tObj->WrapT==GL_REPEAT); |
||
1230 | ASSERT(img->Border==0); |
||
1231 | ASSERT(img->Format==GL_RGBA); |
||
1232 | |||
1233 | for (i = 0; i < n; i++) { |
||
1234 | const GLint col = IFLOOR(texcoords[i][0] * width) & colMask; |
||
1235 | const GLint row = IFLOOR(texcoords[i][1] * height) & rowMask; |
||
1236 | const GLint pos = (row << shift) | col; |
||
1237 | const GLchan *texel = ((GLchan *) img->Data) + (pos << 2); /* pos*4 */ |
||
1238 | COPY_CHAN4(rgba[i], texel); |
||
1239 | } |
||
1240 | } |
||
1241 | |||
1242 | |||
1243 | /* |
||
1244 | * Given an array of texture coordinate and lambda (level of detail) |
||
1245 | * values, return an array of texture sample. |
||
1246 | */ |
||
1247 | static void |
||
1248 | sample_lambda_2d( GLcontext *ctx, GLuint texUnit, |
||
1249 | const struct gl_texture_object *tObj, |
||
1250 | GLuint n, GLfloat texcoords[][4], |
||
1251 | const GLfloat lambda[], GLchan rgba[][4] ) |
||
1252 | { |
||
1253 | const struct gl_texture_image *tImg = tObj->Image[tObj->BaseLevel]; |
||
1254 | GLuint minStart, minEnd; /* texels with minification */ |
||
1255 | GLuint magStart, magEnd; /* texels with magnification */ |
||
1256 | |||
1257 | const GLboolean repeatNoBorder = (tObj->WrapS == GL_REPEAT) |
||
1258 | && (tObj->WrapT == GL_REPEAT) |
||
1259 | && (tImg->Border == 0 && (tImg->Width == tImg->RowStride)) |
||
1260 | && (tImg->Format != GL_COLOR_INDEX); |
||
1261 | |||
1262 | ASSERT(lambda != NULL); |
||
1263 | compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit], |
||
1264 | n, lambda, &minStart, &minEnd, &magStart, &magEnd); |
||
1265 | |||
1266 | if (minStart < minEnd) { |
||
1267 | /* do the minified texels */ |
||
1268 | const GLuint m = minEnd - minStart; |
||
1269 | switch (tObj->MinFilter) { |
||
1270 | case GL_NEAREST: |
||
1271 | if (repeatNoBorder) { |
||
1272 | switch (tImg->Format) { |
||
1273 | case GL_RGB: |
||
1274 | opt_sample_rgb_2d(ctx, texUnit, tObj, m, texcoords + minStart, |
||
1275 | NULL, rgba + minStart); |
||
1276 | break; |
||
1277 | case GL_RGBA: |
||
1278 | opt_sample_rgba_2d(ctx, texUnit, tObj, m, texcoords + minStart, |
||
1279 | NULL, rgba + minStart); |
||
1280 | break; |
||
1281 | default: |
||
1282 | sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + minStart, |
||
1283 | NULL, rgba + minStart ); |
||
1284 | } |
||
1285 | } |
||
1286 | else { |
||
1287 | sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + minStart, |
||
1288 | NULL, rgba + minStart); |
||
1289 | } |
||
1290 | break; |
||
1291 | case GL_LINEAR: |
||
1292 | sample_linear_2d(ctx, texUnit, tObj, m, texcoords + minStart, |
||
1293 | NULL, rgba + minStart); |
||
1294 | break; |
||
1295 | case GL_NEAREST_MIPMAP_NEAREST: |
||
1296 | sample_2d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart, |
||
1297 | lambda + minStart, rgba + minStart); |
||
1298 | break; |
||
1299 | case GL_LINEAR_MIPMAP_NEAREST: |
||
1300 | sample_2d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart, |
||
1301 | lambda + minStart, rgba + minStart); |
||
1302 | break; |
||
1303 | case GL_NEAREST_MIPMAP_LINEAR: |
||
1304 | sample_2d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart, |
||
1305 | lambda + minStart, rgba + minStart); |
||
1306 | break; |
||
1307 | case GL_LINEAR_MIPMAP_LINEAR: |
||
1308 | if (repeatNoBorder) |
||
1309 | sample_2d_linear_mipmap_linear_repeat(ctx, tObj, m, |
||
1310 | texcoords + minStart, lambda + minStart, rgba + minStart); |
||
1311 | else |
||
1312 | sample_2d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart, |
||
1313 | lambda + minStart, rgba + minStart); |
||
1314 | break; |
||
1315 | default: |
||
1316 | _mesa_problem(ctx, "Bad min filter in sample_2d_texture"); |
||
1317 | return; |
||
1318 | } |
||
1319 | } |
||
1320 | |||
1321 | if (magStart < magEnd) { |
||
1322 | /* do the magnified texels */ |
||
1323 | const GLuint m = magEnd - magStart; |
||
1324 | |||
1325 | switch (tObj->MagFilter) { |
||
1326 | case GL_NEAREST: |
||
1327 | if (repeatNoBorder) { |
||
1328 | switch (tImg->Format) { |
||
1329 | case GL_RGB: |
||
1330 | opt_sample_rgb_2d(ctx, texUnit, tObj, m, texcoords + magStart, |
||
1331 | NULL, rgba + magStart); |
||
1332 | break; |
||
1333 | case GL_RGBA: |
||
1334 | opt_sample_rgba_2d(ctx, texUnit, tObj, m, texcoords + magStart, |
||
1335 | NULL, rgba + magStart); |
||
1336 | break; |
||
1337 | default: |
||
1338 | sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + magStart, |
||
1339 | NULL, rgba + magStart ); |
||
1340 | } |
||
1341 | } |
||
1342 | else { |
||
1343 | sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + magStart, |
||
1344 | NULL, rgba + magStart); |
||
1345 | } |
||
1346 | break; |
||
1347 | case GL_LINEAR: |
||
1348 | sample_linear_2d(ctx, texUnit, tObj, m, texcoords + magStart, |
||
1349 | NULL, rgba + magStart); |
||
1350 | break; |
||
1351 | default: |
||
1352 | _mesa_problem(ctx, "Bad mag filter in sample_lambda_2d"); |
||
1353 | } |
||
1354 | } |
||
1355 | } |
||
1356 | |||
1357 | |||
1358 | |||
1359 | /**********************************************************************/ |
||
1360 | /* 3-D Texture Sampling Functions */ |
||
1361 | /**********************************************************************/ |
||
1362 | |||
1363 | /* |
||
1364 | * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter. |
||
1365 | */ |
||
1366 | static void |
||
1367 | sample_3d_nearest(GLcontext *ctx, |
||
1368 | const struct gl_texture_object *tObj, |
||
1369 | const struct gl_texture_image *img, |
||
1370 | const GLfloat texcoord[4], |
||
1371 | GLchan rgba[4]) |
||
1372 | { |
||
1373 | const GLint width = img->Width2; /* without border, power of two */ |
||
1374 | const GLint height = img->Height2; /* without border, power of two */ |
||
1375 | const GLint depth = img->Depth2; /* without border, power of two */ |
||
1376 | GLint i, j, k; |
||
1377 | |||
1378 | COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoord[0], width, i); |
||
1379 | COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, texcoord[1], height, j); |
||
1380 | COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapR, texcoord[2], depth, k); |
||
1381 | |||
1382 | if (i < 0 || i >= (GLint) img->Width || |
||
1383 | j < 0 || j >= (GLint) img->Height || |
||
1384 | k < 0 || k >= (GLint) img->Depth) { |
||
1385 | /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */ |
||
1386 | COPY_CHAN4(rgba, tObj->_BorderChan); |
||
1387 | } |
||
1388 | else { |
||
1389 | (*img->FetchTexel)(img, i, j, k, (GLvoid *) rgba); |
||
1390 | if (img->Format == GL_COLOR_INDEX) { |
||
1391 | palette_sample(ctx, tObj, rgba[0], rgba); |
||
1392 | } |
||
1393 | } |
||
1394 | } |
||
1395 | |||
1396 | |||
1397 | |||
1398 | /* |
||
1399 | * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter. |
||
1400 | */ |
||
1401 | static void |
||
1402 | sample_3d_linear(GLcontext *ctx, |
||
1403 | const struct gl_texture_object *tObj, |
||
1404 | const struct gl_texture_image *img, |
||
1405 | const GLfloat texcoord[4], |
||
1406 | GLchan rgba[4]) |
||
1407 | { |
||
1408 | const GLint width = img->Width2; |
||
1409 | const GLint height = img->Height2; |
||
1410 | const GLint depth = img->Depth2; |
||
1411 | GLint i0, j0, k0, i1, j1, k1; |
||
1412 | GLuint useBorderColor; |
||
1413 | GLfloat u, v, w; |
||
1414 | |||
1415 | COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoord[0], u, width, i0, i1); |
||
1416 | COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, texcoord[1], v, height, j0, j1); |
||
1417 | COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapR, texcoord[2], w, depth, k0, k1); |
||
1418 | |||
1419 | useBorderColor = 0; |
||
1420 | if (img->Border) { |
||
1421 | i0 += img->Border; |
||
1422 | i1 += img->Border; |
||
1423 | j0 += img->Border; |
||
1424 | j1 += img->Border; |
||
1425 | k0 += img->Border; |
||
1426 | k1 += img->Border; |
||
1427 | } |
||
1428 | else { |
||
1429 | /* check if sampling texture border color */ |
||
1430 | if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT; |
||
1431 | if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT; |
||
1432 | if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT; |
||
1433 | if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT; |
||
1434 | if (k0 < 0 || k0 >= depth) useBorderColor |= K0BIT; |
||
1435 | if (k1 < 0 || k1 >= depth) useBorderColor |= K1BIT; |
||
1436 | } |
||
1437 | |||
1438 | { |
||
1439 | const GLfloat a = FRAC(u); |
||
1440 | const GLfloat b = FRAC(v); |
||
1441 | const GLfloat c = FRAC(w); |
||
1442 | |||
1443 | #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT |
||
1444 | /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */ |
||
1445 | GLfloat w000 = (1.0F-a) * (1.0F-b) * (1.0F-c); |
||
1446 | GLfloat w100 = a * (1.0F-b) * (1.0F-c); |
||
1447 | GLfloat w010 = (1.0F-a) * b * (1.0F-c); |
||
1448 | GLfloat w110 = a * b * (1.0F-c); |
||
1449 | GLfloat w001 = (1.0F-a) * (1.0F-b) * c ; |
||
1450 | GLfloat w101 = a * (1.0F-b) * c ; |
||
1451 | GLfloat w011 = (1.0F-a) * b * c ; |
||
1452 | GLfloat w111 = a * b * c ; |
||
1453 | #else /* CHAN_BITS == 8 */ |
||
1454 | /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */ |
||
1455 | GLint w000 = IROUND_POS((1.0F-a) * (1.0F-b) * (1.0F-c) * WEIGHT_SCALE); |
||
1456 | GLint w100 = IROUND_POS( a * (1.0F-b) * (1.0F-c) * WEIGHT_SCALE); |
||
1457 | GLint w010 = IROUND_POS((1.0F-a) * b * (1.0F-c) * WEIGHT_SCALE); |
||
1458 | GLint w110 = IROUND_POS( a * b * (1.0F-c) * WEIGHT_SCALE); |
||
1459 | GLint w001 = IROUND_POS((1.0F-a) * (1.0F-b) * c * WEIGHT_SCALE); |
||
1460 | GLint w101 = IROUND_POS( a * (1.0F-b) * c * WEIGHT_SCALE); |
||
1461 | GLint w011 = IROUND_POS((1.0F-a) * b * c * WEIGHT_SCALE); |
||
1462 | GLint w111 = IROUND_POS( a * b * c * WEIGHT_SCALE); |
||
1463 | #endif |
||
1464 | |||
1465 | GLchan t000[4], t010[4], t001[4], t011[4]; |
||
1466 | GLchan t100[4], t110[4], t101[4], t111[4]; |
||
1467 | |||
1468 | if (useBorderColor & (I0BIT | J0BIT | K0BIT)) { |
||
1469 | COPY_CHAN4(t000, tObj->_BorderChan); |
||
1470 | } |
||
1471 | else { |
||
1472 | (*img->FetchTexel)(img, i0, j0, k0, (GLvoid *) t000); |
||
1473 | if (img->Format == GL_COLOR_INDEX) { |
||
1474 | palette_sample(ctx, tObj, t000[0], t000); |
||
1475 | } |
||
1476 | } |
||
1477 | if (useBorderColor & (I1BIT | J0BIT | K0BIT)) { |
||
1478 | COPY_CHAN4(t100, tObj->_BorderChan); |
||
1479 | } |
||
1480 | else { |
||
1481 | (*img->FetchTexel)(img, i1, j0, k0, (GLvoid *) t100); |
||
1482 | if (img->Format == GL_COLOR_INDEX) { |
||
1483 | palette_sample(ctx, tObj, t100[0], t100); |
||
1484 | } |
||
1485 | } |
||
1486 | if (useBorderColor & (I0BIT | J1BIT | K0BIT)) { |
||
1487 | COPY_CHAN4(t010, tObj->_BorderChan); |
||
1488 | } |
||
1489 | else { |
||
1490 | (*img->FetchTexel)(img, i0, j1, k0, (GLvoid *) t010); |
||
1491 | if (img->Format == GL_COLOR_INDEX) { |
||
1492 | palette_sample(ctx, tObj, t010[0], t010); |
||
1493 | } |
||
1494 | } |
||
1495 | if (useBorderColor & (I1BIT | J1BIT | K0BIT)) { |
||
1496 | COPY_CHAN4(t110, tObj->_BorderChan); |
||
1497 | } |
||
1498 | else { |
||
1499 | (*img->FetchTexel)(img, i1, j1, k0, (GLvoid *) t110); |
||
1500 | if (img->Format == GL_COLOR_INDEX) { |
||
1501 | palette_sample(ctx, tObj, t110[0], t110); |
||
1502 | } |
||
1503 | } |
||
1504 | |||
1505 | if (useBorderColor & (I0BIT | J0BIT | K1BIT)) { |
||
1506 | COPY_CHAN4(t001, tObj->_BorderChan); |
||
1507 | } |
||
1508 | else { |
||
1509 | (*img->FetchTexel)(img, i0, j0, k1, (GLvoid *) t001); |
||
1510 | if (img->Format == GL_COLOR_INDEX) { |
||
1511 | palette_sample(ctx, tObj, t001[0], t001); |
||
1512 | } |
||
1513 | } |
||
1514 | if (useBorderColor & (I1BIT | J0BIT | K1BIT)) { |
||
1515 | COPY_CHAN4(t101, tObj->_BorderChan); |
||
1516 | } |
||
1517 | else { |
||
1518 | (*img->FetchTexel)(img, i1, j0, k1, (GLvoid *) t101); |
||
1519 | if (img->Format == GL_COLOR_INDEX) { |
||
1520 | palette_sample(ctx, tObj, t101[0], t101); |
||
1521 | } |
||
1522 | } |
||
1523 | if (useBorderColor & (I0BIT | J1BIT | K1BIT)) { |
||
1524 | COPY_CHAN4(t011, tObj->_BorderChan); |
||
1525 | } |
||
1526 | else { |
||
1527 | (*img->FetchTexel)(img, i0, j1, k1, (GLvoid *) t011); |
||
1528 | if (img->Format == GL_COLOR_INDEX) { |
||
1529 | palette_sample(ctx, tObj, t011[0], t011); |
||
1530 | } |
||
1531 | } |
||
1532 | if (useBorderColor & (I1BIT | J1BIT | K1BIT)) { |
||
1533 | COPY_CHAN4(t111, tObj->_BorderChan); |
||
1534 | } |
||
1535 | else { |
||
1536 | (*img->FetchTexel)(img, i1, j1, k1, (GLvoid *) t111); |
||
1537 | if (img->Format == GL_COLOR_INDEX) { |
||
1538 | palette_sample(ctx, tObj, t111[0], t111); |
||
1539 | } |
||
1540 | } |
||
1541 | |||
1542 | #if CHAN_TYPE == GL_FLOAT |
||
1543 | rgba[0] = w000*t000[0] + w010*t010[0] + w001*t001[0] + w011*t011[0] + |
||
1544 | w100*t100[0] + w110*t110[0] + w101*t101[0] + w111*t111[0]; |
||
1545 | rgba[1] = w000*t000[1] + w010*t010[1] + w001*t001[1] + w011*t011[1] + |
||
1546 | w100*t100[1] + w110*t110[1] + w101*t101[1] + w111*t111[1]; |
||
1547 | rgba[2] = w000*t000[2] + w010*t010[2] + w001*t001[2] + w011*t011[2] + |
||
1548 | w100*t100[2] + w110*t110[2] + w101*t101[2] + w111*t111[2]; |
||
1549 | rgba[3] = w000*t000[3] + w010*t010[3] + w001*t001[3] + w011*t011[3] + |
||
1550 | w100*t100[3] + w110*t110[3] + w101*t101[3] + w111*t111[3]; |
||
1551 | #elif CHAN_TYPE == GL_UNSIGNED_SHORT |
||
1552 | rgba[0] = (GLchan) (w000*t000[0] + w010*t010[0] + |
||
1553 | w001*t001[0] + w011*t011[0] + |
||
1554 | w100*t100[0] + w110*t110[0] + |
||
1555 | w101*t101[0] + w111*t111[0] + 0.5); |
||
1556 | rgba[1] = (GLchan) (w000*t000[1] + w010*t010[1] + |
||
1557 | w001*t001[1] + w011*t011[1] + |
||
1558 | w100*t100[1] + w110*t110[1] + |
||
1559 | w101*t101[1] + w111*t111[1] + 0.5); |
||
1560 | rgba[2] = (GLchan) (w000*t000[2] + w010*t010[2] + |
||
1561 | w001*t001[2] + w011*t011[2] + |
||
1562 | w100*t100[2] + w110*t110[2] + |
||
1563 | w101*t101[2] + w111*t111[2] + 0.5); |
||
1564 | rgba[3] = (GLchan) (w000*t000[3] + w010*t010[3] + |
||
1565 | w001*t001[3] + w011*t011[3] + |
||
1566 | w100*t100[3] + w110*t110[3] + |
||
1567 | w101*t101[3] + w111*t111[3] + 0.5); |
||
1568 | #else /* CHAN_BITS == 8 */ |
||
1569 | rgba[0] = (GLchan) ( |
||
1570 | (w000*t000[0] + w010*t010[0] + w001*t001[0] + w011*t011[0] + |
||
1571 | w100*t100[0] + w110*t110[0] + w101*t101[0] + w111*t111[0] ) |
||
1572 | >> WEIGHT_SHIFT); |
||
1573 | rgba[1] = (GLchan) ( |
||
1574 | (w000*t000[1] + w010*t010[1] + w001*t001[1] + w011*t011[1] + |
||
1575 | w100*t100[1] + w110*t110[1] + w101*t101[1] + w111*t111[1] ) |
||
1576 | >> WEIGHT_SHIFT); |
||
1577 | rgba[2] = (GLchan) ( |
||
1578 | (w000*t000[2] + w010*t010[2] + w001*t001[2] + w011*t011[2] + |
||
1579 | w100*t100[2] + w110*t110[2] + w101*t101[2] + w111*t111[2] ) |
||
1580 | >> WEIGHT_SHIFT); |
||
1581 | rgba[3] = (GLchan) ( |
||
1582 | (w000*t000[3] + w010*t010[3] + w001*t001[3] + w011*t011[3] + |
||
1583 | w100*t100[3] + w110*t110[3] + w101*t101[3] + w111*t111[3] ) |
||
1584 | >> WEIGHT_SHIFT); |
||
1585 | #endif |
||
1586 | |||
1587 | } |
||
1588 | } |
||
1589 | |||
1590 | |||
1591 | |||
1592 | static void |
||
1593 | sample_3d_nearest_mipmap_nearest(GLcontext *ctx, |
||
1594 | const struct gl_texture_object *tObj, |
||
1595 | GLuint n, GLfloat texcoord[][4], |
||
1596 | const GLfloat lambda[], GLchan rgba[][4] ) |
||
1597 | { |
||
1598 | GLuint i; |
||
1599 | for (i = 0; i < n; i++) { |
||
1600 | GLint level; |
||
1601 | COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level); |
||
1602 | sample_3d_nearest(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]); |
||
1603 | } |
||
1604 | } |
||
1605 | |||
1606 | |||
1607 | static void |
||
1608 | sample_3d_linear_mipmap_nearest(GLcontext *ctx, |
||
1609 | const struct gl_texture_object *tObj, |
||
1610 | GLuint n, GLfloat texcoord[][4], |
||
1611 | const GLfloat lambda[], GLchan rgba[][4]) |
||
1612 | { |
||
1613 | GLuint i; |
||
1614 | ASSERT(lambda != NULL); |
||
1615 | for (i = 0; i < n; i++) { |
||
1616 | GLint level; |
||
1617 | COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level); |
||
1618 | sample_3d_linear(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]); |
||
1619 | } |
||
1620 | } |
||
1621 | |||
1622 | |||
1623 | static void |
||
1624 | sample_3d_nearest_mipmap_linear(GLcontext *ctx, |
||
1625 | const struct gl_texture_object *tObj, |
||
1626 | GLuint n, GLfloat texcoord[][4], |
||
1627 | const GLfloat lambda[], GLchan rgba[][4]) |
||
1628 | { |
||
1629 | GLuint i; |
||
1630 | ASSERT(lambda != NULL); |
||
1631 | for (i = 0; i < n; i++) { |
||
1632 | GLint level; |
||
1633 | COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level); |
||
1634 | if (level >= tObj->_MaxLevel) { |
||
1635 | sample_3d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel], |
||
1636 | texcoord[i], rgba[i]); |
||
1637 | } |
||
1638 | else { |
||
1639 | GLchan t0[4], t1[4]; /* texels */ |
||
1640 | const GLfloat f = FRAC(lambda[i]); |
||
1641 | sample_3d_nearest(ctx, tObj, tObj->Image[level ], texcoord[i], t0); |
||
1642 | sample_3d_nearest(ctx, tObj, tObj->Image[level+1], texcoord[i], t1); |
||
1643 | rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); |
||
1644 | rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); |
||
1645 | rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); |
||
1646 | rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); |
||
1647 | } |
||
1648 | } |
||
1649 | } |
||
1650 | |||
1651 | |||
1652 | static void |
||
1653 | sample_3d_linear_mipmap_linear(GLcontext *ctx, |
||
1654 | const struct gl_texture_object *tObj, |
||
1655 | GLuint n, GLfloat texcoord[][4], |
||
1656 | const GLfloat lambda[], GLchan rgba[][4]) |
||
1657 | { |
||
1658 | GLuint i; |
||
1659 | ASSERT(lambda != NULL); |
||
1660 | for (i = 0; i < n; i++) { |
||
1661 | GLint level; |
||
1662 | COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level); |
||
1663 | if (level >= tObj->_MaxLevel) { |
||
1664 | sample_3d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel], |
||
1665 | texcoord[i], rgba[i]); |
||
1666 | } |
||
1667 | else { |
||
1668 | GLchan t0[4], t1[4]; /* texels */ |
||
1669 | const GLfloat f = FRAC(lambda[i]); |
||
1670 | sample_3d_linear(ctx, tObj, tObj->Image[level ], texcoord[i], t0); |
||
1671 | sample_3d_linear(ctx, tObj, tObj->Image[level+1], texcoord[i], t1); |
||
1672 | rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); |
||
1673 | rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); |
||
1674 | rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); |
||
1675 | rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); |
||
1676 | } |
||
1677 | } |
||
1678 | } |
||
1679 | |||
1680 | |||
1681 | static void |
||
1682 | sample_nearest_3d(GLcontext *ctx, GLuint texUnit, |
||
1683 | const struct gl_texture_object *tObj, GLuint n, |
||
1684 | GLfloat texcoords[][4], const GLfloat lambda[], |
||
1685 | GLchan rgba[][4]) |
||
1686 | { |
||
1687 | GLuint i; |
||
1688 | struct gl_texture_image *image = tObj->Image[tObj->BaseLevel]; |
||
1689 | (void) lambda; |
||
1690 | for (i=0;i<n;i++) { |
||
1691 | sample_3d_nearest(ctx, tObj, image, texcoords[i], rgba[i]); |
||
1692 | } |
||
1693 | } |
||
1694 | |||
1695 | |||
1696 | |||
1697 | static void |
||
1698 | sample_linear_3d( GLcontext *ctx, GLuint texUnit, |
||
1699 | const struct gl_texture_object *tObj, GLuint n, |
||
1700 | GLfloat texcoords[][4], |
||
1701 | const GLfloat lambda[], GLchan rgba[][4] ) |
||
1702 | { |
||
1703 | GLuint i; |
||
1704 | struct gl_texture_image *image = tObj->Image[tObj->BaseLevel]; |
||
1705 | (void) lambda; |
||
1706 | for (i=0;i<n;i++) { |
||
1707 | sample_3d_linear(ctx, tObj, image, texcoords[i], rgba[i]); |
||
1708 | } |
||
1709 | } |
||
1710 | |||
1711 | |||
1712 | /* |
||
1713 | * Given an (s,t,r) texture coordinate and lambda (level of detail) value, |
||
1714 | * return a texture sample. |
||
1715 | */ |
||
1716 | static void |
||
1717 | sample_lambda_3d( GLcontext *ctx, GLuint texUnit, |
||
1718 | const struct gl_texture_object *tObj, GLuint n, |
||
1719 | GLfloat texcoords[][4], const GLfloat lambda[], |
||
1720 | GLchan rgba[][4] ) |
||
1721 | { |
||
1722 | GLuint minStart, minEnd; /* texels with minification */ |
||
1723 | GLuint magStart, magEnd; /* texels with magnification */ |
||
1724 | GLuint i; |
||
1725 | |||
1726 | ASSERT(lambda != NULL); |
||
1727 | compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit], |
||
1728 | n, lambda, &minStart, &minEnd, &magStart, &magEnd); |
||
1729 | |||
1730 | if (minStart < minEnd) { |
||
1731 | /* do the minified texels */ |
||
1732 | GLuint m = minEnd - minStart; |
||
1733 | switch (tObj->MinFilter) { |
||
1734 | case GL_NEAREST: |
||
1735 | for (i = minStart; i < minEnd; i++) |
||
1736 | sample_3d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel], |
||
1737 | texcoords[i], rgba[i]); |
||
1738 | break; |
||
1739 | case GL_LINEAR: |
||
1740 | for (i = minStart; i < minEnd; i++) |
||
1741 | sample_3d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel], |
||
1742 | texcoords[i], rgba[i]); |
||
1743 | break; |
||
1744 | case GL_NEAREST_MIPMAP_NEAREST: |
||
1745 | sample_3d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart, |
||
1746 | lambda + minStart, rgba + minStart); |
||
1747 | break; |
||
1748 | case GL_LINEAR_MIPMAP_NEAREST: |
||
1749 | sample_3d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart, |
||
1750 | lambda + minStart, rgba + minStart); |
||
1751 | break; |
||
1752 | case GL_NEAREST_MIPMAP_LINEAR: |
||
1753 | sample_3d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart, |
||
1754 | lambda + minStart, rgba + minStart); |
||
1755 | break; |
||
1756 | case GL_LINEAR_MIPMAP_LINEAR: |
||
1757 | sample_3d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart, |
||
1758 | lambda + minStart, rgba + minStart); |
||
1759 | break; |
||
1760 | default: |
||
1761 | _mesa_problem(ctx, "Bad min filter in sample_3d_texture"); |
||
1762 | return; |
||
1763 | } |
||
1764 | } |
||
1765 | |||
1766 | if (magStart < magEnd) { |
||
1767 | /* do the magnified texels */ |
||
1768 | switch (tObj->MagFilter) { |
||
1769 | case GL_NEAREST: |
||
1770 | for (i = magStart; i < magEnd; i++) |
||
1771 | sample_3d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel], |
||
1772 | texcoords[i], rgba[i]); |
||
1773 | break; |
||
1774 | case GL_LINEAR: |
||
1775 | for (i = magStart; i < magEnd; i++) |
||
1776 | sample_3d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel], |
||
1777 | texcoords[i], rgba[i]); |
||
1778 | break; |
||
1779 | default: |
||
1780 | _mesa_problem(ctx, "Bad mag filter in sample_3d_texture"); |
||
1781 | return; |
||
1782 | } |
||
1783 | } |
||
1784 | } |
||
1785 | |||
1786 | |||
1787 | /**********************************************************************/ |
||
1788 | /* Texture Cube Map Sampling Functions */ |
||
1789 | /**********************************************************************/ |
||
1790 | |||
1791 | /* |
||
1792 | * Choose one of six sides of a texture cube map given the texture |
||
1793 | * coord (rx,ry,rz). Return pointer to corresponding array of texture |
||
1794 | * images. |
||
1795 | */ |
||
1796 | static const struct gl_texture_image ** |
||
1797 | choose_cube_face(const struct gl_texture_object *texObj, |
||
1798 | const GLfloat texcoord[4], GLfloat newCoord[4]) |
||
1799 | { |
||
1800 | /* |
||
1801 | major axis |
||
1802 | direction target sc tc ma |
||
1803 | ---------- ------------------------------- --- --- --- |
||
1804 | +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx |
||
1805 | -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx |
||
1806 | +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry |
||
1807 | -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry |
||
1808 | +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz |
||
1809 | -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz |
||
1810 | */ |
||
1811 | const GLfloat rx = texcoord[0]; |
||
1812 | const GLfloat ry = texcoord[1]; |
||
1813 | const GLfloat rz = texcoord[2]; |
||
1814 | const struct gl_texture_image **imgArray; |
||
1815 | const GLfloat arx = ABSF(rx), ary = ABSF(ry), arz = ABSF(rz); |
||
1816 | GLfloat sc, tc, ma; |
||
1817 | |||
1818 | if (arx > ary && arx > arz) { |
||
1819 | if (rx >= 0.0F) { |
||
1820 | imgArray = (const struct gl_texture_image **) texObj->Image; |
||
1821 | sc = -rz; |
||
1822 | tc = -ry; |
||
1823 | ma = arx; |
||
1824 | } |
||
1825 | else { |
||
1826 | imgArray = (const struct gl_texture_image **) texObj->NegX; |
||
1827 | sc = rz; |
||
1828 | tc = -ry; |
||
1829 | ma = arx; |
||
1830 | } |
||
1831 | } |
||
1832 | else if (ary > arx && ary > arz) { |
||
1833 | if (ry >= 0.0F) { |
||
1834 | imgArray = (const struct gl_texture_image **) texObj->PosY; |
||
1835 | sc = rx; |
||
1836 | tc = rz; |
||
1837 | ma = ary; |
||
1838 | } |
||
1839 | else { |
||
1840 | imgArray = (const struct gl_texture_image **) texObj->NegY; |
||
1841 | sc = rx; |
||
1842 | tc = -rz; |
||
1843 | ma = ary; |
||
1844 | } |
||
1845 | } |
||
1846 | else { |
||
1847 | if (rz > 0.0F) { |
||
1848 | imgArray = (const struct gl_texture_image **) texObj->PosZ; |
||
1849 | sc = rx; |
||
1850 | tc = -ry; |
||
1851 | ma = arz; |
||
1852 | } |
||
1853 | else { |
||
1854 | imgArray = (const struct gl_texture_image **) texObj->NegZ; |
||
1855 | sc = -rx; |
||
1856 | tc = -ry; |
||
1857 | ma = arz; |
||
1858 | } |
||
1859 | } |
||
1860 | |||
1861 | newCoord[0] = ( sc / ma + 1.0F ) * 0.5F; |
||
1862 | newCoord[1] = ( tc / ma + 1.0F ) * 0.5F; |
||
1863 | return imgArray; |
||
1864 | } |
||
1865 | |||
1866 | |||
1867 | static void |
||
1868 | sample_nearest_cube(GLcontext *ctx, GLuint texUnit, |
||
1869 | const struct gl_texture_object *tObj, GLuint n, |
||
1870 | GLfloat texcoords[][4], const GLfloat lambda[], |
||
1871 | GLchan rgba[][4]) |
||
1872 | { |
||
1873 | GLuint i; |
||
1874 | (void) lambda; |
||
1875 | for (i = 0; i < n; i++) { |
||
1876 | const struct gl_texture_image **images; |
||
1877 | GLfloat newCoord[4]; |
||
1878 | images = choose_cube_face(tObj, texcoords[i], newCoord); |
||
1879 | sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel], |
||
1880 | newCoord, rgba[i]); |
||
1881 | } |
||
1882 | } |
||
1883 | |||
1884 | |||
1885 | static void |
||
1886 | sample_linear_cube(GLcontext *ctx, GLuint texUnit, |
||
1887 | const struct gl_texture_object *tObj, GLuint n, |
||
1888 | GLfloat texcoords[][4], |
||
1889 | const GLfloat lambda[], GLchan rgba[][4]) |
||
1890 | { |
||
1891 | GLuint i; |
||
1892 | (void) lambda; |
||
1893 | for (i = 0; i < n; i++) { |
||
1894 | const struct gl_texture_image **images; |
||
1895 | GLfloat newCoord[4]; |
||
1896 | images = choose_cube_face(tObj, texcoords[i], newCoord); |
||
1897 | sample_2d_linear(ctx, tObj, images[tObj->BaseLevel], |
||
1898 | newCoord, rgba[i]); |
||
1899 | } |
||
1900 | } |
||
1901 | |||
1902 | |||
1903 | static void |
||
1904 | sample_cube_nearest_mipmap_nearest(GLcontext *ctx, |
||
1905 | const struct gl_texture_object *tObj, |
||
1906 | GLuint n, GLfloat texcoord[][4], |
||
1907 | const GLfloat lambda[], GLchan rgba[][4]) |
||
1908 | { |
||
1909 | GLuint i; |
||
1910 | ASSERT(lambda != NULL); |
||
1911 | for (i = 0; i < n; i++) { |
||
1912 | const struct gl_texture_image **images; |
||
1913 | GLfloat newCoord[4]; |
||
1914 | GLint level; |
||
1915 | COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level); |
||
1916 | images = choose_cube_face(tObj, texcoord[i], newCoord); |
||
1917 | sample_2d_nearest(ctx, tObj, images[level], newCoord, rgba[i]); |
||
1918 | } |
||
1919 | } |
||
1920 | |||
1921 | |||
1922 | static void |
||
1923 | sample_cube_linear_mipmap_nearest(GLcontext *ctx, |
||
1924 | const struct gl_texture_object *tObj, |
||
1925 | GLuint n, GLfloat texcoord[][4], |
||
1926 | const GLfloat lambda[], GLchan rgba[][4]) |
||
1927 | { |
||
1928 | GLuint i; |
||
1929 | ASSERT(lambda != NULL); |
||
1930 | for (i = 0; i < n; i++) { |
||
1931 | const struct gl_texture_image **images; |
||
1932 | GLfloat newCoord[4]; |
||
1933 | GLint level; |
||
1934 | COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level); |
||
1935 | images = choose_cube_face(tObj, texcoord[i], newCoord); |
||
1936 | sample_2d_linear(ctx, tObj, images[level], newCoord, rgba[i]); |
||
1937 | } |
||
1938 | } |
||
1939 | |||
1940 | |||
1941 | static void |
||
1942 | sample_cube_nearest_mipmap_linear(GLcontext *ctx, |
||
1943 | const struct gl_texture_object *tObj, |
||
1944 | GLuint n, GLfloat texcoord[][4], |
||
1945 | const GLfloat lambda[], GLchan rgba[][4]) |
||
1946 | { |
||
1947 | GLuint i; |
||
1948 | ASSERT(lambda != NULL); |
||
1949 | for (i = 0; i < n; i++) { |
||
1950 | const struct gl_texture_image **images; |
||
1951 | GLfloat newCoord[4]; |
||
1952 | GLint level; |
||
1953 | COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level); |
||
1954 | images = choose_cube_face(tObj, texcoord[i], newCoord); |
||
1955 | if (level >= tObj->_MaxLevel) { |
||
1956 | sample_2d_nearest(ctx, tObj, images[tObj->_MaxLevel], |
||
1957 | newCoord, rgba[i]); |
||
1958 | } |
||
1959 | else { |
||
1960 | GLchan t0[4], t1[4]; /* texels */ |
||
1961 | const GLfloat f = FRAC(lambda[i]); |
||
1962 | sample_2d_nearest(ctx, tObj, images[level ], newCoord, t0); |
||
1963 | sample_2d_nearest(ctx, tObj, images[level+1], newCoord, t1); |
||
1964 | rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); |
||
1965 | rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); |
||
1966 | rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); |
||
1967 | rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); |
||
1968 | } |
||
1969 | } |
||
1970 | } |
||
1971 | |||
1972 | |||
1973 | static void |
||
1974 | sample_cube_linear_mipmap_linear(GLcontext *ctx, |
||
1975 | const struct gl_texture_object *tObj, |
||
1976 | GLuint n, GLfloat texcoord[][4], |
||
1977 | const GLfloat lambda[], GLchan rgba[][4]) |
||
1978 | { |
||
1979 | GLuint i; |
||
1980 | ASSERT(lambda != NULL); |
||
1981 | for (i = 0; i < n; i++) { |
||
1982 | const struct gl_texture_image **images; |
||
1983 | GLfloat newCoord[4]; |
||
1984 | GLint level; |
||
1985 | COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level); |
||
1986 | images = choose_cube_face(tObj, texcoord[i], newCoord); |
||
1987 | if (level >= tObj->_MaxLevel) { |
||
1988 | sample_2d_linear(ctx, tObj, images[tObj->_MaxLevel], |
||
1989 | newCoord, rgba[i]); |
||
1990 | } |
||
1991 | else { |
||
1992 | GLchan t0[4], t1[4]; |
||
1993 | const GLfloat f = FRAC(lambda[i]); |
||
1994 | sample_2d_linear(ctx, tObj, images[level ], newCoord, t0); |
||
1995 | sample_2d_linear(ctx, tObj, images[level+1], newCoord, t1); |
||
1996 | rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]); |
||
1997 | rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]); |
||
1998 | rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]); |
||
1999 | rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]); |
||
2000 | } |
||
2001 | } |
||
2002 | } |
||
2003 | |||
2004 | |||
2005 | static void |
||
2006 | sample_lambda_cube( GLcontext *ctx, GLuint texUnit, |
||
2007 | const struct gl_texture_object *tObj, GLuint n, |
||
2008 | GLfloat texcoords[][4], const GLfloat lambda[], |
||
2009 | GLchan rgba[][4]) |
||
2010 | { |
||
2011 | GLuint minStart, minEnd; /* texels with minification */ |
||
2012 | GLuint magStart, magEnd; /* texels with magnification */ |
||
2013 | |||
2014 | ASSERT(lambda != NULL); |
||
2015 | compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit], |
||
2016 | n, lambda, &minStart, &minEnd, &magStart, &magEnd); |
||
2017 | |||
2018 | if (minStart < minEnd) { |
||
2019 | /* do the minified texels */ |
||
2020 | const GLuint m = minEnd - minStart; |
||
2021 | switch (tObj->MinFilter) { |
||
2022 | case GL_NEAREST: |
||
2023 | sample_nearest_cube(ctx, texUnit, tObj, m, texcoords + minStart, |
||
2024 | lambda + minStart, rgba + minStart); |
||
2025 | break; |
||
2026 | case GL_LINEAR: |
||
2027 | sample_linear_cube(ctx, texUnit, tObj, m, texcoords + minStart, |
||
2028 | lambda + minStart, rgba + minStart); |
||
2029 | break; |
||
2030 | case GL_NEAREST_MIPMAP_NEAREST: |
||
2031 | sample_cube_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart, |
||
2032 | lambda + minStart, rgba + minStart); |
||
2033 | break; |
||
2034 | case GL_LINEAR_MIPMAP_NEAREST: |
||
2035 | sample_cube_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart, |
||
2036 | lambda + minStart, rgba + minStart); |
||
2037 | break; |
||
2038 | case GL_NEAREST_MIPMAP_LINEAR: |
||
2039 | sample_cube_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart, |
||
2040 | lambda + minStart, rgba + minStart); |
||
2041 | break; |
||
2042 | case GL_LINEAR_MIPMAP_LINEAR: |
||
2043 | sample_cube_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart, |
||
2044 | lambda + minStart, rgba + minStart); |
||
2045 | break; |
||
2046 | default: |
||
2047 | _mesa_problem(ctx, "Bad min filter in sample_lambda_cube"); |
||
2048 | } |
||
2049 | } |
||
2050 | |||
2051 | if (magStart < magEnd) { |
||
2052 | /* do the magnified texels */ |
||
2053 | const GLuint m = magEnd - magStart; |
||
2054 | switch (tObj->MagFilter) { |
||
2055 | case GL_NEAREST: |
||
2056 | sample_nearest_cube(ctx, texUnit, tObj, m, texcoords + magStart, |
||
2057 | lambda + magStart, rgba + magStart); |
||
2058 | break; |
||
2059 | case GL_LINEAR: |
||
2060 | sample_linear_cube(ctx, texUnit, tObj, m, texcoords + magStart, |
||
2061 | lambda + magStart, rgba + magStart); |
||
2062 | break; |
||
2063 | default: |
||
2064 | _mesa_problem(ctx, "Bad mag filter in sample_lambda_cube"); |
||
2065 | } |
||
2066 | } |
||
2067 | } |
||
2068 | |||
2069 | |||
2070 | /**********************************************************************/ |
||
2071 | /* Texture Rectangle Sampling Functions */ |
||
2072 | /**********************************************************************/ |
||
2073 | |||
2074 | static void |
||
2075 | sample_nearest_rect(GLcontext *ctx, GLuint texUnit, |
||
2076 | const struct gl_texture_object *tObj, GLuint n, |
||
2077 | GLfloat texcoords[][4], const GLfloat lambda[], |
||
2078 | GLchan rgba[][4]) |
||
2079 | { |
||
2080 | const struct gl_texture_image *img = tObj->Image[0]; |
||
2081 | const GLfloat width = (GLfloat) img->Width; |
||
2082 | const GLfloat height = (GLfloat) img->Height; |
||
2083 | const GLint width_minus_1 = img->Width - 1; |
||
2084 | const GLint height_minus_1 = img->Height - 1; |
||
2085 | GLuint i; |
||
2086 | |||
2087 | (void) texUnit; |
||
2088 | (void) lambda; |
||
2089 | |||
2090 | ASSERT(tObj->WrapS == GL_CLAMP || |
||
2091 | tObj->WrapS == GL_CLAMP_TO_EDGE || |
||
2092 | tObj->WrapS == GL_CLAMP_TO_BORDER_ARB); |
||
2093 | ASSERT(tObj->WrapT == GL_CLAMP || |
||
2094 | tObj->WrapT == GL_CLAMP_TO_EDGE || |
||
2095 | tObj->WrapT == GL_CLAMP_TO_BORDER_ARB); |
||
2096 | ASSERT(img->Format != GL_COLOR_INDEX); |
||
2097 | |||
2098 | /* XXX move Wrap mode tests outside of loops for common cases */ |
||
2099 | for (i = 0; i < n; i++) { |
||
2100 | GLint row, col; |
||
2101 | /* NOTE: we DO NOT use [0, 1] texture coordinates! */ |
||
2102 | if (tObj->WrapS == GL_CLAMP) { |
||
2103 | col = IFLOOR( CLAMP(texcoords[i][0], 0.0F, width) ); |
||
2104 | } |
||
2105 | else if (tObj->WrapS == GL_CLAMP_TO_EDGE) { |
||
2106 | col = IFLOOR( CLAMP(texcoords[i][0], 0.5F, width - 0.5F) ); |
||
2107 | } |
||
2108 | else { |
||
2109 | col = IFLOOR( CLAMP(texcoords[i][0], -0.5F, width + 0.5F) ); |
||
2110 | } |
||
2111 | if (tObj->WrapT == GL_CLAMP) { |
||
2112 | row = IFLOOR( CLAMP(texcoords[i][1], 0.0F, height) ); |
||
2113 | } |
||
2114 | else if (tObj->WrapT == GL_CLAMP_TO_EDGE) { |
||
2115 | row = IFLOOR( CLAMP(texcoords[i][1], 0.5F, height - 0.5F) ); |
||
2116 | } |
||
2117 | else { |
||
2118 | row = IFLOOR( CLAMP(texcoords[i][1], -0.5F, height + 0.5F) ); |
||
2119 | } |
||
2120 | |||
2121 | col = CLAMP(col, 0, width_minus_1); |
||
2122 | row = CLAMP(row, 0, height_minus_1); |
||
2123 | |||
2124 | (*img->FetchTexel)(img, col, row, 0, (GLvoid *) rgba[i]); |
||
2125 | } |
||
2126 | } |
||
2127 | |||
2128 | |||
2129 | static void |
||
2130 | sample_linear_rect(GLcontext *ctx, GLuint texUnit, |
||
2131 | const struct gl_texture_object *tObj, GLuint n, |
||
2132 | GLfloat texcoords[][4], |
||
2133 | const GLfloat lambda[], GLchan rgba[][4]) |
||
2134 | { |
||
2135 | const struct gl_texture_image *img = tObj->Image[0]; |
||
2136 | const GLfloat width = (GLfloat) img->Width; |
||
2137 | const GLfloat height = (GLfloat) img->Height; |
||
2138 | const GLint width_minus_1 = img->Width - 1; |
||
2139 | const GLint height_minus_1 = img->Height - 1; |
||
2140 | GLuint i; |
||
2141 | |||
2142 | (void) texUnit; |
||
2143 | (void) lambda; |
||
2144 | |||
2145 | ASSERT(tObj->WrapS == GL_CLAMP || |
||
2146 | tObj->WrapS == GL_CLAMP_TO_EDGE || |
||
2147 | tObj->WrapS == GL_CLAMP_TO_BORDER_ARB); |
||
2148 | ASSERT(tObj->WrapT == GL_CLAMP || |
||
2149 | tObj->WrapT == GL_CLAMP_TO_EDGE || |
||
2150 | tObj->WrapT == GL_CLAMP_TO_BORDER_ARB); |
||
2151 | ASSERT(img->Format != GL_COLOR_INDEX); |
||
2152 | |||
2153 | /* XXX lots of opportunity for optimization in this loop */ |
||
2154 | for (i = 0; i < n; i++) { |
||
2155 | GLfloat frow, fcol; |
||
2156 | GLint row0, col0, row1, col1; |
||
2157 | GLchan t00[4], t01[4], t10[4], t11[4]; |
||
2158 | GLfloat a, b, w00, w01, w10, w11; |
||
2159 | |||
2160 | /* NOTE: we DO NOT use [0, 1] texture coordinates! */ |
||
2161 | if (tObj->WrapS == GL_CLAMP) { |
||
2162 | fcol = CLAMP(texcoords[i][0], 0.0F, width); |
||
2163 | } |
||
2164 | else if (tObj->WrapS == GL_CLAMP_TO_EDGE) { |
||
2165 | fcol = CLAMP(texcoords[i][0], 0.5F, width - 0.5F); |
||
2166 | } |
||
2167 | else { |
||
2168 | fcol = CLAMP(texcoords[i][0], -0.5F, width + 0.5F); |
||
2169 | } |
||
2170 | if (tObj->WrapT == GL_CLAMP) { |
||
2171 | frow = CLAMP(texcoords[i][1], 0.0F, height); |
||
2172 | } |
||
2173 | else if (tObj->WrapT == GL_CLAMP_TO_EDGE) { |
||
2174 | frow = CLAMP(texcoords[i][1], 0.5F, height - 0.5F); |
||
2175 | } |
||
2176 | else { |
||
2177 | frow = CLAMP(texcoords[i][1], -0.5F, height + 0.5F); |
||
2178 | } |
||
2179 | |||
2180 | /* compute integer rows/columns */ |
||
2181 | col0 = IFLOOR(fcol); |
||
2182 | col1 = col0 + 1; |
||
2183 | col0 = CLAMP(col0, 0, width_minus_1); |
||
2184 | col1 = CLAMP(col1, 0, width_minus_1); |
||
2185 | row0 = IFLOOR(frow); |
||
2186 | row1 = row0 + 1; |
||
2187 | row0 = CLAMP(row0, 0, height_minus_1); |
||
2188 | row1 = CLAMP(row1, 0, height_minus_1); |
||
2189 | |||
2190 | /* get four texel samples */ |
||
2191 | (*img->FetchTexel)(img, col0, row0, 0, (GLvoid *) t00); |
||
2192 | (*img->FetchTexel)(img, col1, row0, 0, (GLvoid *) t10); |
||
2193 | (*img->FetchTexel)(img, col0, row1, 0, (GLvoid *) t01); |
||
2194 | (*img->FetchTexel)(img, col1, row1, 0, (GLvoid *) t11); |
||
2195 | |||
2196 | /* compute sample weights */ |
||
2197 | a = FRAC(fcol); |
||
2198 | b = FRAC(frow); |
||
2199 | w00 = (1.0F-a) * (1.0F-b); |
||
2200 | w10 = a * (1.0F-b); |
||
2201 | w01 = (1.0F-a) * b ; |
||
2202 | w11 = a * b ; |
||
2203 | |||
2204 | /* compute weighted average of samples */ |
||
2205 | rgba[i][0] = |
||
2206 | (GLchan) (w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0]); |
||
2207 | rgba[i][1] = |
||
2208 | (GLchan) (w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1]); |
||
2209 | rgba[i][2] = |
||
2210 | (GLchan) (w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2]); |
||
2211 | rgba[i][3] = |
||
2212 | (GLchan) (w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3]); |
||
2213 | } |
||
2214 | } |
||
2215 | |||
2216 | |||
2217 | static void |
||
2218 | sample_lambda_rect( GLcontext *ctx, GLuint texUnit, |
||
2219 | const struct gl_texture_object *tObj, GLuint n, |
||
2220 | GLfloat texcoords[][4], const GLfloat lambda[], |
||
2221 | GLchan rgba[][4]) |
||
2222 | { |
||
2223 | GLuint minStart, minEnd, magStart, magEnd; |
||
2224 | |||
2225 | /* We only need lambda to decide between minification and magnification. |
||
2226 | * There is no mipmapping with rectangular textures. |
||
2227 | */ |
||
2228 | compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit], |
||
2229 | n, lambda, &minStart, &minEnd, &magStart, &magEnd); |
||
2230 | |||
2231 | if (minStart < minEnd) { |
||
2232 | if (tObj->MinFilter == GL_NEAREST) { |
||
2233 | sample_nearest_rect( ctx, texUnit, tObj, minEnd - minStart, |
||
2234 | texcoords + minStart, NULL, rgba + minStart); |
||
2235 | } |
||
2236 | else { |
||
2237 | sample_linear_rect( ctx, texUnit, tObj, minEnd - minStart, |
||
2238 | texcoords + minStart, NULL, rgba + minStart); |
||
2239 | } |
||
2240 | } |
||
2241 | if (magStart < magEnd) { |
||
2242 | if (tObj->MagFilter == GL_NEAREST) { |
||
2243 | sample_nearest_rect( ctx, texUnit, tObj, magEnd - magStart, |
||
2244 | texcoords + magStart, NULL, rgba + magStart); |
||
2245 | } |
||
2246 | else { |
||
2247 | sample_linear_rect( ctx, texUnit, tObj, magEnd - magStart, |
||
2248 | texcoords + magStart, NULL, rgba + magStart); |
||
2249 | } |
||
2250 | } |
||
2251 | } |
||
2252 | |||
2253 | |||
2254 | |||
2255 | /* |
||
2256 | * Sample a shadow/depth texture. |
||
2257 | */ |
||
2258 | static void |
||
2259 | sample_depth_texture( GLcontext *ctx, GLuint unit, |
||
2260 | const struct gl_texture_object *tObj, GLuint n, |
||
2261 | GLfloat texcoords[][4], const GLfloat lambda[], |
||
2262 | GLchan texel[][4] ) |
||
2263 | { |
||
2264 | const GLint baseLevel = tObj->BaseLevel; |
||
2265 | const struct gl_texture_image *texImage = tObj->Image[baseLevel]; |
||
2266 | const GLuint width = texImage->Width; |
||
2267 | const GLuint height = texImage->Height; |
||
2268 | GLchan ambient; |
||
2269 | GLenum function; |
||
2270 | GLchan result; |
||
2271 | |||
2272 | (void) unit; |
||
2273 | |||
2274 | ASSERT(tObj->Image[tObj->BaseLevel]->Format == GL_DEPTH_COMPONENT); |
||
2275 | ASSERT(tObj->Target == GL_TEXTURE_1D || |
||
2276 | tObj->Target == GL_TEXTURE_2D || |
||
2277 | tObj->Target == GL_TEXTURE_RECTANGLE_NV); |
||
2278 | |||
2279 | UNCLAMPED_FLOAT_TO_CHAN(ambient, tObj->ShadowAmbient); |
||
2280 | |||
2281 | /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */ |
||
2282 | |||
2283 | /* XXX this could be precomputed and saved in the texture object */ |
||
2284 | if (tObj->CompareFlag) { |
||
2285 | /* GL_SGIX_shadow */ |
||
2286 | if (tObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) { |
||
2287 | function = GL_LEQUAL; |
||
2288 | } |
||
2289 | else { |
||
2290 | ASSERT(tObj->CompareOperator == GL_TEXTURE_GEQUAL_R_SGIX); |
||
2291 | function = GL_GEQUAL; |
||
2292 | } |
||
2293 | } |
||
2294 | else if (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) { |
||
2295 | /* GL_ARB_shadow */ |
||
2296 | function = tObj->CompareFunc; |
||
2297 | } |
||
2298 | else { |
||
2299 | function = GL_NONE; /* pass depth through as grayscale */ |
||
2300 | } |
||
2301 | |||
2302 | if (tObj->MagFilter == GL_NEAREST) { |
||
2303 | GLuint i; |
||
2304 | for (i = 0; i < n; i++) { |
||
2305 | GLfloat depthSample; |
||
2306 | GLint col, row; |
||
2307 | /* XXX fix for texture rectangle! */ |
||
2308 | COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoords[i][0], width, col); |
||
2309 | COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, texcoords[i][1], height, row); |
||
2310 | depthSample = *((const GLfloat *) texImage->Data + row * width + col); |
||
2311 | |||
2312 | switch (function) { |
||
2313 | case GL_LEQUAL: |
||
2314 | result = (texcoords[i][2] <= depthSample) ? CHAN_MAX : ambient; |
||
2315 | break; |
||
2316 | case GL_GEQUAL: |
||
2317 | result = (texcoords[i][2] >= depthSample) ? CHAN_MAX : ambient; |
||
2318 | break; |
||
2319 | case GL_LESS: |
||
2320 | result = (texcoords[i][2] < depthSample) ? CHAN_MAX : ambient; |
||
2321 | break; |
||
2322 | case GL_GREATER: |
||
2323 | result = (texcoords[i][2] > depthSample) ? CHAN_MAX : ambient; |
||
2324 | break; |
||
2325 | case GL_EQUAL: |
||
2326 | result = (texcoords[i][2] == depthSample) ? CHAN_MAX : ambient; |
||
2327 | break; |
||
2328 | case GL_NOTEQUAL: |
||
2329 | result = (texcoords[i][2] != depthSample) ? CHAN_MAX : ambient; |
||
2330 | break; |
||
2331 | case GL_ALWAYS: |
||
2332 | result = CHAN_MAX; |
||
2333 | break; |
||
2334 | case GL_NEVER: |
||
2335 | result = ambient; |
||
2336 | break; |
||
2337 | case GL_NONE: |
||
2338 | CLAMPED_FLOAT_TO_CHAN(result, depthSample); |
||
2339 | break; |
||
2340 | default: |
||
2341 | _mesa_problem(ctx, "Bad compare func in sample_depth_texture"); |
||
2342 | return; |
||
2343 | } |
||
2344 | |||
2345 | switch (tObj->DepthMode) { |
||
2346 | case GL_LUMINANCE: |
||
2347 | texel[i][RCOMP] = result; |
||
2348 | texel[i][GCOMP] = result; |
||
2349 | texel[i][BCOMP] = result; |
||
2350 | texel[i][ACOMP] = CHAN_MAX; |
||
2351 | break; |
||
2352 | case GL_INTENSITY: |
||
2353 | texel[i][RCOMP] = result; |
||
2354 | texel[i][GCOMP] = result; |
||
2355 | texel[i][BCOMP] = result; |
||
2356 | texel[i][ACOMP] = result; |
||
2357 | break; |
||
2358 | case GL_ALPHA: |
||
2359 | texel[i][RCOMP] = 0; |
||
2360 | texel[i][GCOMP] = 0; |
||
2361 | texel[i][BCOMP] = 0; |
||
2362 | texel[i][ACOMP] = result; |
||
2363 | break; |
||
2364 | default: |
||
2365 | _mesa_problem(ctx, "Bad depth texture mode"); |
||
2366 | } |
||
2367 | } |
||
2368 | } |
||
2369 | else { |
||
2370 | GLuint i; |
||
2371 | ASSERT(tObj->MagFilter == GL_LINEAR); |
||
2372 | for (i = 0; i < n; i++) { |
||
2373 | GLfloat depth00, depth01, depth10, depth11; |
||
2374 | GLint i0, i1, j0, j1; |
||
2375 | GLfloat u, v; |
||
2376 | GLuint useBorderTexel; |
||
2377 | |||
2378 | /* XXX fix for texture rectangle! */ |
||
2379 | COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoords[i][0], u, width, i0, i1); |
||
2380 | COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, texcoords[i][1], v, height,j0, j1); |
||
2381 | |||
2382 | useBorderTexel = 0; |
||
2383 | if (texImage->Border) { |
||
2384 | i0 += texImage->Border; |
||
2385 | i1 += texImage->Border; |
||
2386 | j0 += texImage->Border; |
||
2387 | j1 += texImage->Border; |
||
2388 | } |
||
2389 | else { |
||
2390 | if (i0 < 0 || i0 >= (GLint) width) useBorderTexel |= I0BIT; |
||
2391 | if (i1 < 0 || i1 >= (GLint) width) useBorderTexel |= I1BIT; |
||
2392 | if (j0 < 0 || j0 >= (GLint) height) useBorderTexel |= J0BIT; |
||
2393 | if (j1 < 0 || j1 >= (GLint) height) useBorderTexel |= J1BIT; |
||
2394 | } |
||
2395 | |||
2396 | /* get four depth samples from the texture */ |
||
2397 | if (useBorderTexel & (I0BIT | J0BIT)) { |
||
2398 | depth00 = 1.0; |
||
2399 | } |
||
2400 | else { |
||
2401 | depth00 = *((const GLfloat *) texImage->Data + j0 * width + i0); |
||
2402 | } |
||
2403 | if (useBorderTexel & (I1BIT | J0BIT)) { |
||
2404 | depth10 = 1.0; |
||
2405 | } |
||
2406 | else { |
||
2407 | depth10 = *((const GLfloat *) texImage->Data + j0 * width + i1); |
||
2408 | } |
||
2409 | if (useBorderTexel & (I0BIT | J1BIT)) { |
||
2410 | depth01 = 1.0; |
||
2411 | } |
||
2412 | else { |
||
2413 | depth01 = *((const GLfloat *) texImage->Data + j1 * width + i0); |
||
2414 | } |
||
2415 | if (useBorderTexel & (I1BIT | J1BIT)) { |
||
2416 | depth11 = 1.0; |
||
2417 | } |
||
2418 | else { |
||
2419 | depth11 = *((const GLfloat *) texImage->Data + j1 * width + i1); |
||
2420 | } |
||
2421 | |||
2422 | if (0) { |
||
2423 | /* compute a single weighted depth sample and do one comparison */ |
||
2424 | const GLfloat a = FRAC(u + 1.0F); |
||
2425 | const GLfloat b = FRAC(v + 1.0F); |
||
2426 | const GLfloat w00 = (1.0F - a) * (1.0F - b); |
||
2427 | const GLfloat w10 = ( a) * (1.0F - b); |
||
2428 | const GLfloat w01 = (1.0F - a) * ( b); |
||
2429 | const GLfloat w11 = ( a) * ( b); |
||
2430 | const GLfloat depthSample = w00 * depth00 + w10 * depth10 |
||
2431 | + w01 * depth01 + w11 * depth11; |
||
2432 | if ((depthSample <= texcoords[i][2] && function == GL_LEQUAL) || |
||
2433 | (depthSample >= texcoords[i][2] && function == GL_GEQUAL)) { |
||
2434 | result = ambient; |
||
2435 | } |
||
2436 | else { |
||
2437 | result = CHAN_MAX; |
||
2438 | } |
||
2439 | } |
||
2440 | else { |
||
2441 | /* Do four depth/R comparisons and compute a weighted result. |
||
2442 | * If this touches on somebody's I.P., I'll remove this code |
||
2443 | * upon request. |
||
2444 | */ |
||
2445 | const GLfloat d = (CHAN_MAXF - (GLfloat) ambient) * 0.25F; |
||
2446 | GLfloat luminance = CHAN_MAXF; |
||
2447 | |||
2448 | switch (function) { |
||
2449 | case GL_LEQUAL: |
||
2450 | if (depth00 <= texcoords[i][2]) luminance -= d; |
||
2451 | if (depth01 <= texcoords[i][2]) luminance -= d; |
||
2452 | if (depth10 <= texcoords[i][2]) luminance -= d; |
||
2453 | if (depth11 <= texcoords[i][2]) luminance -= d; |
||
2454 | result = (GLchan) luminance; |
||
2455 | break; |
||
2456 | case GL_GEQUAL: |
||
2457 | if (depth00 >= texcoords[i][2]) luminance -= d; |
||
2458 | if (depth01 >= texcoords[i][2]) luminance -= d; |
||
2459 | if (depth10 >= texcoords[i][2]) luminance -= d; |
||
2460 | if (depth11 >= texcoords[i][2]) luminance -= d; |
||
2461 | result = (GLchan) luminance; |
||
2462 | break; |
||
2463 | case GL_LESS: |
||
2464 | if (depth00 < texcoords[i][2]) luminance -= d; |
||
2465 | if (depth01 < texcoords[i][2]) luminance -= d; |
||
2466 | if (depth10 < texcoords[i][2]) luminance -= d; |
||
2467 | if (depth11 < texcoords[i][2]) luminance -= d; |
||
2468 | result = (GLchan) luminance; |
||
2469 | break; |
||
2470 | case GL_GREATER: |
||
2471 | if (depth00 > texcoords[i][2]) luminance -= d; |
||
2472 | if (depth01 > texcoords[i][2]) luminance -= d; |
||
2473 | if (depth10 > texcoords[i][2]) luminance -= d; |
||
2474 | if (depth11 > texcoords[i][2]) luminance -= d; |
||
2475 | result = (GLchan) luminance; |
||
2476 | break; |
||
2477 | case GL_EQUAL: |
||
2478 | if (depth00 == texcoords[i][2]) luminance -= d; |
||
2479 | if (depth01 == texcoords[i][2]) luminance -= d; |
||
2480 | if (depth10 == texcoords[i][2]) luminance -= d; |
||
2481 | if (depth11 == texcoords[i][2]) luminance -= d; |
||
2482 | result = (GLchan) luminance; |
||
2483 | break; |
||
2484 | case GL_NOTEQUAL: |
||
2485 | if (depth00 != texcoords[i][2]) luminance -= d; |
||
2486 | if (depth01 != texcoords[i][2]) luminance -= d; |
||
2487 | if (depth10 != texcoords[i][2]) luminance -= d; |
||
2488 | if (depth11 != texcoords[i][2]) luminance -= d; |
||
2489 | result = (GLchan) luminance; |
||
2490 | break; |
||
2491 | case GL_ALWAYS: |
||
2492 | result = 0; |
||
2493 | break; |
||
2494 | case GL_NEVER: |
||
2495 | result = CHAN_MAX; |
||
2496 | break; |
||
2497 | case GL_NONE: |
||
2498 | /* ordinary bilinear filtering */ |
||
2499 | { |
||
2500 | const GLfloat a = FRAC(u + 1.0F); |
||
2501 | const GLfloat b = FRAC(v + 1.0F); |
||
2502 | const GLfloat w00 = (1.0F - a) * (1.0F - b); |
||
2503 | const GLfloat w10 = ( a) * (1.0F - b); |
||
2504 | const GLfloat w01 = (1.0F - a) * ( b); |
||
2505 | const GLfloat w11 = ( a) * ( b); |
||
2506 | const GLfloat depthSample = w00 * depth00 + w10 * depth10 |
||
2507 | + w01 * depth01 + w11 * depth11; |
||
2508 | CLAMPED_FLOAT_TO_CHAN(result, depthSample); |
||
2509 | } |
||
2510 | break; |
||
2511 | default: |
||
2512 | _mesa_problem(ctx, "Bad compare func in sample_depth_texture"); |
||
2513 | return; |
||
2514 | } |
||
2515 | } |
||
2516 | |||
2517 | switch (tObj->DepthMode) { |
||
2518 | case GL_LUMINANCE: |
||
2519 | texel[i][RCOMP] = result; |
||
2520 | texel[i][GCOMP] = result; |
||
2521 | texel[i][BCOMP] = result; |
||
2522 | texel[i][ACOMP] = CHAN_MAX; |
||
2523 | break; |
||
2524 | case GL_INTENSITY: |
||
2525 | texel[i][RCOMP] = result; |
||
2526 | texel[i][GCOMP] = result; |
||
2527 | texel[i][BCOMP] = result; |
||
2528 | texel[i][ACOMP] = result; |
||
2529 | break; |
||
2530 | case GL_ALPHA: |
||
2531 | texel[i][RCOMP] = 0; |
||
2532 | texel[i][GCOMP] = 0; |
||
2533 | texel[i][BCOMP] = 0; |
||
2534 | texel[i][ACOMP] = result; |
||
2535 | break; |
||
2536 | default: |
||
2537 | _mesa_problem(ctx, "Bad depth texture mode"); |
||
2538 | } |
||
2539 | } /* for */ |
||
2540 | } /* if filter */ |
||
2541 | } |
||
2542 | |||
2543 | |||
2544 | #if 0 |
||
2545 | /* |
||
2546 | * Experimental depth texture sampling function. |
||
2547 | */ |
||
2548 | static void |
||
2549 | sample_depth_texture2(const GLcontext *ctx, |
||
2550 | const struct gl_texture_unit *texUnit, |
||
2551 | GLuint n, GLfloat texcoords[][4], |
||
2552 | GLchan texel[][4]) |
||
2553 | { |
||
2554 | const struct gl_texture_object *texObj = texUnit->_Current; |
||
2555 | const GLint baseLevel = texObj->BaseLevel; |
||
2556 | const struct gl_texture_image *texImage = texObj->Image[baseLevel]; |
||
2557 | const GLuint width = texImage->Width; |
||
2558 | const GLuint height = texImage->Height; |
||
2559 | GLchan ambient; |
||
2560 | GLboolean lequal, gequal; |
||
2561 | |||
2562 | if (texObj->Target != GL_TEXTURE_2D) { |
||
2563 | _mesa_problem(ctx, "only 2-D depth textures supported at this time"); |
||
2564 | return; |
||
2565 | } |
||
2566 | |||
2567 | if (texObj->MinFilter != texObj->MagFilter) { |
||
2568 | _mesa_problem(ctx, "mipmapped depth textures not supported at this time"); |
||
2569 | return; |
||
2570 | } |
||
2571 | |||
2572 | /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if |
||
2573 | * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object |
||
2574 | * isn't a depth texture. |
||
2575 | */ |
||
2576 | if (texImage->Format != GL_DEPTH_COMPONENT) { |
||
2577 | _mesa_problem(ctx,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture"); |
||
2578 | return; |
||
2579 | } |
||
2580 | |||
2581 | UNCLAMPED_FLOAT_TO_CHAN(ambient, tObj->ShadowAmbient); |
||
2582 | |||
2583 | if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) { |
||
2584 | lequal = GL_TRUE; |
||
2585 | gequal = GL_FALSE; |
||
2586 | } |
||
2587 | else { |
||
2588 | lequal = GL_FALSE; |
||
2589 | gequal = GL_TRUE; |
||
2590 | } |
||
2591 | |||
2592 | { |
||
2593 | GLuint i; |
||
2594 | for (i = 0; i < n; i++) { |
||
2595 | const GLint K = 3; |
||
2596 | GLint col, row, ii, jj, imin, imax, jmin, jmax, samples, count; |
||
2597 | GLfloat w; |
||
2598 | GLchan lum; |
||
2599 | COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapS, texcoords[i][0], |
||
2600 | width, col); |
||
2601 | COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, texcoords[i][1], |
||
2602 | height, row); |
||
2603 | |||
2604 | imin = col - K; |
||
2605 | imax = col + K; |
||
2606 | jmin = row - K; |
||
2607 | jmax = row + K; |
||
2608 | |||
2609 | if (imin < 0) imin = 0; |
||
2610 | if (imax >= width) imax = width - 1; |
||
2611 | if (jmin < 0) jmin = 0; |
||
2612 | if (jmax >= height) jmax = height - 1; |
||
2613 | |||
2614 | samples = (imax - imin + 1) * (jmax - jmin + 1); |
||
2615 | count = 0; |
||
2616 | for (jj = jmin; jj <= jmax; jj++) { |
||
2617 | for (ii = imin; ii <= imax; ii++) { |
||
2618 | GLfloat depthSample = *((const GLfloat *) texImage->Data |
||
2619 | + jj * width + ii); |
||
2620 | if ((depthSample <= r[i] && lequal) || |
||
2621 | (depthSample >= r[i] && gequal)) { |
||
2622 | count++; |
||
2623 | } |
||
2624 | } |
||
2625 | } |
||
2626 | |||
2627 | w = (GLfloat) count / (GLfloat) samples; |
||
2628 | w = CHAN_MAXF - w * (CHAN_MAXF - (GLfloat) ambient); |
||
2629 | lum = (GLint) w; |
||
2630 | |||
2631 | texel[i][RCOMP] = lum; |
||
2632 | texel[i][GCOMP] = lum; |
||
2633 | texel[i][BCOMP] = lum; |
||
2634 | texel[i][ACOMP] = CHAN_MAX; |
||
2635 | } |
||
2636 | } |
||
2637 | } |
||
2638 | #endif |
||
2639 | |||
2640 | |||
2641 | /** |
||
2642 | * We use this function when a texture object is in an "incomplete" state. |
||
2643 | */ |
||
2644 | static void |
||
2645 | null_sample_func( GLcontext *ctx, GLuint texUnit, |
||
2646 | const struct gl_texture_object *tObj, GLuint n, |
||
2647 | GLfloat texcoords[][4], const GLfloat lambda[], |
||
2648 | GLchan rgba[][4]) |
||
2649 | { |
||
2650 | } |
||
2651 | |||
2652 | |||
2653 | |||
2654 | /** |
||
2655 | * Setup the texture sampling function for this texture object. |
||
2656 | */ |
||
2657 | void |
||
2658 | _swrast_choose_texture_sample_func( GLcontext *ctx, GLuint texUnit, |
||
2659 | const struct gl_texture_object *t ) |
||
2660 | { |
||
2661 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
2662 | |||
2663 | if (!t->Complete) { |
||
2664 | swrast->TextureSample[texUnit] = null_sample_func; |
||
2665 | } |
||
2666 | else { |
||
2667 | const GLboolean needLambda = (GLboolean) (t->MinFilter != t->MagFilter); |
||
2668 | const GLenum format = t->Image[t->BaseLevel]->Format; |
||
2669 | |||
2670 | if (needLambda) { |
||
2671 | /* Compute min/mag filter threshold */ |
||
2672 | if (t->MagFilter == GL_LINEAR |
||
2673 | && (t->MinFilter == GL_NEAREST_MIPMAP_NEAREST || |
||
2674 | t->MinFilter == GL_NEAREST_MIPMAP_LINEAR)) { |
||
2675 | swrast->_MinMagThresh[texUnit] = 0.5F; |
||
2676 | } |
||
2677 | else { |
||
2678 | swrast->_MinMagThresh[texUnit] = 0.0F; |
||
2679 | } |
||
2680 | } |
||
2681 | |||
2682 | switch (t->Target) { |
||
2683 | case GL_TEXTURE_1D: |
||
2684 | if (format == GL_DEPTH_COMPONENT) { |
||
2685 | swrast->TextureSample[texUnit] = sample_depth_texture; |
||
2686 | } |
||
2687 | else if (needLambda) { |
||
2688 | swrast->TextureSample[texUnit] = sample_lambda_1d; |
||
2689 | } |
||
2690 | else if (t->MinFilter == GL_LINEAR) { |
||
2691 | swrast->TextureSample[texUnit] = sample_linear_1d; |
||
2692 | } |
||
2693 | else { |
||
2694 | ASSERT(t->MinFilter == GL_NEAREST); |
||
2695 | swrast->TextureSample[texUnit] = sample_nearest_1d; |
||
2696 | } |
||
2697 | break; |
||
2698 | case GL_TEXTURE_2D: |
||
2699 | if (format == GL_DEPTH_COMPONENT) { |
||
2700 | swrast->TextureSample[texUnit] = sample_depth_texture; |
||
2701 | } |
||
2702 | else if (needLambda) { |
||
2703 | swrast->TextureSample[texUnit] = sample_lambda_2d; |
||
2704 | } |
||
2705 | else if (t->MinFilter == GL_LINEAR) { |
||
2706 | swrast->TextureSample[texUnit] = sample_linear_2d; |
||
2707 | } |
||
2708 | else { |
||
2709 | GLint baseLevel = t->BaseLevel; |
||
2710 | ASSERT(t->MinFilter == GL_NEAREST); |
||
2711 | if (t->WrapS == GL_REPEAT && |
||
2712 | t->WrapT == GL_REPEAT && |
||
2713 | t->Image[baseLevel]->Border == 0 && |
||
2714 | t->Image[baseLevel]->TexFormat->MesaFormat == MESA_FORMAT_RGB) { |
||
2715 | swrast->TextureSample[texUnit] = opt_sample_rgb_2d; |
||
2716 | } |
||
2717 | else if (t->WrapS == GL_REPEAT && |
||
2718 | t->WrapT == GL_REPEAT && |
||
2719 | t->Image[baseLevel]->Border == 0 && |
||
2720 | t->Image[baseLevel]->TexFormat->MesaFormat == MESA_FORMAT_RGBA) { |
||
2721 | swrast->TextureSample[texUnit] = opt_sample_rgba_2d; |
||
2722 | } |
||
2723 | else |
||
2724 | swrast->TextureSample[texUnit] = sample_nearest_2d; |
||
2725 | } |
||
2726 | break; |
||
2727 | case GL_TEXTURE_3D: |
||
2728 | if (needLambda) { |
||
2729 | swrast->TextureSample[texUnit] = sample_lambda_3d; |
||
2730 | } |
||
2731 | else if (t->MinFilter == GL_LINEAR) { |
||
2732 | swrast->TextureSample[texUnit] = sample_linear_3d; |
||
2733 | } |
||
2734 | else { |
||
2735 | ASSERT(t->MinFilter == GL_NEAREST); |
||
2736 | swrast->TextureSample[texUnit] = sample_nearest_3d; |
||
2737 | } |
||
2738 | break; |
||
2739 | case GL_TEXTURE_CUBE_MAP_ARB: |
||
2740 | if (needLambda) { |
||
2741 | swrast->TextureSample[texUnit] = sample_lambda_cube; |
||
2742 | } |
||
2743 | else if (t->MinFilter == GL_LINEAR) { |
||
2744 | swrast->TextureSample[texUnit] = sample_linear_cube; |
||
2745 | } |
||
2746 | else { |
||
2747 | ASSERT(t->MinFilter == GL_NEAREST); |
||
2748 | swrast->TextureSample[texUnit] = sample_nearest_cube; |
||
2749 | } |
||
2750 | break; |
||
2751 | case GL_TEXTURE_RECTANGLE_NV: |
||
2752 | if (needLambda) { |
||
2753 | swrast->TextureSample[texUnit] = sample_lambda_rect; |
||
2754 | } |
||
2755 | else if (t->MinFilter == GL_LINEAR) { |
||
2756 | swrast->TextureSample[texUnit] = sample_linear_rect; |
||
2757 | } |
||
2758 | else { |
||
2759 | ASSERT(t->MinFilter == GL_NEAREST); |
||
2760 | swrast->TextureSample[texUnit] = sample_nearest_rect; |
||
2761 | } |
||
2762 | break; |
||
2763 | default: |
||
2764 | _mesa_problem(ctx, "invalid target in _swrast_choose_texture_sample_func"); |
||
2765 | } |
||
2766 | } |
||
2767 | } |
||
2768 | |||
2769 | |||
2770 | #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) ) |
||
2771 | #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) ) |
||
2772 | |||
2773 | |||
2774 | /** |
||
2775 | * Do texture application for GL_ARB/EXT_texture_env_combine. |
||
2776 | * Input: |
||
2777 | * ctx - rendering context |
||
2778 | * textureUnit - the texture unit to apply |
||
2779 | * n - number of fragments to process (span width) |
||
2780 | * primary_rgba - incoming fragment color array |
||
2781 | * texelBuffer - pointer to texel colors for all texture units |
||
2782 | * Input/Output: |
||
2783 | * rgba - incoming colors, which get modified here |
||
2784 | */ |
||
2785 | static INLINE void |
||
2786 | texture_combine( const GLcontext *ctx, GLuint unit, GLuint n, |
||
2787 | CONST GLchan (*primary_rgba)[4], |
||
2788 | CONST GLchan *texelBuffer, |
||
2789 | GLchan (*rgba)[4] ) |
||
2790 | { |
||
2791 | const struct gl_texture_unit *textureUnit = &(ctx->Texture.Unit[unit]); |
||
2792 | const GLchan (*argRGB [3])[4]; |
||
2793 | const GLchan (*argA [3])[4]; |
||
2794 | const GLuint RGBshift = textureUnit->CombineScaleShiftRGB; |
||
2795 | const GLuint Ashift = textureUnit->CombineScaleShiftA; |
||
2796 | #if CHAN_TYPE == GL_FLOAT |
||
2797 | const GLchan RGBmult = (GLfloat) (1 << RGBshift); |
||
2798 | const GLchan Amult = (GLfloat) (1 << Ashift); |
||
2799 | #else |
||
2800 | const GLint half = (CHAN_MAX + 1) / 2; |
||
2801 | #endif |
||
2802 | GLuint i, j; |
||
2803 | |||
2804 | /* GLchan ccolor[3][4]; */ |
||
2805 | DEFMNARRAY(GLchan, ccolor, 3, 3 * MAX_WIDTH, 4); /* mac 32k limitation */ |
||
2806 | CHECKARRAY(ccolor, return); /* mac 32k limitation */ |
||
2807 | |||
2808 | ASSERT(ctx->Extensions.EXT_texture_env_combine || |
||
2809 | ctx->Extensions.ARB_texture_env_combine); |
||
2810 | ASSERT(SWRAST_CONTEXT(ctx)->_AnyTextureCombine); |
||
2811 | |||
2812 | |||
2813 | /* |
||
2814 | printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n", |
||
2815 | textureUnit->CombineModeRGB, |
||
2816 | textureUnit->CombineModeA, |
||
2817 | textureUnit->CombineSourceRGB[0], |
||
2818 | textureUnit->CombineSourceA[0], |
||
2819 | textureUnit->CombineSourceRGB[1], |
||
2820 | textureUnit->CombineSourceA[1]); |
||
2821 | */ |
||
2822 | |||
2823 | /* |
||
2824 | * Do operand setup for up to 3 operands. Loop over the terms. |
||
2825 | */ |
||
2826 | for (j = 0; j < 3; j++) { |
||
2827 | const GLenum srcA = textureUnit->CombineSourceA[j]; |
||
2828 | const GLenum srcRGB = textureUnit->CombineSourceRGB[j]; |
||
2829 | |||
2830 | switch (srcA) { |
||
2831 | case GL_TEXTURE: |
||
2832 | argA[j] = (const GLchan (*)[4]) |
||
2833 | (texelBuffer + unit * (n * 4 * sizeof(GLchan))); |
||
2834 | break; |
||
2835 | case GL_PRIMARY_COLOR_EXT: |
||
2836 | argA[j] = primary_rgba; |
||
2837 | break; |
||
2838 | case GL_PREVIOUS_EXT: |
||
2839 | argA[j] = (const GLchan (*)[4]) rgba; |
||
2840 | break; |
||
2841 | case GL_CONSTANT_EXT: |
||
2842 | { |
||
2843 | GLchan alpha, (*c)[4] = ccolor[j]; |
||
2844 | UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]); |
||
2845 | for (i = 0; i < n; i++) |
||
2846 | c[i][ACOMP] = alpha; |
||
2847 | argA[j] = (const GLchan (*)[4]) ccolor[j]; |
||
2848 | } |
||
2849 | break; |
||
2850 | default: |
||
2851 | /* ARB_texture_env_crossbar source */ |
||
2852 | { |
||
2853 | const GLuint srcUnit = srcA - GL_TEXTURE0_ARB; |
||
2854 | ASSERT(srcUnit < ctx->Const.MaxTextureUnits); |
||
2855 | if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled) |
||
2856 | return; |
||
2857 | argA[j] = (const GLchan (*)[4]) |
||
2858 | (texelBuffer + srcUnit * (n * 4 * sizeof(GLchan))); |
||
2859 | } |
||
2860 | } |
||
2861 | |||
2862 | switch (srcRGB) { |
||
2863 | case GL_TEXTURE: |
||
2864 | argRGB[j] = (const GLchan (*)[4]) |
||
2865 | (texelBuffer + unit * (n * 4 * sizeof(GLchan))); |
||
2866 | break; |
||
2867 | case GL_PRIMARY_COLOR_EXT: |
||
2868 | argRGB[j] = primary_rgba; |
||
2869 | break; |
||
2870 | case GL_PREVIOUS_EXT: |
||
2871 | argRGB[j] = (const GLchan (*)[4]) rgba; |
||
2872 | break; |
||
2873 | case GL_CONSTANT_EXT: |
||
2874 | { |
||
2875 | GLchan (*c)[4] = ccolor[j]; |
||
2876 | GLchan red, green, blue, alpha; |
||
2877 | UNCLAMPED_FLOAT_TO_CHAN(red, textureUnit->EnvColor[0]); |
||
2878 | UNCLAMPED_FLOAT_TO_CHAN(green, textureUnit->EnvColor[1]); |
||
2879 | UNCLAMPED_FLOAT_TO_CHAN(blue, textureUnit->EnvColor[2]); |
||
2880 | UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]); |
||
2881 | for (i = 0; i < n; i++) { |
||
2882 | c[i][RCOMP] = red; |
||
2883 | c[i][GCOMP] = green; |
||
2884 | c[i][BCOMP] = blue; |
||
2885 | c[i][ACOMP] = alpha; |
||
2886 | } |
||
2887 | argRGB[j] = (const GLchan (*)[4]) ccolor[j]; |
||
2888 | } |
||
2889 | break; |
||
2890 | default: |
||
2891 | /* ARB_texture_env_crossbar source */ |
||
2892 | { |
||
2893 | const GLuint srcUnit = srcRGB - GL_TEXTURE0_ARB; |
||
2894 | ASSERT(srcUnit < ctx->Const.MaxTextureUnits); |
||
2895 | if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled) |
||
2896 | return; |
||
2897 | argRGB[j] = (const GLchan (*)[4]) |
||
2898 | (texelBuffer + srcUnit * (n * 4 * sizeof(GLchan))); |
||
2899 | } |
||
2900 | } |
||
2901 | |||
2902 | if (textureUnit->CombineOperandRGB[j] != GL_SRC_COLOR) { |
||
2903 | const GLchan (*src)[4] = argRGB[j]; |
||
2904 | GLchan (*dst)[4] = ccolor[j]; |
||
2905 | |||
2906 | /* point to new arg[j] storage */ |
||
2907 | argRGB[j] = (const GLchan (*)[4]) ccolor[j]; |
||
2908 | |||
2909 | if (textureUnit->CombineOperandRGB[j] == GL_ONE_MINUS_SRC_COLOR) { |
||
2910 | for (i = 0; i < n; i++) { |
||
2911 | dst[i][RCOMP] = CHAN_MAX - src[i][RCOMP]; |
||
2912 | dst[i][GCOMP] = CHAN_MAX - src[i][GCOMP]; |
||
2913 | dst[i][BCOMP] = CHAN_MAX - src[i][BCOMP]; |
||
2914 | } |
||
2915 | } |
||
2916 | else if (textureUnit->CombineOperandRGB[j] == GL_SRC_ALPHA) { |
||
2917 | for (i = 0; i < n; i++) { |
||
2918 | dst[i][RCOMP] = src[i][ACOMP]; |
||
2919 | dst[i][GCOMP] = src[i][ACOMP]; |
||
2920 | dst[i][BCOMP] = src[i][ACOMP]; |
||
2921 | } |
||
2922 | } |
||
2923 | else { |
||
2924 | ASSERT(textureUnit->CombineOperandRGB[j] ==GL_ONE_MINUS_SRC_ALPHA); |
||
2925 | for (i = 0; i < n; i++) { |
||
2926 | dst[i][RCOMP] = CHAN_MAX - src[i][ACOMP]; |
||
2927 | dst[i][GCOMP] = CHAN_MAX - src[i][ACOMP]; |
||
2928 | dst[i][BCOMP] = CHAN_MAX - src[i][ACOMP]; |
||
2929 | } |
||
2930 | } |
||
2931 | } |
||
2932 | |||
2933 | if (textureUnit->CombineOperandA[j] == GL_ONE_MINUS_SRC_ALPHA) { |
||
2934 | const GLchan (*src)[4] = argA[j]; |
||
2935 | GLchan (*dst)[4] = ccolor[j]; |
||
2936 | argA[j] = (const GLchan (*)[4]) ccolor[j]; |
||
2937 | for (i = 0; i < n; i++) { |
||
2938 | dst[i][ACOMP] = CHAN_MAX - src[i][ACOMP]; |
||
2939 | } |
||
2940 | } |
||
2941 | |||
2942 | if (textureUnit->CombineModeRGB == GL_REPLACE && |
||
2943 | textureUnit->CombineModeA == GL_REPLACE) { |
||
2944 | break; /* done, we need only arg0 */ |
||
2945 | } |
||
2946 | |||
2947 | if (j == 1 && |
||
2948 | textureUnit->CombineModeRGB != GL_INTERPOLATE_EXT && |
||
2949 | textureUnit->CombineModeA != GL_INTERPOLATE_EXT) { |
||
2950 | break; /* arg0 and arg1 are done. we don't need arg2. */ |
||
2951 | } |
||
2952 | } |
||
2953 | |||
2954 | /* |
||
2955 | * Do the texture combine. |
||
2956 | */ |
||
2957 | switch (textureUnit->CombineModeRGB) { |
||
2958 | case GL_REPLACE: |
||
2959 | { |
||
2960 | const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0]; |
||
2961 | if (RGBshift) { |
||
2962 | for (i = 0; i < n; i++) { |
||
2963 | #if CHAN_TYPE == GL_FLOAT |
||
2964 | rgba[i][RCOMP] = arg0[i][RCOMP] * RGBmult; |
||
2965 | rgba[i][GCOMP] = arg0[i][GCOMP] * RGBmult; |
||
2966 | rgba[i][BCOMP] = arg0[i][BCOMP] * RGBmult; |
||
2967 | #else |
||
2968 | GLuint r = (GLuint) arg0[i][RCOMP] << RGBshift; |
||
2969 | GLuint g = (GLuint) arg0[i][GCOMP] << RGBshift; |
||
2970 | GLuint b = (GLuint) arg0[i][BCOMP] << RGBshift; |
||
2971 | rgba[i][RCOMP] = MIN2(r, CHAN_MAX); |
||
2972 | rgba[i][GCOMP] = MIN2(g, CHAN_MAX); |
||
2973 | rgba[i][BCOMP] = MIN2(b, CHAN_MAX); |
||
2974 | #endif |
||
2975 | } |
||
2976 | } |
||
2977 | else { |
||
2978 | for (i = 0; i < n; i++) { |
||
2979 | rgba[i][RCOMP] = arg0[i][RCOMP]; |
||
2980 | rgba[i][GCOMP] = arg0[i][GCOMP]; |
||
2981 | rgba[i][BCOMP] = arg0[i][BCOMP]; |
||
2982 | } |
||
2983 | } |
||
2984 | } |
||
2985 | break; |
||
2986 | case GL_MODULATE: |
||
2987 | { |
||
2988 | const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0]; |
||
2989 | const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1]; |
||
2990 | #if CHAN_TYPE != GL_FLOAT |
||
2991 | const GLint shift = CHAN_BITS - RGBshift; |
||
2992 | #endif |
||
2993 | for (i = 0; i < n; i++) { |
||
2994 | #if CHAN_TYPE == GL_FLOAT |
||
2995 | rgba[i][RCOMP] = arg0[i][RCOMP] * arg1[i][RCOMP] * RGBmult; |
||
2996 | rgba[i][GCOMP] = arg0[i][GCOMP] * arg1[i][GCOMP] * RGBmult; |
||
2997 | rgba[i][BCOMP] = arg0[i][BCOMP] * arg1[i][BCOMP] * RGBmult; |
||
2998 | #else |
||
2999 | GLuint r = PROD(arg0[i][RCOMP], arg1[i][RCOMP]) >> shift; |
||
3000 | GLuint g = PROD(arg0[i][GCOMP], arg1[i][GCOMP]) >> shift; |
||
3001 | GLuint b = PROD(arg0[i][BCOMP], arg1[i][BCOMP]) >> shift; |
||
3002 | rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX); |
||
3003 | rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX); |
||
3004 | rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX); |
||
3005 | #endif |
||
3006 | } |
||
3007 | } |
||
3008 | break; |
||
3009 | case GL_ADD: |
||
3010 | { |
||
3011 | const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0]; |
||
3012 | const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1]; |
||
3013 | for (i = 0; i < n; i++) { |
||
3014 | #if CHAN_TYPE == GL_FLOAT |
||
3015 | rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP]) * RGBmult; |
||
3016 | rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP]) * RGBmult; |
||
3017 | rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP]) * RGBmult; |
||
3018 | #else |
||
3019 | GLint r = ((GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP]) << RGBshift; |
||
3020 | GLint g = ((GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP]) << RGBshift; |
||
3021 | GLint b = ((GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP]) << RGBshift; |
||
3022 | rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX); |
||
3023 | rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX); |
||
3024 | rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX); |
||
3025 | #endif |
||
3026 | } |
||
3027 | } |
||
3028 | break; |
||
3029 | case GL_ADD_SIGNED_EXT: |
||
3030 | { |
||
3031 | const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0]; |
||
3032 | const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1]; |
||
3033 | for (i = 0; i < n; i++) { |
||
3034 | #if CHAN_TYPE == GL_FLOAT |
||
3035 | rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] - 0.5) * RGBmult; |
||
3036 | rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] - 0.5) * RGBmult; |
||
3037 | rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] - 0.5) * RGBmult; |
||
3038 | #else |
||
3039 | GLint r = (GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP] -half; |
||
3040 | GLint g = (GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP] -half; |
||
3041 | GLint b = (GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP] -half; |
||
3042 | r = (r < 0) ? 0 : r << RGBshift; |
||
3043 | g = (g < 0) ? 0 : g << RGBshift; |
||
3044 | b = (b < 0) ? 0 : b << RGBshift; |
||
3045 | rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX); |
||
3046 | rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX); |
||
3047 | rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX); |
||
3048 | #endif |
||
3049 | } |
||
3050 | } |
||
3051 | break; |
||
3052 | case GL_INTERPOLATE_EXT: |
||
3053 | { |
||
3054 | const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0]; |
||
3055 | const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1]; |
||
3056 | const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2]; |
||
3057 | #if CHAN_TYPE != GL_FLOAT |
||
3058 | const GLint shift = CHAN_BITS - RGBshift; |
||
3059 | #endif |
||
3060 | for (i = 0; i < n; i++) { |
||
3061 | #if CHAN_TYPE == GL_FLOAT |
||
3062 | rgba[i][RCOMP] = (arg0[i][RCOMP] * arg2[i][RCOMP] + |
||
3063 | arg1[i][RCOMP] * (CHAN_MAXF - arg2[i][RCOMP])) * RGBmult; |
||
3064 | rgba[i][GCOMP] = (arg0[i][GCOMP] * arg2[i][GCOMP] + |
||
3065 | arg1[i][GCOMP] * (CHAN_MAXF - arg2[i][GCOMP])) * RGBmult; |
||
3066 | rgba[i][BCOMP] = (arg0[i][BCOMP] * arg2[i][BCOMP] + |
||
3067 | arg1[i][BCOMP] * (CHAN_MAXF - arg2[i][BCOMP])) * RGBmult; |
||
3068 | #else |
||
3069 | GLuint r = (PROD(arg0[i][RCOMP], arg2[i][RCOMP]) |
||
3070 | + PROD(arg1[i][RCOMP], CHAN_MAX - arg2[i][RCOMP])) |
||
3071 | >> shift; |
||
3072 | GLuint g = (PROD(arg0[i][GCOMP], arg2[i][GCOMP]) |
||
3073 | + PROD(arg1[i][GCOMP], CHAN_MAX - arg2[i][GCOMP])) |
||
3074 | >> shift; |
||
3075 | GLuint b = (PROD(arg0[i][BCOMP], arg2[i][BCOMP]) |
||
3076 | + PROD(arg1[i][BCOMP], CHAN_MAX - arg2[i][BCOMP])) |
||
3077 | >> shift; |
||
3078 | rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX); |
||
3079 | rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX); |
||
3080 | rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX); |
||
3081 | #endif |
||
3082 | } |
||
3083 | } |
||
3084 | break; |
||
3085 | case GL_SUBTRACT_ARB: |
||
3086 | { |
||
3087 | const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0]; |
||
3088 | const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1]; |
||
3089 | for (i = 0; i < n; i++) { |
||
3090 | #if CHAN_TYPE == GL_FLOAT |
||
3091 | rgba[i][RCOMP] = (arg0[i][RCOMP] - arg1[i][RCOMP]) * RGBmult; |
||
3092 | rgba[i][GCOMP] = (arg0[i][GCOMP] - arg1[i][GCOMP]) * RGBmult; |
||
3093 | rgba[i][BCOMP] = (arg0[i][BCOMP] - arg1[i][BCOMP]) * RGBmult; |
||
3094 | #else |
||
3095 | GLint r = ((GLint) arg0[i][RCOMP] - (GLint) arg1[i][RCOMP]) << RGBshift; |
||
3096 | GLint g = ((GLint) arg0[i][GCOMP] - (GLint) arg1[i][GCOMP]) << RGBshift; |
||
3097 | GLint b = ((GLint) arg0[i][BCOMP] - (GLint) arg1[i][BCOMP]) << RGBshift; |
||
3098 | rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX); |
||
3099 | rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX); |
||
3100 | rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX); |
||
3101 | #endif |
||
3102 | } |
||
3103 | } |
||
3104 | break; |
||
3105 | case GL_DOT3_RGB_EXT: |
||
3106 | case GL_DOT3_RGBA_EXT: |
||
3107 | { |
||
3108 | /* Do not scale the result by 1 2 or 4 */ |
||
3109 | const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0]; |
||
3110 | const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1]; |
||
3111 | for (i = 0; i < n; i++) { |
||
3112 | #if CHAN_TYPE == GL_FLOAT |
||
3113 | GLchan dot = ((arg0[i][RCOMP]-0.5F) * (arg1[i][RCOMP]-0.5F) + |
||
3114 | (arg0[i][GCOMP]-0.5F) * (arg1[i][GCOMP]-0.5F) + |
||
3115 | (arg0[i][BCOMP]-0.5F) * (arg1[i][BCOMP]-0.5F)) |
||
3116 | * 4.0F; |
||
3117 | dot = CLAMP(dot, 0.0F, CHAN_MAXF); |
||
3118 | #else |
||
3119 | GLint dot = (S_PROD((GLint)arg0[i][RCOMP] - half, |
||
3120 | (GLint)arg1[i][RCOMP] - half) + |
||
3121 | S_PROD((GLint)arg0[i][GCOMP] - half, |
||
3122 | (GLint)arg1[i][GCOMP] - half) + |
||
3123 | S_PROD((GLint)arg0[i][BCOMP] - half, |
||
3124 | (GLint)arg1[i][BCOMP] - half)) >> 6; |
||
3125 | dot = CLAMP(dot, 0, CHAN_MAX); |
||
3126 | #endif |
||
3127 | rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = (GLchan) dot; |
||
3128 | } |
||
3129 | } |
||
3130 | break; |
||
3131 | case GL_DOT3_RGB_ARB: |
||
3132 | case GL_DOT3_RGBA_ARB: |
||
3133 | { |
||
3134 | /* DO scale the result by 1 2 or 4 */ |
||
3135 | const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0]; |
||
3136 | const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1]; |
||
3137 | for (i = 0; i < n; i++) { |
||
3138 | #if CHAN_TYPE == GL_FLOAT |
||
3139 | GLchan dot = ((arg0[i][RCOMP]-0.5F) * (arg1[i][RCOMP]-0.5F) + |
||
3140 | (arg0[i][GCOMP]-0.5F) * (arg1[i][GCOMP]-0.5F) + |
||
3141 | (arg0[i][BCOMP]-0.5F) * (arg1[i][BCOMP]-0.5F)) |
||
3142 | * 4.0F * RGBmult; |
||
3143 | dot = CLAMP(dot, 0.0, CHAN_MAXF); |
||
3144 | #else |
||
3145 | GLint dot = (S_PROD((GLint)arg0[i][RCOMP] - half, |
||
3146 | (GLint)arg1[i][RCOMP] - half) + |
||
3147 | S_PROD((GLint)arg0[i][GCOMP] - half, |
||
3148 | (GLint)arg1[i][GCOMP] - half) + |
||
3149 | S_PROD((GLint)arg0[i][BCOMP] - half, |
||
3150 | (GLint)arg1[i][BCOMP] - half)) >> 6; |
||
3151 | dot <<= RGBshift; |
||
3152 | dot = CLAMP(dot, 0, CHAN_MAX); |
||
3153 | #endif |
||
3154 | rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = (GLchan) dot; |
||
3155 | } |
||
3156 | } |
||
3157 | break; |
||
3158 | default: |
||
3159 | _mesa_problem(ctx, "invalid combine mode"); |
||
3160 | } |
||
3161 | |||
3162 | switch (textureUnit->CombineModeA) { |
||
3163 | case GL_REPLACE: |
||
3164 | { |
||
3165 | const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0]; |
||
3166 | if (Ashift) { |
||
3167 | for (i = 0; i < n; i++) { |
||
3168 | #if CHAN_TYPE == GL_FLOAT |
||
3169 | GLchan a = arg0[i][ACOMP] * Amult; |
||
3170 | #else |
||
3171 | GLuint a = (GLuint) arg0[i][ACOMP] << Ashift; |
||
3172 | #endif |
||
3173 | rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX); |
||
3174 | } |
||
3175 | } |
||
3176 | else { |
||
3177 | for (i = 0; i < n; i++) { |
||
3178 | rgba[i][ACOMP] = arg0[i][ACOMP]; |
||
3179 | } |
||
3180 | } |
||
3181 | } |
||
3182 | break; |
||
3183 | case GL_MODULATE: |
||
3184 | { |
||
3185 | const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0]; |
||
3186 | const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1]; |
||
3187 | #if CHAN_TYPE != GL_FLOAT |
||
3188 | const GLint shift = CHAN_BITS - Ashift; |
||
3189 | #endif |
||
3190 | for (i = 0; i < n; i++) { |
||
3191 | #if CHAN_TYPE == GL_FLOAT |
||
3192 | rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * Amult; |
||
3193 | #else |
||
3194 | GLuint a = (PROD(arg0[i][ACOMP], arg1[i][ACOMP]) >> shift); |
||
3195 | rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX); |
||
3196 | #endif |
||
3197 | } |
||
3198 | } |
||
3199 | break; |
||
3200 | case GL_ADD: |
||
3201 | { |
||
3202 | const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0]; |
||
3203 | const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1]; |
||
3204 | for (i = 0; i < n; i++) { |
||
3205 | #if CHAN_TYPE == GL_FLOAT |
||
3206 | rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * Amult; |
||
3207 | #else |
||
3208 | GLint a = ((GLint) arg0[i][ACOMP] + arg1[i][ACOMP]) << Ashift; |
||
3209 | rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX); |
||
3210 | #endif |
||
3211 | } |
||
3212 | } |
||
3213 | break; |
||
3214 | case GL_ADD_SIGNED_EXT: |
||
3215 | { |
||
3216 | const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0]; |
||
3217 | const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1]; |
||
3218 | for (i = 0; i < n; i++) { |
||
3219 | #if CHAN_TYPE == GL_FLOAT |
||
3220 | rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * Amult; |
||
3221 | #else |
||
3222 | GLint a = (GLint) arg0[i][ACOMP] + (GLint) arg1[i][ACOMP] -half; |
||
3223 | a = (a < 0) ? 0 : a << Ashift; |
||
3224 | rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX); |
||
3225 | #endif |
||
3226 | } |
||
3227 | } |
||
3228 | break; |
||
3229 | case GL_INTERPOLATE_EXT: |
||
3230 | { |
||
3231 | const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0]; |
||
3232 | const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1]; |
||
3233 | const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2]; |
||
3234 | #if CHAN_TYPE != GL_FLOAT |
||
3235 | const GLint shift = CHAN_BITS - Ashift; |
||
3236 | #endif |
||
3237 | for (i=0; i<n; i++) { |
||
3238 | #if CHAN_TYPE == GL_FLOAT |
||
3239 | rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] + |
||
3240 | arg1[i][ACOMP] * (CHAN_MAXF - arg2[i][ACOMP])) |
||
3241 | * Amult; |
||
3242 | #else |
||
3243 | GLuint a = (PROD(arg0[i][ACOMP], arg2[i][ACOMP]) |
||
3244 | + PROD(arg1[i][ACOMP], CHAN_MAX - arg2[i][ACOMP])) |
||
3245 | >> shift; |
||
3246 | rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX); |
||
3247 | #endif |
||
3248 | } |
||
3249 | } |
||
3250 | break; |
||
3251 | case GL_SUBTRACT_ARB: |
||
3252 | { |
||
3253 | const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0]; |
||
3254 | const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1]; |
||
3255 | for (i = 0; i < n; i++) { |
||
3256 | #if CHAN_TYPE == GL_FLOAT |
||
3257 | rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * Amult; |
||
3258 | #else |
||
3259 | GLint a = ((GLint) arg0[i][ACOMP] - (GLint) arg1[i][ACOMP]) << Ashift; |
||
3260 | rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX); |
||
3261 | #endif |
||
3262 | } |
||
3263 | } |
||
3264 | break; |
||
3265 | |||
3266 | default: |
||
3267 | _mesa_problem(ctx, "invalid combine mode"); |
||
3268 | } |
||
3269 | |||
3270 | /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining. |
||
3271 | * This is kind of a kludge. It would have been better if the spec |
||
3272 | * were written such that the GL_COMBINE_ALPHA value could be set to |
||
3273 | * GL_DOT3. |
||
3274 | */ |
||
3275 | if (textureUnit->CombineModeRGB == GL_DOT3_RGBA_EXT || |
||
3276 | textureUnit->CombineModeRGB == GL_DOT3_RGBA_ARB) { |
||
3277 | for (i = 0; i < n; i++) { |
||
3278 | rgba[i][ACOMP] = rgba[i][RCOMP]; |
||
3279 | } |
||
3280 | } |
||
3281 | UNDEFARRAY(ccolor); /* mac 32k limitation */ |
||
3282 | } |
||
3283 | #undef PROD |
||
3284 | |||
3285 | |||
3286 | /** |
||
3287 | * Implement NVIDIA's GL_NV_texture_env_combine4 extension when |
||
3288 | * texUnit->EnvMode == GL_COMBINE4_NV. |
||
3289 | */ |
||
3290 | static INLINE void |
||
3291 | texture_combine4( const GLcontext *ctx, GLuint unit, GLuint n, |
||
3292 | CONST GLchan (*primary_rgba)[4], |
||
3293 | CONST GLchan *texelBuffer, |
||
3294 | GLchan (*rgba)[4] ) |
||
3295 | { |
||
3296 | } |
||
3297 | |||
3298 | |||
3299 | |||
3300 | /** |
||
3301 | * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND, |
||
3302 | * MODULATE, or DECAL) to an array of fragments. |
||
3303 | * Input: textureUnit - pointer to texture unit to apply |
||
3304 | * format - base internal texture format |
||
3305 | * n - number of fragments |
||
3306 | * primary_rgba - primary colors (may alias rgba for single texture) |
||
3307 | * texels - array of texel colors |
||
3308 | * InOut: rgba - incoming fragment colors modified by texel colors |
||
3309 | * according to the texture environment mode. |
||
3310 | */ |
||
3311 | static void |
||
3312 | texture_apply( const GLcontext *ctx, |
||
3313 | const struct gl_texture_unit *texUnit, |
||
3314 | GLuint n, |
||
3315 | CONST GLchan primary_rgba[][4], CONST GLchan texel[][4], |
||
3316 | GLchan rgba[][4] ) |
||
3317 | { |
||
3318 | GLint baseLevel; |
||
3319 | GLuint i; |
||
3320 | GLint Rc, Gc, Bc, Ac; |
||
3321 | GLenum format; |
||
3322 | |||
3323 | ASSERT(texUnit); |
||
3324 | ASSERT(texUnit->_Current); |
||
3325 | |||
3326 | baseLevel = texUnit->_Current->BaseLevel; |
||
3327 | ASSERT(texUnit->_Current->Image[baseLevel]); |
||
3328 | |||
3329 | format = texUnit->_Current->Image[baseLevel]->Format; |
||
3330 | |||
3331 | if (format == GL_COLOR_INDEX || format == GL_DEPTH_COMPONENT |
||
3332 | || format == GL_YCBCR_MESA) { |
||
3333 | format = GL_RGBA; /* a bit of a hack */ |
||
3334 | } |
||
3335 | |||
3336 | switch (texUnit->EnvMode) { |
||
3337 | case GL_REPLACE: |
||
3338 | switch (format) { |
||
3339 | case GL_ALPHA: |
||
3340 | for (i=0;i<n;i++) { |
||
3341 | /* Cv = Cf */ |
||
3342 | /* Av = At */ |
||
3343 | rgba[i][ACOMP] = texel[i][ACOMP]; |
||
3344 | } |
||
3345 | break; |
||
3346 | case GL_LUMINANCE: |
||
3347 | for (i=0;i<n;i++) { |
||
3348 | /* Cv = Lt */ |
||
3349 | GLchan Lt = texel[i][RCOMP]; |
||
3350 | rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt; |
||
3351 | /* Av = Af */ |
||
3352 | } |
||
3353 | break; |
||
3354 | case GL_LUMINANCE_ALPHA: |
||
3355 | for (i=0;i<n;i++) { |
||
3356 | GLchan Lt = texel[i][RCOMP]; |
||
3357 | /* Cv = Lt */ |
||
3358 | rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt; |
||
3359 | /* Av = At */ |
||
3360 | rgba[i][ACOMP] = texel[i][ACOMP]; |
||
3361 | } |
||
3362 | break; |
||
3363 | case GL_INTENSITY: |
||
3364 | for (i=0;i<n;i++) { |
||
3365 | /* Cv = It */ |
||
3366 | GLchan It = texel[i][RCOMP]; |
||
3367 | rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = It; |
||
3368 | /* Av = It */ |
||
3369 | rgba[i][ACOMP] = It; |
||
3370 | } |
||
3371 | break; |
||
3372 | case GL_RGB: |
||
3373 | for (i=0;i<n;i++) { |
||
3374 | /* Cv = Ct */ |
||
3375 | rgba[i][RCOMP] = texel[i][RCOMP]; |
||
3376 | rgba[i][GCOMP] = texel[i][GCOMP]; |
||
3377 | rgba[i][BCOMP] = texel[i][BCOMP]; |
||
3378 | /* Av = Af */ |
||
3379 | } |
||
3380 | break; |
||
3381 | case GL_RGBA: |
||
3382 | for (i=0;i<n;i++) { |
||
3383 | /* Cv = Ct */ |
||
3384 | rgba[i][RCOMP] = texel[i][RCOMP]; |
||
3385 | rgba[i][GCOMP] = texel[i][GCOMP]; |
||
3386 | rgba[i][BCOMP] = texel[i][BCOMP]; |
||
3387 | /* Av = At */ |
||
3388 | rgba[i][ACOMP] = texel[i][ACOMP]; |
||
3389 | } |
||
3390 | break; |
||
3391 | default: |
||
3392 | _mesa_problem(ctx, "Bad format (GL_REPLACE) in texture_apply"); |
||
3393 | return; |
||
3394 | } |
||
3395 | break; |
||
3396 | |||
3397 | case GL_MODULATE: |
||
3398 | switch (format) { |
||
3399 | case GL_ALPHA: |
||
3400 | for (i=0;i<n;i++) { |
||
3401 | /* Cv = Cf */ |
||
3402 | /* Av = AfAt */ |
||
3403 | rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] ); |
||
3404 | } |
||
3405 | break; |
||
3406 | case GL_LUMINANCE: |
||
3407 | for (i=0;i<n;i++) { |
||
3408 | /* Cv = LtCf */ |
||
3409 | GLchan Lt = texel[i][RCOMP]; |
||
3410 | rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt ); |
||
3411 | rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt ); |
||
3412 | rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt ); |
||
3413 | /* Av = Af */ |
||
3414 | } |
||
3415 | break; |
||
3416 | case GL_LUMINANCE_ALPHA: |
||
3417 | for (i=0;i<n;i++) { |
||
3418 | /* Cv = CfLt */ |
||
3419 | GLchan Lt = texel[i][RCOMP]; |
||
3420 | rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt ); |
||
3421 | rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt ); |
||
3422 | rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt ); |
||
3423 | /* Av = AfAt */ |
||
3424 | rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] ); |
||
3425 | } |
||
3426 | break; |
||
3427 | case GL_INTENSITY: |
||
3428 | for (i=0;i<n;i++) { |
||
3429 | /* Cv = CfIt */ |
||
3430 | GLchan It = texel[i][RCOMP]; |
||
3431 | rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], It ); |
||
3432 | rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], It ); |
||
3433 | rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], It ); |
||
3434 | /* Av = AfIt */ |
||
3435 | rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], It ); |
||
3436 | } |
||
3437 | break; |
||
3438 | case GL_RGB: |
||
3439 | for (i=0;i<n;i++) { |
||
3440 | /* Cv = CfCt */ |
||
3441 | rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] ); |
||
3442 | rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] ); |
||
3443 | rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] ); |
||
3444 | /* Av = Af */ |
||
3445 | } |
||
3446 | break; |
||
3447 | case GL_RGBA: |
||
3448 | for (i=0;i<n;i++) { |
||
3449 | /* Cv = CfCt */ |
||
3450 | rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] ); |
||
3451 | rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] ); |
||
3452 | rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] ); |
||
3453 | /* Av = AfAt */ |
||
3454 | rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] ); |
||
3455 | } |
||
3456 | break; |
||
3457 | default: |
||
3458 | _mesa_problem(ctx, "Bad format (GL_MODULATE) in texture_apply"); |
||
3459 | return; |
||
3460 | } |
||
3461 | break; |
||
3462 | |||
3463 | case GL_DECAL: |
||
3464 | switch (format) { |
||
3465 | case GL_ALPHA: |
||
3466 | case GL_LUMINANCE: |
||
3467 | case GL_LUMINANCE_ALPHA: |
||
3468 | case GL_INTENSITY: |
||
3469 | /* undefined */ |
||
3470 | break; |
||
3471 | case GL_RGB: |
||
3472 | for (i=0;i<n;i++) { |
||
3473 | /* Cv = Ct */ |
||
3474 | rgba[i][RCOMP] = texel[i][RCOMP]; |
||
3475 | rgba[i][GCOMP] = texel[i][GCOMP]; |
||
3476 | rgba[i][BCOMP] = texel[i][BCOMP]; |
||
3477 | /* Av = Af */ |
||
3478 | } |
||
3479 | break; |
||
3480 | case GL_RGBA: |
||
3481 | for (i=0;i<n;i++) { |
||
3482 | /* Cv = Cf(1-At) + CtAt */ |
||
3483 | GLint t = texel[i][ACOMP], s = CHAN_MAX - t; |
||
3484 | rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(texel[i][RCOMP],t); |
||
3485 | rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(texel[i][GCOMP],t); |
||
3486 | rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(texel[i][BCOMP],t); |
||
3487 | /* Av = Af */ |
||
3488 | } |
||
3489 | break; |
||
3490 | default: |
||
3491 | _mesa_problem(ctx, "Bad format (GL_DECAL) in texture_apply"); |
||
3492 | return; |
||
3493 | } |
||
3494 | break; |
||
3495 | |||
3496 | case GL_BLEND: |
||
3497 | Rc = (GLint) (texUnit->EnvColor[0] * CHAN_MAXF); |
||
3498 | Gc = (GLint) (texUnit->EnvColor[1] * CHAN_MAXF); |
||
3499 | Bc = (GLint) (texUnit->EnvColor[2] * CHAN_MAXF); |
||
3500 | Ac = (GLint) (texUnit->EnvColor[3] * CHAN_MAXF); |
||
3501 | switch (format) { |
||
3502 | case GL_ALPHA: |
||
3503 | for (i=0;i<n;i++) { |
||
3504 | /* Cv = Cf */ |
||
3505 | /* Av = AfAt */ |
||
3506 | rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]); |
||
3507 | } |
||
3508 | break; |
||
3509 | case GL_LUMINANCE: |
||
3510 | for (i=0;i<n;i++) { |
||
3511 | /* Cv = Cf(1-Lt) + CcLt */ |
||
3512 | GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt; |
||
3513 | rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt); |
||
3514 | rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt); |
||
3515 | rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt); |
||
3516 | /* Av = Af */ |
||
3517 | } |
||
3518 | break; |
||
3519 | case GL_LUMINANCE_ALPHA: |
||
3520 | for (i=0;i<n;i++) { |
||
3521 | /* Cv = Cf(1-Lt) + CcLt */ |
||
3522 | GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt; |
||
3523 | rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt); |
||
3524 | rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt); |
||
3525 | rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt); |
||
3526 | /* Av = AfAt */ |
||
3527 | rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]); |
||
3528 | } |
||
3529 | break; |
||
3530 | case GL_INTENSITY: |
||
3531 | for (i=0;i<n;i++) { |
||
3532 | /* Cv = Cf(1-It) + CcLt */ |
||
3533 | GLchan It = texel[i][RCOMP], s = CHAN_MAX - It; |
||
3534 | rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, It); |
||
3535 | rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, It); |
||
3536 | rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, It); |
||
3537 | /* Av = Af(1-It) + Ac*It */ |
||
3538 | rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], s) + CHAN_PRODUCT(Ac, It); |
||
3539 | } |
||
3540 | break; |
||
3541 | case GL_RGB: |
||
3542 | for (i=0;i<n;i++) { |
||
3543 | /* Cv = Cf(1-Ct) + CcCt */ |
||
3544 | rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]); |
||
3545 | rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]); |
||
3546 | rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]); |
||
3547 | /* Av = Af */ |
||
3548 | } |
||
3549 | break; |
||
3550 | case GL_RGBA: |
||
3551 | for (i=0;i<n;i++) { |
||
3552 | /* Cv = Cf(1-Ct) + CcCt */ |
||
3553 | rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]); |
||
3554 | rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]); |
||
3555 | rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]); |
||
3556 | /* Av = AfAt */ |
||
3557 | rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]); |
||
3558 | } |
||
3559 | break; |
||
3560 | default: |
||
3561 | _mesa_problem(ctx, "Bad format (GL_BLEND) in texture_apply"); |
||
3562 | return; |
||
3563 | } |
||
3564 | break; |
||
3565 | |||
3566 | /* XXX don't clamp results if GLchan is float??? */ |
||
3567 | |||
3568 | case GL_ADD: /* GL_EXT_texture_add_env */ |
||
3569 | switch (format) { |
||
3570 | case GL_ALPHA: |
||
3571 | for (i=0;i<n;i++) { |
||
3572 | /* Rv = Rf */ |
||
3573 | /* Gv = Gf */ |
||
3574 | /* Bv = Bf */ |
||
3575 | rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]); |
||
3576 | } |
||
3577 | break; |
||
3578 | case GL_LUMINANCE: |
||
3579 | for (i=0;i<n;i++) { |
||
3580 | GLuint Lt = texel[i][RCOMP]; |
||
3581 | GLuint r = rgba[i][RCOMP] + Lt; |
||
3582 | GLuint g = rgba[i][GCOMP] + Lt; |
||
3583 | GLuint b = rgba[i][BCOMP] + Lt; |
||
3584 | rgba[i][RCOMP] = MIN2(r, CHAN_MAX); |
||
3585 | rgba[i][GCOMP] = MIN2(g, CHAN_MAX); |
||
3586 | rgba[i][BCOMP] = MIN2(b, CHAN_MAX); |
||
3587 | /* Av = Af */ |
||
3588 | } |
||
3589 | break; |
||
3590 | case GL_LUMINANCE_ALPHA: |
||
3591 | for (i=0;i<n;i++) { |
||
3592 | GLuint Lt = texel[i][RCOMP]; |
||
3593 | GLuint r = rgba[i][RCOMP] + Lt; |
||
3594 | GLuint g = rgba[i][GCOMP] + Lt; |
||
3595 | GLuint b = rgba[i][BCOMP] + Lt; |
||
3596 | rgba[i][RCOMP] = MIN2(r, CHAN_MAX); |
||
3597 | rgba[i][GCOMP] = MIN2(g, CHAN_MAX); |
||
3598 | rgba[i][BCOMP] = MIN2(b, CHAN_MAX); |
||
3599 | rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]); |
||
3600 | } |
||
3601 | break; |
||
3602 | case GL_INTENSITY: |
||
3603 | for (i=0;i<n;i++) { |
||
3604 | GLchan It = texel[i][RCOMP]; |
||
3605 | GLuint r = rgba[i][RCOMP] + It; |
||
3606 | GLuint g = rgba[i][GCOMP] + It; |
||
3607 | GLuint b = rgba[i][BCOMP] + It; |
||
3608 | GLuint a = rgba[i][ACOMP] + It; |
||
3609 | rgba[i][RCOMP] = MIN2(r, CHAN_MAX); |
||
3610 | rgba[i][GCOMP] = MIN2(g, CHAN_MAX); |
||
3611 | rgba[i][BCOMP] = MIN2(b, CHAN_MAX); |
||
3612 | rgba[i][ACOMP] = MIN2(a, CHAN_MAX); |
||
3613 | } |
||
3614 | break; |
||
3615 | case GL_RGB: |
||
3616 | for (i=0;i<n;i++) { |
||
3617 | GLuint r = rgba[i][RCOMP] + texel[i][RCOMP]; |
||
3618 | GLuint g = rgba[i][GCOMP] + texel[i][GCOMP]; |
||
3619 | GLuint b = rgba[i][BCOMP] + texel[i][BCOMP]; |
||
3620 | rgba[i][RCOMP] = MIN2(r, CHAN_MAX); |
||
3621 | rgba[i][GCOMP] = MIN2(g, CHAN_MAX); |
||
3622 | rgba[i][BCOMP] = MIN2(b, CHAN_MAX); |
||
3623 | /* Av = Af */ |
||
3624 | } |
||
3625 | break; |
||
3626 | case GL_RGBA: |
||
3627 | for (i=0;i<n;i++) { |
||
3628 | GLuint r = rgba[i][RCOMP] + texel[i][RCOMP]; |
||
3629 | GLuint g = rgba[i][GCOMP] + texel[i][GCOMP]; |
||
3630 | GLuint b = rgba[i][BCOMP] + texel[i][BCOMP]; |
||
3631 | rgba[i][RCOMP] = MIN2(r, CHAN_MAX); |
||
3632 | rgba[i][GCOMP] = MIN2(g, CHAN_MAX); |
||
3633 | rgba[i][BCOMP] = MIN2(b, CHAN_MAX); |
||
3634 | rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]); |
||
3635 | } |
||
3636 | break; |
||
3637 | default: |
||
3638 | _mesa_problem(ctx, "Bad format (GL_ADD) in texture_apply"); |
||
3639 | return; |
||
3640 | } |
||
3641 | break; |
||
3642 | |||
3643 | default: |
||
3644 | _mesa_problem(ctx, "Bad env mode in texture_apply"); |
||
3645 | return; |
||
3646 | } |
||
3647 | } |
||
3648 | |||
3649 | |||
3650 | |||
3651 | /** |
||
3652 | * Apply texture mapping to a span of fragments. |
||
3653 | */ |
||
3654 | void |
||
3655 | _swrast_texture_span( GLcontext *ctx, struct sw_span *span ) |
||
3656 | { |
||
3657 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
3658 | GLchan primary_rgba[MAX_WIDTH][4]; |
||
3659 | GLuint unit; |
||
3660 | |||
3661 | ASSERT(span->end < MAX_WIDTH); |
||
3662 | ASSERT(span->arrayMask & SPAN_TEXTURE); |
||
3663 | |||
3664 | /* |
||
3665 | * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR) |
||
3666 | */ |
||
3667 | if (swrast->_AnyTextureCombine) |
||
3668 | MEMCPY(primary_rgba, span->array->rgba, 4 * span->end * sizeof(GLchan)); |
||
3669 | |||
3670 | /* |
||
3671 | * Must do all texture sampling before combining in order to |
||
3672 | * accomodate GL_ARB_texture_env_crossbar. |
||
3673 | */ |
||
3674 | for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { |
||
3675 | if (ctx->Texture.Unit[unit]._ReallyEnabled) { |
||
3676 | const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; |
||
3677 | const struct gl_texture_object *curObj = texUnit->_Current; |
||
3678 | GLfloat *lambda = span->array->lambda[unit]; |
||
3679 | GLchan (*texels)[4] = (GLchan (*)[4]) |
||
3680 | (swrast->TexelBuffer + unit * (span->end * 4 * sizeof(GLchan))); |
||
3681 | |||
3682 | /* adjust texture lod (lambda) */ |
||
3683 | if (span->arrayMask | SPAN_LAMBDA) { |
||
3684 | if (texUnit->LodBias != 0.0F) { |
||
3685 | /* apply LOD bias, but don't clamp yet */ |
||
3686 | GLuint i; |
||
3687 | for (i = 0; i < span->end; i++) { |
||
3688 | lambda[i] += texUnit->LodBias; |
||
3689 | } |
||
3690 | } |
||
3691 | |||
3692 | if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) { |
||
3693 | /* apply LOD clamping to lambda */ |
||
3694 | const GLfloat min = curObj->MinLod; |
||
3695 | const GLfloat max = curObj->MaxLod; |
||
3696 | GLuint i; |
||
3697 | for (i = 0; i < span->end; i++) { |
||
3698 | GLfloat l = lambda[i]; |
||
3699 | lambda[i] = CLAMP(l, min, max); |
||
3700 | } |
||
3701 | } |
||
3702 | } |
||
3703 | |||
3704 | /* Sample the texture (span->end fragments) */ |
||
3705 | swrast->TextureSample[unit]( ctx, unit, texUnit->_Current, |
||
3706 | span->end, span->array->texcoords[unit], |
||
3707 | lambda, texels ); |
||
3708 | } |
||
3709 | } |
||
3710 | |||
3711 | /* |
||
3712 | * OK, now apply the texture (aka texture combine/blend). |
||
3713 | * We modify the span->color.rgba values. |
||
3714 | */ |
||
3715 | for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { |
||
3716 | if (ctx->Texture.Unit[unit]._ReallyEnabled) { |
||
3717 | const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; |
||
3718 | if (texUnit->EnvMode == GL_COMBINE_EXT) { |
||
3719 | /* GL_ARB/EXT_texture_env_combine */ |
||
3720 | texture_combine( ctx, unit, span->end, |
||
3721 | (CONST GLchan (*)[4]) primary_rgba, |
||
3722 | swrast->TexelBuffer, |
||
3723 | span->array->rgba ); |
||
3724 | } |
||
3725 | else if (texUnit->EnvMode == GL_COMBINE4_NV) { |
||
3726 | /* GL_NV_texture_env_combine4 */ |
||
3727 | texture_combine4( ctx, unit, span->end, |
||
3728 | (CONST GLchan (*)[4]) primary_rgba, |
||
3729 | swrast->TexelBuffer, |
||
3730 | span->array->rgba ); |
||
3731 | } |
||
3732 | else { |
||
3733 | /* conventional texture blend */ |
||
3734 | const GLchan (*texels)[4] = (const GLchan (*)[4]) |
||
3735 | (swrast->TexelBuffer + unit * |
||
3736 | (span->end * 4 * sizeof(GLchan))); |
||
3737 | texture_apply( ctx, texUnit, span->end, |
||
3738 | (CONST GLchan (*)[4]) primary_rgba, texels, |
||
3739 | span->array->rgba ); |
||
3740 | } |
||
3741 | } |
||
3742 | } |
||
3743 | } |