2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 #include "texformat.h"
34 #include "s_context.h"
35 #include "s_texture.h"
39 * These values are used in the fixed-point arithmetic used
40 * for linear filtering.
42 #define WEIGHT_SCALE 65536.0F
43 #define WEIGHT_SHIFT 16
47 * Compute the remainder of a divided by b, but be careful with
48 * negative values so that GL_REPEAT mode works right.
51 repeat_remainder(GLint a
, GLint b
)
56 return (a
+ 1) % b
+ b
- 1;
61 * Used to compute texel locations for linear sampling.
63 * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER
64 * S = texcoord in [0,1]
65 * SIZE = width (or height or depth) of texture
67 * U = texcoord in [0, width]
68 * I0, I1 = two nearest texel indexes
70 #define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1) \
72 if (wrapMode == GL_REPEAT) { \
73 U = S * SIZE - 0.5F; \
74 if (tObj->_IsPowerOfTwo) { \
75 I0 = IFLOOR(U) & (SIZE - 1); \
76 I1 = (I0 + 1) & (SIZE - 1); \
79 I0 = repeat_remainder(IFLOOR(U), SIZE); \
80 I1 = repeat_remainder(I0 + 1, SIZE); \
83 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
95 if (I1 >= (GLint) SIZE) \
98 else if (wrapMode == GL_CLAMP_TO_BORDER) { \
99 const GLfloat min = -1.0F / (2.0F * SIZE); \
100 const GLfloat max = 1.0F - min; \
111 else if (wrapMode == GL_MIRRORED_REPEAT) { \
112 const GLint flr = IFLOOR(S); \
114 U = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
116 U = S - (GLfloat) flr; /* flr is even */ \
117 U = (U * SIZE) - 0.5F; \
122 if (I1 >= (GLint) SIZE) \
125 else if (wrapMode == GL_MIRROR_CLAMP_ATI) { \
126 U = (GLfloat) fabs(S); \
128 U = (GLfloat) SIZE; \
135 else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_ATI) { \
136 U = (GLfloat) fabs(S); \
138 U = (GLfloat) SIZE; \
146 if (I1 >= (GLint) SIZE) \
150 ASSERT(wrapMode == GL_CLAMP); \
153 else if (S >= 1.0F) \
154 U = (GLfloat) SIZE; \
165 * Used to compute texel location for nearest sampling.
167 #define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I) \
169 if (wrapMode == GL_REPEAT) { \
170 /* s limited to [0,1) */ \
171 /* i limited to [0,size-1] */ \
172 I = IFLOOR(S * SIZE); \
173 if (tObj->_IsPowerOfTwo) \
176 I = repeat_remainder(I, SIZE); \
178 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
179 /* s limited to [min,max] */ \
180 /* i limited to [0, size-1] */ \
181 const GLfloat min = 1.0F / (2.0F * SIZE); \
182 const GLfloat max = 1.0F - min; \
188 I = IFLOOR(S * SIZE); \
190 else if (wrapMode == GL_CLAMP_TO_BORDER) { \
191 /* s limited to [min,max] */ \
192 /* i limited to [-1, size] */ \
193 const GLfloat min = -1.0F / (2.0F * SIZE); \
194 const GLfloat max = 1.0F - min; \
200 I = IFLOOR(S * SIZE); \
202 else if (wrapMode == GL_MIRRORED_REPEAT) { \
203 const GLfloat min = 1.0F / (2.0F * SIZE); \
204 const GLfloat max = 1.0F - min; \
205 const GLint flr = IFLOOR(S); \
208 u = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
210 u = S - (GLfloat) flr; /* flr is even */ \
216 I = IFLOOR(u * SIZE); \
218 else if (wrapMode == GL_MIRROR_CLAMP_ATI) { \
219 /* s limited to [0,1] */ \
220 /* i limited to [0,size-1] */ \
221 const GLfloat u = (GLfloat) fabs(S); \
224 else if (u >= 1.0F) \
227 I = IFLOOR(u * SIZE); \
229 else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_ATI) { \
230 /* s limited to [min,max] */ \
231 /* i limited to [0, size-1] */ \
232 const GLfloat min = 1.0F / (2.0F * SIZE); \
233 const GLfloat max = 1.0F - min; \
234 const GLfloat u = (GLfloat) fabs(S); \
240 I = IFLOOR(u * SIZE); \
243 ASSERT(wrapMode == GL_CLAMP); \
244 /* s limited to [0,1] */ \
245 /* i limited to [0,size-1] */ \
248 else if (S >= 1.0F) \
251 I = IFLOOR(S * SIZE); \
256 /* Power of two image sizes only */
257 #define COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(S, U, SIZE, I0, I1) \
259 U = S * SIZE - 0.5F; \
260 I0 = IFLOOR(U) & (SIZE - 1); \
261 I1 = (I0 + 1) & (SIZE - 1); \
266 * Compute linear mipmap levels for given lambda.
268 #define COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level) \
271 level = tObj->BaseLevel; \
272 else if (lambda > tObj->_MaxLambda) \
273 level = (GLint) (tObj->BaseLevel + tObj->_MaxLambda); \
275 level = (GLint) (tObj->BaseLevel + lambda); \
280 * Compute nearest mipmap level for given lambda.
282 #define COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level) \
285 if (lambda <= 0.5F) \
287 else if (lambda > tObj->_MaxLambda + 0.4999F) \
288 l = tObj->_MaxLambda + 0.4999F; \
291 level = (GLint) (tObj->BaseLevel + l + 0.5F); \
292 if (level > tObj->_MaxLevel) \
293 level = tObj->_MaxLevel; \
299 * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
300 * see 1-pixel bands of improperly weighted linear-sampled texels. The
301 * tests/texwrap.c demo is a good test.
302 * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
303 * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
305 #define FRAC(f) ((f) - IFLOOR(f))
310 * Bitflags for texture border color sampling.
321 * Do the lookup for GL_SGI_texture_color_table.
324 _swrast_texture_table_lookup(const struct gl_color_table
*table
,
325 GLuint n
, GLchan rgba
[][4])
327 if (!table
->Table
|| table
->Size
== 0)
330 switch (table
->Format
) {
332 /* replace RGBA with I */
333 if (table
->FloatTable
) {
334 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
335 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
337 for (i
= 0; i
< n
; i
++) {
338 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
340 CLAMPED_FLOAT_TO_CHAN(c
, lut
[j
]);
341 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] =
342 rgba
[i
][BCOMP
] = rgba
[i
][ACOMP
] = c
;
346 #if CHAN_TYPE == GL_UNSIGNED_BYTE
347 if (table
->Size
== 256) {
349 const GLchan
*lut
= (const GLchan
*) table
->Table
;
351 for (i
= 0; i
< n
; i
++) {
352 const GLchan c
= lut
[rgba
[i
][RCOMP
]];
353 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] =
354 rgba
[i
][BCOMP
] = rgba
[i
][ACOMP
] = c
;
360 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
361 const GLchan
*lut
= (const GLchan
*) table
->Table
;
363 for (i
= 0; i
< n
; i
++) {
364 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
365 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] =
366 rgba
[i
][BCOMP
] = rgba
[i
][ACOMP
] = lut
[j
];
372 /* replace RGB with L */
373 if (table
->FloatTable
) {
374 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
375 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
377 for (i
= 0; i
< n
; i
++) {
378 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
380 CLAMPED_FLOAT_TO_CHAN(c
, lut
[j
]);
381 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = c
;
385 #if CHAN_TYPE == GL_UNSIGNED_BYTE
386 if (table
->Size
== 256) {
388 const GLchan
*lut
= (const GLchan
*) table
->Table
;
390 for (i
= 0; i
< n
; i
++) {
391 const GLchan c
= lut
[rgba
[i
][RCOMP
]];
392 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = c
;
398 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
399 const GLchan
*lut
= (const GLchan
*) table
->Table
;
401 for (i
= 0; i
< n
; i
++) {
402 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
403 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = lut
[j
];
409 /* replace A with A */
410 if (table
->FloatTable
) {
411 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
412 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
414 for (i
= 0; i
< n
; i
++) {
415 GLint j
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
417 CLAMPED_FLOAT_TO_CHAN(c
, lut
[j
]);
422 #if CHAN_TYPE == GL_UNSIGNED_BYTE
423 if (table
->Size
== 256) {
425 const GLchan
*lut
= (const GLchan
*) table
->Table
;
427 for (i
= 0; i
< n
; i
++) {
428 rgba
[i
][ACOMP
] = lut
[rgba
[i
][ACOMP
]];
434 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
435 const GLchan
*lut
= (const GLchan
*) table
->Table
;
437 for (i
= 0; i
< n
; i
++) {
438 GLint j
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
439 rgba
[i
][ACOMP
] = lut
[j
];
444 case GL_LUMINANCE_ALPHA
:
445 /* replace RGBA with LLLA */
446 if (table
->FloatTable
) {
447 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
448 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
450 for (i
= 0; i
< n
; i
++) {
451 GLint jL
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
452 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
453 GLchan luminance
, alpha
;
454 CLAMPED_FLOAT_TO_CHAN(luminance
, lut
[jL
* 2 + 0]);
455 CLAMPED_FLOAT_TO_CHAN(alpha
, lut
[jA
* 2 + 1]);
456 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = luminance
;
457 rgba
[i
][ACOMP
] = alpha
;;
461 #if CHAN_TYPE == GL_UNSIGNED_BYTE
462 if (table
->Size
== 256) {
464 const GLchan
*lut
= (const GLchan
*) table
->Table
;
466 for (i
= 0; i
< n
; i
++) {
467 GLchan l
= lut
[rgba
[i
][RCOMP
] * 2 + 0];
468 GLchan a
= lut
[rgba
[i
][ACOMP
] * 2 + 1];;
469 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = l
;
476 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
477 const GLchan
*lut
= (const GLchan
*) table
->Table
;
479 for (i
= 0; i
< n
; i
++) {
480 GLint jL
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
481 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
482 GLchan luminance
= lut
[jL
* 2 + 0];
483 GLchan alpha
= lut
[jA
* 2 + 1];
484 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = luminance
;
485 rgba
[i
][ACOMP
] = alpha
;
491 /* replace RGB with RGB */
492 if (table
->FloatTable
) {
493 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
494 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
496 for (i
= 0; i
< n
; i
++) {
497 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
498 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
499 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
500 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][RCOMP
], lut
[jR
* 3 + 0]);
501 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][GCOMP
], lut
[jG
* 3 + 1]);
502 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][BCOMP
], lut
[jB
* 3 + 2]);
506 #if CHAN_TYPE == GL_UNSIGNED_BYTE
507 if (table
->Size
== 256) {
509 const GLchan
*lut
= (const GLchan
*) table
->Table
;
511 for (i
= 0; i
< n
; i
++) {
512 rgba
[i
][RCOMP
] = lut
[rgba
[i
][RCOMP
] * 3 + 0];
513 rgba
[i
][GCOMP
] = lut
[rgba
[i
][GCOMP
] * 3 + 1];
514 rgba
[i
][BCOMP
] = lut
[rgba
[i
][BCOMP
] * 3 + 2];
520 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
521 const GLchan
*lut
= (const GLchan
*) table
->Table
;
523 for (i
= 0; i
< n
; i
++) {
524 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
525 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
526 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
527 rgba
[i
][RCOMP
] = lut
[jR
* 3 + 0];
528 rgba
[i
][GCOMP
] = lut
[jG
* 3 + 1];
529 rgba
[i
][BCOMP
] = lut
[jB
* 3 + 2];
535 /* replace RGBA with RGBA */
536 if (table
->FloatTable
) {
537 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
538 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
540 for (i
= 0; i
< n
; i
++) {
541 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
542 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
543 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
544 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
545 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][RCOMP
], lut
[jR
* 4 + 0]);
546 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][GCOMP
], lut
[jG
* 4 + 1]);
547 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][BCOMP
], lut
[jB
* 4 + 2]);
548 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][ACOMP
], lut
[jA
* 4 + 3]);
552 #if CHAN_TYPE == GL_UNSIGNED_BYTE
553 if (table
->Size
== 256) {
555 const GLchan
*lut
= (const GLchan
*) table
->Table
;
557 for (i
= 0; i
< n
; i
++) {
558 rgba
[i
][RCOMP
] = lut
[rgba
[i
][RCOMP
] * 4 + 0];
559 rgba
[i
][GCOMP
] = lut
[rgba
[i
][GCOMP
] * 4 + 1];
560 rgba
[i
][BCOMP
] = lut
[rgba
[i
][BCOMP
] * 4 + 2];
561 rgba
[i
][ACOMP
] = lut
[rgba
[i
][ACOMP
] * 4 + 3];
567 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
568 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
570 for (i
= 0; i
< n
; i
++) {
571 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
572 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
573 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
574 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
575 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][RCOMP
], lut
[jR
* 4 + 0]);
576 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][GCOMP
], lut
[jG
* 4 + 1]);
577 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][BCOMP
], lut
[jB
* 4 + 2]);
578 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][ACOMP
], lut
[jA
* 4 + 3]);
584 _mesa_problem(NULL
, "Bad format in _swrast_texture_table_lookup");
592 * Get texture palette entry.
595 palette_sample(const GLcontext
*ctx
,
596 const struct gl_texture_object
*tObj
,
597 GLint index
, GLchan rgba
[4] )
599 const GLchan
*palette
;
602 if (ctx
->Texture
.SharedPalette
) {
603 ASSERT(!ctx
->Texture
.Palette
.FloatTable
);
604 palette
= (const GLchan
*) ctx
->Texture
.Palette
.Table
;
605 format
= ctx
->Texture
.Palette
.Format
;
608 ASSERT(!tObj
->Palette
.FloatTable
);
609 palette
= (const GLchan
*) tObj
->Palette
.Table
;
610 format
= tObj
->Palette
.Format
;
615 rgba
[ACOMP
] = palette
[index
];
619 rgba
[RCOMP
] = palette
[index
];
621 case GL_LUMINANCE_ALPHA
:
622 rgba
[RCOMP
] = palette
[(index
<< 1) + 0];
623 rgba
[ACOMP
] = palette
[(index
<< 1) + 1];
626 rgba
[RCOMP
] = palette
[index
* 3 + 0];
627 rgba
[GCOMP
] = palette
[index
* 3 + 1];
628 rgba
[BCOMP
] = palette
[index
* 3 + 2];
631 rgba
[RCOMP
] = palette
[(index
<< 2) + 0];
632 rgba
[GCOMP
] = palette
[(index
<< 2) + 1];
633 rgba
[BCOMP
] = palette
[(index
<< 2) + 2];
634 rgba
[ACOMP
] = palette
[(index
<< 2) + 3];
637 _mesa_problem(ctx
, "Bad palette format in palette_sample");
643 * The lambda[] array values are always monotonic. Either the whole span
644 * will be minified, magnified, or split between the two. This function
645 * determines the subranges in [0, n-1] that are to be minified or magnified.
648 compute_min_mag_ranges( GLfloat minMagThresh
, GLuint n
, const GLfloat lambda
[],
649 GLuint
*minStart
, GLuint
*minEnd
,
650 GLuint
*magStart
, GLuint
*magEnd
)
652 ASSERT(lambda
!= NULL
);
654 /* Verify that lambda[] is monotonous.
655 * We can't really use this because the inaccuracy in the LOG2 function
656 * causes this test to fail, yet the resulting texturing is correct.
660 printf("lambda delta = %g\n", lambda
[0] - lambda
[n
-1]);
661 if (lambda
[0] >= lambda
[n
-1]) { /* decreasing */
662 for (i
= 0; i
< n
- 1; i
++) {
663 ASSERT((GLint
) (lambda
[i
] * 10) >= (GLint
) (lambda
[i
+1] * 10));
666 else { /* increasing */
667 for (i
= 0; i
< n
- 1; i
++) {
668 ASSERT((GLint
) (lambda
[i
] * 10) <= (GLint
) (lambda
[i
+1] * 10));
674 /* since lambda is monotonous-array use this check first */
675 if (lambda
[0] <= minMagThresh
&& lambda
[n
-1] <= minMagThresh
) {
676 /* magnification for whole span */
679 *minStart
= *minEnd
= 0;
681 else if (lambda
[0] > minMagThresh
&& lambda
[n
-1] > minMagThresh
) {
682 /* minification for whole span */
685 *magStart
= *magEnd
= 0;
688 /* a mix of minification and magnification */
690 if (lambda
[0] > minMagThresh
) {
691 /* start with minification */
692 for (i
= 1; i
< n
; i
++) {
693 if (lambda
[i
] <= minMagThresh
)
702 /* start with magnification */
703 for (i
= 1; i
< n
; i
++) {
704 if (lambda
[i
] > minMagThresh
)
715 /* Verify the min/mag Start/End values
716 * We don't use this either (see above)
720 for (i
= 0; i
< n
; i
++) {
721 if (lambda
[i
] > minMagThresh
) {
723 ASSERT(i
>= *minStart
);
728 ASSERT(i
>= *magStart
);
737 /**********************************************************************/
738 /* 1-D Texture Sampling Functions */
739 /**********************************************************************/
742 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
745 sample_1d_nearest(GLcontext
*ctx
,
746 const struct gl_texture_object
*tObj
,
747 const struct gl_texture_image
*img
,
748 const GLfloat texcoord
[4], GLchan rgba
[4])
750 const GLint width
= img
->Width2
; /* without border, power of two */
753 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
755 /* skip over the border, if any */
758 if (i
< 0 || i
>= (GLint
) img
->Width
) {
759 /* Need this test for GL_CLAMP_TO_BORDER mode */
760 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
763 (*img
->FetchTexel
)(img
, i
, 0, 0, (GLvoid
*) rgba
);
764 if (img
->Format
== GL_COLOR_INDEX
) {
765 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
773 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
776 sample_1d_linear(GLcontext
*ctx
,
777 const struct gl_texture_object
*tObj
,
778 const struct gl_texture_image
*img
,
779 const GLfloat texcoord
[4], GLchan rgba
[4])
781 const GLint width
= img
->Width2
;
784 GLuint useBorderColor
;
786 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
794 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
795 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
799 const GLfloat a
= FRAC(u
);
801 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
802 const GLfloat w0
= (1.0F
-a
);
803 const GLfloat w1
= a
;
804 #else /* CHAN_BITS == 8 */
805 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
806 const GLint w0
= IROUND_POS((1.0F
- a
) * WEIGHT_SCALE
);
807 const GLint w1
= IROUND_POS( a
* WEIGHT_SCALE
);
809 GLchan t0
[4], t1
[4]; /* texels */
811 if (useBorderColor
& I0BIT
) {
812 COPY_CHAN4(t0
, tObj
->_BorderChan
);
815 (*img
->FetchTexel
)(img
, i0
, 0, 0, (GLvoid
*) t0
);
816 if (img
->Format
== GL_COLOR_INDEX
) {
817 palette_sample(ctx
, tObj
, t0
[0], t0
);
820 if (useBorderColor
& I1BIT
) {
821 COPY_CHAN4(t1
, tObj
->_BorderChan
);
824 (*img
->FetchTexel
)(img
, i1
, 0, 0, (GLvoid
*) t1
);
825 if (img
->Format
== GL_COLOR_INDEX
) {
826 palette_sample(ctx
, tObj
, t1
[0], t1
);
830 #if CHAN_TYPE == GL_FLOAT
831 rgba
[0] = w0
* t0
[0] + w1
* t1
[0];
832 rgba
[1] = w0
* t0
[1] + w1
* t1
[1];
833 rgba
[2] = w0
* t0
[2] + w1
* t1
[2];
834 rgba
[3] = w0
* t0
[3] + w1
* t1
[3];
835 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
836 rgba
[0] = (GLchan
) (w0
* t0
[0] + w1
* t1
[0] + 0.5);
837 rgba
[1] = (GLchan
) (w0
* t0
[1] + w1
* t1
[1] + 0.5);
838 rgba
[2] = (GLchan
) (w0
* t0
[2] + w1
* t1
[2] + 0.5);
839 rgba
[3] = (GLchan
) (w0
* t0
[3] + w1
* t1
[3] + 0.5);
840 #else /* CHAN_BITS == 8 */
841 rgba
[0] = (GLchan
) ((w0
* t0
[0] + w1
* t1
[0]) >> WEIGHT_SHIFT
);
842 rgba
[1] = (GLchan
) ((w0
* t0
[1] + w1
* t1
[1]) >> WEIGHT_SHIFT
);
843 rgba
[2] = (GLchan
) ((w0
* t0
[2] + w1
* t1
[2]) >> WEIGHT_SHIFT
);
844 rgba
[3] = (GLchan
) ((w0
* t0
[3] + w1
* t1
[3]) >> WEIGHT_SHIFT
);
852 sample_1d_nearest_mipmap_nearest(GLcontext
*ctx
,
853 const struct gl_texture_object
*tObj
,
854 GLuint n
, const GLfloat texcoord
[][4],
855 const GLfloat lambda
[], GLchan rgba
[][4])
858 ASSERT(lambda
!= NULL
);
859 for (i
= 0; i
< n
; i
++) {
861 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
862 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
868 sample_1d_linear_mipmap_nearest(GLcontext
*ctx
,
869 const struct gl_texture_object
*tObj
,
870 GLuint n
, const GLfloat texcoord
[][4],
871 const GLfloat lambda
[], GLchan rgba
[][4])
874 ASSERT(lambda
!= NULL
);
875 for (i
= 0; i
< n
; i
++) {
877 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
878 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
885 * This is really just needed in order to prevent warnings with some compilers.
887 #if CHAN_TYPE == GL_FLOAT
890 #define CHAN_CAST (GLchan) (GLint)
895 sample_1d_nearest_mipmap_linear(GLcontext
*ctx
,
896 const struct gl_texture_object
*tObj
,
897 GLuint n
, const GLfloat texcoord
[][4],
898 const GLfloat lambda
[], GLchan rgba
[][4])
901 ASSERT(lambda
!= NULL
);
902 for (i
= 0; i
< n
; i
++) {
904 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
905 if (level
>= tObj
->_MaxLevel
) {
906 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
907 texcoord
[i
], rgba
[i
]);
911 const GLfloat f
= FRAC(lambda
[i
]);
912 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
913 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
914 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
915 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
916 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
917 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
925 sample_1d_linear_mipmap_linear(GLcontext
*ctx
,
926 const struct gl_texture_object
*tObj
,
927 GLuint n
, const GLfloat texcoord
[][4],
928 const GLfloat lambda
[], GLchan rgba
[][4])
931 ASSERT(lambda
!= NULL
);
932 for (i
= 0; i
< n
; i
++) {
934 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
935 if (level
>= tObj
->_MaxLevel
) {
936 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
937 texcoord
[i
], rgba
[i
]);
941 const GLfloat f
= FRAC(lambda
[i
]);
942 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
943 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
944 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
945 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
946 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
947 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
955 sample_nearest_1d( GLcontext
*ctx
, GLuint texUnit
,
956 const struct gl_texture_object
*tObj
, GLuint n
,
957 const GLfloat texcoords
[][4], const GLfloat lambda
[],
961 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
964 sample_1d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
971 sample_linear_1d( GLcontext
*ctx
, GLuint texUnit
,
972 const struct gl_texture_object
*tObj
, GLuint n
,
973 const GLfloat texcoords
[][4], const GLfloat lambda
[],
977 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
980 sample_1d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
986 * Given an (s) texture coordinate and lambda (level of detail) value,
987 * return a texture sample.
991 sample_lambda_1d( GLcontext
*ctx
, GLuint texUnit
,
992 const struct gl_texture_object
*tObj
, GLuint n
,
993 const GLfloat texcoords
[][4],
994 const GLfloat lambda
[], GLchan rgba
[][4] )
996 GLuint minStart
, minEnd
; /* texels with minification */
997 GLuint magStart
, magEnd
; /* texels with magnification */
1000 ASSERT(lambda
!= NULL
);
1001 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1002 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1004 if (minStart
< minEnd
) {
1005 /* do the minified texels */
1006 const GLuint m
= minEnd
- minStart
;
1007 switch (tObj
->MinFilter
) {
1009 for (i
= minStart
; i
< minEnd
; i
++)
1010 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1011 texcoords
[i
], rgba
[i
]);
1014 for (i
= minStart
; i
< minEnd
; i
++)
1015 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1016 texcoords
[i
], rgba
[i
]);
1018 case GL_NEAREST_MIPMAP_NEAREST
:
1019 sample_1d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1020 lambda
+ minStart
, rgba
+ minStart
);
1022 case GL_LINEAR_MIPMAP_NEAREST
:
1023 sample_1d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1024 lambda
+ minStart
, rgba
+ minStart
);
1026 case GL_NEAREST_MIPMAP_LINEAR
:
1027 sample_1d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1028 lambda
+ minStart
, rgba
+ minStart
);
1030 case GL_LINEAR_MIPMAP_LINEAR
:
1031 sample_1d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1032 lambda
+ minStart
, rgba
+ minStart
);
1035 _mesa_problem(ctx
, "Bad min filter in sample_1d_texture");
1040 if (magStart
< magEnd
) {
1041 /* do the magnified texels */
1042 switch (tObj
->MagFilter
) {
1044 for (i
= magStart
; i
< magEnd
; i
++)
1045 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1046 texcoords
[i
], rgba
[i
]);
1049 for (i
= magStart
; i
< magEnd
; i
++)
1050 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1051 texcoords
[i
], rgba
[i
]);
1054 _mesa_problem(ctx
, "Bad mag filter in sample_1d_texture");
1061 /**********************************************************************/
1062 /* 2-D Texture Sampling Functions */
1063 /**********************************************************************/
1067 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
1070 sample_2d_nearest(GLcontext
*ctx
,
1071 const struct gl_texture_object
*tObj
,
1072 const struct gl_texture_image
*img
,
1073 const GLfloat texcoord
[4],
1076 const GLint width
= img
->Width2
; /* without border, power of two */
1077 const GLint height
= img
->Height2
; /* without border, power of two */
1080 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
1081 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
1083 /* skip over the border, if any */
1087 if (i
< 0 || i
>= (GLint
) img
->Width
|| j
< 0 || j
>= (GLint
) img
->Height
) {
1088 /* Need this test for GL_CLAMP_TO_BORDER mode */
1089 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
1092 (*img
->FetchTexel
)(img
, i
, j
, 0, (GLvoid
*) rgba
);
1093 if (img
->Format
== GL_COLOR_INDEX
) {
1094 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
1102 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
1103 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
1106 sample_2d_linear(GLcontext
*ctx
,
1107 const struct gl_texture_object
*tObj
,
1108 const struct gl_texture_image
*img
,
1109 const GLfloat texcoord
[4],
1112 const GLint width
= img
->Width2
;
1113 const GLint height
= img
->Height2
;
1114 GLint i0
, j0
, i1
, j1
;
1115 GLuint useBorderColor
;
1118 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1119 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1129 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1130 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1131 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1132 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1136 const GLfloat a
= FRAC(u
);
1137 const GLfloat b
= FRAC(v
);
1139 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1140 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
1141 const GLfloat w10
= a
* (1.0F
-b
);
1142 const GLfloat w01
= (1.0F
-a
) * b
;
1143 const GLfloat w11
= a
* b
;
1144 #else /* CHAN_BITS == 8 */
1145 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1146 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
1147 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
1148 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
1149 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
1156 if (useBorderColor
& (I0BIT
| J0BIT
)) {
1157 COPY_CHAN4(t00
, tObj
->_BorderChan
);
1160 (*img
->FetchTexel
)(img
, i0
, j0
, 0, (GLvoid
*) t00
);
1161 if (img
->Format
== GL_COLOR_INDEX
) {
1162 palette_sample(ctx
, tObj
, t00
[0], t00
);
1165 if (useBorderColor
& (I1BIT
| J0BIT
)) {
1166 COPY_CHAN4(t10
, tObj
->_BorderChan
);
1169 (*img
->FetchTexel
)(img
, i1
, j0
, 0, (GLvoid
*) t10
);
1170 if (img
->Format
== GL_COLOR_INDEX
) {
1171 palette_sample(ctx
, tObj
, t10
[0], t10
);
1174 if (useBorderColor
& (I0BIT
| J1BIT
)) {
1175 COPY_CHAN4(t01
, tObj
->_BorderChan
);
1178 (*img
->FetchTexel
)(img
, i0
, j1
, 0, (GLvoid
*) t01
);
1179 if (img
->Format
== GL_COLOR_INDEX
) {
1180 palette_sample(ctx
, tObj
, t01
[0], t01
);
1183 if (useBorderColor
& (I1BIT
| J1BIT
)) {
1184 COPY_CHAN4(t11
, tObj
->_BorderChan
);
1187 (*img
->FetchTexel
)(img
, i1
, j1
, 0, (GLvoid
*) t11
);
1188 if (img
->Format
== GL_COLOR_INDEX
) {
1189 palette_sample(ctx
, tObj
, t11
[0], t11
);
1192 #if CHAN_TYPE == GL_FLOAT
1193 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
1194 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
1195 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
1196 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
1197 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1198 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
1199 w01
* t01
[0] + w11
* t11
[0] + 0.5);
1200 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
1201 w01
* t01
[1] + w11
* t11
[1] + 0.5);
1202 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
1203 w01
* t01
[2] + w11
* t11
[2] + 0.5);
1204 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
1205 w01
* t01
[3] + w11
* t11
[3] + 0.5);
1206 #else /* CHAN_BITS == 8 */
1207 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
1208 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
1209 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
1210 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
1211 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
1212 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
1213 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
1214 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
1223 * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT
1224 * and we're not using a paletted texture.
1227 sample_2d_linear_repeat(GLcontext
*ctx
,
1228 const struct gl_texture_object
*tObj
,
1229 const struct gl_texture_image
*img
,
1230 const GLfloat texcoord
[4],
1233 const GLint width
= img
->Width2
;
1234 const GLint height
= img
->Height2
;
1235 GLint i0
, j0
, i1
, j1
;
1238 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1239 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1240 ASSERT(img
->Border
== 0);
1241 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
1242 ASSERT(img
->_IsPowerOfTwo
);
1244 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[0], u
, width
, i0
, i1
);
1245 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[1], v
, height
, j0
, j1
);
1248 const GLfloat a
= FRAC(u
);
1249 const GLfloat b
= FRAC(v
);
1251 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1252 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
1253 const GLfloat w10
= a
* (1.0F
-b
);
1254 const GLfloat w01
= (1.0F
-a
) * b
;
1255 const GLfloat w11
= a
* b
;
1256 #else /* CHAN_BITS == 8 */
1257 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1258 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
1259 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
1260 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
1261 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
1268 (*img
->FetchTexel
)(img
, i0
, j0
, 0, (GLvoid
*) t00
);
1269 (*img
->FetchTexel
)(img
, i1
, j0
, 0, (GLvoid
*) t10
);
1270 (*img
->FetchTexel
)(img
, i0
, j1
, 0, (GLvoid
*) t01
);
1271 (*img
->FetchTexel
)(img
, i1
, j1
, 0, (GLvoid
*) t11
);
1273 #if CHAN_TYPE == GL_FLOAT
1274 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
1275 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
1276 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
1277 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
1278 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1279 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
1280 w01
* t01
[0] + w11
* t11
[0] + 0.5);
1281 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
1282 w01
* t01
[1] + w11
* t11
[1] + 0.5);
1283 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
1284 w01
* t01
[2] + w11
* t11
[2] + 0.5);
1285 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
1286 w01
* t01
[3] + w11
* t11
[3] + 0.5);
1287 #else /* CHAN_BITS == 8 */
1288 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
1289 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
1290 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
1291 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
1292 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
1293 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
1294 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
1295 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
1305 sample_2d_nearest_mipmap_nearest(GLcontext
*ctx
,
1306 const struct gl_texture_object
*tObj
,
1307 GLuint n
, const GLfloat texcoord
[][4],
1308 const GLfloat lambda
[], GLchan rgba
[][4])
1311 for (i
= 0; i
< n
; i
++) {
1313 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1314 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1321 sample_2d_linear_mipmap_nearest(GLcontext
*ctx
,
1322 const struct gl_texture_object
*tObj
,
1323 GLuint n
, const GLfloat texcoord
[][4],
1324 const GLfloat lambda
[], GLchan rgba
[][4])
1327 ASSERT(lambda
!= NULL
);
1328 for (i
= 0; i
< n
; i
++) {
1330 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1331 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1338 sample_2d_nearest_mipmap_linear(GLcontext
*ctx
,
1339 const struct gl_texture_object
*tObj
,
1340 GLuint n
, const GLfloat texcoord
[][4],
1341 const GLfloat lambda
[], GLchan rgba
[][4])
1344 ASSERT(lambda
!= NULL
);
1345 for (i
= 0; i
< n
; i
++) {
1347 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1348 if (level
>= tObj
->_MaxLevel
) {
1349 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1350 texcoord
[i
], rgba
[i
]);
1353 GLchan t0
[4], t1
[4]; /* texels */
1354 const GLfloat f
= FRAC(lambda
[i
]);
1355 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1356 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1357 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1358 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1359 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1360 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1367 /* Trilinear filtering */
1369 sample_2d_linear_mipmap_linear( GLcontext
*ctx
,
1370 const struct gl_texture_object
*tObj
,
1371 GLuint n
, const GLfloat texcoord
[][4],
1372 const GLfloat lambda
[], GLchan rgba
[][4] )
1375 ASSERT(lambda
!= NULL
);
1376 for (i
= 0; i
< n
; i
++) {
1378 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1379 if (level
>= tObj
->_MaxLevel
) {
1380 sample_2d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1381 texcoord
[i
], rgba
[i
]);
1384 GLchan t0
[4], t1
[4]; /* texels */
1385 const GLfloat f
= FRAC(lambda
[i
]);
1386 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1387 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1388 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1389 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1390 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1391 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1398 sample_2d_linear_mipmap_linear_repeat( GLcontext
*ctx
,
1399 const struct gl_texture_object
*tObj
,
1400 GLuint n
, const GLfloat texcoord
[][4],
1401 const GLfloat lambda
[], GLchan rgba
[][4] )
1404 ASSERT(lambda
!= NULL
);
1405 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1406 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1407 ASSERT(tObj
->_IsPowerOfTwo
);
1408 for (i
= 0; i
< n
; i
++) {
1410 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1411 if (level
>= tObj
->_MaxLevel
) {
1412 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1413 texcoord
[i
], rgba
[i
]);
1416 GLchan t0
[4], t1
[4]; /* texels */
1417 const GLfloat f
= FRAC(lambda
[i
]);
1418 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1419 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1420 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1421 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1422 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1423 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1430 sample_nearest_2d( GLcontext
*ctx
, GLuint texUnit
,
1431 const struct gl_texture_object
*tObj
, GLuint n
,
1432 const GLfloat texcoords
[][4],
1433 const GLfloat lambda
[], GLchan rgba
[][4] )
1436 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1439 sample_2d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1446 sample_linear_2d( GLcontext
*ctx
, GLuint texUnit
,
1447 const struct gl_texture_object
*tObj
, GLuint n
,
1448 const GLfloat texcoords
[][4],
1449 const GLfloat lambda
[], GLchan rgba
[][4] )
1452 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1455 sample_2d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1461 * Optimized 2-D texture sampling:
1462 * S and T wrap mode == GL_REPEAT
1463 * GL_NEAREST min/mag filter
1465 * RowStride == Width,
1469 opt_sample_rgb_2d( GLcontext
*ctx
, GLuint texUnit
,
1470 const struct gl_texture_object
*tObj
,
1471 GLuint n
, const GLfloat texcoords
[][4],
1472 const GLfloat lambda
[], GLchan rgba
[][4] )
1474 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
1475 const GLfloat width
= (GLfloat
) img
->Width
;
1476 const GLfloat height
= (GLfloat
) img
->Height
;
1477 const GLint colMask
= img
->Width
- 1;
1478 const GLint rowMask
= img
->Height
- 1;
1479 const GLint shift
= img
->WidthLog2
;
1482 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1483 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1484 ASSERT(img
->Border
==0);
1485 ASSERT(img
->Format
==GL_RGB
);
1486 ASSERT(img
->_IsPowerOfTwo
);
1488 for (k
=0; k
<n
; k
++) {
1489 GLint i
= IFLOOR(texcoords
[k
][0] * width
) & colMask
;
1490 GLint j
= IFLOOR(texcoords
[k
][1] * height
) & rowMask
;
1491 GLint pos
= (j
<< shift
) | i
;
1492 GLchan
*texel
= ((GLchan
*) img
->Data
) + 3*pos
;
1493 rgba
[k
][RCOMP
] = texel
[0];
1494 rgba
[k
][GCOMP
] = texel
[1];
1495 rgba
[k
][BCOMP
] = texel
[2];
1501 * Optimized 2-D texture sampling:
1502 * S and T wrap mode == GL_REPEAT
1503 * GL_NEAREST min/mag filter
1505 * RowStride == Width,
1509 opt_sample_rgba_2d( GLcontext
*ctx
, GLuint texUnit
,
1510 const struct gl_texture_object
*tObj
,
1511 GLuint n
, const GLfloat texcoords
[][4],
1512 const GLfloat lambda
[], GLchan rgba
[][4] )
1514 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
1515 const GLfloat width
= (GLfloat
) img
->Width
;
1516 const GLfloat height
= (GLfloat
) img
->Height
;
1517 const GLint colMask
= img
->Width
- 1;
1518 const GLint rowMask
= img
->Height
- 1;
1519 const GLint shift
= img
->WidthLog2
;
1522 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1523 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1524 ASSERT(img
->Border
==0);
1525 ASSERT(img
->Format
==GL_RGBA
);
1526 ASSERT(img
->_IsPowerOfTwo
);
1528 for (i
= 0; i
< n
; i
++) {
1529 const GLint col
= IFLOOR(texcoords
[i
][0] * width
) & colMask
;
1530 const GLint row
= IFLOOR(texcoords
[i
][1] * height
) & rowMask
;
1531 const GLint pos
= (row
<< shift
) | col
;
1532 const GLchan
*texel
= ((GLchan
*) img
->Data
) + (pos
<< 2); /* pos*4 */
1533 COPY_CHAN4(rgba
[i
], texel
);
1539 * Given an array of texture coordinate and lambda (level of detail)
1540 * values, return an array of texture sample.
1543 sample_lambda_2d( GLcontext
*ctx
, GLuint texUnit
,
1544 const struct gl_texture_object
*tObj
,
1545 GLuint n
, const GLfloat texcoords
[][4],
1546 const GLfloat lambda
[], GLchan rgba
[][4] )
1548 const struct gl_texture_image
*tImg
= tObj
->Image
[tObj
->BaseLevel
];
1549 GLuint minStart
, minEnd
; /* texels with minification */
1550 GLuint magStart
, magEnd
; /* texels with magnification */
1552 const GLboolean repeatNoBorderPOT
= (tObj
->WrapS
== GL_REPEAT
)
1553 && (tObj
->WrapT
== GL_REPEAT
)
1554 && (tImg
->Border
== 0 && (tImg
->Width
== tImg
->RowStride
))
1555 && (tImg
->Format
!= GL_COLOR_INDEX
)
1556 && tImg
->_IsPowerOfTwo
;
1558 ASSERT(lambda
!= NULL
);
1559 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1560 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1562 if (minStart
< minEnd
) {
1563 /* do the minified texels */
1564 const GLuint m
= minEnd
- minStart
;
1565 switch (tObj
->MinFilter
) {
1567 if (repeatNoBorderPOT
) {
1568 switch (tImg
->Format
) {
1570 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1571 NULL
, rgba
+ minStart
);
1574 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1575 NULL
, rgba
+ minStart
);
1578 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1579 NULL
, rgba
+ minStart
);
1583 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1584 NULL
, rgba
+ minStart
);
1588 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1589 NULL
, rgba
+ minStart
);
1591 case GL_NEAREST_MIPMAP_NEAREST
:
1592 sample_2d_nearest_mipmap_nearest(ctx
, tObj
, m
,
1593 texcoords
+ minStart
,
1594 lambda
+ minStart
, rgba
+ minStart
);
1596 case GL_LINEAR_MIPMAP_NEAREST
:
1597 sample_2d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1598 lambda
+ minStart
, rgba
+ minStart
);
1600 case GL_NEAREST_MIPMAP_LINEAR
:
1601 sample_2d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1602 lambda
+ minStart
, rgba
+ minStart
);
1604 case GL_LINEAR_MIPMAP_LINEAR
:
1605 if (repeatNoBorderPOT
)
1606 sample_2d_linear_mipmap_linear_repeat(ctx
, tObj
, m
,
1607 texcoords
+ minStart
, lambda
+ minStart
, rgba
+ minStart
);
1609 sample_2d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1610 lambda
+ minStart
, rgba
+ minStart
);
1613 _mesa_problem(ctx
, "Bad min filter in sample_2d_texture");
1618 if (magStart
< magEnd
) {
1619 /* do the magnified texels */
1620 const GLuint m
= magEnd
- magStart
;
1622 switch (tObj
->MagFilter
) {
1624 if (repeatNoBorderPOT
) {
1625 switch (tImg
->Format
) {
1627 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1628 NULL
, rgba
+ magStart
);
1631 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1632 NULL
, rgba
+ magStart
);
1635 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1636 NULL
, rgba
+ magStart
);
1640 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1641 NULL
, rgba
+ magStart
);
1645 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1646 NULL
, rgba
+ magStart
);
1649 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_2d");
1656 /**********************************************************************/
1657 /* 3-D Texture Sampling Functions */
1658 /**********************************************************************/
1661 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1664 sample_3d_nearest(GLcontext
*ctx
,
1665 const struct gl_texture_object
*tObj
,
1666 const struct gl_texture_image
*img
,
1667 const GLfloat texcoord
[4],
1670 const GLint width
= img
->Width2
; /* without border, power of two */
1671 const GLint height
= img
->Height2
; /* without border, power of two */
1672 const GLint depth
= img
->Depth2
; /* without border, power of two */
1675 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
1676 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
1677 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapR
, texcoord
[2], depth
, k
);
1679 if (i
< 0 || i
>= (GLint
) img
->Width
||
1680 j
< 0 || j
>= (GLint
) img
->Height
||
1681 k
< 0 || k
>= (GLint
) img
->Depth
) {
1682 /* Need this test for GL_CLAMP_TO_BORDER mode */
1683 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
1686 (*img
->FetchTexel
)(img
, i
, j
, k
, (GLvoid
*) rgba
);
1687 if (img
->Format
== GL_COLOR_INDEX
) {
1688 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
1696 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1699 sample_3d_linear(GLcontext
*ctx
,
1700 const struct gl_texture_object
*tObj
,
1701 const struct gl_texture_image
*img
,
1702 const GLfloat texcoord
[4],
1705 const GLint width
= img
->Width2
;
1706 const GLint height
= img
->Height2
;
1707 const GLint depth
= img
->Depth2
;
1708 GLint i0
, j0
, k0
, i1
, j1
, k1
;
1709 GLuint useBorderColor
;
1712 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1713 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1714 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapR
, texcoord
[2], w
, depth
, k0
, k1
);
1726 /* check if sampling texture border color */
1727 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1728 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1729 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1730 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1731 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
1732 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
1736 const GLfloat a
= FRAC(u
);
1737 const GLfloat b
= FRAC(v
);
1738 const GLfloat c
= FRAC(w
);
1740 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1741 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1742 GLfloat w000
= (1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
);
1743 GLfloat w100
= a
* (1.0F
-b
) * (1.0F
-c
);
1744 GLfloat w010
= (1.0F
-a
) * b
* (1.0F
-c
);
1745 GLfloat w110
= a
* b
* (1.0F
-c
);
1746 GLfloat w001
= (1.0F
-a
) * (1.0F
-b
) * c
;
1747 GLfloat w101
= a
* (1.0F
-b
) * c
;
1748 GLfloat w011
= (1.0F
-a
) * b
* c
;
1749 GLfloat w111
= a
* b
* c
;
1750 #else /* CHAN_BITS == 8 */
1751 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1752 GLint w000
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1753 GLint w100
= IROUND_POS( a
* (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1754 GLint w010
= IROUND_POS((1.0F
-a
) * b
* (1.0F
-c
) * WEIGHT_SCALE
);
1755 GLint w110
= IROUND_POS( a
* b
* (1.0F
-c
) * WEIGHT_SCALE
);
1756 GLint w001
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * c
* WEIGHT_SCALE
);
1757 GLint w101
= IROUND_POS( a
* (1.0F
-b
) * c
* WEIGHT_SCALE
);
1758 GLint w011
= IROUND_POS((1.0F
-a
) * b
* c
* WEIGHT_SCALE
);
1759 GLint w111
= IROUND_POS( a
* b
* c
* WEIGHT_SCALE
);
1762 GLchan t000
[4], t010
[4], t001
[4], t011
[4];
1763 GLchan t100
[4], t110
[4], t101
[4], t111
[4];
1765 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
1766 COPY_CHAN4(t000
, tObj
->_BorderChan
);
1769 (*img
->FetchTexel
)(img
, i0
, j0
, k0
, (GLvoid
*) t000
);
1770 if (img
->Format
== GL_COLOR_INDEX
) {
1771 palette_sample(ctx
, tObj
, t000
[0], t000
);
1774 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
1775 COPY_CHAN4(t100
, tObj
->_BorderChan
);
1778 (*img
->FetchTexel
)(img
, i1
, j0
, k0
, (GLvoid
*) t100
);
1779 if (img
->Format
== GL_COLOR_INDEX
) {
1780 palette_sample(ctx
, tObj
, t100
[0], t100
);
1783 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
1784 COPY_CHAN4(t010
, tObj
->_BorderChan
);
1787 (*img
->FetchTexel
)(img
, i0
, j1
, k0
, (GLvoid
*) t010
);
1788 if (img
->Format
== GL_COLOR_INDEX
) {
1789 palette_sample(ctx
, tObj
, t010
[0], t010
);
1792 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
1793 COPY_CHAN4(t110
, tObj
->_BorderChan
);
1796 (*img
->FetchTexel
)(img
, i1
, j1
, k0
, (GLvoid
*) t110
);
1797 if (img
->Format
== GL_COLOR_INDEX
) {
1798 palette_sample(ctx
, tObj
, t110
[0], t110
);
1802 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
1803 COPY_CHAN4(t001
, tObj
->_BorderChan
);
1806 (*img
->FetchTexel
)(img
, i0
, j0
, k1
, (GLvoid
*) t001
);
1807 if (img
->Format
== GL_COLOR_INDEX
) {
1808 palette_sample(ctx
, tObj
, t001
[0], t001
);
1811 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
1812 COPY_CHAN4(t101
, tObj
->_BorderChan
);
1815 (*img
->FetchTexel
)(img
, i1
, j0
, k1
, (GLvoid
*) t101
);
1816 if (img
->Format
== GL_COLOR_INDEX
) {
1817 palette_sample(ctx
, tObj
, t101
[0], t101
);
1820 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
1821 COPY_CHAN4(t011
, tObj
->_BorderChan
);
1824 (*img
->FetchTexel
)(img
, i0
, j1
, k1
, (GLvoid
*) t011
);
1825 if (img
->Format
== GL_COLOR_INDEX
) {
1826 palette_sample(ctx
, tObj
, t011
[0], t011
);
1829 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
1830 COPY_CHAN4(t111
, tObj
->_BorderChan
);
1833 (*img
->FetchTexel
)(img
, i1
, j1
, k1
, (GLvoid
*) t111
);
1834 if (img
->Format
== GL_COLOR_INDEX
) {
1835 palette_sample(ctx
, tObj
, t111
[0], t111
);
1839 #if CHAN_TYPE == GL_FLOAT
1840 rgba
[0] = w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1841 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0];
1842 rgba
[1] = w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1843 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1];
1844 rgba
[2] = w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1845 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2];
1846 rgba
[3] = w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1847 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3];
1848 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1849 rgba
[0] = (GLchan
) (w000
*t000
[0] + w010
*t010
[0] +
1850 w001
*t001
[0] + w011
*t011
[0] +
1851 w100
*t100
[0] + w110
*t110
[0] +
1852 w101
*t101
[0] + w111
*t111
[0] + 0.5);
1853 rgba
[1] = (GLchan
) (w000
*t000
[1] + w010
*t010
[1] +
1854 w001
*t001
[1] + w011
*t011
[1] +
1855 w100
*t100
[1] + w110
*t110
[1] +
1856 w101
*t101
[1] + w111
*t111
[1] + 0.5);
1857 rgba
[2] = (GLchan
) (w000
*t000
[2] + w010
*t010
[2] +
1858 w001
*t001
[2] + w011
*t011
[2] +
1859 w100
*t100
[2] + w110
*t110
[2] +
1860 w101
*t101
[2] + w111
*t111
[2] + 0.5);
1861 rgba
[3] = (GLchan
) (w000
*t000
[3] + w010
*t010
[3] +
1862 w001
*t001
[3] + w011
*t011
[3] +
1863 w100
*t100
[3] + w110
*t110
[3] +
1864 w101
*t101
[3] + w111
*t111
[3] + 0.5);
1865 #else /* CHAN_BITS == 8 */
1866 rgba
[0] = (GLchan
) (
1867 (w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1868 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0] )
1870 rgba
[1] = (GLchan
) (
1871 (w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1872 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1] )
1874 rgba
[2] = (GLchan
) (
1875 (w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1876 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2] )
1878 rgba
[3] = (GLchan
) (
1879 (w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1880 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3] )
1890 sample_3d_nearest_mipmap_nearest(GLcontext
*ctx
,
1891 const struct gl_texture_object
*tObj
,
1892 GLuint n
, const GLfloat texcoord
[][4],
1893 const GLfloat lambda
[], GLchan rgba
[][4] )
1896 for (i
= 0; i
< n
; i
++) {
1898 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1899 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1905 sample_3d_linear_mipmap_nearest(GLcontext
*ctx
,
1906 const struct gl_texture_object
*tObj
,
1907 GLuint n
, const GLfloat texcoord
[][4],
1908 const GLfloat lambda
[], GLchan rgba
[][4])
1911 ASSERT(lambda
!= NULL
);
1912 for (i
= 0; i
< n
; i
++) {
1914 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1915 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1921 sample_3d_nearest_mipmap_linear(GLcontext
*ctx
,
1922 const struct gl_texture_object
*tObj
,
1923 GLuint n
, const GLfloat texcoord
[][4],
1924 const GLfloat lambda
[], GLchan rgba
[][4])
1927 ASSERT(lambda
!= NULL
);
1928 for (i
= 0; i
< n
; i
++) {
1930 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1931 if (level
>= tObj
->_MaxLevel
) {
1932 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1933 texcoord
[i
], rgba
[i
]);
1936 GLchan t0
[4], t1
[4]; /* texels */
1937 const GLfloat f
= FRAC(lambda
[i
]);
1938 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1939 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1940 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1941 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1942 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1943 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1950 sample_3d_linear_mipmap_linear(GLcontext
*ctx
,
1951 const struct gl_texture_object
*tObj
,
1952 GLuint n
, const GLfloat texcoord
[][4],
1953 const GLfloat lambda
[], GLchan rgba
[][4])
1956 ASSERT(lambda
!= NULL
);
1957 for (i
= 0; i
< n
; i
++) {
1959 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1960 if (level
>= tObj
->_MaxLevel
) {
1961 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1962 texcoord
[i
], rgba
[i
]);
1965 GLchan t0
[4], t1
[4]; /* texels */
1966 const GLfloat f
= FRAC(lambda
[i
]);
1967 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1968 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1969 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1970 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1971 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1972 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1979 sample_nearest_3d(GLcontext
*ctx
, GLuint texUnit
,
1980 const struct gl_texture_object
*tObj
, GLuint n
,
1981 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1985 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1988 sample_3d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1995 sample_linear_3d( GLcontext
*ctx
, GLuint texUnit
,
1996 const struct gl_texture_object
*tObj
, GLuint n
,
1997 const GLfloat texcoords
[][4],
1998 const GLfloat lambda
[], GLchan rgba
[][4] )
2001 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
2004 sample_3d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
2010 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
2011 * return a texture sample.
2014 sample_lambda_3d( GLcontext
*ctx
, GLuint texUnit
,
2015 const struct gl_texture_object
*tObj
, GLuint n
,
2016 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2019 GLuint minStart
, minEnd
; /* texels with minification */
2020 GLuint magStart
, magEnd
; /* texels with magnification */
2023 ASSERT(lambda
!= NULL
);
2024 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2025 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2027 if (minStart
< minEnd
) {
2028 /* do the minified texels */
2029 GLuint m
= minEnd
- minStart
;
2030 switch (tObj
->MinFilter
) {
2032 for (i
= minStart
; i
< minEnd
; i
++)
2033 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
2034 texcoords
[i
], rgba
[i
]);
2037 for (i
= minStart
; i
< minEnd
; i
++)
2038 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
2039 texcoords
[i
], rgba
[i
]);
2041 case GL_NEAREST_MIPMAP_NEAREST
:
2042 sample_3d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
2043 lambda
+ minStart
, rgba
+ minStart
);
2045 case GL_LINEAR_MIPMAP_NEAREST
:
2046 sample_3d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
2047 lambda
+ minStart
, rgba
+ minStart
);
2049 case GL_NEAREST_MIPMAP_LINEAR
:
2050 sample_3d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
2051 lambda
+ minStart
, rgba
+ minStart
);
2053 case GL_LINEAR_MIPMAP_LINEAR
:
2054 sample_3d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
2055 lambda
+ minStart
, rgba
+ minStart
);
2058 _mesa_problem(ctx
, "Bad min filter in sample_3d_texture");
2063 if (magStart
< magEnd
) {
2064 /* do the magnified texels */
2065 switch (tObj
->MagFilter
) {
2067 for (i
= magStart
; i
< magEnd
; i
++)
2068 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
2069 texcoords
[i
], rgba
[i
]);
2072 for (i
= magStart
; i
< magEnd
; i
++)
2073 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
2074 texcoords
[i
], rgba
[i
]);
2077 _mesa_problem(ctx
, "Bad mag filter in sample_3d_texture");
2084 /**********************************************************************/
2085 /* Texture Cube Map Sampling Functions */
2086 /**********************************************************************/
2089 * Choose one of six sides of a texture cube map given the texture
2090 * coord (rx,ry,rz). Return pointer to corresponding array of texture
2093 static const struct gl_texture_image
**
2094 choose_cube_face(const struct gl_texture_object
*texObj
,
2095 const GLfloat texcoord
[4], GLfloat newCoord
[4])
2099 direction target sc tc ma
2100 ---------- ------------------------------- --- --- ---
2101 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
2102 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
2103 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
2104 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
2105 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
2106 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
2108 const GLfloat rx
= texcoord
[0];
2109 const GLfloat ry
= texcoord
[1];
2110 const GLfloat rz
= texcoord
[2];
2111 const struct gl_texture_image
**imgArray
;
2112 const GLfloat arx
= FABSF(rx
), ary
= FABSF(ry
), arz
= FABSF(rz
);
2115 if (arx
> ary
&& arx
> arz
) {
2117 imgArray
= (const struct gl_texture_image
**) texObj
->Image
;
2123 imgArray
= (const struct gl_texture_image
**) texObj
->NegX
;
2129 else if (ary
> arx
&& ary
> arz
) {
2131 imgArray
= (const struct gl_texture_image
**) texObj
->PosY
;
2137 imgArray
= (const struct gl_texture_image
**) texObj
->NegY
;
2145 imgArray
= (const struct gl_texture_image
**) texObj
->PosZ
;
2151 imgArray
= (const struct gl_texture_image
**) texObj
->NegZ
;
2158 newCoord
[0] = ( sc
/ ma
+ 1.0F
) * 0.5F
;
2159 newCoord
[1] = ( tc
/ ma
+ 1.0F
) * 0.5F
;
2165 sample_nearest_cube(GLcontext
*ctx
, GLuint texUnit
,
2166 const struct gl_texture_object
*tObj
, GLuint n
,
2167 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2172 for (i
= 0; i
< n
; i
++) {
2173 const struct gl_texture_image
**images
;
2174 GLfloat newCoord
[4];
2175 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
2176 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
2183 sample_linear_cube(GLcontext
*ctx
, GLuint texUnit
,
2184 const struct gl_texture_object
*tObj
, GLuint n
,
2185 const GLfloat texcoords
[][4],
2186 const GLfloat lambda
[], GLchan rgba
[][4])
2190 for (i
= 0; i
< n
; i
++) {
2191 const struct gl_texture_image
**images
;
2192 GLfloat newCoord
[4];
2193 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
2194 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
2201 sample_cube_nearest_mipmap_nearest(GLcontext
*ctx
, GLuint texUnit
,
2202 const struct gl_texture_object
*tObj
,
2203 GLuint n
, const GLfloat texcoord
[][4],
2204 const GLfloat lambda
[], GLchan rgba
[][4])
2207 ASSERT(lambda
!= NULL
);
2208 for (i
= 0; i
< n
; i
++) {
2209 const struct gl_texture_image
**images
;
2210 GLfloat newCoord
[4];
2212 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2213 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2214 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
2220 sample_cube_linear_mipmap_nearest(GLcontext
*ctx
, GLuint texUnit
,
2221 const struct gl_texture_object
*tObj
,
2222 GLuint n
, const GLfloat texcoord
[][4],
2223 const GLfloat lambda
[], GLchan rgba
[][4])
2226 ASSERT(lambda
!= NULL
);
2227 for (i
= 0; i
< n
; i
++) {
2228 const struct gl_texture_image
**images
;
2229 GLfloat newCoord
[4];
2231 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2232 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2233 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
2239 sample_cube_nearest_mipmap_linear(GLcontext
*ctx
, GLuint texUnit
,
2240 const struct gl_texture_object
*tObj
,
2241 GLuint n
, const GLfloat texcoord
[][4],
2242 const GLfloat lambda
[], GLchan rgba
[][4])
2245 ASSERT(lambda
!= NULL
);
2246 for (i
= 0; i
< n
; i
++) {
2247 const struct gl_texture_image
**images
;
2248 GLfloat newCoord
[4];
2250 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2251 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2252 if (level
>= tObj
->_MaxLevel
) {
2253 sample_2d_nearest(ctx
, tObj
, images
[tObj
->_MaxLevel
],
2257 GLchan t0
[4], t1
[4]; /* texels */
2258 const GLfloat f
= FRAC(lambda
[i
]);
2259 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, t0
);
2260 sample_2d_nearest(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
2261 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
2262 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
2263 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
2264 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
2271 sample_cube_linear_mipmap_linear(GLcontext
*ctx
, GLuint texUnit
,
2272 const struct gl_texture_object
*tObj
,
2273 GLuint n
, const GLfloat texcoord
[][4],
2274 const GLfloat lambda
[], GLchan rgba
[][4])
2277 ASSERT(lambda
!= NULL
);
2278 for (i
= 0; i
< n
; i
++) {
2279 const struct gl_texture_image
**images
;
2280 GLfloat newCoord
[4];
2282 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2283 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2284 if (level
>= tObj
->_MaxLevel
) {
2285 sample_2d_linear(ctx
, tObj
, images
[tObj
->_MaxLevel
],
2289 GLchan t0
[4], t1
[4];
2290 const GLfloat f
= FRAC(lambda
[i
]);
2291 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, t0
);
2292 sample_2d_linear(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
2293 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
2294 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
2295 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
2296 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
2303 sample_lambda_cube( GLcontext
*ctx
, GLuint texUnit
,
2304 const struct gl_texture_object
*tObj
, GLuint n
,
2305 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2308 GLuint minStart
, minEnd
; /* texels with minification */
2309 GLuint magStart
, magEnd
; /* texels with magnification */
2311 ASSERT(lambda
!= NULL
);
2312 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2313 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2315 if (minStart
< minEnd
) {
2316 /* do the minified texels */
2317 const GLuint m
= minEnd
- minStart
;
2318 switch (tObj
->MinFilter
) {
2320 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2321 lambda
+ minStart
, rgba
+ minStart
);
2324 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2325 lambda
+ minStart
, rgba
+ minStart
);
2327 case GL_NEAREST_MIPMAP_NEAREST
:
2328 sample_cube_nearest_mipmap_nearest(ctx
, texUnit
, tObj
, m
,
2329 texcoords
+ minStart
,
2330 lambda
+ minStart
, rgba
+ minStart
);
2332 case GL_LINEAR_MIPMAP_NEAREST
:
2333 sample_cube_linear_mipmap_nearest(ctx
, texUnit
, tObj
, m
,
2334 texcoords
+ minStart
,
2335 lambda
+ minStart
, rgba
+ minStart
);
2337 case GL_NEAREST_MIPMAP_LINEAR
:
2338 sample_cube_nearest_mipmap_linear(ctx
, texUnit
, tObj
, m
,
2339 texcoords
+ minStart
,
2340 lambda
+ minStart
, rgba
+ minStart
);
2342 case GL_LINEAR_MIPMAP_LINEAR
:
2343 sample_cube_linear_mipmap_linear(ctx
, texUnit
, tObj
, m
,
2344 texcoords
+ minStart
,
2345 lambda
+ minStart
, rgba
+ minStart
);
2348 _mesa_problem(ctx
, "Bad min filter in sample_lambda_cube");
2352 if (magStart
< magEnd
) {
2353 /* do the magnified texels */
2354 const GLuint m
= magEnd
- magStart
;
2355 switch (tObj
->MagFilter
) {
2357 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2358 lambda
+ magStart
, rgba
+ magStart
);
2361 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2362 lambda
+ magStart
, rgba
+ magStart
);
2365 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_cube");
2371 /**********************************************************************/
2372 /* Texture Rectangle Sampling Functions */
2373 /**********************************************************************/
2376 sample_nearest_rect(GLcontext
*ctx
, GLuint texUnit
,
2377 const struct gl_texture_object
*tObj
, GLuint n
,
2378 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2381 const struct gl_texture_image
*img
= tObj
->Image
[0];
2382 const GLfloat width
= (GLfloat
) img
->Width
;
2383 const GLfloat height
= (GLfloat
) img
->Height
;
2384 const GLint width_minus_1
= img
->Width
- 1;
2385 const GLint height_minus_1
= img
->Height
- 1;
2391 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2392 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2393 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2394 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2395 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2396 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2397 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2399 /* XXX move Wrap mode tests outside of loops for common cases */
2400 for (i
= 0; i
< n
; i
++) {
2402 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2403 if (tObj
->WrapS
== GL_CLAMP
) {
2404 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.0F
, width
) );
2406 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2407 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
) );
2410 col
= IFLOOR( CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
) );
2412 if (tObj
->WrapT
== GL_CLAMP
) {
2413 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.0F
, height
) );
2415 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2416 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
) );
2419 row
= IFLOOR( CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
) );
2422 col
= CLAMP(col
, 0, width_minus_1
);
2423 row
= CLAMP(row
, 0, height_minus_1
);
2425 (*img
->FetchTexel
)(img
, col
, row
, 0, (GLvoid
*) rgba
[i
]);
2431 sample_linear_rect(GLcontext
*ctx
, GLuint texUnit
,
2432 const struct gl_texture_object
*tObj
, GLuint n
,
2433 const GLfloat texcoords
[][4],
2434 const GLfloat lambda
[], GLchan rgba
[][4])
2436 const struct gl_texture_image
*img
= tObj
->Image
[0];
2437 const GLfloat width
= (GLfloat
) img
->Width
;
2438 const GLfloat height
= (GLfloat
) img
->Height
;
2439 const GLint width_minus_1
= img
->Width
- 1;
2440 const GLint height_minus_1
= img
->Height
- 1;
2446 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2447 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2448 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2449 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2450 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2451 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2452 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2454 /* XXX lots of opportunity for optimization in this loop */
2455 for (i
= 0; i
< n
; i
++) {
2457 GLint row0
, col0
, row1
, col1
;
2458 GLchan t00
[4], t01
[4], t10
[4], t11
[4];
2459 GLfloat a
, b
, w00
, w01
, w10
, w11
;
2461 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2462 if (tObj
->WrapS
== GL_CLAMP
) {
2463 fcol
= CLAMP(texcoords
[i
][0], 0.0F
, width
);
2465 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2466 fcol
= CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
);
2469 fcol
= CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
);
2471 if (tObj
->WrapT
== GL_CLAMP
) {
2472 frow
= CLAMP(texcoords
[i
][1], 0.0F
, height
);
2474 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2475 frow
= CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
);
2478 frow
= CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
);
2481 /* compute integer rows/columns */
2482 col0
= IFLOOR(fcol
);
2484 col0
= CLAMP(col0
, 0, width_minus_1
);
2485 col1
= CLAMP(col1
, 0, width_minus_1
);
2486 row0
= IFLOOR(frow
);
2488 row0
= CLAMP(row0
, 0, height_minus_1
);
2489 row1
= CLAMP(row1
, 0, height_minus_1
);
2491 /* get four texel samples */
2492 (*img
->FetchTexel
)(img
, col0
, row0
, 0, (GLvoid
*) t00
);
2493 (*img
->FetchTexel
)(img
, col1
, row0
, 0, (GLvoid
*) t10
);
2494 (*img
->FetchTexel
)(img
, col0
, row1
, 0, (GLvoid
*) t01
);
2495 (*img
->FetchTexel
)(img
, col1
, row1
, 0, (GLvoid
*) t11
);
2497 /* compute sample weights */
2500 w00
= (1.0F
-a
) * (1.0F
-b
);
2502 w01
= (1.0F
-a
) * b
;
2505 /* compute weighted average of samples */
2507 (GLchan
) (w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0]);
2509 (GLchan
) (w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1]);
2511 (GLchan
) (w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2]);
2513 (GLchan
) (w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3]);
2519 sample_lambda_rect( GLcontext
*ctx
, GLuint texUnit
,
2520 const struct gl_texture_object
*tObj
, GLuint n
,
2521 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2524 GLuint minStart
, minEnd
, magStart
, magEnd
;
2526 /* We only need lambda to decide between minification and magnification.
2527 * There is no mipmapping with rectangular textures.
2529 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2530 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2532 if (minStart
< minEnd
) {
2533 if (tObj
->MinFilter
== GL_NEAREST
) {
2534 sample_nearest_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2535 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2538 sample_linear_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2539 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2542 if (magStart
< magEnd
) {
2543 if (tObj
->MagFilter
== GL_NEAREST
) {
2544 sample_nearest_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2545 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2548 sample_linear_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2549 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2557 * Sample a shadow/depth texture.
2560 sample_depth_texture( GLcontext
*ctx
, GLuint unit
,
2561 const struct gl_texture_object
*tObj
, GLuint n
,
2562 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2565 const GLint baseLevel
= tObj
->BaseLevel
;
2566 const struct gl_texture_image
*texImage
= tObj
->Image
[baseLevel
];
2567 const GLuint width
= texImage
->Width
;
2568 const GLuint height
= texImage
->Height
;
2575 ASSERT(tObj
->Image
[tObj
->BaseLevel
]->Format
== GL_DEPTH_COMPONENT
);
2576 ASSERT(tObj
->Target
== GL_TEXTURE_1D
||
2577 tObj
->Target
== GL_TEXTURE_2D
||
2578 tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
2580 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2582 /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
2584 /* XXX this could be precomputed and saved in the texture object */
2585 if (tObj
->CompareFlag
) {
2586 /* GL_SGIX_shadow */
2587 if (tObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2588 function
= GL_LEQUAL
;
2591 ASSERT(tObj
->CompareOperator
== GL_TEXTURE_GEQUAL_R_SGIX
);
2592 function
= GL_GEQUAL
;
2595 else if (tObj
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
) {
2597 function
= tObj
->CompareFunc
;
2600 function
= GL_NONE
; /* pass depth through as grayscale */
2603 if (tObj
->MagFilter
== GL_NEAREST
) {
2605 for (i
= 0; i
< n
; i
++) {
2606 GLfloat depthSample
;
2608 /* XXX fix for texture rectangle! */
2609 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoords
[i
][0], width
, col
);
2610 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoords
[i
][1], height
, row
);
2611 depthSample
= *((const GLfloat
*) texImage
->Data
+ row
* width
+ col
);
2615 result
= (texcoords
[i
][2] <= depthSample
) ? CHAN_MAX
: ambient
;
2618 result
= (texcoords
[i
][2] >= depthSample
) ? CHAN_MAX
: ambient
;
2621 result
= (texcoords
[i
][2] < depthSample
) ? CHAN_MAX
: ambient
;
2624 result
= (texcoords
[i
][2] > depthSample
) ? CHAN_MAX
: ambient
;
2627 result
= (texcoords
[i
][2] == depthSample
) ? CHAN_MAX
: ambient
;
2630 result
= (texcoords
[i
][2] != depthSample
) ? CHAN_MAX
: ambient
;
2639 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2642 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2646 switch (tObj
->DepthMode
) {
2648 texel
[i
][RCOMP
] = result
;
2649 texel
[i
][GCOMP
] = result
;
2650 texel
[i
][BCOMP
] = result
;
2651 texel
[i
][ACOMP
] = CHAN_MAX
;
2654 texel
[i
][RCOMP
] = result
;
2655 texel
[i
][GCOMP
] = result
;
2656 texel
[i
][BCOMP
] = result
;
2657 texel
[i
][ACOMP
] = result
;
2660 texel
[i
][RCOMP
] = 0;
2661 texel
[i
][GCOMP
] = 0;
2662 texel
[i
][BCOMP
] = 0;
2663 texel
[i
][ACOMP
] = result
;
2666 _mesa_problem(ctx
, "Bad depth texture mode");
2672 ASSERT(tObj
->MagFilter
== GL_LINEAR
);
2673 for (i
= 0; i
< n
; i
++) {
2674 GLfloat depth00
, depth01
, depth10
, depth11
;
2675 GLint i0
, i1
, j0
, j1
;
2677 GLuint useBorderTexel
;
2679 /* XXX fix for texture rectangle! */
2680 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoords
[i
][0], u
, width
, i0
, i1
);
2681 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoords
[i
][1], v
, height
,j0
, j1
);
2684 if (texImage
->Border
) {
2685 i0
+= texImage
->Border
;
2686 i1
+= texImage
->Border
;
2687 j0
+= texImage
->Border
;
2688 j1
+= texImage
->Border
;
2691 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
2692 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
2693 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
2694 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
2697 /* get four depth samples from the texture */
2698 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
2702 depth00
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i0
);
2704 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
2708 depth10
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i1
);
2710 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
2714 depth01
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i0
);
2716 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
2720 depth11
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i1
);
2724 /* compute a single weighted depth sample and do one comparison */
2725 const GLfloat a
= FRAC(u
+ 1.0F
);
2726 const GLfloat b
= FRAC(v
+ 1.0F
);
2727 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2728 const GLfloat w10
= ( a
) * (1.0F
- b
);
2729 const GLfloat w01
= (1.0F
- a
) * ( b
);
2730 const GLfloat w11
= ( a
) * ( b
);
2731 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2732 + w01
* depth01
+ w11
* depth11
;
2733 if ((depthSample
<= texcoords
[i
][2] && function
== GL_LEQUAL
) ||
2734 (depthSample
>= texcoords
[i
][2] && function
== GL_GEQUAL
)) {
2742 /* Do four depth/R comparisons and compute a weighted result.
2743 * If this touches on somebody's I.P., I'll remove this code
2746 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
2747 GLfloat luminance
= CHAN_MAXF
;
2751 if (depth00
<= texcoords
[i
][2]) luminance
-= d
;
2752 if (depth01
<= texcoords
[i
][2]) luminance
-= d
;
2753 if (depth10
<= texcoords
[i
][2]) luminance
-= d
;
2754 if (depth11
<= texcoords
[i
][2]) luminance
-= d
;
2755 result
= (GLchan
) luminance
;
2758 if (depth00
>= texcoords
[i
][2]) luminance
-= d
;
2759 if (depth01
>= texcoords
[i
][2]) luminance
-= d
;
2760 if (depth10
>= texcoords
[i
][2]) luminance
-= d
;
2761 if (depth11
>= texcoords
[i
][2]) luminance
-= d
;
2762 result
= (GLchan
) luminance
;
2765 if (depth00
< texcoords
[i
][2]) luminance
-= d
;
2766 if (depth01
< texcoords
[i
][2]) luminance
-= d
;
2767 if (depth10
< texcoords
[i
][2]) luminance
-= d
;
2768 if (depth11
< texcoords
[i
][2]) luminance
-= d
;
2769 result
= (GLchan
) luminance
;
2772 if (depth00
> texcoords
[i
][2]) luminance
-= d
;
2773 if (depth01
> texcoords
[i
][2]) luminance
-= d
;
2774 if (depth10
> texcoords
[i
][2]) luminance
-= d
;
2775 if (depth11
> texcoords
[i
][2]) luminance
-= d
;
2776 result
= (GLchan
) luminance
;
2779 if (depth00
== texcoords
[i
][2]) luminance
-= d
;
2780 if (depth01
== texcoords
[i
][2]) luminance
-= d
;
2781 if (depth10
== texcoords
[i
][2]) luminance
-= d
;
2782 if (depth11
== texcoords
[i
][2]) luminance
-= d
;
2783 result
= (GLchan
) luminance
;
2786 if (depth00
!= texcoords
[i
][2]) luminance
-= d
;
2787 if (depth01
!= texcoords
[i
][2]) luminance
-= d
;
2788 if (depth10
!= texcoords
[i
][2]) luminance
-= d
;
2789 if (depth11
!= texcoords
[i
][2]) luminance
-= d
;
2790 result
= (GLchan
) luminance
;
2799 /* ordinary bilinear filtering */
2801 const GLfloat a
= FRAC(u
+ 1.0F
);
2802 const GLfloat b
= FRAC(v
+ 1.0F
);
2803 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2804 const GLfloat w10
= ( a
) * (1.0F
- b
);
2805 const GLfloat w01
= (1.0F
- a
) * ( b
);
2806 const GLfloat w11
= ( a
) * ( b
);
2807 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2808 + w01
* depth01
+ w11
* depth11
;
2809 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2813 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2818 switch (tObj
->DepthMode
) {
2820 texel
[i
][RCOMP
] = result
;
2821 texel
[i
][GCOMP
] = result
;
2822 texel
[i
][BCOMP
] = result
;
2823 texel
[i
][ACOMP
] = CHAN_MAX
;
2826 texel
[i
][RCOMP
] = result
;
2827 texel
[i
][GCOMP
] = result
;
2828 texel
[i
][BCOMP
] = result
;
2829 texel
[i
][ACOMP
] = result
;
2832 texel
[i
][RCOMP
] = 0;
2833 texel
[i
][GCOMP
] = 0;
2834 texel
[i
][BCOMP
] = 0;
2835 texel
[i
][ACOMP
] = result
;
2838 _mesa_problem(ctx
, "Bad depth texture mode");
2847 * Experimental depth texture sampling function.
2850 sample_depth_texture2(const GLcontext
*ctx
,
2851 const struct gl_texture_unit
*texUnit
,
2852 GLuint n
, const GLfloat texcoords
[][4],
2855 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2856 const GLint baseLevel
= texObj
->BaseLevel
;
2857 const struct gl_texture_image
*texImage
= texObj
->Image
[baseLevel
];
2858 const GLuint width
= texImage
->Width
;
2859 const GLuint height
= texImage
->Height
;
2861 GLboolean lequal
, gequal
;
2863 if (texObj
->Target
!= GL_TEXTURE_2D
) {
2864 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2868 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2869 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2873 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2874 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2875 * isn't a depth texture.
2877 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2878 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2882 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2884 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2895 for (i
= 0; i
< n
; i
++) {
2897 GLint col
, row
, ii
, jj
, imin
, imax
, jmin
, jmax
, samples
, count
;
2900 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, texcoords
[i
][0],
2902 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, texcoords
[i
][1],
2910 if (imin
< 0) imin
= 0;
2911 if (imax
>= width
) imax
= width
- 1;
2912 if (jmin
< 0) jmin
= 0;
2913 if (jmax
>= height
) jmax
= height
- 1;
2915 samples
= (imax
- imin
+ 1) * (jmax
- jmin
+ 1);
2917 for (jj
= jmin
; jj
<= jmax
; jj
++) {
2918 for (ii
= imin
; ii
<= imax
; ii
++) {
2919 GLfloat depthSample
= *((const GLfloat
*) texImage
->Data
2921 if ((depthSample
<= r
[i
] && lequal
) ||
2922 (depthSample
>= r
[i
] && gequal
)) {
2928 w
= (GLfloat
) count
/ (GLfloat
) samples
;
2929 w
= CHAN_MAXF
- w
* (CHAN_MAXF
- (GLfloat
) ambient
);
2932 texel
[i
][RCOMP
] = lum
;
2933 texel
[i
][GCOMP
] = lum
;
2934 texel
[i
][BCOMP
] = lum
;
2935 texel
[i
][ACOMP
] = CHAN_MAX
;
2943 * We use this function when a texture object is in an "incomplete" state.
2944 * When a fragment program attempts to sample an incomplete texture we
2946 * Note: frag progs don't observe texture enable/disable flags.
2949 null_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2950 const struct gl_texture_object
*tObj
, GLuint n
,
2951 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2959 _mesa_bzero(rgba
, n
* 4 * sizeof(GLchan
));
2965 * Setup the texture sampling function for this texture object.
2968 _swrast_choose_texture_sample_func( GLcontext
*ctx
,
2969 const struct gl_texture_object
*t
)
2971 const GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
2972 const GLenum format
= t
->Image
[t
->BaseLevel
]->Format
;
2975 return &null_sample_func
;
2978 switch (t
->Target
) {
2980 if (format
== GL_DEPTH_COMPONENT
) {
2981 return &sample_depth_texture
;
2983 else if (needLambda
) {
2984 return &sample_lambda_1d
;
2986 else if (t
->MinFilter
== GL_LINEAR
) {
2987 return &sample_linear_1d
;
2990 ASSERT(t
->MinFilter
== GL_NEAREST
);
2991 return &sample_nearest_1d
;
2995 if (format
== GL_DEPTH_COMPONENT
) {
2996 return &sample_depth_texture
;
2998 else if (needLambda
) {
2999 return &sample_lambda_2d
;
3001 else if (t
->MinFilter
== GL_LINEAR
) {
3002 return &sample_linear_2d
;
3005 GLint baseLevel
= t
->BaseLevel
;
3006 ASSERT(t
->MinFilter
== GL_NEAREST
);
3007 if (t
->WrapS
== GL_REPEAT
&&
3008 t
->WrapT
== GL_REPEAT
&&
3010 t
->Image
[baseLevel
]->Border
== 0 &&
3011 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGB
) {
3012 return &opt_sample_rgb_2d
;
3014 else if (t
->WrapS
== GL_REPEAT
&&
3015 t
->WrapT
== GL_REPEAT
&&
3017 t
->Image
[baseLevel
]->Border
== 0 &&
3018 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGBA
) {
3019 return &opt_sample_rgba_2d
;
3022 return &sample_nearest_2d
;
3028 return &sample_lambda_3d
;
3030 else if (t
->MinFilter
== GL_LINEAR
) {
3031 return &sample_linear_3d
;
3034 ASSERT(t
->MinFilter
== GL_NEAREST
);
3035 return &sample_nearest_3d
;
3038 case GL_TEXTURE_CUBE_MAP
:
3040 return &sample_lambda_cube
;
3042 else if (t
->MinFilter
== GL_LINEAR
) {
3043 return &sample_linear_cube
;
3046 ASSERT(t
->MinFilter
== GL_NEAREST
);
3047 return &sample_nearest_cube
;
3050 case GL_TEXTURE_RECTANGLE_NV
:
3052 return &sample_lambda_rect
;
3054 else if (t
->MinFilter
== GL_LINEAR
) {
3055 return &sample_linear_rect
;
3058 ASSERT(t
->MinFilter
== GL_NEAREST
);
3059 return &sample_nearest_rect
;
3064 "invalid target in _swrast_choose_texture_sample_func");
3065 return &null_sample_func
;
3070 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
3071 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
3075 * Do texture application for GL_ARB/EXT_texture_env_combine.
3076 * This function also supports GL_{EXT,ARB}_texture_env_dot3 and
3077 * GL_ATI_texture_env_combine3
3079 * \param ctx rendering context
3080 * \param textureUnit the texture unit to apply
3081 * \param n number of fragments to process (span width)
3082 * \param primary_rgba incoming fragment color array
3083 * \param texelBuffer pointer to texel colors for all texture units
3085 * \param rgba incoming colors, which get modified here
3088 texture_combine( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
3089 CONST
GLchan (*primary_rgba
)[4],
3090 CONST GLchan
*texelBuffer
,
3093 const struct gl_texture_unit
*textureUnit
= &(ctx
->Texture
.Unit
[unit
]);
3094 const GLchan (*argRGB
[3])[4];
3095 const GLchan (*argA
[3])[4];
3096 const GLuint RGBshift
= textureUnit
->CombineScaleShiftRGB
;
3097 const GLuint Ashift
= textureUnit
->CombineScaleShiftA
;
3098 #if CHAN_TYPE == GL_FLOAT
3099 const GLchan RGBmult
= (GLfloat
) (1 << RGBshift
);
3100 const GLchan Amult
= (GLfloat
) (1 << Ashift
);
3101 static const GLchan one
[4] = { 1.0, 1.0, 1.0, 1.0 };
3102 static const GLchan zero
[4] = { 0.0, 0.0, 0.0, 0.0 };
3104 const GLint half
= (CHAN_MAX
+ 1) / 2;
3105 static const GLchan one
[4] = { CHAN_MAX
, CHAN_MAX
, CHAN_MAX
, CHAN_MAX
};
3106 static const GLchan zero
[4] = { 0, 0, 0, 0 };
3109 GLuint numColorArgs
;
3110 GLuint numAlphaArgs
;
3112 /* GLchan ccolor[3][4]; */
3113 DEFMNARRAY(GLchan
, ccolor
, 3, 3 * MAX_WIDTH
, 4); /* mac 32k limitation */
3114 CHECKARRAY(ccolor
, return); /* mac 32k limitation */
3116 ASSERT(ctx
->Extensions
.EXT_texture_env_combine
||
3117 ctx
->Extensions
.ARB_texture_env_combine
);
3118 ASSERT(SWRAST_CONTEXT(ctx
)->_AnyTextureCombine
);
3122 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
3123 textureUnit->CombineModeRGB,
3124 textureUnit->CombineModeA,
3125 textureUnit->CombineSourceRGB[0],
3126 textureUnit->CombineSourceA[0],
3127 textureUnit->CombineSourceRGB[1],
3128 textureUnit->CombineSourceA[1]);
3132 * Do operand setup for up to 3 operands. Loop over the terms.
3134 switch (textureUnit
->CombineModeRGB
) {
3144 case GL_DOT3_RGB_EXT
:
3145 case GL_DOT3_RGBA_EXT
:
3148 case GL_INTERPOLATE
:
3149 case GL_MODULATE_ADD_ATI
:
3150 case GL_MODULATE_SIGNED_ADD_ATI
:
3151 case GL_MODULATE_SUBTRACT_ATI
:
3160 switch (textureUnit
->CombineModeA
) {
3170 case GL_INTERPOLATE
:
3171 case GL_MODULATE_ADD_ATI
:
3172 case GL_MODULATE_SIGNED_ADD_ATI
:
3173 case GL_MODULATE_SUBTRACT_ATI
:
3182 for (j
= 0; j
< numColorArgs
; j
++) {
3183 const GLenum srcRGB
= textureUnit
->CombineSourceRGB
[j
];
3188 argRGB
[j
] = (const GLchan (*)[4])
3189 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
3191 case GL_PRIMARY_COLOR
:
3192 argRGB
[j
] = primary_rgba
;
3195 argRGB
[j
] = (const GLchan (*)[4]) rgba
;
3199 GLchan (*c
)[4] = ccolor
[j
];
3200 GLchan red
, green
, blue
, alpha
;
3201 UNCLAMPED_FLOAT_TO_CHAN(red
, textureUnit
->EnvColor
[0]);
3202 UNCLAMPED_FLOAT_TO_CHAN(green
, textureUnit
->EnvColor
[1]);
3203 UNCLAMPED_FLOAT_TO_CHAN(blue
, textureUnit
->EnvColor
[2]);
3204 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
3205 for (i
= 0; i
< n
; i
++) {
3207 c
[i
][GCOMP
] = green
;
3209 c
[i
][ACOMP
] = alpha
;
3211 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3214 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
3223 /* ARB_texture_env_crossbar source */
3225 const GLuint srcUnit
= srcRGB
- GL_TEXTURE0
;
3226 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
3227 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
3229 argRGB
[j
] = (const GLchan (*)[4])
3230 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
3234 if (textureUnit
->CombineOperandRGB
[j
] != GL_SRC_COLOR
) {
3235 const GLchan (*src
)[4] = argRGB
[j
];
3236 GLchan (*dst
)[4] = ccolor
[j
];
3238 /* point to new arg[j] storage */
3239 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3241 if (textureUnit
->CombineOperandRGB
[j
] == GL_ONE_MINUS_SRC_COLOR
) {
3242 for (i
= 0; i
< n
; i
++) {
3243 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][RCOMP
];
3244 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][GCOMP
];
3245 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][BCOMP
];
3248 else if (textureUnit
->CombineOperandRGB
[j
] == GL_SRC_ALPHA
) {
3249 for (i
= 0; i
< n
; i
++) {
3250 dst
[i
][RCOMP
] = src
[i
][ACOMP
];
3251 dst
[i
][GCOMP
] = src
[i
][ACOMP
];
3252 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
3256 ASSERT(textureUnit
->CombineOperandRGB
[j
] ==GL_ONE_MINUS_SRC_ALPHA
);
3257 for (i
= 0; i
< n
; i
++) {
3258 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3259 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3260 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3267 for (j
= 0; j
< numAlphaArgs
; j
++) {
3268 const GLenum srcA
= textureUnit
->CombineSourceA
[j
];
3272 argA
[j
] = (const GLchan (*)[4])
3273 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
3275 case GL_PRIMARY_COLOR
:
3276 argA
[j
] = primary_rgba
;
3279 argA
[j
] = (const GLchan (*)[4]) rgba
;
3283 GLchan alpha
, (*c
)[4] = ccolor
[j
];
3284 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
3285 for (i
= 0; i
< n
; i
++)
3286 c
[i
][ACOMP
] = alpha
;
3287 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3290 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
3299 /* ARB_texture_env_crossbar source */
3301 const GLuint srcUnit
= srcA
- GL_TEXTURE0
;
3302 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
3303 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
3305 argA
[j
] = (const GLchan (*)[4])
3306 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
3310 if (textureUnit
->CombineOperandA
[j
] == GL_ONE_MINUS_SRC_ALPHA
) {
3311 const GLchan (*src
)[4] = argA
[j
];
3312 GLchan (*dst
)[4] = ccolor
[j
];
3313 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3314 for (i
= 0; i
< n
; i
++) {
3315 dst
[i
][ACOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3321 * Do the texture combine.
3323 switch (textureUnit
->CombineModeRGB
) {
3326 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3328 for (i
= 0; i
< n
; i
++) {
3329 #if CHAN_TYPE == GL_FLOAT
3330 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * RGBmult
;
3331 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * RGBmult
;
3332 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * RGBmult
;
3334 GLuint r
= (GLuint
) arg0
[i
][RCOMP
] << RGBshift
;
3335 GLuint g
= (GLuint
) arg0
[i
][GCOMP
] << RGBshift
;
3336 GLuint b
= (GLuint
) arg0
[i
][BCOMP
] << RGBshift
;
3337 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3338 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3339 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3344 for (i
= 0; i
< n
; i
++) {
3345 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
];
3346 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
];
3347 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
];
3354 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3355 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3356 #if CHAN_TYPE != GL_FLOAT
3357 const GLint shift
= CHAN_BITS
- RGBshift
;
3359 for (i
= 0; i
< n
; i
++) {
3360 #if CHAN_TYPE == GL_FLOAT
3361 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * RGBmult
;
3362 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * RGBmult
;
3363 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * RGBmult
;
3365 GLuint r
= PROD(arg0
[i
][RCOMP
], arg1
[i
][RCOMP
]) >> shift
;
3366 GLuint g
= PROD(arg0
[i
][GCOMP
], arg1
[i
][GCOMP
]) >> shift
;
3367 GLuint b
= PROD(arg0
[i
][BCOMP
], arg1
[i
][BCOMP
]) >> shift
;
3368 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3369 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3370 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3377 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3378 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3379 for (i
= 0; i
< n
; i
++) {
3380 #if CHAN_TYPE == GL_FLOAT
3381 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * RGBmult
;
3382 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * RGBmult
;
3383 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * RGBmult
;
3385 GLint r
= ((GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3386 GLint g
= ((GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3387 GLint b
= ((GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3388 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3389 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3390 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3397 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3398 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3399 for (i
= 0; i
< n
; i
++) {
3400 #if CHAN_TYPE == GL_FLOAT
3401 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3402 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3403 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3405 GLint r
= (GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
] -half
;
3406 GLint g
= (GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
] -half
;
3407 GLint b
= (GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
] -half
;
3408 r
= (r
< 0) ? 0 : r
<< RGBshift
;
3409 g
= (g
< 0) ? 0 : g
<< RGBshift
;
3410 b
= (b
< 0) ? 0 : b
<< RGBshift
;
3411 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3412 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3413 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3418 case GL_INTERPOLATE
:
3420 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3421 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3422 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3423 #if CHAN_TYPE != GL_FLOAT
3424 const GLint shift
= CHAN_BITS
- RGBshift
;
3426 for (i
= 0; i
< n
; i
++) {
3427 #if CHAN_TYPE == GL_FLOAT
3428 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
3429 arg1
[i
][RCOMP
] * (CHAN_MAXF
- arg2
[i
][RCOMP
])) * RGBmult
;
3430 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
3431 arg1
[i
][GCOMP
] * (CHAN_MAXF
- arg2
[i
][GCOMP
])) * RGBmult
;
3432 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
3433 arg1
[i
][BCOMP
] * (CHAN_MAXF
- arg2
[i
][BCOMP
])) * RGBmult
;
3435 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3436 + PROD(arg1
[i
][RCOMP
], CHAN_MAX
- arg2
[i
][RCOMP
]))
3438 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3439 + PROD(arg1
[i
][GCOMP
], CHAN_MAX
- arg2
[i
][GCOMP
]))
3441 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3442 + PROD(arg1
[i
][BCOMP
], CHAN_MAX
- arg2
[i
][BCOMP
]))
3444 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3445 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3446 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3453 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3454 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3455 for (i
= 0; i
< n
; i
++) {
3456 #if CHAN_TYPE == GL_FLOAT
3457 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * RGBmult
;
3458 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * RGBmult
;
3459 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * RGBmult
;
3461 GLint r
= ((GLint
) arg0
[i
][RCOMP
] - (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3462 GLint g
= ((GLint
) arg0
[i
][GCOMP
] - (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3463 GLint b
= ((GLint
) arg0
[i
][BCOMP
] - (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3464 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3465 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3466 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3471 case GL_DOT3_RGB_EXT
:
3472 case GL_DOT3_RGBA_EXT
:
3474 /* Do not scale the result by 1 2 or 4 */
3475 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3476 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3477 for (i
= 0; i
< n
; i
++) {
3478 #if CHAN_TYPE == GL_FLOAT
3479 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3480 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3481 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3483 dot
= CLAMP(dot
, 0.0F
, CHAN_MAXF
);
3485 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3486 (GLint
)arg1
[i
][RCOMP
] - half
) +
3487 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3488 (GLint
)arg1
[i
][GCOMP
] - half
) +
3489 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3490 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3491 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3493 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3500 /* DO scale the result by 1 2 or 4 */
3501 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3502 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3503 for (i
= 0; i
< n
; i
++) {
3504 #if CHAN_TYPE == GL_FLOAT
3505 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3506 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3507 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3509 dot
= CLAMP(dot
, 0.0, CHAN_MAXF
);
3511 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3512 (GLint
)arg1
[i
][RCOMP
] - half
) +
3513 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3514 (GLint
)arg1
[i
][GCOMP
] - half
) +
3515 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3516 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3518 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3520 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3524 case GL_MODULATE_ADD_ATI
:
3526 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3527 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3528 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3529 #if CHAN_TYPE != GL_FLOAT
3530 const GLint shift
= CHAN_BITS
- RGBshift
;
3532 for (i
= 0; i
< n
; i
++) {
3533 #if CHAN_TYPE == GL_FLOAT
3534 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) + arg1
[i
][RCOMP
]) * RGBmult
;
3535 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
]) * RGBmult
;
3536 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
]) * RGBmult
;
3538 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3539 + ((GLuint
) arg1
[i
][RCOMP
] << CHAN_BITS
)) >> shift
;
3540 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3541 + ((GLuint
) arg1
[i
][GCOMP
] << CHAN_BITS
)) >> shift
;
3542 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3543 + ((GLuint
) arg1
[i
][BCOMP
] << CHAN_BITS
)) >> shift
;
3544 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3545 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3546 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3551 case GL_MODULATE_SIGNED_ADD_ATI
:
3553 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3554 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3555 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3556 #if CHAN_TYPE != GL_FLOAT
3557 const GLint shift
= CHAN_BITS
- RGBshift
;
3559 for (i
= 0; i
< n
; i
++) {
3560 #if CHAN_TYPE == GL_FLOAT
3561 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3562 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3563 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3565 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3566 + (((GLint
) arg1
[i
][RCOMP
] - half
) << CHAN_BITS
))
3568 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3569 + (((GLint
) arg1
[i
][GCOMP
] - half
) << CHAN_BITS
))
3571 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3572 + (((GLint
) arg1
[i
][BCOMP
] - half
) << CHAN_BITS
))
3574 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3575 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3576 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3581 case GL_MODULATE_SUBTRACT_ATI
:
3583 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3584 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3585 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3586 #if CHAN_TYPE != GL_FLOAT
3587 const GLint shift
= CHAN_BITS
- RGBshift
;
3589 for (i
= 0; i
< n
; i
++) {
3590 #if CHAN_TYPE == GL_FLOAT
3591 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) - arg1
[i
][RCOMP
]) * RGBmult
;
3592 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) - arg1
[i
][GCOMP
]) * RGBmult
;
3593 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) - arg1
[i
][BCOMP
]) * RGBmult
;
3595 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3596 - ((GLint
) arg1
[i
][RCOMP
] << CHAN_BITS
))
3598 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3599 - ((GLint
) arg1
[i
][GCOMP
] << CHAN_BITS
))
3601 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3602 - ((GLint
) arg1
[i
][BCOMP
] << CHAN_BITS
))
3604 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3605 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3606 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3612 _mesa_problem(ctx
, "invalid combine mode");
3615 switch (textureUnit
->CombineModeA
) {
3618 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3620 for (i
= 0; i
< n
; i
++) {
3621 #if CHAN_TYPE == GL_FLOAT
3622 GLchan a
= arg0
[i
][ACOMP
] * Amult
;
3624 GLuint a
= (GLuint
) arg0
[i
][ACOMP
] << Ashift
;
3626 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3630 for (i
= 0; i
< n
; i
++) {
3631 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
];
3638 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3639 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3640 #if CHAN_TYPE != GL_FLOAT
3641 const GLint shift
= CHAN_BITS
- Ashift
;
3643 for (i
= 0; i
< n
; i
++) {
3644 #if CHAN_TYPE == GL_FLOAT
3645 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * Amult
;
3647 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg1
[i
][ACOMP
]) >> shift
);
3648 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3655 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3656 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3657 for (i
= 0; i
< n
; i
++) {
3658 #if CHAN_TYPE == GL_FLOAT
3659 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * Amult
;
3661 GLint a
= ((GLint
) arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) << Ashift
;
3662 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3669 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3670 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3671 for (i
= 0; i
< n
; i
++) {
3672 #if CHAN_TYPE == GL_FLOAT
3673 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3675 GLint a
= (GLint
) arg0
[i
][ACOMP
] + (GLint
) arg1
[i
][ACOMP
] -half
;
3676 a
= (a
< 0) ? 0 : a
<< Ashift
;
3677 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3682 case GL_INTERPOLATE
:
3684 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3685 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3686 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3687 #if CHAN_TYPE != GL_FLOAT
3688 const GLint shift
= CHAN_BITS
- Ashift
;
3690 for (i
=0; i
<n
; i
++) {
3691 #if CHAN_TYPE == GL_FLOAT
3692 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
3693 arg1
[i
][ACOMP
] * (CHAN_MAXF
- arg2
[i
][ACOMP
]))
3696 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3697 + PROD(arg1
[i
][ACOMP
], CHAN_MAX
- arg2
[i
][ACOMP
]))
3699 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3706 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3707 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3708 for (i
= 0; i
< n
; i
++) {
3709 #if CHAN_TYPE == GL_FLOAT
3710 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * Amult
;
3712 GLint a
= ((GLint
) arg0
[i
][ACOMP
] - (GLint
) arg1
[i
][ACOMP
]) << Ashift
;
3713 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3718 case GL_MODULATE_ADD_ATI
:
3720 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3721 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3722 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3723 #if CHAN_TYPE != GL_FLOAT
3724 const GLint shift
= CHAN_BITS
- Ashift
;
3726 for (i
= 0; i
< n
; i
++) {
3727 #if CHAN_TYPE == GL_FLOAT
3728 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
]) * Amult
;
3730 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3731 + ((GLuint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3733 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3738 case GL_MODULATE_SIGNED_ADD_ATI
:
3740 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3741 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3742 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3743 #if CHAN_TYPE != GL_FLOAT
3744 const GLint shift
= CHAN_BITS
- Ashift
;
3746 for (i
= 0; i
< n
; i
++) {
3747 #if CHAN_TYPE == GL_FLOAT
3748 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3750 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3751 + (((GLint
) arg1
[i
][ACOMP
] - half
) << CHAN_BITS
))
3753 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3758 case GL_MODULATE_SUBTRACT_ATI
:
3760 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3761 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3762 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3763 #if CHAN_TYPE != GL_FLOAT
3764 const GLint shift
= CHAN_BITS
- Ashift
;
3766 for (i
= 0; i
< n
; i
++) {
3767 #if CHAN_TYPE == GL_FLOAT
3768 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) - arg1
[i
][ACOMP
]) * Amult
;
3770 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3771 - ((GLint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3773 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3779 _mesa_problem(ctx
, "invalid combine mode");
3782 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
3783 * This is kind of a kludge. It would have been better if the spec
3784 * were written such that the GL_COMBINE_ALPHA value could be set to
3787 if (textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_EXT
||
3788 textureUnit
->CombineModeRGB
== GL_DOT3_RGBA
) {
3789 for (i
= 0; i
< n
; i
++) {
3790 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
3793 UNDEFARRAY(ccolor
); /* mac 32k limitation */
3799 * Implement NVIDIA's GL_NV_texture_env_combine4 extension when
3800 * texUnit->EnvMode == GL_COMBINE4_NV.
3803 texture_combine4( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
3804 CONST
GLchan (*primary_rgba
)[4],
3805 CONST GLchan
*texelBuffer
,
3813 * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND,
3814 * MODULATE, or DECAL) to an array of fragments.
3815 * Input: textureUnit - pointer to texture unit to apply
3816 * format - base internal texture format
3817 * n - number of fragments
3818 * primary_rgba - primary colors (may alias rgba for single texture)
3819 * texels - array of texel colors
3820 * InOut: rgba - incoming fragment colors modified by texel colors
3821 * according to the texture environment mode.
3824 texture_apply( const GLcontext
*ctx
,
3825 const struct gl_texture_unit
*texUnit
,
3827 CONST GLchan primary_rgba
[][4], CONST GLchan texel
[][4],
3832 GLint Rc
, Gc
, Bc
, Ac
;
3836 ASSERT(texUnit
->_Current
);
3838 baseLevel
= texUnit
->_Current
->BaseLevel
;
3839 ASSERT(texUnit
->_Current
->Image
[baseLevel
]);
3841 format
= texUnit
->_Current
->Image
[baseLevel
]->Format
;
3843 if (format
== GL_COLOR_INDEX
|| format
== GL_YCBCR_MESA
) {
3844 format
= GL_RGBA
; /* a bit of a hack */
3846 else if (format
== GL_DEPTH_COMPONENT
) {
3847 format
= texUnit
->_Current
->DepthMode
;
3850 switch (texUnit
->EnvMode
) {
3857 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3863 GLchan Lt
= texel
[i
][RCOMP
];
3864 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3868 case GL_LUMINANCE_ALPHA
:
3870 GLchan Lt
= texel
[i
][RCOMP
];
3872 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3874 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3880 GLchan It
= texel
[i
][RCOMP
];
3881 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
3883 rgba
[i
][ACOMP
] = It
;
3889 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3890 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3891 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3898 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3899 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3900 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3902 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3906 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in texture_apply");
3917 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3923 GLchan Lt
= texel
[i
][RCOMP
];
3924 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3925 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3926 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3930 case GL_LUMINANCE_ALPHA
:
3933 GLchan Lt
= texel
[i
][RCOMP
];
3934 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3935 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3936 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3938 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3944 GLchan It
= texel
[i
][RCOMP
];
3945 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], It
);
3946 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], It
);
3947 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], It
);
3949 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], It
);
3955 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3956 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3957 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3964 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3965 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3966 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3968 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3972 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in texture_apply");
3981 case GL_LUMINANCE_ALPHA
:
3988 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3989 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3990 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3996 /* Cv = Cf(1-At) + CtAt */
3997 GLint t
= texel
[i
][ACOMP
], s
= CHAN_MAX
- t
;
3998 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(texel
[i
][RCOMP
],t
);
3999 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(texel
[i
][GCOMP
],t
);
4000 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(texel
[i
][BCOMP
],t
);
4005 _mesa_problem(ctx
, "Bad format (GL_DECAL) in texture_apply");
4011 Rc
= (GLint
) (texUnit
->EnvColor
[0] * CHAN_MAXF
);
4012 Gc
= (GLint
) (texUnit
->EnvColor
[1] * CHAN_MAXF
);
4013 Bc
= (GLint
) (texUnit
->EnvColor
[2] * CHAN_MAXF
);
4014 Ac
= (GLint
) (texUnit
->EnvColor
[3] * CHAN_MAXF
);
4020 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4025 /* Cv = Cf(1-Lt) + CcLt */
4026 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
4027 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
4028 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
4029 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
4033 case GL_LUMINANCE_ALPHA
:
4035 /* Cv = Cf(1-Lt) + CcLt */
4036 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
4037 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
4038 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
4039 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
4041 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
4046 /* Cv = Cf(1-It) + CcLt */
4047 GLchan It
= texel
[i
][RCOMP
], s
= CHAN_MAX
- It
;
4048 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, It
);
4049 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, It
);
4050 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, It
);
4051 /* Av = Af(1-It) + Ac*It */
4052 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], s
) + CHAN_PRODUCT(Ac
, It
);
4057 /* Cv = Cf(1-Ct) + CcCt */
4058 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
4059 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
4060 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
4066 /* Cv = Cf(1-Ct) + CcCt */
4067 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
4068 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
4069 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
4071 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
4075 _mesa_problem(ctx
, "Bad format (GL_BLEND) in texture_apply");
4080 /* XXX don't clamp results if GLchan is float??? */
4082 case GL_ADD
: /* GL_EXT_texture_add_env */
4089 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4094 GLuint Lt
= texel
[i
][RCOMP
];
4095 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
4096 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
4097 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
4098 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4099 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4100 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4104 case GL_LUMINANCE_ALPHA
:
4106 GLuint Lt
= texel
[i
][RCOMP
];
4107 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
4108 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
4109 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
4110 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4111 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4112 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4113 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4118 GLchan It
= texel
[i
][RCOMP
];
4119 GLuint r
= rgba
[i
][RCOMP
] + It
;
4120 GLuint g
= rgba
[i
][GCOMP
] + It
;
4121 GLuint b
= rgba
[i
][BCOMP
] + It
;
4122 GLuint a
= rgba
[i
][ACOMP
] + It
;
4123 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4124 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4125 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4126 rgba
[i
][ACOMP
] = MIN2(a
, CHAN_MAX
);
4131 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
4132 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
4133 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
4134 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4135 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4136 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4142 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
4143 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
4144 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
4145 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4146 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4147 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4148 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4152 _mesa_problem(ctx
, "Bad format (GL_ADD) in texture_apply");
4158 _mesa_problem(ctx
, "Bad env mode in texture_apply");
4166 * Apply texture mapping to a span of fragments.
4169 _swrast_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
4171 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
4172 GLchan primary_rgba
[MAX_WIDTH
][4];
4175 ASSERT(span
->end
< MAX_WIDTH
);
4176 ASSERT(span
->arrayMask
& SPAN_TEXTURE
);
4179 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
4181 if (swrast
->_AnyTextureCombine
)
4182 MEMCPY(primary_rgba
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
));
4185 * Must do all texture sampling before combining in order to
4186 * accomodate GL_ARB_texture_env_crossbar.
4188 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
4189 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
4190 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
4191 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
4192 GLfloat
*lambda
= span
->array
->lambda
[unit
];
4193 GLchan (*texels
)[4] = (GLchan (*)[4])
4194 (swrast
->TexelBuffer
+ unit
* (span
->end
* 4 * sizeof(GLchan
)));
4196 /* adjust texture lod (lambda) */
4197 if (span
->arrayMask
& SPAN_LAMBDA
) {
4198 if (texUnit
->LodBias
!= 0.0F
) {
4199 /* apply LOD bias, but don't clamp yet */
4201 for (i
= 0; i
< span
->end
; i
++) {
4202 lambda
[i
] += texUnit
->LodBias
;
4206 if (curObj
->MinLod
!= -1000.0 || curObj
->MaxLod
!= 1000.0) {
4207 /* apply LOD clamping to lambda */
4208 const GLfloat min
= curObj
->MinLod
;
4209 const GLfloat max
= curObj
->MaxLod
;
4211 for (i
= 0; i
< span
->end
; i
++) {
4212 GLfloat l
= lambda
[i
];
4213 lambda
[i
] = CLAMP(l
, min
, max
);
4218 /* Sample the texture (span->end fragments) */
4219 swrast
->TextureSample
[unit
]( ctx
, unit
, texUnit
->_Current
, span
->end
,
4220 (const GLfloat (*)[4]) span
->array
->texcoords
[unit
],
4223 /* GL_SGI_texture_color_table */
4224 if (texUnit
->ColorTableEnabled
) {
4225 _swrast_texture_table_lookup(&texUnit
->ColorTable
, span
->end
, texels
);
4231 * OK, now apply the texture (aka texture combine/blend).
4232 * We modify the span->color.rgba values.
4234 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
4235 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
4236 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
4237 if (texUnit
->EnvMode
== GL_COMBINE
) {
4238 /* GL_ARB/EXT_texture_env_combine */
4239 texture_combine( ctx
, unit
, span
->end
,
4240 (CONST
GLchan (*)[4]) primary_rgba
,
4241 swrast
->TexelBuffer
,
4242 span
->array
->rgba
);
4244 else if (texUnit
->EnvMode
== GL_COMBINE4_NV
) {
4245 /* GL_NV_texture_env_combine4 */
4246 texture_combine4( ctx
, unit
, span
->end
,
4247 (CONST
GLchan (*)[4]) primary_rgba
,
4248 swrast
->TexelBuffer
,
4249 span
->array
->rgba
);
4252 /* conventional texture blend */
4253 const GLchan (*texels
)[4] = (const GLchan (*)[4])
4254 (swrast
->TexelBuffer
+ unit
*
4255 (span
->end
* 4 * sizeof(GLchan
)));
4256 texture_apply( ctx
, texUnit
, span
->end
,
4257 (CONST
GLchan (*)[4]) primary_rgba
, texels
,
4258 span
->array
->rgba
);