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