1 /* $Id: s_texture.c,v 1.79 2003/02/06 13:44:55 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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.
300 * Do the lookup for GL_SGI_texture_color_table.
303 _swrast_texture_table_lookup(const struct gl_color_table
*table
,
304 GLuint n
, GLchan rgba
[][4])
306 if (!table
->Table
|| table
->Size
== 0)
309 switch (table
->Format
) {
311 /* replace RGBA with I */
312 if (table
->FloatTable
) {
313 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
314 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
316 for (i
= 0; i
< n
; i
++) {
317 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
319 CLAMPED_FLOAT_TO_CHAN(c
, lut
[j
]);
320 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] =
321 rgba
[i
][BCOMP
] = rgba
[i
][ACOMP
] = c
;
325 if (CHAN_TYPE
== GL_UNSIGNED_BYTE
&& table
->Size
== 256) {
327 const GLchan
*lut
= (const GLchan
*) table
->Table
;
329 for (i
= 0; i
< n
; i
++) {
330 const GLchan c
= lut
[rgba
[i
][RCOMP
]];
331 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] =
332 rgba
[i
][BCOMP
] = rgba
[i
][ACOMP
] = c
;
336 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
337 const GLchan
*lut
= (const GLchan
*) table
->Table
;
339 for (i
= 0; i
< n
; i
++) {
340 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
341 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] =
342 rgba
[i
][BCOMP
] = rgba
[i
][ACOMP
] = lut
[j
];
348 /* replace RGB with L */
349 if (table
->FloatTable
) {
350 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
351 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
353 for (i
= 0; i
< n
; i
++) {
354 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
356 CLAMPED_FLOAT_TO_CHAN(c
, lut
[j
]);
357 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = c
;
361 if (CHAN_TYPE
== GL_UNSIGNED_BYTE
&& table
->Size
== 256) {
363 const GLchan
*lut
= (const GLchan
*) table
->Table
;
365 for (i
= 0; i
< n
; i
++) {
366 const GLchan c
= lut
[rgba
[i
][RCOMP
]];
367 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = c
;
371 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
372 const GLchan
*lut
= (const GLchan
*) table
->Table
;
374 for (i
= 0; i
< n
; i
++) {
375 GLint j
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
376 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = lut
[j
];
382 /* replace A with A */
383 if (table
->FloatTable
) {
384 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
385 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
387 for (i
= 0; i
< n
; i
++) {
388 GLint j
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
390 CLAMPED_FLOAT_TO_CHAN(c
, lut
[j
]);
395 if (CHAN_TYPE
== GL_UNSIGNED_BYTE
&& table
->Size
== 256) {
397 const GLchan
*lut
= (const GLchan
*) table
->Table
;
399 for (i
= 0; i
< n
; i
++) {
400 rgba
[i
][ACOMP
] = lut
[rgba
[i
][ACOMP
]];
404 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
405 const GLchan
*lut
= (const GLchan
*) table
->Table
;
407 for (i
= 0; i
< n
; i
++) {
408 GLint j
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
409 rgba
[i
][ACOMP
] = lut
[j
];
414 case GL_LUMINANCE_ALPHA
:
415 /* replace RGBA with LLLA */
416 if (table
->FloatTable
) {
417 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
418 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
420 for (i
= 0; i
< n
; i
++) {
421 GLint jL
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
422 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
423 GLchan luminance
, alpha
;
424 CLAMPED_FLOAT_TO_CHAN(luminance
, lut
[jL
* 2 + 0]);
425 CLAMPED_FLOAT_TO_CHAN(alpha
, lut
[jA
* 2 + 1]);
426 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = luminance
;
427 rgba
[i
][ACOMP
] = alpha
;;
431 if (CHAN_TYPE
== GL_UNSIGNED_BYTE
&& table
->Size
== 256) {
433 const GLchan
*lut
= (const GLchan
*) table
->Table
;
435 for (i
= 0; i
< n
; i
++) {
436 GLchan l
= lut
[rgba
[i
][RCOMP
] * 2 + 0];
437 GLchan a
= lut
[rgba
[i
][ACOMP
] * 2 + 1];;
438 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = l
;
443 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
444 const GLchan
*lut
= (const GLchan
*) table
->Table
;
446 for (i
= 0; i
< n
; i
++) {
447 GLint jL
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
448 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
449 GLchan luminance
= lut
[jL
* 2 + 0];
450 GLchan alpha
= lut
[jA
* 2 + 1];
451 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = luminance
;
452 rgba
[i
][ACOMP
] = alpha
;
458 /* replace RGB with RGB */
459 if (table
->FloatTable
) {
460 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
461 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
463 for (i
= 0; i
< n
; i
++) {
464 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
465 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
466 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
467 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][RCOMP
], lut
[jR
* 3 + 0]);
468 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][GCOMP
], lut
[jG
* 3 + 1]);
469 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][BCOMP
], lut
[jB
* 3 + 2]);
473 if (CHAN_TYPE
== GL_UNSIGNED_BYTE
&& table
->Size
== 256) {
475 const GLchan
*lut
= (const GLchan
*) table
->Table
;
477 for (i
= 0; i
< n
; i
++) {
478 rgba
[i
][RCOMP
] = lut
[rgba
[i
][RCOMP
] * 3 + 0];
479 rgba
[i
][GCOMP
] = lut
[rgba
[i
][GCOMP
] * 3 + 1];
480 rgba
[i
][BCOMP
] = lut
[rgba
[i
][BCOMP
] * 3 + 2];
484 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
485 const GLchan
*lut
= (const GLchan
*) table
->Table
;
487 for (i
= 0; i
< n
; i
++) {
488 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
489 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
490 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
491 rgba
[i
][RCOMP
] = lut
[jR
* 3 + 0];
492 rgba
[i
][GCOMP
] = lut
[jG
* 3 + 1];
493 rgba
[i
][BCOMP
] = lut
[jB
* 3 + 2];
499 /* replace RGBA with RGBA */
500 if (!table
->FloatTable
) {
501 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
502 const GLchan
*lut
= (const GLchan
*) table
->Table
;
504 for (i
= 0; i
< n
; i
++) {
505 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
506 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
507 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
508 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
509 rgba
[i
][RCOMP
] = lut
[jR
* 4 + 0];
510 rgba
[i
][GCOMP
] = lut
[jG
* 4 + 1];
511 rgba
[i
][BCOMP
] = lut
[jB
* 4 + 2];
512 rgba
[i
][ACOMP
] = lut
[jA
* 4 + 3];
516 if (CHAN_TYPE
== GL_UNSIGNED_BYTE
&& table
->Size
== 256) {
518 const GLchan
*lut
= (const GLchan
*) table
->Table
;
520 for (i
= 0; i
< n
; i
++) {
521 rgba
[i
][RCOMP
] = lut
[rgba
[i
][RCOMP
] * 4 + 0];
522 rgba
[i
][GCOMP
] = lut
[rgba
[i
][GCOMP
] * 4 + 1];
523 rgba
[i
][BCOMP
] = lut
[rgba
[i
][BCOMP
] * 4 + 2];
524 rgba
[i
][ACOMP
] = lut
[rgba
[i
][ACOMP
] * 4 + 3];
528 const GLfloat scale
= (GLfloat
) (table
->Size
- 1) / CHAN_MAXF
;
529 const GLfloat
*lut
= (const GLfloat
*) table
->Table
;
531 for (i
= 0; i
< n
; i
++) {
532 GLint jR
= IROUND((GLfloat
) rgba
[i
][RCOMP
] * scale
);
533 GLint jG
= IROUND((GLfloat
) rgba
[i
][GCOMP
] * scale
);
534 GLint jB
= IROUND((GLfloat
) rgba
[i
][BCOMP
] * scale
);
535 GLint jA
= IROUND((GLfloat
) rgba
[i
][ACOMP
] * scale
);
536 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][RCOMP
], lut
[jR
* 4 + 0]);
537 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][GCOMP
], lut
[jG
* 4 + 1]);
538 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][BCOMP
], lut
[jB
* 4 + 2]);
539 CLAMPED_FLOAT_TO_CHAN(rgba
[i
][ACOMP
], lut
[jA
* 4 + 3]);
545 _mesa_problem(NULL
, "Bad format in _swrast_texture_table_lookup");
553 * Get texture palette entry.
556 palette_sample(const GLcontext
*ctx
,
557 const struct gl_texture_object
*tObj
,
558 GLint index
, GLchan rgba
[4] )
560 const GLchan
*palette
;
563 if (ctx
->Texture
.SharedPalette
) {
564 ASSERT(!ctx
->Texture
.Palette
.FloatTable
);
565 palette
= (const GLchan
*) ctx
->Texture
.Palette
.Table
;
566 format
= ctx
->Texture
.Palette
.Format
;
569 ASSERT(!tObj
->Palette
.FloatTable
);
570 palette
= (const GLchan
*) tObj
->Palette
.Table
;
571 format
= tObj
->Palette
.Format
;
576 rgba
[ACOMP
] = palette
[index
];
580 rgba
[RCOMP
] = palette
[index
];
582 case GL_LUMINANCE_ALPHA
:
583 rgba
[RCOMP
] = palette
[(index
<< 1) + 0];
584 rgba
[ACOMP
] = palette
[(index
<< 1) + 1];
587 rgba
[RCOMP
] = palette
[index
* 3 + 0];
588 rgba
[GCOMP
] = palette
[index
* 3 + 1];
589 rgba
[BCOMP
] = palette
[index
* 3 + 2];
592 rgba
[RCOMP
] = palette
[(index
<< 2) + 0];
593 rgba
[GCOMP
] = palette
[(index
<< 2) + 1];
594 rgba
[BCOMP
] = palette
[(index
<< 2) + 2];
595 rgba
[ACOMP
] = palette
[(index
<< 2) + 3];
598 _mesa_problem(ctx
, "Bad palette format in palette_sample");
604 * The lambda[] array values are always monotonic. Either the whole span
605 * will be minified, magnified, or split between the two. This function
606 * determines the subranges in [0, n-1] that are to be minified or magnified.
609 compute_min_mag_ranges( GLfloat minMagThresh
, GLuint n
, const GLfloat lambda
[],
610 GLuint
*minStart
, GLuint
*minEnd
,
611 GLuint
*magStart
, GLuint
*magEnd
)
613 ASSERT(lambda
!= NULL
);
615 /* Verify that lambda[] is monotonous.
616 * We can't really use this because the inaccuracy in the LOG2 function
617 * causes this test to fail, yet the resulting texturing is correct.
621 printf("lambda delta = %g\n", lambda
[0] - lambda
[n
-1]);
622 if (lambda
[0] >= lambda
[n
-1]) { /* decreasing */
623 for (i
= 0; i
< n
- 1; i
++) {
624 ASSERT((GLint
) (lambda
[i
] * 10) >= (GLint
) (lambda
[i
+1] * 10));
627 else { /* increasing */
628 for (i
= 0; i
< n
- 1; i
++) {
629 ASSERT((GLint
) (lambda
[i
] * 10) <= (GLint
) (lambda
[i
+1] * 10));
635 /* since lambda is monotonous-array use this check first */
636 if (lambda
[0] <= minMagThresh
&& lambda
[n
-1] <= minMagThresh
) {
637 /* magnification for whole span */
640 *minStart
= *minEnd
= 0;
642 else if (lambda
[0] > minMagThresh
&& lambda
[n
-1] > minMagThresh
) {
643 /* minification for whole span */
646 *magStart
= *magEnd
= 0;
649 /* a mix of minification and magnification */
651 if (lambda
[0] > minMagThresh
) {
652 /* start with minification */
653 for (i
= 1; i
< n
; i
++) {
654 if (lambda
[i
] <= minMagThresh
)
663 /* start with magnification */
664 for (i
= 1; i
< n
; i
++) {
665 if (lambda
[i
] > minMagThresh
)
676 /* Verify the min/mag Start/End values
677 * We don't use this either (see above)
681 for (i
= 0; i
< n
; i
++) {
682 if (lambda
[i
] > minMagThresh
) {
684 ASSERT(i
>= *minStart
);
689 ASSERT(i
>= *magStart
);
698 /**********************************************************************/
699 /* 1-D Texture Sampling Functions */
700 /**********************************************************************/
703 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
706 sample_1d_nearest(GLcontext
*ctx
,
707 const struct gl_texture_object
*tObj
,
708 const struct gl_texture_image
*img
,
709 const GLfloat texcoord
[4], GLchan rgba
[4])
711 const GLint width
= img
->Width2
; /* without border, power of two */
714 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
716 /* skip over the border, if any */
719 if (i
< 0 || i
>= (GLint
) img
->Width
) {
720 /* Need this test for GL_CLAMP_TO_BORDER mode */
721 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
724 (*img
->FetchTexel
)(img
, i
, 0, 0, (GLvoid
*) rgba
);
725 if (img
->Format
== GL_COLOR_INDEX
) {
726 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
734 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
737 sample_1d_linear(GLcontext
*ctx
,
738 const struct gl_texture_object
*tObj
,
739 const struct gl_texture_image
*img
,
740 const GLfloat texcoord
[4], GLchan rgba
[4])
742 const GLint width
= img
->Width2
;
745 GLuint useBorderColor
;
747 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
755 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
756 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
760 const GLfloat a
= FRAC(u
);
762 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
763 const GLfloat w0
= (1.0F
-a
);
764 const GLfloat w1
= a
;
765 #else /* CHAN_BITS == 8 */
766 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
767 const GLint w0
= IROUND_POS((1.0F
- a
) * WEIGHT_SCALE
);
768 const GLint w1
= IROUND_POS( a
* WEIGHT_SCALE
);
770 GLchan t0
[4], t1
[4]; /* texels */
772 if (useBorderColor
& I0BIT
) {
773 COPY_CHAN4(t0
, tObj
->_BorderChan
);
776 (*img
->FetchTexel
)(img
, i0
, 0, 0, (GLvoid
*) t0
);
777 if (img
->Format
== GL_COLOR_INDEX
) {
778 palette_sample(ctx
, tObj
, t0
[0], t0
);
781 if (useBorderColor
& I1BIT
) {
782 COPY_CHAN4(t1
, tObj
->_BorderChan
);
785 (*img
->FetchTexel
)(img
, i1
, 0, 0, (GLvoid
*) t1
);
786 if (img
->Format
== GL_COLOR_INDEX
) {
787 palette_sample(ctx
, tObj
, t1
[0], t1
);
791 #if CHAN_TYPE == GL_FLOAT
792 rgba
[0] = w0
* t0
[0] + w1
* t1
[0];
793 rgba
[1] = w0
* t0
[1] + w1
* t1
[1];
794 rgba
[2] = w0
* t0
[2] + w1
* t1
[2];
795 rgba
[3] = w0
* t0
[3] + w1
* t1
[3];
796 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
797 rgba
[0] = (GLchan
) (w0
* t0
[0] + w1
* t1
[0] + 0.5);
798 rgba
[1] = (GLchan
) (w0
* t0
[1] + w1
* t1
[1] + 0.5);
799 rgba
[2] = (GLchan
) (w0
* t0
[2] + w1
* t1
[2] + 0.5);
800 rgba
[3] = (GLchan
) (w0
* t0
[3] + w1
* t1
[3] + 0.5);
801 #else /* CHAN_BITS == 8 */
802 rgba
[0] = (GLchan
) ((w0
* t0
[0] + w1
* t1
[0]) >> WEIGHT_SHIFT
);
803 rgba
[1] = (GLchan
) ((w0
* t0
[1] + w1
* t1
[1]) >> WEIGHT_SHIFT
);
804 rgba
[2] = (GLchan
) ((w0
* t0
[2] + w1
* t1
[2]) >> WEIGHT_SHIFT
);
805 rgba
[3] = (GLchan
) ((w0
* t0
[3] + w1
* t1
[3]) >> WEIGHT_SHIFT
);
813 sample_1d_nearest_mipmap_nearest(GLcontext
*ctx
,
814 const struct gl_texture_object
*tObj
,
815 GLuint n
, GLfloat texcoord
[][4],
816 const GLfloat lambda
[], GLchan rgba
[][4])
819 ASSERT(lambda
!= NULL
);
820 for (i
= 0; i
< n
; i
++) {
822 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
823 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
829 sample_1d_linear_mipmap_nearest(GLcontext
*ctx
,
830 const struct gl_texture_object
*tObj
,
831 GLuint n
, GLfloat texcoord
[][4],
832 const GLfloat lambda
[], GLchan rgba
[][4])
835 ASSERT(lambda
!= NULL
);
836 for (i
= 0; i
< n
; i
++) {
838 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
839 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
846 * This is really just needed in order to prevent warnings with some compilers.
848 #if CHAN_TYPE == GL_FLOAT
851 #define CHAN_CAST (GLchan) (GLint)
856 sample_1d_nearest_mipmap_linear(GLcontext
*ctx
,
857 const struct gl_texture_object
*tObj
,
858 GLuint n
, GLfloat texcoord
[][4],
859 const GLfloat lambda
[], GLchan rgba
[][4])
862 ASSERT(lambda
!= NULL
);
863 for (i
= 0; i
< n
; i
++) {
865 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
866 if (level
>= tObj
->_MaxLevel
) {
867 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
868 texcoord
[i
], rgba
[i
]);
872 const GLfloat f
= FRAC(lambda
[i
]);
873 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
874 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
875 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
876 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
877 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
878 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
886 sample_1d_linear_mipmap_linear(GLcontext
*ctx
,
887 const struct gl_texture_object
*tObj
,
888 GLuint n
, GLfloat texcoord
[][4],
889 const GLfloat lambda
[], GLchan rgba
[][4])
892 ASSERT(lambda
!= NULL
);
893 for (i
= 0; i
< n
; i
++) {
895 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
896 if (level
>= tObj
->_MaxLevel
) {
897 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
898 texcoord
[i
], rgba
[i
]);
902 const GLfloat f
= FRAC(lambda
[i
]);
903 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
904 sample_1d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
905 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
906 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
907 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
908 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
916 sample_nearest_1d( GLcontext
*ctx
, GLuint texUnit
,
917 const struct gl_texture_object
*tObj
, GLuint n
,
918 GLfloat texcoords
[][4], const GLfloat lambda
[],
922 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
925 sample_1d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
932 sample_linear_1d( GLcontext
*ctx
, GLuint texUnit
,
933 const struct gl_texture_object
*tObj
, GLuint n
,
934 GLfloat texcoords
[][4], const GLfloat lambda
[],
938 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
941 sample_1d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
947 * Given an (s) texture coordinate and lambda (level of detail) value,
948 * return a texture sample.
952 sample_lambda_1d( GLcontext
*ctx
, GLuint texUnit
,
953 const struct gl_texture_object
*tObj
, GLuint n
,
954 GLfloat texcoords
[][4],
955 const GLfloat lambda
[], GLchan rgba
[][4] )
957 GLuint minStart
, minEnd
; /* texels with minification */
958 GLuint magStart
, magEnd
; /* texels with magnification */
961 ASSERT(lambda
!= NULL
);
962 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
963 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
965 if (minStart
< minEnd
) {
966 /* do the minified texels */
967 const GLuint m
= minEnd
- minStart
;
968 switch (tObj
->MinFilter
) {
970 for (i
= minStart
; i
< minEnd
; i
++)
971 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
972 texcoords
[i
], rgba
[i
]);
975 for (i
= minStart
; i
< minEnd
; i
++)
976 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
977 texcoords
[i
], rgba
[i
]);
979 case GL_NEAREST_MIPMAP_NEAREST
:
980 sample_1d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
981 lambda
+ minStart
, rgba
+ minStart
);
983 case GL_LINEAR_MIPMAP_NEAREST
:
984 sample_1d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
985 lambda
+ minStart
, rgba
+ minStart
);
987 case GL_NEAREST_MIPMAP_LINEAR
:
988 sample_1d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
989 lambda
+ minStart
, rgba
+ minStart
);
991 case GL_LINEAR_MIPMAP_LINEAR
:
992 sample_1d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
993 lambda
+ minStart
, rgba
+ minStart
);
996 _mesa_problem(ctx
, "Bad min filter in sample_1d_texture");
1001 if (magStart
< magEnd
) {
1002 /* do the magnified texels */
1003 switch (tObj
->MagFilter
) {
1005 for (i
= magStart
; i
< magEnd
; i
++)
1006 sample_1d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1007 texcoords
[i
], rgba
[i
]);
1010 for (i
= magStart
; i
< magEnd
; i
++)
1011 sample_1d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1012 texcoords
[i
], rgba
[i
]);
1015 _mesa_problem(ctx
, "Bad mag filter in sample_1d_texture");
1022 /**********************************************************************/
1023 /* 2-D Texture Sampling Functions */
1024 /**********************************************************************/
1028 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
1031 sample_2d_nearest(GLcontext
*ctx
,
1032 const struct gl_texture_object
*tObj
,
1033 const struct gl_texture_image
*img
,
1034 const GLfloat texcoord
[4],
1037 const GLint width
= img
->Width2
; /* without border, power of two */
1038 const GLint height
= img
->Height2
; /* without border, power of two */
1041 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
1042 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
1044 /* skip over the border, if any */
1048 if (i
< 0 || i
>= (GLint
) img
->Width
|| j
< 0 || j
>= (GLint
) img
->Height
) {
1049 /* Need this test for GL_CLAMP_TO_BORDER mode */
1050 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
1053 (*img
->FetchTexel
)(img
, i
, j
, 0, (GLvoid
*) rgba
);
1054 if (img
->Format
== GL_COLOR_INDEX
) {
1055 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
1063 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
1064 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
1067 sample_2d_linear(GLcontext
*ctx
,
1068 const struct gl_texture_object
*tObj
,
1069 const struct gl_texture_image
*img
,
1070 const GLfloat texcoord
[4],
1073 const GLint width
= img
->Width2
;
1074 const GLint height
= img
->Height2
;
1075 GLint i0
, j0
, i1
, j1
;
1076 GLuint useBorderColor
;
1079 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1080 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1090 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1091 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1092 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1093 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1097 const GLfloat a
= FRAC(u
);
1098 const GLfloat b
= FRAC(v
);
1100 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1101 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
1102 const GLfloat w10
= a
* (1.0F
-b
);
1103 const GLfloat w01
= (1.0F
-a
) * b
;
1104 const GLfloat w11
= a
* b
;
1105 #else /* CHAN_BITS == 8 */
1106 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1107 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
1108 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
1109 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
1110 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
1117 if (useBorderColor
& (I0BIT
| J0BIT
)) {
1118 COPY_CHAN4(t00
, tObj
->_BorderChan
);
1121 (*img
->FetchTexel
)(img
, i0
, j0
, 0, (GLvoid
*) t00
);
1122 if (img
->Format
== GL_COLOR_INDEX
) {
1123 palette_sample(ctx
, tObj
, t00
[0], t00
);
1126 if (useBorderColor
& (I1BIT
| J0BIT
)) {
1127 COPY_CHAN4(t10
, tObj
->_BorderChan
);
1130 (*img
->FetchTexel
)(img
, i1
, j0
, 0, (GLvoid
*) t10
);
1131 if (img
->Format
== GL_COLOR_INDEX
) {
1132 palette_sample(ctx
, tObj
, t10
[0], t10
);
1135 if (useBorderColor
& (I0BIT
| J1BIT
)) {
1136 COPY_CHAN4(t01
, tObj
->_BorderChan
);
1139 (*img
->FetchTexel
)(img
, i0
, j1
, 0, (GLvoid
*) t01
);
1140 if (img
->Format
== GL_COLOR_INDEX
) {
1141 palette_sample(ctx
, tObj
, t01
[0], t01
);
1144 if (useBorderColor
& (I1BIT
| J1BIT
)) {
1145 COPY_CHAN4(t11
, tObj
->_BorderChan
);
1148 (*img
->FetchTexel
)(img
, i1
, j1
, 0, (GLvoid
*) t11
);
1149 if (img
->Format
== GL_COLOR_INDEX
) {
1150 palette_sample(ctx
, tObj
, t11
[0], t11
);
1153 #if CHAN_TYPE == GL_FLOAT
1154 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
1155 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
1156 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
1157 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
1158 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1159 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
1160 w01
* t01
[0] + w11
* t11
[0] + 0.5);
1161 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
1162 w01
* t01
[1] + w11
* t11
[1] + 0.5);
1163 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
1164 w01
* t01
[2] + w11
* t11
[2] + 0.5);
1165 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
1166 w01
* t01
[3] + w11
* t11
[3] + 0.5);
1167 #else /* CHAN_BITS == 8 */
1168 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
1169 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
1170 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
1171 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
1172 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
1173 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
1174 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
1175 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
1184 * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT
1185 * and we're not using a paletted texture.
1188 sample_2d_linear_repeat(GLcontext
*ctx
,
1189 const struct gl_texture_object
*tObj
,
1190 const struct gl_texture_image
*img
,
1191 const GLfloat texcoord
[4],
1194 const GLint width
= img
->Width2
;
1195 const GLint height
= img
->Height2
;
1196 GLint i0
, j0
, i1
, j1
;
1199 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1200 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1201 ASSERT(img
->Border
== 0);
1202 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
1204 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[0], u
, width
, i0
, i1
);
1205 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord
[1], v
, height
, j0
, j1
);
1208 const GLfloat a
= FRAC(u
);
1209 const GLfloat b
= FRAC(v
);
1211 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1212 const GLfloat w00
= (1.0F
-a
) * (1.0F
-b
);
1213 const GLfloat w10
= a
* (1.0F
-b
);
1214 const GLfloat w01
= (1.0F
-a
) * b
;
1215 const GLfloat w11
= a
* b
;
1216 #else /* CHAN_BITS == 8 */
1217 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1218 const GLint w00
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * WEIGHT_SCALE
);
1219 const GLint w10
= IROUND_POS( a
* (1.0F
-b
) * WEIGHT_SCALE
);
1220 const GLint w01
= IROUND_POS((1.0F
-a
) * b
* WEIGHT_SCALE
);
1221 const GLint w11
= IROUND_POS( a
* b
* WEIGHT_SCALE
);
1228 (*img
->FetchTexel
)(img
, i0
, j0
, 0, (GLvoid
*) t00
);
1229 (*img
->FetchTexel
)(img
, i1
, j0
, 0, (GLvoid
*) t10
);
1230 (*img
->FetchTexel
)(img
, i0
, j1
, 0, (GLvoid
*) t01
);
1231 (*img
->FetchTexel
)(img
, i1
, j1
, 0, (GLvoid
*) t11
);
1233 #if CHAN_TYPE == GL_FLOAT
1234 rgba
[0] = w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0];
1235 rgba
[1] = w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1];
1236 rgba
[2] = w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2];
1237 rgba
[3] = w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3];
1238 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1239 rgba
[0] = (GLchan
) (w00
* t00
[0] + w10
* t10
[0] +
1240 w01
* t01
[0] + w11
* t11
[0] + 0.5);
1241 rgba
[1] = (GLchan
) (w00
* t00
[1] + w10
* t10
[1] +
1242 w01
* t01
[1] + w11
* t11
[1] + 0.5);
1243 rgba
[2] = (GLchan
) (w00
* t00
[2] + w10
* t10
[2] +
1244 w01
* t01
[2] + w11
* t11
[2] + 0.5);
1245 rgba
[3] = (GLchan
) (w00
* t00
[3] + w10
* t10
[3] +
1246 w01
* t01
[3] + w11
* t11
[3] + 0.5);
1247 #else /* CHAN_BITS == 8 */
1248 rgba
[0] = (GLchan
) ((w00
* t00
[0] + w10
* t10
[0] +
1249 w01
* t01
[0] + w11
* t11
[0]) >> WEIGHT_SHIFT
);
1250 rgba
[1] = (GLchan
) ((w00
* t00
[1] + w10
* t10
[1] +
1251 w01
* t01
[1] + w11
* t11
[1]) >> WEIGHT_SHIFT
);
1252 rgba
[2] = (GLchan
) ((w00
* t00
[2] + w10
* t10
[2] +
1253 w01
* t01
[2] + w11
* t11
[2]) >> WEIGHT_SHIFT
);
1254 rgba
[3] = (GLchan
) ((w00
* t00
[3] + w10
* t10
[3] +
1255 w01
* t01
[3] + w11
* t11
[3]) >> WEIGHT_SHIFT
);
1265 sample_2d_nearest_mipmap_nearest(GLcontext
*ctx
,
1266 const struct gl_texture_object
*tObj
,
1267 GLuint n
, GLfloat texcoord
[][4],
1268 const GLfloat lambda
[], GLchan rgba
[][4])
1271 for (i
= 0; i
< n
; i
++) {
1273 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1274 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1281 sample_2d_linear_mipmap_nearest(GLcontext
*ctx
,
1282 const struct gl_texture_object
*tObj
,
1283 GLuint n
, GLfloat texcoord
[][4],
1284 const GLfloat lambda
[], GLchan rgba
[][4])
1287 ASSERT(lambda
!= NULL
);
1288 for (i
= 0; i
< n
; i
++) {
1290 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1291 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1298 sample_2d_nearest_mipmap_linear(GLcontext
*ctx
,
1299 const struct gl_texture_object
*tObj
,
1300 GLuint n
, GLfloat texcoord
[][4],
1301 const GLfloat lambda
[], GLchan rgba
[][4])
1304 ASSERT(lambda
!= NULL
);
1305 for (i
= 0; i
< n
; i
++) {
1307 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1308 if (level
>= tObj
->_MaxLevel
) {
1309 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1310 texcoord
[i
], rgba
[i
]);
1313 GLchan t0
[4], t1
[4]; /* texels */
1314 const GLfloat f
= FRAC(lambda
[i
]);
1315 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1316 sample_2d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1317 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1318 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1319 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1320 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1327 /* Trilinear filtering */
1329 sample_2d_linear_mipmap_linear( GLcontext
*ctx
,
1330 const struct gl_texture_object
*tObj
,
1331 GLuint n
, GLfloat texcoord
[][4],
1332 const GLfloat lambda
[], GLchan rgba
[][4] )
1335 ASSERT(lambda
!= NULL
);
1336 for (i
= 0; i
< n
; i
++) {
1338 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1339 if (level
>= tObj
->_MaxLevel
) {
1340 sample_2d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1341 texcoord
[i
], rgba
[i
]);
1344 GLchan t0
[4], t1
[4]; /* texels */
1345 const GLfloat f
= FRAC(lambda
[i
]);
1346 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1347 sample_2d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1348 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1349 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1350 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1351 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1358 sample_2d_linear_mipmap_linear_repeat( GLcontext
*ctx
,
1359 const struct gl_texture_object
*tObj
,
1360 GLuint n
, GLfloat texcoord
[][4],
1361 const GLfloat lambda
[], GLchan rgba
[][4] )
1364 ASSERT(lambda
!= NULL
);
1365 ASSERT(tObj
->WrapS
== GL_REPEAT
);
1366 ASSERT(tObj
->WrapT
== GL_REPEAT
);
1367 for (i
= 0; i
< n
; i
++) {
1369 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1370 if (level
>= tObj
->_MaxLevel
) {
1371 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1372 texcoord
[i
], rgba
[i
]);
1375 GLchan t0
[4], t1
[4]; /* texels */
1376 const GLfloat f
= FRAC(lambda
[i
]);
1377 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1378 sample_2d_linear_repeat(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1379 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1380 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1381 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1382 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1389 sample_nearest_2d( GLcontext
*ctx
, GLuint texUnit
,
1390 const struct gl_texture_object
*tObj
, GLuint n
,
1391 GLfloat texcoords
[][4],
1392 const GLfloat lambda
[], GLchan rgba
[][4] )
1395 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1398 sample_2d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1405 sample_linear_2d( GLcontext
*ctx
, GLuint texUnit
,
1406 const struct gl_texture_object
*tObj
, GLuint n
,
1407 GLfloat texcoords
[][4],
1408 const GLfloat lambda
[], GLchan rgba
[][4] )
1411 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1414 sample_2d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1420 * Optimized 2-D texture sampling:
1421 * S and T wrap mode == GL_REPEAT
1422 * GL_NEAREST min/mag filter
1424 * RowStride == Width,
1428 opt_sample_rgb_2d( GLcontext
*ctx
, GLuint texUnit
,
1429 const struct gl_texture_object
*tObj
,
1430 GLuint n
, GLfloat texcoords
[][4],
1431 const GLfloat lambda
[], GLchan rgba
[][4] )
1433 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
1434 const GLfloat width
= (GLfloat
) img
->Width
;
1435 const GLfloat height
= (GLfloat
) img
->Height
;
1436 const GLint colMask
= img
->Width
- 1;
1437 const GLint rowMask
= img
->Height
- 1;
1438 const GLint shift
= img
->WidthLog2
;
1441 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1442 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1443 ASSERT(img
->Border
==0);
1444 ASSERT(img
->Format
==GL_RGB
);
1446 for (k
=0; k
<n
; k
++) {
1447 GLint i
= IFLOOR(texcoords
[k
][0] * width
) & colMask
;
1448 GLint j
= IFLOOR(texcoords
[k
][1] * height
) & rowMask
;
1449 GLint pos
= (j
<< shift
) | i
;
1450 GLchan
*texel
= ((GLchan
*) img
->Data
) + 3*pos
;
1451 rgba
[k
][RCOMP
] = texel
[0];
1452 rgba
[k
][GCOMP
] = texel
[1];
1453 rgba
[k
][BCOMP
] = texel
[2];
1459 * Optimized 2-D texture sampling:
1460 * S and T wrap mode == GL_REPEAT
1461 * GL_NEAREST min/mag filter
1463 * RowStride == Width,
1467 opt_sample_rgba_2d( GLcontext
*ctx
, GLuint texUnit
,
1468 const struct gl_texture_object
*tObj
,
1469 GLuint n
, GLfloat texcoords
[][4],
1470 const GLfloat lambda
[], GLchan rgba
[][4] )
1472 const struct gl_texture_image
*img
= tObj
->Image
[tObj
->BaseLevel
];
1473 const GLfloat width
= (GLfloat
) img
->Width
;
1474 const GLfloat height
= (GLfloat
) img
->Height
;
1475 const GLint colMask
= img
->Width
- 1;
1476 const GLint rowMask
= img
->Height
- 1;
1477 const GLint shift
= img
->WidthLog2
;
1480 ASSERT(tObj
->WrapS
==GL_REPEAT
);
1481 ASSERT(tObj
->WrapT
==GL_REPEAT
);
1482 ASSERT(img
->Border
==0);
1483 ASSERT(img
->Format
==GL_RGBA
);
1485 for (i
= 0; i
< n
; i
++) {
1486 const GLint col
= IFLOOR(texcoords
[i
][0] * width
) & colMask
;
1487 const GLint row
= IFLOOR(texcoords
[i
][1] * height
) & rowMask
;
1488 const GLint pos
= (row
<< shift
) | col
;
1489 const GLchan
*texel
= ((GLchan
*) img
->Data
) + (pos
<< 2); /* pos*4 */
1490 COPY_CHAN4(rgba
[i
], texel
);
1496 * Given an array of texture coordinate and lambda (level of detail)
1497 * values, return an array of texture sample.
1500 sample_lambda_2d( GLcontext
*ctx
, GLuint texUnit
,
1501 const struct gl_texture_object
*tObj
,
1502 GLuint n
, GLfloat texcoords
[][4],
1503 const GLfloat lambda
[], GLchan rgba
[][4] )
1505 const struct gl_texture_image
*tImg
= tObj
->Image
[tObj
->BaseLevel
];
1506 GLuint minStart
, minEnd
; /* texels with minification */
1507 GLuint magStart
, magEnd
; /* texels with magnification */
1509 const GLboolean repeatNoBorder
= (tObj
->WrapS
== GL_REPEAT
)
1510 && (tObj
->WrapT
== GL_REPEAT
)
1511 && (tImg
->Border
== 0 && (tImg
->Width
== tImg
->RowStride
))
1512 && (tImg
->Format
!= GL_COLOR_INDEX
);
1514 ASSERT(lambda
!= NULL
);
1515 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1516 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1518 if (minStart
< minEnd
) {
1519 /* do the minified texels */
1520 const GLuint m
= minEnd
- minStart
;
1521 switch (tObj
->MinFilter
) {
1523 if (repeatNoBorder
) {
1524 switch (tImg
->Format
) {
1526 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1527 NULL
, rgba
+ minStart
);
1530 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1531 NULL
, rgba
+ minStart
);
1534 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1535 NULL
, rgba
+ minStart
);
1539 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1540 NULL
, rgba
+ minStart
);
1544 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
1545 NULL
, rgba
+ minStart
);
1547 case GL_NEAREST_MIPMAP_NEAREST
:
1548 sample_2d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1549 lambda
+ minStart
, rgba
+ minStart
);
1551 case GL_LINEAR_MIPMAP_NEAREST
:
1552 sample_2d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1553 lambda
+ minStart
, rgba
+ minStart
);
1555 case GL_NEAREST_MIPMAP_LINEAR
:
1556 sample_2d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1557 lambda
+ minStart
, rgba
+ minStart
);
1559 case GL_LINEAR_MIPMAP_LINEAR
:
1561 sample_2d_linear_mipmap_linear_repeat(ctx
, tObj
, m
,
1562 texcoords
+ minStart
, lambda
+ minStart
, rgba
+ minStart
);
1564 sample_2d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1565 lambda
+ minStart
, rgba
+ minStart
);
1568 _mesa_problem(ctx
, "Bad min filter in sample_2d_texture");
1573 if (magStart
< magEnd
) {
1574 /* do the magnified texels */
1575 const GLuint m
= magEnd
- magStart
;
1577 switch (tObj
->MagFilter
) {
1579 if (repeatNoBorder
) {
1580 switch (tImg
->Format
) {
1582 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1583 NULL
, rgba
+ magStart
);
1586 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1587 NULL
, rgba
+ magStart
);
1590 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1591 NULL
, rgba
+ magStart
);
1595 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1596 NULL
, rgba
+ magStart
);
1600 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1601 NULL
, rgba
+ magStart
);
1604 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_2d");
1611 /**********************************************************************/
1612 /* 3-D Texture Sampling Functions */
1613 /**********************************************************************/
1616 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1619 sample_3d_nearest(GLcontext
*ctx
,
1620 const struct gl_texture_object
*tObj
,
1621 const struct gl_texture_image
*img
,
1622 const GLfloat texcoord
[4],
1625 const GLint width
= img
->Width2
; /* without border, power of two */
1626 const GLint height
= img
->Height2
; /* without border, power of two */
1627 const GLint depth
= img
->Depth2
; /* without border, power of two */
1630 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
1631 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
1632 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapR
, texcoord
[2], depth
, k
);
1634 if (i
< 0 || i
>= (GLint
) img
->Width
||
1635 j
< 0 || j
>= (GLint
) img
->Height
||
1636 k
< 0 || k
>= (GLint
) img
->Depth
) {
1637 /* Need this test for GL_CLAMP_TO_BORDER mode */
1638 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
1641 (*img
->FetchTexel
)(img
, i
, j
, k
, (GLvoid
*) rgba
);
1642 if (img
->Format
== GL_COLOR_INDEX
) {
1643 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
1651 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1654 sample_3d_linear(GLcontext
*ctx
,
1655 const struct gl_texture_object
*tObj
,
1656 const struct gl_texture_image
*img
,
1657 const GLfloat texcoord
[4],
1660 const GLint width
= img
->Width2
;
1661 const GLint height
= img
->Height2
;
1662 const GLint depth
= img
->Depth2
;
1663 GLint i0
, j0
, k0
, i1
, j1
, k1
;
1664 GLuint useBorderColor
;
1667 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1668 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1669 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapR
, texcoord
[2], w
, depth
, k0
, k1
);
1681 /* check if sampling texture border color */
1682 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1683 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1684 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1685 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1686 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
1687 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
1691 const GLfloat a
= FRAC(u
);
1692 const GLfloat b
= FRAC(v
);
1693 const GLfloat c
= FRAC(w
);
1695 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1696 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1697 GLfloat w000
= (1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
);
1698 GLfloat w100
= a
* (1.0F
-b
) * (1.0F
-c
);
1699 GLfloat w010
= (1.0F
-a
) * b
* (1.0F
-c
);
1700 GLfloat w110
= a
* b
* (1.0F
-c
);
1701 GLfloat w001
= (1.0F
-a
) * (1.0F
-b
) * c
;
1702 GLfloat w101
= a
* (1.0F
-b
) * c
;
1703 GLfloat w011
= (1.0F
-a
) * b
* c
;
1704 GLfloat w111
= a
* b
* c
;
1705 #else /* CHAN_BITS == 8 */
1706 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1707 GLint w000
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1708 GLint w100
= IROUND_POS( a
* (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1709 GLint w010
= IROUND_POS((1.0F
-a
) * b
* (1.0F
-c
) * WEIGHT_SCALE
);
1710 GLint w110
= IROUND_POS( a
* b
* (1.0F
-c
) * WEIGHT_SCALE
);
1711 GLint w001
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * c
* WEIGHT_SCALE
);
1712 GLint w101
= IROUND_POS( a
* (1.0F
-b
) * c
* WEIGHT_SCALE
);
1713 GLint w011
= IROUND_POS((1.0F
-a
) * b
* c
* WEIGHT_SCALE
);
1714 GLint w111
= IROUND_POS( a
* b
* c
* WEIGHT_SCALE
);
1717 GLchan t000
[4], t010
[4], t001
[4], t011
[4];
1718 GLchan t100
[4], t110
[4], t101
[4], t111
[4];
1720 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
1721 COPY_CHAN4(t000
, tObj
->_BorderChan
);
1724 (*img
->FetchTexel
)(img
, i0
, j0
, k0
, (GLvoid
*) t000
);
1725 if (img
->Format
== GL_COLOR_INDEX
) {
1726 palette_sample(ctx
, tObj
, t000
[0], t000
);
1729 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
1730 COPY_CHAN4(t100
, tObj
->_BorderChan
);
1733 (*img
->FetchTexel
)(img
, i1
, j0
, k0
, (GLvoid
*) t100
);
1734 if (img
->Format
== GL_COLOR_INDEX
) {
1735 palette_sample(ctx
, tObj
, t100
[0], t100
);
1738 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
1739 COPY_CHAN4(t010
, tObj
->_BorderChan
);
1742 (*img
->FetchTexel
)(img
, i0
, j1
, k0
, (GLvoid
*) t010
);
1743 if (img
->Format
== GL_COLOR_INDEX
) {
1744 palette_sample(ctx
, tObj
, t010
[0], t010
);
1747 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
1748 COPY_CHAN4(t110
, tObj
->_BorderChan
);
1751 (*img
->FetchTexel
)(img
, i1
, j1
, k0
, (GLvoid
*) t110
);
1752 if (img
->Format
== GL_COLOR_INDEX
) {
1753 palette_sample(ctx
, tObj
, t110
[0], t110
);
1757 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
1758 COPY_CHAN4(t001
, tObj
->_BorderChan
);
1761 (*img
->FetchTexel
)(img
, i0
, j0
, k1
, (GLvoid
*) t001
);
1762 if (img
->Format
== GL_COLOR_INDEX
) {
1763 palette_sample(ctx
, tObj
, t001
[0], t001
);
1766 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
1767 COPY_CHAN4(t101
, tObj
->_BorderChan
);
1770 (*img
->FetchTexel
)(img
, i1
, j0
, k1
, (GLvoid
*) t101
);
1771 if (img
->Format
== GL_COLOR_INDEX
) {
1772 palette_sample(ctx
, tObj
, t101
[0], t101
);
1775 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
1776 COPY_CHAN4(t011
, tObj
->_BorderChan
);
1779 (*img
->FetchTexel
)(img
, i0
, j1
, k1
, (GLvoid
*) t011
);
1780 if (img
->Format
== GL_COLOR_INDEX
) {
1781 palette_sample(ctx
, tObj
, t011
[0], t011
);
1784 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
1785 COPY_CHAN4(t111
, tObj
->_BorderChan
);
1788 (*img
->FetchTexel
)(img
, i1
, j1
, k1
, (GLvoid
*) t111
);
1789 if (img
->Format
== GL_COLOR_INDEX
) {
1790 palette_sample(ctx
, tObj
, t111
[0], t111
);
1794 #if CHAN_TYPE == GL_FLOAT
1795 rgba
[0] = w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1796 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0];
1797 rgba
[1] = w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1798 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1];
1799 rgba
[2] = w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1800 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2];
1801 rgba
[3] = w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1802 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3];
1803 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1804 rgba
[0] = (GLchan
) (w000
*t000
[0] + w010
*t010
[0] +
1805 w001
*t001
[0] + w011
*t011
[0] +
1806 w100
*t100
[0] + w110
*t110
[0] +
1807 w101
*t101
[0] + w111
*t111
[0] + 0.5);
1808 rgba
[1] = (GLchan
) (w000
*t000
[1] + w010
*t010
[1] +
1809 w001
*t001
[1] + w011
*t011
[1] +
1810 w100
*t100
[1] + w110
*t110
[1] +
1811 w101
*t101
[1] + w111
*t111
[1] + 0.5);
1812 rgba
[2] = (GLchan
) (w000
*t000
[2] + w010
*t010
[2] +
1813 w001
*t001
[2] + w011
*t011
[2] +
1814 w100
*t100
[2] + w110
*t110
[2] +
1815 w101
*t101
[2] + w111
*t111
[2] + 0.5);
1816 rgba
[3] = (GLchan
) (w000
*t000
[3] + w010
*t010
[3] +
1817 w001
*t001
[3] + w011
*t011
[3] +
1818 w100
*t100
[3] + w110
*t110
[3] +
1819 w101
*t101
[3] + w111
*t111
[3] + 0.5);
1820 #else /* CHAN_BITS == 8 */
1821 rgba
[0] = (GLchan
) (
1822 (w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1823 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0] )
1825 rgba
[1] = (GLchan
) (
1826 (w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1827 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1] )
1829 rgba
[2] = (GLchan
) (
1830 (w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1831 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2] )
1833 rgba
[3] = (GLchan
) (
1834 (w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1835 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3] )
1845 sample_3d_nearest_mipmap_nearest(GLcontext
*ctx
,
1846 const struct gl_texture_object
*tObj
,
1847 GLuint n
, GLfloat texcoord
[][4],
1848 const GLfloat lambda
[], GLchan rgba
[][4] )
1851 for (i
= 0; i
< n
; i
++) {
1853 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1854 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1860 sample_3d_linear_mipmap_nearest(GLcontext
*ctx
,
1861 const struct gl_texture_object
*tObj
,
1862 GLuint n
, GLfloat texcoord
[][4],
1863 const GLfloat lambda
[], GLchan rgba
[][4])
1866 ASSERT(lambda
!= NULL
);
1867 for (i
= 0; i
< n
; i
++) {
1869 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1870 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1876 sample_3d_nearest_mipmap_linear(GLcontext
*ctx
,
1877 const struct gl_texture_object
*tObj
,
1878 GLuint n
, GLfloat texcoord
[][4],
1879 const GLfloat lambda
[], GLchan rgba
[][4])
1882 ASSERT(lambda
!= NULL
);
1883 for (i
= 0; i
< n
; i
++) {
1885 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1886 if (level
>= tObj
->_MaxLevel
) {
1887 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1888 texcoord
[i
], rgba
[i
]);
1891 GLchan t0
[4], t1
[4]; /* texels */
1892 const GLfloat f
= FRAC(lambda
[i
]);
1893 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1894 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1895 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1896 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1897 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1898 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1905 sample_3d_linear_mipmap_linear(GLcontext
*ctx
,
1906 const struct gl_texture_object
*tObj
,
1907 GLuint n
, GLfloat texcoord
[][4],
1908 const GLfloat lambda
[], GLchan rgba
[][4])
1911 ASSERT(lambda
!= NULL
);
1912 for (i
= 0; i
< n
; i
++) {
1914 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1915 if (level
>= tObj
->_MaxLevel
) {
1916 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1917 texcoord
[i
], rgba
[i
]);
1920 GLchan t0
[4], t1
[4]; /* texels */
1921 const GLfloat f
= FRAC(lambda
[i
]);
1922 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1923 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1924 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1925 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1926 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1927 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1934 sample_nearest_3d(GLcontext
*ctx
, GLuint texUnit
,
1935 const struct gl_texture_object
*tObj
, GLuint n
,
1936 GLfloat texcoords
[][4], const GLfloat lambda
[],
1940 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1943 sample_3d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1950 sample_linear_3d( GLcontext
*ctx
, GLuint texUnit
,
1951 const struct gl_texture_object
*tObj
, GLuint n
,
1952 GLfloat texcoords
[][4],
1953 const GLfloat lambda
[], GLchan rgba
[][4] )
1956 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1959 sample_3d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1965 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
1966 * return a texture sample.
1969 sample_lambda_3d( GLcontext
*ctx
, GLuint texUnit
,
1970 const struct gl_texture_object
*tObj
, GLuint n
,
1971 GLfloat texcoords
[][4], const GLfloat lambda
[],
1974 GLuint minStart
, minEnd
; /* texels with minification */
1975 GLuint magStart
, magEnd
; /* texels with magnification */
1978 ASSERT(lambda
!= NULL
);
1979 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1980 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1982 if (minStart
< minEnd
) {
1983 /* do the minified texels */
1984 GLuint m
= minEnd
- minStart
;
1985 switch (tObj
->MinFilter
) {
1987 for (i
= minStart
; i
< minEnd
; i
++)
1988 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1989 texcoords
[i
], rgba
[i
]);
1992 for (i
= minStart
; i
< minEnd
; i
++)
1993 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1994 texcoords
[i
], rgba
[i
]);
1996 case GL_NEAREST_MIPMAP_NEAREST
:
1997 sample_3d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1998 lambda
+ minStart
, rgba
+ minStart
);
2000 case GL_LINEAR_MIPMAP_NEAREST
:
2001 sample_3d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
2002 lambda
+ minStart
, rgba
+ minStart
);
2004 case GL_NEAREST_MIPMAP_LINEAR
:
2005 sample_3d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
2006 lambda
+ minStart
, rgba
+ minStart
);
2008 case GL_LINEAR_MIPMAP_LINEAR
:
2009 sample_3d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
2010 lambda
+ minStart
, rgba
+ minStart
);
2013 _mesa_problem(ctx
, "Bad min filter in sample_3d_texture");
2018 if (magStart
< magEnd
) {
2019 /* do the magnified texels */
2020 switch (tObj
->MagFilter
) {
2022 for (i
= magStart
; i
< magEnd
; i
++)
2023 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
2024 texcoords
[i
], rgba
[i
]);
2027 for (i
= magStart
; i
< magEnd
; i
++)
2028 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
2029 texcoords
[i
], rgba
[i
]);
2032 _mesa_problem(ctx
, "Bad mag filter in sample_3d_texture");
2039 /**********************************************************************/
2040 /* Texture Cube Map Sampling Functions */
2041 /**********************************************************************/
2044 * Choose one of six sides of a texture cube map given the texture
2045 * coord (rx,ry,rz). Return pointer to corresponding array of texture
2048 static const struct gl_texture_image
**
2049 choose_cube_face(const struct gl_texture_object
*texObj
,
2050 const GLfloat texcoord
[4], GLfloat newCoord
[4])
2054 direction target sc tc ma
2055 ---------- ------------------------------- --- --- ---
2056 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
2057 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
2058 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
2059 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
2060 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
2061 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
2063 const GLfloat rx
= texcoord
[0];
2064 const GLfloat ry
= texcoord
[1];
2065 const GLfloat rz
= texcoord
[2];
2066 const struct gl_texture_image
**imgArray
;
2067 const GLfloat arx
= ABSF(rx
), ary
= ABSF(ry
), arz
= ABSF(rz
);
2070 if (arx
> ary
&& arx
> arz
) {
2072 imgArray
= (const struct gl_texture_image
**) texObj
->Image
;
2078 imgArray
= (const struct gl_texture_image
**) texObj
->NegX
;
2084 else if (ary
> arx
&& ary
> arz
) {
2086 imgArray
= (const struct gl_texture_image
**) texObj
->PosY
;
2092 imgArray
= (const struct gl_texture_image
**) texObj
->NegY
;
2100 imgArray
= (const struct gl_texture_image
**) texObj
->PosZ
;
2106 imgArray
= (const struct gl_texture_image
**) texObj
->NegZ
;
2113 newCoord
[0] = ( sc
/ ma
+ 1.0F
) * 0.5F
;
2114 newCoord
[1] = ( tc
/ ma
+ 1.0F
) * 0.5F
;
2120 sample_nearest_cube(GLcontext
*ctx
, GLuint texUnit
,
2121 const struct gl_texture_object
*tObj
, GLuint n
,
2122 GLfloat texcoords
[][4], const GLfloat lambda
[],
2127 for (i
= 0; i
< n
; i
++) {
2128 const struct gl_texture_image
**images
;
2129 GLfloat newCoord
[4];
2130 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
2131 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
2138 sample_linear_cube(GLcontext
*ctx
, GLuint texUnit
,
2139 const struct gl_texture_object
*tObj
, GLuint n
,
2140 GLfloat texcoords
[][4],
2141 const GLfloat lambda
[], GLchan rgba
[][4])
2145 for (i
= 0; i
< n
; i
++) {
2146 const struct gl_texture_image
**images
;
2147 GLfloat newCoord
[4];
2148 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
2149 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
2156 sample_cube_nearest_mipmap_nearest(GLcontext
*ctx
, GLuint texUnit
,
2157 const struct gl_texture_object
*tObj
,
2158 GLuint n
, GLfloat texcoord
[][4],
2159 const GLfloat lambda
[], GLchan rgba
[][4])
2162 ASSERT(lambda
!= NULL
);
2163 for (i
= 0; i
< n
; i
++) {
2164 const struct gl_texture_image
**images
;
2165 GLfloat newCoord
[4];
2167 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2168 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2169 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
2175 sample_cube_linear_mipmap_nearest(GLcontext
*ctx
, GLuint texUnit
,
2176 const struct gl_texture_object
*tObj
,
2177 GLuint n
, GLfloat texcoord
[][4],
2178 const GLfloat lambda
[], GLchan rgba
[][4])
2181 ASSERT(lambda
!= NULL
);
2182 for (i
= 0; i
< n
; i
++) {
2183 const struct gl_texture_image
**images
;
2184 GLfloat newCoord
[4];
2186 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2187 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2188 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
2194 sample_cube_nearest_mipmap_linear(GLcontext
*ctx
, GLuint texUnit
,
2195 const struct gl_texture_object
*tObj
,
2196 GLuint n
, GLfloat texcoord
[][4],
2197 const GLfloat lambda
[], GLchan rgba
[][4])
2200 ASSERT(lambda
!= NULL
);
2201 for (i
= 0; i
< n
; i
++) {
2202 const struct gl_texture_image
**images
;
2203 GLfloat newCoord
[4];
2205 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2206 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2207 if (level
>= tObj
->_MaxLevel
) {
2208 sample_2d_nearest(ctx
, tObj
, images
[tObj
->_MaxLevel
],
2212 GLchan t0
[4], t1
[4]; /* texels */
2213 const GLfloat f
= FRAC(lambda
[i
]);
2214 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, t0
);
2215 sample_2d_nearest(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
2216 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
2217 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
2218 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
2219 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
2226 sample_cube_linear_mipmap_linear(GLcontext
*ctx
, GLuint texUnit
,
2227 const struct gl_texture_object
*tObj
,
2228 GLuint n
, GLfloat texcoord
[][4],
2229 const GLfloat lambda
[], GLchan rgba
[][4])
2232 ASSERT(lambda
!= NULL
);
2233 for (i
= 0; i
< n
; i
++) {
2234 const struct gl_texture_image
**images
;
2235 GLfloat newCoord
[4];
2237 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2238 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2239 if (level
>= tObj
->_MaxLevel
) {
2240 sample_2d_linear(ctx
, tObj
, images
[tObj
->_MaxLevel
],
2244 GLchan t0
[4], t1
[4];
2245 const GLfloat f
= FRAC(lambda
[i
]);
2246 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, t0
);
2247 sample_2d_linear(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
2248 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
2249 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
2250 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
2251 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
2258 sample_lambda_cube( GLcontext
*ctx
, GLuint texUnit
,
2259 const struct gl_texture_object
*tObj
, GLuint n
,
2260 GLfloat texcoords
[][4], const GLfloat lambda
[],
2263 GLuint minStart
, minEnd
; /* texels with minification */
2264 GLuint magStart
, magEnd
; /* texels with magnification */
2266 ASSERT(lambda
!= NULL
);
2267 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2268 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2270 if (minStart
< minEnd
) {
2271 /* do the minified texels */
2272 const GLuint m
= minEnd
- minStart
;
2273 switch (tObj
->MinFilter
) {
2275 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2276 lambda
+ minStart
, rgba
+ minStart
);
2279 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2280 lambda
+ minStart
, rgba
+ minStart
);
2282 case GL_NEAREST_MIPMAP_NEAREST
:
2283 sample_cube_nearest_mipmap_nearest(ctx
, texUnit
, tObj
, m
,
2284 texcoords
+ minStart
,
2285 lambda
+ minStart
, rgba
+ minStart
);
2287 case GL_LINEAR_MIPMAP_NEAREST
:
2288 sample_cube_linear_mipmap_nearest(ctx
, texUnit
, tObj
, m
,
2289 texcoords
+ minStart
,
2290 lambda
+ minStart
, rgba
+ minStart
);
2292 case GL_NEAREST_MIPMAP_LINEAR
:
2293 sample_cube_nearest_mipmap_linear(ctx
, texUnit
, tObj
, m
,
2294 texcoords
+ minStart
,
2295 lambda
+ minStart
, rgba
+ minStart
);
2297 case GL_LINEAR_MIPMAP_LINEAR
:
2298 sample_cube_linear_mipmap_linear(ctx
, texUnit
, tObj
, m
,
2299 texcoords
+ minStart
,
2300 lambda
+ minStart
, rgba
+ minStart
);
2303 _mesa_problem(ctx
, "Bad min filter in sample_lambda_cube");
2307 if (magStart
< magEnd
) {
2308 /* do the magnified texels */
2309 const GLuint m
= magEnd
- magStart
;
2310 switch (tObj
->MagFilter
) {
2312 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2313 lambda
+ magStart
, rgba
+ magStart
);
2316 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2317 lambda
+ magStart
, rgba
+ magStart
);
2320 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_cube");
2326 /**********************************************************************/
2327 /* Texture Rectangle Sampling Functions */
2328 /**********************************************************************/
2331 sample_nearest_rect(GLcontext
*ctx
, GLuint texUnit
,
2332 const struct gl_texture_object
*tObj
, GLuint n
,
2333 GLfloat texcoords
[][4], const GLfloat lambda
[],
2336 const struct gl_texture_image
*img
= tObj
->Image
[0];
2337 const GLfloat width
= (GLfloat
) img
->Width
;
2338 const GLfloat height
= (GLfloat
) img
->Height
;
2339 const GLint width_minus_1
= img
->Width
- 1;
2340 const GLint height_minus_1
= img
->Height
- 1;
2346 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2347 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2348 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2349 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2350 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2351 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2352 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2354 /* XXX move Wrap mode tests outside of loops for common cases */
2355 for (i
= 0; i
< n
; i
++) {
2357 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2358 if (tObj
->WrapS
== GL_CLAMP
) {
2359 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.0F
, width
) );
2361 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2362 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
) );
2365 col
= IFLOOR( CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
) );
2367 if (tObj
->WrapT
== GL_CLAMP
) {
2368 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.0F
, height
) );
2370 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2371 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
) );
2374 row
= IFLOOR( CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
) );
2377 col
= CLAMP(col
, 0, width_minus_1
);
2378 row
= CLAMP(row
, 0, height_minus_1
);
2380 (*img
->FetchTexel
)(img
, col
, row
, 0, (GLvoid
*) rgba
[i
]);
2386 sample_linear_rect(GLcontext
*ctx
, GLuint texUnit
,
2387 const struct gl_texture_object
*tObj
, GLuint n
,
2388 GLfloat texcoords
[][4],
2389 const GLfloat lambda
[], GLchan rgba
[][4])
2391 const struct gl_texture_image
*img
= tObj
->Image
[0];
2392 const GLfloat width
= (GLfloat
) img
->Width
;
2393 const GLfloat height
= (GLfloat
) img
->Height
;
2394 const GLint width_minus_1
= img
->Width
- 1;
2395 const GLint height_minus_1
= img
->Height
- 1;
2401 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2402 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2403 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2404 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2405 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2406 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2407 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2409 /* XXX lots of opportunity for optimization in this loop */
2410 for (i
= 0; i
< n
; i
++) {
2412 GLint row0
, col0
, row1
, col1
;
2413 GLchan t00
[4], t01
[4], t10
[4], t11
[4];
2414 GLfloat a
, b
, w00
, w01
, w10
, w11
;
2416 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2417 if (tObj
->WrapS
== GL_CLAMP
) {
2418 fcol
= CLAMP(texcoords
[i
][0], 0.0F
, width
);
2420 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2421 fcol
= CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
);
2424 fcol
= CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
);
2426 if (tObj
->WrapT
== GL_CLAMP
) {
2427 frow
= CLAMP(texcoords
[i
][1], 0.0F
, height
);
2429 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2430 frow
= CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
);
2433 frow
= CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
);
2436 /* compute integer rows/columns */
2437 col0
= IFLOOR(fcol
);
2439 col0
= CLAMP(col0
, 0, width_minus_1
);
2440 col1
= CLAMP(col1
, 0, width_minus_1
);
2441 row0
= IFLOOR(frow
);
2443 row0
= CLAMP(row0
, 0, height_minus_1
);
2444 row1
= CLAMP(row1
, 0, height_minus_1
);
2446 /* get four texel samples */
2447 (*img
->FetchTexel
)(img
, col0
, row0
, 0, (GLvoid
*) t00
);
2448 (*img
->FetchTexel
)(img
, col1
, row0
, 0, (GLvoid
*) t10
);
2449 (*img
->FetchTexel
)(img
, col0
, row1
, 0, (GLvoid
*) t01
);
2450 (*img
->FetchTexel
)(img
, col1
, row1
, 0, (GLvoid
*) t11
);
2452 /* compute sample weights */
2455 w00
= (1.0F
-a
) * (1.0F
-b
);
2457 w01
= (1.0F
-a
) * b
;
2460 /* compute weighted average of samples */
2462 (GLchan
) (w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0]);
2464 (GLchan
) (w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1]);
2466 (GLchan
) (w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2]);
2468 (GLchan
) (w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3]);
2474 sample_lambda_rect( GLcontext
*ctx
, GLuint texUnit
,
2475 const struct gl_texture_object
*tObj
, GLuint n
,
2476 GLfloat texcoords
[][4], const GLfloat lambda
[],
2479 GLuint minStart
, minEnd
, magStart
, magEnd
;
2481 /* We only need lambda to decide between minification and magnification.
2482 * There is no mipmapping with rectangular textures.
2484 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2485 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2487 if (minStart
< minEnd
) {
2488 if (tObj
->MinFilter
== GL_NEAREST
) {
2489 sample_nearest_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2490 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2493 sample_linear_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2494 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2497 if (magStart
< magEnd
) {
2498 if (tObj
->MagFilter
== GL_NEAREST
) {
2499 sample_nearest_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2500 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2503 sample_linear_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2504 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2512 * Sample a shadow/depth texture.
2515 sample_depth_texture( GLcontext
*ctx
, GLuint unit
,
2516 const struct gl_texture_object
*tObj
, GLuint n
,
2517 GLfloat texcoords
[][4], const GLfloat lambda
[],
2520 const GLint baseLevel
= tObj
->BaseLevel
;
2521 const struct gl_texture_image
*texImage
= tObj
->Image
[baseLevel
];
2522 const GLuint width
= texImage
->Width
;
2523 const GLuint height
= texImage
->Height
;
2530 ASSERT(tObj
->Image
[tObj
->BaseLevel
]->Format
== GL_DEPTH_COMPONENT
);
2531 ASSERT(tObj
->Target
== GL_TEXTURE_1D
||
2532 tObj
->Target
== GL_TEXTURE_2D
||
2533 tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
2535 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2537 /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
2539 /* XXX this could be precomputed and saved in the texture object */
2540 if (tObj
->CompareFlag
) {
2541 /* GL_SGIX_shadow */
2542 if (tObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2543 function
= GL_LEQUAL
;
2546 ASSERT(tObj
->CompareOperator
== GL_TEXTURE_GEQUAL_R_SGIX
);
2547 function
= GL_GEQUAL
;
2550 else if (tObj
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
) {
2552 function
= tObj
->CompareFunc
;
2555 function
= GL_NONE
; /* pass depth through as grayscale */
2558 if (tObj
->MagFilter
== GL_NEAREST
) {
2560 for (i
= 0; i
< n
; i
++) {
2561 GLfloat depthSample
;
2563 /* XXX fix for texture rectangle! */
2564 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoords
[i
][0], width
, col
);
2565 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoords
[i
][1], height
, row
);
2566 depthSample
= *((const GLfloat
*) texImage
->Data
+ row
* width
+ col
);
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
;
2582 result
= (texcoords
[i
][2] == depthSample
) ? CHAN_MAX
: ambient
;
2585 result
= (texcoords
[i
][2] != depthSample
) ? CHAN_MAX
: ambient
;
2594 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2597 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2601 switch (tObj
->DepthMode
) {
2603 texel
[i
][RCOMP
] = result
;
2604 texel
[i
][GCOMP
] = result
;
2605 texel
[i
][BCOMP
] = result
;
2606 texel
[i
][ACOMP
] = CHAN_MAX
;
2609 texel
[i
][RCOMP
] = result
;
2610 texel
[i
][GCOMP
] = result
;
2611 texel
[i
][BCOMP
] = result
;
2612 texel
[i
][ACOMP
] = result
;
2615 texel
[i
][RCOMP
] = 0;
2616 texel
[i
][GCOMP
] = 0;
2617 texel
[i
][BCOMP
] = 0;
2618 texel
[i
][ACOMP
] = result
;
2621 _mesa_problem(ctx
, "Bad depth texture mode");
2627 ASSERT(tObj
->MagFilter
== GL_LINEAR
);
2628 for (i
= 0; i
< n
; i
++) {
2629 GLfloat depth00
, depth01
, depth10
, depth11
;
2630 GLint i0
, i1
, j0
, j1
;
2632 GLuint useBorderTexel
;
2634 /* XXX fix for texture rectangle! */
2635 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoords
[i
][0], u
, width
, i0
, i1
);
2636 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoords
[i
][1], v
, height
,j0
, j1
);
2639 if (texImage
->Border
) {
2640 i0
+= texImage
->Border
;
2641 i1
+= texImage
->Border
;
2642 j0
+= texImage
->Border
;
2643 j1
+= texImage
->Border
;
2646 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
2647 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
2648 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
2649 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
2652 /* get four depth samples from the texture */
2653 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
2657 depth00
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i0
);
2659 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
2663 depth10
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i1
);
2665 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
2669 depth01
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i0
);
2671 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
2675 depth11
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i1
);
2679 /* compute a single weighted depth sample and do one comparison */
2680 const GLfloat a
= FRAC(u
+ 1.0F
);
2681 const GLfloat b
= FRAC(v
+ 1.0F
);
2682 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2683 const GLfloat w10
= ( a
) * (1.0F
- b
);
2684 const GLfloat w01
= (1.0F
- a
) * ( b
);
2685 const GLfloat w11
= ( a
) * ( b
);
2686 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2687 + w01
* depth01
+ w11
* depth11
;
2688 if ((depthSample
<= texcoords
[i
][2] && function
== GL_LEQUAL
) ||
2689 (depthSample
>= texcoords
[i
][2] && function
== GL_GEQUAL
)) {
2697 /* Do four depth/R comparisons and compute a weighted result.
2698 * If this touches on somebody's I.P., I'll remove this code
2701 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
2702 GLfloat luminance
= CHAN_MAXF
;
2706 if (depth00
<= texcoords
[i
][2]) luminance
-= d
;
2707 if (depth01
<= texcoords
[i
][2]) luminance
-= d
;
2708 if (depth10
<= texcoords
[i
][2]) luminance
-= d
;
2709 if (depth11
<= texcoords
[i
][2]) luminance
-= d
;
2710 result
= (GLchan
) luminance
;
2713 if (depth00
>= texcoords
[i
][2]) luminance
-= d
;
2714 if (depth01
>= texcoords
[i
][2]) luminance
-= d
;
2715 if (depth10
>= texcoords
[i
][2]) luminance
-= d
;
2716 if (depth11
>= texcoords
[i
][2]) luminance
-= d
;
2717 result
= (GLchan
) luminance
;
2720 if (depth00
< texcoords
[i
][2]) luminance
-= d
;
2721 if (depth01
< texcoords
[i
][2]) luminance
-= d
;
2722 if (depth10
< texcoords
[i
][2]) luminance
-= d
;
2723 if (depth11
< texcoords
[i
][2]) luminance
-= d
;
2724 result
= (GLchan
) luminance
;
2727 if (depth00
> texcoords
[i
][2]) luminance
-= d
;
2728 if (depth01
> texcoords
[i
][2]) luminance
-= d
;
2729 if (depth10
> texcoords
[i
][2]) luminance
-= d
;
2730 if (depth11
> texcoords
[i
][2]) luminance
-= d
;
2731 result
= (GLchan
) luminance
;
2734 if (depth00
== texcoords
[i
][2]) luminance
-= d
;
2735 if (depth01
== texcoords
[i
][2]) luminance
-= d
;
2736 if (depth10
== texcoords
[i
][2]) luminance
-= d
;
2737 if (depth11
== texcoords
[i
][2]) luminance
-= d
;
2738 result
= (GLchan
) luminance
;
2741 if (depth00
!= texcoords
[i
][2]) luminance
-= d
;
2742 if (depth01
!= texcoords
[i
][2]) luminance
-= d
;
2743 if (depth10
!= texcoords
[i
][2]) luminance
-= d
;
2744 if (depth11
!= texcoords
[i
][2]) luminance
-= d
;
2745 result
= (GLchan
) luminance
;
2754 /* ordinary bilinear filtering */
2756 const GLfloat a
= FRAC(u
+ 1.0F
);
2757 const GLfloat b
= FRAC(v
+ 1.0F
);
2758 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2759 const GLfloat w10
= ( a
) * (1.0F
- b
);
2760 const GLfloat w01
= (1.0F
- a
) * ( b
);
2761 const GLfloat w11
= ( a
) * ( b
);
2762 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2763 + w01
* depth01
+ w11
* depth11
;
2764 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2768 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2773 switch (tObj
->DepthMode
) {
2775 texel
[i
][RCOMP
] = result
;
2776 texel
[i
][GCOMP
] = result
;
2777 texel
[i
][BCOMP
] = result
;
2778 texel
[i
][ACOMP
] = CHAN_MAX
;
2781 texel
[i
][RCOMP
] = result
;
2782 texel
[i
][GCOMP
] = result
;
2783 texel
[i
][BCOMP
] = result
;
2784 texel
[i
][ACOMP
] = result
;
2787 texel
[i
][RCOMP
] = 0;
2788 texel
[i
][GCOMP
] = 0;
2789 texel
[i
][BCOMP
] = 0;
2790 texel
[i
][ACOMP
] = result
;
2793 _mesa_problem(ctx
, "Bad depth texture mode");
2802 * Experimental depth texture sampling function.
2805 sample_depth_texture2(const GLcontext
*ctx
,
2806 const struct gl_texture_unit
*texUnit
,
2807 GLuint n
, GLfloat texcoords
[][4],
2810 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2811 const GLint baseLevel
= texObj
->BaseLevel
;
2812 const struct gl_texture_image
*texImage
= texObj
->Image
[baseLevel
];
2813 const GLuint width
= texImage
->Width
;
2814 const GLuint height
= texImage
->Height
;
2816 GLboolean lequal
, gequal
;
2818 if (texObj
->Target
!= GL_TEXTURE_2D
) {
2819 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2823 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2824 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2828 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2829 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2830 * isn't a depth texture.
2832 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2833 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2837 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2839 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2850 for (i
= 0; i
< n
; i
++) {
2852 GLint col
, row
, ii
, jj
, imin
, imax
, jmin
, jmax
, samples
, count
;
2855 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, texcoords
[i
][0],
2857 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, texcoords
[i
][1],
2865 if (imin
< 0) imin
= 0;
2866 if (imax
>= width
) imax
= width
- 1;
2867 if (jmin
< 0) jmin
= 0;
2868 if (jmax
>= height
) jmax
= height
- 1;
2870 samples
= (imax
- imin
+ 1) * (jmax
- jmin
+ 1);
2872 for (jj
= jmin
; jj
<= jmax
; jj
++) {
2873 for (ii
= imin
; ii
<= imax
; ii
++) {
2874 GLfloat depthSample
= *((const GLfloat
*) texImage
->Data
2876 if ((depthSample
<= r
[i
] && lequal
) ||
2877 (depthSample
>= r
[i
] && gequal
)) {
2883 w
= (GLfloat
) count
/ (GLfloat
) samples
;
2884 w
= CHAN_MAXF
- w
* (CHAN_MAXF
- (GLfloat
) ambient
);
2887 texel
[i
][RCOMP
] = lum
;
2888 texel
[i
][GCOMP
] = lum
;
2889 texel
[i
][BCOMP
] = lum
;
2890 texel
[i
][ACOMP
] = CHAN_MAX
;
2898 * We use this function when a texture object is in an "incomplete" state.
2901 null_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2902 const struct gl_texture_object
*tObj
, GLuint n
,
2903 GLfloat texcoords
[][4], const GLfloat lambda
[],
2911 * Setup the texture sampling function for this texture object.
2914 _swrast_choose_texture_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2915 const struct gl_texture_object
*t
)
2917 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
2920 swrast
->TextureSample
[texUnit
] = null_sample_func
;
2923 const GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
2924 const GLenum format
= t
->Image
[t
->BaseLevel
]->Format
;
2927 /* Compute min/mag filter threshold */
2928 if (t
->MagFilter
== GL_LINEAR
2929 && (t
->MinFilter
== GL_NEAREST_MIPMAP_NEAREST
||
2930 t
->MinFilter
== GL_NEAREST_MIPMAP_LINEAR
)) {
2931 swrast
->_MinMagThresh
[texUnit
] = 0.5F
;
2934 swrast
->_MinMagThresh
[texUnit
] = 0.0F
;
2938 switch (t
->Target
) {
2940 if (format
== GL_DEPTH_COMPONENT
) {
2941 swrast
->TextureSample
[texUnit
] = sample_depth_texture
;
2943 else if (needLambda
) {
2944 swrast
->TextureSample
[texUnit
] = sample_lambda_1d
;
2946 else if (t
->MinFilter
== GL_LINEAR
) {
2947 swrast
->TextureSample
[texUnit
] = sample_linear_1d
;
2950 ASSERT(t
->MinFilter
== GL_NEAREST
);
2951 swrast
->TextureSample
[texUnit
] = sample_nearest_1d
;
2955 if (format
== GL_DEPTH_COMPONENT
) {
2956 swrast
->TextureSample
[texUnit
] = sample_depth_texture
;
2958 else if (needLambda
) {
2959 swrast
->TextureSample
[texUnit
] = sample_lambda_2d
;
2961 else if (t
->MinFilter
== GL_LINEAR
) {
2962 swrast
->TextureSample
[texUnit
] = sample_linear_2d
;
2965 GLint baseLevel
= t
->BaseLevel
;
2966 ASSERT(t
->MinFilter
== GL_NEAREST
);
2967 if (t
->WrapS
== GL_REPEAT
&&
2968 t
->WrapT
== GL_REPEAT
&&
2969 t
->Image
[baseLevel
]->Border
== 0 &&
2970 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGB
) {
2971 swrast
->TextureSample
[texUnit
] = opt_sample_rgb_2d
;
2973 else if (t
->WrapS
== GL_REPEAT
&&
2974 t
->WrapT
== GL_REPEAT
&&
2975 t
->Image
[baseLevel
]->Border
== 0 &&
2976 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGBA
) {
2977 swrast
->TextureSample
[texUnit
] = opt_sample_rgba_2d
;
2980 swrast
->TextureSample
[texUnit
] = sample_nearest_2d
;
2985 swrast
->TextureSample
[texUnit
] = sample_lambda_3d
;
2987 else if (t
->MinFilter
== GL_LINEAR
) {
2988 swrast
->TextureSample
[texUnit
] = sample_linear_3d
;
2991 ASSERT(t
->MinFilter
== GL_NEAREST
);
2992 swrast
->TextureSample
[texUnit
] = sample_nearest_3d
;
2995 case GL_TEXTURE_CUBE_MAP
:
2997 swrast
->TextureSample
[texUnit
] = sample_lambda_cube
;
2999 else if (t
->MinFilter
== GL_LINEAR
) {
3000 swrast
->TextureSample
[texUnit
] = sample_linear_cube
;
3003 ASSERT(t
->MinFilter
== GL_NEAREST
);
3004 swrast
->TextureSample
[texUnit
] = sample_nearest_cube
;
3007 case GL_TEXTURE_RECTANGLE_NV
:
3009 swrast
->TextureSample
[texUnit
] = sample_lambda_rect
;
3011 else if (t
->MinFilter
== GL_LINEAR
) {
3012 swrast
->TextureSample
[texUnit
] = sample_linear_rect
;
3015 ASSERT(t
->MinFilter
== GL_NEAREST
);
3016 swrast
->TextureSample
[texUnit
] = sample_nearest_rect
;
3020 _mesa_problem(ctx
, "invalid target in _swrast_choose_texture_sample_func");
3026 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
3027 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
3031 * Do texture application for GL_ARB/EXT_texture_env_combine.
3032 * This function also supports GL_{EXT,ARB}_texture_env_dot3 and
3033 * GL_ATI_texture_env_combine3
3035 * \param ctx rendering context
3036 * \param textureUnit the texture unit to apply
3037 * \param n number of fragments to process (span width)
3038 * \param primary_rgba incoming fragment color array
3039 * \param texelBuffer pointer to texel colors for all texture units
3041 * \param rgba incoming colors, which get modified here
3044 texture_combine( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
3045 CONST
GLchan (*primary_rgba
)[4],
3046 CONST GLchan
*texelBuffer
,
3049 const struct gl_texture_unit
*textureUnit
= &(ctx
->Texture
.Unit
[unit
]);
3050 const GLchan (*argRGB
[3])[4];
3051 const GLchan (*argA
[3])[4];
3052 const GLuint RGBshift
= textureUnit
->CombineScaleShiftRGB
;
3053 const GLuint Ashift
= textureUnit
->CombineScaleShiftA
;
3054 #if CHAN_TYPE == GL_FLOAT
3055 const GLchan RGBmult
= (GLfloat
) (1 << RGBshift
);
3056 const GLchan Amult
= (GLfloat
) (1 << Ashift
);
3057 static const GLchan one
[4] = { 1.0, 1.0, 1.0, 1.0 };
3058 static const GLchan zero
[4] = { 0.0, 0.0, 0.0, 0.0 };
3060 const GLint half
= (CHAN_MAX
+ 1) / 2;
3061 static const GLchan one
[4] = { CHAN_MAX
, CHAN_MAX
, CHAN_MAX
, CHAN_MAX
};
3062 static const GLchan zero
[4] = { 0, 0, 0, 0 };
3065 GLuint numColorArgs
;
3066 GLuint numAlphaArgs
;
3068 /* GLchan ccolor[3][4]; */
3069 DEFMNARRAY(GLchan
, ccolor
, 3, 3 * MAX_WIDTH
, 4); /* mac 32k limitation */
3070 CHECKARRAY(ccolor
, return); /* mac 32k limitation */
3072 ASSERT(ctx
->Extensions
.EXT_texture_env_combine
||
3073 ctx
->Extensions
.ARB_texture_env_combine
);
3074 ASSERT(SWRAST_CONTEXT(ctx
)->_AnyTextureCombine
);
3078 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
3079 textureUnit->CombineModeRGB,
3080 textureUnit->CombineModeA,
3081 textureUnit->CombineSourceRGB[0],
3082 textureUnit->CombineSourceA[0],
3083 textureUnit->CombineSourceRGB[1],
3084 textureUnit->CombineSourceA[1]);
3088 * Do operand setup for up to 3 operands. Loop over the terms.
3090 switch (textureUnit
->CombineModeRGB
) {
3100 case GL_DOT3_RGB_EXT
:
3101 case GL_DOT3_RGBA_EXT
:
3104 case GL_INTERPOLATE
:
3105 case GL_MODULATE_ADD_ATI
:
3106 case GL_MODULATE_SIGNED_ADD_ATI
:
3107 case GL_MODULATE_SUBTRACT_ATI
:
3116 switch (textureUnit
->CombineModeA
) {
3126 case GL_INTERPOLATE
:
3127 case GL_MODULATE_ADD_ATI
:
3128 case GL_MODULATE_SIGNED_ADD_ATI
:
3129 case GL_MODULATE_SUBTRACT_ATI
:
3138 for (j
= 0; j
< numColorArgs
; j
++) {
3139 const GLenum srcRGB
= textureUnit
->CombineSourceRGB
[j
];
3144 argRGB
[j
] = (const GLchan (*)[4])
3145 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
3147 case GL_PRIMARY_COLOR
:
3148 argRGB
[j
] = primary_rgba
;
3151 argRGB
[j
] = (const GLchan (*)[4]) rgba
;
3155 GLchan (*c
)[4] = ccolor
[j
];
3156 GLchan red
, green
, blue
, alpha
;
3157 UNCLAMPED_FLOAT_TO_CHAN(red
, textureUnit
->EnvColor
[0]);
3158 UNCLAMPED_FLOAT_TO_CHAN(green
, textureUnit
->EnvColor
[1]);
3159 UNCLAMPED_FLOAT_TO_CHAN(blue
, textureUnit
->EnvColor
[2]);
3160 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
3161 for (i
= 0; i
< n
; i
++) {
3163 c
[i
][GCOMP
] = green
;
3165 c
[i
][ACOMP
] = alpha
;
3167 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3170 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
3179 /* ARB_texture_env_crossbar source */
3181 const GLuint srcUnit
= srcRGB
- GL_TEXTURE0
;
3182 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
3183 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
3185 argRGB
[j
] = (const GLchan (*)[4])
3186 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
3190 if (textureUnit
->CombineOperandRGB
[j
] != GL_SRC_COLOR
) {
3191 const GLchan (*src
)[4] = argRGB
[j
];
3192 GLchan (*dst
)[4] = ccolor
[j
];
3194 /* point to new arg[j] storage */
3195 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3197 if (textureUnit
->CombineOperandRGB
[j
] == GL_ONE_MINUS_SRC_COLOR
) {
3198 for (i
= 0; i
< n
; i
++) {
3199 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][RCOMP
];
3200 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][GCOMP
];
3201 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][BCOMP
];
3204 else if (textureUnit
->CombineOperandRGB
[j
] == GL_SRC_ALPHA
) {
3205 for (i
= 0; i
< n
; i
++) {
3206 dst
[i
][RCOMP
] = src
[i
][ACOMP
];
3207 dst
[i
][GCOMP
] = src
[i
][ACOMP
];
3208 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
3212 ASSERT(textureUnit
->CombineOperandRGB
[j
] ==GL_ONE_MINUS_SRC_ALPHA
);
3213 for (i
= 0; i
< n
; i
++) {
3214 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3215 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3216 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3223 for (j
= 0; j
< numAlphaArgs
; j
++) {
3224 const GLenum srcA
= textureUnit
->CombineSourceA
[j
];
3228 argA
[j
] = (const GLchan (*)[4])
3229 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
3231 case GL_PRIMARY_COLOR
:
3232 argA
[j
] = primary_rgba
;
3235 argA
[j
] = (const GLchan (*)[4]) rgba
;
3239 GLchan alpha
, (*c
)[4] = ccolor
[j
];
3240 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
3241 for (i
= 0; i
< n
; i
++)
3242 c
[i
][ACOMP
] = alpha
;
3243 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3246 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
3255 /* ARB_texture_env_crossbar source */
3257 const GLuint srcUnit
= srcA
- GL_TEXTURE0
;
3258 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
3259 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
3261 argA
[j
] = (const GLchan (*)[4])
3262 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
3266 if (textureUnit
->CombineOperandA
[j
] == GL_ONE_MINUS_SRC_ALPHA
) {
3267 const GLchan (*src
)[4] = argA
[j
];
3268 GLchan (*dst
)[4] = ccolor
[j
];
3269 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3270 for (i
= 0; i
< n
; i
++) {
3271 dst
[i
][ACOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3277 * Do the texture combine.
3279 switch (textureUnit
->CombineModeRGB
) {
3282 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3284 for (i
= 0; i
< n
; i
++) {
3285 #if CHAN_TYPE == GL_FLOAT
3286 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * RGBmult
;
3287 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * RGBmult
;
3288 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * RGBmult
;
3290 GLuint r
= (GLuint
) arg0
[i
][RCOMP
] << RGBshift
;
3291 GLuint g
= (GLuint
) arg0
[i
][GCOMP
] << RGBshift
;
3292 GLuint b
= (GLuint
) arg0
[i
][BCOMP
] << RGBshift
;
3293 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3294 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3295 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3300 for (i
= 0; i
< n
; i
++) {
3301 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
];
3302 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
];
3303 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
];
3310 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3311 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3312 #if CHAN_TYPE != GL_FLOAT
3313 const GLint shift
= CHAN_BITS
- RGBshift
;
3315 for (i
= 0; i
< n
; i
++) {
3316 #if CHAN_TYPE == GL_FLOAT
3317 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * RGBmult
;
3318 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * RGBmult
;
3319 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * RGBmult
;
3321 GLuint r
= PROD(arg0
[i
][RCOMP
], arg1
[i
][RCOMP
]) >> shift
;
3322 GLuint g
= PROD(arg0
[i
][GCOMP
], arg1
[i
][GCOMP
]) >> shift
;
3323 GLuint b
= PROD(arg0
[i
][BCOMP
], arg1
[i
][BCOMP
]) >> shift
;
3324 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3325 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3326 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3333 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3334 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3335 for (i
= 0; i
< n
; i
++) {
3336 #if CHAN_TYPE == GL_FLOAT
3337 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * RGBmult
;
3338 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * RGBmult
;
3339 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * RGBmult
;
3341 GLint r
= ((GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3342 GLint g
= ((GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3343 GLint b
= ((GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3344 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3345 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3346 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3353 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3354 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3355 for (i
= 0; i
< n
; i
++) {
3356 #if CHAN_TYPE == GL_FLOAT
3357 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3358 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3359 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3361 GLint r
= (GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
] -half
;
3362 GLint g
= (GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
] -half
;
3363 GLint b
= (GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
] -half
;
3364 r
= (r
< 0) ? 0 : r
<< RGBshift
;
3365 g
= (g
< 0) ? 0 : g
<< RGBshift
;
3366 b
= (b
< 0) ? 0 : b
<< RGBshift
;
3367 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3368 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3369 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3374 case GL_INTERPOLATE
:
3376 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3377 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3378 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3379 #if CHAN_TYPE != GL_FLOAT
3380 const GLint shift
= CHAN_BITS
- RGBshift
;
3382 for (i
= 0; i
< n
; i
++) {
3383 #if CHAN_TYPE == GL_FLOAT
3384 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
3385 arg1
[i
][RCOMP
] * (CHAN_MAXF
- arg2
[i
][RCOMP
])) * RGBmult
;
3386 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
3387 arg1
[i
][GCOMP
] * (CHAN_MAXF
- arg2
[i
][GCOMP
])) * RGBmult
;
3388 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
3389 arg1
[i
][BCOMP
] * (CHAN_MAXF
- arg2
[i
][BCOMP
])) * RGBmult
;
3391 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3392 + PROD(arg1
[i
][RCOMP
], CHAN_MAX
- arg2
[i
][RCOMP
]))
3394 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3395 + PROD(arg1
[i
][GCOMP
], CHAN_MAX
- arg2
[i
][GCOMP
]))
3397 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3398 + PROD(arg1
[i
][BCOMP
], CHAN_MAX
- arg2
[i
][BCOMP
]))
3400 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3401 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3402 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3409 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3410 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3411 for (i
= 0; i
< n
; i
++) {
3412 #if CHAN_TYPE == GL_FLOAT
3413 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * RGBmult
;
3414 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * RGBmult
;
3415 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * RGBmult
;
3417 GLint r
= ((GLint
) arg0
[i
][RCOMP
] - (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3418 GLint g
= ((GLint
) arg0
[i
][GCOMP
] - (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3419 GLint b
= ((GLint
) arg0
[i
][BCOMP
] - (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3420 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3421 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3422 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3427 case GL_DOT3_RGB_EXT
:
3428 case GL_DOT3_RGBA_EXT
:
3430 /* Do not scale the result by 1 2 or 4 */
3431 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3432 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3433 for (i
= 0; i
< n
; i
++) {
3434 #if CHAN_TYPE == GL_FLOAT
3435 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3436 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3437 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3439 dot
= CLAMP(dot
, 0.0F
, CHAN_MAXF
);
3441 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3442 (GLint
)arg1
[i
][RCOMP
] - half
) +
3443 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3444 (GLint
)arg1
[i
][GCOMP
] - half
) +
3445 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3446 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3447 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3449 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3456 /* DO scale the result by 1 2 or 4 */
3457 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3458 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3459 for (i
= 0; i
< n
; i
++) {
3460 #if CHAN_TYPE == GL_FLOAT
3461 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3462 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3463 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3465 dot
= CLAMP(dot
, 0.0, CHAN_MAXF
);
3467 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3468 (GLint
)arg1
[i
][RCOMP
] - half
) +
3469 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3470 (GLint
)arg1
[i
][GCOMP
] - half
) +
3471 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3472 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3474 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3476 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3480 case GL_MODULATE_ADD_ATI
:
3482 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3483 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3484 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3485 #if CHAN_TYPE != GL_FLOAT
3486 const GLint shift
= CHAN_BITS
- RGBshift
;
3488 for (i
= 0; i
< n
; i
++) {
3489 #if CHAN_TYPE == GL_FLOAT
3490 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) + arg1
[i
][RCOMP
]) * RGBmult
;
3491 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
]) * RGBmult
;
3492 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
]) * RGBmult
;
3494 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3495 + ((GLuint
) arg1
[i
][RCOMP
] << CHAN_BITS
)) >> shift
;
3496 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3497 + ((GLuint
) arg1
[i
][GCOMP
] << CHAN_BITS
)) >> shift
;
3498 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3499 + ((GLuint
) arg1
[i
][BCOMP
] << CHAN_BITS
)) >> shift
;
3500 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3501 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3502 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3507 case GL_MODULATE_SIGNED_ADD_ATI
:
3509 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3510 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3511 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3512 #if CHAN_TYPE != GL_FLOAT
3513 const GLint shift
= CHAN_BITS
- RGBshift
;
3515 for (i
= 0; i
< n
; i
++) {
3516 #if CHAN_TYPE == GL_FLOAT
3517 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3518 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3519 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3521 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3522 + (((GLint
) arg1
[i
][RCOMP
] - half
) << CHAN_BITS
))
3524 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3525 + (((GLint
) arg1
[i
][GCOMP
] - half
) << CHAN_BITS
))
3527 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3528 + (((GLint
) arg1
[i
][BCOMP
] - half
) << CHAN_BITS
))
3530 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3531 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3532 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3537 case GL_MODULATE_SUBTRACT_ATI
:
3539 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3540 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3541 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3542 #if CHAN_TYPE != GL_FLOAT
3543 const GLint shift
= CHAN_BITS
- RGBshift
;
3545 for (i
= 0; i
< n
; i
++) {
3546 #if CHAN_TYPE == GL_FLOAT
3547 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) - arg1
[i
][RCOMP
]) * RGBmult
;
3548 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) - arg1
[i
][GCOMP
]) * RGBmult
;
3549 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) - arg1
[i
][BCOMP
]) * RGBmult
;
3551 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3552 - ((GLint
) arg1
[i
][RCOMP
] << CHAN_BITS
))
3554 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3555 - ((GLint
) arg1
[i
][GCOMP
] << CHAN_BITS
))
3557 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3558 - ((GLint
) arg1
[i
][BCOMP
] << CHAN_BITS
))
3560 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3561 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3562 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3568 _mesa_problem(ctx
, "invalid combine mode");
3571 switch (textureUnit
->CombineModeA
) {
3574 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3576 for (i
= 0; i
< n
; i
++) {
3577 #if CHAN_TYPE == GL_FLOAT
3578 GLchan a
= arg0
[i
][ACOMP
] * Amult
;
3580 GLuint a
= (GLuint
) arg0
[i
][ACOMP
] << Ashift
;
3582 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3586 for (i
= 0; i
< n
; i
++) {
3587 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
];
3594 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3595 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3596 #if CHAN_TYPE != GL_FLOAT
3597 const GLint shift
= CHAN_BITS
- Ashift
;
3599 for (i
= 0; i
< n
; i
++) {
3600 #if CHAN_TYPE == GL_FLOAT
3601 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * Amult
;
3603 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg1
[i
][ACOMP
]) >> shift
);
3604 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3611 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3612 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3613 for (i
= 0; i
< n
; i
++) {
3614 #if CHAN_TYPE == GL_FLOAT
3615 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * Amult
;
3617 GLint a
= ((GLint
) arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) << Ashift
;
3618 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3625 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3626 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3627 for (i
= 0; i
< n
; i
++) {
3628 #if CHAN_TYPE == GL_FLOAT
3629 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3631 GLint a
= (GLint
) arg0
[i
][ACOMP
] + (GLint
) arg1
[i
][ACOMP
] -half
;
3632 a
= (a
< 0) ? 0 : a
<< Ashift
;
3633 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3638 case GL_INTERPOLATE
:
3640 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3641 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3642 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3643 #if CHAN_TYPE != GL_FLOAT
3644 const GLint shift
= CHAN_BITS
- Ashift
;
3646 for (i
=0; i
<n
; i
++) {
3647 #if CHAN_TYPE == GL_FLOAT
3648 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
3649 arg1
[i
][ACOMP
] * (CHAN_MAXF
- arg2
[i
][ACOMP
]))
3652 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3653 + PROD(arg1
[i
][ACOMP
], CHAN_MAX
- arg2
[i
][ACOMP
]))
3655 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3662 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3663 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3664 for (i
= 0; i
< n
; i
++) {
3665 #if CHAN_TYPE == GL_FLOAT
3666 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * Amult
;
3668 GLint a
= ((GLint
) arg0
[i
][ACOMP
] - (GLint
) arg1
[i
][ACOMP
]) << Ashift
;
3669 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3674 case GL_MODULATE_ADD_ATI
:
3676 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3677 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3678 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3679 #if CHAN_TYPE != GL_FLOAT
3680 const GLint shift
= CHAN_BITS
- Ashift
;
3682 for (i
= 0; i
< n
; i
++) {
3683 #if CHAN_TYPE == GL_FLOAT
3684 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
]) * Amult
;
3686 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3687 + ((GLuint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3689 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3694 case GL_MODULATE_SIGNED_ADD_ATI
:
3696 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3697 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3698 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3699 #if CHAN_TYPE != GL_FLOAT
3700 const GLint shift
= CHAN_BITS
- Ashift
;
3702 for (i
= 0; i
< n
; i
++) {
3703 #if CHAN_TYPE == GL_FLOAT
3704 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3706 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3707 + (((GLint
) arg1
[i
][ACOMP
] - half
) << CHAN_BITS
))
3709 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3714 case GL_MODULATE_SUBTRACT_ATI
:
3716 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3717 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3718 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3719 #if CHAN_TYPE != GL_FLOAT
3720 const GLint shift
= CHAN_BITS
- Ashift
;
3722 for (i
= 0; i
< n
; i
++) {
3723 #if CHAN_TYPE == GL_FLOAT
3724 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) - arg1
[i
][ACOMP
]) * Amult
;
3726 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3727 - ((GLint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3729 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3735 _mesa_problem(ctx
, "invalid combine mode");
3738 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
3739 * This is kind of a kludge. It would have been better if the spec
3740 * were written such that the GL_COMBINE_ALPHA value could be set to
3743 if (textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_EXT
||
3744 textureUnit
->CombineModeRGB
== GL_DOT3_RGBA
) {
3745 for (i
= 0; i
< n
; i
++) {
3746 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
3749 UNDEFARRAY(ccolor
); /* mac 32k limitation */
3755 * Implement NVIDIA's GL_NV_texture_env_combine4 extension when
3756 * texUnit->EnvMode == GL_COMBINE4_NV.
3759 texture_combine4( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
3760 CONST
GLchan (*primary_rgba
)[4],
3761 CONST GLchan
*texelBuffer
,
3769 * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND,
3770 * MODULATE, or DECAL) to an array of fragments.
3771 * Input: textureUnit - pointer to texture unit to apply
3772 * format - base internal texture format
3773 * n - number of fragments
3774 * primary_rgba - primary colors (may alias rgba for single texture)
3775 * texels - array of texel colors
3776 * InOut: rgba - incoming fragment colors modified by texel colors
3777 * according to the texture environment mode.
3780 texture_apply( const GLcontext
*ctx
,
3781 const struct gl_texture_unit
*texUnit
,
3783 CONST GLchan primary_rgba
[][4], CONST GLchan texel
[][4],
3788 GLint Rc
, Gc
, Bc
, Ac
;
3792 ASSERT(texUnit
->_Current
);
3794 baseLevel
= texUnit
->_Current
->BaseLevel
;
3795 ASSERT(texUnit
->_Current
->Image
[baseLevel
]);
3797 format
= texUnit
->_Current
->Image
[baseLevel
]->Format
;
3799 if (format
== GL_COLOR_INDEX
|| format
== GL_DEPTH_COMPONENT
3800 || format
== GL_YCBCR_MESA
) {
3801 format
= GL_RGBA
; /* a bit of a hack */
3804 switch (texUnit
->EnvMode
) {
3811 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3817 GLchan Lt
= texel
[i
][RCOMP
];
3818 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3822 case GL_LUMINANCE_ALPHA
:
3824 GLchan Lt
= texel
[i
][RCOMP
];
3826 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3828 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3834 GLchan It
= texel
[i
][RCOMP
];
3835 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
3837 rgba
[i
][ACOMP
] = It
;
3843 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3844 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3845 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3852 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3853 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3854 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3856 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3860 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in texture_apply");
3871 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3877 GLchan Lt
= texel
[i
][RCOMP
];
3878 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3879 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3880 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3884 case GL_LUMINANCE_ALPHA
:
3887 GLchan Lt
= texel
[i
][RCOMP
];
3888 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3889 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3890 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3892 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3898 GLchan It
= texel
[i
][RCOMP
];
3899 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], It
);
3900 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], It
);
3901 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], It
);
3903 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], It
);
3909 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3910 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3911 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3918 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3919 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3920 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3922 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3926 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in texture_apply");
3935 case GL_LUMINANCE_ALPHA
:
3942 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3943 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3944 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3950 /* Cv = Cf(1-At) + CtAt */
3951 GLint t
= texel
[i
][ACOMP
], s
= CHAN_MAX
- t
;
3952 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(texel
[i
][RCOMP
],t
);
3953 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(texel
[i
][GCOMP
],t
);
3954 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(texel
[i
][BCOMP
],t
);
3959 _mesa_problem(ctx
, "Bad format (GL_DECAL) in texture_apply");
3965 Rc
= (GLint
) (texUnit
->EnvColor
[0] * CHAN_MAXF
);
3966 Gc
= (GLint
) (texUnit
->EnvColor
[1] * CHAN_MAXF
);
3967 Bc
= (GLint
) (texUnit
->EnvColor
[2] * CHAN_MAXF
);
3968 Ac
= (GLint
) (texUnit
->EnvColor
[3] * CHAN_MAXF
);
3974 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3979 /* Cv = Cf(1-Lt) + CcLt */
3980 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3981 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3982 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3983 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3987 case GL_LUMINANCE_ALPHA
:
3989 /* Cv = Cf(1-Lt) + CcLt */
3990 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3991 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3992 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3993 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3995 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
4000 /* Cv = Cf(1-It) + CcLt */
4001 GLchan It
= texel
[i
][RCOMP
], s
= CHAN_MAX
- It
;
4002 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, It
);
4003 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, It
);
4004 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, It
);
4005 /* Av = Af(1-It) + Ac*It */
4006 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], s
) + CHAN_PRODUCT(Ac
, It
);
4011 /* Cv = Cf(1-Ct) + CcCt */
4012 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
4013 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
4014 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
4020 /* Cv = Cf(1-Ct) + CcCt */
4021 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
4022 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
4023 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
4025 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
4029 _mesa_problem(ctx
, "Bad format (GL_BLEND) in texture_apply");
4034 /* XXX don't clamp results if GLchan is float??? */
4036 case GL_ADD
: /* GL_EXT_texture_add_env */
4043 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4048 GLuint Lt
= texel
[i
][RCOMP
];
4049 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
4050 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
4051 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
4052 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4053 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4054 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4058 case GL_LUMINANCE_ALPHA
:
4060 GLuint Lt
= texel
[i
][RCOMP
];
4061 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
4062 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
4063 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
4064 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4065 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4066 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4067 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4072 GLchan It
= texel
[i
][RCOMP
];
4073 GLuint r
= rgba
[i
][RCOMP
] + It
;
4074 GLuint g
= rgba
[i
][GCOMP
] + It
;
4075 GLuint b
= rgba
[i
][BCOMP
] + It
;
4076 GLuint a
= rgba
[i
][ACOMP
] + It
;
4077 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4078 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4079 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4080 rgba
[i
][ACOMP
] = MIN2(a
, CHAN_MAX
);
4085 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
4086 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
4087 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
4088 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4089 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4090 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4096 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
4097 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
4098 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
4099 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4100 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4101 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4102 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4106 _mesa_problem(ctx
, "Bad format (GL_ADD) in texture_apply");
4112 _mesa_problem(ctx
, "Bad env mode in texture_apply");
4120 * Apply texture mapping to a span of fragments.
4123 _swrast_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
4125 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
4126 GLchan primary_rgba
[MAX_WIDTH
][4];
4129 ASSERT(span
->end
< MAX_WIDTH
);
4130 ASSERT(span
->arrayMask
& SPAN_TEXTURE
);
4133 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
4135 if (swrast
->_AnyTextureCombine
)
4136 MEMCPY(primary_rgba
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
));
4139 * Must do all texture sampling before combining in order to
4140 * accomodate GL_ARB_texture_env_crossbar.
4142 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
4143 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
4144 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
4145 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
4146 GLfloat
*lambda
= span
->array
->lambda
[unit
];
4147 GLchan (*texels
)[4] = (GLchan (*)[4])
4148 (swrast
->TexelBuffer
+ unit
* (span
->end
* 4 * sizeof(GLchan
)));
4150 /* adjust texture lod (lambda) */
4151 if (span
->arrayMask
& SPAN_LAMBDA
) {
4152 if (texUnit
->LodBias
!= 0.0F
) {
4153 /* apply LOD bias, but don't clamp yet */
4155 for (i
= 0; i
< span
->end
; i
++) {
4156 lambda
[i
] += texUnit
->LodBias
;
4160 if (curObj
->MinLod
!= -1000.0 || curObj
->MaxLod
!= 1000.0) {
4161 /* apply LOD clamping to lambda */
4162 const GLfloat min
= curObj
->MinLod
;
4163 const GLfloat max
= curObj
->MaxLod
;
4165 for (i
= 0; i
< span
->end
; i
++) {
4166 GLfloat l
= lambda
[i
];
4167 lambda
[i
] = CLAMP(l
, min
, max
);
4172 /* Sample the texture (span->end fragments) */
4173 swrast
->TextureSample
[unit
]( ctx
, unit
, texUnit
->_Current
,
4174 span
->end
, span
->array
->texcoords
[unit
],
4176 /* GL_SGI_texture_color_table */
4177 if (texUnit
->ColorTableEnabled
) {
4178 _swrast_texture_table_lookup(&texUnit
->ColorTable
, span
->end
, texels
);
4184 * OK, now apply the texture (aka texture combine/blend).
4185 * We modify the span->color.rgba values.
4187 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
4188 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
4189 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
4190 if (texUnit
->EnvMode
== GL_COMBINE
) {
4191 /* GL_ARB/EXT_texture_env_combine */
4192 texture_combine( ctx
, unit
, span
->end
,
4193 (CONST
GLchan (*)[4]) primary_rgba
,
4194 swrast
->TexelBuffer
,
4195 span
->array
->rgba
);
4197 else if (texUnit
->EnvMode
== GL_COMBINE4_NV
) {
4198 /* GL_NV_texture_env_combine4 */
4199 texture_combine4( ctx
, unit
, span
->end
,
4200 (CONST
GLchan (*)[4]) primary_rgba
,
4201 swrast
->TexelBuffer
,
4202 span
->array
->rgba
);
4205 /* conventional texture blend */
4206 const GLchan (*texels
)[4] = (const GLchan (*)[4])
4207 (swrast
->TexelBuffer
+ unit
*
4208 (span
->end
* 4 * sizeof(GLchan
)));
4209 texture_apply( ctx
, texUnit
, span
->end
,
4210 (CONST
GLchan (*)[4]) primary_rgba
, texels
,
4211 span
->array
->rgba
);