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