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