2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2004 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_EXT) { \
126 U = (GLfloat) fabs(S); \
128 U = (GLfloat) SIZE; \
135 else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_EXT) { \
136 U = (GLfloat) fabs(S); \
138 U = (GLfloat) SIZE; \
146 if (I1 >= (GLint) SIZE) \
149 else if (wrapMode == GL_MIRROR_CLAMP_TO_BORDER_EXT) { \
150 const GLfloat min = -1.0F / (2.0F * SIZE); \
151 const GLfloat max = 1.0F - min; \
152 U = (GLfloat) fabs(S); \
164 ASSERT(wrapMode == GL_CLAMP); \
167 else if (S >= 1.0F) \
168 U = (GLfloat) SIZE; \
179 * Used to compute texel location for nearest sampling.
181 #define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I) \
183 if (wrapMode == GL_REPEAT) { \
184 /* s limited to [0,1) */ \
185 /* i limited to [0,size-1] */ \
186 I = IFLOOR(S * SIZE); \
187 if (tObj->_IsPowerOfTwo) \
190 I = repeat_remainder(I, SIZE); \
192 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
193 /* s limited to [min,max] */ \
194 /* i limited to [0, size-1] */ \
195 const GLfloat min = 1.0F / (2.0F * SIZE); \
196 const GLfloat max = 1.0F - min; \
202 I = IFLOOR(S * SIZE); \
204 else if (wrapMode == GL_CLAMP_TO_BORDER) { \
205 /* s limited to [min,max] */ \
206 /* i limited to [-1, size] */ \
207 const GLfloat min = -1.0F / (2.0F * SIZE); \
208 const GLfloat max = 1.0F - min; \
214 I = IFLOOR(S * SIZE); \
216 else if (wrapMode == GL_MIRRORED_REPEAT) { \
217 const GLfloat min = 1.0F / (2.0F * SIZE); \
218 const GLfloat max = 1.0F - min; \
219 const GLint flr = IFLOOR(S); \
222 u = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
224 u = S - (GLfloat) flr; /* flr is even */ \
230 I = IFLOOR(u * SIZE); \
232 else if (wrapMode == GL_MIRROR_CLAMP_EXT) { \
233 /* s limited to [0,1] */ \
234 /* i limited to [0,size-1] */ \
235 const GLfloat u = (GLfloat) fabs(S); \
238 else if (u >= 1.0F) \
241 I = IFLOOR(u * SIZE); \
243 else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_EXT) { \
244 /* s limited to [min,max] */ \
245 /* i limited to [0, size-1] */ \
246 const GLfloat min = 1.0F / (2.0F * SIZE); \
247 const GLfloat max = 1.0F - min; \
248 const GLfloat u = (GLfloat) fabs(S); \
254 I = IFLOOR(u * SIZE); \
256 else if (wrapMode == GL_MIRROR_CLAMP_TO_BORDER_EXT) { \
257 /* s limited to [min,max] */ \
258 /* i limited to [0, size-1] */ \
259 const GLfloat min = -1.0F / (2.0F * SIZE); \
260 const GLfloat max = 1.0F - min; \
261 const GLfloat u = (GLfloat) fabs(S); \
267 I = IFLOOR(u * SIZE); \
270 ASSERT(wrapMode == GL_CLAMP); \
271 /* s limited to [0,1] */ \
272 /* i limited to [0,size-1] */ \
275 else if (S >= 1.0F) \
278 I = IFLOOR(S * SIZE); \
283 /* Power of two image sizes only */
284 #define COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(S, U, SIZE, I0, I1) \
286 U = S * SIZE - 0.5F; \
287 I0 = IFLOOR(U) & (SIZE - 1); \
288 I1 = (I0 + 1) & (SIZE - 1); \
293 * Compute linear mipmap levels for given lambda.
295 #define COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level) \
298 level = tObj->BaseLevel; \
299 else if (lambda > tObj->_MaxLambda) \
300 level = (GLint) (tObj->BaseLevel + tObj->_MaxLambda); \
302 level = (GLint) (tObj->BaseLevel + lambda); \
307 * Compute nearest mipmap level for given lambda.
309 #define COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level) \
312 if (lambda <= 0.5F) \
314 else if (lambda > tObj->_MaxLambda + 0.4999F) \
315 l = tObj->_MaxLambda + 0.4999F; \
318 level = (GLint) (tObj->BaseLevel + l + 0.5F); \
319 if (level > tObj->_MaxLevel) \
320 level = tObj->_MaxLevel; \
326 * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
327 * see 1-pixel bands of improperly weighted linear-sampled texels. The
328 * tests/texwrap.c demo is a good test.
329 * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
330 * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
332 #define FRAC(f) ((f) - IFLOOR(f))
337 * Bitflags for texture border color sampling.
348 * Do the lookup for GL_SGI_texture_color_table.
349 * XXX merge with _mesa_lookup_rgba in pixel.c
352 _swrast_texture_table_lookup(const struct gl_color_table
*table
,
353 GLuint n
, GLchan rgba
[][4])
355 if (!table
->Table
|| table
->Size
== 0)
358 switch (table
->Format
) {
360 /* replace RGBA with I */
361 if (table
->Type
== GL_FLOAT
) {
362 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
363 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
365 for (i
= 0; i
< n
; i
++) {
366 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
368 CLAMPED_FLOAT_TO_CHAN(c
, lut
[j
]);
369 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] =
370 rgba
[i
][BCOMP
] = rgba
[i
][ACOMP
] = c
;
374 #if CHAN_TYPE == GL_UNSIGNED_BYTE
375 if (table
->Size
== 256) {
377 const GLchan
*lut
= (const GLchan
*) table
->Table
;
379 for (i
= 0; i
< n
; i
++) {
380 const GLchan c
= lut
[rgba
[i
][RCOMP
]];
381 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] =
382 rgba
[i
][BCOMP
] = rgba
[i
][ACOMP
] = c
;
388 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
389 const GLchan
*lut
= (const GLchan
*) table
->Table
;
391 for (i
= 0; i
< n
; i
++) {
392 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
393 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] =
394 rgba
[i
][BCOMP
] = rgba
[i
][ACOMP
] = lut
[j
];
400 /* replace RGB with L */
401 if (table
->Type
== GL_FLOAT
) {
402 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
403 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
405 for (i
= 0; i
< n
; i
++) {
406 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
408 CLAMPED_FLOAT_TO_CHAN(c
, lut
[j
]);
409 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = c
;
413 #if CHAN_TYPE == GL_UNSIGNED_BYTE
414 if (table
->Size
== 256) {
416 const GLchan
*lut
= (const GLchan
*) table
->Table
;
418 for (i
= 0; i
< n
; i
++) {
419 const GLchan c
= lut
[rgba
[i
][RCOMP
]];
420 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = c
;
426 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
427 const GLchan
*lut
= (const GLchan
*) table
->Table
;
429 for (i
= 0; i
< n
; i
++) {
430 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
431 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = lut
[j
];
437 /* replace A with A */
438 if (table
->Type
== GL_FLOAT
) {
439 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
440 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
442 for (i
= 0; i
< n
; i
++) {
443 GLint j
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
445 CLAMPED_FLOAT_TO_CHAN(c
, lut
[j
]);
450 #if CHAN_TYPE == GL_UNSIGNED_BYTE
451 if (table
->Size
== 256) {
453 const GLchan
*lut
= (const GLchan
*) table
->Table
;
455 for (i
= 0; i
< n
; i
++) {
456 rgba
[i
][ACOMP
] = lut
[rgba
[i
][ACOMP
]];
462 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
463 const GLchan
*lut
= (const GLchan
*) table
->Table
;
465 for (i
= 0; i
< n
; i
++) {
466 GLint j
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
467 rgba
[i
][ACOMP
] = lut
[j
];
472 case GL_LUMINANCE_ALPHA
:
473 /* replace RGBA with LLLA */
474 if (table
->Type
== GL_FLOAT
) {
475 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
476 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
478 for (i
= 0; i
< n
; i
++) {
479 GLint jL
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
480 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
481 GLchan luminance
, alpha
;
482 CLAMPED_FLOAT_TO_CHAN(luminance
, lut
[jL
* 2 + 0]);
483 CLAMPED_FLOAT_TO_CHAN(alpha
, lut
[jA
* 2 + 1]);
484 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = luminance
;
485 rgba
[i
][ACOMP
] = alpha
;;
489 #if CHAN_TYPE == GL_UNSIGNED_BYTE
490 if (table
->Size
== 256) {
492 const GLchan
*lut
= (const GLchan
*) table
->Table
;
494 for (i
= 0; i
< n
; i
++) {
495 GLchan l
= lut
[rgba
[i
][RCOMP
] * 2 + 0];
496 GLchan a
= lut
[rgba
[i
][ACOMP
] * 2 + 1];;
497 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = l
;
504 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
505 const GLchan
*lut
= (const GLchan
*) table
->Table
;
507 for (i
= 0; i
< n
; i
++) {
508 GLint jL
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
509 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
510 GLchan luminance
= lut
[jL
* 2 + 0];
511 GLchan alpha
= lut
[jA
* 2 + 1];
512 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = luminance
;
513 rgba
[i
][ACOMP
] = alpha
;
519 /* replace RGB with RGB */
520 if (table
->Type
== GL_FLOAT
) {
521 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
522 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
524 for (i
= 0; i
< n
; i
++) {
525 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
526 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
527 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
528 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][RCOMP
], lut
[jR
* 3 + 0]);
529 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][GCOMP
], lut
[jG
* 3 + 1]);
530 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][BCOMP
], lut
[jB
* 3 + 2]);
534 #if CHAN_TYPE == GL_UNSIGNED_BYTE
535 if (table
->Size
== 256) {
537 const GLchan
*lut
= (const GLchan
*) table
->Table
;
539 for (i
= 0; i
< n
; i
++) {
540 rgba
[i
][RCOMP
] = lut
[rgba
[i
][RCOMP
] * 3 + 0];
541 rgba
[i
][GCOMP
] = lut
[rgba
[i
][GCOMP
] * 3 + 1];
542 rgba
[i
][BCOMP
] = lut
[rgba
[i
][BCOMP
] * 3 + 2];
548 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
549 const GLchan
*lut
= (const GLchan
*) table
->Table
;
551 for (i
= 0; i
< n
; i
++) {
552 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
553 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
554 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
555 rgba
[i
][RCOMP
] = lut
[jR
* 3 + 0];
556 rgba
[i
][GCOMP
] = lut
[jG
* 3 + 1];
557 rgba
[i
][BCOMP
] = lut
[jB
* 3 + 2];
563 /* replace RGBA with RGBA */
564 if (table
->Type
== GL_FLOAT
) {
565 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
566 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
568 for (i
= 0; i
< n
; i
++) {
569 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
570 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
571 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
572 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
573 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][RCOMP
], lut
[jR
* 4 + 0]);
574 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][GCOMP
], lut
[jG
* 4 + 1]);
575 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][BCOMP
], lut
[jB
* 4 + 2]);
576 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][ACOMP
], lut
[jA
* 4 + 3]);
580 #if CHAN_TYPE == GL_UNSIGNED_BYTE
581 if (table
->Size
== 256) {
583 const GLchan
*lut
= (const GLchan
*) table
->Table
;
585 for (i
= 0; i
< n
; i
++) {
586 rgba
[i
][RCOMP
] = lut
[rgba
[i
][RCOMP
] * 4 + 0];
587 rgba
[i
][GCOMP
] = lut
[rgba
[i
][GCOMP
] * 4 + 1];
588 rgba
[i
][BCOMP
] = lut
[rgba
[i
][BCOMP
] * 4 + 2];
589 rgba
[i
][ACOMP
] = lut
[rgba
[i
][ACOMP
] * 4 + 3];
595 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
596 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
598 for (i
= 0; i
< n
; i
++) {
599 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
600 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
601 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
602 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
603 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][RCOMP
], lut
[jR
* 4 + 0]);
604 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][GCOMP
], lut
[jG
* 4 + 1]);
605 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][BCOMP
], lut
[jB
* 4 + 2]);
606 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][ACOMP
], lut
[jA
* 4 + 3]);
612 _mesa_problem(NULL
, "Bad format in _swrast_texture_table_lookup");
620 * Get texture palette entry.
623 palette_sample(const GLcontext
*ctx
,
624 const struct gl_texture_object
*tObj
,
625 GLint index
, GLchan rgba
[4] )
627 const GLchan
*palette
;
630 if (ctx
->Texture
.SharedPalette
) {
631 ASSERT(ctx
->Texture
.Palette
.Type
!= GL_FLOAT
);
632 palette
= (const GLchan
*) ctx
->Texture
.Palette
.Table
;
633 format
= ctx
->Texture
.Palette
.Format
;
636 ASSERT(tObj
->Palette
.Type
!= GL_FLOAT
);
637 palette
= (const GLchan
*) tObj
->Palette
.Table
;
638 format
= tObj
->Palette
.Format
;
643 rgba
[ACOMP
] = palette
[index
];
647 rgba
[RCOMP
] = palette
[index
];
649 case GL_LUMINANCE_ALPHA
:
650 rgba
[RCOMP
] = palette
[(index
<< 1) + 0];
651 rgba
[ACOMP
] = palette
[(index
<< 1) + 1];
654 rgba
[RCOMP
] = palette
[index
* 3 + 0];
655 rgba
[GCOMP
] = palette
[index
* 3 + 1];
656 rgba
[BCOMP
] = palette
[index
* 3 + 2];
659 rgba
[RCOMP
] = palette
[(index
<< 2) + 0];
660 rgba
[GCOMP
] = palette
[(index
<< 2) + 1];
661 rgba
[BCOMP
] = palette
[(index
<< 2) + 2];
662 rgba
[ACOMP
] = palette
[(index
<< 2) + 3];
665 _mesa_problem(ctx
, "Bad palette format in palette_sample");
671 * The lambda[] array values are always monotonic. Either the whole span
672 * will be minified, magnified, or split between the two. This function
673 * determines the subranges in [0, n-1] that are to be minified or magnified.
676 compute_min_mag_ranges( GLfloat minMagThresh
, GLuint n
, const GLfloat lambda
[],
677 GLuint
*minStart
, GLuint
*minEnd
,
678 GLuint
*magStart
, GLuint
*magEnd
)
680 ASSERT(lambda
!= NULL
);
682 /* Verify that lambda[] is monotonous.
683 * We can't really use this because the inaccuracy in the LOG2 function
684 * causes this test to fail, yet the resulting texturing is correct.
688 printf("lambda delta = %g\n", lambda
[0] - lambda
[n
-1]);
689 if (lambda
[0] >= lambda
[n
-1]) { /* decreasing */
690 for (i
= 0; i
< n
- 1; i
++) {
691 ASSERT((GLint
) (lambda
[i
] * 10) >= (GLint
) (lambda
[i
+1] * 10));
694 else { /* increasing */
695 for (i
= 0; i
< n
- 1; i
++) {
696 ASSERT((GLint
) (lambda
[i
] * 10) <= (GLint
) (lambda
[i
+1] * 10));
702 /* since lambda is monotonous-array use this check first */
703 if (lambda
[0] <= minMagThresh
&& lambda
[n
-1] <= minMagThresh
) {
704 /* magnification for whole span */
707 *minStart
= *minEnd
= 0;
709 else if (lambda
[0] > minMagThresh
&& lambda
[n
-1] > minMagThresh
) {
710 /* minification for whole span */
713 *magStart
= *magEnd
= 0;
716 /* a mix of minification and magnification */
718 if (lambda
[0] > minMagThresh
) {
719 /* start with minification */
720 for (i
= 1; i
< n
; i
++) {
721 if (lambda
[i
] <= minMagThresh
)
730 /* start with magnification */
731 for (i
= 1; i
< n
; i
++) {
732 if (lambda
[i
] > minMagThresh
)
743 /* Verify the min/mag Start/End values
744 * We don't use this either (see above)
748 for (i
= 0; i
< n
; i
++) {
749 if (lambda
[i
] > minMagThresh
) {
751 ASSERT(i
>= *minStart
);
756 ASSERT(i
>= *magStart
);
765 /**********************************************************************/
766 /* 1-D Texture Sampling Functions */
767 /**********************************************************************/
770 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
773 sample_1d_nearest(GLcontext
*ctx
,
774 const struct gl_texture_object
*tObj
,
775 const struct gl_texture_image
*img
,
776 const GLfloat texcoord
[4], GLchan rgba
[4])
778 const GLint width
= img
->Width2
; /* without border, power of two */
781 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
783 /* skip over the border, if any */
786 if (i
< 0 || i
>= (GLint
) img
->Width
) {
787 /* Need this test for GL_CLAMP_TO_BORDER mode */
788 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
791 img
->FetchTexelc(img
, i
, 0, 0, rgba
);
792 if (img
->Format
== GL_COLOR_INDEX
) {
793 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
801 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
804 sample_1d_linear(GLcontext
*ctx
,
805 const struct gl_texture_object
*tObj
,
806 const struct gl_texture_image
*img
,
807 const GLfloat texcoord
[4], GLchan rgba
[4])
809 const GLint width
= img
->Width2
;
812 GLuint useBorderColor
;
814 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
822 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
823 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
827 const GLfloat a
= FRAC(u
);
829 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
830 const GLfloat w0
= (1.0F
-a
);
831 const GLfloat w1
= a
;
832 #else /* CHAN_BITS == 8 */
833 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
834 const GLint w0
= IROUND_POS((1.0F
- a
) * WEIGHT_SCALE
);
835 const GLint w1
= IROUND_POS( a
* WEIGHT_SCALE
);
837 GLchan t0
[4], t1
[4]; /* texels */
839 if (useBorderColor
& I0BIT
) {
840 COPY_CHAN4(t0
, tObj
->_BorderChan
);
843 img
->FetchTexelc(img
, i0
, 0, 0, t0
);
844 if (img
->Format
== GL_COLOR_INDEX
) {
845 palette_sample(ctx
, tObj
, t0
[0], t0
);
848 if (useBorderColor
& I1BIT
) {
849 COPY_CHAN4(t1
, tObj
->_BorderChan
);
852 img
->FetchTexelc(img
, i1
, 0, 0, t1
);
853 if (img
->Format
== GL_COLOR_INDEX
) {
854 palette_sample(ctx
, tObj
, t1
[0], t1
);
858 #if CHAN_TYPE == GL_FLOAT
859 rgba
[0] = w0
* t0
[0] + w1
* t1
[0];
860 rgba
[1] = w0
* t0
[1] + w1
* t1
[1];
861 rgba
[2] = w0
* t0
[2] + w1
* t1
[2];
862 rgba
[3] = w0
* t0
[3] + w1
* t1
[3];
863 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
864 rgba
[0] = (GLchan
) (w0
* t0
[0] + w1
* t1
[0] + 0.5);
865 rgba
[1] = (GLchan
) (w0
* t0
[1] + w1
* t1
[1] + 0.5);
866 rgba
[2] = (GLchan
) (w0
* t0
[2] + w1
* t1
[2] + 0.5);
867 rgba
[3] = (GLchan
) (w0
* t0
[3] + w1
* t1
[3] + 0.5);
868 #else /* CHAN_BITS == 8 */
869 rgba
[0] = (GLchan
) ((w0
* t0
[0] + w1
* t1
[0]) >> WEIGHT_SHIFT
);
870 rgba
[1] = (GLchan
) ((w0
* t0
[1] + w1
* t1
[1]) >> WEIGHT_SHIFT
);
871 rgba
[2] = (GLchan
) ((w0
* t0
[2] + w1
* t1
[2]) >> WEIGHT_SHIFT
);
872 rgba
[3] = (GLchan
) ((w0
* t0
[3] + w1
* t1
[3]) >> WEIGHT_SHIFT
);
880 sample_1d_nearest_mipmap_nearest(GLcontext
*ctx
,
881 const struct gl_texture_object
*tObj
,
882 GLuint n
, const GLfloat texcoord
[][4],
883 const GLfloat lambda
[], GLchan rgba
[][4])
886 ASSERT(lambda
!= NULL
);
887 for (i
= 0; i
< n
; i
++) {
889 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
890 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
896 sample_1d_linear_mipmap_nearest(GLcontext
*ctx
,
897 const struct gl_texture_object
*tObj
,
898 GLuint n
, const GLfloat texcoord
[][4],
899 const GLfloat lambda
[], GLchan rgba
[][4])
902 ASSERT(lambda
!= NULL
);
903 for (i
= 0; i
< n
; i
++) {
905 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
906 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
913 * This is really just needed in order to prevent warnings with some compilers.
915 #if CHAN_TYPE == GL_FLOAT
918 #define CHAN_CAST (GLchan) (GLint)
923 sample_1d_nearest_mipmap_linear(GLcontext
*ctx
,
924 const struct gl_texture_object
*tObj
,
925 GLuint n
, const GLfloat texcoord
[][4],
926 const GLfloat lambda
[], GLchan rgba
[][4])
929 ASSERT(lambda
!= NULL
);
930 for (i
= 0; i
< n
; i
++) {
932 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
933 if (level
>= tObj
->_MaxLevel
) {
934 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
935 texcoord
[i
], rgba
[i
]);
939 const GLfloat f
= FRAC(lambda
[i
]);
940 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
941 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
942 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
943 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
944 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
945 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
953 sample_1d_linear_mipmap_linear(GLcontext
*ctx
,
954 const struct gl_texture_object
*tObj
,
955 GLuint n
, const GLfloat texcoord
[][4],
956 const GLfloat lambda
[], GLchan rgba
[][4])
959 ASSERT(lambda
!= NULL
);
960 for (i
= 0; i
< n
; i
++) {
962 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
963 if (level
>= tObj
->_MaxLevel
) {
964 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
965 texcoord
[i
], rgba
[i
]);
969 const GLfloat f
= FRAC(lambda
[i
]);
970 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
971 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
972 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
973 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
974 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
975 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
983 sample_nearest_1d( GLcontext
*ctx
, GLuint texUnit
,
984 const struct gl_texture_object
*tObj
, GLuint n
,
985 const GLfloat texcoords
[][4], const GLfloat lambda
[],
989 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
992 sample_1d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
999 sample_linear_1d( GLcontext
*ctx
, GLuint texUnit
,
1000 const struct gl_texture_object
*tObj
, GLuint n
,
1001 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1005 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1008 sample_1d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1014 * Given an (s) texture coordinate and lambda (level of detail) value,
1015 * return a texture sample.
1019 sample_lambda_1d( GLcontext
*ctx
, GLuint texUnit
,
1020 const struct gl_texture_object
*tObj
, GLuint n
,
1021 const GLfloat texcoords
[][4],
1022 const GLfloat lambda
[], GLchan rgba
[][4] )
1024 GLuint minStart
, minEnd
; /* texels with minification */
1025 GLuint magStart
, magEnd
; /* texels with magnification */
1028 ASSERT(lambda
!= NULL
);
1029 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1030 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1032 if (minStart
< minEnd
) {
1033 /* do the minified texels */
1034 const GLuint m
= minEnd
- minStart
;
1035 switch (tObj
->MinFilter
) {
1037 for (i
= minStart
; i
< minEnd
; i
++)
1038 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1039 texcoords
[i
], rgba
[i
]);
1042 for (i
= minStart
; i
< minEnd
; i
++)
1043 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1044 texcoords
[i
], rgba
[i
]);
1046 case GL_NEAREST_MIPMAP_NEAREST
:
1047 sample_1d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1048 lambda
+ minStart
, rgba
+ minStart
);
1050 case GL_LINEAR_MIPMAP_NEAREST
:
1051 sample_1d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1052 lambda
+ minStart
, rgba
+ minStart
);
1054 case GL_NEAREST_MIPMAP_LINEAR
:
1055 sample_1d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1056 lambda
+ minStart
, rgba
+ minStart
);
1058 case GL_LINEAR_MIPMAP_LINEAR
:
1059 sample_1d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1060 lambda
+ minStart
, rgba
+ minStart
);
1063 _mesa_problem(ctx
, "Bad min filter in sample_1d_texture");
1068 if (magStart
< magEnd
) {
1069 /* do the magnified texels */
1070 switch (tObj
->MagFilter
) {
1072 for (i
= magStart
; i
< magEnd
; i
++)
1073 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1074 texcoords
[i
], rgba
[i
]);
1077 for (i
= magStart
; i
< magEnd
; i
++)
1078 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1079 texcoords
[i
], rgba
[i
]);
1082 _mesa_problem(ctx
, "Bad mag filter in sample_1d_texture");
1089 /**********************************************************************/
1090 /* 2-D Texture Sampling Functions */
1091 /**********************************************************************/
1095 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
1098 sample_2d_nearest(GLcontext
*ctx
,
1099 const struct gl_texture_object
*tObj
,
1100 const struct gl_texture_image
*img
,
1101 const GLfloat texcoord
[4],
1104 const GLint width
= img
->Width2
; /* without border, power of two */
1105 const GLint height
= img
->Height2
; /* without border, power of two */
1108 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
1109 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
1111 /* skip over the border, if any */
1115 if (i
< 0 || i
>= (GLint
) img
->Width
|| j
< 0 || j
>= (GLint
) img
->Height
) {
1116 /* Need this test for GL_CLAMP_TO_BORDER mode */
1117 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
1120 img
->FetchTexelc(img
, i
, j
, 0, rgba
);
1121 if (img
->Format
== GL_COLOR_INDEX
) {
1122 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
1130 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
1131 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
1134 sample_2d_linear(GLcontext
*ctx
,
1135 const struct gl_texture_object
*tObj
,
1136 const struct gl_texture_image
*img
,
1137 const GLfloat texcoord
[4],
1140 const GLint width
= img
->Width2
;
1141 const GLint height
= img
->Height2
;
1142 GLint i0
, j0
, i1
, j1
;
1143 GLuint useBorderColor
;
1146 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1147 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1157 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1158 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1159 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1160 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1164 const GLfloat a
= FRAC(u
);
1165 const GLfloat b
= FRAC(v
);
1167 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1168 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
1169 const GLfloat w10
= a
* (1.0F
-b
);
1170 const GLfloat w01
= (1.0F
-a
) * b
;
1171 const GLfloat w11
= a
* b
;
1172 #else /* CHAN_BITS == 8 */
1173 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1174 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
1175 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
1176 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
1177 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
1184 if (useBorderColor
& (I0BIT
| J0BIT
)) {
1185 COPY_CHAN4(t00
, tObj
->_BorderChan
);
1188 img
->FetchTexelc(img
, i0
, j0
, 0, t00
);
1189 if (img
->Format
== GL_COLOR_INDEX
) {
1190 palette_sample(ctx
, tObj
, t00
[0], t00
);
1193 if (useBorderColor
& (I1BIT
| J0BIT
)) {
1194 COPY_CHAN4(t10
, tObj
->_BorderChan
);
1197 img
->FetchTexelc(img
, i1
, j0
, 0, t10
);
1198 if (img
->Format
== GL_COLOR_INDEX
) {
1199 palette_sample(ctx
, tObj
, t10
[0], t10
);
1202 if (useBorderColor
& (I0BIT
| J1BIT
)) {
1203 COPY_CHAN4(t01
, tObj
->_BorderChan
);
1206 img
->FetchTexelc(img
, i0
, j1
, 0, t01
);
1207 if (img
->Format
== GL_COLOR_INDEX
) {
1208 palette_sample(ctx
, tObj
, t01
[0], t01
);
1211 if (useBorderColor
& (I1BIT
| J1BIT
)) {
1212 COPY_CHAN4(t11
, tObj
->_BorderChan
);
1215 img
->FetchTexelc(img
, i1
, j1
, 0, t11
);
1216 if (img
->Format
== GL_COLOR_INDEX
) {
1217 palette_sample(ctx
, tObj
, t11
[0], t11
);
1220 #if CHAN_TYPE == GL_FLOAT
1221 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
1222 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
1223 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
1224 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
1225 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1226 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
1227 w01
* t01
[0] + w11
* t11
[0] + 0.5);
1228 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
1229 w01
* t01
[1] + w11
* t11
[1] + 0.5);
1230 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
1231 w01
* t01
[2] + w11
* t11
[2] + 0.5);
1232 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
1233 w01
* t01
[3] + w11
* t11
[3] + 0.5);
1234 #else /* CHAN_BITS == 8 */
1235 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
1236 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
1237 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
1238 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
1239 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
1240 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
1241 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
1242 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
1251 * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT
1252 * and we're not using a paletted texture.
1255 sample_2d_linear_repeat(GLcontext
*ctx
,
1256 const struct gl_texture_object
*tObj
,
1257 const struct gl_texture_image
*img
,
1258 const GLfloat texcoord
[4],
1261 const GLint width
= img
->Width2
;
1262 const GLint height
= img
->Height2
;
1263 GLint i0
, j0
, i1
, j1
;
1266 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1267 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1268 ASSERT(img
->Border
== 0);
1269 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
1270 ASSERT(img
->_IsPowerOfTwo
);
1272 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[0], u
, width
, i0
, i1
);
1273 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[1], v
, height
, j0
, j1
);
1276 const GLfloat a
= FRAC(u
);
1277 const GLfloat b
= FRAC(v
);
1279 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1280 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
1281 const GLfloat w10
= a
* (1.0F
-b
);
1282 const GLfloat w01
= (1.0F
-a
) * b
;
1283 const GLfloat w11
= a
* b
;
1284 #else /* CHAN_BITS == 8 */
1285 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1286 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
1287 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
1288 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
1289 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
1296 img
->FetchTexelc(img
, i0
, j0
, 0, t00
);
1297 img
->FetchTexelc(img
, i1
, j0
, 0, t10
);
1298 img
->FetchTexelc(img
, i0
, j1
, 0, t01
);
1299 img
->FetchTexelc(img
, i1
, j1
, 0, t11
);
1301 #if CHAN_TYPE == GL_FLOAT
1302 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
1303 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
1304 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
1305 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
1306 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1307 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
1308 w01
* t01
[0] + w11
* t11
[0] + 0.5);
1309 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
1310 w01
* t01
[1] + w11
* t11
[1] + 0.5);
1311 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
1312 w01
* t01
[2] + w11
* t11
[2] + 0.5);
1313 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
1314 w01
* t01
[3] + w11
* t11
[3] + 0.5);
1315 #else /* CHAN_BITS == 8 */
1316 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
1317 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
1318 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
1319 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
1320 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
1321 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
1322 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
1323 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
1333 sample_2d_nearest_mipmap_nearest(GLcontext
*ctx
,
1334 const struct gl_texture_object
*tObj
,
1335 GLuint n
, const GLfloat texcoord
[][4],
1336 const GLfloat lambda
[], GLchan rgba
[][4])
1339 for (i
= 0; i
< n
; i
++) {
1341 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1342 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1349 sample_2d_linear_mipmap_nearest(GLcontext
*ctx
,
1350 const struct gl_texture_object
*tObj
,
1351 GLuint n
, const GLfloat texcoord
[][4],
1352 const GLfloat lambda
[], GLchan rgba
[][4])
1355 ASSERT(lambda
!= NULL
);
1356 for (i
= 0; i
< n
; i
++) {
1358 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1359 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1366 sample_2d_nearest_mipmap_linear(GLcontext
*ctx
,
1367 const struct gl_texture_object
*tObj
,
1368 GLuint n
, const GLfloat texcoord
[][4],
1369 const GLfloat lambda
[], GLchan rgba
[][4])
1372 ASSERT(lambda
!= NULL
);
1373 for (i
= 0; i
< n
; i
++) {
1375 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1376 if (level
>= tObj
->_MaxLevel
) {
1377 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1378 texcoord
[i
], rgba
[i
]);
1381 GLchan t0
[4], t1
[4]; /* texels */
1382 const GLfloat f
= FRAC(lambda
[i
]);
1383 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1384 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1385 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1386 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1387 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1388 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1395 /* Trilinear filtering */
1397 sample_2d_linear_mipmap_linear( GLcontext
*ctx
,
1398 const struct gl_texture_object
*tObj
,
1399 GLuint n
, const GLfloat texcoord
[][4],
1400 const GLfloat lambda
[], GLchan rgba
[][4] )
1403 ASSERT(lambda
!= NULL
);
1404 for (i
= 0; i
< n
; i
++) {
1406 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1407 if (level
>= tObj
->_MaxLevel
) {
1408 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1409 texcoord
[i
], rgba
[i
]);
1412 GLchan t0
[4], t1
[4]; /* texels */
1413 const GLfloat f
= FRAC(lambda
[i
]);
1414 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1415 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1416 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1417 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1418 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1419 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1426 sample_2d_linear_mipmap_linear_repeat( GLcontext
*ctx
,
1427 const struct gl_texture_object
*tObj
,
1428 GLuint n
, const GLfloat texcoord
[][4],
1429 const GLfloat lambda
[], GLchan rgba
[][4] )
1432 ASSERT(lambda
!= NULL
);
1433 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1434 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1435 ASSERT(tObj
->_IsPowerOfTwo
);
1436 for (i
= 0; i
< n
; i
++) {
1438 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1439 if (level
>= tObj
->_MaxLevel
) {
1440 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1441 texcoord
[i
], rgba
[i
]);
1444 GLchan t0
[4], t1
[4]; /* texels */
1445 const GLfloat f
= FRAC(lambda
[i
]);
1446 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1447 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1448 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1449 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1450 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1451 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1458 sample_nearest_2d( GLcontext
*ctx
, GLuint texUnit
,
1459 const struct gl_texture_object
*tObj
, GLuint n
,
1460 const GLfloat texcoords
[][4],
1461 const GLfloat lambda
[], GLchan rgba
[][4] )
1464 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1467 sample_2d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1474 sample_linear_2d( GLcontext
*ctx
, GLuint texUnit
,
1475 const struct gl_texture_object
*tObj
, GLuint n
,
1476 const GLfloat texcoords
[][4],
1477 const GLfloat lambda
[], GLchan rgba
[][4] )
1480 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1483 sample_2d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1489 * Optimized 2-D texture sampling:
1490 * S and T wrap mode == GL_REPEAT
1491 * GL_NEAREST min/mag filter
1493 * RowStride == Width,
1497 opt_sample_rgb_2d( GLcontext
*ctx
, GLuint texUnit
,
1498 const struct gl_texture_object
*tObj
,
1499 GLuint n
, const GLfloat texcoords
[][4],
1500 const GLfloat lambda
[], GLchan rgba
[][4] )
1502 const struct gl_texture_image
*img
= tObj
->Image
[0][tObj
->BaseLevel
];
1503 const GLfloat width
= (GLfloat
) img
->Width
;
1504 const GLfloat height
= (GLfloat
) img
->Height
;
1505 const GLint colMask
= img
->Width
- 1;
1506 const GLint rowMask
= img
->Height
- 1;
1507 const GLint shift
= img
->WidthLog2
;
1510 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1511 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1512 ASSERT(img
->Border
==0);
1513 ASSERT(img
->Format
==GL_RGB
);
1514 ASSERT(img
->_IsPowerOfTwo
);
1516 for (k
=0; k
<n
; k
++) {
1517 GLint i
= IFLOOR(texcoords
[k
][0] * width
) & colMask
;
1518 GLint j
= IFLOOR(texcoords
[k
][1] * height
) & rowMask
;
1519 GLint pos
= (j
<< shift
) | i
;
1520 GLchan
*texel
= ((GLchan
*) img
->Data
) + 3*pos
;
1521 rgba
[k
][RCOMP
] = texel
[0];
1522 rgba
[k
][GCOMP
] = texel
[1];
1523 rgba
[k
][BCOMP
] = texel
[2];
1529 * Optimized 2-D texture sampling:
1530 * S and T wrap mode == GL_REPEAT
1531 * GL_NEAREST min/mag filter
1533 * RowStride == Width,
1537 opt_sample_rgba_2d( GLcontext
*ctx
, GLuint texUnit
,
1538 const struct gl_texture_object
*tObj
,
1539 GLuint n
, const GLfloat texcoords
[][4],
1540 const GLfloat lambda
[], GLchan rgba
[][4] )
1542 const struct gl_texture_image
*img
= tObj
->Image
[0][tObj
->BaseLevel
];
1543 const GLfloat width
= (GLfloat
) img
->Width
;
1544 const GLfloat height
= (GLfloat
) img
->Height
;
1545 const GLint colMask
= img
->Width
- 1;
1546 const GLint rowMask
= img
->Height
- 1;
1547 const GLint shift
= img
->WidthLog2
;
1550 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1551 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1552 ASSERT(img
->Border
==0);
1553 ASSERT(img
->Format
==GL_RGBA
);
1554 ASSERT(img
->_IsPowerOfTwo
);
1556 for (i
= 0; i
< n
; i
++) {
1557 const GLint col
= IFLOOR(texcoords
[i
][0] * width
) & colMask
;
1558 const GLint row
= IFLOOR(texcoords
[i
][1] * height
) & rowMask
;
1559 const GLint pos
= (row
<< shift
) | col
;
1560 const GLchan
*texel
= ((GLchan
*) img
->Data
) + (pos
<< 2); /* pos*4 */
1561 COPY_CHAN4(rgba
[i
], texel
);
1567 * Given an array of texture coordinate and lambda (level of detail)
1568 * values, return an array of texture sample.
1571 sample_lambda_2d( GLcontext
*ctx
, GLuint texUnit
,
1572 const struct gl_texture_object
*tObj
,
1573 GLuint n
, const GLfloat texcoords
[][4],
1574 const GLfloat lambda
[], GLchan rgba
[][4] )
1576 const struct gl_texture_image
*tImg
= tObj
->Image
[0][tObj
->BaseLevel
];
1577 GLuint minStart
, minEnd
; /* texels with minification */
1578 GLuint magStart
, magEnd
; /* texels with magnification */
1580 const GLboolean repeatNoBorderPOT
= (tObj
->WrapS
== GL_REPEAT
)
1581 && (tObj
->WrapT
== GL_REPEAT
)
1582 && (tImg
->Border
== 0 && (tImg
->Width
== tImg
->RowStride
))
1583 && (tImg
->Format
!= GL_COLOR_INDEX
)
1584 && tImg
->_IsPowerOfTwo
;
1586 ASSERT(lambda
!= NULL
);
1587 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1588 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1590 if (minStart
< minEnd
) {
1591 /* do the minified texels */
1592 const GLuint m
= minEnd
- minStart
;
1593 switch (tObj
->MinFilter
) {
1595 if (repeatNoBorderPOT
) {
1596 switch (tImg
->TexFormat
->MesaFormat
) {
1597 case MESA_FORMAT_RGB
:
1598 case MESA_FORMAT_RGB888
:
1599 /*case MESA_FORMAT_BGR888:*/
1600 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1601 NULL
, rgba
+ minStart
);
1603 case MESA_FORMAT_RGBA
:
1604 case MESA_FORMAT_RGBA8888
:
1605 case MESA_FORMAT_ARGB8888
:
1606 /*case MESA_FORMAT_ABGR8888:*/
1607 /*case MESA_FORMAT_BGRA8888:*/
1608 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1609 NULL
, rgba
+ minStart
);
1612 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1613 NULL
, rgba
+ minStart
);
1617 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1618 NULL
, rgba
+ minStart
);
1622 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1623 NULL
, rgba
+ minStart
);
1625 case GL_NEAREST_MIPMAP_NEAREST
:
1626 sample_2d_nearest_mipmap_nearest(ctx
, tObj
, m
,
1627 texcoords
+ minStart
,
1628 lambda
+ minStart
, rgba
+ minStart
);
1630 case GL_LINEAR_MIPMAP_NEAREST
:
1631 sample_2d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1632 lambda
+ minStart
, rgba
+ minStart
);
1634 case GL_NEAREST_MIPMAP_LINEAR
:
1635 sample_2d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1636 lambda
+ minStart
, rgba
+ minStart
);
1638 case GL_LINEAR_MIPMAP_LINEAR
:
1639 if (repeatNoBorderPOT
)
1640 sample_2d_linear_mipmap_linear_repeat(ctx
, tObj
, m
,
1641 texcoords
+ minStart
, lambda
+ minStart
, rgba
+ minStart
);
1643 sample_2d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1644 lambda
+ minStart
, rgba
+ minStart
);
1647 _mesa_problem(ctx
, "Bad min filter in sample_2d_texture");
1652 if (magStart
< magEnd
) {
1653 /* do the magnified texels */
1654 const GLuint m
= magEnd
- magStart
;
1656 switch (tObj
->MagFilter
) {
1658 if (repeatNoBorderPOT
) {
1659 switch (tImg
->TexFormat
->MesaFormat
) {
1660 case MESA_FORMAT_RGB
:
1661 case MESA_FORMAT_RGB888
:
1662 /*case MESA_FORMAT_BGR888:*/
1663 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1664 NULL
, rgba
+ magStart
);
1666 case MESA_FORMAT_RGBA
:
1667 case MESA_FORMAT_RGBA8888
:
1668 case MESA_FORMAT_ARGB8888
:
1669 /*case MESA_FORMAT_ABGR8888:*/
1670 /*case MESA_FORMAT_BGRA8888:*/
1671 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1672 NULL
, rgba
+ magStart
);
1675 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1676 NULL
, rgba
+ magStart
);
1680 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1681 NULL
, rgba
+ magStart
);
1685 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1686 NULL
, rgba
+ magStart
);
1689 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_2d");
1696 /**********************************************************************/
1697 /* 3-D Texture Sampling Functions */
1698 /**********************************************************************/
1701 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1704 sample_3d_nearest(GLcontext
*ctx
,
1705 const struct gl_texture_object
*tObj
,
1706 const struct gl_texture_image
*img
,
1707 const GLfloat texcoord
[4],
1710 const GLint width
= img
->Width2
; /* without border, power of two */
1711 const GLint height
= img
->Height2
; /* without border, power of two */
1712 const GLint depth
= img
->Depth2
; /* without border, power of two */
1715 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
1716 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
1717 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapR
, texcoord
[2], depth
, k
);
1719 if (i
< 0 || i
>= (GLint
) img
->Width
||
1720 j
< 0 || j
>= (GLint
) img
->Height
||
1721 k
< 0 || k
>= (GLint
) img
->Depth
) {
1722 /* Need this test for GL_CLAMP_TO_BORDER mode */
1723 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
1726 img
->FetchTexelc(img
, i
, j
, k
, rgba
);
1727 if (img
->Format
== GL_COLOR_INDEX
) {
1728 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
1736 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1739 sample_3d_linear(GLcontext
*ctx
,
1740 const struct gl_texture_object
*tObj
,
1741 const struct gl_texture_image
*img
,
1742 const GLfloat texcoord
[4],
1745 const GLint width
= img
->Width2
;
1746 const GLint height
= img
->Height2
;
1747 const GLint depth
= img
->Depth2
;
1748 GLint i0
, j0
, k0
, i1
, j1
, k1
;
1749 GLuint useBorderColor
;
1752 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1753 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1754 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapR
, texcoord
[2], w
, depth
, k0
, k1
);
1766 /* check if sampling texture border color */
1767 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1768 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1769 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1770 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1771 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
1772 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
1776 const GLfloat a
= FRAC(u
);
1777 const GLfloat b
= FRAC(v
);
1778 const GLfloat c
= FRAC(w
);
1780 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1781 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1782 GLfloat w000
= (1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
);
1783 GLfloat w100
= a
* (1.0F
-b
) * (1.0F
-c
);
1784 GLfloat w010
= (1.0F
-a
) * b
* (1.0F
-c
);
1785 GLfloat w110
= a
* b
* (1.0F
-c
);
1786 GLfloat w001
= (1.0F
-a
) * (1.0F
-b
) * c
;
1787 GLfloat w101
= a
* (1.0F
-b
) * c
;
1788 GLfloat w011
= (1.0F
-a
) * b
* c
;
1789 GLfloat w111
= a
* b
* c
;
1790 #else /* CHAN_BITS == 8 */
1791 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1792 GLint w000
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1793 GLint w100
= IROUND_POS( a
* (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1794 GLint w010
= IROUND_POS((1.0F
-a
) * b
* (1.0F
-c
) * WEIGHT_SCALE
);
1795 GLint w110
= IROUND_POS( a
* b
* (1.0F
-c
) * WEIGHT_SCALE
);
1796 GLint w001
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * c
* WEIGHT_SCALE
);
1797 GLint w101
= IROUND_POS( a
* (1.0F
-b
) * c
* WEIGHT_SCALE
);
1798 GLint w011
= IROUND_POS((1.0F
-a
) * b
* c
* WEIGHT_SCALE
);
1799 GLint w111
= IROUND_POS( a
* b
* c
* WEIGHT_SCALE
);
1802 GLchan t000
[4], t010
[4], t001
[4], t011
[4];
1803 GLchan t100
[4], t110
[4], t101
[4], t111
[4];
1805 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
1806 COPY_CHAN4(t000
, tObj
->_BorderChan
);
1809 img
->FetchTexelc(img
, i0
, j0
, k0
, t000
);
1810 if (img
->Format
== GL_COLOR_INDEX
) {
1811 palette_sample(ctx
, tObj
, t000
[0], t000
);
1814 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
1815 COPY_CHAN4(t100
, tObj
->_BorderChan
);
1818 img
->FetchTexelc(img
, i1
, j0
, k0
, t100
);
1819 if (img
->Format
== GL_COLOR_INDEX
) {
1820 palette_sample(ctx
, tObj
, t100
[0], t100
);
1823 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
1824 COPY_CHAN4(t010
, tObj
->_BorderChan
);
1827 img
->FetchTexelc(img
, i0
, j1
, k0
, t010
);
1828 if (img
->Format
== GL_COLOR_INDEX
) {
1829 palette_sample(ctx
, tObj
, t010
[0], t010
);
1832 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
1833 COPY_CHAN4(t110
, tObj
->_BorderChan
);
1836 img
->FetchTexelc(img
, i1
, j1
, k0
, t110
);
1837 if (img
->Format
== GL_COLOR_INDEX
) {
1838 palette_sample(ctx
, tObj
, t110
[0], t110
);
1842 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
1843 COPY_CHAN4(t001
, tObj
->_BorderChan
);
1846 img
->FetchTexelc(img
, i0
, j0
, k1
, t001
);
1847 if (img
->Format
== GL_COLOR_INDEX
) {
1848 palette_sample(ctx
, tObj
, t001
[0], t001
);
1851 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
1852 COPY_CHAN4(t101
, tObj
->_BorderChan
);
1855 img
->FetchTexelc(img
, i1
, j0
, k1
, t101
);
1856 if (img
->Format
== GL_COLOR_INDEX
) {
1857 palette_sample(ctx
, tObj
, t101
[0], t101
);
1860 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
1861 COPY_CHAN4(t011
, tObj
->_BorderChan
);
1864 img
->FetchTexelc(img
, i0
, j1
, k1
, t011
);
1865 if (img
->Format
== GL_COLOR_INDEX
) {
1866 palette_sample(ctx
, tObj
, t011
[0], t011
);
1869 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
1870 COPY_CHAN4(t111
, tObj
->_BorderChan
);
1873 img
->FetchTexelc(img
, i1
, j1
, k1
, t111
);
1874 if (img
->Format
== GL_COLOR_INDEX
) {
1875 palette_sample(ctx
, tObj
, t111
[0], t111
);
1879 #if CHAN_TYPE == GL_FLOAT
1880 rgba
[0] = w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1881 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0];
1882 rgba
[1] = w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1883 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1];
1884 rgba
[2] = w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1885 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2];
1886 rgba
[3] = w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1887 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3];
1888 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1889 rgba
[0] = (GLchan
) (w000
*t000
[0] + w010
*t010
[0] +
1890 w001
*t001
[0] + w011
*t011
[0] +
1891 w100
*t100
[0] + w110
*t110
[0] +
1892 w101
*t101
[0] + w111
*t111
[0] + 0.5);
1893 rgba
[1] = (GLchan
) (w000
*t000
[1] + w010
*t010
[1] +
1894 w001
*t001
[1] + w011
*t011
[1] +
1895 w100
*t100
[1] + w110
*t110
[1] +
1896 w101
*t101
[1] + w111
*t111
[1] + 0.5);
1897 rgba
[2] = (GLchan
) (w000
*t000
[2] + w010
*t010
[2] +
1898 w001
*t001
[2] + w011
*t011
[2] +
1899 w100
*t100
[2] + w110
*t110
[2] +
1900 w101
*t101
[2] + w111
*t111
[2] + 0.5);
1901 rgba
[3] = (GLchan
) (w000
*t000
[3] + w010
*t010
[3] +
1902 w001
*t001
[3] + w011
*t011
[3] +
1903 w100
*t100
[3] + w110
*t110
[3] +
1904 w101
*t101
[3] + w111
*t111
[3] + 0.5);
1905 #else /* CHAN_BITS == 8 */
1906 rgba
[0] = (GLchan
) (
1907 (w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1908 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0] )
1910 rgba
[1] = (GLchan
) (
1911 (w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1912 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1] )
1914 rgba
[2] = (GLchan
) (
1915 (w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1916 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2] )
1918 rgba
[3] = (GLchan
) (
1919 (w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1920 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3] )
1930 sample_3d_nearest_mipmap_nearest(GLcontext
*ctx
,
1931 const struct gl_texture_object
*tObj
,
1932 GLuint n
, const GLfloat texcoord
[][4],
1933 const GLfloat lambda
[], GLchan rgba
[][4] )
1936 for (i
= 0; i
< n
; i
++) {
1938 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1939 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1945 sample_3d_linear_mipmap_nearest(GLcontext
*ctx
,
1946 const struct gl_texture_object
*tObj
,
1947 GLuint n
, const GLfloat texcoord
[][4],
1948 const GLfloat lambda
[], GLchan rgba
[][4])
1951 ASSERT(lambda
!= NULL
);
1952 for (i
= 0; i
< n
; i
++) {
1954 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1955 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1961 sample_3d_nearest_mipmap_linear(GLcontext
*ctx
,
1962 const struct gl_texture_object
*tObj
,
1963 GLuint n
, const GLfloat texcoord
[][4],
1964 const GLfloat lambda
[], GLchan rgba
[][4])
1967 ASSERT(lambda
!= NULL
);
1968 for (i
= 0; i
< n
; i
++) {
1970 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1971 if (level
>= tObj
->_MaxLevel
) {
1972 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1973 texcoord
[i
], rgba
[i
]);
1976 GLchan t0
[4], t1
[4]; /* texels */
1977 const GLfloat f
= FRAC(lambda
[i
]);
1978 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1979 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1980 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1981 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1982 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1983 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1990 sample_3d_linear_mipmap_linear(GLcontext
*ctx
,
1991 const struct gl_texture_object
*tObj
,
1992 GLuint n
, const GLfloat texcoord
[][4],
1993 const GLfloat lambda
[], GLchan rgba
[][4])
1996 ASSERT(lambda
!= NULL
);
1997 for (i
= 0; i
< n
; i
++) {
1999 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2000 if (level
>= tObj
->_MaxLevel
) {
2001 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
2002 texcoord
[i
], rgba
[i
]);
2005 GLchan t0
[4], t1
[4]; /* texels */
2006 const GLfloat f
= FRAC(lambda
[i
]);
2007 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
2008 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
2009 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
2010 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
2011 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
2012 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
2019 sample_nearest_3d(GLcontext
*ctx
, GLuint texUnit
,
2020 const struct gl_texture_object
*tObj
, GLuint n
,
2021 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2025 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
2028 sample_3d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
2035 sample_linear_3d( GLcontext
*ctx
, GLuint texUnit
,
2036 const struct gl_texture_object
*tObj
, GLuint n
,
2037 const GLfloat texcoords
[][4],
2038 const GLfloat lambda
[], GLchan rgba
[][4] )
2041 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
2044 sample_3d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
2050 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
2051 * return a texture sample.
2054 sample_lambda_3d( GLcontext
*ctx
, GLuint texUnit
,
2055 const struct gl_texture_object
*tObj
, GLuint n
,
2056 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2059 GLuint minStart
, minEnd
; /* texels with minification */
2060 GLuint magStart
, magEnd
; /* texels with magnification */
2063 ASSERT(lambda
!= NULL
);
2064 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2065 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2067 if (minStart
< minEnd
) {
2068 /* do the minified texels */
2069 GLuint m
= minEnd
- minStart
;
2070 switch (tObj
->MinFilter
) {
2072 for (i
= minStart
; i
< minEnd
; i
++)
2073 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2074 texcoords
[i
], rgba
[i
]);
2077 for (i
= minStart
; i
< minEnd
; i
++)
2078 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2079 texcoords
[i
], rgba
[i
]);
2081 case GL_NEAREST_MIPMAP_NEAREST
:
2082 sample_3d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
2083 lambda
+ minStart
, rgba
+ minStart
);
2085 case GL_LINEAR_MIPMAP_NEAREST
:
2086 sample_3d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
2087 lambda
+ minStart
, rgba
+ minStart
);
2089 case GL_NEAREST_MIPMAP_LINEAR
:
2090 sample_3d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
2091 lambda
+ minStart
, rgba
+ minStart
);
2093 case GL_LINEAR_MIPMAP_LINEAR
:
2094 sample_3d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
2095 lambda
+ minStart
, rgba
+ minStart
);
2098 _mesa_problem(ctx
, "Bad min filter in sample_3d_texture");
2103 if (magStart
< magEnd
) {
2104 /* do the magnified texels */
2105 switch (tObj
->MagFilter
) {
2107 for (i
= magStart
; i
< magEnd
; i
++)
2108 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2109 texcoords
[i
], rgba
[i
]);
2112 for (i
= magStart
; i
< magEnd
; i
++)
2113 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2114 texcoords
[i
], rgba
[i
]);
2117 _mesa_problem(ctx
, "Bad mag filter in sample_3d_texture");
2124 /**********************************************************************/
2125 /* Texture Cube Map Sampling Functions */
2126 /**********************************************************************/
2129 * Choose one of six sides of a texture cube map given the texture
2130 * coord (rx,ry,rz). Return pointer to corresponding array of texture
2133 static const struct gl_texture_image
**
2134 choose_cube_face(const struct gl_texture_object
*texObj
,
2135 const GLfloat texcoord
[4], GLfloat newCoord
[4])
2139 direction target sc tc ma
2140 ---------- ------------------------------- --- --- ---
2141 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
2142 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
2143 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
2144 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
2145 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
2146 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
2148 const GLfloat rx
= texcoord
[0];
2149 const GLfloat ry
= texcoord
[1];
2150 const GLfloat rz
= texcoord
[2];
2151 const struct gl_texture_image
**imgArray
;
2152 const GLfloat arx
= FABSF(rx
), ary
= FABSF(ry
), arz
= FABSF(rz
);
2155 if (arx
> ary
&& arx
> arz
) {
2157 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_POS_X
];
2163 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_NEG_X
];
2169 else if (ary
> arx
&& ary
> arz
) {
2171 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_POS_Y
];
2177 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_NEG_Y
];
2185 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_POS_Z
];
2191 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_NEG_Z
];
2198 newCoord
[0] = ( sc
/ ma
+ 1.0F
) * 0.5F
;
2199 newCoord
[1] = ( tc
/ ma
+ 1.0F
) * 0.5F
;
2205 sample_nearest_cube(GLcontext
*ctx
, GLuint texUnit
,
2206 const struct gl_texture_object
*tObj
, GLuint n
,
2207 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2212 for (i
= 0; i
< n
; i
++) {
2213 const struct gl_texture_image
**images
;
2214 GLfloat newCoord
[4];
2215 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
2216 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
2223 sample_linear_cube(GLcontext
*ctx
, GLuint texUnit
,
2224 const struct gl_texture_object
*tObj
, GLuint n
,
2225 const GLfloat texcoords
[][4],
2226 const GLfloat lambda
[], GLchan rgba
[][4])
2230 for (i
= 0; i
< n
; i
++) {
2231 const struct gl_texture_image
**images
;
2232 GLfloat newCoord
[4];
2233 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
2234 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
2241 sample_cube_nearest_mipmap_nearest(GLcontext
*ctx
, GLuint texUnit
,
2242 const struct gl_texture_object
*tObj
,
2243 GLuint n
, const GLfloat texcoord
[][4],
2244 const GLfloat lambda
[], GLchan rgba
[][4])
2247 ASSERT(lambda
!= NULL
);
2248 for (i
= 0; i
< n
; i
++) {
2249 const struct gl_texture_image
**images
;
2250 GLfloat newCoord
[4];
2252 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2253 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2254 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
2260 sample_cube_linear_mipmap_nearest(GLcontext
*ctx
, GLuint texUnit
,
2261 const struct gl_texture_object
*tObj
,
2262 GLuint n
, const GLfloat texcoord
[][4],
2263 const GLfloat lambda
[], GLchan rgba
[][4])
2266 ASSERT(lambda
!= NULL
);
2267 for (i
= 0; i
< n
; i
++) {
2268 const struct gl_texture_image
**images
;
2269 GLfloat newCoord
[4];
2271 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2272 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2273 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
2279 sample_cube_nearest_mipmap_linear(GLcontext
*ctx
, GLuint texUnit
,
2280 const struct gl_texture_object
*tObj
,
2281 GLuint n
, const GLfloat texcoord
[][4],
2282 const GLfloat lambda
[], GLchan rgba
[][4])
2285 ASSERT(lambda
!= NULL
);
2286 for (i
= 0; i
< n
; i
++) {
2287 const struct gl_texture_image
**images
;
2288 GLfloat newCoord
[4];
2290 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2291 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2292 if (level
>= tObj
->_MaxLevel
) {
2293 sample_2d_nearest(ctx
, tObj
, images
[tObj
->_MaxLevel
],
2297 GLchan t0
[4], t1
[4]; /* texels */
2298 const GLfloat f
= FRAC(lambda
[i
]);
2299 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, t0
);
2300 sample_2d_nearest(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
2301 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
2302 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
2303 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
2304 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
2311 sample_cube_linear_mipmap_linear(GLcontext
*ctx
, GLuint texUnit
,
2312 const struct gl_texture_object
*tObj
,
2313 GLuint n
, const GLfloat texcoord
[][4],
2314 const GLfloat lambda
[], GLchan rgba
[][4])
2317 ASSERT(lambda
!= NULL
);
2318 for (i
= 0; i
< n
; i
++) {
2319 const struct gl_texture_image
**images
;
2320 GLfloat newCoord
[4];
2322 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2323 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2324 if (level
>= tObj
->_MaxLevel
) {
2325 sample_2d_linear(ctx
, tObj
, images
[tObj
->_MaxLevel
],
2329 GLchan t0
[4], t1
[4];
2330 const GLfloat f
= FRAC(lambda
[i
]);
2331 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, t0
);
2332 sample_2d_linear(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
2333 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
2334 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
2335 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
2336 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
2343 sample_lambda_cube( GLcontext
*ctx
, GLuint texUnit
,
2344 const struct gl_texture_object
*tObj
, GLuint n
,
2345 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2348 GLuint minStart
, minEnd
; /* texels with minification */
2349 GLuint magStart
, magEnd
; /* texels with magnification */
2351 ASSERT(lambda
!= NULL
);
2352 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2353 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2355 if (minStart
< minEnd
) {
2356 /* do the minified texels */
2357 const GLuint m
= minEnd
- minStart
;
2358 switch (tObj
->MinFilter
) {
2360 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2361 lambda
+ minStart
, rgba
+ minStart
);
2364 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2365 lambda
+ minStart
, rgba
+ minStart
);
2367 case GL_NEAREST_MIPMAP_NEAREST
:
2368 sample_cube_nearest_mipmap_nearest(ctx
, texUnit
, tObj
, m
,
2369 texcoords
+ minStart
,
2370 lambda
+ minStart
, rgba
+ minStart
);
2372 case GL_LINEAR_MIPMAP_NEAREST
:
2373 sample_cube_linear_mipmap_nearest(ctx
, texUnit
, tObj
, m
,
2374 texcoords
+ minStart
,
2375 lambda
+ minStart
, rgba
+ minStart
);
2377 case GL_NEAREST_MIPMAP_LINEAR
:
2378 sample_cube_nearest_mipmap_linear(ctx
, texUnit
, tObj
, m
,
2379 texcoords
+ minStart
,
2380 lambda
+ minStart
, rgba
+ minStart
);
2382 case GL_LINEAR_MIPMAP_LINEAR
:
2383 sample_cube_linear_mipmap_linear(ctx
, texUnit
, tObj
, m
,
2384 texcoords
+ minStart
,
2385 lambda
+ minStart
, rgba
+ minStart
);
2388 _mesa_problem(ctx
, "Bad min filter in sample_lambda_cube");
2392 if (magStart
< magEnd
) {
2393 /* do the magnified texels */
2394 const GLuint m
= magEnd
- magStart
;
2395 switch (tObj
->MagFilter
) {
2397 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2398 lambda
+ magStart
, rgba
+ magStart
);
2401 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2402 lambda
+ magStart
, rgba
+ magStart
);
2405 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_cube");
2411 /**********************************************************************/
2412 /* Texture Rectangle Sampling Functions */
2413 /**********************************************************************/
2416 sample_nearest_rect(GLcontext
*ctx
, GLuint texUnit
,
2417 const struct gl_texture_object
*tObj
, GLuint n
,
2418 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2421 const struct gl_texture_image
*img
= tObj
->Image
[0][0];
2422 const GLfloat width
= (GLfloat
) img
->Width
;
2423 const GLfloat height
= (GLfloat
) img
->Height
;
2424 const GLint width_minus_1
= img
->Width
- 1;
2425 const GLint height_minus_1
= img
->Height
- 1;
2431 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2432 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2433 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2434 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2435 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2436 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2437 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2439 /* XXX move Wrap mode tests outside of loops for common cases */
2440 for (i
= 0; i
< n
; i
++) {
2442 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2443 if (tObj
->WrapS
== GL_CLAMP
) {
2444 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.0F
, width
) );
2446 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2447 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
) );
2450 col
= IFLOOR( CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
) );
2452 if (tObj
->WrapT
== GL_CLAMP
) {
2453 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.0F
, height
) );
2455 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2456 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
) );
2459 row
= IFLOOR( CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
) );
2462 col
= CLAMP(col
, 0, width_minus_1
);
2463 row
= CLAMP(row
, 0, height_minus_1
);
2465 img
->FetchTexelc(img
, col
, row
, 0, rgba
[i
]);
2471 sample_linear_rect(GLcontext
*ctx
, GLuint texUnit
,
2472 const struct gl_texture_object
*tObj
, GLuint n
,
2473 const GLfloat texcoords
[][4],
2474 const GLfloat lambda
[], GLchan rgba
[][4])
2476 const struct gl_texture_image
*img
= tObj
->Image
[0][0];
2477 const GLfloat width
= (GLfloat
) img
->Width
;
2478 const GLfloat height
= (GLfloat
) img
->Height
;
2479 const GLint width_minus_1
= img
->Width
- 1;
2480 const GLint height_minus_1
= img
->Height
- 1;
2486 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2487 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2488 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2489 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2490 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2491 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2492 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2494 /* XXX lots of opportunity for optimization in this loop */
2495 for (i
= 0; i
< n
; i
++) {
2497 GLint row0
, col0
, row1
, col1
;
2498 GLchan t00
[4], t01
[4], t10
[4], t11
[4];
2499 GLfloat a
, b
, w00
, w01
, w10
, w11
;
2501 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2502 if (tObj
->WrapS
== GL_CLAMP
) {
2503 fcol
= CLAMP(texcoords
[i
][0], 0.0F
, width
);
2505 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2506 fcol
= CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
);
2509 fcol
= CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
);
2511 if (tObj
->WrapT
== GL_CLAMP
) {
2512 frow
= CLAMP(texcoords
[i
][1], 0.0F
, height
);
2514 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2515 frow
= CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
);
2518 frow
= CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
);
2521 /* compute integer rows/columns */
2522 col0
= IFLOOR(fcol
);
2524 col0
= CLAMP(col0
, 0, width_minus_1
);
2525 col1
= CLAMP(col1
, 0, width_minus_1
);
2526 row0
= IFLOOR(frow
);
2528 row0
= CLAMP(row0
, 0, height_minus_1
);
2529 row1
= CLAMP(row1
, 0, height_minus_1
);
2531 /* get four texel samples */
2532 img
->FetchTexelc(img
, col0
, row0
, 0, t00
);
2533 img
->FetchTexelc(img
, col1
, row0
, 0, t10
);
2534 img
->FetchTexelc(img
, col0
, row1
, 0, t01
);
2535 img
->FetchTexelc(img
, col1
, row1
, 0, t11
);
2537 /* compute sample weights */
2540 w00
= (1.0F
-a
) * (1.0F
-b
);
2542 w01
= (1.0F
-a
) * b
;
2545 /* compute weighted average of samples */
2547 (GLchan
) (w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0]);
2549 (GLchan
) (w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1]);
2551 (GLchan
) (w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2]);
2553 (GLchan
) (w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3]);
2559 sample_lambda_rect( GLcontext
*ctx
, GLuint texUnit
,
2560 const struct gl_texture_object
*tObj
, GLuint n
,
2561 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2564 GLuint minStart
, minEnd
, magStart
, magEnd
;
2566 /* We only need lambda to decide between minification and magnification.
2567 * There is no mipmapping with rectangular textures.
2569 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2570 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2572 if (minStart
< minEnd
) {
2573 if (tObj
->MinFilter
== GL_NEAREST
) {
2574 sample_nearest_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2575 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2578 sample_linear_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2579 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2582 if (magStart
< magEnd
) {
2583 if (tObj
->MagFilter
== GL_NEAREST
) {
2584 sample_nearest_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2585 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2588 sample_linear_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2589 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2597 * Sample a shadow/depth texture.
2600 sample_depth_texture( GLcontext
*ctx
, GLuint unit
,
2601 const struct gl_texture_object
*tObj
, GLuint n
,
2602 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2605 const GLint baseLevel
= tObj
->BaseLevel
;
2606 const struct gl_texture_image
*texImage
= tObj
->Image
[0][baseLevel
];
2607 const GLuint width
= texImage
->Width
;
2608 const GLuint height
= texImage
->Height
;
2615 ASSERT(tObj
->Image
[0][tObj
->BaseLevel
]->Format
== GL_DEPTH_COMPONENT
);
2616 ASSERT(tObj
->Target
== GL_TEXTURE_1D
||
2617 tObj
->Target
== GL_TEXTURE_2D
||
2618 tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
2620 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2622 /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
2624 /* XXX this could be precomputed and saved in the texture object */
2625 if (tObj
->CompareFlag
) {
2626 /* GL_SGIX_shadow */
2627 if (tObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2628 function
= GL_LEQUAL
;
2631 ASSERT(tObj
->CompareOperator
== GL_TEXTURE_GEQUAL_R_SGIX
);
2632 function
= GL_GEQUAL
;
2635 else if (tObj
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
) {
2637 function
= tObj
->CompareFunc
;
2640 function
= GL_NONE
; /* pass depth through as grayscale */
2643 if (tObj
->MagFilter
== GL_NEAREST
) {
2645 for (i
= 0; i
< n
; i
++) {
2646 GLfloat depthSample
;
2648 /* XXX fix for texture rectangle! */
2649 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoords
[i
][0], width
, col
);
2650 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoords
[i
][1], height
, row
);
2651 texImage
->FetchTexelf(texImage
, col
, row
, 0, &depthSample
);
2655 result
= (texcoords
[i
][2] <= depthSample
) ? CHAN_MAX
: ambient
;
2658 result
= (texcoords
[i
][2] >= depthSample
) ? CHAN_MAX
: ambient
;
2661 result
= (texcoords
[i
][2] < depthSample
) ? CHAN_MAX
: ambient
;
2664 result
= (texcoords
[i
][2] > depthSample
) ? CHAN_MAX
: ambient
;
2667 result
= (texcoords
[i
][2] == depthSample
) ? CHAN_MAX
: ambient
;
2670 result
= (texcoords
[i
][2] != depthSample
) ? CHAN_MAX
: ambient
;
2679 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2682 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2686 switch (tObj
->DepthMode
) {
2688 texel
[i
][RCOMP
] = result
;
2689 texel
[i
][GCOMP
] = result
;
2690 texel
[i
][BCOMP
] = result
;
2691 texel
[i
][ACOMP
] = CHAN_MAX
;
2694 texel
[i
][RCOMP
] = result
;
2695 texel
[i
][GCOMP
] = result
;
2696 texel
[i
][BCOMP
] = result
;
2697 texel
[i
][ACOMP
] = result
;
2700 texel
[i
][RCOMP
] = 0;
2701 texel
[i
][GCOMP
] = 0;
2702 texel
[i
][BCOMP
] = 0;
2703 texel
[i
][ACOMP
] = result
;
2706 _mesa_problem(ctx
, "Bad depth texture mode");
2712 ASSERT(tObj
->MagFilter
== GL_LINEAR
);
2713 for (i
= 0; i
< n
; i
++) {
2714 GLfloat depth00
, depth01
, depth10
, depth11
;
2715 GLint i0
, i1
, j0
, j1
;
2717 GLuint useBorderTexel
;
2719 /* XXX fix for texture rectangle! */
2720 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoords
[i
][0], u
, width
, i0
, i1
);
2721 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoords
[i
][1], v
, height
,j0
, j1
);
2724 if (texImage
->Border
) {
2725 i0
+= texImage
->Border
;
2726 i1
+= texImage
->Border
;
2727 j0
+= texImage
->Border
;
2728 j1
+= texImage
->Border
;
2731 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
2732 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
2733 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
2734 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
2737 /* get four depth samples from the texture */
2738 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
2742 texImage
->FetchTexelf(texImage
, i0
, j0
, 0, &depth00
);
2744 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
2748 texImage
->FetchTexelf(texImage
, i1
, j0
, 0, &depth10
);
2750 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
2754 texImage
->FetchTexelf(texImage
, i0
, j1
, 0, &depth01
);
2756 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
2760 texImage
->FetchTexelf(texImage
, i1
, j1
, 0, &depth11
);
2764 /* compute a single weighted depth sample and do one comparison */
2765 const GLfloat a
= FRAC(u
+ 1.0F
);
2766 const GLfloat b
= FRAC(v
+ 1.0F
);
2767 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2768 const GLfloat w10
= ( a
) * (1.0F
- b
);
2769 const GLfloat w01
= (1.0F
- a
) * ( b
);
2770 const GLfloat w11
= ( a
) * ( b
);
2771 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2772 + w01
* depth01
+ w11
* depth11
;
2773 if ((depthSample
<= texcoords
[i
][2] && function
== GL_LEQUAL
) ||
2774 (depthSample
>= texcoords
[i
][2] && function
== GL_GEQUAL
)) {
2782 /* Do four depth/R comparisons and compute a weighted result.
2783 * If this touches on somebody's I.P., I'll remove this code
2786 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
2787 GLfloat luminance
= CHAN_MAXF
;
2791 if (depth00
<= texcoords
[i
][2]) luminance
-= d
;
2792 if (depth01
<= texcoords
[i
][2]) luminance
-= d
;
2793 if (depth10
<= texcoords
[i
][2]) luminance
-= d
;
2794 if (depth11
<= texcoords
[i
][2]) luminance
-= d
;
2795 result
= (GLchan
) luminance
;
2798 if (depth00
>= texcoords
[i
][2]) luminance
-= d
;
2799 if (depth01
>= texcoords
[i
][2]) luminance
-= d
;
2800 if (depth10
>= texcoords
[i
][2]) luminance
-= d
;
2801 if (depth11
>= texcoords
[i
][2]) luminance
-= d
;
2802 result
= (GLchan
) luminance
;
2805 if (depth00
< texcoords
[i
][2]) luminance
-= d
;
2806 if (depth01
< texcoords
[i
][2]) luminance
-= d
;
2807 if (depth10
< texcoords
[i
][2]) luminance
-= d
;
2808 if (depth11
< texcoords
[i
][2]) luminance
-= d
;
2809 result
= (GLchan
) luminance
;
2812 if (depth00
> texcoords
[i
][2]) luminance
-= d
;
2813 if (depth01
> texcoords
[i
][2]) luminance
-= d
;
2814 if (depth10
> texcoords
[i
][2]) luminance
-= d
;
2815 if (depth11
> texcoords
[i
][2]) luminance
-= d
;
2816 result
= (GLchan
) luminance
;
2819 if (depth00
== texcoords
[i
][2]) luminance
-= d
;
2820 if (depth01
== texcoords
[i
][2]) luminance
-= d
;
2821 if (depth10
== texcoords
[i
][2]) luminance
-= d
;
2822 if (depth11
== texcoords
[i
][2]) luminance
-= d
;
2823 result
= (GLchan
) luminance
;
2826 if (depth00
!= texcoords
[i
][2]) luminance
-= d
;
2827 if (depth01
!= texcoords
[i
][2]) luminance
-= d
;
2828 if (depth10
!= texcoords
[i
][2]) luminance
-= d
;
2829 if (depth11
!= texcoords
[i
][2]) luminance
-= d
;
2830 result
= (GLchan
) luminance
;
2839 /* ordinary bilinear filtering */
2841 const GLfloat a
= FRAC(u
+ 1.0F
);
2842 const GLfloat b
= FRAC(v
+ 1.0F
);
2843 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2844 const GLfloat w10
= ( a
) * (1.0F
- b
);
2845 const GLfloat w01
= (1.0F
- a
) * ( b
);
2846 const GLfloat w11
= ( a
) * ( b
);
2847 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2848 + w01
* depth01
+ w11
* depth11
;
2849 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2853 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2858 switch (tObj
->DepthMode
) {
2860 texel
[i
][RCOMP
] = result
;
2861 texel
[i
][GCOMP
] = result
;
2862 texel
[i
][BCOMP
] = result
;
2863 texel
[i
][ACOMP
] = CHAN_MAX
;
2866 texel
[i
][RCOMP
] = result
;
2867 texel
[i
][GCOMP
] = result
;
2868 texel
[i
][BCOMP
] = result
;
2869 texel
[i
][ACOMP
] = result
;
2872 texel
[i
][RCOMP
] = 0;
2873 texel
[i
][GCOMP
] = 0;
2874 texel
[i
][BCOMP
] = 0;
2875 texel
[i
][ACOMP
] = result
;
2878 _mesa_problem(ctx
, "Bad depth texture mode");
2887 * Experimental depth texture sampling function.
2890 sample_depth_texture2(const GLcontext
*ctx
,
2891 const struct gl_texture_unit
*texUnit
,
2892 GLuint n
, const GLfloat texcoords
[][4],
2895 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2896 const GLint baseLevel
= texObj
->BaseLevel
;
2897 const struct gl_texture_image
*texImage
= texObj
->Image
[0][baseLevel
];
2898 const GLuint width
= texImage
->Width
;
2899 const GLuint height
= texImage
->Height
;
2901 GLboolean lequal
, gequal
;
2903 if (texObj
->Target
!= GL_TEXTURE_2D
) {
2904 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2908 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2909 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2913 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2914 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2915 * isn't a depth texture.
2917 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2918 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2922 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2924 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2935 for (i
= 0; i
< n
; i
++) {
2937 GLint col
, row
, ii
, jj
, imin
, imax
, jmin
, jmax
, samples
, count
;
2940 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, texcoords
[i
][0],
2942 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, texcoords
[i
][1],
2950 if (imin
< 0) imin
= 0;
2951 if (imax
>= width
) imax
= width
- 1;
2952 if (jmin
< 0) jmin
= 0;
2953 if (jmax
>= height
) jmax
= height
- 1;
2955 samples
= (imax
- imin
+ 1) * (jmax
- jmin
+ 1);
2957 for (jj
= jmin
; jj
<= jmax
; jj
++) {
2958 for (ii
= imin
; ii
<= imax
; ii
++) {
2959 GLfloat depthSample
;
2960 texImage
->FetchTexelf(texImage
, ii
, jj
, 0, &depthSample
);
2961 if ((depthSample
<= r
[i
] && lequal
) ||
2962 (depthSample
>= r
[i
] && gequal
)) {
2968 w
= (GLfloat
) count
/ (GLfloat
) samples
;
2969 w
= CHAN_MAXF
- w
* (CHAN_MAXF
- (GLfloat
) ambient
);
2972 texel
[i
][RCOMP
] = lum
;
2973 texel
[i
][GCOMP
] = lum
;
2974 texel
[i
][BCOMP
] = lum
;
2975 texel
[i
][ACOMP
] = CHAN_MAX
;
2983 * We use this function when a texture object is in an "incomplete" state.
2984 * When a fragment program attempts to sample an incomplete texture we
2986 * Note: frag progs don't observe texture enable/disable flags.
2989 null_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2990 const struct gl_texture_object
*tObj
, GLuint n
,
2991 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2999 _mesa_bzero(rgba
, n
* 4 * sizeof(GLchan
));
3005 * Setup the texture sampling function for this texture object.
3008 _swrast_choose_texture_sample_func( GLcontext
*ctx
,
3009 const struct gl_texture_object
*t
)
3011 const GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
3012 const GLenum format
= t
->Image
[0][t
->BaseLevel
]->Format
;
3015 return &null_sample_func
;
3018 switch (t
->Target
) {
3020 if (format
== GL_DEPTH_COMPONENT
) {
3021 return &sample_depth_texture
;
3023 else if (needLambda
) {
3024 return &sample_lambda_1d
;
3026 else if (t
->MinFilter
== GL_LINEAR
) {
3027 return &sample_linear_1d
;
3030 ASSERT(t
->MinFilter
== GL_NEAREST
);
3031 return &sample_nearest_1d
;
3035 if (format
== GL_DEPTH_COMPONENT
) {
3036 return &sample_depth_texture
;
3038 else if (needLambda
) {
3039 return &sample_lambda_2d
;
3041 else if (t
->MinFilter
== GL_LINEAR
) {
3042 return &sample_linear_2d
;
3045 GLint baseLevel
= t
->BaseLevel
;
3046 ASSERT(t
->MinFilter
== GL_NEAREST
);
3047 if (t
->WrapS
== GL_REPEAT
&&
3048 t
->WrapT
== GL_REPEAT
&&
3050 t
->Image
[0][baseLevel
]->Border
== 0 &&
3051 t
->Image
[0][baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGB
) {
3052 return &opt_sample_rgb_2d
;
3054 else if (t
->WrapS
== GL_REPEAT
&&
3055 t
->WrapT
== GL_REPEAT
&&
3057 t
->Image
[0][baseLevel
]->Border
== 0 &&
3058 t
->Image
[0][baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGBA
) {
3059 return &opt_sample_rgba_2d
;
3062 return &sample_nearest_2d
;
3068 return &sample_lambda_3d
;
3070 else if (t
->MinFilter
== GL_LINEAR
) {
3071 return &sample_linear_3d
;
3074 ASSERT(t
->MinFilter
== GL_NEAREST
);
3075 return &sample_nearest_3d
;
3078 case GL_TEXTURE_CUBE_MAP
:
3080 return &sample_lambda_cube
;
3082 else if (t
->MinFilter
== GL_LINEAR
) {
3083 return &sample_linear_cube
;
3086 ASSERT(t
->MinFilter
== GL_NEAREST
);
3087 return &sample_nearest_cube
;
3090 case GL_TEXTURE_RECTANGLE_NV
:
3092 return &sample_lambda_rect
;
3094 else if (t
->MinFilter
== GL_LINEAR
) {
3095 return &sample_linear_rect
;
3098 ASSERT(t
->MinFilter
== GL_NEAREST
);
3099 return &sample_nearest_rect
;
3104 "invalid target in _swrast_choose_texture_sample_func");
3105 return &null_sample_func
;
3110 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
3111 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
3115 * Do texture application for GL_ARB/EXT_texture_env_combine.
3116 * This function also supports GL_{EXT,ARB}_texture_env_dot3 and
3117 * GL_ATI_texture_env_combine3. Since "classic" texture environments are
3118 * implemented using GL_ARB_texture_env_combine-like state, this same function
3119 * is used for classic texture environment application as well.
3121 * \param ctx rendering context
3122 * \param textureUnit the texture unit to apply
3123 * \param n number of fragments to process (span width)
3124 * \param primary_rgba incoming fragment color array
3125 * \param texelBuffer pointer to texel colors for all texture units
3127 * \param rgba incoming colors, which get modified here
3130 texture_combine( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
3131 CONST
GLchan (*primary_rgba
)[4],
3132 CONST GLchan
*texelBuffer
,
3135 const struct gl_texture_unit
*textureUnit
= &(ctx
->Texture
.Unit
[unit
]);
3136 const GLchan (*argRGB
[3])[4];
3137 const GLchan (*argA
[3])[4];
3138 const GLuint RGBshift
= textureUnit
->_CurrentCombine
->ScaleShiftRGB
;
3139 const GLuint Ashift
= textureUnit
->_CurrentCombine
->ScaleShiftA
;
3140 #if CHAN_TYPE == GL_FLOAT
3141 const GLchan RGBmult
= (GLfloat
) (1 << RGBshift
);
3142 const GLchan Amult
= (GLfloat
) (1 << Ashift
);
3143 static const GLchan one
[4] = { 1.0, 1.0, 1.0, 1.0 };
3144 static const GLchan zero
[4] = { 0.0, 0.0, 0.0, 0.0 };
3146 const GLint half
= (CHAN_MAX
+ 1) / 2;
3147 static const GLchan one
[4] = { CHAN_MAX
, CHAN_MAX
, CHAN_MAX
, CHAN_MAX
};
3148 static const GLchan zero
[4] = { 0, 0, 0, 0 };
3151 GLuint numColorArgs
;
3152 GLuint numAlphaArgs
;
3154 /* GLchan ccolor[3][4]; */
3155 DEFMNARRAY(GLchan
, ccolor
, 3, 3 * MAX_WIDTH
, 4); /* mac 32k limitation */
3156 CHECKARRAY(ccolor
, return); /* mac 32k limitation */
3158 ASSERT(ctx
->Extensions
.EXT_texture_env_combine
||
3159 ctx
->Extensions
.ARB_texture_env_combine
);
3160 ASSERT(SWRAST_CONTEXT(ctx
)->_AnyTextureCombine
);
3164 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
3165 textureUnit->_CurrentCombine->ModeRGB,
3166 textureUnit->_CurrentCombine->ModeA,
3167 textureUnit->_CurrentCombine->SourceRGB[0],
3168 textureUnit->_CurrentCombine->SourceA[0],
3169 textureUnit->_CurrentCombine->SourceRGB[1],
3170 textureUnit->_CurrentCombine->SourceA[1]);
3174 * Do operand setup for up to 3 operands. Loop over the terms.
3176 numColorArgs
= textureUnit
->_CurrentCombine
->_NumArgsRGB
;
3177 numAlphaArgs
= textureUnit
->_CurrentCombine
->_NumArgsA
;
3179 for (j
= 0; j
< numColorArgs
; j
++) {
3180 const GLenum srcRGB
= textureUnit
->_CurrentCombine
->SourceRGB
[j
];
3185 argRGB
[j
] = (const GLchan (*)[4])
3186 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
3188 case GL_PRIMARY_COLOR
:
3189 argRGB
[j
] = primary_rgba
;
3192 argRGB
[j
] = (const GLchan (*)[4]) rgba
;
3196 GLchan (*c
)[4] = ccolor
[j
];
3197 GLchan red
, green
, blue
, alpha
;
3198 UNCLAMPED_FLOAT_TO_CHAN(red
, textureUnit
->EnvColor
[0]);
3199 UNCLAMPED_FLOAT_TO_CHAN(green
, textureUnit
->EnvColor
[1]);
3200 UNCLAMPED_FLOAT_TO_CHAN(blue
, textureUnit
->EnvColor
[2]);
3201 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
3202 for (i
= 0; i
< n
; i
++) {
3204 c
[i
][GCOMP
] = green
;
3206 c
[i
][ACOMP
] = alpha
;
3208 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3211 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
3220 /* ARB_texture_env_crossbar source */
3222 const GLuint srcUnit
= srcRGB
- GL_TEXTURE0
;
3223 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
3224 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
3226 argRGB
[j
] = (const GLchan (*)[4])
3227 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
3231 if (textureUnit
->_CurrentCombine
->OperandRGB
[j
] != GL_SRC_COLOR
) {
3232 const GLchan (*src
)[4] = argRGB
[j
];
3233 GLchan (*dst
)[4] = ccolor
[j
];
3235 /* point to new arg[j] storage */
3236 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3238 if (textureUnit
->_CurrentCombine
->OperandRGB
[j
] == GL_ONE_MINUS_SRC_COLOR
) {
3239 for (i
= 0; i
< n
; i
++) {
3240 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][RCOMP
];
3241 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][GCOMP
];
3242 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][BCOMP
];
3245 else if (textureUnit
->_CurrentCombine
->OperandRGB
[j
] == GL_SRC_ALPHA
) {
3246 for (i
= 0; i
< n
; i
++) {
3247 dst
[i
][RCOMP
] = src
[i
][ACOMP
];
3248 dst
[i
][GCOMP
] = src
[i
][ACOMP
];
3249 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
3253 ASSERT(textureUnit
->_CurrentCombine
->OperandRGB
[j
] ==GL_ONE_MINUS_SRC_ALPHA
);
3254 for (i
= 0; i
< n
; i
++) {
3255 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3256 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3257 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3264 for (j
= 0; j
< numAlphaArgs
; j
++) {
3265 const GLenum srcA
= textureUnit
->_CurrentCombine
->SourceA
[j
];
3269 argA
[j
] = (const GLchan (*)[4])
3270 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
3272 case GL_PRIMARY_COLOR
:
3273 argA
[j
] = primary_rgba
;
3276 argA
[j
] = (const GLchan (*)[4]) rgba
;
3280 GLchan alpha
, (*c
)[4] = ccolor
[j
];
3281 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
3282 for (i
= 0; i
< n
; i
++)
3283 c
[i
][ACOMP
] = alpha
;
3284 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3287 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
3296 /* ARB_texture_env_crossbar source */
3298 const GLuint srcUnit
= srcA
- GL_TEXTURE0
;
3299 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
3300 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
3302 argA
[j
] = (const GLchan (*)[4])
3303 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
3307 if (textureUnit
->_CurrentCombine
->OperandA
[j
] == GL_ONE_MINUS_SRC_ALPHA
) {
3308 const GLchan (*src
)[4] = argA
[j
];
3309 GLchan (*dst
)[4] = ccolor
[j
];
3310 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3311 for (i
= 0; i
< n
; i
++) {
3312 dst
[i
][ACOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3318 * Do the texture combine.
3320 switch (textureUnit
->_CurrentCombine
->ModeRGB
) {
3323 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3325 for (i
= 0; i
< n
; i
++) {
3326 #if CHAN_TYPE == GL_FLOAT
3327 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * RGBmult
;
3328 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * RGBmult
;
3329 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * RGBmult
;
3331 GLuint r
= (GLuint
) arg0
[i
][RCOMP
] << RGBshift
;
3332 GLuint g
= (GLuint
) arg0
[i
][GCOMP
] << RGBshift
;
3333 GLuint b
= (GLuint
) arg0
[i
][BCOMP
] << RGBshift
;
3334 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3335 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3336 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3341 for (i
= 0; i
< n
; i
++) {
3342 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
];
3343 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
];
3344 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
];
3351 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3352 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3353 #if CHAN_TYPE != GL_FLOAT
3354 const GLint shift
= CHAN_BITS
- RGBshift
;
3356 for (i
= 0; i
< n
; i
++) {
3357 #if CHAN_TYPE == GL_FLOAT
3358 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * RGBmult
;
3359 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * RGBmult
;
3360 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * RGBmult
;
3362 GLuint r
= PROD(arg0
[i
][RCOMP
], arg1
[i
][RCOMP
]) >> shift
;
3363 GLuint g
= PROD(arg0
[i
][GCOMP
], arg1
[i
][GCOMP
]) >> shift
;
3364 GLuint b
= PROD(arg0
[i
][BCOMP
], arg1
[i
][BCOMP
]) >> shift
;
3365 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3366 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3367 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3374 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3375 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3376 for (i
= 0; i
< n
; i
++) {
3377 #if CHAN_TYPE == GL_FLOAT
3378 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * RGBmult
;
3379 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * RGBmult
;
3380 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * RGBmult
;
3382 GLint r
= ((GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3383 GLint g
= ((GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3384 GLint b
= ((GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3385 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3386 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3387 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3394 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3395 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3396 for (i
= 0; i
< n
; i
++) {
3397 #if CHAN_TYPE == GL_FLOAT
3398 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3399 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3400 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3402 GLint r
= (GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
] -half
;
3403 GLint g
= (GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
] -half
;
3404 GLint b
= (GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
] -half
;
3405 r
= (r
< 0) ? 0 : r
<< RGBshift
;
3406 g
= (g
< 0) ? 0 : g
<< RGBshift
;
3407 b
= (b
< 0) ? 0 : b
<< RGBshift
;
3408 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3409 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3410 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3415 case GL_INTERPOLATE
:
3417 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3418 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3419 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3420 #if CHAN_TYPE != GL_FLOAT
3421 const GLint shift
= CHAN_BITS
- RGBshift
;
3423 for (i
= 0; i
< n
; i
++) {
3424 #if CHAN_TYPE == GL_FLOAT
3425 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
3426 arg1
[i
][RCOMP
] * (CHAN_MAXF
- arg2
[i
][RCOMP
])) * RGBmult
;
3427 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
3428 arg1
[i
][GCOMP
] * (CHAN_MAXF
- arg2
[i
][GCOMP
])) * RGBmult
;
3429 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
3430 arg1
[i
][BCOMP
] * (CHAN_MAXF
- arg2
[i
][BCOMP
])) * RGBmult
;
3432 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3433 + PROD(arg1
[i
][RCOMP
], CHAN_MAX
- arg2
[i
][RCOMP
]))
3435 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3436 + PROD(arg1
[i
][GCOMP
], CHAN_MAX
- arg2
[i
][GCOMP
]))
3438 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3439 + PROD(arg1
[i
][BCOMP
], CHAN_MAX
- arg2
[i
][BCOMP
]))
3441 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3442 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3443 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3450 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3451 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3452 for (i
= 0; i
< n
; i
++) {
3453 #if CHAN_TYPE == GL_FLOAT
3454 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * RGBmult
;
3455 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * RGBmult
;
3456 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * RGBmult
;
3458 GLint r
= ((GLint
) arg0
[i
][RCOMP
] - (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3459 GLint g
= ((GLint
) arg0
[i
][GCOMP
] - (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3460 GLint b
= ((GLint
) arg0
[i
][BCOMP
] - (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3461 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3462 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3463 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3468 case GL_DOT3_RGB_EXT
:
3469 case GL_DOT3_RGBA_EXT
:
3471 /* Do not scale the result by 1 2 or 4 */
3472 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3473 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3474 for (i
= 0; i
< n
; i
++) {
3475 #if CHAN_TYPE == GL_FLOAT
3476 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3477 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3478 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3480 dot
= CLAMP(dot
, 0.0F
, CHAN_MAXF
);
3482 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3483 (GLint
)arg1
[i
][RCOMP
] - half
) +
3484 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3485 (GLint
)arg1
[i
][GCOMP
] - half
) +
3486 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3487 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3488 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3490 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3497 /* DO scale the result by 1 2 or 4 */
3498 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3499 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3500 for (i
= 0; i
< n
; i
++) {
3501 #if CHAN_TYPE == GL_FLOAT
3502 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3503 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3504 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3506 dot
= CLAMP(dot
, 0.0, CHAN_MAXF
);
3508 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3509 (GLint
)arg1
[i
][RCOMP
] - half
) +
3510 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3511 (GLint
)arg1
[i
][GCOMP
] - half
) +
3512 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3513 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3515 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3517 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3521 case GL_MODULATE_ADD_ATI
:
3523 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3524 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3525 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3526 #if CHAN_TYPE != GL_FLOAT
3527 const GLint shift
= CHAN_BITS
- RGBshift
;
3529 for (i
= 0; i
< n
; i
++) {
3530 #if CHAN_TYPE == GL_FLOAT
3531 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) + arg1
[i
][RCOMP
]) * RGBmult
;
3532 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
]) * RGBmult
;
3533 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
]) * RGBmult
;
3535 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3536 + ((GLuint
) arg1
[i
][RCOMP
] << CHAN_BITS
)) >> shift
;
3537 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3538 + ((GLuint
) arg1
[i
][GCOMP
] << CHAN_BITS
)) >> shift
;
3539 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3540 + ((GLuint
) arg1
[i
][BCOMP
] << CHAN_BITS
)) >> shift
;
3541 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3542 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3543 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3548 case GL_MODULATE_SIGNED_ADD_ATI
:
3550 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3551 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3552 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3553 #if CHAN_TYPE != GL_FLOAT
3554 const GLint shift
= CHAN_BITS
- RGBshift
;
3556 for (i
= 0; i
< n
; i
++) {
3557 #if CHAN_TYPE == GL_FLOAT
3558 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3559 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3560 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3562 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3563 + (((GLint
) arg1
[i
][RCOMP
] - half
) << CHAN_BITS
))
3565 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3566 + (((GLint
) arg1
[i
][GCOMP
] - half
) << CHAN_BITS
))
3568 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3569 + (((GLint
) arg1
[i
][BCOMP
] - half
) << CHAN_BITS
))
3571 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3572 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3573 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3578 case GL_MODULATE_SUBTRACT_ATI
:
3580 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3581 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3582 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3583 #if CHAN_TYPE != GL_FLOAT
3584 const GLint shift
= CHAN_BITS
- RGBshift
;
3586 for (i
= 0; i
< n
; i
++) {
3587 #if CHAN_TYPE == GL_FLOAT
3588 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) - arg1
[i
][RCOMP
]) * RGBmult
;
3589 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) - arg1
[i
][GCOMP
]) * RGBmult
;
3590 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) - arg1
[i
][BCOMP
]) * RGBmult
;
3592 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3593 - ((GLint
) arg1
[i
][RCOMP
] << CHAN_BITS
))
3595 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3596 - ((GLint
) arg1
[i
][GCOMP
] << CHAN_BITS
))
3598 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3599 - ((GLint
) arg1
[i
][BCOMP
] << CHAN_BITS
))
3601 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3602 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3603 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3609 _mesa_problem(ctx
, "invalid combine mode");
3612 switch (textureUnit
->_CurrentCombine
->ModeA
) {
3615 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3617 for (i
= 0; i
< n
; i
++) {
3618 #if CHAN_TYPE == GL_FLOAT
3619 GLchan a
= arg0
[i
][ACOMP
] * Amult
;
3621 GLuint a
= (GLuint
) arg0
[i
][ACOMP
] << Ashift
;
3623 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3627 for (i
= 0; i
< n
; i
++) {
3628 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
];
3635 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3636 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3637 #if CHAN_TYPE != GL_FLOAT
3638 const GLint shift
= CHAN_BITS
- Ashift
;
3640 for (i
= 0; i
< n
; i
++) {
3641 #if CHAN_TYPE == GL_FLOAT
3642 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * Amult
;
3644 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg1
[i
][ACOMP
]) >> shift
);
3645 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3652 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3653 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3654 for (i
= 0; i
< n
; i
++) {
3655 #if CHAN_TYPE == GL_FLOAT
3656 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * Amult
;
3658 GLint a
= ((GLint
) arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) << Ashift
;
3659 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3666 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3667 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3668 for (i
= 0; i
< n
; i
++) {
3669 #if CHAN_TYPE == GL_FLOAT
3670 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3672 GLint a
= (GLint
) arg0
[i
][ACOMP
] + (GLint
) arg1
[i
][ACOMP
] -half
;
3673 a
= (a
< 0) ? 0 : a
<< Ashift
;
3674 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3679 case GL_INTERPOLATE
:
3681 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3682 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3683 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3684 #if CHAN_TYPE != GL_FLOAT
3685 const GLint shift
= CHAN_BITS
- Ashift
;
3687 for (i
=0; i
<n
; i
++) {
3688 #if CHAN_TYPE == GL_FLOAT
3689 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
3690 arg1
[i
][ACOMP
] * (CHAN_MAXF
- arg2
[i
][ACOMP
]))
3693 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3694 + PROD(arg1
[i
][ACOMP
], CHAN_MAX
- arg2
[i
][ACOMP
]))
3696 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3703 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3704 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3705 for (i
= 0; i
< n
; i
++) {
3706 #if CHAN_TYPE == GL_FLOAT
3707 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * Amult
;
3709 GLint a
= ((GLint
) arg0
[i
][ACOMP
] - (GLint
) arg1
[i
][ACOMP
]) << Ashift
;
3710 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3715 case GL_MODULATE_ADD_ATI
:
3717 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3718 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3719 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3720 #if CHAN_TYPE != GL_FLOAT
3721 const GLint shift
= CHAN_BITS
- Ashift
;
3723 for (i
= 0; i
< n
; i
++) {
3724 #if CHAN_TYPE == GL_FLOAT
3725 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
]) * Amult
;
3727 GLint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3728 + ((GLuint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3730 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3735 case GL_MODULATE_SIGNED_ADD_ATI
:
3737 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3738 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3739 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3740 #if CHAN_TYPE != GL_FLOAT
3741 const GLint shift
= CHAN_BITS
- Ashift
;
3743 for (i
= 0; i
< n
; i
++) {
3744 #if CHAN_TYPE == GL_FLOAT
3745 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3747 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3748 + (((GLint
) arg1
[i
][ACOMP
] - half
) << CHAN_BITS
))
3750 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3755 case GL_MODULATE_SUBTRACT_ATI
:
3757 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3758 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3759 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3760 #if CHAN_TYPE != GL_FLOAT
3761 const GLint shift
= CHAN_BITS
- Ashift
;
3763 for (i
= 0; i
< n
; i
++) {
3764 #if CHAN_TYPE == GL_FLOAT
3765 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) - arg1
[i
][ACOMP
]) * Amult
;
3767 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3768 - ((GLint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3770 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3776 _mesa_problem(ctx
, "invalid combine mode");
3779 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
3780 * This is kind of a kludge. It would have been better if the spec
3781 * were written such that the GL_COMBINE_ALPHA value could be set to
3784 if (textureUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
||
3785 textureUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) {
3786 for (i
= 0; i
< n
; i
++) {
3787 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
3790 UNDEFARRAY(ccolor
); /* mac 32k limitation */
3796 * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND,
3797 * MODULATE, or DECAL) to an array of fragments.
3798 * Input: textureUnit - pointer to texture unit to apply
3799 * format - base internal texture format
3800 * n - number of fragments
3801 * primary_rgba - primary colors (may alias rgba for single texture)
3802 * texels - array of texel colors
3803 * InOut: rgba - incoming fragment colors modified by texel colors
3804 * according to the texture environment mode.
3807 texture_apply( const GLcontext
*ctx
,
3808 const struct gl_texture_unit
*texUnit
,
3810 CONST GLchan primary_rgba
[][4], CONST GLchan texel
[][4],
3815 GLint Rc
, Gc
, Bc
, Ac
;
3819 ASSERT(texUnit
->_Current
);
3821 baseLevel
= texUnit
->_Current
->BaseLevel
;
3822 ASSERT(texUnit
->_Current
->Image
[0][baseLevel
]);
3824 format
= texUnit
->_Current
->Image
[0][baseLevel
]->Format
;
3826 if (format
== GL_COLOR_INDEX
|| format
== GL_YCBCR_MESA
) {
3827 format
= GL_RGBA
; /* a bit of a hack */
3829 else if (format
== GL_DEPTH_COMPONENT
) {
3830 format
= texUnit
->_Current
->DepthMode
;
3833 switch (texUnit
->EnvMode
) {
3840 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3846 GLchan Lt
= texel
[i
][RCOMP
];
3847 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3851 case GL_LUMINANCE_ALPHA
:
3853 GLchan Lt
= texel
[i
][RCOMP
];
3855 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3857 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3863 GLchan It
= texel
[i
][RCOMP
];
3864 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
3866 rgba
[i
][ACOMP
] = It
;
3872 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3873 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3874 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3881 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3882 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3883 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3885 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3889 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in texture_apply");
3900 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3906 GLchan Lt
= texel
[i
][RCOMP
];
3907 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3908 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3909 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3913 case GL_LUMINANCE_ALPHA
:
3916 GLchan Lt
= texel
[i
][RCOMP
];
3917 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3918 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3919 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3921 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3927 GLchan It
= texel
[i
][RCOMP
];
3928 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], It
);
3929 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], It
);
3930 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], It
);
3932 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], It
);
3938 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3939 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3940 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3947 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3948 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3949 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3951 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3955 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in texture_apply");
3964 case GL_LUMINANCE_ALPHA
:
3971 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3972 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3973 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3979 /* Cv = Cf(1-At) + CtAt */
3980 GLint t
= texel
[i
][ACOMP
], s
= CHAN_MAX
- t
;
3981 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(texel
[i
][RCOMP
],t
);
3982 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(texel
[i
][GCOMP
],t
);
3983 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(texel
[i
][BCOMP
],t
);
3988 _mesa_problem(ctx
, "Bad format (GL_DECAL) in texture_apply");
3994 Rc
= (GLint
) (texUnit
->EnvColor
[0] * CHAN_MAXF
);
3995 Gc
= (GLint
) (texUnit
->EnvColor
[1] * CHAN_MAXF
);
3996 Bc
= (GLint
) (texUnit
->EnvColor
[2] * CHAN_MAXF
);
3997 Ac
= (GLint
) (texUnit
->EnvColor
[3] * CHAN_MAXF
);
4003 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4008 /* Cv = Cf(1-Lt) + CcLt */
4009 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
4010 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
4011 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
4012 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
4016 case GL_LUMINANCE_ALPHA
:
4018 /* Cv = Cf(1-Lt) + CcLt */
4019 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
4020 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
4021 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
4022 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
4024 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
4029 /* Cv = Cf(1-It) + CcLt */
4030 GLchan It
= texel
[i
][RCOMP
], s
= CHAN_MAX
- It
;
4031 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, It
);
4032 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, It
);
4033 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, It
);
4034 /* Av = Af(1-It) + Ac*It */
4035 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], s
) + CHAN_PRODUCT(Ac
, It
);
4040 /* Cv = Cf(1-Ct) + CcCt */
4041 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
4042 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
4043 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
4049 /* Cv = Cf(1-Ct) + CcCt */
4050 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
4051 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
4052 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
4054 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
4058 _mesa_problem(ctx
, "Bad format (GL_BLEND) in texture_apply");
4063 /* XXX don't clamp results if GLchan is float??? */
4065 case GL_ADD
: /* GL_EXT_texture_add_env */
4072 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4077 GLuint Lt
= texel
[i
][RCOMP
];
4078 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
4079 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
4080 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
4081 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4082 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4083 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4087 case GL_LUMINANCE_ALPHA
:
4089 GLuint Lt
= texel
[i
][RCOMP
];
4090 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
4091 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
4092 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
4093 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4094 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4095 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4096 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4101 GLchan It
= texel
[i
][RCOMP
];
4102 GLuint r
= rgba
[i
][RCOMP
] + It
;
4103 GLuint g
= rgba
[i
][GCOMP
] + It
;
4104 GLuint b
= rgba
[i
][BCOMP
] + It
;
4105 GLuint a
= rgba
[i
][ACOMP
] + It
;
4106 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4107 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4108 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4109 rgba
[i
][ACOMP
] = MIN2(a
, CHAN_MAX
);
4114 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
4115 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
4116 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
4117 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4118 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4119 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4125 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
4126 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
4127 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
4128 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4129 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4130 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4131 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4135 _mesa_problem(ctx
, "Bad format (GL_ADD) in texture_apply");
4141 _mesa_problem(ctx
, "Bad env mode in texture_apply");
4149 * Apply texture mapping to a span of fragments.
4152 _swrast_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
4154 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
4155 GLchan primary_rgba
[MAX_WIDTH
][4];
4158 ASSERT(span
->end
< MAX_WIDTH
);
4159 ASSERT(span
->arrayMask
& SPAN_TEXTURE
);
4162 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
4164 if (swrast
->_AnyTextureCombine
)
4165 MEMCPY(primary_rgba
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
));
4168 * Must do all texture sampling before combining in order to
4169 * accomodate GL_ARB_texture_env_crossbar.
4171 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
4172 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
4173 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
4174 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
4175 GLfloat
*lambda
= span
->array
->lambda
[unit
];
4176 GLchan (*texels
)[4] = (GLchan (*)[4])
4177 (swrast
->TexelBuffer
+ unit
* (span
->end
* 4 * sizeof(GLchan
)));
4179 /* adjust texture lod (lambda) */
4180 if (span
->arrayMask
& SPAN_LAMBDA
) {
4181 if (texUnit
->LodBias
+ curObj
->LodBias
!= 0.0F
) {
4182 /* apply LOD bias, but don't clamp yet */
4183 const GLfloat bias
= CLAMP(texUnit
->LodBias
+ curObj
->LodBias
,
4184 -ctx
->Const
.MaxTextureLodBias
,
4185 ctx
->Const
.MaxTextureLodBias
);
4187 for (i
= 0; i
< span
->end
; i
++) {
4192 if (curObj
->MinLod
!= -1000.0 || curObj
->MaxLod
!= 1000.0) {
4193 /* apply LOD clamping to lambda */
4194 const GLfloat min
= curObj
->MinLod
;
4195 const GLfloat max
= curObj
->MaxLod
;
4197 for (i
= 0; i
< span
->end
; i
++) {
4198 GLfloat l
= lambda
[i
];
4199 lambda
[i
] = CLAMP(l
, min
, max
);
4204 /* Sample the texture (span->end fragments) */
4205 swrast
->TextureSample
[unit
]( ctx
, unit
, texUnit
->_Current
, span
->end
,
4206 (const GLfloat (*)[4]) span
->array
->texcoords
[unit
],
4209 /* GL_SGI_texture_color_table */
4210 if (texUnit
->ColorTableEnabled
) {
4211 _swrast_texture_table_lookup(&texUnit
->ColorTable
, span
->end
, texels
);
4217 * OK, now apply the texture (aka texture combine/blend).
4218 * We modify the span->color.rgba values.
4220 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
4221 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
4222 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
4223 if (texUnit
->_CurrentCombine
!= &texUnit
->_EnvMode
) {
4224 texture_combine( ctx
, unit
, span
->end
,
4225 (CONST
GLchan (*)[4]) primary_rgba
,
4226 swrast
->TexelBuffer
,
4227 span
->array
->rgba
);
4230 /* conventional texture blend */
4231 const GLchan (*texels
)[4] = (const GLchan (*)[4])
4232 (swrast
->TexelBuffer
+ unit
*
4233 (span
->end
* 4 * sizeof(GLchan
)));
4234 texture_apply( ctx
, texUnit
, span
->end
,
4235 (CONST
GLchan (*)[4]) primary_rgba
, texels
,
4236 span
->array
->rgba
);