1 /* $Id: s_texture.c,v 1.81 2003/02/27 19:40:45 kschultz 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
, const 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
, const 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
, const 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
, const 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 const 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 const 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 const 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
, const 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
, const 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
, const 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
, const 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
, const 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 const 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 const 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
, const 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
, const 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
, const 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
,
1549 texcoords
+ minStart
,
1550 lambda
+ minStart
, rgba
+ minStart
);
1552 case GL_LINEAR_MIPMAP_NEAREST
:
1553 sample_2d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1554 lambda
+ minStart
, rgba
+ minStart
);
1556 case GL_NEAREST_MIPMAP_LINEAR
:
1557 sample_2d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1558 lambda
+ minStart
, rgba
+ minStart
);
1560 case GL_LINEAR_MIPMAP_LINEAR
:
1562 sample_2d_linear_mipmap_linear_repeat(ctx
, tObj
, m
,
1563 texcoords
+ minStart
, lambda
+ minStart
, rgba
+ minStart
);
1565 sample_2d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
1566 lambda
+ minStart
, rgba
+ minStart
);
1569 _mesa_problem(ctx
, "Bad min filter in sample_2d_texture");
1574 if (magStart
< magEnd
) {
1575 /* do the magnified texels */
1576 const GLuint m
= magEnd
- magStart
;
1578 switch (tObj
->MagFilter
) {
1580 if (repeatNoBorder
) {
1581 switch (tImg
->Format
) {
1583 opt_sample_rgb_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1584 NULL
, rgba
+ magStart
);
1587 opt_sample_rgba_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1588 NULL
, rgba
+ magStart
);
1591 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1592 NULL
, rgba
+ magStart
);
1596 sample_nearest_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1597 NULL
, rgba
+ magStart
);
1601 sample_linear_2d(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
1602 NULL
, rgba
+ magStart
);
1605 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_2d");
1612 /**********************************************************************/
1613 /* 3-D Texture Sampling Functions */
1614 /**********************************************************************/
1617 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1620 sample_3d_nearest(GLcontext
*ctx
,
1621 const struct gl_texture_object
*tObj
,
1622 const struct gl_texture_image
*img
,
1623 const GLfloat texcoord
[4],
1626 const GLint width
= img
->Width2
; /* without border, power of two */
1627 const GLint height
= img
->Height2
; /* without border, power of two */
1628 const GLint depth
= img
->Depth2
; /* without border, power of two */
1631 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoord
[0], width
, i
);
1632 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoord
[1], height
, j
);
1633 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapR
, texcoord
[2], depth
, k
);
1635 if (i
< 0 || i
>= (GLint
) img
->Width
||
1636 j
< 0 || j
>= (GLint
) img
->Height
||
1637 k
< 0 || k
>= (GLint
) img
->Depth
) {
1638 /* Need this test for GL_CLAMP_TO_BORDER mode */
1639 COPY_CHAN4(rgba
, tObj
->_BorderChan
);
1642 (*img
->FetchTexel
)(img
, i
, j
, k
, (GLvoid
*) rgba
);
1643 if (img
->Format
== GL_COLOR_INDEX
) {
1644 palette_sample(ctx
, tObj
, rgba
[0], rgba
);
1652 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1655 sample_3d_linear(GLcontext
*ctx
,
1656 const struct gl_texture_object
*tObj
,
1657 const struct gl_texture_image
*img
,
1658 const GLfloat texcoord
[4],
1661 const GLint width
= img
->Width2
;
1662 const GLint height
= img
->Height2
;
1663 const GLint depth
= img
->Depth2
;
1664 GLint i0
, j0
, k0
, i1
, j1
, k1
;
1665 GLuint useBorderColor
;
1668 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoord
[0], u
, width
, i0
, i1
);
1669 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoord
[1], v
, height
, j0
, j1
);
1670 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapR
, texcoord
[2], w
, depth
, k0
, k1
);
1682 /* check if sampling texture border color */
1683 if (i0
< 0 || i0
>= width
) useBorderColor
|= I0BIT
;
1684 if (i1
< 0 || i1
>= width
) useBorderColor
|= I1BIT
;
1685 if (j0
< 0 || j0
>= height
) useBorderColor
|= J0BIT
;
1686 if (j1
< 0 || j1
>= height
) useBorderColor
|= J1BIT
;
1687 if (k0
< 0 || k0
>= depth
) useBorderColor
|= K0BIT
;
1688 if (k1
< 0 || k1
>= depth
) useBorderColor
|= K1BIT
;
1692 const GLfloat a
= FRAC(u
);
1693 const GLfloat b
= FRAC(v
);
1694 const GLfloat c
= FRAC(w
);
1696 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1697 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1698 GLfloat w000
= (1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
);
1699 GLfloat w100
= a
* (1.0F
-b
) * (1.0F
-c
);
1700 GLfloat w010
= (1.0F
-a
) * b
* (1.0F
-c
);
1701 GLfloat w110
= a
* b
* (1.0F
-c
);
1702 GLfloat w001
= (1.0F
-a
) * (1.0F
-b
) * c
;
1703 GLfloat w101
= a
* (1.0F
-b
) * c
;
1704 GLfloat w011
= (1.0F
-a
) * b
* c
;
1705 GLfloat w111
= a
* b
* c
;
1706 #else /* CHAN_BITS == 8 */
1707 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1708 GLint w000
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1709 GLint w100
= IROUND_POS( a
* (1.0F
-b
) * (1.0F
-c
) * WEIGHT_SCALE
);
1710 GLint w010
= IROUND_POS((1.0F
-a
) * b
* (1.0F
-c
) * WEIGHT_SCALE
);
1711 GLint w110
= IROUND_POS( a
* b
* (1.0F
-c
) * WEIGHT_SCALE
);
1712 GLint w001
= IROUND_POS((1.0F
-a
) * (1.0F
-b
) * c
* WEIGHT_SCALE
);
1713 GLint w101
= IROUND_POS( a
* (1.0F
-b
) * c
* WEIGHT_SCALE
);
1714 GLint w011
= IROUND_POS((1.0F
-a
) * b
* c
* WEIGHT_SCALE
);
1715 GLint w111
= IROUND_POS( a
* b
* c
* WEIGHT_SCALE
);
1718 GLchan t000
[4], t010
[4], t001
[4], t011
[4];
1719 GLchan t100
[4], t110
[4], t101
[4], t111
[4];
1721 if (useBorderColor
& (I0BIT
| J0BIT
| K0BIT
)) {
1722 COPY_CHAN4(t000
, tObj
->_BorderChan
);
1725 (*img
->FetchTexel
)(img
, i0
, j0
, k0
, (GLvoid
*) t000
);
1726 if (img
->Format
== GL_COLOR_INDEX
) {
1727 palette_sample(ctx
, tObj
, t000
[0], t000
);
1730 if (useBorderColor
& (I1BIT
| J0BIT
| K0BIT
)) {
1731 COPY_CHAN4(t100
, tObj
->_BorderChan
);
1734 (*img
->FetchTexel
)(img
, i1
, j0
, k0
, (GLvoid
*) t100
);
1735 if (img
->Format
== GL_COLOR_INDEX
) {
1736 palette_sample(ctx
, tObj
, t100
[0], t100
);
1739 if (useBorderColor
& (I0BIT
| J1BIT
| K0BIT
)) {
1740 COPY_CHAN4(t010
, tObj
->_BorderChan
);
1743 (*img
->FetchTexel
)(img
, i0
, j1
, k0
, (GLvoid
*) t010
);
1744 if (img
->Format
== GL_COLOR_INDEX
) {
1745 palette_sample(ctx
, tObj
, t010
[0], t010
);
1748 if (useBorderColor
& (I1BIT
| J1BIT
| K0BIT
)) {
1749 COPY_CHAN4(t110
, tObj
->_BorderChan
);
1752 (*img
->FetchTexel
)(img
, i1
, j1
, k0
, (GLvoid
*) t110
);
1753 if (img
->Format
== GL_COLOR_INDEX
) {
1754 palette_sample(ctx
, tObj
, t110
[0], t110
);
1758 if (useBorderColor
& (I0BIT
| J0BIT
| K1BIT
)) {
1759 COPY_CHAN4(t001
, tObj
->_BorderChan
);
1762 (*img
->FetchTexel
)(img
, i0
, j0
, k1
, (GLvoid
*) t001
);
1763 if (img
->Format
== GL_COLOR_INDEX
) {
1764 palette_sample(ctx
, tObj
, t001
[0], t001
);
1767 if (useBorderColor
& (I1BIT
| J0BIT
| K1BIT
)) {
1768 COPY_CHAN4(t101
, tObj
->_BorderChan
);
1771 (*img
->FetchTexel
)(img
, i1
, j0
, k1
, (GLvoid
*) t101
);
1772 if (img
->Format
== GL_COLOR_INDEX
) {
1773 palette_sample(ctx
, tObj
, t101
[0], t101
);
1776 if (useBorderColor
& (I0BIT
| J1BIT
| K1BIT
)) {
1777 COPY_CHAN4(t011
, tObj
->_BorderChan
);
1780 (*img
->FetchTexel
)(img
, i0
, j1
, k1
, (GLvoid
*) t011
);
1781 if (img
->Format
== GL_COLOR_INDEX
) {
1782 palette_sample(ctx
, tObj
, t011
[0], t011
);
1785 if (useBorderColor
& (I1BIT
| J1BIT
| K1BIT
)) {
1786 COPY_CHAN4(t111
, tObj
->_BorderChan
);
1789 (*img
->FetchTexel
)(img
, i1
, j1
, k1
, (GLvoid
*) t111
);
1790 if (img
->Format
== GL_COLOR_INDEX
) {
1791 palette_sample(ctx
, tObj
, t111
[0], t111
);
1795 #if CHAN_TYPE == GL_FLOAT
1796 rgba
[0] = w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1797 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0];
1798 rgba
[1] = w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1799 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1];
1800 rgba
[2] = w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1801 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2];
1802 rgba
[3] = w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1803 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3];
1804 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1805 rgba
[0] = (GLchan
) (w000
*t000
[0] + w010
*t010
[0] +
1806 w001
*t001
[0] + w011
*t011
[0] +
1807 w100
*t100
[0] + w110
*t110
[0] +
1808 w101
*t101
[0] + w111
*t111
[0] + 0.5);
1809 rgba
[1] = (GLchan
) (w000
*t000
[1] + w010
*t010
[1] +
1810 w001
*t001
[1] + w011
*t011
[1] +
1811 w100
*t100
[1] + w110
*t110
[1] +
1812 w101
*t101
[1] + w111
*t111
[1] + 0.5);
1813 rgba
[2] = (GLchan
) (w000
*t000
[2] + w010
*t010
[2] +
1814 w001
*t001
[2] + w011
*t011
[2] +
1815 w100
*t100
[2] + w110
*t110
[2] +
1816 w101
*t101
[2] + w111
*t111
[2] + 0.5);
1817 rgba
[3] = (GLchan
) (w000
*t000
[3] + w010
*t010
[3] +
1818 w001
*t001
[3] + w011
*t011
[3] +
1819 w100
*t100
[3] + w110
*t110
[3] +
1820 w101
*t101
[3] + w111
*t111
[3] + 0.5);
1821 #else /* CHAN_BITS == 8 */
1822 rgba
[0] = (GLchan
) (
1823 (w000
*t000
[0] + w010
*t010
[0] + w001
*t001
[0] + w011
*t011
[0] +
1824 w100
*t100
[0] + w110
*t110
[0] + w101
*t101
[0] + w111
*t111
[0] )
1826 rgba
[1] = (GLchan
) (
1827 (w000
*t000
[1] + w010
*t010
[1] + w001
*t001
[1] + w011
*t011
[1] +
1828 w100
*t100
[1] + w110
*t110
[1] + w101
*t101
[1] + w111
*t111
[1] )
1830 rgba
[2] = (GLchan
) (
1831 (w000
*t000
[2] + w010
*t010
[2] + w001
*t001
[2] + w011
*t011
[2] +
1832 w100
*t100
[2] + w110
*t110
[2] + w101
*t101
[2] + w111
*t111
[2] )
1834 rgba
[3] = (GLchan
) (
1835 (w000
*t000
[3] + w010
*t010
[3] + w001
*t001
[3] + w011
*t011
[3] +
1836 w100
*t100
[3] + w110
*t110
[3] + w101
*t101
[3] + w111
*t111
[3] )
1846 sample_3d_nearest_mipmap_nearest(GLcontext
*ctx
,
1847 const struct gl_texture_object
*tObj
,
1848 GLuint n
, const GLfloat texcoord
[][4],
1849 const GLfloat lambda
[], GLchan rgba
[][4] )
1852 for (i
= 0; i
< n
; i
++) {
1854 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1855 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1861 sample_3d_linear_mipmap_nearest(GLcontext
*ctx
,
1862 const struct gl_texture_object
*tObj
,
1863 GLuint n
, const GLfloat texcoord
[][4],
1864 const GLfloat lambda
[], GLchan rgba
[][4])
1867 ASSERT(lambda
!= NULL
);
1868 for (i
= 0; i
< n
; i
++) {
1870 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1871 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], rgba
[i
]);
1877 sample_3d_nearest_mipmap_linear(GLcontext
*ctx
,
1878 const struct gl_texture_object
*tObj
,
1879 GLuint n
, const GLfloat texcoord
[][4],
1880 const GLfloat lambda
[], GLchan rgba
[][4])
1883 ASSERT(lambda
!= NULL
);
1884 for (i
= 0; i
< n
; i
++) {
1886 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1887 if (level
>= tObj
->_MaxLevel
) {
1888 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1889 texcoord
[i
], rgba
[i
]);
1892 GLchan t0
[4], t1
[4]; /* texels */
1893 const GLfloat f
= FRAC(lambda
[i
]);
1894 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1895 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1896 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1897 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1898 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1899 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1906 sample_3d_linear_mipmap_linear(GLcontext
*ctx
,
1907 const struct gl_texture_object
*tObj
,
1908 GLuint n
, const GLfloat texcoord
[][4],
1909 const GLfloat lambda
[], GLchan rgba
[][4])
1912 ASSERT(lambda
!= NULL
);
1913 for (i
= 0; i
< n
; i
++) {
1915 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
1916 if (level
>= tObj
->_MaxLevel
) {
1917 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->_MaxLevel
],
1918 texcoord
[i
], rgba
[i
]);
1921 GLchan t0
[4], t1
[4]; /* texels */
1922 const GLfloat f
= FRAC(lambda
[i
]);
1923 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
], texcoord
[i
], t0
);
1924 sample_3d_linear(ctx
, tObj
, tObj
->Image
[level
+1], texcoord
[i
], t1
);
1925 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
1926 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
1927 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
1928 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
1935 sample_nearest_3d(GLcontext
*ctx
, GLuint texUnit
,
1936 const struct gl_texture_object
*tObj
, GLuint n
,
1937 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1941 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1944 sample_3d_nearest(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1951 sample_linear_3d( GLcontext
*ctx
, GLuint texUnit
,
1952 const struct gl_texture_object
*tObj
, GLuint n
,
1953 const GLfloat texcoords
[][4],
1954 const GLfloat lambda
[], GLchan rgba
[][4] )
1957 struct gl_texture_image
*image
= tObj
->Image
[tObj
->BaseLevel
];
1960 sample_3d_linear(ctx
, tObj
, image
, texcoords
[i
], rgba
[i
]);
1966 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
1967 * return a texture sample.
1970 sample_lambda_3d( GLcontext
*ctx
, GLuint texUnit
,
1971 const struct gl_texture_object
*tObj
, GLuint n
,
1972 const GLfloat texcoords
[][4], const GLfloat lambda
[],
1975 GLuint minStart
, minEnd
; /* texels with minification */
1976 GLuint magStart
, magEnd
; /* texels with magnification */
1979 ASSERT(lambda
!= NULL
);
1980 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
1981 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
1983 if (minStart
< minEnd
) {
1984 /* do the minified texels */
1985 GLuint m
= minEnd
- minStart
;
1986 switch (tObj
->MinFilter
) {
1988 for (i
= minStart
; i
< minEnd
; i
++)
1989 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1990 texcoords
[i
], rgba
[i
]);
1993 for (i
= minStart
; i
< minEnd
; i
++)
1994 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
1995 texcoords
[i
], rgba
[i
]);
1997 case GL_NEAREST_MIPMAP_NEAREST
:
1998 sample_3d_nearest_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
1999 lambda
+ minStart
, rgba
+ minStart
);
2001 case GL_LINEAR_MIPMAP_NEAREST
:
2002 sample_3d_linear_mipmap_nearest(ctx
, tObj
, m
, texcoords
+ minStart
,
2003 lambda
+ minStart
, rgba
+ minStart
);
2005 case GL_NEAREST_MIPMAP_LINEAR
:
2006 sample_3d_nearest_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
2007 lambda
+ minStart
, rgba
+ minStart
);
2009 case GL_LINEAR_MIPMAP_LINEAR
:
2010 sample_3d_linear_mipmap_linear(ctx
, tObj
, m
, texcoords
+ minStart
,
2011 lambda
+ minStart
, rgba
+ minStart
);
2014 _mesa_problem(ctx
, "Bad min filter in sample_3d_texture");
2019 if (magStart
< magEnd
) {
2020 /* do the magnified texels */
2021 switch (tObj
->MagFilter
) {
2023 for (i
= magStart
; i
< magEnd
; i
++)
2024 sample_3d_nearest(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
2025 texcoords
[i
], rgba
[i
]);
2028 for (i
= magStart
; i
< magEnd
; i
++)
2029 sample_3d_linear(ctx
, tObj
, tObj
->Image
[tObj
->BaseLevel
],
2030 texcoords
[i
], rgba
[i
]);
2033 _mesa_problem(ctx
, "Bad mag filter in sample_3d_texture");
2040 /**********************************************************************/
2041 /* Texture Cube Map Sampling Functions */
2042 /**********************************************************************/
2045 * Choose one of six sides of a texture cube map given the texture
2046 * coord (rx,ry,rz). Return pointer to corresponding array of texture
2049 static const struct gl_texture_image
**
2050 choose_cube_face(const struct gl_texture_object
*texObj
,
2051 const GLfloat texcoord
[4], GLfloat newCoord
[4])
2055 direction target sc tc ma
2056 ---------- ------------------------------- --- --- ---
2057 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
2058 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
2059 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
2060 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
2061 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
2062 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
2064 const GLfloat rx
= texcoord
[0];
2065 const GLfloat ry
= texcoord
[1];
2066 const GLfloat rz
= texcoord
[2];
2067 const struct gl_texture_image
**imgArray
;
2068 const GLfloat arx
= ABSF(rx
), ary
= ABSF(ry
), arz
= ABSF(rz
);
2071 if (arx
> ary
&& arx
> arz
) {
2073 imgArray
= (const struct gl_texture_image
**) texObj
->Image
;
2079 imgArray
= (const struct gl_texture_image
**) texObj
->NegX
;
2085 else if (ary
> arx
&& ary
> arz
) {
2087 imgArray
= (const struct gl_texture_image
**) texObj
->PosY
;
2093 imgArray
= (const struct gl_texture_image
**) texObj
->NegY
;
2101 imgArray
= (const struct gl_texture_image
**) texObj
->PosZ
;
2107 imgArray
= (const struct gl_texture_image
**) texObj
->NegZ
;
2114 newCoord
[0] = ( sc
/ ma
+ 1.0F
) * 0.5F
;
2115 newCoord
[1] = ( tc
/ ma
+ 1.0F
) * 0.5F
;
2121 sample_nearest_cube(GLcontext
*ctx
, GLuint texUnit
,
2122 const struct gl_texture_object
*tObj
, GLuint n
,
2123 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2128 for (i
= 0; i
< n
; i
++) {
2129 const struct gl_texture_image
**images
;
2130 GLfloat newCoord
[4];
2131 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
2132 sample_2d_nearest(ctx
, tObj
, images
[tObj
->BaseLevel
],
2139 sample_linear_cube(GLcontext
*ctx
, GLuint texUnit
,
2140 const struct gl_texture_object
*tObj
, GLuint n
,
2141 const GLfloat texcoords
[][4],
2142 const GLfloat lambda
[], GLchan rgba
[][4])
2146 for (i
= 0; i
< n
; i
++) {
2147 const struct gl_texture_image
**images
;
2148 GLfloat newCoord
[4];
2149 images
= choose_cube_face(tObj
, texcoords
[i
], newCoord
);
2150 sample_2d_linear(ctx
, tObj
, images
[tObj
->BaseLevel
],
2157 sample_cube_nearest_mipmap_nearest(GLcontext
*ctx
, GLuint texUnit
,
2158 const struct gl_texture_object
*tObj
,
2159 GLuint n
, const GLfloat texcoord
[][4],
2160 const GLfloat lambda
[], GLchan rgba
[][4])
2163 ASSERT(lambda
!= NULL
);
2164 for (i
= 0; i
< n
; i
++) {
2165 const struct gl_texture_image
**images
;
2166 GLfloat newCoord
[4];
2168 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2169 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2170 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
2176 sample_cube_linear_mipmap_nearest(GLcontext
*ctx
, GLuint texUnit
,
2177 const struct gl_texture_object
*tObj
,
2178 GLuint n
, const GLfloat texcoord
[][4],
2179 const GLfloat lambda
[], GLchan rgba
[][4])
2182 ASSERT(lambda
!= NULL
);
2183 for (i
= 0; i
< n
; i
++) {
2184 const struct gl_texture_image
**images
;
2185 GLfloat newCoord
[4];
2187 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2188 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2189 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, rgba
[i
]);
2195 sample_cube_nearest_mipmap_linear(GLcontext
*ctx
, GLuint texUnit
,
2196 const struct gl_texture_object
*tObj
,
2197 GLuint n
, const GLfloat texcoord
[][4],
2198 const GLfloat lambda
[], GLchan rgba
[][4])
2201 ASSERT(lambda
!= NULL
);
2202 for (i
= 0; i
< n
; i
++) {
2203 const struct gl_texture_image
**images
;
2204 GLfloat newCoord
[4];
2206 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2207 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2208 if (level
>= tObj
->_MaxLevel
) {
2209 sample_2d_nearest(ctx
, tObj
, images
[tObj
->_MaxLevel
],
2213 GLchan t0
[4], t1
[4]; /* texels */
2214 const GLfloat f
= FRAC(lambda
[i
]);
2215 sample_2d_nearest(ctx
, tObj
, images
[level
], newCoord
, t0
);
2216 sample_2d_nearest(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
2217 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
2218 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
2219 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
2220 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
2227 sample_cube_linear_mipmap_linear(GLcontext
*ctx
, GLuint texUnit
,
2228 const struct gl_texture_object
*tObj
,
2229 GLuint n
, const GLfloat texcoord
[][4],
2230 const GLfloat lambda
[], GLchan rgba
[][4])
2233 ASSERT(lambda
!= NULL
);
2234 for (i
= 0; i
< n
; i
++) {
2235 const struct gl_texture_image
**images
;
2236 GLfloat newCoord
[4];
2238 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj
, lambda
[i
], level
);
2239 images
= choose_cube_face(tObj
, texcoord
[i
], newCoord
);
2240 if (level
>= tObj
->_MaxLevel
) {
2241 sample_2d_linear(ctx
, tObj
, images
[tObj
->_MaxLevel
],
2245 GLchan t0
[4], t1
[4];
2246 const GLfloat f
= FRAC(lambda
[i
]);
2247 sample_2d_linear(ctx
, tObj
, images
[level
], newCoord
, t0
);
2248 sample_2d_linear(ctx
, tObj
, images
[level
+1], newCoord
, t1
);
2249 rgba
[i
][RCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[RCOMP
] + f
* t1
[RCOMP
]);
2250 rgba
[i
][GCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[GCOMP
] + f
* t1
[GCOMP
]);
2251 rgba
[i
][BCOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[BCOMP
] + f
* t1
[BCOMP
]);
2252 rgba
[i
][ACOMP
] = CHAN_CAST ((1.0F
-f
) * t0
[ACOMP
] + f
* t1
[ACOMP
]);
2259 sample_lambda_cube( GLcontext
*ctx
, GLuint texUnit
,
2260 const struct gl_texture_object
*tObj
, GLuint n
,
2261 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2264 GLuint minStart
, minEnd
; /* texels with minification */
2265 GLuint magStart
, magEnd
; /* texels with magnification */
2267 ASSERT(lambda
!= NULL
);
2268 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2269 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2271 if (minStart
< minEnd
) {
2272 /* do the minified texels */
2273 const GLuint m
= minEnd
- minStart
;
2274 switch (tObj
->MinFilter
) {
2276 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2277 lambda
+ minStart
, rgba
+ minStart
);
2280 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ minStart
,
2281 lambda
+ minStart
, rgba
+ minStart
);
2283 case GL_NEAREST_MIPMAP_NEAREST
:
2284 sample_cube_nearest_mipmap_nearest(ctx
, texUnit
, tObj
, m
,
2285 texcoords
+ minStart
,
2286 lambda
+ minStart
, rgba
+ minStart
);
2288 case GL_LINEAR_MIPMAP_NEAREST
:
2289 sample_cube_linear_mipmap_nearest(ctx
, texUnit
, tObj
, m
,
2290 texcoords
+ minStart
,
2291 lambda
+ minStart
, rgba
+ minStart
);
2293 case GL_NEAREST_MIPMAP_LINEAR
:
2294 sample_cube_nearest_mipmap_linear(ctx
, texUnit
, tObj
, m
,
2295 texcoords
+ minStart
,
2296 lambda
+ minStart
, rgba
+ minStart
);
2298 case GL_LINEAR_MIPMAP_LINEAR
:
2299 sample_cube_linear_mipmap_linear(ctx
, texUnit
, tObj
, m
,
2300 texcoords
+ minStart
,
2301 lambda
+ minStart
, rgba
+ minStart
);
2304 _mesa_problem(ctx
, "Bad min filter in sample_lambda_cube");
2308 if (magStart
< magEnd
) {
2309 /* do the magnified texels */
2310 const GLuint m
= magEnd
- magStart
;
2311 switch (tObj
->MagFilter
) {
2313 sample_nearest_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2314 lambda
+ magStart
, rgba
+ magStart
);
2317 sample_linear_cube(ctx
, texUnit
, tObj
, m
, texcoords
+ magStart
,
2318 lambda
+ magStart
, rgba
+ magStart
);
2321 _mesa_problem(ctx
, "Bad mag filter in sample_lambda_cube");
2327 /**********************************************************************/
2328 /* Texture Rectangle Sampling Functions */
2329 /**********************************************************************/
2332 sample_nearest_rect(GLcontext
*ctx
, GLuint texUnit
,
2333 const struct gl_texture_object
*tObj
, GLuint n
,
2334 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2337 const struct gl_texture_image
*img
= tObj
->Image
[0];
2338 const GLfloat width
= (GLfloat
) img
->Width
;
2339 const GLfloat height
= (GLfloat
) img
->Height
;
2340 const GLint width_minus_1
= img
->Width
- 1;
2341 const GLint height_minus_1
= img
->Height
- 1;
2347 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2348 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2349 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2350 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2351 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2352 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2353 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2355 /* XXX move Wrap mode tests outside of loops for common cases */
2356 for (i
= 0; i
< n
; i
++) {
2358 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2359 if (tObj
->WrapS
== GL_CLAMP
) {
2360 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.0F
, width
) );
2362 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2363 col
= IFLOOR( CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
) );
2366 col
= IFLOOR( CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
) );
2368 if (tObj
->WrapT
== GL_CLAMP
) {
2369 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.0F
, height
) );
2371 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2372 row
= IFLOOR( CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
) );
2375 row
= IFLOOR( CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
) );
2378 col
= CLAMP(col
, 0, width_minus_1
);
2379 row
= CLAMP(row
, 0, height_minus_1
);
2381 (*img
->FetchTexel
)(img
, col
, row
, 0, (GLvoid
*) rgba
[i
]);
2387 sample_linear_rect(GLcontext
*ctx
, GLuint texUnit
,
2388 const struct gl_texture_object
*tObj
, GLuint n
,
2389 const GLfloat texcoords
[][4],
2390 const GLfloat lambda
[], GLchan rgba
[][4])
2392 const struct gl_texture_image
*img
= tObj
->Image
[0];
2393 const GLfloat width
= (GLfloat
) img
->Width
;
2394 const GLfloat height
= (GLfloat
) img
->Height
;
2395 const GLint width_minus_1
= img
->Width
- 1;
2396 const GLint height_minus_1
= img
->Height
- 1;
2402 ASSERT(tObj
->WrapS
== GL_CLAMP
||
2403 tObj
->WrapS
== GL_CLAMP_TO_EDGE
||
2404 tObj
->WrapS
== GL_CLAMP_TO_BORDER
);
2405 ASSERT(tObj
->WrapT
== GL_CLAMP
||
2406 tObj
->WrapT
== GL_CLAMP_TO_EDGE
||
2407 tObj
->WrapT
== GL_CLAMP_TO_BORDER
);
2408 ASSERT(img
->Format
!= GL_COLOR_INDEX
);
2410 /* XXX lots of opportunity for optimization in this loop */
2411 for (i
= 0; i
< n
; i
++) {
2413 GLint row0
, col0
, row1
, col1
;
2414 GLchan t00
[4], t01
[4], t10
[4], t11
[4];
2415 GLfloat a
, b
, w00
, w01
, w10
, w11
;
2417 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2418 if (tObj
->WrapS
== GL_CLAMP
) {
2419 fcol
= CLAMP(texcoords
[i
][0], 0.0F
, width
);
2421 else if (tObj
->WrapS
== GL_CLAMP_TO_EDGE
) {
2422 fcol
= CLAMP(texcoords
[i
][0], 0.5F
, width
- 0.5F
);
2425 fcol
= CLAMP(texcoords
[i
][0], -0.5F
, width
+ 0.5F
);
2427 if (tObj
->WrapT
== GL_CLAMP
) {
2428 frow
= CLAMP(texcoords
[i
][1], 0.0F
, height
);
2430 else if (tObj
->WrapT
== GL_CLAMP_TO_EDGE
) {
2431 frow
= CLAMP(texcoords
[i
][1], 0.5F
, height
- 0.5F
);
2434 frow
= CLAMP(texcoords
[i
][1], -0.5F
, height
+ 0.5F
);
2437 /* compute integer rows/columns */
2438 col0
= IFLOOR(fcol
);
2440 col0
= CLAMP(col0
, 0, width_minus_1
);
2441 col1
= CLAMP(col1
, 0, width_minus_1
);
2442 row0
= IFLOOR(frow
);
2444 row0
= CLAMP(row0
, 0, height_minus_1
);
2445 row1
= CLAMP(row1
, 0, height_minus_1
);
2447 /* get four texel samples */
2448 (*img
->FetchTexel
)(img
, col0
, row0
, 0, (GLvoid
*) t00
);
2449 (*img
->FetchTexel
)(img
, col1
, row0
, 0, (GLvoid
*) t10
);
2450 (*img
->FetchTexel
)(img
, col0
, row1
, 0, (GLvoid
*) t01
);
2451 (*img
->FetchTexel
)(img
, col1
, row1
, 0, (GLvoid
*) t11
);
2453 /* compute sample weights */
2456 w00
= (1.0F
-a
) * (1.0F
-b
);
2458 w01
= (1.0F
-a
) * b
;
2461 /* compute weighted average of samples */
2463 (GLchan
) (w00
* t00
[0] + w10
* t10
[0] + w01
* t01
[0] + w11
* t11
[0]);
2465 (GLchan
) (w00
* t00
[1] + w10
* t10
[1] + w01
* t01
[1] + w11
* t11
[1]);
2467 (GLchan
) (w00
* t00
[2] + w10
* t10
[2] + w01
* t01
[2] + w11
* t11
[2]);
2469 (GLchan
) (w00
* t00
[3] + w10
* t10
[3] + w01
* t01
[3] + w11
* t11
[3]);
2475 sample_lambda_rect( GLcontext
*ctx
, GLuint texUnit
,
2476 const struct gl_texture_object
*tObj
, GLuint n
,
2477 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2480 GLuint minStart
, minEnd
, magStart
, magEnd
;
2482 /* We only need lambda to decide between minification and magnification.
2483 * There is no mipmapping with rectangular textures.
2485 compute_min_mag_ranges(SWRAST_CONTEXT(ctx
)->_MinMagThresh
[texUnit
],
2486 n
, lambda
, &minStart
, &minEnd
, &magStart
, &magEnd
);
2488 if (minStart
< minEnd
) {
2489 if (tObj
->MinFilter
== GL_NEAREST
) {
2490 sample_nearest_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2491 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2494 sample_linear_rect( ctx
, texUnit
, tObj
, minEnd
- minStart
,
2495 texcoords
+ minStart
, NULL
, rgba
+ minStart
);
2498 if (magStart
< magEnd
) {
2499 if (tObj
->MagFilter
== GL_NEAREST
) {
2500 sample_nearest_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2501 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2504 sample_linear_rect( ctx
, texUnit
, tObj
, magEnd
- magStart
,
2505 texcoords
+ magStart
, NULL
, rgba
+ magStart
);
2513 * Sample a shadow/depth texture.
2516 sample_depth_texture( GLcontext
*ctx
, GLuint unit
,
2517 const struct gl_texture_object
*tObj
, GLuint n
,
2518 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2521 const GLint baseLevel
= tObj
->BaseLevel
;
2522 const struct gl_texture_image
*texImage
= tObj
->Image
[baseLevel
];
2523 const GLuint width
= texImage
->Width
;
2524 const GLuint height
= texImage
->Height
;
2531 ASSERT(tObj
->Image
[tObj
->BaseLevel
]->Format
== GL_DEPTH_COMPONENT
);
2532 ASSERT(tObj
->Target
== GL_TEXTURE_1D
||
2533 tObj
->Target
== GL_TEXTURE_2D
||
2534 tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
2536 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2538 /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
2540 /* XXX this could be precomputed and saved in the texture object */
2541 if (tObj
->CompareFlag
) {
2542 /* GL_SGIX_shadow */
2543 if (tObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2544 function
= GL_LEQUAL
;
2547 ASSERT(tObj
->CompareOperator
== GL_TEXTURE_GEQUAL_R_SGIX
);
2548 function
= GL_GEQUAL
;
2551 else if (tObj
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
) {
2553 function
= tObj
->CompareFunc
;
2556 function
= GL_NONE
; /* pass depth through as grayscale */
2559 if (tObj
->MagFilter
== GL_NEAREST
) {
2561 for (i
= 0; i
< n
; i
++) {
2562 GLfloat depthSample
;
2564 /* XXX fix for texture rectangle! */
2565 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapS
, texcoords
[i
][0], width
, col
);
2566 COMPUTE_NEAREST_TEXEL_LOCATION(tObj
->WrapT
, texcoords
[i
][1], height
, row
);
2567 depthSample
= *((const GLfloat
*) texImage
->Data
+ row
* width
+ col
);
2571 result
= (texcoords
[i
][2] <= depthSample
) ? CHAN_MAX
: ambient
;
2574 result
= (texcoords
[i
][2] >= depthSample
) ? CHAN_MAX
: ambient
;
2577 result
= (texcoords
[i
][2] < depthSample
) ? CHAN_MAX
: ambient
;
2580 result
= (texcoords
[i
][2] > depthSample
) ? CHAN_MAX
: ambient
;
2583 result
= (texcoords
[i
][2] == depthSample
) ? CHAN_MAX
: ambient
;
2586 result
= (texcoords
[i
][2] != depthSample
) ? CHAN_MAX
: ambient
;
2595 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2598 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2602 switch (tObj
->DepthMode
) {
2604 texel
[i
][RCOMP
] = result
;
2605 texel
[i
][GCOMP
] = result
;
2606 texel
[i
][BCOMP
] = result
;
2607 texel
[i
][ACOMP
] = CHAN_MAX
;
2610 texel
[i
][RCOMP
] = result
;
2611 texel
[i
][GCOMP
] = result
;
2612 texel
[i
][BCOMP
] = result
;
2613 texel
[i
][ACOMP
] = result
;
2616 texel
[i
][RCOMP
] = 0;
2617 texel
[i
][GCOMP
] = 0;
2618 texel
[i
][BCOMP
] = 0;
2619 texel
[i
][ACOMP
] = result
;
2622 _mesa_problem(ctx
, "Bad depth texture mode");
2628 ASSERT(tObj
->MagFilter
== GL_LINEAR
);
2629 for (i
= 0; i
< n
; i
++) {
2630 GLfloat depth00
, depth01
, depth10
, depth11
;
2631 GLint i0
, i1
, j0
, j1
;
2633 GLuint useBorderTexel
;
2635 /* XXX fix for texture rectangle! */
2636 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapS
, texcoords
[i
][0], u
, width
, i0
, i1
);
2637 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj
->WrapT
, texcoords
[i
][1], v
, height
,j0
, j1
);
2640 if (texImage
->Border
) {
2641 i0
+= texImage
->Border
;
2642 i1
+= texImage
->Border
;
2643 j0
+= texImage
->Border
;
2644 j1
+= texImage
->Border
;
2647 if (i0
< 0 || i0
>= (GLint
) width
) useBorderTexel
|= I0BIT
;
2648 if (i1
< 0 || i1
>= (GLint
) width
) useBorderTexel
|= I1BIT
;
2649 if (j0
< 0 || j0
>= (GLint
) height
) useBorderTexel
|= J0BIT
;
2650 if (j1
< 0 || j1
>= (GLint
) height
) useBorderTexel
|= J1BIT
;
2653 /* get four depth samples from the texture */
2654 if (useBorderTexel
& (I0BIT
| J0BIT
)) {
2658 depth00
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i0
);
2660 if (useBorderTexel
& (I1BIT
| J0BIT
)) {
2664 depth10
= *((const GLfloat
*) texImage
->Data
+ j0
* width
+ i1
);
2666 if (useBorderTexel
& (I0BIT
| J1BIT
)) {
2670 depth01
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i0
);
2672 if (useBorderTexel
& (I1BIT
| J1BIT
)) {
2676 depth11
= *((const GLfloat
*) texImage
->Data
+ j1
* width
+ i1
);
2680 /* compute a single weighted depth sample and do one comparison */
2681 const GLfloat a
= FRAC(u
+ 1.0F
);
2682 const GLfloat b
= FRAC(v
+ 1.0F
);
2683 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2684 const GLfloat w10
= ( a
) * (1.0F
- b
);
2685 const GLfloat w01
= (1.0F
- a
) * ( b
);
2686 const GLfloat w11
= ( a
) * ( b
);
2687 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2688 + w01
* depth01
+ w11
* depth11
;
2689 if ((depthSample
<= texcoords
[i
][2] && function
== GL_LEQUAL
) ||
2690 (depthSample
>= texcoords
[i
][2] && function
== GL_GEQUAL
)) {
2698 /* Do four depth/R comparisons and compute a weighted result.
2699 * If this touches on somebody's I.P., I'll remove this code
2702 const GLfloat d
= (CHAN_MAXF
- (GLfloat
) ambient
) * 0.25F
;
2703 GLfloat luminance
= CHAN_MAXF
;
2707 if (depth00
<= texcoords
[i
][2]) luminance
-= d
;
2708 if (depth01
<= texcoords
[i
][2]) luminance
-= d
;
2709 if (depth10
<= texcoords
[i
][2]) luminance
-= d
;
2710 if (depth11
<= texcoords
[i
][2]) luminance
-= d
;
2711 result
= (GLchan
) luminance
;
2714 if (depth00
>= texcoords
[i
][2]) luminance
-= d
;
2715 if (depth01
>= texcoords
[i
][2]) luminance
-= d
;
2716 if (depth10
>= texcoords
[i
][2]) luminance
-= d
;
2717 if (depth11
>= texcoords
[i
][2]) luminance
-= d
;
2718 result
= (GLchan
) luminance
;
2721 if (depth00
< texcoords
[i
][2]) luminance
-= d
;
2722 if (depth01
< texcoords
[i
][2]) luminance
-= d
;
2723 if (depth10
< texcoords
[i
][2]) luminance
-= d
;
2724 if (depth11
< texcoords
[i
][2]) luminance
-= d
;
2725 result
= (GLchan
) luminance
;
2728 if (depth00
> texcoords
[i
][2]) luminance
-= d
;
2729 if (depth01
> texcoords
[i
][2]) luminance
-= d
;
2730 if (depth10
> texcoords
[i
][2]) luminance
-= d
;
2731 if (depth11
> texcoords
[i
][2]) luminance
-= d
;
2732 result
= (GLchan
) luminance
;
2735 if (depth00
== texcoords
[i
][2]) luminance
-= d
;
2736 if (depth01
== texcoords
[i
][2]) luminance
-= d
;
2737 if (depth10
== texcoords
[i
][2]) luminance
-= d
;
2738 if (depth11
== texcoords
[i
][2]) luminance
-= d
;
2739 result
= (GLchan
) luminance
;
2742 if (depth00
!= texcoords
[i
][2]) luminance
-= d
;
2743 if (depth01
!= texcoords
[i
][2]) luminance
-= d
;
2744 if (depth10
!= texcoords
[i
][2]) luminance
-= d
;
2745 if (depth11
!= texcoords
[i
][2]) luminance
-= d
;
2746 result
= (GLchan
) luminance
;
2755 /* ordinary bilinear filtering */
2757 const GLfloat a
= FRAC(u
+ 1.0F
);
2758 const GLfloat b
= FRAC(v
+ 1.0F
);
2759 const GLfloat w00
= (1.0F
- a
) * (1.0F
- b
);
2760 const GLfloat w10
= ( a
) * (1.0F
- b
);
2761 const GLfloat w01
= (1.0F
- a
) * ( b
);
2762 const GLfloat w11
= ( a
) * ( b
);
2763 const GLfloat depthSample
= w00
* depth00
+ w10
* depth10
2764 + w01
* depth01
+ w11
* depth11
;
2765 CLAMPED_FLOAT_TO_CHAN(result
, depthSample
);
2769 _mesa_problem(ctx
, "Bad compare func in sample_depth_texture");
2774 switch (tObj
->DepthMode
) {
2776 texel
[i
][RCOMP
] = result
;
2777 texel
[i
][GCOMP
] = result
;
2778 texel
[i
][BCOMP
] = result
;
2779 texel
[i
][ACOMP
] = CHAN_MAX
;
2782 texel
[i
][RCOMP
] = result
;
2783 texel
[i
][GCOMP
] = result
;
2784 texel
[i
][BCOMP
] = result
;
2785 texel
[i
][ACOMP
] = result
;
2788 texel
[i
][RCOMP
] = 0;
2789 texel
[i
][GCOMP
] = 0;
2790 texel
[i
][BCOMP
] = 0;
2791 texel
[i
][ACOMP
] = result
;
2794 _mesa_problem(ctx
, "Bad depth texture mode");
2803 * Experimental depth texture sampling function.
2806 sample_depth_texture2(const GLcontext
*ctx
,
2807 const struct gl_texture_unit
*texUnit
,
2808 GLuint n
, const GLfloat texcoords
[][4],
2811 const struct gl_texture_object
*texObj
= texUnit
->_Current
;
2812 const GLint baseLevel
= texObj
->BaseLevel
;
2813 const struct gl_texture_image
*texImage
= texObj
->Image
[baseLevel
];
2814 const GLuint width
= texImage
->Width
;
2815 const GLuint height
= texImage
->Height
;
2817 GLboolean lequal
, gequal
;
2819 if (texObj
->Target
!= GL_TEXTURE_2D
) {
2820 _mesa_problem(ctx
, "only 2-D depth textures supported at this time");
2824 if (texObj
->MinFilter
!= texObj
->MagFilter
) {
2825 _mesa_problem(ctx
, "mipmapped depth textures not supported at this time");
2829 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2830 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2831 * isn't a depth texture.
2833 if (texImage
->Format
!= GL_DEPTH_COMPONENT
) {
2834 _mesa_problem(ctx
,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2838 UNCLAMPED_FLOAT_TO_CHAN(ambient
, tObj
->ShadowAmbient
);
2840 if (texObj
->CompareOperator
== GL_TEXTURE_LEQUAL_R_SGIX
) {
2851 for (i
= 0; i
< n
; i
++) {
2853 GLint col
, row
, ii
, jj
, imin
, imax
, jmin
, jmax
, samples
, count
;
2856 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapS
, texcoords
[i
][0],
2858 COMPUTE_NEAREST_TEXEL_LOCATION(texObj
->WrapT
, texcoords
[i
][1],
2866 if (imin
< 0) imin
= 0;
2867 if (imax
>= width
) imax
= width
- 1;
2868 if (jmin
< 0) jmin
= 0;
2869 if (jmax
>= height
) jmax
= height
- 1;
2871 samples
= (imax
- imin
+ 1) * (jmax
- jmin
+ 1);
2873 for (jj
= jmin
; jj
<= jmax
; jj
++) {
2874 for (ii
= imin
; ii
<= imax
; ii
++) {
2875 GLfloat depthSample
= *((const GLfloat
*) texImage
->Data
2877 if ((depthSample
<= r
[i
] && lequal
) ||
2878 (depthSample
>= r
[i
] && gequal
)) {
2884 w
= (GLfloat
) count
/ (GLfloat
) samples
;
2885 w
= CHAN_MAXF
- w
* (CHAN_MAXF
- (GLfloat
) ambient
);
2888 texel
[i
][RCOMP
] = lum
;
2889 texel
[i
][GCOMP
] = lum
;
2890 texel
[i
][BCOMP
] = lum
;
2891 texel
[i
][ACOMP
] = CHAN_MAX
;
2899 * We use this function when a texture object is in an "incomplete" state.
2900 * When a fragment program attempts to sample an incomplete texture we
2902 * Note: frag progs don't observe texture enable/disable flags.
2905 null_sample_func( GLcontext
*ctx
, GLuint texUnit
,
2906 const struct gl_texture_object
*tObj
, GLuint n
,
2907 const GLfloat texcoords
[][4], const GLfloat lambda
[],
2915 _mesa_bzero(rgba
, n
* 4 * sizeof(GLchan
));
2921 * Setup the texture sampling function for this texture object.
2924 _swrast_choose_texture_sample_func( GLcontext
*ctx
,
2925 const struct gl_texture_object
*t
)
2927 const GLboolean needLambda
= (GLboolean
) (t
->MinFilter
!= t
->MagFilter
);
2928 const GLenum format
= t
->Image
[t
->BaseLevel
]->Format
;
2931 return &null_sample_func
;
2934 switch (t
->Target
) {
2936 if (format
== GL_DEPTH_COMPONENT
) {
2937 return &sample_depth_texture
;
2939 else if (needLambda
) {
2940 return &sample_lambda_1d
;
2942 else if (t
->MinFilter
== GL_LINEAR
) {
2943 return &sample_linear_1d
;
2946 ASSERT(t
->MinFilter
== GL_NEAREST
);
2947 return &sample_nearest_1d
;
2951 if (format
== GL_DEPTH_COMPONENT
) {
2952 return &sample_depth_texture
;
2954 else if (needLambda
) {
2955 return &sample_lambda_2d
;
2957 else if (t
->MinFilter
== GL_LINEAR
) {
2958 return &sample_linear_2d
;
2961 GLint baseLevel
= t
->BaseLevel
;
2962 ASSERT(t
->MinFilter
== GL_NEAREST
);
2963 if (t
->WrapS
== GL_REPEAT
&&
2964 t
->WrapT
== GL_REPEAT
&&
2965 t
->Image
[baseLevel
]->Border
== 0 &&
2966 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGB
) {
2967 return &opt_sample_rgb_2d
;
2969 else if (t
->WrapS
== GL_REPEAT
&&
2970 t
->WrapT
== GL_REPEAT
&&
2971 t
->Image
[baseLevel
]->Border
== 0 &&
2972 t
->Image
[baseLevel
]->TexFormat
->MesaFormat
== MESA_FORMAT_RGBA
) {
2973 return &opt_sample_rgba_2d
;
2976 return &sample_nearest_2d
;
2982 return &sample_lambda_3d
;
2984 else if (t
->MinFilter
== GL_LINEAR
) {
2985 return &sample_linear_3d
;
2988 ASSERT(t
->MinFilter
== GL_NEAREST
);
2989 return &sample_nearest_3d
;
2992 case GL_TEXTURE_CUBE_MAP
:
2994 return &sample_lambda_cube
;
2996 else if (t
->MinFilter
== GL_LINEAR
) {
2997 return &sample_linear_cube
;
3000 ASSERT(t
->MinFilter
== GL_NEAREST
);
3001 return &sample_nearest_cube
;
3004 case GL_TEXTURE_RECTANGLE_NV
:
3006 return &sample_lambda_rect
;
3008 else if (t
->MinFilter
== GL_LINEAR
) {
3009 return &sample_linear_rect
;
3012 ASSERT(t
->MinFilter
== GL_NEAREST
);
3013 return &sample_nearest_rect
;
3018 "invalid target in _swrast_choose_texture_sample_func");
3019 return &null_sample_func
;
3024 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
3025 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
3029 * Do texture application for GL_ARB/EXT_texture_env_combine.
3030 * This function also supports GL_{EXT,ARB}_texture_env_dot3 and
3031 * GL_ATI_texture_env_combine3
3033 * \param ctx rendering context
3034 * \param textureUnit the texture unit to apply
3035 * \param n number of fragments to process (span width)
3036 * \param primary_rgba incoming fragment color array
3037 * \param texelBuffer pointer to texel colors for all texture units
3039 * \param rgba incoming colors, which get modified here
3042 texture_combine( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
3043 CONST
GLchan (*primary_rgba
)[4],
3044 CONST GLchan
*texelBuffer
,
3047 const struct gl_texture_unit
*textureUnit
= &(ctx
->Texture
.Unit
[unit
]);
3048 const GLchan (*argRGB
[3])[4];
3049 const GLchan (*argA
[3])[4];
3050 const GLuint RGBshift
= textureUnit
->CombineScaleShiftRGB
;
3051 const GLuint Ashift
= textureUnit
->CombineScaleShiftA
;
3052 #if CHAN_TYPE == GL_FLOAT
3053 const GLchan RGBmult
= (GLfloat
) (1 << RGBshift
);
3054 const GLchan Amult
= (GLfloat
) (1 << Ashift
);
3055 static const GLchan one
[4] = { 1.0, 1.0, 1.0, 1.0 };
3056 static const GLchan zero
[4] = { 0.0, 0.0, 0.0, 0.0 };
3058 const GLint half
= (CHAN_MAX
+ 1) / 2;
3059 static const GLchan one
[4] = { CHAN_MAX
, CHAN_MAX
, CHAN_MAX
, CHAN_MAX
};
3060 static const GLchan zero
[4] = { 0, 0, 0, 0 };
3063 GLuint numColorArgs
;
3064 GLuint numAlphaArgs
;
3066 /* GLchan ccolor[3][4]; */
3067 DEFMNARRAY(GLchan
, ccolor
, 3, 3 * MAX_WIDTH
, 4); /* mac 32k limitation */
3068 CHECKARRAY(ccolor
, return); /* mac 32k limitation */
3070 ASSERT(ctx
->Extensions
.EXT_texture_env_combine
||
3071 ctx
->Extensions
.ARB_texture_env_combine
);
3072 ASSERT(SWRAST_CONTEXT(ctx
)->_AnyTextureCombine
);
3076 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
3077 textureUnit->CombineModeRGB,
3078 textureUnit->CombineModeA,
3079 textureUnit->CombineSourceRGB[0],
3080 textureUnit->CombineSourceA[0],
3081 textureUnit->CombineSourceRGB[1],
3082 textureUnit->CombineSourceA[1]);
3086 * Do operand setup for up to 3 operands. Loop over the terms.
3088 switch (textureUnit
->CombineModeRGB
) {
3098 case GL_DOT3_RGB_EXT
:
3099 case GL_DOT3_RGBA_EXT
:
3102 case GL_INTERPOLATE
:
3103 case GL_MODULATE_ADD_ATI
:
3104 case GL_MODULATE_SIGNED_ADD_ATI
:
3105 case GL_MODULATE_SUBTRACT_ATI
:
3114 switch (textureUnit
->CombineModeA
) {
3124 case GL_INTERPOLATE
:
3125 case GL_MODULATE_ADD_ATI
:
3126 case GL_MODULATE_SIGNED_ADD_ATI
:
3127 case GL_MODULATE_SUBTRACT_ATI
:
3136 for (j
= 0; j
< numColorArgs
; j
++) {
3137 const GLenum srcRGB
= textureUnit
->CombineSourceRGB
[j
];
3142 argRGB
[j
] = (const GLchan (*)[4])
3143 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
3145 case GL_PRIMARY_COLOR
:
3146 argRGB
[j
] = primary_rgba
;
3149 argRGB
[j
] = (const GLchan (*)[4]) rgba
;
3153 GLchan (*c
)[4] = ccolor
[j
];
3154 GLchan red
, green
, blue
, alpha
;
3155 UNCLAMPED_FLOAT_TO_CHAN(red
, textureUnit
->EnvColor
[0]);
3156 UNCLAMPED_FLOAT_TO_CHAN(green
, textureUnit
->EnvColor
[1]);
3157 UNCLAMPED_FLOAT_TO_CHAN(blue
, textureUnit
->EnvColor
[2]);
3158 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
3159 for (i
= 0; i
< n
; i
++) {
3161 c
[i
][GCOMP
] = green
;
3163 c
[i
][ACOMP
] = alpha
;
3165 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3168 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
3177 /* ARB_texture_env_crossbar source */
3179 const GLuint srcUnit
= srcRGB
- GL_TEXTURE0
;
3180 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
3181 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
3183 argRGB
[j
] = (const GLchan (*)[4])
3184 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
3188 if (textureUnit
->CombineOperandRGB
[j
] != GL_SRC_COLOR
) {
3189 const GLchan (*src
)[4] = argRGB
[j
];
3190 GLchan (*dst
)[4] = ccolor
[j
];
3192 /* point to new arg[j] storage */
3193 argRGB
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3195 if (textureUnit
->CombineOperandRGB
[j
] == GL_ONE_MINUS_SRC_COLOR
) {
3196 for (i
= 0; i
< n
; i
++) {
3197 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][RCOMP
];
3198 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][GCOMP
];
3199 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][BCOMP
];
3202 else if (textureUnit
->CombineOperandRGB
[j
] == GL_SRC_ALPHA
) {
3203 for (i
= 0; i
< n
; i
++) {
3204 dst
[i
][RCOMP
] = src
[i
][ACOMP
];
3205 dst
[i
][GCOMP
] = src
[i
][ACOMP
];
3206 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
3210 ASSERT(textureUnit
->CombineOperandRGB
[j
] ==GL_ONE_MINUS_SRC_ALPHA
);
3211 for (i
= 0; i
< n
; i
++) {
3212 dst
[i
][RCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3213 dst
[i
][GCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3214 dst
[i
][BCOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3221 for (j
= 0; j
< numAlphaArgs
; j
++) {
3222 const GLenum srcA
= textureUnit
->CombineSourceA
[j
];
3226 argA
[j
] = (const GLchan (*)[4])
3227 (texelBuffer
+ unit
* (n
* 4 * sizeof(GLchan
)));
3229 case GL_PRIMARY_COLOR
:
3230 argA
[j
] = primary_rgba
;
3233 argA
[j
] = (const GLchan (*)[4]) rgba
;
3237 GLchan alpha
, (*c
)[4] = ccolor
[j
];
3238 UNCLAMPED_FLOAT_TO_CHAN(alpha
, textureUnit
->EnvColor
[3]);
3239 for (i
= 0; i
< n
; i
++)
3240 c
[i
][ACOMP
] = alpha
;
3241 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3244 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
3253 /* ARB_texture_env_crossbar source */
3255 const GLuint srcUnit
= srcA
- GL_TEXTURE0
;
3256 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
3257 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
3259 argA
[j
] = (const GLchan (*)[4])
3260 (texelBuffer
+ srcUnit
* (n
* 4 * sizeof(GLchan
)));
3264 if (textureUnit
->CombineOperandA
[j
] == GL_ONE_MINUS_SRC_ALPHA
) {
3265 const GLchan (*src
)[4] = argA
[j
];
3266 GLchan (*dst
)[4] = ccolor
[j
];
3267 argA
[j
] = (const GLchan (*)[4]) ccolor
[j
];
3268 for (i
= 0; i
< n
; i
++) {
3269 dst
[i
][ACOMP
] = CHAN_MAX
- src
[i
][ACOMP
];
3275 * Do the texture combine.
3277 switch (textureUnit
->CombineModeRGB
) {
3280 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3282 for (i
= 0; i
< n
; i
++) {
3283 #if CHAN_TYPE == GL_FLOAT
3284 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * RGBmult
;
3285 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * RGBmult
;
3286 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * RGBmult
;
3288 GLuint r
= (GLuint
) arg0
[i
][RCOMP
] << RGBshift
;
3289 GLuint g
= (GLuint
) arg0
[i
][GCOMP
] << RGBshift
;
3290 GLuint b
= (GLuint
) arg0
[i
][BCOMP
] << RGBshift
;
3291 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
3292 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
3293 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
3298 for (i
= 0; i
< n
; i
++) {
3299 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
];
3300 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
];
3301 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
];
3308 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3309 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3310 #if CHAN_TYPE != GL_FLOAT
3311 const GLint shift
= CHAN_BITS
- RGBshift
;
3313 for (i
= 0; i
< n
; i
++) {
3314 #if CHAN_TYPE == GL_FLOAT
3315 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * RGBmult
;
3316 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * RGBmult
;
3317 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * RGBmult
;
3319 GLuint r
= PROD(arg0
[i
][RCOMP
], arg1
[i
][RCOMP
]) >> shift
;
3320 GLuint g
= PROD(arg0
[i
][GCOMP
], arg1
[i
][GCOMP
]) >> shift
;
3321 GLuint b
= PROD(arg0
[i
][BCOMP
], arg1
[i
][BCOMP
]) >> shift
;
3322 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3323 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3324 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3331 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3332 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3333 for (i
= 0; i
< n
; i
++) {
3334 #if CHAN_TYPE == GL_FLOAT
3335 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * RGBmult
;
3336 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * RGBmult
;
3337 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * RGBmult
;
3339 GLint r
= ((GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3340 GLint g
= ((GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3341 GLint b
= ((GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3342 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3343 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3344 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3351 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3352 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3353 for (i
= 0; i
< n
; i
++) {
3354 #if CHAN_TYPE == GL_FLOAT
3355 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3356 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3357 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3359 GLint r
= (GLint
) arg0
[i
][RCOMP
] + (GLint
) arg1
[i
][RCOMP
] -half
;
3360 GLint g
= (GLint
) arg0
[i
][GCOMP
] + (GLint
) arg1
[i
][GCOMP
] -half
;
3361 GLint b
= (GLint
) arg0
[i
][BCOMP
] + (GLint
) arg1
[i
][BCOMP
] -half
;
3362 r
= (r
< 0) ? 0 : r
<< RGBshift
;
3363 g
= (g
< 0) ? 0 : g
<< RGBshift
;
3364 b
= (b
< 0) ? 0 : b
<< RGBshift
;
3365 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3366 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3367 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3372 case GL_INTERPOLATE
:
3374 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3375 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3376 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3377 #if CHAN_TYPE != GL_FLOAT
3378 const GLint shift
= CHAN_BITS
- RGBshift
;
3380 for (i
= 0; i
< n
; i
++) {
3381 #if CHAN_TYPE == GL_FLOAT
3382 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
3383 arg1
[i
][RCOMP
] * (CHAN_MAXF
- arg2
[i
][RCOMP
])) * RGBmult
;
3384 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
3385 arg1
[i
][GCOMP
] * (CHAN_MAXF
- arg2
[i
][GCOMP
])) * RGBmult
;
3386 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
3387 arg1
[i
][BCOMP
] * (CHAN_MAXF
- arg2
[i
][BCOMP
])) * RGBmult
;
3389 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3390 + PROD(arg1
[i
][RCOMP
], CHAN_MAX
- arg2
[i
][RCOMP
]))
3392 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3393 + PROD(arg1
[i
][GCOMP
], CHAN_MAX
- arg2
[i
][GCOMP
]))
3395 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3396 + PROD(arg1
[i
][BCOMP
], CHAN_MAX
- arg2
[i
][BCOMP
]))
3398 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3399 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3400 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3407 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3408 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3409 for (i
= 0; i
< n
; i
++) {
3410 #if CHAN_TYPE == GL_FLOAT
3411 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * RGBmult
;
3412 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * RGBmult
;
3413 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * RGBmult
;
3415 GLint r
= ((GLint
) arg0
[i
][RCOMP
] - (GLint
) arg1
[i
][RCOMP
]) << RGBshift
;
3416 GLint g
= ((GLint
) arg0
[i
][GCOMP
] - (GLint
) arg1
[i
][GCOMP
]) << RGBshift
;
3417 GLint b
= ((GLint
) arg0
[i
][BCOMP
] - (GLint
) arg1
[i
][BCOMP
]) << RGBshift
;
3418 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3419 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3420 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3425 case GL_DOT3_RGB_EXT
:
3426 case GL_DOT3_RGBA_EXT
:
3428 /* Do not scale the result by 1 2 or 4 */
3429 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3430 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3431 for (i
= 0; i
< n
; i
++) {
3432 #if CHAN_TYPE == GL_FLOAT
3433 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3434 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3435 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3437 dot
= CLAMP(dot
, 0.0F
, CHAN_MAXF
);
3439 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3440 (GLint
)arg1
[i
][RCOMP
] - half
) +
3441 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3442 (GLint
)arg1
[i
][GCOMP
] - half
) +
3443 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3444 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3445 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3447 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3454 /* DO scale the result by 1 2 or 4 */
3455 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3456 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3457 for (i
= 0; i
< n
; i
++) {
3458 #if CHAN_TYPE == GL_FLOAT
3459 GLchan dot
= ((arg0
[i
][RCOMP
]-0.5F
) * (arg1
[i
][RCOMP
]-0.5F
) +
3460 (arg0
[i
][GCOMP
]-0.5F
) * (arg1
[i
][GCOMP
]-0.5F
) +
3461 (arg0
[i
][BCOMP
]-0.5F
) * (arg1
[i
][BCOMP
]-0.5F
))
3463 dot
= CLAMP(dot
, 0.0, CHAN_MAXF
);
3465 GLint dot
= (S_PROD((GLint
)arg0
[i
][RCOMP
] - half
,
3466 (GLint
)arg1
[i
][RCOMP
] - half
) +
3467 S_PROD((GLint
)arg0
[i
][GCOMP
] - half
,
3468 (GLint
)arg1
[i
][GCOMP
] - half
) +
3469 S_PROD((GLint
)arg0
[i
][BCOMP
] - half
,
3470 (GLint
)arg1
[i
][BCOMP
] - half
)) >> 6;
3472 dot
= CLAMP(dot
, 0, CHAN_MAX
);
3474 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLchan
) dot
;
3478 case GL_MODULATE_ADD_ATI
:
3480 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3481 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3482 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3483 #if CHAN_TYPE != GL_FLOAT
3484 const GLint shift
= CHAN_BITS
- RGBshift
;
3486 for (i
= 0; i
< n
; i
++) {
3487 #if CHAN_TYPE == GL_FLOAT
3488 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) + arg1
[i
][RCOMP
]) * RGBmult
;
3489 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
]) * RGBmult
;
3490 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
]) * RGBmult
;
3492 GLuint r
= (PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3493 + ((GLuint
) arg1
[i
][RCOMP
] << CHAN_BITS
)) >> shift
;
3494 GLuint g
= (PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3495 + ((GLuint
) arg1
[i
][GCOMP
] << CHAN_BITS
)) >> shift
;
3496 GLuint b
= (PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3497 + ((GLuint
) arg1
[i
][BCOMP
] << CHAN_BITS
)) >> shift
;
3498 rgba
[i
][RCOMP
] = (GLchan
) MIN2(r
, CHAN_MAX
);
3499 rgba
[i
][GCOMP
] = (GLchan
) MIN2(g
, CHAN_MAX
);
3500 rgba
[i
][BCOMP
] = (GLchan
) MIN2(b
, CHAN_MAX
);
3505 case GL_MODULATE_SIGNED_ADD_ATI
:
3507 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3508 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3509 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3510 #if CHAN_TYPE != GL_FLOAT
3511 const GLint shift
= CHAN_BITS
- RGBshift
;
3513 for (i
= 0; i
< n
; i
++) {
3514 #if CHAN_TYPE == GL_FLOAT
3515 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) + arg1
[i
][RCOMP
] - 0.5) * RGBmult
;
3516 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) + arg1
[i
][GCOMP
] - 0.5) * RGBmult
;
3517 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) + arg1
[i
][BCOMP
] - 0.5) * RGBmult
;
3519 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3520 + (((GLint
) arg1
[i
][RCOMP
] - half
) << CHAN_BITS
))
3522 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3523 + (((GLint
) arg1
[i
][GCOMP
] - half
) << CHAN_BITS
))
3525 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3526 + (((GLint
) arg1
[i
][BCOMP
] - half
) << CHAN_BITS
))
3528 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3529 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3530 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3535 case GL_MODULATE_SUBTRACT_ATI
:
3537 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argRGB
[0];
3538 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argRGB
[1];
3539 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argRGB
[2];
3540 #if CHAN_TYPE != GL_FLOAT
3541 const GLint shift
= CHAN_BITS
- RGBshift
;
3543 for (i
= 0; i
< n
; i
++) {
3544 #if CHAN_TYPE == GL_FLOAT
3545 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) - arg1
[i
][RCOMP
]) * RGBmult
;
3546 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) - arg1
[i
][GCOMP
]) * RGBmult
;
3547 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) - arg1
[i
][BCOMP
]) * RGBmult
;
3549 GLint r
= (S_PROD(arg0
[i
][RCOMP
], arg2
[i
][RCOMP
])
3550 - ((GLint
) arg1
[i
][RCOMP
] << CHAN_BITS
))
3552 GLint g
= (S_PROD(arg0
[i
][GCOMP
], arg2
[i
][GCOMP
])
3553 - ((GLint
) arg1
[i
][GCOMP
] << CHAN_BITS
))
3555 GLint b
= (S_PROD(arg0
[i
][BCOMP
], arg2
[i
][BCOMP
])
3556 - ((GLint
) arg1
[i
][BCOMP
] << CHAN_BITS
))
3558 rgba
[i
][RCOMP
] = (GLchan
) CLAMP(r
, 0, CHAN_MAX
);
3559 rgba
[i
][GCOMP
] = (GLchan
) CLAMP(g
, 0, CHAN_MAX
);
3560 rgba
[i
][BCOMP
] = (GLchan
) CLAMP(b
, 0, CHAN_MAX
);
3566 _mesa_problem(ctx
, "invalid combine mode");
3569 switch (textureUnit
->CombineModeA
) {
3572 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3574 for (i
= 0; i
< n
; i
++) {
3575 #if CHAN_TYPE == GL_FLOAT
3576 GLchan a
= arg0
[i
][ACOMP
] * Amult
;
3578 GLuint a
= (GLuint
) arg0
[i
][ACOMP
] << Ashift
;
3580 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3584 for (i
= 0; i
< n
; i
++) {
3585 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
];
3592 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3593 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3594 #if CHAN_TYPE != GL_FLOAT
3595 const GLint shift
= CHAN_BITS
- Ashift
;
3597 for (i
= 0; i
< n
; i
++) {
3598 #if CHAN_TYPE == GL_FLOAT
3599 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * Amult
;
3601 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg1
[i
][ACOMP
]) >> shift
);
3602 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3609 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3610 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3611 for (i
= 0; i
< n
; i
++) {
3612 #if CHAN_TYPE == GL_FLOAT
3613 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * Amult
;
3615 GLint a
= ((GLint
) arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) << Ashift
;
3616 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3623 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3624 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3625 for (i
= 0; i
< n
; i
++) {
3626 #if CHAN_TYPE == GL_FLOAT
3627 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3629 GLint a
= (GLint
) arg0
[i
][ACOMP
] + (GLint
) arg1
[i
][ACOMP
] -half
;
3630 a
= (a
< 0) ? 0 : a
<< Ashift
;
3631 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3636 case GL_INTERPOLATE
:
3638 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3639 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3640 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3641 #if CHAN_TYPE != GL_FLOAT
3642 const GLint shift
= CHAN_BITS
- Ashift
;
3644 for (i
=0; i
<n
; i
++) {
3645 #if CHAN_TYPE == GL_FLOAT
3646 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
3647 arg1
[i
][ACOMP
] * (CHAN_MAXF
- arg2
[i
][ACOMP
]))
3650 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3651 + PROD(arg1
[i
][ACOMP
], CHAN_MAX
- arg2
[i
][ACOMP
]))
3653 rgba
[i
][ACOMP
] = (GLchan
) MIN2(a
, CHAN_MAX
);
3660 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3661 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3662 for (i
= 0; i
< n
; i
++) {
3663 #if CHAN_TYPE == GL_FLOAT
3664 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * Amult
;
3666 GLint a
= ((GLint
) arg0
[i
][ACOMP
] - (GLint
) arg1
[i
][ACOMP
]) << Ashift
;
3667 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3672 case GL_MODULATE_ADD_ATI
:
3674 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3675 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3676 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3677 #if CHAN_TYPE != GL_FLOAT
3678 const GLint shift
= CHAN_BITS
- Ashift
;
3680 for (i
= 0; i
< n
; i
++) {
3681 #if CHAN_TYPE == GL_FLOAT
3682 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
]) * Amult
;
3684 GLuint a
= (PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3685 + ((GLuint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3687 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3692 case GL_MODULATE_SIGNED_ADD_ATI
:
3694 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3695 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3696 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3697 #if CHAN_TYPE != GL_FLOAT
3698 const GLint shift
= CHAN_BITS
- Ashift
;
3700 for (i
= 0; i
< n
; i
++) {
3701 #if CHAN_TYPE == GL_FLOAT
3702 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) + arg1
[i
][ACOMP
] - 0.5F
) * Amult
;
3704 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3705 + (((GLint
) arg1
[i
][ACOMP
] - half
) << CHAN_BITS
))
3707 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3712 case GL_MODULATE_SUBTRACT_ATI
:
3714 const GLchan (*arg0
)[4] = (const GLchan (*)[4]) argA
[0];
3715 const GLchan (*arg1
)[4] = (const GLchan (*)[4]) argA
[1];
3716 const GLchan (*arg2
)[4] = (const GLchan (*)[4]) argA
[2];
3717 #if CHAN_TYPE != GL_FLOAT
3718 const GLint shift
= CHAN_BITS
- Ashift
;
3720 for (i
= 0; i
< n
; i
++) {
3721 #if CHAN_TYPE == GL_FLOAT
3722 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) - arg1
[i
][ACOMP
]) * Amult
;
3724 GLint a
= (S_PROD(arg0
[i
][ACOMP
], arg2
[i
][ACOMP
])
3725 - ((GLint
) arg1
[i
][ACOMP
] << CHAN_BITS
))
3727 rgba
[i
][ACOMP
] = (GLchan
) CLAMP(a
, 0, CHAN_MAX
);
3733 _mesa_problem(ctx
, "invalid combine mode");
3736 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
3737 * This is kind of a kludge. It would have been better if the spec
3738 * were written such that the GL_COMBINE_ALPHA value could be set to
3741 if (textureUnit
->CombineModeRGB
== GL_DOT3_RGBA_EXT
||
3742 textureUnit
->CombineModeRGB
== GL_DOT3_RGBA
) {
3743 for (i
= 0; i
< n
; i
++) {
3744 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
3747 UNDEFARRAY(ccolor
); /* mac 32k limitation */
3753 * Implement NVIDIA's GL_NV_texture_env_combine4 extension when
3754 * texUnit->EnvMode == GL_COMBINE4_NV.
3757 texture_combine4( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
3758 CONST
GLchan (*primary_rgba
)[4],
3759 CONST GLchan
*texelBuffer
,
3767 * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND,
3768 * MODULATE, or DECAL) to an array of fragments.
3769 * Input: textureUnit - pointer to texture unit to apply
3770 * format - base internal texture format
3771 * n - number of fragments
3772 * primary_rgba - primary colors (may alias rgba for single texture)
3773 * texels - array of texel colors
3774 * InOut: rgba - incoming fragment colors modified by texel colors
3775 * according to the texture environment mode.
3778 texture_apply( const GLcontext
*ctx
,
3779 const struct gl_texture_unit
*texUnit
,
3781 CONST GLchan primary_rgba
[][4], CONST GLchan texel
[][4],
3786 GLint Rc
, Gc
, Bc
, Ac
;
3790 ASSERT(texUnit
->_Current
);
3792 baseLevel
= texUnit
->_Current
->BaseLevel
;
3793 ASSERT(texUnit
->_Current
->Image
[baseLevel
]);
3795 format
= texUnit
->_Current
->Image
[baseLevel
]->Format
;
3797 if (format
== GL_COLOR_INDEX
|| format
== GL_DEPTH_COMPONENT
3798 || format
== GL_YCBCR_MESA
) {
3799 format
= GL_RGBA
; /* a bit of a hack */
3802 switch (texUnit
->EnvMode
) {
3809 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3815 GLchan Lt
= texel
[i
][RCOMP
];
3816 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3820 case GL_LUMINANCE_ALPHA
:
3822 GLchan Lt
= texel
[i
][RCOMP
];
3824 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
3826 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3832 GLchan It
= texel
[i
][RCOMP
];
3833 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
3835 rgba
[i
][ACOMP
] = It
;
3841 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3842 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3843 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3850 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3851 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3852 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3854 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
3858 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in texture_apply");
3869 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3875 GLchan Lt
= texel
[i
][RCOMP
];
3876 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3877 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3878 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3882 case GL_LUMINANCE_ALPHA
:
3885 GLchan Lt
= texel
[i
][RCOMP
];
3886 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], Lt
);
3887 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], Lt
);
3888 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], Lt
);
3890 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3896 GLchan It
= texel
[i
][RCOMP
];
3897 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], It
);
3898 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], It
);
3899 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], It
);
3901 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], It
);
3907 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3908 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3909 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3916 rgba
[i
][RCOMP
] = CHAN_PRODUCT( rgba
[i
][RCOMP
], texel
[i
][RCOMP
] );
3917 rgba
[i
][GCOMP
] = CHAN_PRODUCT( rgba
[i
][GCOMP
], texel
[i
][GCOMP
] );
3918 rgba
[i
][BCOMP
] = CHAN_PRODUCT( rgba
[i
][BCOMP
], texel
[i
][BCOMP
] );
3920 rgba
[i
][ACOMP
] = CHAN_PRODUCT( rgba
[i
][ACOMP
], texel
[i
][ACOMP
] );
3924 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in texture_apply");
3933 case GL_LUMINANCE_ALPHA
:
3940 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
3941 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
3942 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
3948 /* Cv = Cf(1-At) + CtAt */
3949 GLint t
= texel
[i
][ACOMP
], s
= CHAN_MAX
- t
;
3950 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(texel
[i
][RCOMP
],t
);
3951 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(texel
[i
][GCOMP
],t
);
3952 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(texel
[i
][BCOMP
],t
);
3957 _mesa_problem(ctx
, "Bad format (GL_DECAL) in texture_apply");
3963 Rc
= (GLint
) (texUnit
->EnvColor
[0] * CHAN_MAXF
);
3964 Gc
= (GLint
) (texUnit
->EnvColor
[1] * CHAN_MAXF
);
3965 Bc
= (GLint
) (texUnit
->EnvColor
[2] * CHAN_MAXF
);
3966 Ac
= (GLint
) (texUnit
->EnvColor
[3] * CHAN_MAXF
);
3972 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
3977 /* Cv = Cf(1-Lt) + CcLt */
3978 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3979 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3980 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3981 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3985 case GL_LUMINANCE_ALPHA
:
3987 /* Cv = Cf(1-Lt) + CcLt */
3988 GLchan Lt
= texel
[i
][RCOMP
], s
= CHAN_MAX
- Lt
;
3989 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, Lt
);
3990 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, Lt
);
3991 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, Lt
);
3993 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
3998 /* Cv = Cf(1-It) + CcLt */
3999 GLchan It
= texel
[i
][RCOMP
], s
= CHAN_MAX
- It
;
4000 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], s
) + CHAN_PRODUCT(Rc
, It
);
4001 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], s
) + CHAN_PRODUCT(Gc
, It
);
4002 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], s
) + CHAN_PRODUCT(Bc
, It
);
4003 /* Av = Af(1-It) + Ac*It */
4004 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], s
) + CHAN_PRODUCT(Ac
, It
);
4009 /* Cv = Cf(1-Ct) + CcCt */
4010 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
4011 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
4012 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
4018 /* Cv = Cf(1-Ct) + CcCt */
4019 rgba
[i
][RCOMP
] = CHAN_PRODUCT(rgba
[i
][RCOMP
], (CHAN_MAX
-texel
[i
][RCOMP
])) + CHAN_PRODUCT(Rc
,texel
[i
][RCOMP
]);
4020 rgba
[i
][GCOMP
] = CHAN_PRODUCT(rgba
[i
][GCOMP
], (CHAN_MAX
-texel
[i
][GCOMP
])) + CHAN_PRODUCT(Gc
,texel
[i
][GCOMP
]);
4021 rgba
[i
][BCOMP
] = CHAN_PRODUCT(rgba
[i
][BCOMP
], (CHAN_MAX
-texel
[i
][BCOMP
])) + CHAN_PRODUCT(Bc
,texel
[i
][BCOMP
]);
4023 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
],texel
[i
][ACOMP
]);
4027 _mesa_problem(ctx
, "Bad format (GL_BLEND) in texture_apply");
4032 /* XXX don't clamp results if GLchan is float??? */
4034 case GL_ADD
: /* GL_EXT_texture_add_env */
4041 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4046 GLuint Lt
= texel
[i
][RCOMP
];
4047 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
4048 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
4049 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
4050 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4051 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4052 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4056 case GL_LUMINANCE_ALPHA
:
4058 GLuint Lt
= texel
[i
][RCOMP
];
4059 GLuint r
= rgba
[i
][RCOMP
] + Lt
;
4060 GLuint g
= rgba
[i
][GCOMP
] + Lt
;
4061 GLuint b
= rgba
[i
][BCOMP
] + Lt
;
4062 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4063 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4064 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4065 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4070 GLchan It
= texel
[i
][RCOMP
];
4071 GLuint r
= rgba
[i
][RCOMP
] + It
;
4072 GLuint g
= rgba
[i
][GCOMP
] + It
;
4073 GLuint b
= rgba
[i
][BCOMP
] + It
;
4074 GLuint a
= rgba
[i
][ACOMP
] + It
;
4075 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4076 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4077 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4078 rgba
[i
][ACOMP
] = MIN2(a
, CHAN_MAX
);
4083 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
4084 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
4085 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
4086 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4087 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4088 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4094 GLuint r
= rgba
[i
][RCOMP
] + texel
[i
][RCOMP
];
4095 GLuint g
= rgba
[i
][GCOMP
] + texel
[i
][GCOMP
];
4096 GLuint b
= rgba
[i
][BCOMP
] + texel
[i
][BCOMP
];
4097 rgba
[i
][RCOMP
] = MIN2(r
, CHAN_MAX
);
4098 rgba
[i
][GCOMP
] = MIN2(g
, CHAN_MAX
);
4099 rgba
[i
][BCOMP
] = MIN2(b
, CHAN_MAX
);
4100 rgba
[i
][ACOMP
] = CHAN_PRODUCT(rgba
[i
][ACOMP
], texel
[i
][ACOMP
]);
4104 _mesa_problem(ctx
, "Bad format (GL_ADD) in texture_apply");
4110 _mesa_problem(ctx
, "Bad env mode in texture_apply");
4118 * Apply texture mapping to a span of fragments.
4121 _swrast_texture_span( GLcontext
*ctx
, struct sw_span
*span
)
4123 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
4124 GLchan primary_rgba
[MAX_WIDTH
][4];
4127 ASSERT(span
->end
< MAX_WIDTH
);
4128 ASSERT(span
->arrayMask
& SPAN_TEXTURE
);
4131 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
4133 if (swrast
->_AnyTextureCombine
)
4134 MEMCPY(primary_rgba
, span
->array
->rgba
, 4 * span
->end
* sizeof(GLchan
));
4137 * Must do all texture sampling before combining in order to
4138 * accomodate GL_ARB_texture_env_crossbar.
4140 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
4141 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
4142 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
4143 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
4144 GLfloat
*lambda
= span
->array
->lambda
[unit
];
4145 GLchan (*texels
)[4] = (GLchan (*)[4])
4146 (swrast
->TexelBuffer
+ unit
* (span
->end
* 4 * sizeof(GLchan
)));
4148 /* adjust texture lod (lambda) */
4149 if (span
->arrayMask
& SPAN_LAMBDA
) {
4150 if (texUnit
->LodBias
!= 0.0F
) {
4151 /* apply LOD bias, but don't clamp yet */
4153 for (i
= 0; i
< span
->end
; i
++) {
4154 lambda
[i
] += texUnit
->LodBias
;
4158 if (curObj
->MinLod
!= -1000.0 || curObj
->MaxLod
!= 1000.0) {
4159 /* apply LOD clamping to lambda */
4160 const GLfloat min
= curObj
->MinLod
;
4161 const GLfloat max
= curObj
->MaxLod
;
4163 for (i
= 0; i
< span
->end
; i
++) {
4164 GLfloat l
= lambda
[i
];
4165 lambda
[i
] = CLAMP(l
, min
, max
);
4170 /* Sample the texture (span->end fragments) */
4171 swrast
->TextureSample
[unit
]( ctx
, unit
, texUnit
->_Current
, span
->end
,
4172 (const GLfloat (*)[4]) span
->array
->texcoords
[unit
],
4174 /* GL_SGI_texture_color_table */
4175 if (texUnit
->ColorTableEnabled
) {
4176 _swrast_texture_table_lookup(&texUnit
->ColorTable
, span
->end
, texels
);
4182 * OK, now apply the texture (aka texture combine/blend).
4183 * We modify the span->color.rgba values.
4185 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
4186 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
4187 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
4188 if (texUnit
->EnvMode
== GL_COMBINE
) {
4189 /* GL_ARB/EXT_texture_env_combine */
4190 texture_combine( ctx
, unit
, span
->end
,
4191 (CONST
GLchan (*)[4]) primary_rgba
,
4192 swrast
->TexelBuffer
,
4193 span
->array
->rgba
);
4195 else if (texUnit
->EnvMode
== GL_COMBINE4_NV
) {
4196 /* GL_NV_texture_env_combine4 */
4197 texture_combine4( ctx
, unit
, span
->end
,
4198 (CONST
GLchan (*)[4]) primary_rgba
,
4199 swrast
->TexelBuffer
,
4200 span
->array
->rgba
);
4203 /* conventional texture blend */
4204 const GLchan (*texels
)[4] = (const GLchan (*)[4])
4205 (swrast
->TexelBuffer
+ unit
*
4206 (span
->end
* 4 * sizeof(GLchan
)));
4207 texture_apply( ctx
, texUnit
, span
->end
,
4208 (CONST
GLchan (*)[4]) primary_rgba
, texels
,
4209 span
->array
->rgba
);