1 /* $Id: s_texture.c,v 1.83 2003/03/04 19:17:31 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 #include "texformat.h"
36 #include "s_context.h"
37 #include "s_texture.h"
41 * These values are used in the fixed-point arithmetic used
42 * for linear filtering.
44 #define WEIGHT_SCALE 65536.0F
45 #define WEIGHT_SHIFT 16
49 * Used to compute texel locations for linear sampling.
51 * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER
52 * S = texcoord in [0,1]
53 * SIZE = width (or height or depth) of texture
55 * U = texcoord in [0, width]
56 * I0, I1 = two nearest texel indexes
58 #define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1) \
60 if (wrapMode == GL_REPEAT) { \
61 U = S * SIZE - 0.5F; \
62 I0 = IFLOOR(U) & (SIZE - 1); \
63 I1 = (I0 + 1) & (SIZE - 1); \
65 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
77 if (I1 >= (GLint) SIZE) \
80 else if (wrapMode == GL_CLAMP_TO_BORDER) { \
81 const GLfloat min = -1.0F / (2.0F * SIZE); \
82 const GLfloat max = 1.0F - min; \
93 else if (wrapMode == GL_MIRRORED_REPEAT) { \
94 const GLint flr = IFLOOR(S); \
96 U = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
98 U = S - (GLfloat) flr; /* flr is even */ \
99 U = (U * SIZE) - 0.5F; \
104 if (I1 >= (GLint) SIZE) \
107 else if (wrapMode == GL_MIRROR_CLAMP_ATI) { \
108 U = (GLfloat) fabs(S); \
110 U = (GLfloat) SIZE; \
117 else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_ATI) { \
118 U = (GLfloat) fabs(S); \
120 U = (GLfloat) SIZE; \
128 if (I1 >= (GLint) SIZE) \
132 ASSERT(wrapMode == GL_CLAMP); \
135 else if (S >= 1.0F) \
136 U = (GLfloat) SIZE; \
147 * Used to compute texel location for nearest sampling.
149 #define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I) \
151 if (wrapMode == GL_REPEAT) { \
152 /* s limited to [0,1) */ \
153 /* i limited to [0,size-1] */ \
154 I = IFLOOR(S * SIZE); \
157 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
158 /* s limited to [min,max] */ \
159 /* i limited to [0, size-1] */ \
160 const GLfloat min = 1.0F / (2.0F * SIZE); \
161 const GLfloat max = 1.0F - min; \
167 I = IFLOOR(S * SIZE); \
169 else if (wrapMode == GL_CLAMP_TO_BORDER) { \
170 /* s limited to [min,max] */ \
171 /* i limited to [-1, size] */ \
172 const GLfloat min = -1.0F / (2.0F * SIZE); \
173 const GLfloat max = 1.0F - min; \
179 I = IFLOOR(S * SIZE); \
181 else if (wrapMode == GL_MIRRORED_REPEAT) { \
182 const GLfloat min = 1.0F / (2.0F * SIZE); \
183 const GLfloat max = 1.0F - min; \
184 const GLint flr = IFLOOR(S); \
187 u = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
189 u = S - (GLfloat) flr; /* flr is even */ \
195 I = IFLOOR(u * SIZE); \
197 else if (wrapMode == GL_MIRROR_CLAMP_ATI) { \
198 /* s limited to [0,1] */ \
199 /* i limited to [0,size-1] */ \
200 const GLfloat u = (GLfloat) fabs(S); \
203 else if (u >= 1.0F) \
206 I = IFLOOR(u * SIZE); \
208 else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_ATI) { \
209 /* s limited to [min,max] */ \
210 /* i limited to [0, size-1] */ \
211 const GLfloat min = 1.0F / (2.0F * SIZE); \
212 const GLfloat max = 1.0F - min; \
213 const GLfloat u = (GLfloat) fabs(S); \
219 I = IFLOOR(u * SIZE); \
222 ASSERT(wrapMode == GL_CLAMP); \
223 /* s limited to [0,1] */ \
224 /* i limited to [0,size-1] */ \
227 else if (S >= 1.0F) \
230 I = IFLOOR(S * SIZE); \
235 #define COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(S, U, SIZE, I0, I1) \
237 U = S * SIZE - 0.5F; \
238 I0 = IFLOOR(U) & (SIZE - 1); \
239 I1 = (I0 + 1) & (SIZE - 1); \
244 * Compute linear mipmap levels for given lambda.
246 #define COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level) \
249 level = tObj->BaseLevel; \
250 else if (lambda > tObj->_MaxLambda) \
251 level = (GLint) (tObj->BaseLevel + tObj->_MaxLambda); \
253 level = (GLint) (tObj->BaseLevel + lambda); \
258 * Compute nearest mipmap level for given lambda.
260 #define COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level) \
263 if (lambda <= 0.5F) \
265 else if (lambda > tObj->_MaxLambda + 0.4999F) \
266 l = tObj->_MaxLambda + 0.4999F; \
269 level = (GLint) (tObj->BaseLevel + l + 0.5F); \
270 if (level > tObj->_MaxLevel) \
271 level = tObj->_MaxLevel; \
277 * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
278 * see 1-pixel bands of improperly weighted linear-sampled texels. The
279 * tests/texwrap.c demo is a good test.
280 * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
281 * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
283 #define FRAC(f) ((f) - IFLOOR(f))
288 * Bitflags for texture border color sampling.
299 * Do the lookup for GL_SGI_texture_color_table.
302 _swrast_texture_table_lookup(const struct gl_color_table
*table
,
303 GLuint n
, GLchan rgba
[][4])
305 if (!table
->Table
|| table
->Size
== 0)
308 switch (table
->Format
) {
310 /* replace RGBA with I */
311 if (table
->FloatTable
) {
312 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
313 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
315 for (i
= 0; i
< n
; i
++) {
316 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
318 CLAMPED_FLOAT_TO_CHAN(c
, lut
[j
]);
319 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] =
320 rgba
[i
][BCOMP
] = rgba
[i
][ACOMP
] = c
;
324 #if CHAN_TYPE == GL_UNSIGNED_BYTE
325 if (table
->Size
== 256) {
327 const GLchan
*lut
= (const GLchan
*) table
->Table
;
329 for (i
= 0; i
< n
; i
++) {
330 const GLchan c
= lut
[rgba
[i
][RCOMP
]];
331 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] =
332 rgba
[i
][BCOMP
] = rgba
[i
][ACOMP
] = c
;
338 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
339 const GLchan
*lut
= (const GLchan
*) table
->Table
;
341 for (i
= 0; i
< n
; i
++) {
342 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
343 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] =
344 rgba
[i
][BCOMP
] = rgba
[i
][ACOMP
] = lut
[j
];
350 /* replace RGB with L */
351 if (table
->FloatTable
) {
352 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
353 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
355 for (i
= 0; i
< n
; i
++) {
356 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
358 CLAMPED_FLOAT_TO_CHAN(c
, lut
[j
]);
359 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = c
;
363 #if CHAN_TYPE == GL_UNSIGNED_BYTE
364 if (table
->Size
== 256) {
366 const GLchan
*lut
= (const GLchan
*) table
->Table
;
368 for (i
= 0; i
< n
; i
++) {
369 const GLchan c
= lut
[rgba
[i
][RCOMP
]];
370 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = c
;
376 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
377 const GLchan
*lut
= (const GLchan
*) table
->Table
;
379 for (i
= 0; i
< n
; i
++) {
380 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
381 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = lut
[j
];
387 /* replace A with A */
388 if (table
->FloatTable
) {
389 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
390 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
392 for (i
= 0; i
< n
; i
++) {
393 GLint j
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
395 CLAMPED_FLOAT_TO_CHAN(c
, lut
[j
]);
400 #if CHAN_TYPE == GL_UNSIGNED_BYTE
401 if (table
->Size
== 256) {
403 const GLchan
*lut
= (const GLchan
*) table
->Table
;
405 for (i
= 0; i
< n
; i
++) {
406 rgba
[i
][ACOMP
] = lut
[rgba
[i
][ACOMP
]];
412 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
413 const GLchan
*lut
= (const GLchan
*) table
->Table
;
415 for (i
= 0; i
< n
; i
++) {
416 GLint j
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
417 rgba
[i
][ACOMP
] = lut
[j
];
422 case GL_LUMINANCE_ALPHA
:
423 /* replace RGBA with LLLA */
424 if (table
->FloatTable
) {
425 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
426 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
428 for (i
= 0; i
< n
; i
++) {
429 GLint jL
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
430 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
431 GLchan luminance
, alpha
;
432 CLAMPED_FLOAT_TO_CHAN(luminance
, lut
[jL
* 2 + 0]);
433 CLAMPED_FLOAT_TO_CHAN(alpha
, lut
[jA
* 2 + 1]);
434 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = luminance
;
435 rgba
[i
][ACOMP
] = alpha
;;
439 #if CHAN_TYPE == GL_UNSIGNED_BYTE
440 if (table
->Size
== 256) {
442 const GLchan
*lut
= (const GLchan
*) table
->Table
;
444 for (i
= 0; i
< n
; i
++) {
445 GLchan l
= lut
[rgba
[i
][RCOMP
] * 2 + 0];
446 GLchan a
= lut
[rgba
[i
][ACOMP
] * 2 + 1];;
447 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = l
;
454 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
455 const GLchan
*lut
= (const GLchan
*) table
->Table
;
457 for (i
= 0; i
< n
; i
++) {
458 GLint jL
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
459 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
460 GLchan luminance
= lut
[jL
* 2 + 0];
461 GLchan alpha
= lut
[jA
* 2 + 1];
462 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = luminance
;
463 rgba
[i
][ACOMP
] = alpha
;
469 /* replace RGB with RGB */
470 if (table
->FloatTable
) {
471 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
472 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
474 for (i
= 0; i
< n
; i
++) {
475 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
476 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
477 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
478 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][RCOMP
], lut
[jR
* 3 + 0]);
479 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][GCOMP
], lut
[jG
* 3 + 1]);
480 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][BCOMP
], lut
[jB
* 3 + 2]);
484 #if CHAN_TYPE == GL_UNSIGNED_BYTE
485 if (table
->Size
== 256) {
487 const GLchan
*lut
= (const GLchan
*) table
->Table
;
489 for (i
= 0; i
< n
; i
++) {
490 rgba
[i
][RCOMP
] = lut
[rgba
[i
][RCOMP
] * 3 + 0];
491 rgba
[i
][GCOMP
] = lut
[rgba
[i
][GCOMP
] * 3 + 1];
492 rgba
[i
][BCOMP
] = lut
[rgba
[i
][BCOMP
] * 3 + 2];
498 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
499 const GLchan
*lut
= (const GLchan
*) table
->Table
;
501 for (i
= 0; i
< n
; i
++) {
502 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
503 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
504 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
505 rgba
[i
][RCOMP
] = lut
[jR
* 3 + 0];
506 rgba
[i
][GCOMP
] = lut
[jG
* 3 + 1];
507 rgba
[i
][BCOMP
] = lut
[jB
* 3 + 2];
513 /* replace RGBA with RGBA */
514 if (!table
->FloatTable
) {
515 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
516 const GLchan
*lut
= (const GLchan
*) table
->Table
;
518 for (i
= 0; i
< n
; i
++) {
519 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
520 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
521 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
522 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
523 rgba
[i
][RCOMP
] = lut
[jR
* 4 + 0];
524 rgba
[i
][GCOMP
] = lut
[jG
* 4 + 1];
525 rgba
[i
][BCOMP
] = lut
[jB
* 4 + 2];
526 rgba
[i
][ACOMP
] = lut
[jA
* 4 + 3];
530 #if CHAN_TYPE == GL_UNSIGNED_BYTE
531 if (table
->Size
== 256) {
533 const GLchan
*lut
= (const GLchan
*) table
->Table
;
535 for (i
= 0; i
< n
; i
++) {
536 rgba
[i
][RCOMP
] = lut
[rgba
[i
][RCOMP
] * 4 + 0];
537 rgba
[i
][GCOMP
] = lut
[rgba
[i
][GCOMP
] * 4 + 1];
538 rgba
[i
][BCOMP
] = lut
[rgba
[i
][BCOMP
] * 4 + 2];
539 rgba
[i
][ACOMP
] = lut
[rgba
[i
][ACOMP
] * 4 + 3];
545 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
546 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
548 for (i
= 0; i
< n
; i
++) {
549 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
550 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
551 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
552 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
553 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][RCOMP
], lut
[jR
* 4 + 0]);
554 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][GCOMP
], lut
[jG
* 4 + 1]);
555 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][BCOMP
], lut
[jB
* 4 + 2]);
556 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][ACOMP
], lut
[jA
* 4 + 3]);
562 _mesa_problem(NULL
, "Bad format in _swrast_texture_table_lookup");
570 * Get texture palette entry.
573 palette_sample(const GLcontext
*ctx
,
574 const struct gl_texture_object
*tObj
,
575 GLint index
, GLchan rgba
[4] )
577 const GLchan
*palette
;
580 if (ctx
->Texture
.SharedPalette
) {
581 ASSERT(!ctx
->Texture
.Palette
.FloatTable
);
582 palette
= (const GLchan
*) ctx
->Texture
.Palette
.Table
;
583 format
= ctx
->Texture
.Palette
.Format
;
586 ASSERT(!tObj
->Palette
.FloatTable
);
587 palette
= (const GLchan
*) tObj
->Palette
.Table
;
588 format
= tObj
->Palette
.Format
;
593 rgba
[ACOMP
] = palette
[index
];
597 rgba
[RCOMP
] = palette
[index
];
599 case GL_LUMINANCE_ALPHA
:
600 rgba
[RCOMP
] = palette
[(index
<< 1) + 0];
601 rgba
[ACOMP
] = palette
[(index
<< 1) + 1];
604 rgba
[RCOMP
] = palette
[index
* 3 + 0];
605 rgba
[GCOMP
] = palette
[index
* 3 + 1];
606 rgba
[BCOMP
] = palette
[index
* 3 + 2];
609 rgba
[RCOMP
] = palette
[(index
<< 2) + 0];
610 rgba
[GCOMP
] = palette
[(index
<< 2) + 1];
611 rgba
[BCOMP
] = palette
[(index
<< 2) + 2];
612 rgba
[ACOMP
] = palette
[(index
<< 2) + 3];
615 _mesa_problem(ctx
, "Bad palette format in palette_sample");
621 * The lambda[] array values are always monotonic. Either the whole span
622 * will be minified, magnified, or split between the two. This function
623 * determines the subranges in [0, n-1] that are to be minified or magnified.
626 compute_min_mag_ranges( GLfloat minMagThresh
, GLuint n
, const GLfloat lambda
[],
627 GLuint
*minStart
, GLuint
*minEnd
,
628 GLuint
*magStart
, GLuint
*magEnd
)
630 ASSERT(lambda
!= NULL
);
632 /* Verify that lambda[] is monotonous.
633 * We can't really use this because the inaccuracy in the LOG2 function
634 * causes this test to fail, yet the resulting texturing is correct.
638 printf("lambda delta = %g\n", lambda
[0] - lambda
[n
-1]);
639 if (lambda
[0] >= lambda
[n
-1]) { /* decreasing */
640 for (i
= 0; i
< n
- 1; i
++) {
641 ASSERT((GLint
) (lambda
[i
] * 10) >= (GLint
) (lambda
[i
+1] * 10));
644 else { /* increasing */
645 for (i
= 0; i
< n
- 1; i
++) {
646 ASSERT((GLint
) (lambda
[i
] * 10) <= (GLint
) (lambda
[i
+1] * 10));
652 /* since lambda is monotonous-array use this check first */
653 if (lambda
[0] <= minMagThresh
&& lambda
[n
-1] <= minMagThresh
) {
654 /* magnification for whole span */
657 *minStart
= *minEnd
= 0;
659 else if (lambda
[0] > minMagThresh
&& lambda
[n
-1] > minMagThresh
) {
660 /* minification for whole span */
663 *magStart
= *magEnd
= 0;
666 /* a mix of minification and magnification */
668 if (lambda
[0] > minMagThresh
) {
669 /* start with minification */
670 for (i
= 1; i
< n
; i
++) {
671 if (lambda
[i
] <= minMagThresh
)
680 /* start with magnification */
681 for (i
= 1; i
< n
; i
++) {
682 if (lambda
[i
] > minMagThresh
)
693 /* Verify the min/mag Start/End values
694 * We don't use this either (see above)
698 for (i
= 0; i
< n
; i
++) {
699 if (lambda
[i
] > minMagThresh
) {
701 ASSERT(i
>= *minStart
);
706 ASSERT(i
>= *magStart
);
715 /**********************************************************************/
716 /* 1-D Texture Sampling Functions */
717 /**********************************************************************/
720 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
723 sample_1d_nearest(GLcontext
*ctx
,
724 const struct gl_texture_object
*tObj
,
725 const struct gl_texture_image
*img
,
726 const GLfloat texcoord
[4], GLchan rgba
[4])
728 const GLint width
= img
->Width2
; /* without border, power of two */
731 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
733 /* skip over the border, if any */
736 if (i
< 0 || i
>= (GLint
) img
->Width
) {
737 /* Need this test for GL_CLAMP_TO_BORDER mode */
738 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
741 (*img
->FetchTexel
)(img
, i
, 0, 0, (GLvoid
*) rgba
);
742 if (img
->Format
== GL_COLOR_INDEX
) {
743 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
751 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
754 sample_1d_linear(GLcontext
*ctx
,
755 const struct gl_texture_object
*tObj
,
756 const struct gl_texture_image
*img
,
757 const GLfloat texcoord
[4], GLchan rgba
[4])
759 const GLint width
= img
->Width2
;
762 GLuint useBorderColor
;
764 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
772 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
773 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
777 const GLfloat a
= FRAC(u
);
779 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
780 const GLfloat w0
= (1.0F
-a
);
781 const GLfloat w1
= a
;
782 #else /* CHAN_BITS == 8 */
783 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
784 const GLint w0
= IROUND_POS((1.0F
- a
) * WEIGHT_SCALE
);
785 const GLint w1
= IROUND_POS( a
* WEIGHT_SCALE
);
787 GLchan t0
[4], t1
[4]; /* texels */
789 if (useBorderColor
& I0BIT
) {
790 COPY_CHAN4(t0
, tObj
->_BorderChan
);
793 (*img
->FetchTexel
)(img
, i0
, 0, 0, (GLvoid
*) t0
);
794 if (img
->Format
== GL_COLOR_INDEX
) {
795 palette_sample(ctx
, tObj
, t0
[0], t0
);
798 if (useBorderColor
& I1BIT
) {
799 COPY_CHAN4(t1
, tObj
->_BorderChan
);
802 (*img
->FetchTexel
)(img
, i1
, 0, 0, (GLvoid
*) t1
);
803 if (img
->Format
== GL_COLOR_INDEX
) {
804 palette_sample(ctx
, tObj
, t1
[0], t1
);
808 #if CHAN_TYPE == GL_FLOAT
809 rgba
[0] = w0
* t0
[0] + w1
* t1
[0];
810 rgba
[1] = w0
* t0
[1] + w1
* t1
[1];
811 rgba
[2] = w0
* t0
[2] + w1
* t1
[2];
812 rgba
[3] = w0
* t0
[3] + w1
* t1
[3];
813 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
814 rgba
[0] = (GLchan
) (w0
* t0
[0] + w1
* t1
[0] + 0.5);
815 rgba
[1] = (GLchan
) (w0
* t0
[1] + w1
* t1
[1] + 0.5);
816 rgba
[2] = (GLchan
) (w0
* t0
[2] + w1
* t1
[2] + 0.5);
817 rgba
[3] = (GLchan
) (w0
* t0
[3] + w1
* t1
[3] + 0.5);
818 #else /* CHAN_BITS == 8 */
819 rgba
[0] = (GLchan
) ((w0
* t0
[0] + w1
* t1
[0]) >> WEIGHT_SHIFT
);
820 rgba
[1] = (GLchan
) ((w0
* t0
[1] + w1
* t1
[1]) >> WEIGHT_SHIFT
);
821 rgba
[2] = (GLchan
) ((w0
* t0
[2] + w1
* t1
[2]) >> WEIGHT_SHIFT
);
822 rgba
[3] = (GLchan
) ((w0
* t0
[3] + w1
* t1
[3]) >> WEIGHT_SHIFT
);
830 sample_1d_nearest_mipmap_nearest(GLcontext
*ctx
,
831 const struct gl_texture_object
*tObj
,
832 GLuint n
, const GLfloat texcoord
[][4],
833 const GLfloat lambda
[], GLchan rgba
[][4])
836 ASSERT(lambda
!= NULL
);
837 for (i
= 0; i
< n
; i
++) {
839 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
840 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
846 sample_1d_linear_mipmap_nearest(GLcontext
*ctx
,
847 const struct gl_texture_object
*tObj
,
848 GLuint n
, const GLfloat texcoord
[][4],
849 const GLfloat lambda
[], GLchan rgba
[][4])
852 ASSERT(lambda
!= NULL
);
853 for (i
= 0; i
< n
; i
++) {
855 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
856 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
863 * This is really just needed in order to prevent warnings with some compilers.
865 #if CHAN_TYPE == GL_FLOAT
868 #define CHAN_CAST (GLchan) (GLint)
873 sample_1d_nearest_mipmap_linear(GLcontext
*ctx
,
874 const struct gl_texture_object
*tObj
,
875 GLuint n
, const GLfloat texcoord
[][4],
876 const GLfloat lambda
[], GLchan rgba
[][4])
879 ASSERT(lambda
!= NULL
);
880 for (i
= 0; i
< n
; i
++) {
882 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
883 if (level
>= tObj
->_MaxLevel
) {
884 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
885 texcoord
[i
], rgba
[i
]);
889 const GLfloat f
= FRAC(lambda
[i
]);
890 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
891 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
892 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
893 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
894 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
895 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
903 sample_1d_linear_mipmap_linear(GLcontext
*ctx
,
904 const struct gl_texture_object
*tObj
,
905 GLuint n
, const GLfloat texcoord
[][4],
906 const GLfloat lambda
[], GLchan rgba
[][4])
909 ASSERT(lambda
!= NULL
);
910 for (i
= 0; i
< n
; i
++) {
912 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
913 if (level
>= tObj
->_MaxLevel
) {
914 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
915 texcoord
[i
], rgba
[i
]);
919 const GLfloat f
= FRAC(lambda
[i
]);
920 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
921 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
922 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
923 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
924 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
925 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
933 sample_nearest_1d( GLcontext
*ctx
, GLuint texUnit
,
934 const struct gl_texture_object
*tObj
, GLuint n
,
935 const GLfloat texcoords
[][4], const GLfloat lambda
[],
939 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
942 sample_1d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
949 sample_linear_1d( GLcontext
*ctx
, GLuint texUnit
,
950 const struct gl_texture_object
*tObj
, GLuint n
,
951 const GLfloat texcoords
[][4], const GLfloat lambda
[],
955 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
958 sample_1d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
964 * Given an (s) texture coordinate and lambda (level of detail) value,
965 * return a texture sample.
969 sample_lambda_1d( GLcontext
*ctx
, GLuint texUnit
,
970 const struct gl_texture_object
*tObj
, GLuint n
,
971 const GLfloat texcoords
[][4],
972 const GLfloat lambda
[], GLchan rgba
[][4] )
974 GLuint minStart
, minEnd
; /* texels with minification */
975 GLuint magStart
, magEnd
; /* texels with magnification */
978 ASSERT(lambda
!= NULL
);
979 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
980 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
982 if (minStart
< minEnd
) {
983 /* do the minified texels */
984 const GLuint m
= minEnd
- minStart
;
985 switch (tObj
->MinFilter
) {
987 for (i
= minStart
; i
< minEnd
; i
++)
988 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
989 texcoords
[i
], rgba
[i
]);
992 for (i
= minStart
; i
< minEnd
; i
++)
993 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
994 texcoords
[i
], rgba
[i
]);
996 case GL_NEAREST_MIPMAP_NEAREST
:
997 sample_1d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
998 lambda
+ minStart
, rgba
+ minStart
);
1000 case GL_LINEAR_MIPMAP_NEAREST
:
1001 sample_1d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1002 lambda
+ minStart
, rgba
+ minStart
);
1004 case GL_NEAREST_MIPMAP_LINEAR
:
1005 sample_1d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1006 lambda
+ minStart
, rgba
+ minStart
);
1008 case GL_LINEAR_MIPMAP_LINEAR
:
1009 sample_1d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1010 lambda
+ minStart
, rgba
+ minStart
);
1013 _mesa_problem(ctx
, "Bad min filter in sample_1d_texture");
1018 if (magStart
< magEnd
) {
1019 /* do the magnified texels */
1020 switch (tObj
->MagFilter
) {
1022 for (i
= magStart
; i
< magEnd
; i
++)
1023 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1024 texcoords
[i
], rgba
[i
]);
1027 for (i
= magStart
; i
< magEnd
; i
++)
1028 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1029 texcoords
[i
], rgba
[i
]);
1032 _mesa_problem(ctx
, "Bad mag filter in sample_1d_texture");
1039 /**********************************************************************/
1040 /* 2-D Texture Sampling Functions */
1041 /**********************************************************************/
1045 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
1048 sample_2d_nearest(GLcontext
*ctx
,
1049 const struct gl_texture_object
*tObj
,
1050 const struct gl_texture_image
*img
,
1051 const GLfloat texcoord
[4],
1054 const GLint width
= img
->Width2
; /* without border, power of two */
1055 const GLint height
= img
->Height2
; /* without border, power of two */
1058 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
1059 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
1061 /* skip over the border, if any */
1065 if (i
< 0 || i
>= (GLint
) img
->Width
|| j
< 0 || j
>= (GLint
) img
->Height
) {
1066 /* Need this test for GL_CLAMP_TO_BORDER mode */
1067 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
1070 (*img
->FetchTexel
)(img
, i
, j
, 0, (GLvoid
*) rgba
);
1071 if (img
->Format
== GL_COLOR_INDEX
) {
1072 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
1080 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
1081 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
1084 sample_2d_linear(GLcontext
*ctx
,
1085 const struct gl_texture_object
*tObj
,
1086 const struct gl_texture_image
*img
,
1087 const GLfloat texcoord
[4],
1090 const GLint width
= img
->Width2
;
1091 const GLint height
= img
->Height2
;
1092 GLint i0
, j0
, i1
, j1
;
1093 GLuint useBorderColor
;
1096 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1097 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1107 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1108 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1109 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1110 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1114 const GLfloat a
= FRAC(u
);
1115 const GLfloat b
= FRAC(v
);
1117 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1118 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
1119 const GLfloat w10
= a
* (1.0F
-b
);
1120 const GLfloat w01
= (1.0F
-a
) * b
;
1121 const GLfloat w11
= a
* b
;
1122 #else /* CHAN_BITS == 8 */
1123 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1124 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
1125 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
1126 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
1127 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
1134 if (useBorderColor
& (I0BIT
| J0BIT
)) {
1135 COPY_CHAN4(t00
, tObj
->_BorderChan
);
1138 (*img
->FetchTexel
)(img
, i0
, j0
, 0, (GLvoid
*) t00
);
1139 if (img
->Format
== GL_COLOR_INDEX
) {
1140 palette_sample(ctx
, tObj
, t00
[0], t00
);
1143 if (useBorderColor
& (I1BIT
| J0BIT
)) {
1144 COPY_CHAN4(t10
, tObj
->_BorderChan
);
1147 (*img
->FetchTexel
)(img
, i1
, j0
, 0, (GLvoid
*) t10
);
1148 if (img
->Format
== GL_COLOR_INDEX
) {
1149 palette_sample(ctx
, tObj
, t10
[0], t10
);
1152 if (useBorderColor
& (I0BIT
| J1BIT
)) {
1153 COPY_CHAN4(t01
, tObj
->_BorderChan
);
1156 (*img
->FetchTexel
)(img
, i0
, j1
, 0, (GLvoid
*) t01
);
1157 if (img
->Format
== GL_COLOR_INDEX
) {
1158 palette_sample(ctx
, tObj
, t01
[0], t01
);
1161 if (useBorderColor
& (I1BIT
| J1BIT
)) {
1162 COPY_CHAN4(t11
, tObj
->_BorderChan
);
1165 (*img
->FetchTexel
)(img
, i1
, j1
, 0, (GLvoid
*) t11
);
1166 if (img
->Format
== GL_COLOR_INDEX
) {
1167 palette_sample(ctx
, tObj
, t11
[0], t11
);
1170 #if CHAN_TYPE == GL_FLOAT
1171 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
1172 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
1173 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
1174 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
1175 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1176 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
1177 w01
* t01
[0] + w11
* t11
[0] + 0.5);
1178 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
1179 w01
* t01
[1] + w11
* t11
[1] + 0.5);
1180 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
1181 w01
* t01
[2] + w11
* t11
[2] + 0.5);
1182 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
1183 w01
* t01
[3] + w11
* t11
[3] + 0.5);
1184 #else /* CHAN_BITS == 8 */
1185 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
1186 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
1187 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
1188 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
1189 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
1190 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
1191 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
1192 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
1201 * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT
1202 * and we're not using a paletted texture.
1205 sample_2d_linear_repeat(GLcontext
*ctx
,
1206 const struct gl_texture_object
*tObj
,
1207 const struct gl_texture_image
*img
,
1208 const GLfloat texcoord
[4],
1211 const GLint width
= img
->Width2
;
1212 const GLint height
= img
->Height2
;
1213 GLint i0
, j0
, i1
, j1
;
1216 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1217 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1218 ASSERT(img
->Border
== 0);
1219 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
1221 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[0], u
, width
, i0
, i1
);
1222 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[1], v
, height
, j0
, j1
);
1225 const GLfloat a
= FRAC(u
);
1226 const GLfloat b
= FRAC(v
);
1228 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1229 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
1230 const GLfloat w10
= a
* (1.0F
-b
);
1231 const GLfloat w01
= (1.0F
-a
) * b
;
1232 const GLfloat w11
= a
* b
;
1233 #else /* CHAN_BITS == 8 */
1234 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1235 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
1236 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
1237 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
1238 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
1245 (*img
->FetchTexel
)(img
, i0
, j0
, 0, (GLvoid
*) t00
);
1246 (*img
->FetchTexel
)(img
, i1
, j0
, 0, (GLvoid
*) t10
);
1247 (*img
->FetchTexel
)(img
, i0
, j1
, 0, (GLvoid
*) t01
);
1248 (*img
->FetchTexel
)(img
, i1
, j1
, 0, (GLvoid
*) t11
);
1250 #if CHAN_TYPE == GL_FLOAT
1251 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
1252 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
1253 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
1254 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
1255 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1256 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
1257 w01
* t01
[0] + w11
* t11
[0] + 0.5);
1258 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
1259 w01
* t01
[1] + w11
* t11
[1] + 0.5);
1260 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
1261 w01
* t01
[2] + w11
* t11
[2] + 0.5);
1262 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
1263 w01
* t01
[3] + w11
* t11
[3] + 0.5);
1264 #else /* CHAN_BITS == 8 */
1265 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
1266 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
1267 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
1268 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
1269 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
1270 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
1271 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
1272 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
1282 sample_2d_nearest_mipmap_nearest(GLcontext
*ctx
,
1283 const struct gl_texture_object
*tObj
,
1284 GLuint n
, const GLfloat texcoord
[][4],
1285 const GLfloat lambda
[], GLchan rgba
[][4])
1288 for (i
= 0; i
< n
; i
++) {
1290 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1291 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1298 sample_2d_linear_mipmap_nearest(GLcontext
*ctx
,
1299 const struct gl_texture_object
*tObj
,
1300 GLuint n
, const GLfloat texcoord
[][4],
1301 const GLfloat lambda
[], GLchan rgba
[][4])
1304 ASSERT(lambda
!= NULL
);
1305 for (i
= 0; i
< n
; i
++) {
1307 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1308 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1315 sample_2d_nearest_mipmap_linear(GLcontext
*ctx
,
1316 const struct gl_texture_object
*tObj
,
1317 GLuint n
, const GLfloat texcoord
[][4],
1318 const GLfloat lambda
[], GLchan rgba
[][4])
1321 ASSERT(lambda
!= NULL
);
1322 for (i
= 0; i
< n
; i
++) {
1324 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1325 if (level
>= tObj
->_MaxLevel
) {
1326 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1327 texcoord
[i
], rgba
[i
]);
1330 GLchan t0
[4], t1
[4]; /* texels */
1331 const GLfloat f
= FRAC(lambda
[i
]);
1332 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1333 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1334 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1335 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1336 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1337 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1344 /* Trilinear filtering */
1346 sample_2d_linear_mipmap_linear( GLcontext
*ctx
,
1347 const struct gl_texture_object
*tObj
,
1348 GLuint n
, const GLfloat texcoord
[][4],
1349 const GLfloat lambda
[], GLchan rgba
[][4] )
1352 ASSERT(lambda
!= NULL
);
1353 for (i
= 0; i
< n
; i
++) {
1355 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1356 if (level
>= tObj
->_MaxLevel
) {
1357 sample_2d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1358 texcoord
[i
], rgba
[i
]);
1361 GLchan t0
[4], t1
[4]; /* texels */
1362 const GLfloat f
= FRAC(lambda
[i
]);
1363 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1364 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1365 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1366 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1367 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1368 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1375 sample_2d_linear_mipmap_linear_repeat( GLcontext
*ctx
,
1376 const struct gl_texture_object
*tObj
,
1377 GLuint n
, const GLfloat texcoord
[][4],
1378 const GLfloat lambda
[], GLchan rgba
[][4] )
1381 ASSERT(lambda
!= NULL
);
1382 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1383 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1384 for (i
= 0; i
< n
; i
++) {
1386 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1387 if (level
>= tObj
->_MaxLevel
) {
1388 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1389 texcoord
[i
], rgba
[i
]);
1392 GLchan t0
[4], t1
[4]; /* texels */
1393 const GLfloat f
= FRAC(lambda
[i
]);
1394 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1395 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1396 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1397 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1398 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1399 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1406 sample_nearest_2d( GLcontext
*ctx
, GLuint texUnit
,
1407 const struct gl_texture_object
*tObj
, GLuint n
,
1408 const GLfloat texcoords
[][4],
1409 const GLfloat lambda
[], GLchan rgba
[][4] )
1412 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1415 sample_2d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1422 sample_linear_2d( GLcontext
*ctx
, GLuint texUnit
,
1423 const struct gl_texture_object
*tObj
, GLuint n
,
1424 const GLfloat texcoords
[][4],
1425 const GLfloat lambda
[], GLchan rgba
[][4] )
1428 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1431 sample_2d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1437 * Optimized 2-D texture sampling:
1438 * S and T wrap mode == GL_REPEAT
1439 * GL_NEAREST min/mag filter
1441 * RowStride == Width,
1445 opt_sample_rgb_2d( GLcontext
*ctx
, GLuint texUnit
,
1446 const struct gl_texture_object
*tObj
,
1447 GLuint n
, const GLfloat texcoords
[][4],
1448 const GLfloat lambda
[], GLchan rgba
[][4] )
1450 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
1451 const GLfloat width
= (GLfloat
) img
->Width
;
1452 const GLfloat height
= (GLfloat
) img
->Height
;
1453 const GLint colMask
= img
->Width
- 1;
1454 const GLint rowMask
= img
->Height
- 1;
1455 const GLint shift
= img
->WidthLog2
;
1458 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1459 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1460 ASSERT(img
->Border
==0);
1461 ASSERT(img
->Format
==GL_RGB
);
1463 for (k
=0; k
<n
; k
++) {
1464 GLint i
= IFLOOR(texcoords
[k
][0] * width
) & colMask
;
1465 GLint j
= IFLOOR(texcoords
[k
][1] * height
) & rowMask
;
1466 GLint pos
= (j
<< shift
) | i
;
1467 GLchan
*texel
= ((GLchan
*) img
->Data
) + 3*pos
;
1468 rgba
[k
][RCOMP
] = texel
[0];
1469 rgba
[k
][GCOMP
] = texel
[1];
1470 rgba
[k
][BCOMP
] = texel
[2];
1476 * Optimized 2-D texture sampling:
1477 * S and T wrap mode == GL_REPEAT
1478 * GL_NEAREST min/mag filter
1480 * RowStride == Width,
1484 opt_sample_rgba_2d( GLcontext
*ctx
, GLuint texUnit
,
1485 const struct gl_texture_object
*tObj
,
1486 GLuint n
, const GLfloat texcoords
[][4],
1487 const GLfloat lambda
[], GLchan rgba
[][4] )
1489 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
1490 const GLfloat width
= (GLfloat
) img
->Width
;
1491 const GLfloat height
= (GLfloat
) img
->Height
;
1492 const GLint colMask
= img
->Width
- 1;
1493 const GLint rowMask
= img
->Height
- 1;
1494 const GLint shift
= img
->WidthLog2
;
1497 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1498 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1499 ASSERT(img
->Border
==0);
1500 ASSERT(img
->Format
==GL_RGBA
);
1502 for (i
= 0; i
< n
; i
++) {
1503 const GLint col
= IFLOOR(texcoords
[i
][0] * width
) & colMask
;
1504 const GLint row
= IFLOOR(texcoords
[i
][1] * height
) & rowMask
;
1505 const GLint pos
= (row
<< shift
) | col
;
1506 const GLchan
*texel
= ((GLchan
*) img
->Data
) + (pos
<< 2); /* pos*4 */
1507 COPY_CHAN4(rgba
[i
], texel
);
1513 * Given an array of texture coordinate and lambda (level of detail)
1514 * values, return an array of texture sample.
1517 sample_lambda_2d( GLcontext
*ctx
, GLuint texUnit
,
1518 const struct gl_texture_object
*tObj
,
1519 GLuint n
, const GLfloat texcoords
[][4],
1520 const GLfloat lambda
[], GLchan rgba
[][4] )
1522 const struct gl_texture_image
*tImg
= tObj
->Image
[tObj
->BaseLevel
];
1523 GLuint minStart
, minEnd
; /* texels with minification */
1524 GLuint magStart
, magEnd
; /* texels with magnification */
1526 const GLboolean repeatNoBorder
= (tObj
->WrapS
== GL_REPEAT
)
1527 && (tObj
->WrapT
== GL_REPEAT
)
1528 && (tImg
->Border
== 0 && (tImg
->Width
== tImg
->RowStride
))
1529 && (tImg
->Format
!= GL_COLOR_INDEX
);
1531 ASSERT(lambda
!= NULL
);
1532 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1533 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1535 if (minStart
< minEnd
) {
1536 /* do the minified texels */
1537 const GLuint m
= minEnd
- minStart
;
1538 switch (tObj
->MinFilter
) {
1540 if (repeatNoBorder
) {
1541 switch (tImg
->Format
) {
1543 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1544 NULL
, rgba
+ minStart
);
1547 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1548 NULL
, rgba
+ minStart
);
1551 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1552 NULL
, rgba
+ minStart
);
1556 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1557 NULL
, rgba
+ minStart
);
1561 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1562 NULL
, rgba
+ minStart
);
1564 case GL_NEAREST_MIPMAP_NEAREST
:
1565 sample_2d_nearest_mipmap_nearest(ctx
, tObj
, m
,
1566 texcoords
+ minStart
,
1567 lambda
+ minStart
, rgba
+ minStart
);
1569 case GL_LINEAR_MIPMAP_NEAREST
:
1570 sample_2d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1571 lambda
+ minStart
, rgba
+ minStart
);
1573 case GL_NEAREST_MIPMAP_LINEAR
:
1574 sample_2d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1575 lambda
+ minStart
, rgba
+ minStart
);
1577 case GL_LINEAR_MIPMAP_LINEAR
:
1579 sample_2d_linear_mipmap_linear_repeat(ctx
, tObj
, m
,
1580 texcoords
+ minStart
, lambda
+ minStart
, rgba
+ minStart
);
1582 sample_2d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1583 lambda
+ minStart
, rgba
+ minStart
);
1586 _mesa_problem(ctx
, "Bad min filter in sample_2d_texture");
1591 if (magStart
< magEnd
) {
1592 /* do the magnified texels */
1593 const GLuint m
= magEnd
- magStart
;
1595 switch (tObj
->MagFilter
) {
1597 if (repeatNoBorder
) {
1598 switch (tImg
->Format
) {
1600 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1601 NULL
, rgba
+ magStart
);
1604 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1605 NULL
, rgba
+ magStart
);
1608 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1609 NULL
, rgba
+ magStart
);
1613 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1614 NULL
, rgba
+ magStart
);
1618 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1619 NULL
, rgba
+ magStart
);
1622 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_2d");
1629 /**********************************************************************/
1630 /* 3-D Texture Sampling Functions */
1631 /**********************************************************************/
1634 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1637 sample_3d_nearest(GLcontext
*ctx
,
1638 const struct gl_texture_object
*tObj
,
1639 const struct gl_texture_image
*img
,
1640 const GLfloat texcoord
[4],
1643 const GLint width
= img
->Width2
; /* without border, power of two */
1644 const GLint height
= img
->Height2
; /* without border, power of two */
1645 const GLint depth
= img
->Depth2
; /* without border, power of two */
1648 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
1649 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
1650 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapR
, texcoord
[2], depth
, k
);
1652 if (i
< 0 || i
>= (GLint
) img
->Width
||
1653 j
< 0 || j
>= (GLint
) img
->Height
||
1654 k
< 0 || k
>= (GLint
) img
->Depth
) {
1655 /* Need this test for GL_CLAMP_TO_BORDER mode */
1656 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
1659 (*img
->FetchTexel
)(img
, i
, j
, k
, (GLvoid
*) rgba
);
1660 if (img
->Format
== GL_COLOR_INDEX
) {
1661 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
1669 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1672 sample_3d_linear(GLcontext
*ctx
,
1673 const struct gl_texture_object
*tObj
,
1674 const struct gl_texture_image
*img
,
1675 const GLfloat texcoord
[4],
1678 const GLint width
= img
->Width2
;
1679 const GLint height
= img
->Height2
;
1680 const GLint depth
= img
->Depth2
;
1681 GLint i0
, j0
, k0
, i1
, j1
, k1
;
1682 GLuint useBorderColor
;
1685 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1686 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1687 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapR
, texcoord
[2], w
, depth
, k0
, k1
);
1699 /* check if sampling texture border color */
1700 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1701 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1702 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1703 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1704 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
1705 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
1709 const GLfloat a
= FRAC(u
);
1710 const GLfloat b
= FRAC(v
);
1711 const GLfloat c
= FRAC(w
);
1713 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1714 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1715 GLfloat w000
= (1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
);
1716 GLfloat w100
= a
* (1.0F
-b
) * (1.0F
-c
);
1717 GLfloat w010
= (1.0F
-a
) * b
* (1.0F
-c
);
1718 GLfloat w110
= a
* b
* (1.0F
-c
);
1719 GLfloat w001
= (1.0F
-a
) * (1.0F
-b
) * c
;
1720 GLfloat w101
= a
* (1.0F
-b
) * c
;
1721 GLfloat w011
= (1.0F
-a
) * b
* c
;
1722 GLfloat w111
= a
* b
* c
;
1723 #else /* CHAN_BITS == 8 */
1724 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1725 GLint w000
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1726 GLint w100
= IROUND_POS( a
* (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1727 GLint w010
= IROUND_POS((1.0F
-a
) * b
* (1.0F
-c
) * WEIGHT_SCALE
);
1728 GLint w110
= IROUND_POS( a
* b
* (1.0F
-c
) * WEIGHT_SCALE
);
1729 GLint w001
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * c
* WEIGHT_SCALE
);
1730 GLint w101
= IROUND_POS( a
* (1.0F
-b
) * c
* WEIGHT_SCALE
);
1731 GLint w011
= IROUND_POS((1.0F
-a
) * b
* c
* WEIGHT_SCALE
);
1732 GLint w111
= IROUND_POS( a
* b
* c
* WEIGHT_SCALE
);
1735 GLchan t000
[4], t010
[4], t001
[4], t011
[4];
1736 GLchan t100
[4], t110
[4], t101
[4], t111
[4];
1738 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
1739 COPY_CHAN4(t000
, tObj
->_BorderChan
);
1742 (*img
->FetchTexel
)(img
, i0
, j0
, k0
, (GLvoid
*) t000
);
1743 if (img
->Format
== GL_COLOR_INDEX
) {
1744 palette_sample(ctx
, tObj
, t000
[0], t000
);
1747 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
1748 COPY_CHAN4(t100
, tObj
->_BorderChan
);
1751 (*img
->FetchTexel
)(img
, i1
, j0
, k0
, (GLvoid
*) t100
);
1752 if (img
->Format
== GL_COLOR_INDEX
) {
1753 palette_sample(ctx
, tObj
, t100
[0], t100
);
1756 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
1757 COPY_CHAN4(t010
, tObj
->_BorderChan
);
1760 (*img
->FetchTexel
)(img
, i0
, j1
, k0
, (GLvoid
*) t010
);
1761 if (img
->Format
== GL_COLOR_INDEX
) {
1762 palette_sample(ctx
, tObj
, t010
[0], t010
);
1765 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
1766 COPY_CHAN4(t110
, tObj
->_BorderChan
);
1769 (*img
->FetchTexel
)(img
, i1
, j1
, k0
, (GLvoid
*) t110
);
1770 if (img
->Format
== GL_COLOR_INDEX
) {
1771 palette_sample(ctx
, tObj
, t110
[0], t110
);
1775 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
1776 COPY_CHAN4(t001
, tObj
->_BorderChan
);
1779 (*img
->FetchTexel
)(img
, i0
, j0
, k1
, (GLvoid
*) t001
);
1780 if (img
->Format
== GL_COLOR_INDEX
) {
1781 palette_sample(ctx
, tObj
, t001
[0], t001
);
1784 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
1785 COPY_CHAN4(t101
, tObj
->_BorderChan
);
1788 (*img
->FetchTexel
)(img
, i1
, j0
, k1
, (GLvoid
*) t101
);
1789 if (img
->Format
== GL_COLOR_INDEX
) {
1790 palette_sample(ctx
, tObj
, t101
[0], t101
);
1793 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
1794 COPY_CHAN4(t011
, tObj
->_BorderChan
);
1797 (*img
->FetchTexel
)(img
, i0
, j1
, k1
, (GLvoid
*) t011
);
1798 if (img
->Format
== GL_COLOR_INDEX
) {
1799 palette_sample(ctx
, tObj
, t011
[0], t011
);
1802 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
1803 COPY_CHAN4(t111
, tObj
->_BorderChan
);
1806 (*img
->FetchTexel
)(img
, i1
, j1
, k1
, (GLvoid
*) t111
);
1807 if (img
->Format
== GL_COLOR_INDEX
) {
1808 palette_sample(ctx
, tObj
, t111
[0], t111
);
1812 #if CHAN_TYPE == GL_FLOAT
1813 rgba
[0] = w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1814 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0];
1815 rgba
[1] = w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1816 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1];
1817 rgba
[2] = w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1818 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2];
1819 rgba
[3] = w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1820 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3];
1821 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1822 rgba
[0] = (GLchan
) (w000
*t000
[0] + w010
*t010
[0] +
1823 w001
*t001
[0] + w011
*t011
[0] +
1824 w100
*t100
[0] + w110
*t110
[0] +
1825 w101
*t101
[0] + w111
*t111
[0] + 0.5);
1826 rgba
[1] = (GLchan
) (w000
*t000
[1] + w010
*t010
[1] +
1827 w001
*t001
[1] + w011
*t011
[1] +
1828 w100
*t100
[1] + w110
*t110
[1] +
1829 w101
*t101
[1] + w111
*t111
[1] + 0.5);
1830 rgba
[2] = (GLchan
) (w000
*t000
[2] + w010
*t010
[2] +
1831 w001
*t001
[2] + w011
*t011
[2] +
1832 w100
*t100
[2] + w110
*t110
[2] +
1833 w101
*t101
[2] + w111
*t111
[2] + 0.5);
1834 rgba
[3] = (GLchan
) (w000
*t000
[3] + w010
*t010
[3] +
1835 w001
*t001
[3] + w011
*t011
[3] +
1836 w100
*t100
[3] + w110
*t110
[3] +
1837 w101
*t101
[3] + w111
*t111
[3] + 0.5);
1838 #else /* CHAN_BITS == 8 */
1839 rgba
[0] = (GLchan
) (
1840 (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] )
1843 rgba
[1] = (GLchan
) (
1844 (w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1845 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1] )
1847 rgba
[2] = (GLchan
) (
1848 (w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1849 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2] )
1851 rgba
[3] = (GLchan
) (
1852 (w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1853 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3] )
1863 sample_3d_nearest_mipmap_nearest(GLcontext
*ctx
,
1864 const struct gl_texture_object
*tObj
,
1865 GLuint n
, const GLfloat texcoord
[][4],
1866 const GLfloat lambda
[], GLchan rgba
[][4] )
1869 for (i
= 0; i
< n
; i
++) {
1871 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1872 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1878 sample_3d_linear_mipmap_nearest(GLcontext
*ctx
,
1879 const struct gl_texture_object
*tObj
,
1880 GLuint n
, const GLfloat texcoord
[][4],
1881 const GLfloat lambda
[], GLchan rgba
[][4])
1884 ASSERT(lambda
!= NULL
);
1885 for (i
= 0; i
< n
; i
++) {
1887 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1888 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1894 sample_3d_nearest_mipmap_linear(GLcontext
*ctx
,
1895 const struct gl_texture_object
*tObj
,
1896 GLuint n
, const GLfloat texcoord
[][4],
1897 const GLfloat lambda
[], GLchan rgba
[][4])
1900 ASSERT(lambda
!= NULL
);
1901 for (i
= 0; i
< n
; i
++) {
1903 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1904 if (level
>= tObj
->_MaxLevel
) {
1905 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1906 texcoord
[i
], rgba
[i
]);
1909 GLchan t0
[4], t1
[4]; /* texels */
1910 const GLfloat f
= FRAC(lambda
[i
]);
1911 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1912 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1913 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1914 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1915 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1916 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1923 sample_3d_linear_mipmap_linear(GLcontext
*ctx
,
1924 const struct gl_texture_object
*tObj
,
1925 GLuint n
, const GLfloat texcoord
[][4],
1926 const GLfloat lambda
[], GLchan rgba
[][4])
1929 ASSERT(lambda
!= NULL
);
1930 for (i
= 0; i
< n
; i
++) {
1932 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1933 if (level
>= tObj
->_MaxLevel
) {
1934 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1935 texcoord
[i
], rgba
[i
]);
1938 GLchan t0
[4], t1
[4]; /* texels */
1939 const GLfloat f
= FRAC(lambda
[i
]);
1940 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1941 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1942 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1943 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1944 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1945 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1952 sample_nearest_3d(GLcontext
*ctx
, GLuint texUnit
,
1953 const struct gl_texture_object
*tObj
, GLuint n
,
1954 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1958 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1961 sample_3d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1968 sample_linear_3d( GLcontext
*ctx
, GLuint texUnit
,
1969 const struct gl_texture_object
*tObj
, GLuint n
,
1970 const GLfloat texcoords
[][4],
1971 const GLfloat lambda
[], GLchan rgba
[][4] )
1974 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1977 sample_3d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1983 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
1984 * return a texture sample.
1987 sample_lambda_3d( GLcontext
*ctx
, GLuint texUnit
,
1988 const struct gl_texture_object
*tObj
, GLuint n
,
1989 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1992 GLuint minStart
, minEnd
; /* texels with minification */
1993 GLuint magStart
, magEnd
; /* texels with magnification */
1996 ASSERT(lambda
!= NULL
);
1997 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1998 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2000 if (minStart
< minEnd
) {
2001 /* do the minified texels */
2002 GLuint m
= minEnd
- minStart
;
2003 switch (tObj
->MinFilter
) {
2005 for (i
= minStart
; i
< minEnd
; i
++)
2006 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
2007 texcoords
[i
], rgba
[i
]);
2010 for (i
= minStart
; i
< minEnd
; i
++)
2011 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
2012 texcoords
[i
], rgba
[i
]);
2014 case GL_NEAREST_MIPMAP_NEAREST
:
2015 sample_3d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
2016 lambda
+ minStart
, rgba
+ minStart
);
2018 case GL_LINEAR_MIPMAP_NEAREST
:
2019 sample_3d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
2020 lambda
+ minStart
, rgba
+ minStart
);
2022 case GL_NEAREST_MIPMAP_LINEAR
:
2023 sample_3d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
2024 lambda
+ minStart
, rgba
+ minStart
);
2026 case GL_LINEAR_MIPMAP_LINEAR
:
2027 sample_3d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
2028 lambda
+ minStart
, rgba
+ minStart
);
2031 _mesa_problem(ctx
, "Bad min filter in sample_3d_texture");
2036 if (magStart
< magEnd
) {
2037 /* do the magnified texels */
2038 switch (tObj
->MagFilter
) {
2040 for (i
= magStart
; i
< magEnd
; i
++)
2041 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
2042 texcoords
[i
], rgba
[i
]);
2045 for (i
= magStart
; i
< magEnd
; i
++)
2046 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
2047 texcoords
[i
], rgba
[i
]);
2050 _mesa_problem(ctx
, "Bad mag filter in sample_3d_texture");
2057 /**********************************************************************/
2058 /* Texture Cube Map Sampling Functions */
2059 /**********************************************************************/
2062 * Choose one of six sides of a texture cube map given the texture
2063 * coord (rx,ry,rz). Return pointer to corresponding array of texture
2066 static const struct gl_texture_image
**
2067 choose_cube_face(const struct gl_texture_object
*texObj
,
2068 const GLfloat texcoord
[4], GLfloat newCoord
[4])
2072 direction target sc tc ma
2073 ---------- ------------------------------- --- --- ---
2074 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
2075 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
2076 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
2077 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
2078 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
2079 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
2081 const GLfloat rx
= texcoord
[0];
2082 const GLfloat ry
= texcoord
[1];
2083 const GLfloat rz
= texcoord
[2];
2084 const struct gl_texture_image
**imgArray
;
2085 const GLfloat arx
= FABSF(rx
), ary
= FABSF(ry
), arz
= FABSF(rz
);
2088 if (arx
> ary
&& arx
> arz
) {
2090 imgArray
= (const struct gl_texture_image
**) texObj
->Image
;
2096 imgArray
= (const struct gl_texture_image
**) texObj
->NegX
;
2102 else if (ary
> arx
&& ary
> arz
) {
2104 imgArray
= (const struct gl_texture_image
**) texObj
->PosY
;
2110 imgArray
= (const struct gl_texture_image
**) texObj
->NegY
;
2118 imgArray
= (const struct gl_texture_image
**) texObj
->PosZ
;
2124 imgArray
= (const struct gl_texture_image
**) texObj
->NegZ
;
2131 newCoord
[0] = ( sc
/ ma
+ 1.0F
) * 0.5F
;
2132 newCoord
[1] = ( tc
/ ma
+ 1.0F
) * 0.5F
;
2138 sample_nearest_cube(GLcontext
*ctx
, GLuint texUnit
,
2139 const struct gl_texture_object
*tObj
, GLuint n
,
2140 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2145 for (i
= 0; i
< n
; i
++) {
2146 const struct gl_texture_image
**images
;
2147 GLfloat newCoord
[4];
2148 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
2149 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
2156 sample_linear_cube(GLcontext
*ctx
, GLuint texUnit
,
2157 const struct gl_texture_object
*tObj
, GLuint n
,
2158 const GLfloat texcoords
[][4],
2159 const GLfloat lambda
[], GLchan rgba
[][4])
2163 for (i
= 0; i
< n
; i
++) {
2164 const struct gl_texture_image
**images
;
2165 GLfloat newCoord
[4];
2166 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
2167 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
2174 sample_cube_nearest_mipmap_nearest(GLcontext
*ctx
, GLuint texUnit
,
2175 const struct gl_texture_object
*tObj
,
2176 GLuint n
, const GLfloat texcoord
[][4],
2177 const GLfloat lambda
[], GLchan rgba
[][4])
2180 ASSERT(lambda
!= NULL
);
2181 for (i
= 0; i
< n
; i
++) {
2182 const struct gl_texture_image
**images
;
2183 GLfloat newCoord
[4];
2185 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2186 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2187 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
2193 sample_cube_linear_mipmap_nearest(GLcontext
*ctx
, GLuint texUnit
,
2194 const struct gl_texture_object
*tObj
,
2195 GLuint n
, const GLfloat texcoord
[][4],
2196 const GLfloat lambda
[], GLchan rgba
[][4])
2199 ASSERT(lambda
!= NULL
);
2200 for (i
= 0; i
< n
; i
++) {
2201 const struct gl_texture_image
**images
;
2202 GLfloat newCoord
[4];
2204 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2205 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2206 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
2212 sample_cube_nearest_mipmap_linear(GLcontext
*ctx
, GLuint texUnit
,
2213 const struct gl_texture_object
*tObj
,
2214 GLuint n
, const GLfloat texcoord
[][4],
2215 const GLfloat lambda
[], GLchan rgba
[][4])
2218 ASSERT(lambda
!= NULL
);
2219 for (i
= 0; i
< n
; i
++) {
2220 const struct gl_texture_image
**images
;
2221 GLfloat newCoord
[4];
2223 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2224 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2225 if (level
>= tObj
->_MaxLevel
) {
2226 sample_2d_nearest(ctx
, tObj
, images
[tObj
->_MaxLevel
],
2230 GLchan t0
[4], t1
[4]; /* texels */
2231 const GLfloat f
= FRAC(lambda
[i
]);
2232 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, t0
);
2233 sample_2d_nearest(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
2234 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
2235 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
2236 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
2237 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
2244 sample_cube_linear_mipmap_linear(GLcontext
*ctx
, GLuint texUnit
,
2245 const struct gl_texture_object
*tObj
,
2246 GLuint n
, const GLfloat texcoord
[][4],
2247 const GLfloat lambda
[], GLchan rgba
[][4])
2250 ASSERT(lambda
!= NULL
);
2251 for (i
= 0; i
< n
; i
++) {
2252 const struct gl_texture_image
**images
;
2253 GLfloat newCoord
[4];
2255 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2256 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2257 if (level
>= tObj
->_MaxLevel
) {
2258 sample_2d_linear(ctx
, tObj
, images
[tObj
->_MaxLevel
],
2262 GLchan t0
[4], t1
[4];
2263 const GLfloat f
= FRAC(lambda
[i
]);
2264 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, t0
);
2265 sample_2d_linear(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
2266 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
2267 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
2268 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
2269 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
2276 sample_lambda_cube( GLcontext
*ctx
, GLuint texUnit
,
2277 const struct gl_texture_object
*tObj
, GLuint n
,
2278 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2281 GLuint minStart
, minEnd
; /* texels with minification */
2282 GLuint magStart
, magEnd
; /* texels with magnification */
2284 ASSERT(lambda
!= NULL
);
2285 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2286 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2288 if (minStart
< minEnd
) {
2289 /* do the minified texels */
2290 const GLuint m
= minEnd
- minStart
;
2291 switch (tObj
->MinFilter
) {
2293 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2294 lambda
+ minStart
, rgba
+ minStart
);
2297 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2298 lambda
+ minStart
, rgba
+ minStart
);
2300 case GL_NEAREST_MIPMAP_NEAREST
:
2301 sample_cube_nearest_mipmap_nearest(ctx
, texUnit
, tObj
, m
,
2302 texcoords
+ minStart
,
2303 lambda
+ minStart
, rgba
+ minStart
);
2305 case GL_LINEAR_MIPMAP_NEAREST
:
2306 sample_cube_linear_mipmap_nearest(ctx
, texUnit
, tObj
, m
,
2307 texcoords
+ minStart
,
2308 lambda
+ minStart
, rgba
+ minStart
);
2310 case GL_NEAREST_MIPMAP_LINEAR
:
2311 sample_cube_nearest_mipmap_linear(ctx
, texUnit
, tObj
, m
,
2312 texcoords
+ minStart
,
2313 lambda
+ minStart
, rgba
+ minStart
);
2315 case GL_LINEAR_MIPMAP_LINEAR
:
2316 sample_cube_linear_mipmap_linear(ctx
, texUnit
, tObj
, m
,
2317 texcoords
+ minStart
,
2318 lambda
+ minStart
, rgba
+ minStart
);
2321 _mesa_problem(ctx
, "Bad min filter in sample_lambda_cube");
2325 if (magStart
< magEnd
) {
2326 /* do the magnified texels */
2327 const GLuint m
= magEnd
- magStart
;
2328 switch (tObj
->MagFilter
) {
2330 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2331 lambda
+ magStart
, rgba
+ magStart
);
2334 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2335 lambda
+ magStart
, rgba
+ magStart
);
2338 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_cube");
2344 /**********************************************************************/
2345 /* Texture Rectangle Sampling Functions */
2346 /**********************************************************************/
2349 sample_nearest_rect(GLcontext
*ctx
, GLuint texUnit
,
2350 const struct gl_texture_object
*tObj
, GLuint n
,
2351 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2354 const struct gl_texture_image
*img
= tObj
->Image
[0];
2355 const GLfloat width
= (GLfloat
) img
->Width
;
2356 const GLfloat height
= (GLfloat
) img
->Height
;
2357 const GLint width_minus_1
= img
->Width
- 1;
2358 const GLint height_minus_1
= img
->Height
- 1;
2364 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2365 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2366 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2367 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2368 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2369 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2370 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2372 /* XXX move Wrap mode tests outside of loops for common cases */
2373 for (i
= 0; i
< n
; i
++) {
2375 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2376 if (tObj
->WrapS
== GL_CLAMP
) {
2377 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.0F
, width
) );
2379 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2380 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
) );
2383 col
= IFLOOR( CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
) );
2385 if (tObj
->WrapT
== GL_CLAMP
) {
2386 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.0F
, height
) );
2388 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2389 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
) );
2392 row
= IFLOOR( CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
) );
2395 col
= CLAMP(col
, 0, width_minus_1
);
2396 row
= CLAMP(row
, 0, height_minus_1
);
2398 (*img
->FetchTexel
)(img
, col
, row
, 0, (GLvoid
*) rgba
[i
]);
2404 sample_linear_rect(GLcontext
*ctx
, GLuint texUnit
,
2405 const struct gl_texture_object
*tObj
, GLuint n
,
2406 const GLfloat texcoords
[][4],
2407 const GLfloat lambda
[], GLchan rgba
[][4])
2409 const struct gl_texture_image
*img
= tObj
->Image
[0];
2410 const GLfloat width
= (GLfloat
) img
->Width
;
2411 const GLfloat height
= (GLfloat
) img
->Height
;
2412 const GLint width_minus_1
= img
->Width
- 1;
2413 const GLint height_minus_1
= img
->Height
- 1;
2419 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2420 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2421 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2422 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2423 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2424 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2425 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2427 /* XXX lots of opportunity for optimization in this loop */
2428 for (i
= 0; i
< n
; i
++) {
2430 GLint row0
, col0
, row1
, col1
;
2431 GLchan t00
[4], t01
[4], t10
[4], t11
[4];
2432 GLfloat a
, b
, w00
, w01
, w10
, w11
;
2434 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2435 if (tObj
->WrapS
== GL_CLAMP
) {
2436 fcol
= CLAMP(texcoords
[i
][0], 0.0F
, width
);
2438 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2439 fcol
= CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
);
2442 fcol
= CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
);
2444 if (tObj
->WrapT
== GL_CLAMP
) {
2445 frow
= CLAMP(texcoords
[i
][1], 0.0F
, height
);
2447 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2448 frow
= CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
);
2451 frow
= CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
);
2454 /* compute integer rows/columns */
2455 col0
= IFLOOR(fcol
);
2457 col0
= CLAMP(col0
, 0, width_minus_1
);
2458 col1
= CLAMP(col1
, 0, width_minus_1
);
2459 row0
= IFLOOR(frow
);
2461 row0
= CLAMP(row0
, 0, height_minus_1
);
2462 row1
= CLAMP(row1
, 0, height_minus_1
);
2464 /* get four texel samples */
2465 (*img
->FetchTexel
)(img
, col0
, row0
, 0, (GLvoid
*) t00
);
2466 (*img
->FetchTexel
)(img
, col1
, row0
, 0, (GLvoid
*) t10
);
2467 (*img
->FetchTexel
)(img
, col0
, row1
, 0, (GLvoid
*) t01
);
2468 (*img
->FetchTexel
)(img
, col1
, row1
, 0, (GLvoid
*) t11
);
2470 /* compute sample weights */
2473 w00
= (1.0F
-a
) * (1.0F
-b
);
2475 w01
= (1.0F
-a
) * b
;
2478 /* compute weighted average of samples */
2480 (GLchan
) (w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0]);
2482 (GLchan
) (w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1]);
2484 (GLchan
) (w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2]);
2486 (GLchan
) (w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3]);
2492 sample_lambda_rect( GLcontext
*ctx
, GLuint texUnit
,
2493 const struct gl_texture_object
*tObj
, GLuint n
,
2494 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2497 GLuint minStart
, minEnd
, magStart
, magEnd
;
2499 /* We only need lambda to decide between minification and magnification.
2500 * There is no mipmapping with rectangular textures.
2502 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2503 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2505 if (minStart
< minEnd
) {
2506 if (tObj
->MinFilter
== GL_NEAREST
) {
2507 sample_nearest_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2508 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2511 sample_linear_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2512 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2515 if (magStart
< magEnd
) {
2516 if (tObj
->MagFilter
== GL_NEAREST
) {
2517 sample_nearest_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2518 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2521 sample_linear_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2522 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2530 * Sample a shadow/depth texture.
2533 sample_depth_texture( GLcontext
*ctx
, GLuint unit
,
2534 const struct gl_texture_object
*tObj
, GLuint n
,
2535 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2538 const GLint baseLevel
= tObj
->BaseLevel
;
2539 const struct gl_texture_image
*texImage
= tObj
->Image
[baseLevel
];
2540 const GLuint width
= texImage
->Width
;
2541 const GLuint height
= texImage
->Height
;
2548 ASSERT(tObj
->Image
[tObj
->BaseLevel
]->Format
== GL_DEPTH_COMPONENT
);
2549 ASSERT(tObj
->Target
== GL_TEXTURE_1D
||
2550 tObj
->Target
== GL_TEXTURE_2D
||
2551 tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
2553 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2555 /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
2557 /* XXX this could be precomputed and saved in the texture object */
2558 if (tObj
->CompareFlag
) {
2559 /* GL_SGIX_shadow */
2560 if (tObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2561 function
= GL_LEQUAL
;
2564 ASSERT(tObj
->CompareOperator
== GL_TEXTURE_GEQUAL_R_SGIX
);
2565 function
= GL_GEQUAL
;
2568 else if (tObj
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
) {
2570 function
= tObj
->CompareFunc
;
2573 function
= GL_NONE
; /* pass depth through as grayscale */
2576 if (tObj
->MagFilter
== GL_NEAREST
) {
2578 for (i
= 0; i
< n
; i
++) {
2579 GLfloat depthSample
;
2581 /* XXX fix for texture rectangle! */
2582 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoords
[i
][0], width
, col
);
2583 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoords
[i
][1], height
, row
);
2584 depthSample
= *((const GLfloat
*) texImage
->Data
+ row
* width
+ col
);
2588 result
= (texcoords
[i
][2] <= depthSample
) ? CHAN_MAX
: ambient
;
2591 result
= (texcoords
[i
][2] >= depthSample
) ? CHAN_MAX
: ambient
;
2594 result
= (texcoords
[i
][2] < depthSample
) ? CHAN_MAX
: ambient
;
2597 result
= (texcoords
[i
][2] > depthSample
) ? CHAN_MAX
: ambient
;
2600 result
= (texcoords
[i
][2] == depthSample
) ? CHAN_MAX
: ambient
;
2603 result
= (texcoords
[i
][2] != depthSample
) ? CHAN_MAX
: ambient
;
2612 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2615 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2619 switch (tObj
->DepthMode
) {
2621 texel
[i
][RCOMP
] = result
;
2622 texel
[i
][GCOMP
] = result
;
2623 texel
[i
][BCOMP
] = result
;
2624 texel
[i
][ACOMP
] = CHAN_MAX
;
2627 texel
[i
][RCOMP
] = result
;
2628 texel
[i
][GCOMP
] = result
;
2629 texel
[i
][BCOMP
] = result
;
2630 texel
[i
][ACOMP
] = result
;
2633 texel
[i
][RCOMP
] = 0;
2634 texel
[i
][GCOMP
] = 0;
2635 texel
[i
][BCOMP
] = 0;
2636 texel
[i
][ACOMP
] = result
;
2639 _mesa_problem(ctx
, "Bad depth texture mode");
2645 ASSERT(tObj
->MagFilter
== GL_LINEAR
);
2646 for (i
= 0; i
< n
; i
++) {
2647 GLfloat depth00
, depth01
, depth10
, depth11
;
2648 GLint i0
, i1
, j0
, j1
;
2650 GLuint useBorderTexel
;
2652 /* XXX fix for texture rectangle! */
2653 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoords
[i
][0], u
, width
, i0
, i1
);
2654 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoords
[i
][1], v
, height
,j0
, j1
);
2657 if (texImage
->Border
) {
2658 i0
+= texImage
->Border
;
2659 i1
+= texImage
->Border
;
2660 j0
+= texImage
->Border
;
2661 j1
+= texImage
->Border
;
2664 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
2665 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
2666 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
2667 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
2670 /* get four depth samples from the texture */
2671 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
2675 depth00
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i0
);
2677 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
2681 depth10
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i1
);
2683 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
2687 depth01
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i0
);
2689 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
2693 depth11
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i1
);
2697 /* compute a single weighted depth sample and do one comparison */
2698 const GLfloat a
= FRAC(u
+ 1.0F
);
2699 const GLfloat b
= FRAC(v
+ 1.0F
);
2700 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2701 const GLfloat w10
= ( a
) * (1.0F
- b
);
2702 const GLfloat w01
= (1.0F
- a
) * ( b
);
2703 const GLfloat w11
= ( a
) * ( b
);
2704 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2705 + w01
* depth01
+ w11
* depth11
;
2706 if ((depthSample
<= texcoords
[i
][2] && function
== GL_LEQUAL
) ||
2707 (depthSample
>= texcoords
[i
][2] && function
== GL_GEQUAL
)) {
2715 /* Do four depth/R comparisons and compute a weighted result.
2716 * If this touches on somebody's I.P., I'll remove this code
2719 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
2720 GLfloat luminance
= CHAN_MAXF
;
2724 if (depth00
<= texcoords
[i
][2]) luminance
-= d
;
2725 if (depth01
<= texcoords
[i
][2]) luminance
-= d
;
2726 if (depth10
<= texcoords
[i
][2]) luminance
-= d
;
2727 if (depth11
<= texcoords
[i
][2]) luminance
-= d
;
2728 result
= (GLchan
) luminance
;
2731 if (depth00
>= texcoords
[i
][2]) luminance
-= d
;
2732 if (depth01
>= texcoords
[i
][2]) luminance
-= d
;
2733 if (depth10
>= texcoords
[i
][2]) luminance
-= d
;
2734 if (depth11
>= texcoords
[i
][2]) luminance
-= d
;
2735 result
= (GLchan
) luminance
;
2738 if (depth00
< texcoords
[i
][2]) luminance
-= d
;
2739 if (depth01
< texcoords
[i
][2]) luminance
-= d
;
2740 if (depth10
< texcoords
[i
][2]) luminance
-= d
;
2741 if (depth11
< texcoords
[i
][2]) luminance
-= d
;
2742 result
= (GLchan
) luminance
;
2745 if (depth00
> texcoords
[i
][2]) luminance
-= d
;
2746 if (depth01
> texcoords
[i
][2]) luminance
-= d
;
2747 if (depth10
> texcoords
[i
][2]) luminance
-= d
;
2748 if (depth11
> texcoords
[i
][2]) luminance
-= d
;
2749 result
= (GLchan
) luminance
;
2752 if (depth00
== texcoords
[i
][2]) luminance
-= d
;
2753 if (depth01
== texcoords
[i
][2]) luminance
-= d
;
2754 if (depth10
== texcoords
[i
][2]) luminance
-= d
;
2755 if (depth11
== texcoords
[i
][2]) luminance
-= d
;
2756 result
= (GLchan
) luminance
;
2759 if (depth00
!= texcoords
[i
][2]) luminance
-= d
;
2760 if (depth01
!= texcoords
[i
][2]) luminance
-= d
;
2761 if (depth10
!= texcoords
[i
][2]) luminance
-= d
;
2762 if (depth11
!= texcoords
[i
][2]) luminance
-= d
;
2763 result
= (GLchan
) luminance
;
2772 /* ordinary bilinear filtering */
2774 const GLfloat a
= FRAC(u
+ 1.0F
);
2775 const GLfloat b
= FRAC(v
+ 1.0F
);
2776 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2777 const GLfloat w10
= ( a
) * (1.0F
- b
);
2778 const GLfloat w01
= (1.0F
- a
) * ( b
);
2779 const GLfloat w11
= ( a
) * ( b
);
2780 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2781 + w01
* depth01
+ w11
* depth11
;
2782 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2786 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2791 switch (tObj
->DepthMode
) {
2793 texel
[i
][RCOMP
] = result
;
2794 texel
[i
][GCOMP
] = result
;
2795 texel
[i
][BCOMP
] = result
;
2796 texel
[i
][ACOMP
] = CHAN_MAX
;
2799 texel
[i
][RCOMP
] = result
;
2800 texel
[i
][GCOMP
] = result
;
2801 texel
[i
][BCOMP
] = result
;
2802 texel
[i
][ACOMP
] = result
;
2805 texel
[i
][RCOMP
] = 0;
2806 texel
[i
][GCOMP
] = 0;
2807 texel
[i
][BCOMP
] = 0;
2808 texel
[i
][ACOMP
] = result
;
2811 _mesa_problem(ctx
, "Bad depth texture mode");
2820 * Experimental depth texture sampling function.
2823 sample_depth_texture2(const GLcontext
*ctx
,
2824 const struct gl_texture_unit
*texUnit
,
2825 GLuint n
, const GLfloat texcoords
[][4],
2828 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2829 const GLint baseLevel
= texObj
->BaseLevel
;
2830 const struct gl_texture_image
*texImage
= texObj
->Image
[baseLevel
];
2831 const GLuint width
= texImage
->Width
;
2832 const GLuint height
= texImage
->Height
;
2834 GLboolean lequal
, gequal
;
2836 if (texObj
->Target
!= GL_TEXTURE_2D
) {
2837 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2841 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2842 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2846 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2847 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2848 * isn't a depth texture.
2850 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2851 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2855 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2857 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2868 for (i
= 0; i
< n
; i
++) {
2870 GLint col
, row
, ii
, jj
, imin
, imax
, jmin
, jmax
, samples
, count
;
2873 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, texcoords
[i
][0],
2875 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, texcoords
[i
][1],
2883 if (imin
< 0) imin
= 0;
2884 if (imax
>= width
) imax
= width
- 1;
2885 if (jmin
< 0) jmin
= 0;
2886 if (jmax
>= height
) jmax
= height
- 1;
2888 samples
= (imax
- imin
+ 1) * (jmax
- jmin
+ 1);
2890 for (jj
= jmin
; jj
<= jmax
; jj
++) {
2891 for (ii
= imin
; ii
<= imax
; ii
++) {
2892 GLfloat depthSample
= *((const GLfloat
*) texImage
->Data
2894 if ((depthSample
<= r
[i
] && lequal
) ||
2895 (depthSample
>= r
[i
] && gequal
)) {
2901 w
= (GLfloat
) count
/ (GLfloat
) samples
;
2902 w
= CHAN_MAXF
- w
* (CHAN_MAXF
- (GLfloat
) ambient
);
2905 texel
[i
][RCOMP
] = lum
;
2906 texel
[i
][GCOMP
] = lum
;
2907 texel
[i
][BCOMP
] = lum
;
2908 texel
[i
][ACOMP
] = CHAN_MAX
;
2916 * We use this function when a texture object is in an "incomplete" state.
2917 * When a fragment program attempts to sample an incomplete texture we
2919 * Note: frag progs don't observe texture enable/disable flags.
2922 null_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2923 const struct gl_texture_object
*tObj
, GLuint n
,
2924 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2932 _mesa_bzero(rgba
, n
* 4 * sizeof(GLchan
));
2938 * Setup the texture sampling function for this texture object.
2941 _swrast_choose_texture_sample_func( GLcontext
*ctx
,
2942 const struct gl_texture_object
*t
)
2944 const GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
2945 const GLenum format
= t
->Image
[t
->BaseLevel
]->Format
;
2948 return &null_sample_func
;
2951 switch (t
->Target
) {
2953 if (format
== GL_DEPTH_COMPONENT
) {
2954 return &sample_depth_texture
;
2956 else if (needLambda
) {
2957 return &sample_lambda_1d
;
2959 else if (t
->MinFilter
== GL_LINEAR
) {
2960 return &sample_linear_1d
;
2963 ASSERT(t
->MinFilter
== GL_NEAREST
);
2964 return &sample_nearest_1d
;
2968 if (format
== GL_DEPTH_COMPONENT
) {
2969 return &sample_depth_texture
;
2971 else if (needLambda
) {
2972 return &sample_lambda_2d
;
2974 else if (t
->MinFilter
== GL_LINEAR
) {
2975 return &sample_linear_2d
;
2978 GLint baseLevel
= t
->BaseLevel
;
2979 ASSERT(t
->MinFilter
== GL_NEAREST
);
2980 if (t
->WrapS
== GL_REPEAT
&&
2981 t
->WrapT
== GL_REPEAT
&&
2982 t
->Image
[baseLevel
]->Border
== 0 &&
2983 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGB
) {
2984 return &opt_sample_rgb_2d
;
2986 else if (t
->WrapS
== GL_REPEAT
&&
2987 t
->WrapT
== GL_REPEAT
&&
2988 t
->Image
[baseLevel
]->Border
== 0 &&
2989 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGBA
) {
2990 return &opt_sample_rgba_2d
;
2993 return &sample_nearest_2d
;
2999 return &sample_lambda_3d
;
3001 else if (t
->MinFilter
== GL_LINEAR
) {
3002 return &sample_linear_3d
;
3005 ASSERT(t
->MinFilter
== GL_NEAREST
);
3006 return &sample_nearest_3d
;
3009 case GL_TEXTURE_CUBE_MAP
:
3011 return &sample_lambda_cube
;
3013 else if (t
->MinFilter
== GL_LINEAR
) {
3014 return &sample_linear_cube
;
3017 ASSERT(t
->MinFilter
== GL_NEAREST
);
3018 return &sample_nearest_cube
;
3021 case GL_TEXTURE_RECTANGLE_NV
:
3023 return &sample_lambda_rect
;
3025 else if (t
->MinFilter
== GL_LINEAR
) {
3026 return &sample_linear_rect
;
3029 ASSERT(t
->MinFilter
== GL_NEAREST
);
3030 return &sample_nearest_rect
;
3035 "invalid target in _swrast_choose_texture_sample_func");
3036 return &null_sample_func
;
3041 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
3042 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
3046 * Do texture application for GL_ARB/EXT_texture_env_combine.
3047 * This function also supports GL_{EXT,ARB}_texture_env_dot3 and
3048 * GL_ATI_texture_env_combine3
3050 * \param ctx rendering context
3051 * \param textureUnit the texture unit to apply
3052 * \param n number of fragments to process (span width)
3053 * \param primary_rgba incoming fragment color array
3054 * \param texelBuffer pointer to texel colors for all texture units
3056 * \param rgba incoming colors, which get modified here
3059 texture_combine( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
3060 CONST
GLchan (*primary_rgba
)[4],
3061 CONST GLchan
*texelBuffer
,
3064 const struct gl_texture_unit
*textureUnit
= &(ctx
->Texture
.Unit
[unit
]);
3065 const GLchan (*argRGB
[3])[4];
3066 const GLchan (*argA
[3])[4];
3067 const GLuint RGBshift
= textureUnit
->CombineScaleShiftRGB
;
3068 const GLuint Ashift
= textureUnit
->CombineScaleShiftA
;
3069 #if CHAN_TYPE == GL_FLOAT
3070 const GLchan RGBmult
= (GLfloat
) (1 << RGBshift
);
3071 const GLchan Amult
= (GLfloat
) (1 << Ashift
);
3072 static const GLchan one
[4] = { 1.0, 1.0, 1.0, 1.0 };
3073 static const GLchan zero
[4] = { 0.0, 0.0, 0.0, 0.0 };
3075 const GLint half
= (CHAN_MAX
+ 1) / 2;
3076 static const GLchan one
[4] = { CHAN_MAX
, CHAN_MAX
, CHAN_MAX
, CHAN_MAX
};
3077 static const GLchan zero
[4] = { 0, 0, 0, 0 };
3080 GLuint numColorArgs
;
3081 GLuint numAlphaArgs
;
3083 /* GLchan ccolor[3][4]; */
3084 DEFMNARRAY(GLchan
, ccolor
, 3, 3 * MAX_WIDTH
, 4); /* mac 32k limitation */
3085 CHECKARRAY(ccolor
, return); /* mac 32k limitation */
3087 ASSERT(ctx
->Extensions
.EXT_texture_env_combine
||
3088 ctx
->Extensions
.ARB_texture_env_combine
);
3089 ASSERT(SWRAST_CONTEXT(ctx
)->_AnyTextureCombine
);
3093 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
3094 textureUnit->CombineModeRGB,
3095 textureUnit->CombineModeA,
3096 textureUnit->CombineSourceRGB[0],
3097 textureUnit->CombineSourceA[0],
3098 textureUnit->CombineSourceRGB[1],
3099 textureUnit->CombineSourceA[1]);
3103 * Do operand setup for up to 3 operands. Loop over the terms.
3105 switch (textureUnit
->CombineModeRGB
) {
3115 case GL_DOT3_RGB_EXT
:
3116 case GL_DOT3_RGBA_EXT
:
3119 case GL_INTERPOLATE
:
3120 case GL_MODULATE_ADD_ATI
:
3121 case GL_MODULATE_SIGNED_ADD_ATI
:
3122 case GL_MODULATE_SUBTRACT_ATI
:
3131 switch (textureUnit
->CombineModeA
) {
3141 case GL_INTERPOLATE
:
3142 case GL_MODULATE_ADD_ATI
:
3143 case GL_MODULATE_SIGNED_ADD_ATI
:
3144 case GL_MODULATE_SUBTRACT_ATI
:
3153 for (j
= 0; j
< numColorArgs
; j
++) {
3154 const GLenum srcRGB
= textureUnit
->CombineSourceRGB
[j
];
3159 argRGB
[j
] = (const GLchan (*)[4])
3160 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
3162 case GL_PRIMARY_COLOR
:
3163 argRGB
[j
] = primary_rgba
;
3166 argRGB
[j
] = (const GLchan (*)[4]) rgba
;
3170 GLchan (*c
)[4] = ccolor
[j
];
3171 GLchan red
, green
, blue
, alpha
;
3172 UNCLAMPED_FLOAT_TO_CHAN(red
, textureUnit
->EnvColor
[0]);
3173 UNCLAMPED_FLOAT_TO_CHAN(green
, textureUnit
->EnvColor
[1]);
3174 UNCLAMPED_FLOAT_TO_CHAN(blue
, textureUnit
->EnvColor
[2]);
3175 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
3176 for (i
= 0; i
< n
; i
++) {
3178 c
[i
][GCOMP
] = green
;
3180 c
[i
][ACOMP
] = alpha
;
3182 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3185 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
3194 /* ARB_texture_env_crossbar source */
3196 const GLuint srcUnit
= srcRGB
- GL_TEXTURE0
;
3197 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
3198 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
3200 argRGB
[j
] = (const GLchan (*)[4])
3201 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
3205 if (textureUnit
->CombineOperandRGB
[j
] != GL_SRC_COLOR
) {
3206 const GLchan (*src
)[4] = argRGB
[j
];
3207 GLchan (*dst
)[4] = ccolor
[j
];
3209 /* point to new arg[j] storage */
3210 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3212 if (textureUnit
->CombineOperandRGB
[j
] == GL_ONE_MINUS_SRC_COLOR
) {
3213 for (i
= 0; i
< n
; i
++) {
3214 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][RCOMP
];
3215 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][GCOMP
];
3216 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][BCOMP
];
3219 else if (textureUnit
->CombineOperandRGB
[j
] == GL_SRC_ALPHA
) {
3220 for (i
= 0; i
< n
; i
++) {
3221 dst
[i
][RCOMP
] = src
[i
][ACOMP
];
3222 dst
[i
][GCOMP
] = src
[i
][ACOMP
];
3223 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
3227 ASSERT(textureUnit
->CombineOperandRGB
[j
] ==GL_ONE_MINUS_SRC_ALPHA
);
3228 for (i
= 0; i
< n
; i
++) {
3229 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3230 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3231 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3238 for (j
= 0; j
< numAlphaArgs
; j
++) {
3239 const GLenum srcA
= textureUnit
->CombineSourceA
[j
];
3243 argA
[j
] = (const GLchan (*)[4])
3244 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
3246 case GL_PRIMARY_COLOR
:
3247 argA
[j
] = primary_rgba
;
3250 argA
[j
] = (const GLchan (*)[4]) rgba
;
3254 GLchan alpha
, (*c
)[4] = ccolor
[j
];
3255 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
3256 for (i
= 0; i
< n
; i
++)
3257 c
[i
][ACOMP
] = alpha
;
3258 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3261 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
3270 /* ARB_texture_env_crossbar source */
3272 const GLuint srcUnit
= srcA
- GL_TEXTURE0
;
3273 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
3274 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
3276 argA
[j
] = (const GLchan (*)[4])
3277 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
3281 if (textureUnit
->CombineOperandA
[j
] == GL_ONE_MINUS_SRC_ALPHA
) {
3282 const GLchan (*src
)[4] = argA
[j
];
3283 GLchan (*dst
)[4] = ccolor
[j
];
3284 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3285 for (i
= 0; i
< n
; i
++) {
3286 dst
[i
][ACOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3292 * Do the texture combine.
3294 switch (textureUnit
->CombineModeRGB
) {
3297 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3299 for (i
= 0; i
< n
; i
++) {
3300 #if CHAN_TYPE == GL_FLOAT
3301 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * RGBmult
;
3302 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * RGBmult
;
3303 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * RGBmult
;
3305 GLuint r
= (GLuint
) arg0
[i
][RCOMP
] << RGBshift
;
3306 GLuint g
= (GLuint
) arg0
[i
][GCOMP
] << RGBshift
;
3307 GLuint b
= (GLuint
) arg0
[i
][BCOMP
] << RGBshift
;
3308 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3309 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3310 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3315 for (i
= 0; i
< n
; i
++) {
3316 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
];
3317 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
];
3318 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
];
3325 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3326 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3327 #if CHAN_TYPE != GL_FLOAT
3328 const GLint shift
= CHAN_BITS
- RGBshift
;
3330 for (i
= 0; i
< n
; i
++) {
3331 #if CHAN_TYPE == GL_FLOAT
3332 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * RGBmult
;
3333 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * RGBmult
;
3334 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * RGBmult
;
3336 GLuint r
= PROD(arg0
[i
][RCOMP
], arg1
[i
][RCOMP
]) >> shift
;
3337 GLuint g
= PROD(arg0
[i
][GCOMP
], arg1
[i
][GCOMP
]) >> shift
;
3338 GLuint b
= PROD(arg0
[i
][BCOMP
], arg1
[i
][BCOMP
]) >> shift
;
3339 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3340 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3341 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3348 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3349 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3350 for (i
= 0; i
< n
; i
++) {
3351 #if CHAN_TYPE == GL_FLOAT
3352 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * RGBmult
;
3353 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * RGBmult
;
3354 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * RGBmult
;
3356 GLint r
= ((GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3357 GLint g
= ((GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3358 GLint b
= ((GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3359 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3360 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3361 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3368 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3369 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3370 for (i
= 0; i
< n
; i
++) {
3371 #if CHAN_TYPE == GL_FLOAT
3372 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3373 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3374 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3376 GLint r
= (GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
] -half
;
3377 GLint g
= (GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
] -half
;
3378 GLint b
= (GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
] -half
;
3379 r
= (r
< 0) ? 0 : r
<< RGBshift
;
3380 g
= (g
< 0) ? 0 : g
<< RGBshift
;
3381 b
= (b
< 0) ? 0 : b
<< RGBshift
;
3382 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3383 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3384 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3389 case GL_INTERPOLATE
:
3391 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3392 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3393 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3394 #if CHAN_TYPE != GL_FLOAT
3395 const GLint shift
= CHAN_BITS
- RGBshift
;
3397 for (i
= 0; i
< n
; i
++) {
3398 #if CHAN_TYPE == GL_FLOAT
3399 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
3400 arg1
[i
][RCOMP
] * (CHAN_MAXF
- arg2
[i
][RCOMP
])) * RGBmult
;
3401 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
3402 arg1
[i
][GCOMP
] * (CHAN_MAXF
- arg2
[i
][GCOMP
])) * RGBmult
;
3403 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
3404 arg1
[i
][BCOMP
] * (CHAN_MAXF
- arg2
[i
][BCOMP
])) * RGBmult
;
3406 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3407 + PROD(arg1
[i
][RCOMP
], CHAN_MAX
- arg2
[i
][RCOMP
]))
3409 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3410 + PROD(arg1
[i
][GCOMP
], CHAN_MAX
- arg2
[i
][GCOMP
]))
3412 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3413 + PROD(arg1
[i
][BCOMP
], CHAN_MAX
- arg2
[i
][BCOMP
]))
3415 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3416 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3417 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3424 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3425 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3426 for (i
= 0; i
< n
; i
++) {
3427 #if CHAN_TYPE == GL_FLOAT
3428 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * RGBmult
;
3429 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * RGBmult
;
3430 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * RGBmult
;
3432 GLint r
= ((GLint
) arg0
[i
][RCOMP
] - (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3433 GLint g
= ((GLint
) arg0
[i
][GCOMP
] - (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3434 GLint b
= ((GLint
) arg0
[i
][BCOMP
] - (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3435 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3436 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3437 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3442 case GL_DOT3_RGB_EXT
:
3443 case GL_DOT3_RGBA_EXT
:
3445 /* Do not scale the result by 1 2 or 4 */
3446 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3447 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3448 for (i
= 0; i
< n
; i
++) {
3449 #if CHAN_TYPE == GL_FLOAT
3450 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3451 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3452 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3454 dot
= CLAMP(dot
, 0.0F
, CHAN_MAXF
);
3456 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3457 (GLint
)arg1
[i
][RCOMP
] - half
) +
3458 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3459 (GLint
)arg1
[i
][GCOMP
] - half
) +
3460 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3461 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3462 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3464 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3471 /* DO scale the result by 1 2 or 4 */
3472 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3473 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3474 for (i
= 0; i
< n
; i
++) {
3475 #if CHAN_TYPE == GL_FLOAT
3476 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3477 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3478 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3480 dot
= CLAMP(dot
, 0.0, CHAN_MAXF
);
3482 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3483 (GLint
)arg1
[i
][RCOMP
] - half
) +
3484 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3485 (GLint
)arg1
[i
][GCOMP
] - half
) +
3486 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3487 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3489 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3491 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3495 case GL_MODULATE_ADD_ATI
:
3497 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3498 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3499 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3500 #if CHAN_TYPE != GL_FLOAT
3501 const GLint shift
= CHAN_BITS
- RGBshift
;
3503 for (i
= 0; i
< n
; i
++) {
3504 #if CHAN_TYPE == GL_FLOAT
3505 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) + arg1
[i
][RCOMP
]) * RGBmult
;
3506 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
]) * RGBmult
;
3507 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
]) * RGBmult
;
3509 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3510 + ((GLuint
) arg1
[i
][RCOMP
] << CHAN_BITS
)) >> shift
;
3511 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3512 + ((GLuint
) arg1
[i
][GCOMP
] << CHAN_BITS
)) >> shift
;
3513 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3514 + ((GLuint
) arg1
[i
][BCOMP
] << CHAN_BITS
)) >> shift
;
3515 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3516 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3517 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3522 case GL_MODULATE_SIGNED_ADD_ATI
:
3524 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3525 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3526 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3527 #if CHAN_TYPE != GL_FLOAT
3528 const GLint shift
= CHAN_BITS
- RGBshift
;
3530 for (i
= 0; i
< n
; i
++) {
3531 #if CHAN_TYPE == GL_FLOAT
3532 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3533 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3534 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3536 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3537 + (((GLint
) arg1
[i
][RCOMP
] - half
) << CHAN_BITS
))
3539 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3540 + (((GLint
) arg1
[i
][GCOMP
] - half
) << CHAN_BITS
))
3542 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3543 + (((GLint
) arg1
[i
][BCOMP
] - half
) << CHAN_BITS
))
3545 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3546 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3547 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3552 case GL_MODULATE_SUBTRACT_ATI
:
3554 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3555 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3556 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3557 #if CHAN_TYPE != GL_FLOAT
3558 const GLint shift
= CHAN_BITS
- RGBshift
;
3560 for (i
= 0; i
< n
; i
++) {
3561 #if CHAN_TYPE == GL_FLOAT
3562 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) - arg1
[i
][RCOMP
]) * RGBmult
;
3563 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) - arg1
[i
][GCOMP
]) * RGBmult
;
3564 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) - arg1
[i
][BCOMP
]) * RGBmult
;
3566 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3567 - ((GLint
) arg1
[i
][RCOMP
] << CHAN_BITS
))
3569 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3570 - ((GLint
) arg1
[i
][GCOMP
] << CHAN_BITS
))
3572 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3573 - ((GLint
) arg1
[i
][BCOMP
] << CHAN_BITS
))
3575 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3576 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3577 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3583 _mesa_problem(ctx
, "invalid combine mode");
3586 switch (textureUnit
->CombineModeA
) {
3589 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3591 for (i
= 0; i
< n
; i
++) {
3592 #if CHAN_TYPE == GL_FLOAT
3593 GLchan a
= arg0
[i
][ACOMP
] * Amult
;
3595 GLuint a
= (GLuint
) arg0
[i
][ACOMP
] << Ashift
;
3597 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3601 for (i
= 0; i
< n
; i
++) {
3602 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
];
3609 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3610 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3611 #if CHAN_TYPE != GL_FLOAT
3612 const GLint shift
= CHAN_BITS
- Ashift
;
3614 for (i
= 0; i
< n
; i
++) {
3615 #if CHAN_TYPE == GL_FLOAT
3616 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * Amult
;
3618 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg1
[i
][ACOMP
]) >> shift
);
3619 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3626 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3627 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3628 for (i
= 0; i
< n
; i
++) {
3629 #if CHAN_TYPE == GL_FLOAT
3630 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * Amult
;
3632 GLint a
= ((GLint
) arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) << Ashift
;
3633 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3640 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3641 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3642 for (i
= 0; i
< n
; i
++) {
3643 #if CHAN_TYPE == GL_FLOAT
3644 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3646 GLint a
= (GLint
) arg0
[i
][ACOMP
] + (GLint
) arg1
[i
][ACOMP
] -half
;
3647 a
= (a
< 0) ? 0 : a
<< Ashift
;
3648 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3653 case GL_INTERPOLATE
:
3655 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3656 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3657 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3658 #if CHAN_TYPE != GL_FLOAT
3659 const GLint shift
= CHAN_BITS
- Ashift
;
3661 for (i
=0; i
<n
; i
++) {
3662 #if CHAN_TYPE == GL_FLOAT
3663 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
3664 arg1
[i
][ACOMP
] * (CHAN_MAXF
- arg2
[i
][ACOMP
]))
3667 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3668 + PROD(arg1
[i
][ACOMP
], CHAN_MAX
- arg2
[i
][ACOMP
]))
3670 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3677 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3678 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3679 for (i
= 0; i
< n
; i
++) {
3680 #if CHAN_TYPE == GL_FLOAT
3681 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * Amult
;
3683 GLint a
= ((GLint
) arg0
[i
][ACOMP
] - (GLint
) arg1
[i
][ACOMP
]) << Ashift
;
3684 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3689 case GL_MODULATE_ADD_ATI
:
3691 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3692 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3693 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3694 #if CHAN_TYPE != GL_FLOAT
3695 const GLint shift
= CHAN_BITS
- Ashift
;
3697 for (i
= 0; i
< n
; i
++) {
3698 #if CHAN_TYPE == GL_FLOAT
3699 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
]) * Amult
;
3701 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3702 + ((GLuint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3704 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3709 case GL_MODULATE_SIGNED_ADD_ATI
:
3711 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3712 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3713 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3714 #if CHAN_TYPE != GL_FLOAT
3715 const GLint shift
= CHAN_BITS
- Ashift
;
3717 for (i
= 0; i
< n
; i
++) {
3718 #if CHAN_TYPE == GL_FLOAT
3719 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3721 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3722 + (((GLint
) arg1
[i
][ACOMP
] - half
) << CHAN_BITS
))
3724 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3729 case GL_MODULATE_SUBTRACT_ATI
:
3731 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3732 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3733 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3734 #if CHAN_TYPE != GL_FLOAT
3735 const GLint shift
= CHAN_BITS
- Ashift
;
3737 for (i
= 0; i
< n
; i
++) {
3738 #if CHAN_TYPE == GL_FLOAT
3739 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) - arg1
[i
][ACOMP
]) * Amult
;
3741 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3742 - ((GLint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3744 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3750 _mesa_problem(ctx
, "invalid combine mode");
3753 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
3754 * This is kind of a kludge. It would have been better if the spec
3755 * were written such that the GL_COMBINE_ALPHA value could be set to
3758 if (textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_EXT
||
3759 textureUnit
->CombineModeRGB
== GL_DOT3_RGBA
) {
3760 for (i
= 0; i
< n
; i
++) {
3761 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
3764 UNDEFARRAY(ccolor
); /* mac 32k limitation */
3770 * Implement NVIDIA's GL_NV_texture_env_combine4 extension when
3771 * texUnit->EnvMode == GL_COMBINE4_NV.
3774 texture_combine4( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
3775 CONST
GLchan (*primary_rgba
)[4],
3776 CONST GLchan
*texelBuffer
,
3784 * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND,
3785 * MODULATE, or DECAL) to an array of fragments.
3786 * Input: textureUnit - pointer to texture unit to apply
3787 * format - base internal texture format
3788 * n - number of fragments
3789 * primary_rgba - primary colors (may alias rgba for single texture)
3790 * texels - array of texel colors
3791 * InOut: rgba - incoming fragment colors modified by texel colors
3792 * according to the texture environment mode.
3795 texture_apply( const GLcontext
*ctx
,
3796 const struct gl_texture_unit
*texUnit
,
3798 CONST GLchan primary_rgba
[][4], CONST GLchan texel
[][4],
3803 GLint Rc
, Gc
, Bc
, Ac
;
3807 ASSERT(texUnit
->_Current
);
3809 baseLevel
= texUnit
->_Current
->BaseLevel
;
3810 ASSERT(texUnit
->_Current
->Image
[baseLevel
]);
3812 format
= texUnit
->_Current
->Image
[baseLevel
]->Format
;
3814 if (format
== GL_COLOR_INDEX
|| format
== GL_DEPTH_COMPONENT
3815 || format
== GL_YCBCR_MESA
) {
3816 format
= GL_RGBA
; /* a bit of a hack */
3819 switch (texUnit
->EnvMode
) {
3826 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3832 GLchan Lt
= texel
[i
][RCOMP
];
3833 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3837 case GL_LUMINANCE_ALPHA
:
3839 GLchan Lt
= texel
[i
][RCOMP
];
3841 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3843 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3849 GLchan It
= texel
[i
][RCOMP
];
3850 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
3852 rgba
[i
][ACOMP
] = It
;
3858 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3859 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3860 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3867 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3868 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3869 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3871 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3875 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in texture_apply");
3886 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3892 GLchan Lt
= texel
[i
][RCOMP
];
3893 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3894 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3895 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3899 case GL_LUMINANCE_ALPHA
:
3902 GLchan Lt
= texel
[i
][RCOMP
];
3903 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3904 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3905 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3907 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3913 GLchan It
= texel
[i
][RCOMP
];
3914 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], It
);
3915 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], It
);
3916 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], It
);
3918 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], It
);
3924 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3925 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3926 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3933 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3934 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3935 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3937 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3941 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in texture_apply");
3950 case GL_LUMINANCE_ALPHA
:
3957 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3958 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3959 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3965 /* Cv = Cf(1-At) + CtAt */
3966 GLint t
= texel
[i
][ACOMP
], s
= CHAN_MAX
- t
;
3967 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(texel
[i
][RCOMP
],t
);
3968 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(texel
[i
][GCOMP
],t
);
3969 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(texel
[i
][BCOMP
],t
);
3974 _mesa_problem(ctx
, "Bad format (GL_DECAL) in texture_apply");
3980 Rc
= (GLint
) (texUnit
->EnvColor
[0] * CHAN_MAXF
);
3981 Gc
= (GLint
) (texUnit
->EnvColor
[1] * CHAN_MAXF
);
3982 Bc
= (GLint
) (texUnit
->EnvColor
[2] * CHAN_MAXF
);
3983 Ac
= (GLint
) (texUnit
->EnvColor
[3] * CHAN_MAXF
);
3989 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3994 /* Cv = Cf(1-Lt) + CcLt */
3995 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3996 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3997 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3998 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
4002 case GL_LUMINANCE_ALPHA
:
4004 /* Cv = Cf(1-Lt) + CcLt */
4005 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
4006 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
4007 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
4008 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
4010 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
4015 /* Cv = Cf(1-It) + CcLt */
4016 GLchan It
= texel
[i
][RCOMP
], s
= CHAN_MAX
- It
;
4017 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, It
);
4018 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, It
);
4019 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, It
);
4020 /* Av = Af(1-It) + Ac*It */
4021 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], s
) + CHAN_PRODUCT(Ac
, It
);
4026 /* Cv = Cf(1-Ct) + CcCt */
4027 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
4028 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
4029 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
4035 /* Cv = Cf(1-Ct) + CcCt */
4036 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
4037 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
4038 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
4040 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
4044 _mesa_problem(ctx
, "Bad format (GL_BLEND) in texture_apply");
4049 /* XXX don't clamp results if GLchan is float??? */
4051 case GL_ADD
: /* GL_EXT_texture_add_env */
4058 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4063 GLuint Lt
= texel
[i
][RCOMP
];
4064 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
4065 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
4066 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
4067 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4068 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4069 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4073 case GL_LUMINANCE_ALPHA
:
4075 GLuint Lt
= texel
[i
][RCOMP
];
4076 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
4077 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
4078 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
4079 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4080 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4081 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4082 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4087 GLchan It
= texel
[i
][RCOMP
];
4088 GLuint r
= rgba
[i
][RCOMP
] + It
;
4089 GLuint g
= rgba
[i
][GCOMP
] + It
;
4090 GLuint b
= rgba
[i
][BCOMP
] + It
;
4091 GLuint a
= rgba
[i
][ACOMP
] + It
;
4092 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4093 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4094 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4095 rgba
[i
][ACOMP
] = MIN2(a
, CHAN_MAX
);
4100 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
4101 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
4102 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
4103 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4104 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4105 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4111 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
4112 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
4113 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
4114 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4115 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4116 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4117 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4121 _mesa_problem(ctx
, "Bad format (GL_ADD) in texture_apply");
4127 _mesa_problem(ctx
, "Bad env mode in texture_apply");
4135 * Apply texture mapping to a span of fragments.
4138 _swrast_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
4140 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
4141 GLchan primary_rgba
[MAX_WIDTH
][4];
4144 ASSERT(span
->end
< MAX_WIDTH
);
4145 ASSERT(span
->arrayMask
& SPAN_TEXTURE
);
4148 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
4150 if (swrast
->_AnyTextureCombine
)
4151 MEMCPY(primary_rgba
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
));
4154 * Must do all texture sampling before combining in order to
4155 * accomodate GL_ARB_texture_env_crossbar.
4157 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
4158 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
4159 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
4160 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
4161 GLfloat
*lambda
= span
->array
->lambda
[unit
];
4162 GLchan (*texels
)[4] = (GLchan (*)[4])
4163 (swrast
->TexelBuffer
+ unit
* (span
->end
* 4 * sizeof(GLchan
)));
4165 /* adjust texture lod (lambda) */
4166 if (span
->arrayMask
& SPAN_LAMBDA
) {
4167 if (texUnit
->LodBias
!= 0.0F
) {
4168 /* apply LOD bias, but don't clamp yet */
4170 for (i
= 0; i
< span
->end
; i
++) {
4171 lambda
[i
] += texUnit
->LodBias
;
4175 if (curObj
->MinLod
!= -1000.0 || curObj
->MaxLod
!= 1000.0) {
4176 /* apply LOD clamping to lambda */
4177 const GLfloat min
= curObj
->MinLod
;
4178 const GLfloat max
= curObj
->MaxLod
;
4180 for (i
= 0; i
< span
->end
; i
++) {
4181 GLfloat l
= lambda
[i
];
4182 lambda
[i
] = CLAMP(l
, min
, max
);
4187 /* Sample the texture (span->end fragments) */
4188 swrast
->TextureSample
[unit
]( ctx
, unit
, texUnit
->_Current
, span
->end
,
4189 (const GLfloat (*)[4]) span
->array
->texcoords
[unit
],
4191 /* GL_SGI_texture_color_table */
4192 if (texUnit
->ColorTableEnabled
) {
4193 _swrast_texture_table_lookup(&texUnit
->ColorTable
, span
->end
, texels
);
4199 * OK, now apply the texture (aka texture combine/blend).
4200 * We modify the span->color.rgba values.
4202 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
4203 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
4204 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
4205 if (texUnit
->EnvMode
== GL_COMBINE
) {
4206 /* GL_ARB/EXT_texture_env_combine */
4207 texture_combine( ctx
, unit
, span
->end
,
4208 (CONST
GLchan (*)[4]) primary_rgba
,
4209 swrast
->TexelBuffer
,
4210 span
->array
->rgba
);
4212 else if (texUnit
->EnvMode
== GL_COMBINE4_NV
) {
4213 /* GL_NV_texture_env_combine4 */
4214 texture_combine4( ctx
, unit
, span
->end
,
4215 (CONST
GLchan (*)[4]) primary_rgba
,
4216 swrast
->TexelBuffer
,
4217 span
->array
->rgba
);
4220 /* conventional texture blend */
4221 const GLchan (*texels
)[4] = (const GLchan (*)[4])
4222 (swrast
->TexelBuffer
+ unit
*
4223 (span
->end
* 4 * sizeof(GLchan
)));
4224 texture_apply( ctx
, texUnit
, span
->end
,
4225 (CONST
GLchan (*)[4]) primary_rgba
, texels
,
4226 span
->array
->rgba
);