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.
351 _swrast_texture_table_lookup(const struct gl_color_table
*table
,
352 GLuint n
, GLchan rgba
[][4])
354 if (!table
->Table
|| table
->Size
== 0)
357 switch (table
->Format
) {
359 /* replace RGBA with I */
360 if (table
->FloatTable
) {
361 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
362 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
364 for (i
= 0; i
< n
; i
++) {
365 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
367 CLAMPED_FLOAT_TO_CHAN(c
, lut
[j
]);
368 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] =
369 rgba
[i
][BCOMP
] = rgba
[i
][ACOMP
] = c
;
373 #if CHAN_TYPE == GL_UNSIGNED_BYTE
374 if (table
->Size
== 256) {
376 const GLchan
*lut
= (const GLchan
*) table
->Table
;
378 for (i
= 0; i
< n
; i
++) {
379 const GLchan c
= lut
[rgba
[i
][RCOMP
]];
380 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] =
381 rgba
[i
][BCOMP
] = rgba
[i
][ACOMP
] = c
;
387 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
388 const GLchan
*lut
= (const GLchan
*) table
->Table
;
390 for (i
= 0; i
< n
; i
++) {
391 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
392 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] =
393 rgba
[i
][BCOMP
] = rgba
[i
][ACOMP
] = lut
[j
];
399 /* replace RGB with L */
400 if (table
->FloatTable
) {
401 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
402 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
404 for (i
= 0; i
< n
; i
++) {
405 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
407 CLAMPED_FLOAT_TO_CHAN(c
, lut
[j
]);
408 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = c
;
412 #if CHAN_TYPE == GL_UNSIGNED_BYTE
413 if (table
->Size
== 256) {
415 const GLchan
*lut
= (const GLchan
*) table
->Table
;
417 for (i
= 0; i
< n
; i
++) {
418 const GLchan c
= lut
[rgba
[i
][RCOMP
]];
419 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = c
;
425 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
426 const GLchan
*lut
= (const GLchan
*) table
->Table
;
428 for (i
= 0; i
< n
; i
++) {
429 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
430 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = lut
[j
];
436 /* replace A with A */
437 if (table
->FloatTable
) {
438 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
439 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
441 for (i
= 0; i
< n
; i
++) {
442 GLint j
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
444 CLAMPED_FLOAT_TO_CHAN(c
, lut
[j
]);
449 #if CHAN_TYPE == GL_UNSIGNED_BYTE
450 if (table
->Size
== 256) {
452 const GLchan
*lut
= (const GLchan
*) table
->Table
;
454 for (i
= 0; i
< n
; i
++) {
455 rgba
[i
][ACOMP
] = lut
[rgba
[i
][ACOMP
]];
461 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
462 const GLchan
*lut
= (const GLchan
*) table
->Table
;
464 for (i
= 0; i
< n
; i
++) {
465 GLint j
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
466 rgba
[i
][ACOMP
] = lut
[j
];
471 case GL_LUMINANCE_ALPHA
:
472 /* replace RGBA with LLLA */
473 if (table
->FloatTable
) {
474 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
475 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
477 for (i
= 0; i
< n
; i
++) {
478 GLint jL
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
479 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
480 GLchan luminance
, alpha
;
481 CLAMPED_FLOAT_TO_CHAN(luminance
, lut
[jL
* 2 + 0]);
482 CLAMPED_FLOAT_TO_CHAN(alpha
, lut
[jA
* 2 + 1]);
483 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = luminance
;
484 rgba
[i
][ACOMP
] = alpha
;;
488 #if CHAN_TYPE == GL_UNSIGNED_BYTE
489 if (table
->Size
== 256) {
491 const GLchan
*lut
= (const GLchan
*) table
->Table
;
493 for (i
= 0; i
< n
; i
++) {
494 GLchan l
= lut
[rgba
[i
][RCOMP
] * 2 + 0];
495 GLchan a
= lut
[rgba
[i
][ACOMP
] * 2 + 1];;
496 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = l
;
503 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
504 const GLchan
*lut
= (const GLchan
*) table
->Table
;
506 for (i
= 0; i
< n
; i
++) {
507 GLint jL
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
508 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
509 GLchan luminance
= lut
[jL
* 2 + 0];
510 GLchan alpha
= lut
[jA
* 2 + 1];
511 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = luminance
;
512 rgba
[i
][ACOMP
] = alpha
;
518 /* replace RGB with RGB */
519 if (table
->FloatTable
) {
520 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
521 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
523 for (i
= 0; i
< n
; i
++) {
524 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
525 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
526 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
527 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][RCOMP
], lut
[jR
* 3 + 0]);
528 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][GCOMP
], lut
[jG
* 3 + 1]);
529 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][BCOMP
], lut
[jB
* 3 + 2]);
533 #if CHAN_TYPE == GL_UNSIGNED_BYTE
534 if (table
->Size
== 256) {
536 const GLchan
*lut
= (const GLchan
*) table
->Table
;
538 for (i
= 0; i
< n
; i
++) {
539 rgba
[i
][RCOMP
] = lut
[rgba
[i
][RCOMP
] * 3 + 0];
540 rgba
[i
][GCOMP
] = lut
[rgba
[i
][GCOMP
] * 3 + 1];
541 rgba
[i
][BCOMP
] = lut
[rgba
[i
][BCOMP
] * 3 + 2];
547 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
548 const GLchan
*lut
= (const GLchan
*) table
->Table
;
550 for (i
= 0; i
< n
; i
++) {
551 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
552 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
553 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
554 rgba
[i
][RCOMP
] = lut
[jR
* 3 + 0];
555 rgba
[i
][GCOMP
] = lut
[jG
* 3 + 1];
556 rgba
[i
][BCOMP
] = lut
[jB
* 3 + 2];
562 /* replace RGBA with RGBA */
563 if (table
->FloatTable
) {
564 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
565 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
567 for (i
= 0; i
< n
; i
++) {
568 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
569 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
570 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
571 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
572 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][RCOMP
], lut
[jR
* 4 + 0]);
573 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][GCOMP
], lut
[jG
* 4 + 1]);
574 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][BCOMP
], lut
[jB
* 4 + 2]);
575 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][ACOMP
], lut
[jA
* 4 + 3]);
579 #if CHAN_TYPE == GL_UNSIGNED_BYTE
580 if (table
->Size
== 256) {
582 const GLchan
*lut
= (const GLchan
*) table
->Table
;
584 for (i
= 0; i
< n
; i
++) {
585 rgba
[i
][RCOMP
] = lut
[rgba
[i
][RCOMP
] * 4 + 0];
586 rgba
[i
][GCOMP
] = lut
[rgba
[i
][GCOMP
] * 4 + 1];
587 rgba
[i
][BCOMP
] = lut
[rgba
[i
][BCOMP
] * 4 + 2];
588 rgba
[i
][ACOMP
] = lut
[rgba
[i
][ACOMP
] * 4 + 3];
594 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
595 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
597 for (i
= 0; i
< n
; i
++) {
598 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
599 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
600 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
601 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
602 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][RCOMP
], lut
[jR
* 4 + 0]);
603 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][GCOMP
], lut
[jG
* 4 + 1]);
604 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][BCOMP
], lut
[jB
* 4 + 2]);
605 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][ACOMP
], lut
[jA
* 4 + 3]);
611 _mesa_problem(NULL
, "Bad format in _swrast_texture_table_lookup");
619 * Get texture palette entry.
622 palette_sample(const GLcontext
*ctx
,
623 const struct gl_texture_object
*tObj
,
624 GLint index
, GLchan rgba
[4] )
626 const GLchan
*palette
;
629 if (ctx
->Texture
.SharedPalette
) {
630 ASSERT(!ctx
->Texture
.Palette
.FloatTable
);
631 palette
= (const GLchan
*) ctx
->Texture
.Palette
.Table
;
632 format
= ctx
->Texture
.Palette
.Format
;
635 ASSERT(!tObj
->Palette
.FloatTable
);
636 palette
= (const GLchan
*) tObj
->Palette
.Table
;
637 format
= tObj
->Palette
.Format
;
642 rgba
[ACOMP
] = palette
[index
];
646 rgba
[RCOMP
] = palette
[index
];
648 case GL_LUMINANCE_ALPHA
:
649 rgba
[RCOMP
] = palette
[(index
<< 1) + 0];
650 rgba
[ACOMP
] = palette
[(index
<< 1) + 1];
653 rgba
[RCOMP
] = palette
[index
* 3 + 0];
654 rgba
[GCOMP
] = palette
[index
* 3 + 1];
655 rgba
[BCOMP
] = palette
[index
* 3 + 2];
658 rgba
[RCOMP
] = palette
[(index
<< 2) + 0];
659 rgba
[GCOMP
] = palette
[(index
<< 2) + 1];
660 rgba
[BCOMP
] = palette
[(index
<< 2) + 2];
661 rgba
[ACOMP
] = palette
[(index
<< 2) + 3];
664 _mesa_problem(ctx
, "Bad palette format in palette_sample");
670 * The lambda[] array values are always monotonic. Either the whole span
671 * will be minified, magnified, or split between the two. This function
672 * determines the subranges in [0, n-1] that are to be minified or magnified.
675 compute_min_mag_ranges( GLfloat minMagThresh
, GLuint n
, const GLfloat lambda
[],
676 GLuint
*minStart
, GLuint
*minEnd
,
677 GLuint
*magStart
, GLuint
*magEnd
)
679 ASSERT(lambda
!= NULL
);
681 /* Verify that lambda[] is monotonous.
682 * We can't really use this because the inaccuracy in the LOG2 function
683 * causes this test to fail, yet the resulting texturing is correct.
687 printf("lambda delta = %g\n", lambda
[0] - lambda
[n
-1]);
688 if (lambda
[0] >= lambda
[n
-1]) { /* decreasing */
689 for (i
= 0; i
< n
- 1; i
++) {
690 ASSERT((GLint
) (lambda
[i
] * 10) >= (GLint
) (lambda
[i
+1] * 10));
693 else { /* increasing */
694 for (i
= 0; i
< n
- 1; i
++) {
695 ASSERT((GLint
) (lambda
[i
] * 10) <= (GLint
) (lambda
[i
+1] * 10));
701 /* since lambda is monotonous-array use this check first */
702 if (lambda
[0] <= minMagThresh
&& lambda
[n
-1] <= minMagThresh
) {
703 /* magnification for whole span */
706 *minStart
= *minEnd
= 0;
708 else if (lambda
[0] > minMagThresh
&& lambda
[n
-1] > minMagThresh
) {
709 /* minification for whole span */
712 *magStart
= *magEnd
= 0;
715 /* a mix of minification and magnification */
717 if (lambda
[0] > minMagThresh
) {
718 /* start with minification */
719 for (i
= 1; i
< n
; i
++) {
720 if (lambda
[i
] <= minMagThresh
)
729 /* start with magnification */
730 for (i
= 1; i
< n
; i
++) {
731 if (lambda
[i
] > minMagThresh
)
742 /* Verify the min/mag Start/End values
743 * We don't use this either (see above)
747 for (i
= 0; i
< n
; i
++) {
748 if (lambda
[i
] > minMagThresh
) {
750 ASSERT(i
>= *minStart
);
755 ASSERT(i
>= *magStart
);
764 /**********************************************************************/
765 /* 1-D Texture Sampling Functions */
766 /**********************************************************************/
769 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
772 sample_1d_nearest(GLcontext
*ctx
,
773 const struct gl_texture_object
*tObj
,
774 const struct gl_texture_image
*img
,
775 const GLfloat texcoord
[4], GLchan rgba
[4])
777 const GLint width
= img
->Width2
; /* without border, power of two */
780 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
782 /* skip over the border, if any */
785 if (i
< 0 || i
>= (GLint
) img
->Width
) {
786 /* Need this test for GL_CLAMP_TO_BORDER mode */
787 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
790 img
->FetchTexelc(img
, i
, 0, 0, rgba
);
791 if (img
->Format
== GL_COLOR_INDEX
) {
792 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
800 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
803 sample_1d_linear(GLcontext
*ctx
,
804 const struct gl_texture_object
*tObj
,
805 const struct gl_texture_image
*img
,
806 const GLfloat texcoord
[4], GLchan rgba
[4])
808 const GLint width
= img
->Width2
;
811 GLuint useBorderColor
;
813 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
821 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
822 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
826 const GLfloat a
= FRAC(u
);
828 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
829 const GLfloat w0
= (1.0F
-a
);
830 const GLfloat w1
= a
;
831 #else /* CHAN_BITS == 8 */
832 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
833 const GLint w0
= IROUND_POS((1.0F
- a
) * WEIGHT_SCALE
);
834 const GLint w1
= IROUND_POS( a
* WEIGHT_SCALE
);
836 GLchan t0
[4], t1
[4]; /* texels */
838 if (useBorderColor
& I0BIT
) {
839 COPY_CHAN4(t0
, tObj
->_BorderChan
);
842 img
->FetchTexelc(img
, i0
, 0, 0, t0
);
843 if (img
->Format
== GL_COLOR_INDEX
) {
844 palette_sample(ctx
, tObj
, t0
[0], t0
);
847 if (useBorderColor
& I1BIT
) {
848 COPY_CHAN4(t1
, tObj
->_BorderChan
);
851 img
->FetchTexelc(img
, i1
, 0, 0, t1
);
852 if (img
->Format
== GL_COLOR_INDEX
) {
853 palette_sample(ctx
, tObj
, t1
[0], t1
);
857 #if CHAN_TYPE == GL_FLOAT
858 rgba
[0] = w0
* t0
[0] + w1
* t1
[0];
859 rgba
[1] = w0
* t0
[1] + w1
* t1
[1];
860 rgba
[2] = w0
* t0
[2] + w1
* t1
[2];
861 rgba
[3] = w0
* t0
[3] + w1
* t1
[3];
862 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
863 rgba
[0] = (GLchan
) (w0
* t0
[0] + w1
* t1
[0] + 0.5);
864 rgba
[1] = (GLchan
) (w0
* t0
[1] + w1
* t1
[1] + 0.5);
865 rgba
[2] = (GLchan
) (w0
* t0
[2] + w1
* t1
[2] + 0.5);
866 rgba
[3] = (GLchan
) (w0
* t0
[3] + w1
* t1
[3] + 0.5);
867 #else /* CHAN_BITS == 8 */
868 rgba
[0] = (GLchan
) ((w0
* t0
[0] + w1
* t1
[0]) >> WEIGHT_SHIFT
);
869 rgba
[1] = (GLchan
) ((w0
* t0
[1] + w1
* t1
[1]) >> WEIGHT_SHIFT
);
870 rgba
[2] = (GLchan
) ((w0
* t0
[2] + w1
* t1
[2]) >> WEIGHT_SHIFT
);
871 rgba
[3] = (GLchan
) ((w0
* t0
[3] + w1
* t1
[3]) >> WEIGHT_SHIFT
);
879 sample_1d_nearest_mipmap_nearest(GLcontext
*ctx
,
880 const struct gl_texture_object
*tObj
,
881 GLuint n
, const GLfloat texcoord
[][4],
882 const GLfloat lambda
[], GLchan rgba
[][4])
885 ASSERT(lambda
!= NULL
);
886 for (i
= 0; i
< n
; i
++) {
888 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
889 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
895 sample_1d_linear_mipmap_nearest(GLcontext
*ctx
,
896 const struct gl_texture_object
*tObj
,
897 GLuint n
, const GLfloat texcoord
[][4],
898 const GLfloat lambda
[], GLchan rgba
[][4])
901 ASSERT(lambda
!= NULL
);
902 for (i
= 0; i
< n
; i
++) {
904 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
905 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
912 * This is really just needed in order to prevent warnings with some compilers.
914 #if CHAN_TYPE == GL_FLOAT
917 #define CHAN_CAST (GLchan) (GLint)
922 sample_1d_nearest_mipmap_linear(GLcontext
*ctx
,
923 const struct gl_texture_object
*tObj
,
924 GLuint n
, const GLfloat texcoord
[][4],
925 const GLfloat lambda
[], GLchan rgba
[][4])
928 ASSERT(lambda
!= NULL
);
929 for (i
= 0; i
< n
; i
++) {
931 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
932 if (level
>= tObj
->_MaxLevel
) {
933 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
934 texcoord
[i
], rgba
[i
]);
938 const GLfloat f
= FRAC(lambda
[i
]);
939 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
940 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
941 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
942 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
943 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
944 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
952 sample_1d_linear_mipmap_linear(GLcontext
*ctx
,
953 const struct gl_texture_object
*tObj
,
954 GLuint n
, const GLfloat texcoord
[][4],
955 const GLfloat lambda
[], GLchan rgba
[][4])
958 ASSERT(lambda
!= NULL
);
959 for (i
= 0; i
< n
; i
++) {
961 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
962 if (level
>= tObj
->_MaxLevel
) {
963 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
964 texcoord
[i
], rgba
[i
]);
968 const GLfloat f
= FRAC(lambda
[i
]);
969 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
970 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
971 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
972 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
973 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
974 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
982 sample_nearest_1d( GLcontext
*ctx
, GLuint texUnit
,
983 const struct gl_texture_object
*tObj
, GLuint n
,
984 const GLfloat texcoords
[][4], const GLfloat lambda
[],
988 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
991 sample_1d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
998 sample_linear_1d( GLcontext
*ctx
, GLuint texUnit
,
999 const struct gl_texture_object
*tObj
, GLuint n
,
1000 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1004 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1007 sample_1d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1013 * Given an (s) texture coordinate and lambda (level of detail) value,
1014 * return a texture sample.
1018 sample_lambda_1d( GLcontext
*ctx
, GLuint texUnit
,
1019 const struct gl_texture_object
*tObj
, GLuint n
,
1020 const GLfloat texcoords
[][4],
1021 const GLfloat lambda
[], GLchan rgba
[][4] )
1023 GLuint minStart
, minEnd
; /* texels with minification */
1024 GLuint magStart
, magEnd
; /* texels with magnification */
1027 ASSERT(lambda
!= NULL
);
1028 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1029 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1031 if (minStart
< minEnd
) {
1032 /* do the minified texels */
1033 const GLuint m
= minEnd
- minStart
;
1034 switch (tObj
->MinFilter
) {
1036 for (i
= minStart
; i
< minEnd
; i
++)
1037 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1038 texcoords
[i
], rgba
[i
]);
1041 for (i
= minStart
; i
< minEnd
; i
++)
1042 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1043 texcoords
[i
], rgba
[i
]);
1045 case GL_NEAREST_MIPMAP_NEAREST
:
1046 sample_1d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1047 lambda
+ minStart
, rgba
+ minStart
);
1049 case GL_LINEAR_MIPMAP_NEAREST
:
1050 sample_1d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1051 lambda
+ minStart
, rgba
+ minStart
);
1053 case GL_NEAREST_MIPMAP_LINEAR
:
1054 sample_1d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1055 lambda
+ minStart
, rgba
+ minStart
);
1057 case GL_LINEAR_MIPMAP_LINEAR
:
1058 sample_1d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1059 lambda
+ minStart
, rgba
+ minStart
);
1062 _mesa_problem(ctx
, "Bad min filter in sample_1d_texture");
1067 if (magStart
< magEnd
) {
1068 /* do the magnified texels */
1069 switch (tObj
->MagFilter
) {
1071 for (i
= magStart
; i
< magEnd
; i
++)
1072 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1073 texcoords
[i
], rgba
[i
]);
1076 for (i
= magStart
; i
< magEnd
; i
++)
1077 sample_1d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
1078 texcoords
[i
], rgba
[i
]);
1081 _mesa_problem(ctx
, "Bad mag filter in sample_1d_texture");
1088 /**********************************************************************/
1089 /* 2-D Texture Sampling Functions */
1090 /**********************************************************************/
1094 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
1097 sample_2d_nearest(GLcontext
*ctx
,
1098 const struct gl_texture_object
*tObj
,
1099 const struct gl_texture_image
*img
,
1100 const GLfloat texcoord
[4],
1103 const GLint width
= img
->Width2
; /* without border, power of two */
1104 const GLint height
= img
->Height2
; /* without border, power of two */
1107 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
1108 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
1110 /* skip over the border, if any */
1114 if (i
< 0 || i
>= (GLint
) img
->Width
|| j
< 0 || j
>= (GLint
) img
->Height
) {
1115 /* Need this test for GL_CLAMP_TO_BORDER mode */
1116 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
1119 img
->FetchTexelc(img
, i
, j
, 0, rgba
);
1120 if (img
->Format
== GL_COLOR_INDEX
) {
1121 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
1129 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
1130 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
1133 sample_2d_linear(GLcontext
*ctx
,
1134 const struct gl_texture_object
*tObj
,
1135 const struct gl_texture_image
*img
,
1136 const GLfloat texcoord
[4],
1139 const GLint width
= img
->Width2
;
1140 const GLint height
= img
->Height2
;
1141 GLint i0
, j0
, i1
, j1
;
1142 GLuint useBorderColor
;
1145 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1146 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1156 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1157 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1158 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1159 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1163 const GLfloat a
= FRAC(u
);
1164 const GLfloat b
= FRAC(v
);
1166 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1167 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
1168 const GLfloat w10
= a
* (1.0F
-b
);
1169 const GLfloat w01
= (1.0F
-a
) * b
;
1170 const GLfloat w11
= a
* b
;
1171 #else /* CHAN_BITS == 8 */
1172 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1173 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
1174 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
1175 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
1176 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
1183 if (useBorderColor
& (I0BIT
| J0BIT
)) {
1184 COPY_CHAN4(t00
, tObj
->_BorderChan
);
1187 img
->FetchTexelc(img
, i0
, j0
, 0, t00
);
1188 if (img
->Format
== GL_COLOR_INDEX
) {
1189 palette_sample(ctx
, tObj
, t00
[0], t00
);
1192 if (useBorderColor
& (I1BIT
| J0BIT
)) {
1193 COPY_CHAN4(t10
, tObj
->_BorderChan
);
1196 img
->FetchTexelc(img
, i1
, j0
, 0, t10
);
1197 if (img
->Format
== GL_COLOR_INDEX
) {
1198 palette_sample(ctx
, tObj
, t10
[0], t10
);
1201 if (useBorderColor
& (I0BIT
| J1BIT
)) {
1202 COPY_CHAN4(t01
, tObj
->_BorderChan
);
1205 img
->FetchTexelc(img
, i0
, j1
, 0, t01
);
1206 if (img
->Format
== GL_COLOR_INDEX
) {
1207 palette_sample(ctx
, tObj
, t01
[0], t01
);
1210 if (useBorderColor
& (I1BIT
| J1BIT
)) {
1211 COPY_CHAN4(t11
, tObj
->_BorderChan
);
1214 img
->FetchTexelc(img
, i1
, j1
, 0, t11
);
1215 if (img
->Format
== GL_COLOR_INDEX
) {
1216 palette_sample(ctx
, tObj
, t11
[0], t11
);
1219 #if CHAN_TYPE == GL_FLOAT
1220 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
1221 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
1222 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
1223 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
1224 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1225 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
1226 w01
* t01
[0] + w11
* t11
[0] + 0.5);
1227 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
1228 w01
* t01
[1] + w11
* t11
[1] + 0.5);
1229 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
1230 w01
* t01
[2] + w11
* t11
[2] + 0.5);
1231 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
1232 w01
* t01
[3] + w11
* t11
[3] + 0.5);
1233 #else /* CHAN_BITS == 8 */
1234 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
1235 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
1236 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
1237 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
1238 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
1239 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
1240 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
1241 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
1250 * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT
1251 * and we're not using a paletted texture.
1254 sample_2d_linear_repeat(GLcontext
*ctx
,
1255 const struct gl_texture_object
*tObj
,
1256 const struct gl_texture_image
*img
,
1257 const GLfloat texcoord
[4],
1260 const GLint width
= img
->Width2
;
1261 const GLint height
= img
->Height2
;
1262 GLint i0
, j0
, i1
, j1
;
1265 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1266 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1267 ASSERT(img
->Border
== 0);
1268 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
1269 ASSERT(img
->_IsPowerOfTwo
);
1271 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[0], u
, width
, i0
, i1
);
1272 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[1], v
, height
, j0
, j1
);
1275 const GLfloat a
= FRAC(u
);
1276 const GLfloat b
= FRAC(v
);
1278 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1279 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
1280 const GLfloat w10
= a
* (1.0F
-b
);
1281 const GLfloat w01
= (1.0F
-a
) * b
;
1282 const GLfloat w11
= a
* b
;
1283 #else /* CHAN_BITS == 8 */
1284 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1285 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
1286 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
1287 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
1288 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
1295 img
->FetchTexelc(img
, i0
, j0
, 0, t00
);
1296 img
->FetchTexelc(img
, i1
, j0
, 0, t10
);
1297 img
->FetchTexelc(img
, i0
, j1
, 0, t01
);
1298 img
->FetchTexelc(img
, i1
, j1
, 0, t11
);
1300 #if CHAN_TYPE == GL_FLOAT
1301 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
1302 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
1303 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
1304 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
1305 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1306 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
1307 w01
* t01
[0] + w11
* t11
[0] + 0.5);
1308 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
1309 w01
* t01
[1] + w11
* t11
[1] + 0.5);
1310 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
1311 w01
* t01
[2] + w11
* t11
[2] + 0.5);
1312 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
1313 w01
* t01
[3] + w11
* t11
[3] + 0.5);
1314 #else /* CHAN_BITS == 8 */
1315 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
1316 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
1317 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
1318 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
1319 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
1320 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
1321 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
1322 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
1332 sample_2d_nearest_mipmap_nearest(GLcontext
*ctx
,
1333 const struct gl_texture_object
*tObj
,
1334 GLuint n
, const GLfloat texcoord
[][4],
1335 const GLfloat lambda
[], GLchan rgba
[][4])
1338 for (i
= 0; i
< n
; i
++) {
1340 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1341 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1348 sample_2d_linear_mipmap_nearest(GLcontext
*ctx
,
1349 const struct gl_texture_object
*tObj
,
1350 GLuint n
, const GLfloat texcoord
[][4],
1351 const GLfloat lambda
[], GLchan rgba
[][4])
1354 ASSERT(lambda
!= NULL
);
1355 for (i
= 0; i
< n
; i
++) {
1357 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1358 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1365 sample_2d_nearest_mipmap_linear(GLcontext
*ctx
,
1366 const struct gl_texture_object
*tObj
,
1367 GLuint n
, const GLfloat texcoord
[][4],
1368 const GLfloat lambda
[], GLchan rgba
[][4])
1371 ASSERT(lambda
!= NULL
);
1372 for (i
= 0; i
< n
; i
++) {
1374 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1375 if (level
>= tObj
->_MaxLevel
) {
1376 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1377 texcoord
[i
], rgba
[i
]);
1380 GLchan t0
[4], t1
[4]; /* texels */
1381 const GLfloat f
= FRAC(lambda
[i
]);
1382 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1383 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1384 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1385 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1386 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1387 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1394 /* Trilinear filtering */
1396 sample_2d_linear_mipmap_linear( GLcontext
*ctx
,
1397 const struct gl_texture_object
*tObj
,
1398 GLuint n
, const GLfloat texcoord
[][4],
1399 const GLfloat lambda
[], GLchan rgba
[][4] )
1402 ASSERT(lambda
!= NULL
);
1403 for (i
= 0; i
< n
; i
++) {
1405 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1406 if (level
>= tObj
->_MaxLevel
) {
1407 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1408 texcoord
[i
], rgba
[i
]);
1411 GLchan t0
[4], t1
[4]; /* texels */
1412 const GLfloat f
= FRAC(lambda
[i
]);
1413 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1414 sample_2d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1415 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1416 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1417 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1418 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1425 sample_2d_linear_mipmap_linear_repeat( GLcontext
*ctx
,
1426 const struct gl_texture_object
*tObj
,
1427 GLuint n
, const GLfloat texcoord
[][4],
1428 const GLfloat lambda
[], GLchan rgba
[][4] )
1431 ASSERT(lambda
!= NULL
);
1432 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1433 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1434 ASSERT(tObj
->_IsPowerOfTwo
);
1435 for (i
= 0; i
< n
; i
++) {
1437 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1438 if (level
>= tObj
->_MaxLevel
) {
1439 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1440 texcoord
[i
], rgba
[i
]);
1443 GLchan t0
[4], t1
[4]; /* texels */
1444 const GLfloat f
= FRAC(lambda
[i
]);
1445 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1446 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1447 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1448 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1449 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1450 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1457 sample_nearest_2d( GLcontext
*ctx
, GLuint texUnit
,
1458 const struct gl_texture_object
*tObj
, GLuint n
,
1459 const GLfloat texcoords
[][4],
1460 const GLfloat lambda
[], GLchan rgba
[][4] )
1463 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1466 sample_2d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1473 sample_linear_2d( GLcontext
*ctx
, GLuint texUnit
,
1474 const struct gl_texture_object
*tObj
, GLuint n
,
1475 const GLfloat texcoords
[][4],
1476 const GLfloat lambda
[], GLchan rgba
[][4] )
1479 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
1482 sample_2d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1488 * Optimized 2-D texture sampling:
1489 * S and T wrap mode == GL_REPEAT
1490 * GL_NEAREST min/mag filter
1492 * RowStride == Width,
1496 opt_sample_rgb_2d( GLcontext
*ctx
, GLuint texUnit
,
1497 const struct gl_texture_object
*tObj
,
1498 GLuint n
, const GLfloat texcoords
[][4],
1499 const GLfloat lambda
[], GLchan rgba
[][4] )
1501 const struct gl_texture_image
*img
= tObj
->Image
[0][tObj
->BaseLevel
];
1502 const GLfloat width
= (GLfloat
) img
->Width
;
1503 const GLfloat height
= (GLfloat
) img
->Height
;
1504 const GLint colMask
= img
->Width
- 1;
1505 const GLint rowMask
= img
->Height
- 1;
1506 const GLint shift
= img
->WidthLog2
;
1509 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1510 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1511 ASSERT(img
->Border
==0);
1512 ASSERT(img
->Format
==GL_RGB
);
1513 ASSERT(img
->_IsPowerOfTwo
);
1515 for (k
=0; k
<n
; k
++) {
1516 GLint i
= IFLOOR(texcoords
[k
][0] * width
) & colMask
;
1517 GLint j
= IFLOOR(texcoords
[k
][1] * height
) & rowMask
;
1518 GLint pos
= (j
<< shift
) | i
;
1519 GLchan
*texel
= ((GLchan
*) img
->Data
) + 3*pos
;
1520 rgba
[k
][RCOMP
] = texel
[0];
1521 rgba
[k
][GCOMP
] = texel
[1];
1522 rgba
[k
][BCOMP
] = texel
[2];
1528 * Optimized 2-D texture sampling:
1529 * S and T wrap mode == GL_REPEAT
1530 * GL_NEAREST min/mag filter
1532 * RowStride == Width,
1536 opt_sample_rgba_2d( GLcontext
*ctx
, GLuint texUnit
,
1537 const struct gl_texture_object
*tObj
,
1538 GLuint n
, const GLfloat texcoords
[][4],
1539 const GLfloat lambda
[], GLchan rgba
[][4] )
1541 const struct gl_texture_image
*img
= tObj
->Image
[0][tObj
->BaseLevel
];
1542 const GLfloat width
= (GLfloat
) img
->Width
;
1543 const GLfloat height
= (GLfloat
) img
->Height
;
1544 const GLint colMask
= img
->Width
- 1;
1545 const GLint rowMask
= img
->Height
- 1;
1546 const GLint shift
= img
->WidthLog2
;
1549 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1550 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1551 ASSERT(img
->Border
==0);
1552 ASSERT(img
->Format
==GL_RGBA
);
1553 ASSERT(img
->_IsPowerOfTwo
);
1555 for (i
= 0; i
< n
; i
++) {
1556 const GLint col
= IFLOOR(texcoords
[i
][0] * width
) & colMask
;
1557 const GLint row
= IFLOOR(texcoords
[i
][1] * height
) & rowMask
;
1558 const GLint pos
= (row
<< shift
) | col
;
1559 const GLchan
*texel
= ((GLchan
*) img
->Data
) + (pos
<< 2); /* pos*4 */
1560 COPY_CHAN4(rgba
[i
], texel
);
1566 * Given an array of texture coordinate and lambda (level of detail)
1567 * values, return an array of texture sample.
1570 sample_lambda_2d( GLcontext
*ctx
, GLuint texUnit
,
1571 const struct gl_texture_object
*tObj
,
1572 GLuint n
, const GLfloat texcoords
[][4],
1573 const GLfloat lambda
[], GLchan rgba
[][4] )
1575 const struct gl_texture_image
*tImg
= tObj
->Image
[0][tObj
->BaseLevel
];
1576 GLuint minStart
, minEnd
; /* texels with minification */
1577 GLuint magStart
, magEnd
; /* texels with magnification */
1579 const GLboolean repeatNoBorderPOT
= (tObj
->WrapS
== GL_REPEAT
)
1580 && (tObj
->WrapT
== GL_REPEAT
)
1581 && (tImg
->Border
== 0 && (tImg
->Width
== tImg
->RowStride
))
1582 && (tImg
->Format
!= GL_COLOR_INDEX
)
1583 && tImg
->_IsPowerOfTwo
;
1585 ASSERT(lambda
!= NULL
);
1586 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1587 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1589 if (minStart
< minEnd
) {
1590 /* do the minified texels */
1591 const GLuint m
= minEnd
- minStart
;
1592 switch (tObj
->MinFilter
) {
1594 if (repeatNoBorderPOT
) {
1595 switch (tImg
->Format
) {
1597 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1598 NULL
, rgba
+ minStart
);
1601 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1602 NULL
, rgba
+ minStart
);
1605 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1606 NULL
, rgba
+ minStart
);
1610 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1611 NULL
, rgba
+ minStart
);
1615 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1616 NULL
, rgba
+ minStart
);
1618 case GL_NEAREST_MIPMAP_NEAREST
:
1619 sample_2d_nearest_mipmap_nearest(ctx
, tObj
, m
,
1620 texcoords
+ minStart
,
1621 lambda
+ minStart
, rgba
+ minStart
);
1623 case GL_LINEAR_MIPMAP_NEAREST
:
1624 sample_2d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1625 lambda
+ minStart
, rgba
+ minStart
);
1627 case GL_NEAREST_MIPMAP_LINEAR
:
1628 sample_2d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1629 lambda
+ minStart
, rgba
+ minStart
);
1631 case GL_LINEAR_MIPMAP_LINEAR
:
1632 if (repeatNoBorderPOT
)
1633 sample_2d_linear_mipmap_linear_repeat(ctx
, tObj
, m
,
1634 texcoords
+ minStart
, lambda
+ minStart
, rgba
+ minStart
);
1636 sample_2d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1637 lambda
+ minStart
, rgba
+ minStart
);
1640 _mesa_problem(ctx
, "Bad min filter in sample_2d_texture");
1645 if (magStart
< magEnd
) {
1646 /* do the magnified texels */
1647 const GLuint m
= magEnd
- magStart
;
1649 switch (tObj
->MagFilter
) {
1651 if (repeatNoBorderPOT
) {
1652 switch (tImg
->Format
) {
1654 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1655 NULL
, rgba
+ magStart
);
1658 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1659 NULL
, rgba
+ magStart
);
1662 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1663 NULL
, rgba
+ magStart
);
1667 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1668 NULL
, rgba
+ magStart
);
1672 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1673 NULL
, rgba
+ magStart
);
1676 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_2d");
1683 /**********************************************************************/
1684 /* 3-D Texture Sampling Functions */
1685 /**********************************************************************/
1688 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1691 sample_3d_nearest(GLcontext
*ctx
,
1692 const struct gl_texture_object
*tObj
,
1693 const struct gl_texture_image
*img
,
1694 const GLfloat texcoord
[4],
1697 const GLint width
= img
->Width2
; /* without border, power of two */
1698 const GLint height
= img
->Height2
; /* without border, power of two */
1699 const GLint depth
= img
->Depth2
; /* without border, power of two */
1702 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
1703 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
1704 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapR
, texcoord
[2], depth
, k
);
1706 if (i
< 0 || i
>= (GLint
) img
->Width
||
1707 j
< 0 || j
>= (GLint
) img
->Height
||
1708 k
< 0 || k
>= (GLint
) img
->Depth
) {
1709 /* Need this test for GL_CLAMP_TO_BORDER mode */
1710 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
1713 img
->FetchTexelc(img
, i
, j
, k
, rgba
);
1714 if (img
->Format
== GL_COLOR_INDEX
) {
1715 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
1723 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1726 sample_3d_linear(GLcontext
*ctx
,
1727 const struct gl_texture_object
*tObj
,
1728 const struct gl_texture_image
*img
,
1729 const GLfloat texcoord
[4],
1732 const GLint width
= img
->Width2
;
1733 const GLint height
= img
->Height2
;
1734 const GLint depth
= img
->Depth2
;
1735 GLint i0
, j0
, k0
, i1
, j1
, k1
;
1736 GLuint useBorderColor
;
1739 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1740 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1741 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapR
, texcoord
[2], w
, depth
, k0
, k1
);
1753 /* check if sampling texture border color */
1754 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1755 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1756 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1757 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1758 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
1759 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
1763 const GLfloat a
= FRAC(u
);
1764 const GLfloat b
= FRAC(v
);
1765 const GLfloat c
= FRAC(w
);
1767 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1768 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1769 GLfloat w000
= (1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
);
1770 GLfloat w100
= a
* (1.0F
-b
) * (1.0F
-c
);
1771 GLfloat w010
= (1.0F
-a
) * b
* (1.0F
-c
);
1772 GLfloat w110
= a
* b
* (1.0F
-c
);
1773 GLfloat w001
= (1.0F
-a
) * (1.0F
-b
) * c
;
1774 GLfloat w101
= a
* (1.0F
-b
) * c
;
1775 GLfloat w011
= (1.0F
-a
) * b
* c
;
1776 GLfloat w111
= a
* b
* c
;
1777 #else /* CHAN_BITS == 8 */
1778 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1779 GLint w000
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1780 GLint w100
= IROUND_POS( a
* (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1781 GLint w010
= IROUND_POS((1.0F
-a
) * b
* (1.0F
-c
) * WEIGHT_SCALE
);
1782 GLint w110
= IROUND_POS( a
* b
* (1.0F
-c
) * WEIGHT_SCALE
);
1783 GLint w001
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * c
* WEIGHT_SCALE
);
1784 GLint w101
= IROUND_POS( a
* (1.0F
-b
) * c
* WEIGHT_SCALE
);
1785 GLint w011
= IROUND_POS((1.0F
-a
) * b
* c
* WEIGHT_SCALE
);
1786 GLint w111
= IROUND_POS( a
* b
* c
* WEIGHT_SCALE
);
1789 GLchan t000
[4], t010
[4], t001
[4], t011
[4];
1790 GLchan t100
[4], t110
[4], t101
[4], t111
[4];
1792 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
1793 COPY_CHAN4(t000
, tObj
->_BorderChan
);
1796 img
->FetchTexelc(img
, i0
, j0
, k0
, t000
);
1797 if (img
->Format
== GL_COLOR_INDEX
) {
1798 palette_sample(ctx
, tObj
, t000
[0], t000
);
1801 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
1802 COPY_CHAN4(t100
, tObj
->_BorderChan
);
1805 img
->FetchTexelc(img
, i1
, j0
, k0
, t100
);
1806 if (img
->Format
== GL_COLOR_INDEX
) {
1807 palette_sample(ctx
, tObj
, t100
[0], t100
);
1810 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
1811 COPY_CHAN4(t010
, tObj
->_BorderChan
);
1814 img
->FetchTexelc(img
, i0
, j1
, k0
, t010
);
1815 if (img
->Format
== GL_COLOR_INDEX
) {
1816 palette_sample(ctx
, tObj
, t010
[0], t010
);
1819 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
1820 COPY_CHAN4(t110
, tObj
->_BorderChan
);
1823 img
->FetchTexelc(img
, i1
, j1
, k0
, t110
);
1824 if (img
->Format
== GL_COLOR_INDEX
) {
1825 palette_sample(ctx
, tObj
, t110
[0], t110
);
1829 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
1830 COPY_CHAN4(t001
, tObj
->_BorderChan
);
1833 img
->FetchTexelc(img
, i0
, j0
, k1
, t001
);
1834 if (img
->Format
== GL_COLOR_INDEX
) {
1835 palette_sample(ctx
, tObj
, t001
[0], t001
);
1838 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
1839 COPY_CHAN4(t101
, tObj
->_BorderChan
);
1842 img
->FetchTexelc(img
, i1
, j0
, k1
, t101
);
1843 if (img
->Format
== GL_COLOR_INDEX
) {
1844 palette_sample(ctx
, tObj
, t101
[0], t101
);
1847 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
1848 COPY_CHAN4(t011
, tObj
->_BorderChan
);
1851 img
->FetchTexelc(img
, i0
, j1
, k1
, t011
);
1852 if (img
->Format
== GL_COLOR_INDEX
) {
1853 palette_sample(ctx
, tObj
, t011
[0], t011
);
1856 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
1857 COPY_CHAN4(t111
, tObj
->_BorderChan
);
1860 img
->FetchTexelc(img
, i1
, j1
, k1
, t111
);
1861 if (img
->Format
== GL_COLOR_INDEX
) {
1862 palette_sample(ctx
, tObj
, t111
[0], t111
);
1866 #if CHAN_TYPE == GL_FLOAT
1867 rgba
[0] = w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1868 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0];
1869 rgba
[1] = w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1870 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1];
1871 rgba
[2] = w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1872 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2];
1873 rgba
[3] = w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1874 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3];
1875 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1876 rgba
[0] = (GLchan
) (w000
*t000
[0] + w010
*t010
[0] +
1877 w001
*t001
[0] + w011
*t011
[0] +
1878 w100
*t100
[0] + w110
*t110
[0] +
1879 w101
*t101
[0] + w111
*t111
[0] + 0.5);
1880 rgba
[1] = (GLchan
) (w000
*t000
[1] + w010
*t010
[1] +
1881 w001
*t001
[1] + w011
*t011
[1] +
1882 w100
*t100
[1] + w110
*t110
[1] +
1883 w101
*t101
[1] + w111
*t111
[1] + 0.5);
1884 rgba
[2] = (GLchan
) (w000
*t000
[2] + w010
*t010
[2] +
1885 w001
*t001
[2] + w011
*t011
[2] +
1886 w100
*t100
[2] + w110
*t110
[2] +
1887 w101
*t101
[2] + w111
*t111
[2] + 0.5);
1888 rgba
[3] = (GLchan
) (w000
*t000
[3] + w010
*t010
[3] +
1889 w001
*t001
[3] + w011
*t011
[3] +
1890 w100
*t100
[3] + w110
*t110
[3] +
1891 w101
*t101
[3] + w111
*t111
[3] + 0.5);
1892 #else /* CHAN_BITS == 8 */
1893 rgba
[0] = (GLchan
) (
1894 (w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1895 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0] )
1897 rgba
[1] = (GLchan
) (
1898 (w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1899 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1] )
1901 rgba
[2] = (GLchan
) (
1902 (w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1903 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2] )
1905 rgba
[3] = (GLchan
) (
1906 (w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1907 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3] )
1917 sample_3d_nearest_mipmap_nearest(GLcontext
*ctx
,
1918 const struct gl_texture_object
*tObj
,
1919 GLuint n
, const GLfloat texcoord
[][4],
1920 const GLfloat lambda
[], GLchan rgba
[][4] )
1923 for (i
= 0; i
< n
; i
++) {
1925 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1926 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1932 sample_3d_linear_mipmap_nearest(GLcontext
*ctx
,
1933 const struct gl_texture_object
*tObj
,
1934 GLuint n
, const GLfloat texcoord
[][4],
1935 const GLfloat lambda
[], GLchan rgba
[][4])
1938 ASSERT(lambda
!= NULL
);
1939 for (i
= 0; i
< n
; i
++) {
1941 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1942 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], rgba
[i
]);
1948 sample_3d_nearest_mipmap_linear(GLcontext
*ctx
,
1949 const struct gl_texture_object
*tObj
,
1950 GLuint n
, const GLfloat texcoord
[][4],
1951 const GLfloat lambda
[], GLchan rgba
[][4])
1954 ASSERT(lambda
!= NULL
);
1955 for (i
= 0; i
< n
; i
++) {
1957 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1958 if (level
>= tObj
->_MaxLevel
) {
1959 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1960 texcoord
[i
], rgba
[i
]);
1963 GLchan t0
[4], t1
[4]; /* texels */
1964 const GLfloat f
= FRAC(lambda
[i
]);
1965 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1966 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1967 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1968 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1969 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1970 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1977 sample_3d_linear_mipmap_linear(GLcontext
*ctx
,
1978 const struct gl_texture_object
*tObj
,
1979 GLuint n
, const GLfloat texcoord
[][4],
1980 const GLfloat lambda
[], GLchan rgba
[][4])
1983 ASSERT(lambda
!= NULL
);
1984 for (i
= 0; i
< n
; i
++) {
1986 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1987 if (level
>= tObj
->_MaxLevel
) {
1988 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->_MaxLevel
],
1989 texcoord
[i
], rgba
[i
]);
1992 GLchan t0
[4], t1
[4]; /* texels */
1993 const GLfloat f
= FRAC(lambda
[i
]);
1994 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
], texcoord
[i
], t0
);
1995 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][level
+1], texcoord
[i
], t1
);
1996 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1997 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1998 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1999 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
2006 sample_nearest_3d(GLcontext
*ctx
, GLuint texUnit
,
2007 const struct gl_texture_object
*tObj
, GLuint n
,
2008 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2012 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
2015 sample_3d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
2022 sample_linear_3d( GLcontext
*ctx
, GLuint texUnit
,
2023 const struct gl_texture_object
*tObj
, GLuint n
,
2024 const GLfloat texcoords
[][4],
2025 const GLfloat lambda
[], GLchan rgba
[][4] )
2028 struct gl_texture_image
*image
= tObj
->Image
[0][tObj
->BaseLevel
];
2031 sample_3d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
2037 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
2038 * return a texture sample.
2041 sample_lambda_3d( GLcontext
*ctx
, GLuint texUnit
,
2042 const struct gl_texture_object
*tObj
, GLuint n
,
2043 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2046 GLuint minStart
, minEnd
; /* texels with minification */
2047 GLuint magStart
, magEnd
; /* texels with magnification */
2050 ASSERT(lambda
!= NULL
);
2051 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2052 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2054 if (minStart
< minEnd
) {
2055 /* do the minified texels */
2056 GLuint m
= minEnd
- minStart
;
2057 switch (tObj
->MinFilter
) {
2059 for (i
= minStart
; i
< minEnd
; i
++)
2060 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2061 texcoords
[i
], rgba
[i
]);
2064 for (i
= minStart
; i
< minEnd
; i
++)
2065 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2066 texcoords
[i
], rgba
[i
]);
2068 case GL_NEAREST_MIPMAP_NEAREST
:
2069 sample_3d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
2070 lambda
+ minStart
, rgba
+ minStart
);
2072 case GL_LINEAR_MIPMAP_NEAREST
:
2073 sample_3d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
2074 lambda
+ minStart
, rgba
+ minStart
);
2076 case GL_NEAREST_MIPMAP_LINEAR
:
2077 sample_3d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
2078 lambda
+ minStart
, rgba
+ minStart
);
2080 case GL_LINEAR_MIPMAP_LINEAR
:
2081 sample_3d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
2082 lambda
+ minStart
, rgba
+ minStart
);
2085 _mesa_problem(ctx
, "Bad min filter in sample_3d_texture");
2090 if (magStart
< magEnd
) {
2091 /* do the magnified texels */
2092 switch (tObj
->MagFilter
) {
2094 for (i
= magStart
; i
< magEnd
; i
++)
2095 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2096 texcoords
[i
], rgba
[i
]);
2099 for (i
= magStart
; i
< magEnd
; i
++)
2100 sample_3d_linear(ctx
, tObj
, tObj
->Image
[0][tObj
->BaseLevel
],
2101 texcoords
[i
], rgba
[i
]);
2104 _mesa_problem(ctx
, "Bad mag filter in sample_3d_texture");
2111 /**********************************************************************/
2112 /* Texture Cube Map Sampling Functions */
2113 /**********************************************************************/
2116 * Choose one of six sides of a texture cube map given the texture
2117 * coord (rx,ry,rz). Return pointer to corresponding array of texture
2120 static const struct gl_texture_image
**
2121 choose_cube_face(const struct gl_texture_object
*texObj
,
2122 const GLfloat texcoord
[4], GLfloat newCoord
[4])
2126 direction target sc tc ma
2127 ---------- ------------------------------- --- --- ---
2128 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
2129 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
2130 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
2131 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
2132 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
2133 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
2135 const GLfloat rx
= texcoord
[0];
2136 const GLfloat ry
= texcoord
[1];
2137 const GLfloat rz
= texcoord
[2];
2138 const struct gl_texture_image
**imgArray
;
2139 const GLfloat arx
= FABSF(rx
), ary
= FABSF(ry
), arz
= FABSF(rz
);
2142 if (arx
> ary
&& arx
> arz
) {
2144 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_POS_X
];
2150 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_NEG_X
];
2156 else if (ary
> arx
&& ary
> arz
) {
2158 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_POS_Y
];
2164 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_NEG_Y
];
2172 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_POS_Z
];
2178 imgArray
= (const struct gl_texture_image
**) texObj
->Image
[FACE_NEG_Z
];
2185 newCoord
[0] = ( sc
/ ma
+ 1.0F
) * 0.5F
;
2186 newCoord
[1] = ( tc
/ ma
+ 1.0F
) * 0.5F
;
2192 sample_nearest_cube(GLcontext
*ctx
, GLuint texUnit
,
2193 const struct gl_texture_object
*tObj
, GLuint n
,
2194 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2199 for (i
= 0; i
< n
; i
++) {
2200 const struct gl_texture_image
**images
;
2201 GLfloat newCoord
[4];
2202 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
2203 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
2210 sample_linear_cube(GLcontext
*ctx
, GLuint texUnit
,
2211 const struct gl_texture_object
*tObj
, GLuint n
,
2212 const GLfloat texcoords
[][4],
2213 const GLfloat lambda
[], GLchan rgba
[][4])
2217 for (i
= 0; i
< n
; i
++) {
2218 const struct gl_texture_image
**images
;
2219 GLfloat newCoord
[4];
2220 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
2221 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
2228 sample_cube_nearest_mipmap_nearest(GLcontext
*ctx
, GLuint texUnit
,
2229 const struct gl_texture_object
*tObj
,
2230 GLuint n
, const GLfloat texcoord
[][4],
2231 const GLfloat lambda
[], GLchan rgba
[][4])
2234 ASSERT(lambda
!= NULL
);
2235 for (i
= 0; i
< n
; i
++) {
2236 const struct gl_texture_image
**images
;
2237 GLfloat newCoord
[4];
2239 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2240 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2241 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
2247 sample_cube_linear_mipmap_nearest(GLcontext
*ctx
, GLuint texUnit
,
2248 const struct gl_texture_object
*tObj
,
2249 GLuint n
, const GLfloat texcoord
[][4],
2250 const GLfloat lambda
[], GLchan rgba
[][4])
2253 ASSERT(lambda
!= NULL
);
2254 for (i
= 0; i
< n
; i
++) {
2255 const struct gl_texture_image
**images
;
2256 GLfloat newCoord
[4];
2258 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2259 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2260 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
2266 sample_cube_nearest_mipmap_linear(GLcontext
*ctx
, GLuint texUnit
,
2267 const struct gl_texture_object
*tObj
,
2268 GLuint n
, const GLfloat texcoord
[][4],
2269 const GLfloat lambda
[], GLchan rgba
[][4])
2272 ASSERT(lambda
!= NULL
);
2273 for (i
= 0; i
< n
; i
++) {
2274 const struct gl_texture_image
**images
;
2275 GLfloat newCoord
[4];
2277 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2278 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2279 if (level
>= tObj
->_MaxLevel
) {
2280 sample_2d_nearest(ctx
, tObj
, images
[tObj
->_MaxLevel
],
2284 GLchan t0
[4], t1
[4]; /* texels */
2285 const GLfloat f
= FRAC(lambda
[i
]);
2286 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, t0
);
2287 sample_2d_nearest(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
2288 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
2289 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
2290 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
2291 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
2298 sample_cube_linear_mipmap_linear(GLcontext
*ctx
, GLuint texUnit
,
2299 const struct gl_texture_object
*tObj
,
2300 GLuint n
, const GLfloat texcoord
[][4],
2301 const GLfloat lambda
[], GLchan rgba
[][4])
2304 ASSERT(lambda
!= NULL
);
2305 for (i
= 0; i
< n
; i
++) {
2306 const struct gl_texture_image
**images
;
2307 GLfloat newCoord
[4];
2309 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2310 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2311 if (level
>= tObj
->_MaxLevel
) {
2312 sample_2d_linear(ctx
, tObj
, images
[tObj
->_MaxLevel
],
2316 GLchan t0
[4], t1
[4];
2317 const GLfloat f
= FRAC(lambda
[i
]);
2318 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, t0
);
2319 sample_2d_linear(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
2320 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
2321 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
2322 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
2323 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
2330 sample_lambda_cube( GLcontext
*ctx
, GLuint texUnit
,
2331 const struct gl_texture_object
*tObj
, GLuint n
,
2332 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2335 GLuint minStart
, minEnd
; /* texels with minification */
2336 GLuint magStart
, magEnd
; /* texels with magnification */
2338 ASSERT(lambda
!= NULL
);
2339 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2340 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2342 if (minStart
< minEnd
) {
2343 /* do the minified texels */
2344 const GLuint m
= minEnd
- minStart
;
2345 switch (tObj
->MinFilter
) {
2347 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2348 lambda
+ minStart
, rgba
+ minStart
);
2351 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2352 lambda
+ minStart
, rgba
+ minStart
);
2354 case GL_NEAREST_MIPMAP_NEAREST
:
2355 sample_cube_nearest_mipmap_nearest(ctx
, texUnit
, tObj
, m
,
2356 texcoords
+ minStart
,
2357 lambda
+ minStart
, rgba
+ minStart
);
2359 case GL_LINEAR_MIPMAP_NEAREST
:
2360 sample_cube_linear_mipmap_nearest(ctx
, texUnit
, tObj
, m
,
2361 texcoords
+ minStart
,
2362 lambda
+ minStart
, rgba
+ minStart
);
2364 case GL_NEAREST_MIPMAP_LINEAR
:
2365 sample_cube_nearest_mipmap_linear(ctx
, texUnit
, tObj
, m
,
2366 texcoords
+ minStart
,
2367 lambda
+ minStart
, rgba
+ minStart
);
2369 case GL_LINEAR_MIPMAP_LINEAR
:
2370 sample_cube_linear_mipmap_linear(ctx
, texUnit
, tObj
, m
,
2371 texcoords
+ minStart
,
2372 lambda
+ minStart
, rgba
+ minStart
);
2375 _mesa_problem(ctx
, "Bad min filter in sample_lambda_cube");
2379 if (magStart
< magEnd
) {
2380 /* do the magnified texels */
2381 const GLuint m
= magEnd
- magStart
;
2382 switch (tObj
->MagFilter
) {
2384 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2385 lambda
+ magStart
, rgba
+ magStart
);
2388 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2389 lambda
+ magStart
, rgba
+ magStart
);
2392 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_cube");
2398 /**********************************************************************/
2399 /* Texture Rectangle Sampling Functions */
2400 /**********************************************************************/
2403 sample_nearest_rect(GLcontext
*ctx
, GLuint texUnit
,
2404 const struct gl_texture_object
*tObj
, GLuint n
,
2405 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2408 const struct gl_texture_image
*img
= tObj
->Image
[0][0];
2409 const GLfloat width
= (GLfloat
) img
->Width
;
2410 const GLfloat height
= (GLfloat
) img
->Height
;
2411 const GLint width_minus_1
= img
->Width
- 1;
2412 const GLint height_minus_1
= img
->Height
- 1;
2418 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2419 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2420 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2421 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2422 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2423 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2424 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2426 /* XXX move Wrap mode tests outside of loops for common cases */
2427 for (i
= 0; i
< n
; i
++) {
2429 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2430 if (tObj
->WrapS
== GL_CLAMP
) {
2431 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.0F
, width
) );
2433 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2434 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
) );
2437 col
= IFLOOR( CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
) );
2439 if (tObj
->WrapT
== GL_CLAMP
) {
2440 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.0F
, height
) );
2442 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2443 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
) );
2446 row
= IFLOOR( CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
) );
2449 col
= CLAMP(col
, 0, width_minus_1
);
2450 row
= CLAMP(row
, 0, height_minus_1
);
2452 img
->FetchTexelc(img
, col
, row
, 0, rgba
[i
]);
2458 sample_linear_rect(GLcontext
*ctx
, GLuint texUnit
,
2459 const struct gl_texture_object
*tObj
, GLuint n
,
2460 const GLfloat texcoords
[][4],
2461 const GLfloat lambda
[], GLchan rgba
[][4])
2463 const struct gl_texture_image
*img
= tObj
->Image
[0][0];
2464 const GLfloat width
= (GLfloat
) img
->Width
;
2465 const GLfloat height
= (GLfloat
) img
->Height
;
2466 const GLint width_minus_1
= img
->Width
- 1;
2467 const GLint height_minus_1
= img
->Height
- 1;
2473 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2474 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2475 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2476 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2477 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2478 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2479 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2481 /* XXX lots of opportunity for optimization in this loop */
2482 for (i
= 0; i
< n
; i
++) {
2484 GLint row0
, col0
, row1
, col1
;
2485 GLchan t00
[4], t01
[4], t10
[4], t11
[4];
2486 GLfloat a
, b
, w00
, w01
, w10
, w11
;
2488 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2489 if (tObj
->WrapS
== GL_CLAMP
) {
2490 fcol
= CLAMP(texcoords
[i
][0], 0.0F
, width
);
2492 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2493 fcol
= CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
);
2496 fcol
= CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
);
2498 if (tObj
->WrapT
== GL_CLAMP
) {
2499 frow
= CLAMP(texcoords
[i
][1], 0.0F
, height
);
2501 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2502 frow
= CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
);
2505 frow
= CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
);
2508 /* compute integer rows/columns */
2509 col0
= IFLOOR(fcol
);
2511 col0
= CLAMP(col0
, 0, width_minus_1
);
2512 col1
= CLAMP(col1
, 0, width_minus_1
);
2513 row0
= IFLOOR(frow
);
2515 row0
= CLAMP(row0
, 0, height_minus_1
);
2516 row1
= CLAMP(row1
, 0, height_minus_1
);
2518 /* get four texel samples */
2519 img
->FetchTexelc(img
, col0
, row0
, 0, t00
);
2520 img
->FetchTexelc(img
, col1
, row0
, 0, t10
);
2521 img
->FetchTexelc(img
, col0
, row1
, 0, t01
);
2522 img
->FetchTexelc(img
, col1
, row1
, 0, t11
);
2524 /* compute sample weights */
2527 w00
= (1.0F
-a
) * (1.0F
-b
);
2529 w01
= (1.0F
-a
) * b
;
2532 /* compute weighted average of samples */
2534 (GLchan
) (w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0]);
2536 (GLchan
) (w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1]);
2538 (GLchan
) (w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2]);
2540 (GLchan
) (w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3]);
2546 sample_lambda_rect( GLcontext
*ctx
, GLuint texUnit
,
2547 const struct gl_texture_object
*tObj
, GLuint n
,
2548 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2551 GLuint minStart
, minEnd
, magStart
, magEnd
;
2553 /* We only need lambda to decide between minification and magnification.
2554 * There is no mipmapping with rectangular textures.
2556 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2557 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2559 if (minStart
< minEnd
) {
2560 if (tObj
->MinFilter
== GL_NEAREST
) {
2561 sample_nearest_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2562 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2565 sample_linear_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2566 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2569 if (magStart
< magEnd
) {
2570 if (tObj
->MagFilter
== GL_NEAREST
) {
2571 sample_nearest_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2572 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2575 sample_linear_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2576 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2584 * Sample a shadow/depth texture.
2587 sample_depth_texture( GLcontext
*ctx
, GLuint unit
,
2588 const struct gl_texture_object
*tObj
, GLuint n
,
2589 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2592 const GLint baseLevel
= tObj
->BaseLevel
;
2593 const struct gl_texture_image
*texImage
= tObj
->Image
[0][baseLevel
];
2594 const GLuint width
= texImage
->Width
;
2595 const GLuint height
= texImage
->Height
;
2602 ASSERT(tObj
->Image
[0][tObj
->BaseLevel
]->Format
== GL_DEPTH_COMPONENT
);
2603 ASSERT(tObj
->Target
== GL_TEXTURE_1D
||
2604 tObj
->Target
== GL_TEXTURE_2D
||
2605 tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
2607 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2609 /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
2611 /* XXX this could be precomputed and saved in the texture object */
2612 if (tObj
->CompareFlag
) {
2613 /* GL_SGIX_shadow */
2614 if (tObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2615 function
= GL_LEQUAL
;
2618 ASSERT(tObj
->CompareOperator
== GL_TEXTURE_GEQUAL_R_SGIX
);
2619 function
= GL_GEQUAL
;
2622 else if (tObj
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
) {
2624 function
= tObj
->CompareFunc
;
2627 function
= GL_NONE
; /* pass depth through as grayscale */
2630 if (tObj
->MagFilter
== GL_NEAREST
) {
2632 for (i
= 0; i
< n
; i
++) {
2633 GLfloat depthSample
;
2635 /* XXX fix for texture rectangle! */
2636 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoords
[i
][0], width
, col
);
2637 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoords
[i
][1], height
, row
);
2638 texImage
->FetchTexelf(texImage
, col
, row
, 0, &depthSample
);
2642 result
= (texcoords
[i
][2] <= depthSample
) ? CHAN_MAX
: ambient
;
2645 result
= (texcoords
[i
][2] >= depthSample
) ? CHAN_MAX
: ambient
;
2648 result
= (texcoords
[i
][2] < depthSample
) ? CHAN_MAX
: ambient
;
2651 result
= (texcoords
[i
][2] > depthSample
) ? CHAN_MAX
: ambient
;
2654 result
= (texcoords
[i
][2] == depthSample
) ? CHAN_MAX
: ambient
;
2657 result
= (texcoords
[i
][2] != depthSample
) ? CHAN_MAX
: ambient
;
2666 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2669 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2673 switch (tObj
->DepthMode
) {
2675 texel
[i
][RCOMP
] = result
;
2676 texel
[i
][GCOMP
] = result
;
2677 texel
[i
][BCOMP
] = result
;
2678 texel
[i
][ACOMP
] = CHAN_MAX
;
2681 texel
[i
][RCOMP
] = result
;
2682 texel
[i
][GCOMP
] = result
;
2683 texel
[i
][BCOMP
] = result
;
2684 texel
[i
][ACOMP
] = result
;
2687 texel
[i
][RCOMP
] = 0;
2688 texel
[i
][GCOMP
] = 0;
2689 texel
[i
][BCOMP
] = 0;
2690 texel
[i
][ACOMP
] = result
;
2693 _mesa_problem(ctx
, "Bad depth texture mode");
2699 ASSERT(tObj
->MagFilter
== GL_LINEAR
);
2700 for (i
= 0; i
< n
; i
++) {
2701 GLfloat depth00
, depth01
, depth10
, depth11
;
2702 GLint i0
, i1
, j0
, j1
;
2704 GLuint useBorderTexel
;
2706 /* XXX fix for texture rectangle! */
2707 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoords
[i
][0], u
, width
, i0
, i1
);
2708 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoords
[i
][1], v
, height
,j0
, j1
);
2711 if (texImage
->Border
) {
2712 i0
+= texImage
->Border
;
2713 i1
+= texImage
->Border
;
2714 j0
+= texImage
->Border
;
2715 j1
+= texImage
->Border
;
2718 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
2719 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
2720 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
2721 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
2724 /* get four depth samples from the texture */
2725 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
2729 texImage
->FetchTexelf(texImage
, i0
, j0
, 0, &depth00
);
2731 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
2735 texImage
->FetchTexelf(texImage
, i1
, j0
, 0, &depth10
);
2737 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
2741 texImage
->FetchTexelf(texImage
, i0
, j1
, 0, &depth01
);
2743 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
2747 texImage
->FetchTexelf(texImage
, i1
, j1
, 0, &depth11
);
2751 /* compute a single weighted depth sample and do one comparison */
2752 const GLfloat a
= FRAC(u
+ 1.0F
);
2753 const GLfloat b
= FRAC(v
+ 1.0F
);
2754 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2755 const GLfloat w10
= ( a
) * (1.0F
- b
);
2756 const GLfloat w01
= (1.0F
- a
) * ( b
);
2757 const GLfloat w11
= ( a
) * ( b
);
2758 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2759 + w01
* depth01
+ w11
* depth11
;
2760 if ((depthSample
<= texcoords
[i
][2] && function
== GL_LEQUAL
) ||
2761 (depthSample
>= texcoords
[i
][2] && function
== GL_GEQUAL
)) {
2769 /* Do four depth/R comparisons and compute a weighted result.
2770 * If this touches on somebody's I.P., I'll remove this code
2773 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
2774 GLfloat luminance
= CHAN_MAXF
;
2778 if (depth00
<= texcoords
[i
][2]) luminance
-= d
;
2779 if (depth01
<= texcoords
[i
][2]) luminance
-= d
;
2780 if (depth10
<= texcoords
[i
][2]) luminance
-= d
;
2781 if (depth11
<= texcoords
[i
][2]) luminance
-= d
;
2782 result
= (GLchan
) luminance
;
2785 if (depth00
>= texcoords
[i
][2]) luminance
-= d
;
2786 if (depth01
>= texcoords
[i
][2]) luminance
-= d
;
2787 if (depth10
>= texcoords
[i
][2]) luminance
-= d
;
2788 if (depth11
>= texcoords
[i
][2]) luminance
-= d
;
2789 result
= (GLchan
) luminance
;
2792 if (depth00
< texcoords
[i
][2]) luminance
-= d
;
2793 if (depth01
< texcoords
[i
][2]) luminance
-= d
;
2794 if (depth10
< texcoords
[i
][2]) luminance
-= d
;
2795 if (depth11
< texcoords
[i
][2]) luminance
-= d
;
2796 result
= (GLchan
) luminance
;
2799 if (depth00
> texcoords
[i
][2]) luminance
-= d
;
2800 if (depth01
> texcoords
[i
][2]) luminance
-= d
;
2801 if (depth10
> texcoords
[i
][2]) luminance
-= d
;
2802 if (depth11
> texcoords
[i
][2]) luminance
-= d
;
2803 result
= (GLchan
) luminance
;
2806 if (depth00
== texcoords
[i
][2]) luminance
-= d
;
2807 if (depth01
== texcoords
[i
][2]) luminance
-= d
;
2808 if (depth10
== texcoords
[i
][2]) luminance
-= d
;
2809 if (depth11
== texcoords
[i
][2]) luminance
-= d
;
2810 result
= (GLchan
) luminance
;
2813 if (depth00
!= texcoords
[i
][2]) luminance
-= d
;
2814 if (depth01
!= texcoords
[i
][2]) luminance
-= d
;
2815 if (depth10
!= texcoords
[i
][2]) luminance
-= d
;
2816 if (depth11
!= texcoords
[i
][2]) luminance
-= d
;
2817 result
= (GLchan
) luminance
;
2826 /* ordinary bilinear filtering */
2828 const GLfloat a
= FRAC(u
+ 1.0F
);
2829 const GLfloat b
= FRAC(v
+ 1.0F
);
2830 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2831 const GLfloat w10
= ( a
) * (1.0F
- b
);
2832 const GLfloat w01
= (1.0F
- a
) * ( b
);
2833 const GLfloat w11
= ( a
) * ( b
);
2834 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2835 + w01
* depth01
+ w11
* depth11
;
2836 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2840 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2845 switch (tObj
->DepthMode
) {
2847 texel
[i
][RCOMP
] = result
;
2848 texel
[i
][GCOMP
] = result
;
2849 texel
[i
][BCOMP
] = result
;
2850 texel
[i
][ACOMP
] = CHAN_MAX
;
2853 texel
[i
][RCOMP
] = result
;
2854 texel
[i
][GCOMP
] = result
;
2855 texel
[i
][BCOMP
] = result
;
2856 texel
[i
][ACOMP
] = result
;
2859 texel
[i
][RCOMP
] = 0;
2860 texel
[i
][GCOMP
] = 0;
2861 texel
[i
][BCOMP
] = 0;
2862 texel
[i
][ACOMP
] = result
;
2865 _mesa_problem(ctx
, "Bad depth texture mode");
2874 * Experimental depth texture sampling function.
2877 sample_depth_texture2(const GLcontext
*ctx
,
2878 const struct gl_texture_unit
*texUnit
,
2879 GLuint n
, const GLfloat texcoords
[][4],
2882 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2883 const GLint baseLevel
= texObj
->BaseLevel
;
2884 const struct gl_texture_image
*texImage
= texObj
->Image
[0][baseLevel
];
2885 const GLuint width
= texImage
->Width
;
2886 const GLuint height
= texImage
->Height
;
2888 GLboolean lequal
, gequal
;
2890 if (texObj
->Target
!= GL_TEXTURE_2D
) {
2891 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2895 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2896 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2900 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2901 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2902 * isn't a depth texture.
2904 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2905 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2909 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2911 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2922 for (i
= 0; i
< n
; i
++) {
2924 GLint col
, row
, ii
, jj
, imin
, imax
, jmin
, jmax
, samples
, count
;
2927 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, texcoords
[i
][0],
2929 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, texcoords
[i
][1],
2937 if (imin
< 0) imin
= 0;
2938 if (imax
>= width
) imax
= width
- 1;
2939 if (jmin
< 0) jmin
= 0;
2940 if (jmax
>= height
) jmax
= height
- 1;
2942 samples
= (imax
- imin
+ 1) * (jmax
- jmin
+ 1);
2944 for (jj
= jmin
; jj
<= jmax
; jj
++) {
2945 for (ii
= imin
; ii
<= imax
; ii
++) {
2946 GLfloat depthSample
;
2947 texImage
->FetchTexelf(texImage
, ii
, jj
, 0, &depthSample
);
2948 if ((depthSample
<= r
[i
] && lequal
) ||
2949 (depthSample
>= r
[i
] && gequal
)) {
2955 w
= (GLfloat
) count
/ (GLfloat
) samples
;
2956 w
= CHAN_MAXF
- w
* (CHAN_MAXF
- (GLfloat
) ambient
);
2959 texel
[i
][RCOMP
] = lum
;
2960 texel
[i
][GCOMP
] = lum
;
2961 texel
[i
][BCOMP
] = lum
;
2962 texel
[i
][ACOMP
] = CHAN_MAX
;
2970 * We use this function when a texture object is in an "incomplete" state.
2971 * When a fragment program attempts to sample an incomplete texture we
2973 * Note: frag progs don't observe texture enable/disable flags.
2976 null_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2977 const struct gl_texture_object
*tObj
, GLuint n
,
2978 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2986 _mesa_bzero(rgba
, n
* 4 * sizeof(GLchan
));
2992 * Setup the texture sampling function for this texture object.
2995 _swrast_choose_texture_sample_func( GLcontext
*ctx
,
2996 const struct gl_texture_object
*t
)
2998 const GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
2999 const GLenum format
= t
->Image
[0][t
->BaseLevel
]->Format
;
3002 return &null_sample_func
;
3005 switch (t
->Target
) {
3007 if (format
== GL_DEPTH_COMPONENT
) {
3008 return &sample_depth_texture
;
3010 else if (needLambda
) {
3011 return &sample_lambda_1d
;
3013 else if (t
->MinFilter
== GL_LINEAR
) {
3014 return &sample_linear_1d
;
3017 ASSERT(t
->MinFilter
== GL_NEAREST
);
3018 return &sample_nearest_1d
;
3022 if (format
== GL_DEPTH_COMPONENT
) {
3023 return &sample_depth_texture
;
3025 else if (needLambda
) {
3026 return &sample_lambda_2d
;
3028 else if (t
->MinFilter
== GL_LINEAR
) {
3029 return &sample_linear_2d
;
3032 GLint baseLevel
= t
->BaseLevel
;
3033 ASSERT(t
->MinFilter
== GL_NEAREST
);
3034 if (t
->WrapS
== GL_REPEAT
&&
3035 t
->WrapT
== GL_REPEAT
&&
3037 t
->Image
[0][baseLevel
]->Border
== 0 &&
3038 t
->Image
[0][baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGB
) {
3039 return &opt_sample_rgb_2d
;
3041 else if (t
->WrapS
== GL_REPEAT
&&
3042 t
->WrapT
== GL_REPEAT
&&
3044 t
->Image
[0][baseLevel
]->Border
== 0 &&
3045 t
->Image
[0][baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGBA
) {
3046 return &opt_sample_rgba_2d
;
3049 return &sample_nearest_2d
;
3055 return &sample_lambda_3d
;
3057 else if (t
->MinFilter
== GL_LINEAR
) {
3058 return &sample_linear_3d
;
3061 ASSERT(t
->MinFilter
== GL_NEAREST
);
3062 return &sample_nearest_3d
;
3065 case GL_TEXTURE_CUBE_MAP
:
3067 return &sample_lambda_cube
;
3069 else if (t
->MinFilter
== GL_LINEAR
) {
3070 return &sample_linear_cube
;
3073 ASSERT(t
->MinFilter
== GL_NEAREST
);
3074 return &sample_nearest_cube
;
3077 case GL_TEXTURE_RECTANGLE_NV
:
3079 return &sample_lambda_rect
;
3081 else if (t
->MinFilter
== GL_LINEAR
) {
3082 return &sample_linear_rect
;
3085 ASSERT(t
->MinFilter
== GL_NEAREST
);
3086 return &sample_nearest_rect
;
3091 "invalid target in _swrast_choose_texture_sample_func");
3092 return &null_sample_func
;
3097 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
3098 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
3102 * Do texture application for GL_ARB/EXT_texture_env_combine.
3103 * This function also supports GL_{EXT,ARB}_texture_env_dot3 and
3104 * GL_ATI_texture_env_combine3
3106 * \param ctx rendering context
3107 * \param textureUnit the texture unit to apply
3108 * \param n number of fragments to process (span width)
3109 * \param primary_rgba incoming fragment color array
3110 * \param texelBuffer pointer to texel colors for all texture units
3112 * \param rgba incoming colors, which get modified here
3115 texture_combine( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
3116 CONST
GLchan (*primary_rgba
)[4],
3117 CONST GLchan
*texelBuffer
,
3120 const struct gl_texture_unit
*textureUnit
= &(ctx
->Texture
.Unit
[unit
]);
3121 const GLchan (*argRGB
[3])[4];
3122 const GLchan (*argA
[3])[4];
3123 const GLuint RGBshift
= textureUnit
->CombineScaleShiftRGB
;
3124 const GLuint Ashift
= textureUnit
->CombineScaleShiftA
;
3125 #if CHAN_TYPE == GL_FLOAT
3126 const GLchan RGBmult
= (GLfloat
) (1 << RGBshift
);
3127 const GLchan Amult
= (GLfloat
) (1 << Ashift
);
3128 static const GLchan one
[4] = { 1.0, 1.0, 1.0, 1.0 };
3129 static const GLchan zero
[4] = { 0.0, 0.0, 0.0, 0.0 };
3131 const GLint half
= (CHAN_MAX
+ 1) / 2;
3132 static const GLchan one
[4] = { CHAN_MAX
, CHAN_MAX
, CHAN_MAX
, CHAN_MAX
};
3133 static const GLchan zero
[4] = { 0, 0, 0, 0 };
3136 GLuint numColorArgs
;
3137 GLuint numAlphaArgs
;
3139 /* GLchan ccolor[3][4]; */
3140 DEFMNARRAY(GLchan
, ccolor
, 3, 3 * MAX_WIDTH
, 4); /* mac 32k limitation */
3141 CHECKARRAY(ccolor
, return); /* mac 32k limitation */
3143 ASSERT(ctx
->Extensions
.EXT_texture_env_combine
||
3144 ctx
->Extensions
.ARB_texture_env_combine
);
3145 ASSERT(SWRAST_CONTEXT(ctx
)->_AnyTextureCombine
);
3149 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
3150 textureUnit->CombineModeRGB,
3151 textureUnit->CombineModeA,
3152 textureUnit->CombineSourceRGB[0],
3153 textureUnit->CombineSourceA[0],
3154 textureUnit->CombineSourceRGB[1],
3155 textureUnit->CombineSourceA[1]);
3159 * Do operand setup for up to 3 operands. Loop over the terms.
3161 switch (textureUnit
->CombineModeRGB
) {
3171 case GL_DOT3_RGB_EXT
:
3172 case GL_DOT3_RGBA_EXT
:
3175 case GL_INTERPOLATE
:
3176 case GL_MODULATE_ADD_ATI
:
3177 case GL_MODULATE_SIGNED_ADD_ATI
:
3178 case GL_MODULATE_SUBTRACT_ATI
:
3187 switch (textureUnit
->CombineModeA
) {
3197 case GL_INTERPOLATE
:
3198 case GL_MODULATE_ADD_ATI
:
3199 case GL_MODULATE_SIGNED_ADD_ATI
:
3200 case GL_MODULATE_SUBTRACT_ATI
:
3209 for (j
= 0; j
< numColorArgs
; j
++) {
3210 const GLenum srcRGB
= textureUnit
->CombineSourceRGB
[j
];
3215 argRGB
[j
] = (const GLchan (*)[4])
3216 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
3218 case GL_PRIMARY_COLOR
:
3219 argRGB
[j
] = primary_rgba
;
3222 argRGB
[j
] = (const GLchan (*)[4]) rgba
;
3226 GLchan (*c
)[4] = ccolor
[j
];
3227 GLchan red
, green
, blue
, alpha
;
3228 UNCLAMPED_FLOAT_TO_CHAN(red
, textureUnit
->EnvColor
[0]);
3229 UNCLAMPED_FLOAT_TO_CHAN(green
, textureUnit
->EnvColor
[1]);
3230 UNCLAMPED_FLOAT_TO_CHAN(blue
, textureUnit
->EnvColor
[2]);
3231 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
3232 for (i
= 0; i
< n
; i
++) {
3234 c
[i
][GCOMP
] = green
;
3236 c
[i
][ACOMP
] = alpha
;
3238 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3241 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
3250 /* ARB_texture_env_crossbar source */
3252 const GLuint srcUnit
= srcRGB
- GL_TEXTURE0
;
3253 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
3254 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
3256 argRGB
[j
] = (const GLchan (*)[4])
3257 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
3261 if (textureUnit
->CombineOperandRGB
[j
] != GL_SRC_COLOR
) {
3262 const GLchan (*src
)[4] = argRGB
[j
];
3263 GLchan (*dst
)[4] = ccolor
[j
];
3265 /* point to new arg[j] storage */
3266 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3268 if (textureUnit
->CombineOperandRGB
[j
] == GL_ONE_MINUS_SRC_COLOR
) {
3269 for (i
= 0; i
< n
; i
++) {
3270 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][RCOMP
];
3271 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][GCOMP
];
3272 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][BCOMP
];
3275 else if (textureUnit
->CombineOperandRGB
[j
] == GL_SRC_ALPHA
) {
3276 for (i
= 0; i
< n
; i
++) {
3277 dst
[i
][RCOMP
] = src
[i
][ACOMP
];
3278 dst
[i
][GCOMP
] = src
[i
][ACOMP
];
3279 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
3283 ASSERT(textureUnit
->CombineOperandRGB
[j
] ==GL_ONE_MINUS_SRC_ALPHA
);
3284 for (i
= 0; i
< n
; i
++) {
3285 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3286 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3287 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3294 for (j
= 0; j
< numAlphaArgs
; j
++) {
3295 const GLenum srcA
= textureUnit
->CombineSourceA
[j
];
3299 argA
[j
] = (const GLchan (*)[4])
3300 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
3302 case GL_PRIMARY_COLOR
:
3303 argA
[j
] = primary_rgba
;
3306 argA
[j
] = (const GLchan (*)[4]) rgba
;
3310 GLchan alpha
, (*c
)[4] = ccolor
[j
];
3311 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
3312 for (i
= 0; i
< n
; i
++)
3313 c
[i
][ACOMP
] = alpha
;
3314 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3317 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
3326 /* ARB_texture_env_crossbar source */
3328 const GLuint srcUnit
= srcA
- GL_TEXTURE0
;
3329 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
3330 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
3332 argA
[j
] = (const GLchan (*)[4])
3333 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
3337 if (textureUnit
->CombineOperandA
[j
] == GL_ONE_MINUS_SRC_ALPHA
) {
3338 const GLchan (*src
)[4] = argA
[j
];
3339 GLchan (*dst
)[4] = ccolor
[j
];
3340 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3341 for (i
= 0; i
< n
; i
++) {
3342 dst
[i
][ACOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3348 * Do the texture combine.
3350 switch (textureUnit
->CombineModeRGB
) {
3353 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3355 for (i
= 0; i
< n
; i
++) {
3356 #if CHAN_TYPE == GL_FLOAT
3357 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * RGBmult
;
3358 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * RGBmult
;
3359 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * RGBmult
;
3361 GLuint r
= (GLuint
) arg0
[i
][RCOMP
] << RGBshift
;
3362 GLuint g
= (GLuint
) arg0
[i
][GCOMP
] << RGBshift
;
3363 GLuint b
= (GLuint
) arg0
[i
][BCOMP
] << RGBshift
;
3364 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3365 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3366 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3371 for (i
= 0; i
< n
; i
++) {
3372 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
];
3373 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
];
3374 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
];
3381 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3382 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3383 #if CHAN_TYPE != GL_FLOAT
3384 const GLint shift
= CHAN_BITS
- RGBshift
;
3386 for (i
= 0; i
< n
; i
++) {
3387 #if CHAN_TYPE == GL_FLOAT
3388 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * RGBmult
;
3389 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * RGBmult
;
3390 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * RGBmult
;
3392 GLuint r
= PROD(arg0
[i
][RCOMP
], arg1
[i
][RCOMP
]) >> shift
;
3393 GLuint g
= PROD(arg0
[i
][GCOMP
], arg1
[i
][GCOMP
]) >> shift
;
3394 GLuint b
= PROD(arg0
[i
][BCOMP
], arg1
[i
][BCOMP
]) >> shift
;
3395 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3396 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3397 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3404 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3405 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3406 for (i
= 0; i
< n
; i
++) {
3407 #if CHAN_TYPE == GL_FLOAT
3408 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * RGBmult
;
3409 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * RGBmult
;
3410 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * RGBmult
;
3412 GLint r
= ((GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3413 GLint g
= ((GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3414 GLint b
= ((GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3415 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3416 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3417 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3424 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3425 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3426 for (i
= 0; i
< n
; i
++) {
3427 #if CHAN_TYPE == GL_FLOAT
3428 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3429 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3430 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3432 GLint r
= (GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
] -half
;
3433 GLint g
= (GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
] -half
;
3434 GLint b
= (GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
] -half
;
3435 r
= (r
< 0) ? 0 : r
<< RGBshift
;
3436 g
= (g
< 0) ? 0 : g
<< RGBshift
;
3437 b
= (b
< 0) ? 0 : b
<< RGBshift
;
3438 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3439 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3440 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3445 case GL_INTERPOLATE
:
3447 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3448 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3449 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3450 #if CHAN_TYPE != GL_FLOAT
3451 const GLint shift
= CHAN_BITS
- RGBshift
;
3453 for (i
= 0; i
< n
; i
++) {
3454 #if CHAN_TYPE == GL_FLOAT
3455 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
3456 arg1
[i
][RCOMP
] * (CHAN_MAXF
- arg2
[i
][RCOMP
])) * RGBmult
;
3457 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
3458 arg1
[i
][GCOMP
] * (CHAN_MAXF
- arg2
[i
][GCOMP
])) * RGBmult
;
3459 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
3460 arg1
[i
][BCOMP
] * (CHAN_MAXF
- arg2
[i
][BCOMP
])) * RGBmult
;
3462 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3463 + PROD(arg1
[i
][RCOMP
], CHAN_MAX
- arg2
[i
][RCOMP
]))
3465 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3466 + PROD(arg1
[i
][GCOMP
], CHAN_MAX
- arg2
[i
][GCOMP
]))
3468 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3469 + PROD(arg1
[i
][BCOMP
], CHAN_MAX
- arg2
[i
][BCOMP
]))
3471 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3472 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3473 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3480 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3481 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3482 for (i
= 0; i
< n
; i
++) {
3483 #if CHAN_TYPE == GL_FLOAT
3484 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * RGBmult
;
3485 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * RGBmult
;
3486 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * RGBmult
;
3488 GLint r
= ((GLint
) arg0
[i
][RCOMP
] - (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3489 GLint g
= ((GLint
) arg0
[i
][GCOMP
] - (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3490 GLint b
= ((GLint
) arg0
[i
][BCOMP
] - (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3491 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3492 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3493 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3498 case GL_DOT3_RGB_EXT
:
3499 case GL_DOT3_RGBA_EXT
:
3501 /* Do not scale the result by 1 2 or 4 */
3502 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3503 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3504 for (i
= 0; i
< n
; i
++) {
3505 #if CHAN_TYPE == GL_FLOAT
3506 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3507 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3508 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3510 dot
= CLAMP(dot
, 0.0F
, CHAN_MAXF
);
3512 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3513 (GLint
)arg1
[i
][RCOMP
] - half
) +
3514 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3515 (GLint
)arg1
[i
][GCOMP
] - half
) +
3516 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3517 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3518 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3520 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3527 /* DO scale the result by 1 2 or 4 */
3528 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3529 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3530 for (i
= 0; i
< n
; i
++) {
3531 #if CHAN_TYPE == GL_FLOAT
3532 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3533 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3534 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3536 dot
= CLAMP(dot
, 0.0, CHAN_MAXF
);
3538 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3539 (GLint
)arg1
[i
][RCOMP
] - half
) +
3540 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3541 (GLint
)arg1
[i
][GCOMP
] - half
) +
3542 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3543 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3545 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3547 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3551 case GL_MODULATE_ADD_ATI
:
3553 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3554 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3555 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3556 #if CHAN_TYPE != GL_FLOAT
3557 const GLint shift
= CHAN_BITS
- RGBshift
;
3559 for (i
= 0; i
< n
; i
++) {
3560 #if CHAN_TYPE == GL_FLOAT
3561 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) + arg1
[i
][RCOMP
]) * RGBmult
;
3562 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
]) * RGBmult
;
3563 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
]) * RGBmult
;
3565 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3566 + ((GLuint
) arg1
[i
][RCOMP
] << CHAN_BITS
)) >> shift
;
3567 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3568 + ((GLuint
) arg1
[i
][GCOMP
] << CHAN_BITS
)) >> shift
;
3569 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3570 + ((GLuint
) arg1
[i
][BCOMP
] << CHAN_BITS
)) >> shift
;
3571 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3572 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3573 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3578 case GL_MODULATE_SIGNED_ADD_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
] - 0.5) * RGBmult
;
3589 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3590 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3592 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3593 + (((GLint
) arg1
[i
][RCOMP
] - half
) << CHAN_BITS
))
3595 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3596 + (((GLint
) arg1
[i
][GCOMP
] - half
) << CHAN_BITS
))
3598 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3599 + (((GLint
) arg1
[i
][BCOMP
] - half
) << 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
);
3608 case GL_MODULATE_SUBTRACT_ATI
:
3610 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3611 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3612 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3613 #if CHAN_TYPE != GL_FLOAT
3614 const GLint shift
= CHAN_BITS
- RGBshift
;
3616 for (i
= 0; i
< n
; i
++) {
3617 #if CHAN_TYPE == GL_FLOAT
3618 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) - arg1
[i
][RCOMP
]) * RGBmult
;
3619 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) - arg1
[i
][GCOMP
]) * RGBmult
;
3620 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) - arg1
[i
][BCOMP
]) * RGBmult
;
3622 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3623 - ((GLint
) arg1
[i
][RCOMP
] << CHAN_BITS
))
3625 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3626 - ((GLint
) arg1
[i
][GCOMP
] << CHAN_BITS
))
3628 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3629 - ((GLint
) arg1
[i
][BCOMP
] << CHAN_BITS
))
3631 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3632 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3633 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3639 _mesa_problem(ctx
, "invalid combine mode");
3642 switch (textureUnit
->CombineModeA
) {
3645 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3647 for (i
= 0; i
< n
; i
++) {
3648 #if CHAN_TYPE == GL_FLOAT
3649 GLchan a
= arg0
[i
][ACOMP
] * Amult
;
3651 GLuint a
= (GLuint
) arg0
[i
][ACOMP
] << Ashift
;
3653 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3657 for (i
= 0; i
< n
; i
++) {
3658 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
];
3665 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3666 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3667 #if CHAN_TYPE != GL_FLOAT
3668 const GLint shift
= CHAN_BITS
- Ashift
;
3670 for (i
= 0; i
< n
; i
++) {
3671 #if CHAN_TYPE == GL_FLOAT
3672 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * Amult
;
3674 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg1
[i
][ACOMP
]) >> shift
);
3675 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3682 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3683 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3684 for (i
= 0; i
< n
; i
++) {
3685 #if CHAN_TYPE == GL_FLOAT
3686 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * Amult
;
3688 GLint a
= ((GLint
) arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) << Ashift
;
3689 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3696 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3697 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3698 for (i
= 0; i
< n
; i
++) {
3699 #if CHAN_TYPE == GL_FLOAT
3700 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3702 GLint a
= (GLint
) arg0
[i
][ACOMP
] + (GLint
) arg1
[i
][ACOMP
] -half
;
3703 a
= (a
< 0) ? 0 : a
<< Ashift
;
3704 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3709 case GL_INTERPOLATE
:
3711 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3712 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3713 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3714 #if CHAN_TYPE != GL_FLOAT
3715 const GLint shift
= CHAN_BITS
- Ashift
;
3717 for (i
=0; i
<n
; i
++) {
3718 #if CHAN_TYPE == GL_FLOAT
3719 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
3720 arg1
[i
][ACOMP
] * (CHAN_MAXF
- arg2
[i
][ACOMP
]))
3723 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3724 + PROD(arg1
[i
][ACOMP
], CHAN_MAX
- arg2
[i
][ACOMP
]))
3726 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3733 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3734 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3735 for (i
= 0; i
< n
; i
++) {
3736 #if CHAN_TYPE == GL_FLOAT
3737 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * Amult
;
3739 GLint a
= ((GLint
) arg0
[i
][ACOMP
] - (GLint
) arg1
[i
][ACOMP
]) << Ashift
;
3740 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3745 case GL_MODULATE_ADD_ATI
:
3747 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3748 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3749 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3750 #if CHAN_TYPE != GL_FLOAT
3751 const GLint shift
= CHAN_BITS
- Ashift
;
3753 for (i
= 0; i
< n
; i
++) {
3754 #if CHAN_TYPE == GL_FLOAT
3755 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
]) * Amult
;
3757 GLint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3758 + ((GLuint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3760 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3765 case GL_MODULATE_SIGNED_ADD_ATI
:
3767 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3768 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3769 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3770 #if CHAN_TYPE != GL_FLOAT
3771 const GLint shift
= CHAN_BITS
- Ashift
;
3773 for (i
= 0; i
< n
; i
++) {
3774 #if CHAN_TYPE == GL_FLOAT
3775 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3777 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3778 + (((GLint
) arg1
[i
][ACOMP
] - half
) << CHAN_BITS
))
3780 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3785 case GL_MODULATE_SUBTRACT_ATI
:
3787 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3788 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3789 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3790 #if CHAN_TYPE != GL_FLOAT
3791 const GLint shift
= CHAN_BITS
- Ashift
;
3793 for (i
= 0; i
< n
; i
++) {
3794 #if CHAN_TYPE == GL_FLOAT
3795 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) - arg1
[i
][ACOMP
]) * Amult
;
3797 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3798 - ((GLint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3800 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3806 _mesa_problem(ctx
, "invalid combine mode");
3809 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
3810 * This is kind of a kludge. It would have been better if the spec
3811 * were written such that the GL_COMBINE_ALPHA value could be set to
3814 if (textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_EXT
||
3815 textureUnit
->CombineModeRGB
== GL_DOT3_RGBA
) {
3816 for (i
= 0; i
< n
; i
++) {
3817 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
3820 UNDEFARRAY(ccolor
); /* mac 32k limitation */
3826 * Implement NVIDIA's GL_NV_texture_env_combine4 extension when
3827 * texUnit->EnvMode == GL_COMBINE4_NV.
3830 texture_combine4( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
3831 CONST
GLchan (*primary_rgba
)[4],
3832 CONST GLchan
*texelBuffer
,
3840 * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND,
3841 * MODULATE, or DECAL) to an array of fragments.
3842 * Input: textureUnit - pointer to texture unit to apply
3843 * format - base internal texture format
3844 * n - number of fragments
3845 * primary_rgba - primary colors (may alias rgba for single texture)
3846 * texels - array of texel colors
3847 * InOut: rgba - incoming fragment colors modified by texel colors
3848 * according to the texture environment mode.
3851 texture_apply( const GLcontext
*ctx
,
3852 const struct gl_texture_unit
*texUnit
,
3854 CONST GLchan primary_rgba
[][4], CONST GLchan texel
[][4],
3859 GLint Rc
, Gc
, Bc
, Ac
;
3863 ASSERT(texUnit
->_Current
);
3865 baseLevel
= texUnit
->_Current
->BaseLevel
;
3866 ASSERT(texUnit
->_Current
->Image
[0][baseLevel
]);
3868 format
= texUnit
->_Current
->Image
[0][baseLevel
]->Format
;
3870 if (format
== GL_COLOR_INDEX
|| format
== GL_YCBCR_MESA
) {
3871 format
= GL_RGBA
; /* a bit of a hack */
3873 else if (format
== GL_DEPTH_COMPONENT
) {
3874 format
= texUnit
->_Current
->DepthMode
;
3877 switch (texUnit
->EnvMode
) {
3884 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3890 GLchan Lt
= texel
[i
][RCOMP
];
3891 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3895 case GL_LUMINANCE_ALPHA
:
3897 GLchan Lt
= texel
[i
][RCOMP
];
3899 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3901 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3907 GLchan It
= texel
[i
][RCOMP
];
3908 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
3910 rgba
[i
][ACOMP
] = It
;
3916 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3917 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3918 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3925 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3926 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3927 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3929 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3933 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in texture_apply");
3944 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3950 GLchan Lt
= texel
[i
][RCOMP
];
3951 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3952 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3953 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3957 case GL_LUMINANCE_ALPHA
:
3960 GLchan Lt
= texel
[i
][RCOMP
];
3961 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3962 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3963 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3965 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3971 GLchan It
= texel
[i
][RCOMP
];
3972 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], It
);
3973 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], It
);
3974 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], It
);
3976 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], It
);
3982 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3983 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3984 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3991 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3992 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3993 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3995 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3999 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in texture_apply");
4008 case GL_LUMINANCE_ALPHA
:
4015 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
4016 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
4017 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
4023 /* Cv = Cf(1-At) + CtAt */
4024 GLint t
= texel
[i
][ACOMP
], s
= CHAN_MAX
- t
;
4025 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(texel
[i
][RCOMP
],t
);
4026 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(texel
[i
][GCOMP
],t
);
4027 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(texel
[i
][BCOMP
],t
);
4032 _mesa_problem(ctx
, "Bad format (GL_DECAL) in texture_apply");
4038 Rc
= (GLint
) (texUnit
->EnvColor
[0] * CHAN_MAXF
);
4039 Gc
= (GLint
) (texUnit
->EnvColor
[1] * CHAN_MAXF
);
4040 Bc
= (GLint
) (texUnit
->EnvColor
[2] * CHAN_MAXF
);
4041 Ac
= (GLint
) (texUnit
->EnvColor
[3] * CHAN_MAXF
);
4047 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4052 /* Cv = Cf(1-Lt) + CcLt */
4053 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
4054 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
4055 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
4056 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
4060 case GL_LUMINANCE_ALPHA
:
4062 /* Cv = Cf(1-Lt) + CcLt */
4063 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
4064 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
4065 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
4066 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
4068 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
4073 /* Cv = Cf(1-It) + CcLt */
4074 GLchan It
= texel
[i
][RCOMP
], s
= CHAN_MAX
- It
;
4075 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, It
);
4076 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, It
);
4077 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, It
);
4078 /* Av = Af(1-It) + Ac*It */
4079 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], s
) + CHAN_PRODUCT(Ac
, It
);
4084 /* Cv = Cf(1-Ct) + CcCt */
4085 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
4086 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
4087 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
4093 /* Cv = Cf(1-Ct) + CcCt */
4094 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
4095 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
4096 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
4098 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
4102 _mesa_problem(ctx
, "Bad format (GL_BLEND) in texture_apply");
4107 /* XXX don't clamp results if GLchan is float??? */
4109 case GL_ADD
: /* GL_EXT_texture_add_env */
4116 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4121 GLuint Lt
= texel
[i
][RCOMP
];
4122 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
4123 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
4124 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
4125 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4126 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4127 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4131 case GL_LUMINANCE_ALPHA
:
4133 GLuint Lt
= texel
[i
][RCOMP
];
4134 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
4135 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
4136 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
4137 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4138 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4139 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4140 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4145 GLchan It
= texel
[i
][RCOMP
];
4146 GLuint r
= rgba
[i
][RCOMP
] + It
;
4147 GLuint g
= rgba
[i
][GCOMP
] + It
;
4148 GLuint b
= rgba
[i
][BCOMP
] + It
;
4149 GLuint a
= rgba
[i
][ACOMP
] + It
;
4150 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4151 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4152 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4153 rgba
[i
][ACOMP
] = MIN2(a
, CHAN_MAX
);
4158 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
4159 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
4160 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
4161 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4162 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4163 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4169 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
4170 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
4171 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
4172 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4173 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4174 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4175 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4179 _mesa_problem(ctx
, "Bad format (GL_ADD) in texture_apply");
4185 _mesa_problem(ctx
, "Bad env mode in texture_apply");
4193 * Apply texture mapping to a span of fragments.
4196 _swrast_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
4198 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
4199 GLchan primary_rgba
[MAX_WIDTH
][4];
4202 ASSERT(span
->end
< MAX_WIDTH
);
4203 ASSERT(span
->arrayMask
& SPAN_TEXTURE
);
4206 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
4208 if (swrast
->_AnyTextureCombine
)
4209 MEMCPY(primary_rgba
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
));
4212 * Must do all texture sampling before combining in order to
4213 * accomodate GL_ARB_texture_env_crossbar.
4215 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
4216 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
4217 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
4218 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
4219 GLfloat
*lambda
= span
->array
->lambda
[unit
];
4220 GLchan (*texels
)[4] = (GLchan (*)[4])
4221 (swrast
->TexelBuffer
+ unit
* (span
->end
* 4 * sizeof(GLchan
)));
4223 /* adjust texture lod (lambda) */
4224 if (span
->arrayMask
& SPAN_LAMBDA
) {
4225 if (texUnit
->LodBias
+ curObj
->LodBias
!= 0.0F
) {
4226 /* apply LOD bias, but don't clamp yet */
4227 const GLfloat bias
= CLAMP(texUnit
->LodBias
+ curObj
->LodBias
,
4228 -ctx
->Const
.MaxTextureLodBias
,
4229 ctx
->Const
.MaxTextureLodBias
);
4231 for (i
= 0; i
< span
->end
; i
++) {
4236 if (curObj
->MinLod
!= -1000.0 || curObj
->MaxLod
!= 1000.0) {
4237 /* apply LOD clamping to lambda */
4238 const GLfloat min
= curObj
->MinLod
;
4239 const GLfloat max
= curObj
->MaxLod
;
4241 for (i
= 0; i
< span
->end
; i
++) {
4242 GLfloat l
= lambda
[i
];
4243 lambda
[i
] = CLAMP(l
, min
, max
);
4248 /* Sample the texture (span->end fragments) */
4249 swrast
->TextureSample
[unit
]( ctx
, unit
, texUnit
->_Current
, span
->end
,
4250 (const GLfloat (*)[4]) span
->array
->texcoords
[unit
],
4253 /* GL_SGI_texture_color_table */
4254 if (texUnit
->ColorTableEnabled
) {
4255 _swrast_texture_table_lookup(&texUnit
->ColorTable
, span
->end
, texels
);
4261 * OK, now apply the texture (aka texture combine/blend).
4262 * We modify the span->color.rgba values.
4264 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
4265 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
4266 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
4267 if (texUnit
->EnvMode
== GL_COMBINE
) {
4268 /* GL_ARB/EXT_texture_env_combine */
4269 texture_combine( ctx
, unit
, span
->end
,
4270 (CONST
GLchan (*)[4]) primary_rgba
,
4271 swrast
->TexelBuffer
,
4272 span
->array
->rgba
);
4274 else if (texUnit
->EnvMode
== GL_COMBINE4_NV
) {
4275 /* GL_NV_texture_env_combine4 */
4276 texture_combine4( ctx
, unit
, span
->end
,
4277 (CONST
GLchan (*)[4]) primary_rgba
,
4278 swrast
->TexelBuffer
,
4279 span
->array
->rgba
);
4282 /* conventional texture blend */
4283 const GLchan (*texels
)[4] = (const GLchan (*)[4])
4284 (swrast
->TexelBuffer
+ unit
*
4285 (span
->end
* 4 * sizeof(GLchan
)));
4286 texture_apply( ctx
, texUnit
, span
->end
,
4287 (CONST
GLchan (*)[4]) primary_rgba
, texels
,
4288 span
->array
->rgba
);