1 /* $Id: s_texture.c,v 1.77 2003/01/21 21:47:53 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 #include "texformat.h"
37 #include "s_context.h"
38 #include "s_texture.h"
42 * These values are used in the fixed-point arithmetic used
43 * for linear filtering.
45 #define WEIGHT_SCALE 65536.0F
46 #define WEIGHT_SHIFT 16
50 * Used to compute texel locations for linear sampling.
52 * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER
53 * S = texcoord in [0,1]
54 * SIZE = width (or height or depth) of texture
56 * U = texcoord in [0, width]
57 * I0, I1 = two nearest texel indexes
59 #define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1) \
61 if (wrapMode == GL_REPEAT) { \
62 U = S * SIZE - 0.5F; \
63 I0 = IFLOOR(U) & (SIZE - 1); \
64 I1 = (I0 + 1) & (SIZE - 1); \
66 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
78 if (I1 >= (GLint) SIZE) \
81 else if (wrapMode == GL_CLAMP_TO_BORDER) { \
82 const GLfloat min = -1.0F / (2.0F * SIZE); \
83 const GLfloat max = 1.0F - min; \
94 else if (wrapMode == GL_MIRRORED_REPEAT) { \
95 const GLint flr = IFLOOR(S); \
97 U = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
99 U = S - (GLfloat) flr; /* flr is even */ \
100 U = (U * SIZE) - 0.5F; \
105 if (I1 >= (GLint) SIZE) \
108 else if (wrapMode == GL_MIRROR_CLAMP_ATI) { \
109 U = (GLfloat) fabs(S); \
111 U = (GLfloat) SIZE; \
118 else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_ATI) { \
119 U = (GLfloat) fabs(S); \
121 U = (GLfloat) SIZE; \
129 if (I1 >= (GLint) SIZE) \
133 ASSERT(wrapMode == GL_CLAMP); \
136 else if (S >= 1.0F) \
137 U = (GLfloat) SIZE; \
148 * Used to compute texel location for nearest sampling.
150 #define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I) \
152 if (wrapMode == GL_REPEAT) { \
153 /* s limited to [0,1) */ \
154 /* i limited to [0,size-1] */ \
155 I = IFLOOR(S * SIZE); \
158 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
159 /* s limited to [min,max] */ \
160 /* i limited to [0, size-1] */ \
161 const GLfloat min = 1.0F / (2.0F * SIZE); \
162 const GLfloat max = 1.0F - min; \
168 I = IFLOOR(S * SIZE); \
170 else if (wrapMode == GL_CLAMP_TO_BORDER) { \
171 /* s limited to [min,max] */ \
172 /* i limited to [-1, size] */ \
173 const GLfloat min = -1.0F / (2.0F * SIZE); \
174 const GLfloat max = 1.0F - min; \
180 I = IFLOOR(S * SIZE); \
182 else if (wrapMode == GL_MIRRORED_REPEAT) { \
183 const GLfloat min = 1.0F / (2.0F * SIZE); \
184 const GLfloat max = 1.0F - min; \
185 const GLint flr = IFLOOR(S); \
188 u = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
190 u = S - (GLfloat) flr; /* flr is even */ \
196 I = IFLOOR(u * SIZE); \
198 else if (wrapMode == GL_MIRROR_CLAMP_ATI) { \
199 /* s limited to [0,1] */ \
200 /* i limited to [0,size-1] */ \
201 const GLfloat u = (GLfloat) fabs(S); \
204 else if (u >= 1.0F) \
207 I = IFLOOR(u * SIZE); \
209 else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_ATI) { \
210 /* s limited to [min,max] */ \
211 /* i limited to [0, size-1] */ \
212 const GLfloat min = 1.0F / (2.0F * SIZE); \
213 const GLfloat max = 1.0F - min; \
214 const GLfloat u = (GLfloat) fabs(S); \
220 I = IFLOOR(u * SIZE); \
223 ASSERT(wrapMode == GL_CLAMP); \
224 /* s limited to [0,1] */ \
225 /* i limited to [0,size-1] */ \
228 else if (S >= 1.0F) \
231 I = IFLOOR(S * SIZE); \
236 #define COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(S, U, SIZE, I0, I1) \
238 U = S * SIZE - 0.5F; \
239 I0 = IFLOOR(U) & (SIZE - 1); \
240 I1 = (I0 + 1) & (SIZE - 1); \
245 * Compute linear mipmap levels for given lambda.
247 #define COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level) \
250 level = tObj->BaseLevel; \
251 else if (lambda > tObj->_MaxLambda) \
252 level = (GLint) (tObj->BaseLevel + tObj->_MaxLambda); \
254 level = (GLint) (tObj->BaseLevel + lambda); \
259 * Compute nearest mipmap level for given lambda.
261 #define COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level) \
264 if (lambda <= 0.5F) \
266 else if (lambda > tObj->_MaxLambda + 0.4999F) \
267 l = tObj->_MaxLambda + 0.4999F; \
270 level = (GLint) (tObj->BaseLevel + l + 0.5F); \
271 if (level > tObj->_MaxLevel) \
272 level = tObj->_MaxLevel; \
278 * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
279 * see 1-pixel bands of improperly weighted linear-sampled texels. The
280 * tests/texwrap.c demo is a good test.
281 * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
282 * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
284 #define FRAC(f) ((f) - IFLOOR(f))
289 * Bitflags for texture border color sampling.
299 static void texture_table_lookup(const struct gl_color_table
*table
,
300 GLuint n
, GLchan rgba
[][4])
302 ASSERT(table
->FloatTable
);
303 if (!table
->Table
|| table
->Size
== 0)
306 switch (table
->Format
) {
308 /* replace RGBA with I */
309 if (!table
->FloatTable
) {
310 const GLint max
= table
->Size
- 1;
311 const GLfloat scale
= (GLfloat
) max
;
312 const GLchan
*lut
= (const GLchan
*) table
->Table
;
314 for (i
= 0; i
< n
; i
++) {
315 GLint j
= CHAN_TO_FLOAT(rgba
[i
][RCOMP
])*scale
;
316 GLchan c
= lut
[CLAMP(j
, 0, 1)];
317 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] =
318 rgba
[i
][BCOMP
] = rgba
[i
][ACOMP
] = c
;
323 const GLint max
= table
->Size
- 1;
324 const GLfloat scale
= (GLfloat
) max
;
325 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
327 for (i
= 0; i
< n
; i
++) {
328 GLint j
= CHAN_TO_FLOAT(rgba
[i
][RCOMP
])*scale
;
330 CLAMPED_FLOAT_TO_CHAN(c
, lut
[j
]);
331 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] =
332 rgba
[i
][BCOMP
] = rgba
[i
][ACOMP
] = c
;
337 /* replace RGB with L */
338 if (!table
->FloatTable
) {
339 const GLint max
= table
->Size
- 1;
340 const GLfloat scale
= (GLfloat
) max
;
341 const GLchan
*lut
= (const GLchan
*) table
->Table
;
343 for (i
= 0; i
< n
; i
++) {
344 GLint j
= CHAN_TO_FLOAT(rgba
[i
][RCOMP
])*scale
;
346 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = c
;
350 const GLint max
= table
->Size
- 1;
351 const GLfloat scale
= (GLfloat
) max
;
352 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
354 for (i
= 0; i
< n
; i
++) {
355 GLint j
= CHAN_TO_FLOAT(rgba
[i
][RCOMP
])*scale
;
357 CLAMPED_FLOAT_TO_CHAN(c
, lut
[j
]);
358 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = c
;
363 /* replace A with A */
364 if (!table
->FloatTable
) {
365 const GLint max
= table
->Size
- 1;
366 const GLfloat scale
= (GLfloat
) max
;
367 const GLchan
*lut
= (const GLchan
*) table
->Table
;
369 for (i
= 0; i
< n
; i
++) {
370 GLint j
= CHAN_TO_FLOAT(rgba
[i
][ACOMP
])*scale
;
371 rgba
[i
][ACOMP
] = lut
[j
];
375 const GLint max
= table
->Size
- 1;
376 const GLfloat scale
= (GLfloat
) max
;
377 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
379 for (i
= 0; i
< n
; i
++) {
380 GLint j
= CHAN_TO_FLOAT(rgba
[i
][ACOMP
])*scale
;
381 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][ACOMP
], lut
[j
]);
385 case GL_LUMINANCE_ALPHA
:
386 /* replace RGBA with LLLA */
387 if (!table
->FloatTable
) {
388 const GLint max
= table
->Size
- 1;
389 const GLfloat scale
= (GLfloat
) max
;
390 const GLchan
*lut
= (const GLchan
*) table
->Table
;
392 for (i
= 0; i
< n
; i
++) {
393 GLint jL
= CHAN_TO_FLOAT(rgba
[i
][RCOMP
])*scale
;
394 GLint jA
= CHAN_TO_FLOAT(rgba
[i
][ACOMP
])*scale
;
395 GLchan luminance
, alpha
;
396 luminance
= lut
[jL
* 2 + 0];
397 alpha
= lut
[jA
* 2 + 1];
398 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = luminance
;
399 rgba
[i
][ACOMP
] = alpha
;;
403 const GLint max
= table
->Size
- 1;
404 const GLfloat scale
= (GLfloat
) max
;
405 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
407 for (i
= 0; i
< n
; i
++) {
408 GLint jL
= CHAN_TO_FLOAT(rgba
[i
][RCOMP
])*scale
;
409 GLint jA
= CHAN_TO_FLOAT(rgba
[i
][ACOMP
])*scale
;
410 GLchan luminance
, alpha
;
411 CLAMPED_FLOAT_TO_CHAN(luminance
, lut
[jL
* 2 + 0]);
412 CLAMPED_FLOAT_TO_CHAN(alpha
, lut
[jA
* 2 + 1]);
413 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = luminance
;
414 rgba
[i
][ACOMP
] = alpha
;;
419 /* replace RGB with RGB */
420 if (!table
->FloatTable
) {
421 const GLint max
= table
->Size
- 1;
422 const GLfloat scale
= (GLfloat
) max
;
423 const GLchan
*lut
= (const GLchan
*) table
->Table
;
425 for (i
= 0; i
< n
; i
++) {
426 GLint jR
= CHAN_TO_FLOAT(rgba
[i
][RCOMP
])*scale
;
427 GLint jG
= CHAN_TO_FLOAT(rgba
[i
][GCOMP
])*scale
;
428 GLint jB
= CHAN_TO_FLOAT(rgba
[i
][BCOMP
])*scale
;
429 rgba
[i
][RCOMP
] = lut
[jR
* 3 + 0];
430 rgba
[i
][GCOMP
] = lut
[jG
* 3 + 1];
431 rgba
[i
][BCOMP
] = lut
[jB
* 3 + 2];
435 const GLint max
= table
->Size
- 1;
436 const GLfloat scale
= (GLfloat
) max
;
437 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
439 for (i
= 0; i
< n
; i
++) {
440 GLint jR
= CHAN_TO_FLOAT(rgba
[i
][RCOMP
])*scale
;
441 GLint jG
= CHAN_TO_FLOAT(rgba
[i
][GCOMP
])*scale
;
442 GLint jB
= CHAN_TO_FLOAT(rgba
[i
][BCOMP
])*scale
;
443 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][RCOMP
], lut
[jR
* 3 + 0]);
444 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][GCOMP
], lut
[jG
* 3 + 1]);
445 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][BCOMP
], lut
[jB
* 3 + 2]);
450 /* replace RGBA with RGBA */
451 if (!table
->FloatTable
) {
452 const GLint max
= table
->Size
- 1;
453 const GLfloat scale
= (GLfloat
) max
;
454 const GLchan
*lut
= (const GLchan
*) table
->Table
;
456 for (i
= 0; i
< n
; i
++) {
457 GLint jR
= CHAN_TO_FLOAT(rgba
[i
][RCOMP
])*scale
;
458 GLint jG
= CHAN_TO_FLOAT(rgba
[i
][GCOMP
])*scale
;
459 GLint jB
= CHAN_TO_FLOAT(rgba
[i
][BCOMP
])*scale
;
460 GLint jA
= CHAN_TO_FLOAT(rgba
[i
][ACOMP
])*scale
;
461 rgba
[i
][RCOMP
] = lut
[jR
* 4 + 0];
462 rgba
[i
][GCOMP
] = lut
[jG
* 4 + 1];
463 rgba
[i
][BCOMP
] = lut
[jB
* 4 + 2];
464 rgba
[i
][ACOMP
] = lut
[jA
* 4 + 3];
468 const GLint max
= table
->Size
- 1;
469 const GLfloat scale
= (GLfloat
) max
;
470 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
472 for (i
= 0; i
< n
; i
++) {
473 GLint jR
= CHAN_TO_FLOAT(rgba
[i
][RCOMP
])*scale
;
474 GLint jG
= CHAN_TO_FLOAT(rgba
[i
][GCOMP
])*scale
;
475 GLint jB
= CHAN_TO_FLOAT(rgba
[i
][BCOMP
])*scale
;
476 GLint jA
= CHAN_TO_FLOAT(rgba
[i
][ACOMP
])*scale
;
477 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][RCOMP
], lut
[jR
* 4 + 0]);
478 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][GCOMP
], lut
[jG
* 4 + 1]);
479 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][BCOMP
], lut
[jB
* 4 + 2]);
480 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][ACOMP
], lut
[jA
* 4 + 3]);
485 _mesa_problem(NULL
, "Bad format in _mesa_lookup_rgba");
493 * Get texture palette entry.
496 palette_sample(const GLcontext
*ctx
,
497 const struct gl_texture_object
*tObj
,
498 GLint index
, GLchan rgba
[4] )
500 const GLchan
*palette
;
503 if (ctx
->Texture
.SharedPalette
) {
504 ASSERT(!ctx
->Texture
.Palette
.FloatTable
);
505 palette
= (const GLchan
*) ctx
->Texture
.Palette
.Table
;
506 format
= ctx
->Texture
.Palette
.Format
;
509 ASSERT(!tObj
->Palette
.FloatTable
);
510 palette
= (const GLchan
*) tObj
->Palette
.Table
;
511 format
= tObj
->Palette
.Format
;
516 rgba
[ACOMP
] = palette
[index
];
520 rgba
[RCOMP
] = palette
[index
];
522 case GL_LUMINANCE_ALPHA
:
523 rgba
[RCOMP
] = palette
[(index
<< 1) + 0];
524 rgba
[ACOMP
] = palette
[(index
<< 1) + 1];
527 rgba
[RCOMP
] = palette
[index
* 3 + 0];
528 rgba
[GCOMP
] = palette
[index
* 3 + 1];
529 rgba
[BCOMP
] = palette
[index
* 3 + 2];
532 rgba
[RCOMP
] = palette
[(index
<< 2) + 0];
533 rgba
[GCOMP
] = palette
[(index
<< 2) + 1];
534 rgba
[BCOMP
] = palette
[(index
<< 2) + 2];
535 rgba
[ACOMP
] = palette
[(index
<< 2) + 3];
538 _mesa_problem(ctx
, "Bad palette format in palette_sample");
544 * The lambda[] array values are always monotonic. Either the whole span
545 * will be minified, magnified, or split between the two. This function
546 * determines the subranges in [0, n-1] that are to be minified or magnified.
549 compute_min_mag_ranges( GLfloat minMagThresh
, GLuint n
, const GLfloat lambda
[],
550 GLuint
*minStart
, GLuint
*minEnd
,
551 GLuint
*magStart
, GLuint
*magEnd
)
553 ASSERT(lambda
!= NULL
);
555 /* Verify that lambda[] is monotonous.
556 * We can't really use this because the inaccuracy in the LOG2 function
557 * causes this test to fail, yet the resulting texturing is correct.
561 printf("lambda delta = %g\n", lambda
[0] - lambda
[n
-1]);
562 if (lambda
[0] >= lambda
[n
-1]) { /* decreasing */
563 for (i
= 0; i
< n
- 1; i
++) {
564 ASSERT((GLint
) (lambda
[i
] * 10) >= (GLint
) (lambda
[i
+1] * 10));
567 else { /* increasing */
568 for (i
= 0; i
< n
- 1; i
++) {
569 ASSERT((GLint
) (lambda
[i
] * 10) <= (GLint
) (lambda
[i
+1] * 10));
575 /* since lambda is monotonous-array use this check first */
576 if (lambda
[0] <= minMagThresh
&& lambda
[n
-1] <= minMagThresh
) {
577 /* magnification for whole span */
580 *minStart
= *minEnd
= 0;
582 else if (lambda
[0] > minMagThresh
&& lambda
[n
-1] > minMagThresh
) {
583 /* minification for whole span */
586 *magStart
= *magEnd
= 0;
589 /* a mix of minification and magnification */
591 if (lambda
[0] > minMagThresh
) {
592 /* start with minification */
593 for (i
= 1; i
< n
; i
++) {
594 if (lambda
[i
] <= minMagThresh
)
603 /* start with magnification */
604 for (i
= 1; i
< n
; i
++) {
605 if (lambda
[i
] > minMagThresh
)
616 /* Verify the min/mag Start/End values
617 * We don't use this either (see above)
621 for (i
= 0; i
< n
; i
++) {
622 if (lambda
[i
] > minMagThresh
) {
624 ASSERT(i
>= *minStart
);
629 ASSERT(i
>= *magStart
);
638 /**********************************************************************/
639 /* 1-D Texture Sampling Functions */
640 /**********************************************************************/
643 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
646 sample_1d_nearest(GLcontext
*ctx
,
647 const struct gl_texture_object
*tObj
,
648 const struct gl_texture_image
*img
,
649 const GLfloat texcoord
[4], GLchan rgba
[4])
651 const GLint width
= img
->Width2
; /* without border, power of two */
654 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
656 /* skip over the border, if any */
659 if (i
< 0 || i
>= (GLint
) img
->Width
) {
660 /* Need this test for GL_CLAMP_TO_BORDER mode */
661 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
664 (*img
->FetchTexel
)(img
, i
, 0, 0, (GLvoid
*) rgba
);
665 if (img
->Format
== GL_COLOR_INDEX
) {
666 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
674 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
677 sample_1d_linear(GLcontext
*ctx
,
678 const struct gl_texture_object
*tObj
,
679 const struct gl_texture_image
*img
,
680 const GLfloat texcoord
[4], GLchan rgba
[4])
682 const GLint width
= img
->Width2
;
685 GLuint useBorderColor
;
687 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
695 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
696 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
700 const GLfloat a
= FRAC(u
);
702 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
703 const GLfloat w0
= (1.0F
-a
);
704 const GLfloat w1
= a
;
705 #else /* CHAN_BITS == 8 */
706 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
707 const GLint w0
= IROUND_POS((1.0F
- a
) * WEIGHT_SCALE
);
708 const GLint w1
= IROUND_POS( a
* WEIGHT_SCALE
);
710 GLchan t0
[4], t1
[4]; /* texels */
712 if (useBorderColor
& I0BIT
) {
713 COPY_CHAN4(t0
, tObj
->_BorderChan
);
716 (*img
->FetchTexel
)(img
, i0
, 0, 0, (GLvoid
*) t0
);
717 if (img
->Format
== GL_COLOR_INDEX
) {
718 palette_sample(ctx
, tObj
, t0
[0], t0
);
721 if (useBorderColor
& I1BIT
) {
722 COPY_CHAN4(t1
, tObj
->_BorderChan
);
725 (*img
->FetchTexel
)(img
, i1
, 0, 0, (GLvoid
*) t1
);
726 if (img
->Format
== GL_COLOR_INDEX
) {
727 palette_sample(ctx
, tObj
, t1
[0], t1
);
731 #if CHAN_TYPE == GL_FLOAT
732 rgba
[0] = w0
* t0
[0] + w1
* t1
[0];
733 rgba
[1] = w0
* t0
[1] + w1
* t1
[1];
734 rgba
[2] = w0
* t0
[2] + w1
* t1
[2];
735 rgba
[3] = w0
* t0
[3] + w1
* t1
[3];
736 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
737 rgba
[0] = (GLchan
) (w0
* t0
[0] + w1
* t1
[0] + 0.5);
738 rgba
[1] = (GLchan
) (w0
* t0
[1] + w1
* t1
[1] + 0.5);
739 rgba
[2] = (GLchan
) (w0
* t0
[2] + w1
* t1
[2] + 0.5);
740 rgba
[3] = (GLchan
) (w0
* t0
[3] + w1
* t1
[3] + 0.5);
741 #else /* CHAN_BITS == 8 */
742 rgba
[0] = (GLchan
) ((w0
* t0
[0] + w1
* t1
[0]) >> WEIGHT_SHIFT
);
743 rgba
[1] = (GLchan
) ((w0
* t0
[1] + w1
* t1
[1]) >> WEIGHT_SHIFT
);
744 rgba
[2] = (GLchan
) ((w0
* t0
[2] + w1
* t1
[2]) >> WEIGHT_SHIFT
);
745 rgba
[3] = (GLchan
) ((w0
* t0
[3] + w1
* t1
[3]) >> WEIGHT_SHIFT
);
753 sample_1d_nearest_mipmap_nearest(GLcontext
*ctx
,
754 const struct gl_texture_object
*tObj
,
755 GLuint n
, GLfloat texcoord
[][4],
756 const GLfloat lambda
[], GLchan rgba
[][4])
759 ASSERT(lambda
!= NULL
);
760 for (i
= 0; i
< n
; i
++) {
762 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
763 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
769 sample_1d_linear_mipmap_nearest(GLcontext
*ctx
,
770 const struct gl_texture_object
*tObj
,
771 GLuint n
, GLfloat texcoord
[][4],
772 const GLfloat lambda
[], GLchan rgba
[][4])
775 ASSERT(lambda
!= NULL
);
776 for (i
= 0; i
< n
; i
++) {
778 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
779 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
786 * This is really just needed in order to prevent warnings with some compilers.
788 #if CHAN_TYPE == GL_FLOAT
791 #define CHAN_CAST (GLchan) (GLint)
796 sample_1d_nearest_mipmap_linear(GLcontext
*ctx
,
797 const struct gl_texture_object
*tObj
,
798 GLuint n
, GLfloat texcoord
[][4],
799 const GLfloat lambda
[], GLchan rgba
[][4])
802 ASSERT(lambda
!= NULL
);
803 for (i
= 0; i
< n
; i
++) {
805 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
806 if (level
>= tObj
->_MaxLevel
) {
807 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
808 texcoord
[i
], rgba
[i
]);
812 const GLfloat f
= FRAC(lambda
[i
]);
813 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
814 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
815 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
816 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
817 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
818 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
826 sample_1d_linear_mipmap_linear(GLcontext
*ctx
,
827 const struct gl_texture_object
*tObj
,
828 GLuint n
, GLfloat texcoord
[][4],
829 const GLfloat lambda
[], GLchan rgba
[][4])
832 ASSERT(lambda
!= NULL
);
833 for (i
= 0; i
< n
; i
++) {
835 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
836 if (level
>= tObj
->_MaxLevel
) {
837 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
838 texcoord
[i
], rgba
[i
]);
842 const GLfloat f
= FRAC(lambda
[i
]);
843 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
844 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
845 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
846 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
847 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
848 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
856 sample_nearest_1d( GLcontext
*ctx
, GLuint texUnit
,
857 const struct gl_texture_object
*tObj
, GLuint n
,
858 GLfloat texcoords
[][4], const GLfloat lambda
[],
862 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
865 sample_1d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
867 if (ctx
->Texture
.ColorTableEnabled
) {
868 texture_table_lookup(&ctx
->TextureColorTable
, n
, rgba
);
876 sample_linear_1d( GLcontext
*ctx
, GLuint texUnit
,
877 const struct gl_texture_object
*tObj
, GLuint n
,
878 GLfloat texcoords
[][4], const GLfloat lambda
[],
882 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
885 sample_1d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
887 if (ctx
->Texture
.ColorTableEnabled
) {
888 texture_table_lookup(&ctx
->TextureColorTable
, n
, rgba
);
894 * Given an (s) texture coordinate and lambda (level of detail) value,
895 * return a texture sample.
899 sample_lambda_1d( GLcontext
*ctx
, GLuint texUnit
,
900 const struct gl_texture_object
*tObj
, GLuint n
,
901 GLfloat texcoords
[][4],
902 const GLfloat lambda
[], GLchan rgba
[][4] )
904 GLuint minStart
, minEnd
; /* texels with minification */
905 GLuint magStart
, magEnd
; /* texels with magnification */
908 ASSERT(lambda
!= NULL
);
909 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
910 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
912 if (minStart
< minEnd
) {
913 /* do the minified texels */
914 const GLuint m
= minEnd
- minStart
;
915 switch (tObj
->MinFilter
) {
917 for (i
= minStart
; i
< minEnd
; i
++)
918 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
919 texcoords
[i
], rgba
[i
]);
922 for (i
= minStart
; i
< minEnd
; i
++)
923 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
924 texcoords
[i
], rgba
[i
]);
926 case GL_NEAREST_MIPMAP_NEAREST
:
927 sample_1d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
928 lambda
+ minStart
, rgba
+ minStart
);
930 case GL_LINEAR_MIPMAP_NEAREST
:
931 sample_1d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
932 lambda
+ minStart
, rgba
+ minStart
);
934 case GL_NEAREST_MIPMAP_LINEAR
:
935 sample_1d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
936 lambda
+ minStart
, rgba
+ minStart
);
938 case GL_LINEAR_MIPMAP_LINEAR
:
939 sample_1d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
940 lambda
+ minStart
, rgba
+ minStart
);
943 _mesa_problem(ctx
, "Bad min filter in sample_1d_texture");
948 if (magStart
< magEnd
) {
949 /* do the magnified texels */
950 switch (tObj
->MagFilter
) {
952 for (i
= magStart
; i
< magEnd
; i
++)
953 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
954 texcoords
[i
], rgba
[i
]);
957 for (i
= magStart
; i
< magEnd
; i
++)
958 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
959 texcoords
[i
], rgba
[i
]);
962 _mesa_problem(ctx
, "Bad mag filter in sample_1d_texture");
966 if (ctx
->Texture
.ColorTableEnabled
) {
967 texture_table_lookup(&ctx
->TextureColorTable
, n
, rgba
);
972 /**********************************************************************/
973 /* 2-D Texture Sampling Functions */
974 /**********************************************************************/
978 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
981 sample_2d_nearest(GLcontext
*ctx
,
982 const struct gl_texture_object
*tObj
,
983 const struct gl_texture_image
*img
,
984 const GLfloat texcoord
[4],
987 const GLint width
= img
->Width2
; /* without border, power of two */
988 const GLint height
= img
->Height2
; /* without border, power of two */
991 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
992 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
994 /* skip over the border, if any */
998 if (i
< 0 || i
>= (GLint
) img
->Width
|| j
< 0 || j
>= (GLint
) img
->Height
) {
999 /* Need this test for GL_CLAMP_TO_BORDER mode */
1000 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
1003 (*img
->FetchTexel
)(img
, i
, j
, 0, (GLvoid
*) rgba
);
1004 if (img
->Format
== GL_COLOR_INDEX
) {
1005 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
1013 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
1014 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
1017 sample_2d_linear(GLcontext
*ctx
,
1018 const struct gl_texture_object
*tObj
,
1019 const struct gl_texture_image
*img
,
1020 const GLfloat texcoord
[4],
1023 const GLint width
= img
->Width2
;
1024 const GLint height
= img
->Height2
;
1025 GLint i0
, j0
, i1
, j1
;
1026 GLuint useBorderColor
;
1029 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1030 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1040 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1041 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1042 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1043 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1047 const GLfloat a
= FRAC(u
);
1048 const GLfloat b
= FRAC(v
);
1050 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1051 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
1052 const GLfloat w10
= a
* (1.0F
-b
);
1053 const GLfloat w01
= (1.0F
-a
) * b
;
1054 const GLfloat w11
= a
* b
;
1055 #else /* CHAN_BITS == 8 */
1056 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1057 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
1058 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
1059 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
1060 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
1067 if (useBorderColor
& (I0BIT
| J0BIT
)) {
1068 COPY_CHAN4(t00
, tObj
->_BorderChan
);
1071 (*img
->FetchTexel
)(img
, i0
, j0
, 0, (GLvoid
*) t00
);
1072 if (img
->Format
== GL_COLOR_INDEX
) {
1073 palette_sample(ctx
, tObj
, t00
[0], t00
);
1076 if (useBorderColor
& (I1BIT
| J0BIT
)) {
1077 COPY_CHAN4(t10
, tObj
->_BorderChan
);
1080 (*img
->FetchTexel
)(img
, i1
, j0
, 0, (GLvoid
*) t10
);
1081 if (img
->Format
== GL_COLOR_INDEX
) {
1082 palette_sample(ctx
, tObj
, t10
[0], t10
);
1085 if (useBorderColor
& (I0BIT
| J1BIT
)) {
1086 COPY_CHAN4(t01
, tObj
->_BorderChan
);
1089 (*img
->FetchTexel
)(img
, i0
, j1
, 0, (GLvoid
*) t01
);
1090 if (img
->Format
== GL_COLOR_INDEX
) {
1091 palette_sample(ctx
, tObj
, t01
[0], t01
);
1094 if (useBorderColor
& (I1BIT
| J1BIT
)) {
1095 COPY_CHAN4(t11
, tObj
->_BorderChan
);
1098 (*img
->FetchTexel
)(img
, i1
, j1
, 0, (GLvoid
*) t11
);
1099 if (img
->Format
== GL_COLOR_INDEX
) {
1100 palette_sample(ctx
, tObj
, t11
[0], t11
);
1103 #if CHAN_TYPE == GL_FLOAT
1104 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
1105 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
1106 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
1107 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
1108 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1109 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
1110 w01
* t01
[0] + w11
* t11
[0] + 0.5);
1111 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
1112 w01
* t01
[1] + w11
* t11
[1] + 0.5);
1113 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
1114 w01
* t01
[2] + w11
* t11
[2] + 0.5);
1115 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
1116 w01
* t01
[3] + w11
* t11
[3] + 0.5);
1117 #else /* CHAN_BITS == 8 */
1118 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
1119 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
1120 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
1121 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
1122 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
1123 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
1124 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
1125 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
1134 * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT
1135 * and we're not using a paletted texture.
1138 sample_2d_linear_repeat(GLcontext
*ctx
,
1139 const struct gl_texture_object
*tObj
,
1140 const struct gl_texture_image
*img
,
1141 const GLfloat texcoord
[4],
1144 const GLint width
= img
->Width2
;
1145 const GLint height
= img
->Height2
;
1146 GLint i0
, j0
, i1
, j1
;
1149 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1150 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1151 ASSERT(img
->Border
== 0);
1152 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
1154 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[0], u
, width
, i0
, i1
);
1155 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[1], v
, height
, j0
, j1
);
1158 const GLfloat a
= FRAC(u
);
1159 const GLfloat b
= FRAC(v
);
1161 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1162 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
1163 const GLfloat w10
= a
* (1.0F
-b
);
1164 const GLfloat w01
= (1.0F
-a
) * b
;
1165 const GLfloat w11
= a
* b
;
1166 #else /* CHAN_BITS == 8 */
1167 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1168 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
1169 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
1170 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
1171 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
1178 (*img
->FetchTexel
)(img
, i0
, j0
, 0, (GLvoid
*) t00
);
1179 (*img
->FetchTexel
)(img
, i1
, j0
, 0, (GLvoid
*) t10
);
1180 (*img
->FetchTexel
)(img
, i0
, j1
, 0, (GLvoid
*) t01
);
1181 (*img
->FetchTexel
)(img
, i1
, j1
, 0, (GLvoid
*) t11
);
1183 #if CHAN_TYPE == GL_FLOAT
1184 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
1185 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
1186 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
1187 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
1188 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1189 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
1190 w01
* t01
[0] + w11
* t11
[0] + 0.5);
1191 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
1192 w01
* t01
[1] + w11
* t11
[1] + 0.5);
1193 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
1194 w01
* t01
[2] + w11
* t11
[2] + 0.5);
1195 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
1196 w01
* t01
[3] + w11
* t11
[3] + 0.5);
1197 #else /* CHAN_BITS == 8 */
1198 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
1199 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
1200 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
1201 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
1202 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
1203 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
1204 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
1205 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
1215 sample_2d_nearest_mipmap_nearest(GLcontext
*ctx
,
1216 const struct gl_texture_object
*tObj
,
1217 GLuint n
, GLfloat texcoord
[][4],
1218 const GLfloat lambda
[], GLchan rgba
[][4])
1221 for (i
= 0; i
< n
; i
++) {
1223 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1224 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1231 sample_2d_linear_mipmap_nearest(GLcontext
*ctx
,
1232 const struct gl_texture_object
*tObj
,
1233 GLuint n
, GLfloat texcoord
[][4],
1234 const GLfloat lambda
[], GLchan rgba
[][4])
1237 ASSERT(lambda
!= NULL
);
1238 for (i
= 0; i
< n
; i
++) {
1240 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1241 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1248 sample_2d_nearest_mipmap_linear(GLcontext
*ctx
,
1249 const struct gl_texture_object
*tObj
,
1250 GLuint n
, GLfloat texcoord
[][4],
1251 const GLfloat lambda
[], GLchan rgba
[][4])
1254 ASSERT(lambda
!= NULL
);
1255 for (i
= 0; i
< n
; i
++) {
1257 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1258 if (level
>= tObj
->_MaxLevel
) {
1259 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1260 texcoord
[i
], rgba
[i
]);
1263 GLchan t0
[4], t1
[4]; /* texels */
1264 const GLfloat f
= FRAC(lambda
[i
]);
1265 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1266 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1267 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1268 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1269 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1270 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1277 /* Trilinear filtering */
1279 sample_2d_linear_mipmap_linear( GLcontext
*ctx
,
1280 const struct gl_texture_object
*tObj
,
1281 GLuint n
, GLfloat texcoord
[][4],
1282 const GLfloat lambda
[], GLchan rgba
[][4] )
1285 ASSERT(lambda
!= NULL
);
1286 for (i
= 0; i
< n
; i
++) {
1288 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1289 if (level
>= tObj
->_MaxLevel
) {
1290 sample_2d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1291 texcoord
[i
], rgba
[i
]);
1294 GLchan t0
[4], t1
[4]; /* texels */
1295 const GLfloat f
= FRAC(lambda
[i
]);
1296 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1297 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1298 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1299 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1300 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1301 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1308 sample_2d_linear_mipmap_linear_repeat( GLcontext
*ctx
,
1309 const struct gl_texture_object
*tObj
,
1310 GLuint n
, GLfloat texcoord
[][4],
1311 const GLfloat lambda
[], GLchan rgba
[][4] )
1314 ASSERT(lambda
!= NULL
);
1315 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1316 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1317 for (i
= 0; i
< n
; i
++) {
1319 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1320 if (level
>= tObj
->_MaxLevel
) {
1321 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1322 texcoord
[i
], rgba
[i
]);
1325 GLchan t0
[4], t1
[4]; /* texels */
1326 const GLfloat f
= FRAC(lambda
[i
]);
1327 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1328 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1329 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1330 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1331 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1332 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1339 sample_nearest_2d( GLcontext
*ctx
, GLuint texUnit
,
1340 const struct gl_texture_object
*tObj
, GLuint n
,
1341 GLfloat texcoords
[][4],
1342 const GLfloat lambda
[], GLchan rgba
[][4] )
1345 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1348 sample_2d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1350 if (ctx
->Texture
.ColorTableEnabled
) {
1351 texture_table_lookup(&ctx
->TextureColorTable
, n
, rgba
);
1358 sample_linear_2d( GLcontext
*ctx
, GLuint texUnit
,
1359 const struct gl_texture_object
*tObj
, GLuint n
,
1360 GLfloat texcoords
[][4],
1361 const GLfloat lambda
[], GLchan rgba
[][4] )
1364 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1367 sample_2d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1369 if (ctx
->Texture
.ColorTableEnabled
) {
1370 texture_table_lookup(&ctx
->TextureColorTable
, n
, rgba
);
1376 * Optimized 2-D texture sampling:
1377 * S and T wrap mode == GL_REPEAT
1378 * GL_NEAREST min/mag filter
1380 * RowStride == Width,
1384 opt_sample_rgb_2d( GLcontext
*ctx
, GLuint texUnit
,
1385 const struct gl_texture_object
*tObj
,
1386 GLuint n
, GLfloat texcoords
[][4],
1387 const GLfloat lambda
[], GLchan rgba
[][4] )
1389 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
1390 const GLfloat width
= (GLfloat
) img
->Width
;
1391 const GLfloat height
= (GLfloat
) img
->Height
;
1392 const GLint colMask
= img
->Width
- 1;
1393 const GLint rowMask
= img
->Height
- 1;
1394 const GLint shift
= img
->WidthLog2
;
1397 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1398 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1399 ASSERT(img
->Border
==0);
1400 ASSERT(img
->Format
==GL_RGB
);
1402 for (k
=0; k
<n
; k
++) {
1403 GLint i
= IFLOOR(texcoords
[k
][0] * width
) & colMask
;
1404 GLint j
= IFLOOR(texcoords
[k
][1] * height
) & rowMask
;
1405 GLint pos
= (j
<< shift
) | i
;
1406 GLchan
*texel
= ((GLchan
*) img
->Data
) + 3*pos
;
1407 rgba
[k
][RCOMP
] = texel
[0];
1408 rgba
[k
][GCOMP
] = texel
[1];
1409 rgba
[k
][BCOMP
] = texel
[2];
1415 * Optimized 2-D texture sampling:
1416 * S and T wrap mode == GL_REPEAT
1417 * GL_NEAREST min/mag filter
1419 * RowStride == Width,
1423 opt_sample_rgba_2d( GLcontext
*ctx
, GLuint texUnit
,
1424 const struct gl_texture_object
*tObj
,
1425 GLuint n
, GLfloat texcoords
[][4],
1426 const GLfloat lambda
[], GLchan rgba
[][4] )
1428 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
1429 const GLfloat width
= (GLfloat
) img
->Width
;
1430 const GLfloat height
= (GLfloat
) img
->Height
;
1431 const GLint colMask
= img
->Width
- 1;
1432 const GLint rowMask
= img
->Height
- 1;
1433 const GLint shift
= img
->WidthLog2
;
1436 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1437 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1438 ASSERT(img
->Border
==0);
1439 ASSERT(img
->Format
==GL_RGBA
);
1441 for (i
= 0; i
< n
; i
++) {
1442 const GLint col
= IFLOOR(texcoords
[i
][0] * width
) & colMask
;
1443 const GLint row
= IFLOOR(texcoords
[i
][1] * height
) & rowMask
;
1444 const GLint pos
= (row
<< shift
) | col
;
1445 const GLchan
*texel
= ((GLchan
*) img
->Data
) + (pos
<< 2); /* pos*4 */
1446 COPY_CHAN4(rgba
[i
], texel
);
1452 * Given an array of texture coordinate and lambda (level of detail)
1453 * values, return an array of texture sample.
1456 sample_lambda_2d( GLcontext
*ctx
, GLuint texUnit
,
1457 const struct gl_texture_object
*tObj
,
1458 GLuint n
, GLfloat texcoords
[][4],
1459 const GLfloat lambda
[], GLchan rgba
[][4] )
1461 const struct gl_texture_image
*tImg
= tObj
->Image
[tObj
->BaseLevel
];
1462 GLuint minStart
, minEnd
; /* texels with minification */
1463 GLuint magStart
, magEnd
; /* texels with magnification */
1465 const GLboolean repeatNoBorder
= (tObj
->WrapS
== GL_REPEAT
)
1466 && (tObj
->WrapT
== GL_REPEAT
)
1467 && (tImg
->Border
== 0 && (tImg
->Width
== tImg
->RowStride
))
1468 && (tImg
->Format
!= GL_COLOR_INDEX
);
1470 ASSERT(lambda
!= NULL
);
1471 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1472 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1474 if (minStart
< minEnd
) {
1475 /* do the minified texels */
1476 const GLuint m
= minEnd
- minStart
;
1477 switch (tObj
->MinFilter
) {
1479 if (repeatNoBorder
) {
1480 switch (tImg
->Format
) {
1482 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1483 NULL
, rgba
+ minStart
);
1486 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1487 NULL
, rgba
+ minStart
);
1490 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1491 NULL
, rgba
+ minStart
);
1495 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1496 NULL
, rgba
+ minStart
);
1500 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1501 NULL
, rgba
+ minStart
);
1503 case GL_NEAREST_MIPMAP_NEAREST
:
1504 sample_2d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1505 lambda
+ minStart
, rgba
+ minStart
);
1507 case GL_LINEAR_MIPMAP_NEAREST
:
1508 sample_2d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1509 lambda
+ minStart
, rgba
+ minStart
);
1511 case GL_NEAREST_MIPMAP_LINEAR
:
1512 sample_2d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1513 lambda
+ minStart
, rgba
+ minStart
);
1515 case GL_LINEAR_MIPMAP_LINEAR
:
1517 sample_2d_linear_mipmap_linear_repeat(ctx
, tObj
, m
,
1518 texcoords
+ minStart
, lambda
+ minStart
, rgba
+ minStart
);
1520 sample_2d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1521 lambda
+ minStart
, rgba
+ minStart
);
1524 _mesa_problem(ctx
, "Bad min filter in sample_2d_texture");
1529 if (magStart
< magEnd
) {
1530 /* do the magnified texels */
1531 const GLuint m
= magEnd
- magStart
;
1533 switch (tObj
->MagFilter
) {
1535 if (repeatNoBorder
) {
1536 switch (tImg
->Format
) {
1538 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1539 NULL
, rgba
+ magStart
);
1542 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1543 NULL
, rgba
+ magStart
);
1546 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1547 NULL
, rgba
+ magStart
);
1551 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1552 NULL
, rgba
+ magStart
);
1556 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1557 NULL
, rgba
+ magStart
);
1560 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_2d");
1563 if (ctx
->Texture
.ColorTableEnabled
) {
1564 texture_table_lookup(&ctx
->TextureColorTable
, n
, rgba
);
1570 /**********************************************************************/
1571 /* 3-D Texture Sampling Functions */
1572 /**********************************************************************/
1575 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1578 sample_3d_nearest(GLcontext
*ctx
,
1579 const struct gl_texture_object
*tObj
,
1580 const struct gl_texture_image
*img
,
1581 const GLfloat texcoord
[4],
1584 const GLint width
= img
->Width2
; /* without border, power of two */
1585 const GLint height
= img
->Height2
; /* without border, power of two */
1586 const GLint depth
= img
->Depth2
; /* without border, power of two */
1589 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
1590 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
1591 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapR
, texcoord
[2], depth
, k
);
1593 if (i
< 0 || i
>= (GLint
) img
->Width
||
1594 j
< 0 || j
>= (GLint
) img
->Height
||
1595 k
< 0 || k
>= (GLint
) img
->Depth
) {
1596 /* Need this test for GL_CLAMP_TO_BORDER mode */
1597 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
1600 (*img
->FetchTexel
)(img
, i
, j
, k
, (GLvoid
*) rgba
);
1601 if (img
->Format
== GL_COLOR_INDEX
) {
1602 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
1610 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1613 sample_3d_linear(GLcontext
*ctx
,
1614 const struct gl_texture_object
*tObj
,
1615 const struct gl_texture_image
*img
,
1616 const GLfloat texcoord
[4],
1619 const GLint width
= img
->Width2
;
1620 const GLint height
= img
->Height2
;
1621 const GLint depth
= img
->Depth2
;
1622 GLint i0
, j0
, k0
, i1
, j1
, k1
;
1623 GLuint useBorderColor
;
1626 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1627 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1628 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapR
, texcoord
[2], w
, depth
, k0
, k1
);
1640 /* check if sampling texture border color */
1641 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1642 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1643 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1644 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1645 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
1646 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
1650 const GLfloat a
= FRAC(u
);
1651 const GLfloat b
= FRAC(v
);
1652 const GLfloat c
= FRAC(w
);
1654 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1655 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1656 GLfloat w000
= (1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
);
1657 GLfloat w100
= a
* (1.0F
-b
) * (1.0F
-c
);
1658 GLfloat w010
= (1.0F
-a
) * b
* (1.0F
-c
);
1659 GLfloat w110
= a
* b
* (1.0F
-c
);
1660 GLfloat w001
= (1.0F
-a
) * (1.0F
-b
) * c
;
1661 GLfloat w101
= a
* (1.0F
-b
) * c
;
1662 GLfloat w011
= (1.0F
-a
) * b
* c
;
1663 GLfloat w111
= a
* b
* c
;
1664 #else /* CHAN_BITS == 8 */
1665 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1666 GLint w000
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1667 GLint w100
= IROUND_POS( a
* (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1668 GLint w010
= IROUND_POS((1.0F
-a
) * b
* (1.0F
-c
) * WEIGHT_SCALE
);
1669 GLint w110
= IROUND_POS( a
* b
* (1.0F
-c
) * WEIGHT_SCALE
);
1670 GLint w001
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * c
* WEIGHT_SCALE
);
1671 GLint w101
= IROUND_POS( a
* (1.0F
-b
) * c
* WEIGHT_SCALE
);
1672 GLint w011
= IROUND_POS((1.0F
-a
) * b
* c
* WEIGHT_SCALE
);
1673 GLint w111
= IROUND_POS( a
* b
* c
* WEIGHT_SCALE
);
1676 GLchan t000
[4], t010
[4], t001
[4], t011
[4];
1677 GLchan t100
[4], t110
[4], t101
[4], t111
[4];
1679 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
1680 COPY_CHAN4(t000
, tObj
->_BorderChan
);
1683 (*img
->FetchTexel
)(img
, i0
, j0
, k0
, (GLvoid
*) t000
);
1684 if (img
->Format
== GL_COLOR_INDEX
) {
1685 palette_sample(ctx
, tObj
, t000
[0], t000
);
1688 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
1689 COPY_CHAN4(t100
, tObj
->_BorderChan
);
1692 (*img
->FetchTexel
)(img
, i1
, j0
, k0
, (GLvoid
*) t100
);
1693 if (img
->Format
== GL_COLOR_INDEX
) {
1694 palette_sample(ctx
, tObj
, t100
[0], t100
);
1697 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
1698 COPY_CHAN4(t010
, tObj
->_BorderChan
);
1701 (*img
->FetchTexel
)(img
, i0
, j1
, k0
, (GLvoid
*) t010
);
1702 if (img
->Format
== GL_COLOR_INDEX
) {
1703 palette_sample(ctx
, tObj
, t010
[0], t010
);
1706 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
1707 COPY_CHAN4(t110
, tObj
->_BorderChan
);
1710 (*img
->FetchTexel
)(img
, i1
, j1
, k0
, (GLvoid
*) t110
);
1711 if (img
->Format
== GL_COLOR_INDEX
) {
1712 palette_sample(ctx
, tObj
, t110
[0], t110
);
1716 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
1717 COPY_CHAN4(t001
, tObj
->_BorderChan
);
1720 (*img
->FetchTexel
)(img
, i0
, j0
, k1
, (GLvoid
*) t001
);
1721 if (img
->Format
== GL_COLOR_INDEX
) {
1722 palette_sample(ctx
, tObj
, t001
[0], t001
);
1725 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
1726 COPY_CHAN4(t101
, tObj
->_BorderChan
);
1729 (*img
->FetchTexel
)(img
, i1
, j0
, k1
, (GLvoid
*) t101
);
1730 if (img
->Format
== GL_COLOR_INDEX
) {
1731 palette_sample(ctx
, tObj
, t101
[0], t101
);
1734 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
1735 COPY_CHAN4(t011
, tObj
->_BorderChan
);
1738 (*img
->FetchTexel
)(img
, i0
, j1
, k1
, (GLvoid
*) t011
);
1739 if (img
->Format
== GL_COLOR_INDEX
) {
1740 palette_sample(ctx
, tObj
, t011
[0], t011
);
1743 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
1744 COPY_CHAN4(t111
, tObj
->_BorderChan
);
1747 (*img
->FetchTexel
)(img
, i1
, j1
, k1
, (GLvoid
*) t111
);
1748 if (img
->Format
== GL_COLOR_INDEX
) {
1749 palette_sample(ctx
, tObj
, t111
[0], t111
);
1753 #if CHAN_TYPE == GL_FLOAT
1754 rgba
[0] = w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1755 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0];
1756 rgba
[1] = w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1757 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1];
1758 rgba
[2] = w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1759 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2];
1760 rgba
[3] = w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1761 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3];
1762 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1763 rgba
[0] = (GLchan
) (w000
*t000
[0] + w010
*t010
[0] +
1764 w001
*t001
[0] + w011
*t011
[0] +
1765 w100
*t100
[0] + w110
*t110
[0] +
1766 w101
*t101
[0] + w111
*t111
[0] + 0.5);
1767 rgba
[1] = (GLchan
) (w000
*t000
[1] + w010
*t010
[1] +
1768 w001
*t001
[1] + w011
*t011
[1] +
1769 w100
*t100
[1] + w110
*t110
[1] +
1770 w101
*t101
[1] + w111
*t111
[1] + 0.5);
1771 rgba
[2] = (GLchan
) (w000
*t000
[2] + w010
*t010
[2] +
1772 w001
*t001
[2] + w011
*t011
[2] +
1773 w100
*t100
[2] + w110
*t110
[2] +
1774 w101
*t101
[2] + w111
*t111
[2] + 0.5);
1775 rgba
[3] = (GLchan
) (w000
*t000
[3] + w010
*t010
[3] +
1776 w001
*t001
[3] + w011
*t011
[3] +
1777 w100
*t100
[3] + w110
*t110
[3] +
1778 w101
*t101
[3] + w111
*t111
[3] + 0.5);
1779 #else /* CHAN_BITS == 8 */
1780 rgba
[0] = (GLchan
) (
1781 (w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1782 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0] )
1784 rgba
[1] = (GLchan
) (
1785 (w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1786 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1] )
1788 rgba
[2] = (GLchan
) (
1789 (w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1790 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2] )
1792 rgba
[3] = (GLchan
) (
1793 (w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1794 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3] )
1804 sample_3d_nearest_mipmap_nearest(GLcontext
*ctx
,
1805 const struct gl_texture_object
*tObj
,
1806 GLuint n
, GLfloat texcoord
[][4],
1807 const GLfloat lambda
[], GLchan rgba
[][4] )
1810 for (i
= 0; i
< n
; i
++) {
1812 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1813 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1819 sample_3d_linear_mipmap_nearest(GLcontext
*ctx
,
1820 const struct gl_texture_object
*tObj
,
1821 GLuint n
, GLfloat texcoord
[][4],
1822 const GLfloat lambda
[], GLchan rgba
[][4])
1825 ASSERT(lambda
!= NULL
);
1826 for (i
= 0; i
< n
; i
++) {
1828 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1829 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1835 sample_3d_nearest_mipmap_linear(GLcontext
*ctx
,
1836 const struct gl_texture_object
*tObj
,
1837 GLuint n
, GLfloat texcoord
[][4],
1838 const GLfloat lambda
[], GLchan rgba
[][4])
1841 ASSERT(lambda
!= NULL
);
1842 for (i
= 0; i
< n
; i
++) {
1844 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1845 if (level
>= tObj
->_MaxLevel
) {
1846 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1847 texcoord
[i
], rgba
[i
]);
1850 GLchan t0
[4], t1
[4]; /* texels */
1851 const GLfloat f
= FRAC(lambda
[i
]);
1852 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1853 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1854 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1855 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1856 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1857 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1864 sample_3d_linear_mipmap_linear(GLcontext
*ctx
,
1865 const struct gl_texture_object
*tObj
,
1866 GLuint n
, GLfloat texcoord
[][4],
1867 const GLfloat lambda
[], GLchan rgba
[][4])
1870 ASSERT(lambda
!= NULL
);
1871 for (i
= 0; i
< n
; i
++) {
1873 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1874 if (level
>= tObj
->_MaxLevel
) {
1875 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1876 texcoord
[i
], rgba
[i
]);
1879 GLchan t0
[4], t1
[4]; /* texels */
1880 const GLfloat f
= FRAC(lambda
[i
]);
1881 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1882 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1883 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1884 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1885 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1886 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1893 sample_nearest_3d(GLcontext
*ctx
, GLuint texUnit
,
1894 const struct gl_texture_object
*tObj
, GLuint n
,
1895 GLfloat texcoords
[][4], const GLfloat lambda
[],
1899 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1902 sample_3d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1904 if (ctx
->Texture
.ColorTableEnabled
) {
1905 texture_table_lookup(&ctx
->TextureColorTable
, n
, rgba
);
1912 sample_linear_3d( GLcontext
*ctx
, GLuint texUnit
,
1913 const struct gl_texture_object
*tObj
, GLuint n
,
1914 GLfloat texcoords
[][4],
1915 const GLfloat lambda
[], GLchan rgba
[][4] )
1918 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1921 sample_3d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1923 if (ctx
->Texture
.ColorTableEnabled
) {
1924 texture_table_lookup(&ctx
->TextureColorTable
, n
, rgba
);
1930 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
1931 * return a texture sample.
1934 sample_lambda_3d( GLcontext
*ctx
, GLuint texUnit
,
1935 const struct gl_texture_object
*tObj
, GLuint n
,
1936 GLfloat texcoords
[][4], const GLfloat lambda
[],
1939 GLuint minStart
, minEnd
; /* texels with minification */
1940 GLuint magStart
, magEnd
; /* texels with magnification */
1943 ASSERT(lambda
!= NULL
);
1944 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1945 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1947 if (minStart
< minEnd
) {
1948 /* do the minified texels */
1949 GLuint m
= minEnd
- minStart
;
1950 switch (tObj
->MinFilter
) {
1952 for (i
= minStart
; i
< minEnd
; i
++)
1953 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1954 texcoords
[i
], rgba
[i
]);
1957 for (i
= minStart
; i
< minEnd
; i
++)
1958 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1959 texcoords
[i
], rgba
[i
]);
1961 case GL_NEAREST_MIPMAP_NEAREST
:
1962 sample_3d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1963 lambda
+ minStart
, rgba
+ minStart
);
1965 case GL_LINEAR_MIPMAP_NEAREST
:
1966 sample_3d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1967 lambda
+ minStart
, rgba
+ minStart
);
1969 case GL_NEAREST_MIPMAP_LINEAR
:
1970 sample_3d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1971 lambda
+ minStart
, rgba
+ minStart
);
1973 case GL_LINEAR_MIPMAP_LINEAR
:
1974 sample_3d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1975 lambda
+ minStart
, rgba
+ minStart
);
1978 _mesa_problem(ctx
, "Bad min filter in sample_3d_texture");
1983 if (magStart
< magEnd
) {
1984 /* do the magnified texels */
1985 switch (tObj
->MagFilter
) {
1987 for (i
= magStart
; i
< magEnd
; i
++)
1988 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1989 texcoords
[i
], rgba
[i
]);
1992 for (i
= magStart
; i
< magEnd
; i
++)
1993 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1994 texcoords
[i
], rgba
[i
]);
1997 _mesa_problem(ctx
, "Bad mag filter in sample_3d_texture");
2001 if (ctx
->Texture
.ColorTableEnabled
) {
2002 texture_table_lookup(&ctx
->TextureColorTable
, n
, rgba
);
2007 /**********************************************************************/
2008 /* Texture Cube Map Sampling Functions */
2009 /**********************************************************************/
2012 * Choose one of six sides of a texture cube map given the texture
2013 * coord (rx,ry,rz). Return pointer to corresponding array of texture
2016 static const struct gl_texture_image
**
2017 choose_cube_face(const struct gl_texture_object
*texObj
,
2018 const GLfloat texcoord
[4], GLfloat newCoord
[4])
2022 direction target sc tc ma
2023 ---------- ------------------------------- --- --- ---
2024 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
2025 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
2026 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
2027 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
2028 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
2029 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
2031 const GLfloat rx
= texcoord
[0];
2032 const GLfloat ry
= texcoord
[1];
2033 const GLfloat rz
= texcoord
[2];
2034 const struct gl_texture_image
**imgArray
;
2035 const GLfloat arx
= ABSF(rx
), ary
= ABSF(ry
), arz
= ABSF(rz
);
2038 if (arx
> ary
&& arx
> arz
) {
2040 imgArray
= (const struct gl_texture_image
**) texObj
->Image
;
2046 imgArray
= (const struct gl_texture_image
**) texObj
->NegX
;
2052 else if (ary
> arx
&& ary
> arz
) {
2054 imgArray
= (const struct gl_texture_image
**) texObj
->PosY
;
2060 imgArray
= (const struct gl_texture_image
**) texObj
->NegY
;
2068 imgArray
= (const struct gl_texture_image
**) texObj
->PosZ
;
2074 imgArray
= (const struct gl_texture_image
**) texObj
->NegZ
;
2081 newCoord
[0] = ( sc
/ ma
+ 1.0F
) * 0.5F
;
2082 newCoord
[1] = ( tc
/ ma
+ 1.0F
) * 0.5F
;
2088 sample_nearest_cube(GLcontext
*ctx
, GLuint texUnit
,
2089 const struct gl_texture_object
*tObj
, GLuint n
,
2090 GLfloat texcoords
[][4], const GLfloat lambda
[],
2095 for (i
= 0; i
< n
; i
++) {
2096 const struct gl_texture_image
**images
;
2097 GLfloat newCoord
[4];
2098 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
2099 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
2102 if (ctx
->Texture
.ColorTableEnabled
) {
2103 texture_table_lookup(&ctx
->TextureColorTable
, n
, rgba
);
2109 sample_linear_cube(GLcontext
*ctx
, GLuint texUnit
,
2110 const struct gl_texture_object
*tObj
, GLuint n
,
2111 GLfloat texcoords
[][4],
2112 const GLfloat lambda
[], GLchan rgba
[][4])
2116 for (i
= 0; i
< n
; i
++) {
2117 const struct gl_texture_image
**images
;
2118 GLfloat newCoord
[4];
2119 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
2120 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
2123 if (ctx
->Texture
.ColorTableEnabled
) {
2124 texture_table_lookup(&ctx
->TextureColorTable
, n
, rgba
);
2130 sample_cube_nearest_mipmap_nearest(GLcontext
*ctx
,
2131 const struct gl_texture_object
*tObj
,
2132 GLuint n
, GLfloat texcoord
[][4],
2133 const GLfloat lambda
[], GLchan rgba
[][4])
2136 ASSERT(lambda
!= NULL
);
2137 for (i
= 0; i
< n
; i
++) {
2138 const struct gl_texture_image
**images
;
2139 GLfloat newCoord
[4];
2141 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2142 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2143 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
2145 if (ctx
->Texture
.ColorTableEnabled
) {
2146 texture_table_lookup(&ctx
->TextureColorTable
, n
, rgba
);
2152 sample_cube_linear_mipmap_nearest(GLcontext
*ctx
,
2153 const struct gl_texture_object
*tObj
,
2154 GLuint n
, GLfloat texcoord
[][4],
2155 const GLfloat lambda
[], GLchan rgba
[][4])
2158 ASSERT(lambda
!= NULL
);
2159 for (i
= 0; i
< n
; i
++) {
2160 const struct gl_texture_image
**images
;
2161 GLfloat newCoord
[4];
2163 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2164 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2165 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
2167 if (ctx
->Texture
.ColorTableEnabled
) {
2168 texture_table_lookup(&ctx
->TextureColorTable
, n
, rgba
);
2174 sample_cube_nearest_mipmap_linear(GLcontext
*ctx
,
2175 const struct gl_texture_object
*tObj
,
2176 GLuint n
, GLfloat texcoord
[][4],
2177 const GLfloat lambda
[], GLchan rgba
[][4])
2180 ASSERT(lambda
!= NULL
);
2181 for (i
= 0; i
< n
; i
++) {
2182 const struct gl_texture_image
**images
;
2183 GLfloat newCoord
[4];
2185 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2186 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2187 if (level
>= tObj
->_MaxLevel
) {
2188 sample_2d_nearest(ctx
, tObj
, images
[tObj
->_MaxLevel
],
2192 GLchan t0
[4], t1
[4]; /* texels */
2193 const GLfloat f
= FRAC(lambda
[i
]);
2194 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, t0
);
2195 sample_2d_nearest(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
2196 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
2197 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
2198 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
2199 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
2202 if (ctx
->Texture
.ColorTableEnabled
) {
2203 texture_table_lookup(&ctx
->TextureColorTable
, n
, rgba
);
2209 sample_cube_linear_mipmap_linear(GLcontext
*ctx
,
2210 const struct gl_texture_object
*tObj
,
2211 GLuint n
, GLfloat texcoord
[][4],
2212 const GLfloat lambda
[], GLchan rgba
[][4])
2215 ASSERT(lambda
!= NULL
);
2216 for (i
= 0; i
< n
; i
++) {
2217 const struct gl_texture_image
**images
;
2218 GLfloat newCoord
[4];
2220 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2221 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2222 if (level
>= tObj
->_MaxLevel
) {
2223 sample_2d_linear(ctx
, tObj
, images
[tObj
->_MaxLevel
],
2227 GLchan t0
[4], t1
[4];
2228 const GLfloat f
= FRAC(lambda
[i
]);
2229 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, t0
);
2230 sample_2d_linear(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
2231 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
2232 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
2233 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
2234 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
2237 if (ctx
->Texture
.ColorTableEnabled
) {
2238 texture_table_lookup(&ctx
->TextureColorTable
, n
, rgba
);
2244 sample_lambda_cube( GLcontext
*ctx
, GLuint texUnit
,
2245 const struct gl_texture_object
*tObj
, GLuint n
,
2246 GLfloat texcoords
[][4], const GLfloat lambda
[],
2249 GLuint minStart
, minEnd
; /* texels with minification */
2250 GLuint magStart
, magEnd
; /* texels with magnification */
2252 ASSERT(lambda
!= NULL
);
2253 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2254 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2256 if (minStart
< minEnd
) {
2257 /* do the minified texels */
2258 const GLuint m
= minEnd
- minStart
;
2259 switch (tObj
->MinFilter
) {
2261 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2262 lambda
+ minStart
, rgba
+ minStart
);
2265 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2266 lambda
+ minStart
, rgba
+ minStart
);
2268 case GL_NEAREST_MIPMAP_NEAREST
:
2269 sample_cube_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
2270 lambda
+ minStart
, rgba
+ minStart
);
2272 case GL_LINEAR_MIPMAP_NEAREST
:
2273 sample_cube_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
2274 lambda
+ minStart
, rgba
+ minStart
);
2276 case GL_NEAREST_MIPMAP_LINEAR
:
2277 sample_cube_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
2278 lambda
+ minStart
, rgba
+ minStart
);
2280 case GL_LINEAR_MIPMAP_LINEAR
:
2281 sample_cube_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
2282 lambda
+ minStart
, rgba
+ minStart
);
2285 _mesa_problem(ctx
, "Bad min filter in sample_lambda_cube");
2289 if (magStart
< magEnd
) {
2290 /* do the magnified texels */
2291 const GLuint m
= magEnd
- magStart
;
2292 switch (tObj
->MagFilter
) {
2294 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2295 lambda
+ magStart
, rgba
+ magStart
);
2298 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2299 lambda
+ magStart
, rgba
+ magStart
);
2302 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_cube");
2305 if (ctx
->Texture
.ColorTableEnabled
) {
2306 texture_table_lookup(&ctx
->TextureColorTable
, n
, rgba
);
2311 /**********************************************************************/
2312 /* Texture Rectangle Sampling Functions */
2313 /**********************************************************************/
2316 sample_nearest_rect(GLcontext
*ctx
, GLuint texUnit
,
2317 const struct gl_texture_object
*tObj
, GLuint n
,
2318 GLfloat texcoords
[][4], const GLfloat lambda
[],
2321 const struct gl_texture_image
*img
= tObj
->Image
[0];
2322 const GLfloat width
= (GLfloat
) img
->Width
;
2323 const GLfloat height
= (GLfloat
) img
->Height
;
2324 const GLint width_minus_1
= img
->Width
- 1;
2325 const GLint height_minus_1
= img
->Height
- 1;
2331 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2332 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2333 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2334 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2335 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2336 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2337 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2339 /* XXX move Wrap mode tests outside of loops for common cases */
2340 for (i
= 0; i
< n
; i
++) {
2342 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2343 if (tObj
->WrapS
== GL_CLAMP
) {
2344 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.0F
, width
) );
2346 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2347 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
) );
2350 col
= IFLOOR( CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
) );
2352 if (tObj
->WrapT
== GL_CLAMP
) {
2353 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.0F
, height
) );
2355 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2356 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
) );
2359 row
= IFLOOR( CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
) );
2362 col
= CLAMP(col
, 0, width_minus_1
);
2363 row
= CLAMP(row
, 0, height_minus_1
);
2365 (*img
->FetchTexel
)(img
, col
, row
, 0, (GLvoid
*) rgba
[i
]);
2367 if (ctx
->Texture
.ColorTableEnabled
) {
2368 texture_table_lookup(&ctx
->TextureColorTable
, n
, rgba
);
2374 sample_linear_rect(GLcontext
*ctx
, GLuint texUnit
,
2375 const struct gl_texture_object
*tObj
, GLuint n
,
2376 GLfloat texcoords
[][4],
2377 const GLfloat lambda
[], GLchan rgba
[][4])
2379 const struct gl_texture_image
*img
= tObj
->Image
[0];
2380 const GLfloat width
= (GLfloat
) img
->Width
;
2381 const GLfloat height
= (GLfloat
) img
->Height
;
2382 const GLint width_minus_1
= img
->Width
- 1;
2383 const GLint height_minus_1
= img
->Height
- 1;
2389 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2390 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2391 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2392 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2393 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2394 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2395 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2397 /* XXX lots of opportunity for optimization in this loop */
2398 for (i
= 0; i
< n
; i
++) {
2400 GLint row0
, col0
, row1
, col1
;
2401 GLchan t00
[4], t01
[4], t10
[4], t11
[4];
2402 GLfloat a
, b
, w00
, w01
, w10
, w11
;
2404 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2405 if (tObj
->WrapS
== GL_CLAMP
) {
2406 fcol
= CLAMP(texcoords
[i
][0], 0.0F
, width
);
2408 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2409 fcol
= CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
);
2412 fcol
= CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
);
2414 if (tObj
->WrapT
== GL_CLAMP
) {
2415 frow
= CLAMP(texcoords
[i
][1], 0.0F
, height
);
2417 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2418 frow
= CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
);
2421 frow
= CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
);
2424 /* compute integer rows/columns */
2425 col0
= IFLOOR(fcol
);
2427 col0
= CLAMP(col0
, 0, width_minus_1
);
2428 col1
= CLAMP(col1
, 0, width_minus_1
);
2429 row0
= IFLOOR(frow
);
2431 row0
= CLAMP(row0
, 0, height_minus_1
);
2432 row1
= CLAMP(row1
, 0, height_minus_1
);
2434 /* get four texel samples */
2435 (*img
->FetchTexel
)(img
, col0
, row0
, 0, (GLvoid
*) t00
);
2436 (*img
->FetchTexel
)(img
, col1
, row0
, 0, (GLvoid
*) t10
);
2437 (*img
->FetchTexel
)(img
, col0
, row1
, 0, (GLvoid
*) t01
);
2438 (*img
->FetchTexel
)(img
, col1
, row1
, 0, (GLvoid
*) t11
);
2440 /* compute sample weights */
2443 w00
= (1.0F
-a
) * (1.0F
-b
);
2445 w01
= (1.0F
-a
) * b
;
2448 /* compute weighted average of samples */
2450 (GLchan
) (w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0]);
2452 (GLchan
) (w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1]);
2454 (GLchan
) (w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2]);
2456 (GLchan
) (w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3]);
2458 if (ctx
->Texture
.ColorTableEnabled
) {
2459 texture_table_lookup(&ctx
->TextureColorTable
, n
, rgba
);
2465 sample_lambda_rect( GLcontext
*ctx
, GLuint texUnit
,
2466 const struct gl_texture_object
*tObj
, GLuint n
,
2467 GLfloat texcoords
[][4], const GLfloat lambda
[],
2470 GLuint minStart
, minEnd
, magStart
, magEnd
;
2472 /* We only need lambda to decide between minification and magnification.
2473 * There is no mipmapping with rectangular textures.
2475 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2476 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2478 if (minStart
< minEnd
) {
2479 if (tObj
->MinFilter
== GL_NEAREST
) {
2480 sample_nearest_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2481 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2484 sample_linear_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2485 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2488 if (magStart
< magEnd
) {
2489 if (tObj
->MagFilter
== GL_NEAREST
) {
2490 sample_nearest_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2491 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2494 sample_linear_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2495 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2498 if (ctx
->Texture
.ColorTableEnabled
) {
2499 texture_table_lookup(&ctx
->TextureColorTable
, n
, rgba
);
2506 * Sample a shadow/depth texture.
2509 sample_depth_texture( GLcontext
*ctx
, GLuint unit
,
2510 const struct gl_texture_object
*tObj
, GLuint n
,
2511 GLfloat texcoords
[][4], const GLfloat lambda
[],
2514 const GLint baseLevel
= tObj
->BaseLevel
;
2515 const struct gl_texture_image
*texImage
= tObj
->Image
[baseLevel
];
2516 const GLuint width
= texImage
->Width
;
2517 const GLuint height
= texImage
->Height
;
2524 ASSERT(tObj
->Image
[tObj
->BaseLevel
]->Format
== GL_DEPTH_COMPONENT
);
2525 ASSERT(tObj
->Target
== GL_TEXTURE_1D
||
2526 tObj
->Target
== GL_TEXTURE_2D
||
2527 tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
2529 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2531 /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
2533 /* XXX this could be precomputed and saved in the texture object */
2534 if (tObj
->CompareFlag
) {
2535 /* GL_SGIX_shadow */
2536 if (tObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2537 function
= GL_LEQUAL
;
2540 ASSERT(tObj
->CompareOperator
== GL_TEXTURE_GEQUAL_R_SGIX
);
2541 function
= GL_GEQUAL
;
2544 else if (tObj
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
) {
2546 function
= tObj
->CompareFunc
;
2549 function
= GL_NONE
; /* pass depth through as grayscale */
2552 if (tObj
->MagFilter
== GL_NEAREST
) {
2554 for (i
= 0; i
< n
; i
++) {
2555 GLfloat depthSample
;
2557 /* XXX fix for texture rectangle! */
2558 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoords
[i
][0], width
, col
);
2559 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoords
[i
][1], height
, row
);
2560 depthSample
= *((const GLfloat
*) texImage
->Data
+ row
* width
+ col
);
2564 result
= (texcoords
[i
][2] <= depthSample
) ? CHAN_MAX
: ambient
;
2567 result
= (texcoords
[i
][2] >= depthSample
) ? CHAN_MAX
: ambient
;
2570 result
= (texcoords
[i
][2] < depthSample
) ? CHAN_MAX
: ambient
;
2573 result
= (texcoords
[i
][2] > depthSample
) ? CHAN_MAX
: ambient
;
2576 result
= (texcoords
[i
][2] == depthSample
) ? CHAN_MAX
: ambient
;
2579 result
= (texcoords
[i
][2] != depthSample
) ? CHAN_MAX
: ambient
;
2588 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2591 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2595 switch (tObj
->DepthMode
) {
2597 texel
[i
][RCOMP
] = result
;
2598 texel
[i
][GCOMP
] = result
;
2599 texel
[i
][BCOMP
] = result
;
2600 texel
[i
][ACOMP
] = CHAN_MAX
;
2603 texel
[i
][RCOMP
] = result
;
2604 texel
[i
][GCOMP
] = result
;
2605 texel
[i
][BCOMP
] = result
;
2606 texel
[i
][ACOMP
] = result
;
2609 texel
[i
][RCOMP
] = 0;
2610 texel
[i
][GCOMP
] = 0;
2611 texel
[i
][BCOMP
] = 0;
2612 texel
[i
][ACOMP
] = result
;
2615 _mesa_problem(ctx
, "Bad depth texture mode");
2621 ASSERT(tObj
->MagFilter
== GL_LINEAR
);
2622 for (i
= 0; i
< n
; i
++) {
2623 GLfloat depth00
, depth01
, depth10
, depth11
;
2624 GLint i0
, i1
, j0
, j1
;
2626 GLuint useBorderTexel
;
2628 /* XXX fix for texture rectangle! */
2629 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoords
[i
][0], u
, width
, i0
, i1
);
2630 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoords
[i
][1], v
, height
,j0
, j1
);
2633 if (texImage
->Border
) {
2634 i0
+= texImage
->Border
;
2635 i1
+= texImage
->Border
;
2636 j0
+= texImage
->Border
;
2637 j1
+= texImage
->Border
;
2640 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
2641 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
2642 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
2643 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
2646 /* get four depth samples from the texture */
2647 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
2651 depth00
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i0
);
2653 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
2657 depth10
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i1
);
2659 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
2663 depth01
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i0
);
2665 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
2669 depth11
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i1
);
2673 /* compute a single weighted depth sample and do one comparison */
2674 const GLfloat a
= FRAC(u
+ 1.0F
);
2675 const GLfloat b
= FRAC(v
+ 1.0F
);
2676 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2677 const GLfloat w10
= ( a
) * (1.0F
- b
);
2678 const GLfloat w01
= (1.0F
- a
) * ( b
);
2679 const GLfloat w11
= ( a
) * ( b
);
2680 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2681 + w01
* depth01
+ w11
* depth11
;
2682 if ((depthSample
<= texcoords
[i
][2] && function
== GL_LEQUAL
) ||
2683 (depthSample
>= texcoords
[i
][2] && function
== GL_GEQUAL
)) {
2691 /* Do four depth/R comparisons and compute a weighted result.
2692 * If this touches on somebody's I.P., I'll remove this code
2695 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
2696 GLfloat luminance
= CHAN_MAXF
;
2700 if (depth00
<= texcoords
[i
][2]) luminance
-= d
;
2701 if (depth01
<= texcoords
[i
][2]) luminance
-= d
;
2702 if (depth10
<= texcoords
[i
][2]) luminance
-= d
;
2703 if (depth11
<= texcoords
[i
][2]) luminance
-= d
;
2704 result
= (GLchan
) luminance
;
2707 if (depth00
>= texcoords
[i
][2]) luminance
-= d
;
2708 if (depth01
>= texcoords
[i
][2]) luminance
-= d
;
2709 if (depth10
>= texcoords
[i
][2]) luminance
-= d
;
2710 if (depth11
>= texcoords
[i
][2]) luminance
-= d
;
2711 result
= (GLchan
) luminance
;
2714 if (depth00
< texcoords
[i
][2]) luminance
-= d
;
2715 if (depth01
< texcoords
[i
][2]) luminance
-= d
;
2716 if (depth10
< texcoords
[i
][2]) luminance
-= d
;
2717 if (depth11
< texcoords
[i
][2]) luminance
-= d
;
2718 result
= (GLchan
) luminance
;
2721 if (depth00
> texcoords
[i
][2]) luminance
-= d
;
2722 if (depth01
> texcoords
[i
][2]) luminance
-= d
;
2723 if (depth10
> texcoords
[i
][2]) luminance
-= d
;
2724 if (depth11
> texcoords
[i
][2]) luminance
-= d
;
2725 result
= (GLchan
) luminance
;
2728 if (depth00
== texcoords
[i
][2]) luminance
-= d
;
2729 if (depth01
== texcoords
[i
][2]) luminance
-= d
;
2730 if (depth10
== texcoords
[i
][2]) luminance
-= d
;
2731 if (depth11
== texcoords
[i
][2]) luminance
-= d
;
2732 result
= (GLchan
) luminance
;
2735 if (depth00
!= texcoords
[i
][2]) luminance
-= d
;
2736 if (depth01
!= texcoords
[i
][2]) luminance
-= d
;
2737 if (depth10
!= texcoords
[i
][2]) luminance
-= d
;
2738 if (depth11
!= texcoords
[i
][2]) luminance
-= d
;
2739 result
= (GLchan
) luminance
;
2748 /* ordinary bilinear filtering */
2750 const GLfloat a
= FRAC(u
+ 1.0F
);
2751 const GLfloat b
= FRAC(v
+ 1.0F
);
2752 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2753 const GLfloat w10
= ( a
) * (1.0F
- b
);
2754 const GLfloat w01
= (1.0F
- a
) * ( b
);
2755 const GLfloat w11
= ( a
) * ( b
);
2756 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2757 + w01
* depth01
+ w11
* depth11
;
2758 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2762 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2767 switch (tObj
->DepthMode
) {
2769 texel
[i
][RCOMP
] = result
;
2770 texel
[i
][GCOMP
] = result
;
2771 texel
[i
][BCOMP
] = result
;
2772 texel
[i
][ACOMP
] = CHAN_MAX
;
2775 texel
[i
][RCOMP
] = result
;
2776 texel
[i
][GCOMP
] = result
;
2777 texel
[i
][BCOMP
] = result
;
2778 texel
[i
][ACOMP
] = result
;
2781 texel
[i
][RCOMP
] = 0;
2782 texel
[i
][GCOMP
] = 0;
2783 texel
[i
][BCOMP
] = 0;
2784 texel
[i
][ACOMP
] = result
;
2787 _mesa_problem(ctx
, "Bad depth texture mode");
2796 * Experimental depth texture sampling function.
2799 sample_depth_texture2(const GLcontext
*ctx
,
2800 const struct gl_texture_unit
*texUnit
,
2801 GLuint n
, GLfloat texcoords
[][4],
2804 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2805 const GLint baseLevel
= texObj
->BaseLevel
;
2806 const struct gl_texture_image
*texImage
= texObj
->Image
[baseLevel
];
2807 const GLuint width
= texImage
->Width
;
2808 const GLuint height
= texImage
->Height
;
2810 GLboolean lequal
, gequal
;
2812 if (texObj
->Target
!= GL_TEXTURE_2D
) {
2813 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2817 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2818 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2822 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2823 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2824 * isn't a depth texture.
2826 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2827 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2831 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2833 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2844 for (i
= 0; i
< n
; i
++) {
2846 GLint col
, row
, ii
, jj
, imin
, imax
, jmin
, jmax
, samples
, count
;
2849 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, texcoords
[i
][0],
2851 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, texcoords
[i
][1],
2859 if (imin
< 0) imin
= 0;
2860 if (imax
>= width
) imax
= width
- 1;
2861 if (jmin
< 0) jmin
= 0;
2862 if (jmax
>= height
) jmax
= height
- 1;
2864 samples
= (imax
- imin
+ 1) * (jmax
- jmin
+ 1);
2866 for (jj
= jmin
; jj
<= jmax
; jj
++) {
2867 for (ii
= imin
; ii
<= imax
; ii
++) {
2868 GLfloat depthSample
= *((const GLfloat
*) texImage
->Data
2870 if ((depthSample
<= r
[i
] && lequal
) ||
2871 (depthSample
>= r
[i
] && gequal
)) {
2877 w
= (GLfloat
) count
/ (GLfloat
) samples
;
2878 w
= CHAN_MAXF
- w
* (CHAN_MAXF
- (GLfloat
) ambient
);
2881 texel
[i
][RCOMP
] = lum
;
2882 texel
[i
][GCOMP
] = lum
;
2883 texel
[i
][BCOMP
] = lum
;
2884 texel
[i
][ACOMP
] = CHAN_MAX
;
2892 * We use this function when a texture object is in an "incomplete" state.
2895 null_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2896 const struct gl_texture_object
*tObj
, GLuint n
,
2897 GLfloat texcoords
[][4], const GLfloat lambda
[],
2905 * Setup the texture sampling function for this texture object.
2908 _swrast_choose_texture_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2909 const struct gl_texture_object
*t
)
2911 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
2914 swrast
->TextureSample
[texUnit
] = null_sample_func
;
2917 const GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
2918 const GLenum format
= t
->Image
[t
->BaseLevel
]->Format
;
2921 /* Compute min/mag filter threshold */
2922 if (t
->MagFilter
== GL_LINEAR
2923 && (t
->MinFilter
== GL_NEAREST_MIPMAP_NEAREST
||
2924 t
->MinFilter
== GL_NEAREST_MIPMAP_LINEAR
)) {
2925 swrast
->_MinMagThresh
[texUnit
] = 0.5F
;
2928 swrast
->_MinMagThresh
[texUnit
] = 0.0F
;
2932 switch (t
->Target
) {
2934 if (format
== GL_DEPTH_COMPONENT
) {
2935 swrast
->TextureSample
[texUnit
] = sample_depth_texture
;
2937 else if (needLambda
) {
2938 swrast
->TextureSample
[texUnit
] = sample_lambda_1d
;
2940 else if (t
->MinFilter
== GL_LINEAR
) {
2941 swrast
->TextureSample
[texUnit
] = sample_linear_1d
;
2944 ASSERT(t
->MinFilter
== GL_NEAREST
);
2945 swrast
->TextureSample
[texUnit
] = sample_nearest_1d
;
2949 if (format
== GL_DEPTH_COMPONENT
) {
2950 swrast
->TextureSample
[texUnit
] = sample_depth_texture
;
2952 else if (needLambda
) {
2953 swrast
->TextureSample
[texUnit
] = sample_lambda_2d
;
2955 else if (t
->MinFilter
== GL_LINEAR
) {
2956 swrast
->TextureSample
[texUnit
] = sample_linear_2d
;
2959 GLint baseLevel
= t
->BaseLevel
;
2960 ASSERT(t
->MinFilter
== GL_NEAREST
);
2961 if (t
->WrapS
== GL_REPEAT
&&
2962 t
->WrapT
== GL_REPEAT
&&
2963 t
->Image
[baseLevel
]->Border
== 0 &&
2964 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGB
) {
2965 swrast
->TextureSample
[texUnit
] = opt_sample_rgb_2d
;
2967 else if (t
->WrapS
== GL_REPEAT
&&
2968 t
->WrapT
== GL_REPEAT
&&
2969 t
->Image
[baseLevel
]->Border
== 0 &&
2970 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGBA
) {
2971 swrast
->TextureSample
[texUnit
] = opt_sample_rgba_2d
;
2974 swrast
->TextureSample
[texUnit
] = sample_nearest_2d
;
2979 swrast
->TextureSample
[texUnit
] = sample_lambda_3d
;
2981 else if (t
->MinFilter
== GL_LINEAR
) {
2982 swrast
->TextureSample
[texUnit
] = sample_linear_3d
;
2985 ASSERT(t
->MinFilter
== GL_NEAREST
);
2986 swrast
->TextureSample
[texUnit
] = sample_nearest_3d
;
2989 case GL_TEXTURE_CUBE_MAP
:
2991 swrast
->TextureSample
[texUnit
] = sample_lambda_cube
;
2993 else if (t
->MinFilter
== GL_LINEAR
) {
2994 swrast
->TextureSample
[texUnit
] = sample_linear_cube
;
2997 ASSERT(t
->MinFilter
== GL_NEAREST
);
2998 swrast
->TextureSample
[texUnit
] = sample_nearest_cube
;
3001 case GL_TEXTURE_RECTANGLE_NV
:
3003 swrast
->TextureSample
[texUnit
] = sample_lambda_rect
;
3005 else if (t
->MinFilter
== GL_LINEAR
) {
3006 swrast
->TextureSample
[texUnit
] = sample_linear_rect
;
3009 ASSERT(t
->MinFilter
== GL_NEAREST
);
3010 swrast
->TextureSample
[texUnit
] = sample_nearest_rect
;
3014 _mesa_problem(ctx
, "invalid target in _swrast_choose_texture_sample_func");
3020 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
3021 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
3025 * Do texture application for GL_ARB/EXT_texture_env_combine.
3026 * This function also supports GL_{EXT,ARB}_texture_env_dot3 and
3027 * GL_ATI_texture_env_combine3
3029 * \param ctx rendering context
3030 * \param textureUnit the texture unit to apply
3031 * \param n number of fragments to process (span width)
3032 * \param primary_rgba incoming fragment color array
3033 * \param texelBuffer pointer to texel colors for all texture units
3035 * \param rgba incoming colors, which get modified here
3038 texture_combine( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
3039 CONST
GLchan (*primary_rgba
)[4],
3040 CONST GLchan
*texelBuffer
,
3043 const struct gl_texture_unit
*textureUnit
= &(ctx
->Texture
.Unit
[unit
]);
3044 const GLchan (*argRGB
[3])[4];
3045 const GLchan (*argA
[3])[4];
3046 const GLuint RGBshift
= textureUnit
->CombineScaleShiftRGB
;
3047 const GLuint Ashift
= textureUnit
->CombineScaleShiftA
;
3048 #if CHAN_TYPE == GL_FLOAT
3049 const GLchan RGBmult
= (GLfloat
) (1 << RGBshift
);
3050 const GLchan Amult
= (GLfloat
) (1 << Ashift
);
3051 static const GLchan one
[4] = { 1.0, 1.0, 1.0, 1.0 };
3052 static const GLchan zero
[4] = { 0.0, 0.0, 0.0, 0.0 };
3054 const GLint half
= (CHAN_MAX
+ 1) / 2;
3055 static const GLchan one
[4] = { CHAN_MAX
, CHAN_MAX
, CHAN_MAX
, CHAN_MAX
};
3056 static const GLchan zero
[4] = { 0, 0, 0, 0 };
3059 GLuint numColorArgs
;
3060 GLuint numAlphaArgs
;
3062 /* GLchan ccolor[3][4]; */
3063 DEFMNARRAY(GLchan
, ccolor
, 3, 3 * MAX_WIDTH
, 4); /* mac 32k limitation */
3064 CHECKARRAY(ccolor
, return); /* mac 32k limitation */
3066 ASSERT(ctx
->Extensions
.EXT_texture_env_combine
||
3067 ctx
->Extensions
.ARB_texture_env_combine
);
3068 ASSERT(SWRAST_CONTEXT(ctx
)->_AnyTextureCombine
);
3072 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
3073 textureUnit->CombineModeRGB,
3074 textureUnit->CombineModeA,
3075 textureUnit->CombineSourceRGB[0],
3076 textureUnit->CombineSourceA[0],
3077 textureUnit->CombineSourceRGB[1],
3078 textureUnit->CombineSourceA[1]);
3082 * Do operand setup for up to 3 operands. Loop over the terms.
3084 switch (textureUnit
->CombineModeRGB
) {
3094 case GL_DOT3_RGB_EXT
:
3095 case GL_DOT3_RGBA_EXT
:
3098 case GL_INTERPOLATE
:
3099 case GL_MODULATE_ADD_ATI
:
3100 case GL_MODULATE_SIGNED_ADD_ATI
:
3101 case GL_MODULATE_SUBTRACT_ATI
:
3110 switch (textureUnit
->CombineModeA
) {
3120 case GL_INTERPOLATE
:
3121 case GL_MODULATE_ADD_ATI
:
3122 case GL_MODULATE_SIGNED_ADD_ATI
:
3123 case GL_MODULATE_SUBTRACT_ATI
:
3132 for (j
= 0; j
< numColorArgs
; j
++) {
3133 const GLenum srcRGB
= textureUnit
->CombineSourceRGB
[j
];
3138 argRGB
[j
] = (const GLchan (*)[4])
3139 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
3141 case GL_PRIMARY_COLOR
:
3142 argRGB
[j
] = primary_rgba
;
3145 argRGB
[j
] = (const GLchan (*)[4]) rgba
;
3149 GLchan (*c
)[4] = ccolor
[j
];
3150 GLchan red
, green
, blue
, alpha
;
3151 UNCLAMPED_FLOAT_TO_CHAN(red
, textureUnit
->EnvColor
[0]);
3152 UNCLAMPED_FLOAT_TO_CHAN(green
, textureUnit
->EnvColor
[1]);
3153 UNCLAMPED_FLOAT_TO_CHAN(blue
, textureUnit
->EnvColor
[2]);
3154 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
3155 for (i
= 0; i
< n
; i
++) {
3157 c
[i
][GCOMP
] = green
;
3159 c
[i
][ACOMP
] = alpha
;
3161 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3164 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
3173 /* ARB_texture_env_crossbar source */
3175 const GLuint srcUnit
= srcRGB
- GL_TEXTURE0
;
3176 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
3177 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
3179 argRGB
[j
] = (const GLchan (*)[4])
3180 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
3184 if (textureUnit
->CombineOperandRGB
[j
] != GL_SRC_COLOR
) {
3185 const GLchan (*src
)[4] = argRGB
[j
];
3186 GLchan (*dst
)[4] = ccolor
[j
];
3188 /* point to new arg[j] storage */
3189 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3191 if (textureUnit
->CombineOperandRGB
[j
] == GL_ONE_MINUS_SRC_COLOR
) {
3192 for (i
= 0; i
< n
; i
++) {
3193 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][RCOMP
];
3194 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][GCOMP
];
3195 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][BCOMP
];
3198 else if (textureUnit
->CombineOperandRGB
[j
] == GL_SRC_ALPHA
) {
3199 for (i
= 0; i
< n
; i
++) {
3200 dst
[i
][RCOMP
] = src
[i
][ACOMP
];
3201 dst
[i
][GCOMP
] = src
[i
][ACOMP
];
3202 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
3206 ASSERT(textureUnit
->CombineOperandRGB
[j
] ==GL_ONE_MINUS_SRC_ALPHA
);
3207 for (i
= 0; i
< n
; i
++) {
3208 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3209 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3210 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3217 for (j
= 0; j
< numAlphaArgs
; j
++) {
3218 const GLenum srcA
= textureUnit
->CombineSourceA
[j
];
3222 argA
[j
] = (const GLchan (*)[4])
3223 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
3225 case GL_PRIMARY_COLOR
:
3226 argA
[j
] = primary_rgba
;
3229 argA
[j
] = (const GLchan (*)[4]) rgba
;
3233 GLchan alpha
, (*c
)[4] = ccolor
[j
];
3234 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
3235 for (i
= 0; i
< n
; i
++)
3236 c
[i
][ACOMP
] = alpha
;
3237 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3240 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
3249 /* ARB_texture_env_crossbar source */
3251 const GLuint srcUnit
= srcA
- GL_TEXTURE0
;
3252 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
3253 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
3255 argA
[j
] = (const GLchan (*)[4])
3256 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
3260 if (textureUnit
->CombineOperandA
[j
] == GL_ONE_MINUS_SRC_ALPHA
) {
3261 const GLchan (*src
)[4] = argA
[j
];
3262 GLchan (*dst
)[4] = ccolor
[j
];
3263 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3264 for (i
= 0; i
< n
; i
++) {
3265 dst
[i
][ACOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3271 * Do the texture combine.
3273 switch (textureUnit
->CombineModeRGB
) {
3276 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3278 for (i
= 0; i
< n
; i
++) {
3279 #if CHAN_TYPE == GL_FLOAT
3280 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * RGBmult
;
3281 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * RGBmult
;
3282 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * RGBmult
;
3284 GLuint r
= (GLuint
) arg0
[i
][RCOMP
] << RGBshift
;
3285 GLuint g
= (GLuint
) arg0
[i
][GCOMP
] << RGBshift
;
3286 GLuint b
= (GLuint
) arg0
[i
][BCOMP
] << RGBshift
;
3287 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3288 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3289 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3294 for (i
= 0; i
< n
; i
++) {
3295 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
];
3296 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
];
3297 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
];
3304 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3305 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3306 #if CHAN_TYPE != GL_FLOAT
3307 const GLint shift
= CHAN_BITS
- RGBshift
;
3309 for (i
= 0; i
< n
; i
++) {
3310 #if CHAN_TYPE == GL_FLOAT
3311 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * RGBmult
;
3312 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * RGBmult
;
3313 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * RGBmult
;
3315 GLuint r
= PROD(arg0
[i
][RCOMP
], arg1
[i
][RCOMP
]) >> shift
;
3316 GLuint g
= PROD(arg0
[i
][GCOMP
], arg1
[i
][GCOMP
]) >> shift
;
3317 GLuint b
= PROD(arg0
[i
][BCOMP
], arg1
[i
][BCOMP
]) >> shift
;
3318 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3319 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3320 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3327 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3328 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3329 for (i
= 0; i
< n
; i
++) {
3330 #if CHAN_TYPE == GL_FLOAT
3331 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * RGBmult
;
3332 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * RGBmult
;
3333 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * RGBmult
;
3335 GLint r
= ((GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3336 GLint g
= ((GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3337 GLint b
= ((GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3338 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3339 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3340 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3347 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3348 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3349 for (i
= 0; i
< n
; i
++) {
3350 #if CHAN_TYPE == GL_FLOAT
3351 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3352 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3353 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3355 GLint r
= (GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
] -half
;
3356 GLint g
= (GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
] -half
;
3357 GLint b
= (GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
] -half
;
3358 r
= (r
< 0) ? 0 : r
<< RGBshift
;
3359 g
= (g
< 0) ? 0 : g
<< RGBshift
;
3360 b
= (b
< 0) ? 0 : b
<< RGBshift
;
3361 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3362 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3363 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3368 case GL_INTERPOLATE
:
3370 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3371 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3372 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3373 #if CHAN_TYPE != GL_FLOAT
3374 const GLint shift
= CHAN_BITS
- RGBshift
;
3376 for (i
= 0; i
< n
; i
++) {
3377 #if CHAN_TYPE == GL_FLOAT
3378 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
3379 arg1
[i
][RCOMP
] * (CHAN_MAXF
- arg2
[i
][RCOMP
])) * RGBmult
;
3380 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
3381 arg1
[i
][GCOMP
] * (CHAN_MAXF
- arg2
[i
][GCOMP
])) * RGBmult
;
3382 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
3383 arg1
[i
][BCOMP
] * (CHAN_MAXF
- arg2
[i
][BCOMP
])) * RGBmult
;
3385 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3386 + PROD(arg1
[i
][RCOMP
], CHAN_MAX
- arg2
[i
][RCOMP
]))
3388 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3389 + PROD(arg1
[i
][GCOMP
], CHAN_MAX
- arg2
[i
][GCOMP
]))
3391 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3392 + PROD(arg1
[i
][BCOMP
], CHAN_MAX
- arg2
[i
][BCOMP
]))
3394 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3395 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3396 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3403 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3404 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3405 for (i
= 0; i
< n
; i
++) {
3406 #if CHAN_TYPE == GL_FLOAT
3407 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * RGBmult
;
3408 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * RGBmult
;
3409 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * RGBmult
;
3411 GLint r
= ((GLint
) arg0
[i
][RCOMP
] - (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3412 GLint g
= ((GLint
) arg0
[i
][GCOMP
] - (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3413 GLint b
= ((GLint
) arg0
[i
][BCOMP
] - (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3414 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3415 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3416 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3421 case GL_DOT3_RGB_EXT
:
3422 case GL_DOT3_RGBA_EXT
:
3424 /* Do not scale the result by 1 2 or 4 */
3425 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3426 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3427 for (i
= 0; i
< n
; i
++) {
3428 #if CHAN_TYPE == GL_FLOAT
3429 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3430 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3431 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3433 dot
= CLAMP(dot
, 0.0F
, CHAN_MAXF
);
3435 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3436 (GLint
)arg1
[i
][RCOMP
] - half
) +
3437 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3438 (GLint
)arg1
[i
][GCOMP
] - half
) +
3439 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3440 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3441 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3443 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3450 /* DO scale the result by 1 2 or 4 */
3451 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3452 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3453 for (i
= 0; i
< n
; i
++) {
3454 #if CHAN_TYPE == GL_FLOAT
3455 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3456 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3457 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3459 dot
= CLAMP(dot
, 0.0, CHAN_MAXF
);
3461 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3462 (GLint
)arg1
[i
][RCOMP
] - half
) +
3463 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3464 (GLint
)arg1
[i
][GCOMP
] - half
) +
3465 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3466 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3468 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3470 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3474 case GL_MODULATE_ADD_ATI
:
3476 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3477 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3478 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3479 #if CHAN_TYPE != GL_FLOAT
3480 const GLint shift
= CHAN_BITS
- RGBshift
;
3482 for (i
= 0; i
< n
; i
++) {
3483 #if CHAN_TYPE == GL_FLOAT
3484 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) + arg1
[i
][RCOMP
]) * RGBmult
;
3485 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
]) * RGBmult
;
3486 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
]) * RGBmult
;
3488 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3489 + ((GLuint
) arg1
[i
][RCOMP
] << CHAN_BITS
)) >> shift
;
3490 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3491 + ((GLuint
) arg1
[i
][GCOMP
] << CHAN_BITS
)) >> shift
;
3492 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3493 + ((GLuint
) arg1
[i
][BCOMP
] << CHAN_BITS
)) >> shift
;
3494 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3495 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3496 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3501 case GL_MODULATE_SIGNED_ADD_ATI
:
3503 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3504 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3505 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3506 #if CHAN_TYPE != GL_FLOAT
3507 const GLint shift
= CHAN_BITS
- RGBshift
;
3509 for (i
= 0; i
< n
; i
++) {
3510 #if CHAN_TYPE == GL_FLOAT
3511 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3512 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3513 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3515 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3516 + (((GLint
) arg1
[i
][RCOMP
] - half
) << CHAN_BITS
))
3518 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3519 + (((GLint
) arg1
[i
][GCOMP
] - half
) << CHAN_BITS
))
3521 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3522 + (((GLint
) arg1
[i
][BCOMP
] - half
) << CHAN_BITS
))
3524 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3525 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3526 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3531 case GL_MODULATE_SUBTRACT_ATI
:
3533 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3534 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3535 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3536 #if CHAN_TYPE != GL_FLOAT
3537 const GLint shift
= CHAN_BITS
- RGBshift
;
3539 for (i
= 0; i
< n
; i
++) {
3540 #if CHAN_TYPE == GL_FLOAT
3541 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) - arg1
[i
][RCOMP
]) * RGBmult
;
3542 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) - arg1
[i
][GCOMP
]) * RGBmult
;
3543 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) - arg1
[i
][BCOMP
]) * RGBmult
;
3545 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3546 - ((GLint
) arg1
[i
][RCOMP
] << CHAN_BITS
))
3548 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3549 - ((GLint
) arg1
[i
][GCOMP
] << CHAN_BITS
))
3551 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3552 - ((GLint
) arg1
[i
][BCOMP
] << CHAN_BITS
))
3554 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3555 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3556 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3562 _mesa_problem(ctx
, "invalid combine mode");
3565 switch (textureUnit
->CombineModeA
) {
3568 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3570 for (i
= 0; i
< n
; i
++) {
3571 #if CHAN_TYPE == GL_FLOAT
3572 GLchan a
= arg0
[i
][ACOMP
] * Amult
;
3574 GLuint a
= (GLuint
) arg0
[i
][ACOMP
] << Ashift
;
3576 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3580 for (i
= 0; i
< n
; i
++) {
3581 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
];
3588 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3589 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3590 #if CHAN_TYPE != GL_FLOAT
3591 const GLint shift
= CHAN_BITS
- Ashift
;
3593 for (i
= 0; i
< n
; i
++) {
3594 #if CHAN_TYPE == GL_FLOAT
3595 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * Amult
;
3597 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg1
[i
][ACOMP
]) >> shift
);
3598 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3605 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3606 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3607 for (i
= 0; i
< n
; i
++) {
3608 #if CHAN_TYPE == GL_FLOAT
3609 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * Amult
;
3611 GLint a
= ((GLint
) arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) << Ashift
;
3612 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3619 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3620 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3621 for (i
= 0; i
< n
; i
++) {
3622 #if CHAN_TYPE == GL_FLOAT
3623 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3625 GLint a
= (GLint
) arg0
[i
][ACOMP
] + (GLint
) arg1
[i
][ACOMP
] -half
;
3626 a
= (a
< 0) ? 0 : a
<< Ashift
;
3627 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3632 case GL_INTERPOLATE
:
3634 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3635 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3636 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3637 #if CHAN_TYPE != GL_FLOAT
3638 const GLint shift
= CHAN_BITS
- Ashift
;
3640 for (i
=0; i
<n
; i
++) {
3641 #if CHAN_TYPE == GL_FLOAT
3642 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
3643 arg1
[i
][ACOMP
] * (CHAN_MAXF
- arg2
[i
][ACOMP
]))
3646 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3647 + PROD(arg1
[i
][ACOMP
], CHAN_MAX
- arg2
[i
][ACOMP
]))
3649 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3656 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3657 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3658 for (i
= 0; i
< n
; i
++) {
3659 #if CHAN_TYPE == GL_FLOAT
3660 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * Amult
;
3662 GLint a
= ((GLint
) arg0
[i
][ACOMP
] - (GLint
) arg1
[i
][ACOMP
]) << Ashift
;
3663 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3668 case GL_MODULATE_ADD_ATI
:
3670 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3671 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3672 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3673 #if CHAN_TYPE != GL_FLOAT
3674 const GLint shift
= CHAN_BITS
- Ashift
;
3676 for (i
= 0; i
< n
; i
++) {
3677 #if CHAN_TYPE == GL_FLOAT
3678 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
]) * Amult
;
3680 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3681 + ((GLuint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3683 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3688 case GL_MODULATE_SIGNED_ADD_ATI
:
3690 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3691 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3692 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3693 #if CHAN_TYPE != GL_FLOAT
3694 const GLint shift
= CHAN_BITS
- Ashift
;
3696 for (i
= 0; i
< n
; i
++) {
3697 #if CHAN_TYPE == GL_FLOAT
3698 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3700 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3701 + (((GLint
) arg1
[i
][ACOMP
] - half
) << CHAN_BITS
))
3703 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3708 case GL_MODULATE_SUBTRACT_ATI
:
3710 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3711 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3712 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3713 #if CHAN_TYPE != GL_FLOAT
3714 const GLint shift
= CHAN_BITS
- Ashift
;
3716 for (i
= 0; i
< n
; i
++) {
3717 #if CHAN_TYPE == GL_FLOAT
3718 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) - arg1
[i
][ACOMP
]) * Amult
;
3720 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3721 - ((GLint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3723 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3729 _mesa_problem(ctx
, "invalid combine mode");
3732 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
3733 * This is kind of a kludge. It would have been better if the spec
3734 * were written such that the GL_COMBINE_ALPHA value could be set to
3737 if (textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_EXT
||
3738 textureUnit
->CombineModeRGB
== GL_DOT3_RGBA
) {
3739 for (i
= 0; i
< n
; i
++) {
3740 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
3743 UNDEFARRAY(ccolor
); /* mac 32k limitation */
3749 * Implement NVIDIA's GL_NV_texture_env_combine4 extension when
3750 * texUnit->EnvMode == GL_COMBINE4_NV.
3753 texture_combine4( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
3754 CONST
GLchan (*primary_rgba
)[4],
3755 CONST GLchan
*texelBuffer
,
3763 * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND,
3764 * MODULATE, or DECAL) to an array of fragments.
3765 * Input: textureUnit - pointer to texture unit to apply
3766 * format - base internal texture format
3767 * n - number of fragments
3768 * primary_rgba - primary colors (may alias rgba for single texture)
3769 * texels - array of texel colors
3770 * InOut: rgba - incoming fragment colors modified by texel colors
3771 * according to the texture environment mode.
3774 texture_apply( const GLcontext
*ctx
,
3775 const struct gl_texture_unit
*texUnit
,
3777 CONST GLchan primary_rgba
[][4], CONST GLchan texel
[][4],
3782 GLint Rc
, Gc
, Bc
, Ac
;
3786 ASSERT(texUnit
->_Current
);
3788 baseLevel
= texUnit
->_Current
->BaseLevel
;
3789 ASSERT(texUnit
->_Current
->Image
[baseLevel
]);
3791 format
= texUnit
->_Current
->Image
[baseLevel
]->Format
;
3793 if (format
== GL_COLOR_INDEX
|| format
== GL_DEPTH_COMPONENT
3794 || format
== GL_YCBCR_MESA
) {
3795 format
= GL_RGBA
; /* a bit of a hack */
3798 switch (texUnit
->EnvMode
) {
3805 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3811 GLchan Lt
= texel
[i
][RCOMP
];
3812 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3816 case GL_LUMINANCE_ALPHA
:
3818 GLchan Lt
= texel
[i
][RCOMP
];
3820 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3822 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3828 GLchan It
= texel
[i
][RCOMP
];
3829 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
3831 rgba
[i
][ACOMP
] = It
;
3837 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3838 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3839 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3846 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3847 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3848 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3850 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3854 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in texture_apply");
3865 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3871 GLchan Lt
= texel
[i
][RCOMP
];
3872 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3873 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3874 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3878 case GL_LUMINANCE_ALPHA
:
3881 GLchan Lt
= texel
[i
][RCOMP
];
3882 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3883 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3884 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3886 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3892 GLchan It
= texel
[i
][RCOMP
];
3893 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], It
);
3894 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], It
);
3895 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], It
);
3897 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], It
);
3903 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3904 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3905 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3912 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3913 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3914 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3916 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3920 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in texture_apply");
3929 case GL_LUMINANCE_ALPHA
:
3936 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3937 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3938 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3944 /* Cv = Cf(1-At) + CtAt */
3945 GLint t
= texel
[i
][ACOMP
], s
= CHAN_MAX
- t
;
3946 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(texel
[i
][RCOMP
],t
);
3947 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(texel
[i
][GCOMP
],t
);
3948 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(texel
[i
][BCOMP
],t
);
3953 _mesa_problem(ctx
, "Bad format (GL_DECAL) in texture_apply");
3959 Rc
= (GLint
) (texUnit
->EnvColor
[0] * CHAN_MAXF
);
3960 Gc
= (GLint
) (texUnit
->EnvColor
[1] * CHAN_MAXF
);
3961 Bc
= (GLint
) (texUnit
->EnvColor
[2] * CHAN_MAXF
);
3962 Ac
= (GLint
) (texUnit
->EnvColor
[3] * CHAN_MAXF
);
3968 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3973 /* Cv = Cf(1-Lt) + CcLt */
3974 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3975 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3976 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3977 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3981 case GL_LUMINANCE_ALPHA
:
3983 /* Cv = Cf(1-Lt) + CcLt */
3984 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3985 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3986 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3987 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3989 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
3994 /* Cv = Cf(1-It) + CcLt */
3995 GLchan It
= texel
[i
][RCOMP
], s
= CHAN_MAX
- It
;
3996 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, It
);
3997 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, It
);
3998 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, It
);
3999 /* Av = Af(1-It) + Ac*It */
4000 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], s
) + CHAN_PRODUCT(Ac
, It
);
4005 /* Cv = Cf(1-Ct) + CcCt */
4006 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
4007 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
4008 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
4014 /* Cv = Cf(1-Ct) + CcCt */
4015 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
4016 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
4017 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
4019 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
4023 _mesa_problem(ctx
, "Bad format (GL_BLEND) in texture_apply");
4028 /* XXX don't clamp results if GLchan is float??? */
4030 case GL_ADD
: /* GL_EXT_texture_add_env */
4037 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4042 GLuint Lt
= texel
[i
][RCOMP
];
4043 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
4044 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
4045 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
4046 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4047 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4048 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4052 case GL_LUMINANCE_ALPHA
:
4054 GLuint Lt
= texel
[i
][RCOMP
];
4055 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
4056 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
4057 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
4058 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4059 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4060 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4061 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4066 GLchan It
= texel
[i
][RCOMP
];
4067 GLuint r
= rgba
[i
][RCOMP
] + It
;
4068 GLuint g
= rgba
[i
][GCOMP
] + It
;
4069 GLuint b
= rgba
[i
][BCOMP
] + It
;
4070 GLuint a
= rgba
[i
][ACOMP
] + It
;
4071 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4072 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4073 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4074 rgba
[i
][ACOMP
] = MIN2(a
, CHAN_MAX
);
4079 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
4080 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
4081 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
4082 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4083 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4084 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4090 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
4091 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
4092 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
4093 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4094 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4095 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4096 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4100 _mesa_problem(ctx
, "Bad format (GL_ADD) in texture_apply");
4106 _mesa_problem(ctx
, "Bad env mode in texture_apply");
4114 * Apply texture mapping to a span of fragments.
4117 _swrast_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
4119 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
4120 GLchan primary_rgba
[MAX_WIDTH
][4];
4123 ASSERT(span
->end
< MAX_WIDTH
);
4124 ASSERT(span
->arrayMask
& SPAN_TEXTURE
);
4127 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
4129 if (swrast
->_AnyTextureCombine
)
4130 MEMCPY(primary_rgba
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
));
4133 * Must do all texture sampling before combining in order to
4134 * accomodate GL_ARB_texture_env_crossbar.
4136 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
4137 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
4138 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
4139 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
4140 GLfloat
*lambda
= span
->array
->lambda
[unit
];
4141 GLchan (*texels
)[4] = (GLchan (*)[4])
4142 (swrast
->TexelBuffer
+ unit
* (span
->end
* 4 * sizeof(GLchan
)));
4144 /* adjust texture lod (lambda) */
4145 if (span
->arrayMask
| SPAN_LAMBDA
) {
4146 if (texUnit
->LodBias
!= 0.0F
) {
4147 /* apply LOD bias, but don't clamp yet */
4149 for (i
= 0; i
< span
->end
; i
++) {
4150 lambda
[i
] += texUnit
->LodBias
;
4154 if (curObj
->MinLod
!= -1000.0 || curObj
->MaxLod
!= 1000.0) {
4155 /* apply LOD clamping to lambda */
4156 const GLfloat min
= curObj
->MinLod
;
4157 const GLfloat max
= curObj
->MaxLod
;
4159 for (i
= 0; i
< span
->end
; i
++) {
4160 GLfloat l
= lambda
[i
];
4161 lambda
[i
] = CLAMP(l
, min
, max
);
4166 /* Sample the texture (span->end fragments) */
4167 swrast
->TextureSample
[unit
]( ctx
, unit
, texUnit
->_Current
,
4168 span
->end
, span
->array
->texcoords
[unit
],
4174 * OK, now apply the texture (aka texture combine/blend).
4175 * We modify the span->color.rgba values.
4177 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
4178 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
4179 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
4180 if (texUnit
->EnvMode
== GL_COMBINE
) {
4181 /* GL_ARB/EXT_texture_env_combine */
4182 texture_combine( ctx
, unit
, span
->end
,
4183 (CONST
GLchan (*)[4]) primary_rgba
,
4184 swrast
->TexelBuffer
,
4185 span
->array
->rgba
);
4187 else if (texUnit
->EnvMode
== GL_COMBINE4_NV
) {
4188 /* GL_NV_texture_env_combine4 */
4189 texture_combine4( ctx
, unit
, span
->end
,
4190 (CONST
GLchan (*)[4]) primary_rgba
,
4191 swrast
->TexelBuffer
,
4192 span
->array
->rgba
);
4195 /* conventional texture blend */
4196 const GLchan (*texels
)[4] = (const GLchan (*)[4])
4197 (swrast
->TexelBuffer
+ unit
*
4198 (span
->end
* 4 * sizeof(GLchan
)));
4199 texture_apply( ctx
, texUnit
, span
->end
,
4200 (CONST
GLchan (*)[4]) primary_rgba
, texels
,
4201 span
->array
->rgba
);