fixed Min/Max lod clamp bug
[mesa.git] / src / mesa / swrast / s_texture.c
1 /* $Id: s_texture.c,v 1.19 2001/03/23 18:53:26 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
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.
25 */
26
27
28 #include "glheader.h"
29 #include "context.h"
30 #include "colormac.h"
31 #include "macros.h"
32 #include "mmath.h"
33 #include "mem.h"
34 #include "teximage.h"
35
36 #include "s_context.h"
37 #include "s_pb.h"
38 #include "s_texture.h"
39
40
41 /* XXX this is temporary, until GL/glext.h is updated. */
42 #ifndef GL_DOT3_RGB_ARB
43 #define GL_DOT3_RGB_ARB 0x86AE
44 #endif
45 #ifndef GL_DOT3_RGBA_ARB
46 #define GL_DOT3_RGBA_ARB 0x86AF
47 #endif
48
49
50 /*
51 * These values are used in the fixed-point arithmetic used
52 * for linear filtering.
53 */
54 #define WEIGHT_SCALE 65536.0F
55 #define WEIGHT_SHIFT 16
56
57
58 /*
59 * Used to compute texel locations for linear sampling.
60 * Input:
61 * wrapMode = GL_REPEAT, GL_CLAMP or GL_CLAMP_TO_EDGE
62 * S = texcoord in [0,1]
63 * SIZE = width (or height or depth) of texture
64 * Output:
65 * U = texcoord in [0, width]
66 * I0, I1 = two nearest texel indexes
67 */
68 #define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1) \
69 { \
70 if (wrapMode == GL_REPEAT) { \
71 U = S * SIZE - 0.5F; \
72 I0 = IFLOOR(U) & (SIZE - 1); \
73 I1 = (I0 + 1) & (SIZE - 1); \
74 } \
75 else { \
76 if (S <= 0.0F) \
77 U = 0.0F; \
78 else if (S >= 1.0F) \
79 U = SIZE; \
80 else \
81 U = S * SIZE; \
82 U -= 0.5F; \
83 I0 = IFLOOR(U); \
84 I1 = I0 + 1; \
85 if (wrapMode == GL_CLAMP_TO_EDGE) { \
86 if (I0 < 0) \
87 I0 = 0; \
88 if (I1 >= (GLint) SIZE) \
89 I1 = SIZE - 1; \
90 } \
91 } \
92 }
93
94
95 /*
96 * Used to compute texel location for nearest sampling.
97 */
98 #define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I) \
99 { \
100 if (wrapMode == GL_REPEAT) { \
101 /* s limited to [0,1) */ \
102 /* i limited to [0,width-1] */ \
103 I = (GLint) (S * SIZE); \
104 if (S < 0.0F) \
105 I -= 1; \
106 I &= (SIZE - 1); \
107 } \
108 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
109 const GLfloat min = 1.0F / (2.0F * SIZE); \
110 const GLfloat max = 1.0F - min; \
111 if (S < min) \
112 I = 0; \
113 else if (S > max) \
114 I = SIZE - 1; \
115 else \
116 I = (GLint) (S * SIZE); \
117 } \
118 else { \
119 ASSERT(wrapMode == GL_CLAMP); \
120 /* s limited to [0,1] */ \
121 /* i limited to [0,width-1] */ \
122 if (S <= 0.0F) \
123 I = 0; \
124 else if (S >= 1.0F) \
125 I = SIZE - 1; \
126 else \
127 I = (GLint) (S * SIZE); \
128 } \
129 }
130
131
132 /*
133 * Compute linear mipmap levels for given lambda.
134 */
135 #define COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level) \
136 { \
137 if (lambda < 0.0F) \
138 lambda = 0.0F; \
139 else if (lambda > tObj->_MaxLambda) \
140 lambda = tObj->_MaxLambda; \
141 level = (GLint) (tObj->BaseLevel + lambda); \
142 }
143
144
145 /*
146 * Compute nearest mipmap level for given lambda.
147 */
148 #define COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level) \
149 { \
150 if (lambda <= 0.5F) \
151 lambda = 0.0F; \
152 else if (lambda > tObj->_MaxLambda + 0.4999F) \
153 lambda = tObj->_MaxLambda + 0.4999F; \
154 level = (GLint) (tObj->BaseLevel + lambda + 0.5F); \
155 if (level > tObj->_MaxLevel) \
156 level = tObj->_MaxLevel; \
157 }
158
159
160
161
162 /*
163 * Bitflags for texture border color sampling.
164 */
165 #define I0BIT 1
166 #define I1BIT 2
167 #define J0BIT 4
168 #define J1BIT 8
169 #define K0BIT 16
170 #define K1BIT 32
171
172
173
174 /*
175 * Get texture palette entry.
176 */
177 static void
178 palette_sample(const GLcontext *ctx,
179 const struct gl_texture_object *tObj,
180 GLint index, GLchan rgba[4] )
181 {
182 const GLchan *palette;
183 GLenum format;
184
185 if (ctx->Texture.SharedPalette) {
186 ASSERT(!ctx->Texture.Palette.FloatTable);
187 palette = (const GLchan *) ctx->Texture.Palette.Table;
188 format = ctx->Texture.Palette.Format;
189 }
190 else {
191 ASSERT(!tObj->Palette.FloatTable);
192 palette = (const GLchan *) tObj->Palette.Table;
193 format = tObj->Palette.Format;
194 }
195
196 switch (format) {
197 case GL_ALPHA:
198 rgba[ACOMP] = palette[index];
199 return;
200 case GL_LUMINANCE:
201 case GL_INTENSITY:
202 rgba[RCOMP] = palette[index];
203 return;
204 case GL_LUMINANCE_ALPHA:
205 rgba[RCOMP] = palette[(index << 1) + 0];
206 rgba[ACOMP] = palette[(index << 1) + 1];
207 return;
208 case GL_RGB:
209 rgba[RCOMP] = palette[index * 3 + 0];
210 rgba[GCOMP] = palette[index * 3 + 1];
211 rgba[BCOMP] = palette[index * 3 + 2];
212 return;
213 case GL_RGBA:
214 rgba[RCOMP] = palette[(index << 2) + 0];
215 rgba[GCOMP] = palette[(index << 2) + 1];
216 rgba[BCOMP] = palette[(index << 2) + 2];
217 rgba[ACOMP] = palette[(index << 2) + 3];
218 return;
219 default:
220 _mesa_problem(ctx, "Bad palette format in palette_sample");
221 }
222 }
223
224
225
226 /**********************************************************************/
227 /* 1-D Texture Sampling Functions */
228 /**********************************************************************/
229
230 /*
231 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
232 */
233 static void
234 sample_1d_nearest(GLcontext *ctx,
235 const struct gl_texture_object *tObj,
236 const struct gl_texture_image *img,
237 GLfloat s, GLchan rgba[4])
238 {
239 const GLint width = img->Width2; /* without border, power of two */
240 GLint i;
241
242 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, s, width, i);
243
244 /* skip over the border, if any */
245 i += img->Border;
246
247 (*img->FetchTexel)(img, i, 0, 0, (GLvoid *) rgba);
248 if (img->Format == GL_COLOR_INDEX) {
249 palette_sample(ctx, tObj, rgba[0], rgba);
250 }
251 }
252
253
254
255 /*
256 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
257 */
258 static void
259 sample_1d_linear(GLcontext *ctx,
260 const struct gl_texture_object *tObj,
261 const struct gl_texture_image *img,
262 GLfloat s, GLchan rgba[4])
263 {
264 const GLint width = img->Width2;
265 GLint i0, i1;
266 GLfloat u;
267 GLuint useBorderColor;
268
269 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, s, u, width, i0, i1);
270
271 useBorderColor = 0;
272 if (img->Border) {
273 i0 += img->Border;
274 i1 += img->Border;
275 }
276 else {
277 if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
278 if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
279 }
280
281 {
282 const GLfloat a = FRAC(u);
283 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
284 const GLint w0 = IROUND((1.0F-a) * WEIGHT_SCALE);
285 const GLint w1 = IROUND( a * WEIGHT_SCALE);
286
287 GLchan t0[4], t1[4]; /* texels */
288
289 if (useBorderColor & I0BIT) {
290 COPY_CHAN4(t0, tObj->BorderColor);
291 }
292 else {
293 (*img->FetchTexel)(img, i0, 0, 0, (GLvoid *) t0);
294 if (img->Format == GL_COLOR_INDEX) {
295 palette_sample(ctx, tObj, t0[0], t0);
296 }
297 }
298 if (useBorderColor & I1BIT) {
299 COPY_CHAN4(t1, tObj->BorderColor);
300 }
301 else {
302 (*img->FetchTexel)(img, i1, 0, 0, (GLvoid *) t1);
303 if (img->Format == GL_COLOR_INDEX) {
304 palette_sample(ctx, tObj, t1[0], t1);
305 }
306 }
307
308 rgba[0] = (GLchan) ((w0 * t0[0] + w1 * t1[0]) >> WEIGHT_SHIFT);
309 rgba[1] = (GLchan) ((w0 * t0[1] + w1 * t1[1]) >> WEIGHT_SHIFT);
310 rgba[2] = (GLchan) ((w0 * t0[2] + w1 * t1[2]) >> WEIGHT_SHIFT);
311 rgba[3] = (GLchan) ((w0 * t0[3] + w1 * t1[3]) >> WEIGHT_SHIFT);
312 }
313 }
314
315
316 static void
317 sample_1d_nearest_mipmap_nearest(GLcontext *ctx,
318 const struct gl_texture_object *tObj,
319 GLfloat s, GLfloat lambda,
320 GLchan rgba[4])
321 {
322 GLint level;
323 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level);
324 sample_1d_nearest(ctx, tObj, tObj->Image[level], s, rgba);
325 }
326
327
328 static void
329 sample_1d_linear_mipmap_nearest(GLcontext *ctx,
330 const struct gl_texture_object *tObj,
331 GLfloat s, GLfloat lambda,
332 GLchan rgba[4])
333 {
334 GLint level;
335 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level);
336 sample_1d_linear(ctx, tObj, tObj->Image[level], s, rgba);
337 }
338
339
340
341 static void
342 sample_1d_nearest_mipmap_linear(GLcontext *ctx,
343 const struct gl_texture_object *tObj,
344 GLfloat s, GLfloat lambda,
345 GLchan rgba[4])
346 {
347 GLint level;
348
349 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level);
350
351 if (level >= tObj->_MaxLevel) {
352 sample_1d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel], s, rgba);
353 }
354 else {
355 GLchan t0[4], t1[4];
356 const GLfloat f = FRAC(lambda);
357 sample_1d_nearest(ctx, tObj, tObj->Image[level ], s, t0);
358 sample_1d_nearest(ctx, tObj, tObj->Image[level+1], s, t1);
359 rgba[RCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
360 rgba[GCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
361 rgba[BCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
362 rgba[ACOMP] = (GLchan) (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
363 }
364 }
365
366
367
368 static void
369 sample_1d_linear_mipmap_linear(GLcontext *ctx,
370 const struct gl_texture_object *tObj,
371 GLfloat s, GLfloat lambda,
372 GLchan rgba[4])
373 {
374 GLint level;
375
376 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level);
377
378 if (level >= tObj->_MaxLevel) {
379 sample_1d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel], s, rgba);
380 }
381 else {
382 GLchan t0[4], t1[4];
383 const GLfloat f = FRAC(lambda);
384 sample_1d_linear(ctx, tObj, tObj->Image[level ], s, t0);
385 sample_1d_linear(ctx, tObj, tObj->Image[level+1], s, t1);
386 rgba[RCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
387 rgba[GCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
388 rgba[BCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
389 rgba[ACOMP] = (GLchan) (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
390 }
391 }
392
393
394
395 static void
396 sample_nearest_1d( GLcontext *ctx, GLuint texUnit,
397 const struct gl_texture_object *tObj, GLuint n,
398 const GLfloat s[], const GLfloat t[],
399 const GLfloat u[], const GLfloat lambda[],
400 GLchan rgba[][4] )
401 {
402 GLuint i;
403 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
404 (void) t;
405 (void) u;
406 (void) lambda;
407 for (i=0;i<n;i++) {
408 sample_1d_nearest(ctx, tObj, image, s[i], rgba[i]);
409 }
410 }
411
412
413
414 static void
415 sample_linear_1d( GLcontext *ctx, GLuint texUnit,
416 const struct gl_texture_object *tObj, GLuint n,
417 const GLfloat s[], const GLfloat t[],
418 const GLfloat u[], const GLfloat lambda[],
419 GLchan rgba[][4] )
420 {
421 GLuint i;
422 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
423 (void) t;
424 (void) u;
425 (void) lambda;
426 for (i=0;i<n;i++) {
427 sample_1d_linear(ctx, tObj, image, s[i], rgba[i]);
428 }
429 }
430
431
432 /*
433 * Given an (s) texture coordinate and lambda (level of detail) value,
434 * return a texture sample.
435 *
436 */
437 static void
438 sample_lambda_1d( GLcontext *ctx, GLuint texUnit,
439 const struct gl_texture_object *tObj, GLuint n,
440 const GLfloat s[], const GLfloat t[],
441 const GLfloat u[], const GLfloat lambda[],
442 GLchan rgba[][4] )
443 {
444 GLfloat MinMagThresh = SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit];
445 GLuint i;
446
447 (void) t;
448 (void) u;
449
450 for (i=0;i<n;i++) {
451 if (lambda[i] > MinMagThresh) {
452 /* minification */
453 switch (tObj->MinFilter) {
454 case GL_NEAREST:
455 sample_1d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
456 s[i], rgba[i]);
457 break;
458 case GL_LINEAR:
459 sample_1d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
460 s[i], rgba[i]);
461 break;
462 case GL_NEAREST_MIPMAP_NEAREST:
463 sample_1d_nearest_mipmap_nearest(ctx, tObj, lambda[i], s[i],
464 rgba[i]);
465 break;
466 case GL_LINEAR_MIPMAP_NEAREST:
467 sample_1d_linear_mipmap_nearest(ctx, tObj, s[i], lambda[i],
468 rgba[i]);
469 break;
470 case GL_NEAREST_MIPMAP_LINEAR:
471 sample_1d_nearest_mipmap_linear(ctx, tObj, s[i], lambda[i],
472 rgba[i]);
473 break;
474 case GL_LINEAR_MIPMAP_LINEAR:
475 sample_1d_linear_mipmap_linear(ctx, tObj, s[i], lambda[i],
476 rgba[i]);
477 break;
478 default:
479 _mesa_problem(NULL, "Bad min filter in sample_1d_texture");
480 return;
481 }
482 }
483 else {
484 /* magnification */
485 switch (tObj->MagFilter) {
486 case GL_NEAREST:
487 sample_1d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
488 s[i], rgba[i]);
489 break;
490 case GL_LINEAR:
491 sample_1d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
492 s[i], rgba[i]);
493 break;
494 default:
495 _mesa_problem(NULL, "Bad mag filter in sample_1d_texture");
496 return;
497 }
498 }
499 }
500 }
501
502
503
504
505 /**********************************************************************/
506 /* 2-D Texture Sampling Functions */
507 /**********************************************************************/
508
509
510 /*
511 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
512 */
513 static void
514 sample_2d_nearest(GLcontext *ctx,
515 const struct gl_texture_object *tObj,
516 const struct gl_texture_image *img,
517 GLfloat s, GLfloat t,
518 GLchan rgba[])
519 {
520 const GLint width = img->Width2; /* without border, power of two */
521 const GLint height = img->Height2; /* without border, power of two */
522 GLint i, j;
523
524 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, s, width, i);
525 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, t, height, j);
526
527 /* skip over the border, if any */
528 i += img->Border;
529 j += img->Border;
530
531 (*img->FetchTexel)(img, i, j, 0, (GLvoid *) rgba);
532 if (img->Format == GL_COLOR_INDEX) {
533 palette_sample(ctx, tObj, rgba[0], rgba);
534 }
535 }
536
537
538
539 /*
540 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
541 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
542 */
543 static void
544 sample_2d_linear(GLcontext *ctx,
545 const struct gl_texture_object *tObj,
546 const struct gl_texture_image *img,
547 GLfloat s, GLfloat t,
548 GLchan rgba[])
549 {
550 const GLint width = img->Width2;
551 const GLint height = img->Height2;
552 GLint i0, j0, i1, j1;
553 GLuint useBorderColor;
554 GLfloat u, v;
555
556 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, s, u, width, i0, i1);
557 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, t, v, height, j0, j1);
558
559 useBorderColor = 0;
560 if (img->Border) {
561 i0 += img->Border;
562 i1 += img->Border;
563 j0 += img->Border;
564 j1 += img->Border;
565 }
566 else {
567 if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
568 if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
569 if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT;
570 if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT;
571 }
572
573 {
574 const GLfloat a = FRAC(u);
575 const GLfloat b = FRAC(v);
576 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
577 const GLint w00 = IROUND((1.0F-a) * (1.0F-b) * WEIGHT_SCALE);
578 const GLint w10 = IROUND( a * (1.0F-b) * WEIGHT_SCALE);
579 const GLint w01 = IROUND((1.0F-a) * b * WEIGHT_SCALE);
580 const GLint w11 = IROUND( a * b * WEIGHT_SCALE);
581 GLchan t00[4];
582 GLchan t10[4];
583 GLchan t01[4];
584 GLchan t11[4];
585
586 if (useBorderColor & (I0BIT | J0BIT)) {
587 COPY_CHAN4(t00, tObj->BorderColor);
588 }
589 else {
590 (*img->FetchTexel)(img, i0, j0, 0, (GLvoid *) t00);
591 if (img->Format == GL_COLOR_INDEX) {
592 palette_sample(ctx, tObj, t00[0], t00);
593 }
594 }
595 if (useBorderColor & (I1BIT | J0BIT)) {
596 COPY_CHAN4(t10, tObj->BorderColor);
597 }
598 else {
599 (*img->FetchTexel)(img, i1, j0, 0, (GLvoid *) t10);
600 if (img->Format == GL_COLOR_INDEX) {
601 palette_sample(ctx, tObj, t10[0], t10);
602 }
603 }
604 if (useBorderColor & (I0BIT | J1BIT)) {
605 COPY_CHAN4(t01, tObj->BorderColor);
606 }
607 else {
608 (*img->FetchTexel)(img, i0, j1, 0, (GLvoid *) t01);
609 if (img->Format == GL_COLOR_INDEX) {
610 palette_sample(ctx, tObj, t01[0], t01);
611 }
612 }
613 if (useBorderColor & (I1BIT | J1BIT)) {
614 COPY_CHAN4(t11, tObj->BorderColor);
615 }
616 else {
617 (*img->FetchTexel)(img, i1, j1, 0, (GLvoid *) t11);
618 if (img->Format == GL_COLOR_INDEX) {
619 palette_sample(ctx, tObj, t11[0], t11);
620 }
621 }
622
623 rgba[0] = (GLchan) ((w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0]) >> WEIGHT_SHIFT);
624 rgba[1] = (GLchan) ((w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1]) >> WEIGHT_SHIFT);
625 rgba[2] = (GLchan) ((w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2]) >> WEIGHT_SHIFT);
626 rgba[3] = (GLchan) ((w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3]) >> WEIGHT_SHIFT);
627 }
628
629 }
630
631
632
633 static void
634 sample_2d_nearest_mipmap_nearest(GLcontext *ctx,
635 const struct gl_texture_object *tObj,
636 GLfloat s, GLfloat t, GLfloat lambda,
637 GLchan rgba[4])
638 {
639 GLint level;
640 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level);
641 sample_2d_nearest(ctx, tObj, tObj->Image[level], s, t, rgba);
642 }
643
644
645
646 static void
647 sample_2d_linear_mipmap_nearest(GLcontext *ctx,
648 const struct gl_texture_object *tObj,
649 GLfloat s, GLfloat t, GLfloat lambda,
650 GLchan rgba[4])
651 {
652 GLint level;
653 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level);
654 sample_2d_linear(ctx, tObj, tObj->Image[level], s, t, rgba);
655 }
656
657
658
659 static void
660 sample_2d_nearest_mipmap_linear(GLcontext *ctx,
661 const struct gl_texture_object *tObj,
662 GLfloat s, GLfloat t, GLfloat lambda,
663 GLchan rgba[4])
664 {
665 GLint level;
666
667 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level);
668
669 if (level >= tObj->_MaxLevel) {
670 sample_2d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel], s, t, rgba);
671 }
672 else {
673 GLchan t0[4], t1[4]; /* texels */
674 const GLfloat f = FRAC(lambda);
675 sample_2d_nearest(ctx, tObj, tObj->Image[level ], s, t, t0);
676 sample_2d_nearest(ctx, tObj, tObj->Image[level+1], s, t, t1);
677 rgba[RCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
678 rgba[GCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
679 rgba[BCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
680 rgba[ACOMP] = (GLchan) (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
681 }
682 }
683
684
685
686 static void
687 sample_2d_linear_mipmap_linear(GLcontext *ctx,
688 const struct gl_texture_object *tObj,
689 GLfloat s, GLfloat t, GLfloat lambda,
690 GLchan rgba[4])
691 {
692 GLint level;
693
694 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level);
695
696 if (level >= tObj->_MaxLevel) {
697 sample_2d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel], s, t, rgba);
698 }
699 else {
700 GLchan t0[4], t1[4]; /* texels */
701 const GLfloat f = FRAC(lambda);
702 sample_2d_linear(ctx, tObj, tObj->Image[level ], s, t, t0);
703 sample_2d_linear(ctx, tObj, tObj->Image[level+1], s, t, t1);
704 rgba[RCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
705 rgba[GCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
706 rgba[BCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
707 rgba[ACOMP] = (GLchan) (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
708 }
709 }
710
711
712
713 static void
714 sample_nearest_2d( GLcontext *ctx, GLuint texUnit,
715 const struct gl_texture_object *tObj, GLuint n,
716 const GLfloat s[], const GLfloat t[],
717 const GLfloat u[], const GLfloat lambda[],
718 GLchan rgba[][4] )
719 {
720 GLuint i;
721 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
722 (void) u;
723 (void) lambda;
724 for (i=0;i<n;i++) {
725 sample_2d_nearest(ctx, tObj, image, s[i], t[i], rgba[i]);
726 }
727 }
728
729
730
731 static void
732 sample_linear_2d( GLcontext *ctx, GLuint texUnit,
733 const struct gl_texture_object *tObj, GLuint n,
734 const GLfloat s[], const GLfloat t[],
735 const GLfloat u[], const GLfloat lambda[],
736 GLchan rgba[][4] )
737 {
738 GLuint i;
739 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
740 (void) u;
741 (void) lambda;
742 for (i=0;i<n;i++) {
743 sample_2d_linear(ctx, tObj, image, s[i], t[i], rgba[i]);
744 }
745 }
746
747
748 /*
749 * Given an array of (s,t) texture coordinate and lambda (level of detail)
750 * values, return an array of texture sample.
751 */
752 static void
753 sample_lambda_2d( GLcontext *ctx, GLuint texUnit,
754 const struct gl_texture_object *tObj,
755 GLuint n,
756 const GLfloat s[], const GLfloat t[],
757 const GLfloat u[], const GLfloat lambda[],
758 GLchan rgba[][4] )
759 {
760 const GLfloat minMagThresh = SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit];
761 GLuint i;
762 (void) u;
763
764 /* since lambda is monotonous-array use this check first */
765 if (lambda[0] <= minMagThresh && lambda[n-1] <= minMagThresh) {
766 /* magnification for whole span */
767 switch (tObj->MagFilter) {
768 case GL_NEAREST:
769 sample_nearest_2d(ctx, texUnit, tObj, n, s, t, u,
770 lambda, rgba);
771 break;
772 case GL_LINEAR:
773 sample_linear_2d(ctx, texUnit, tObj, n, s, t, u,
774 lambda, rgba);
775 break;
776 default:
777 _mesa_problem(NULL, "Bad mag filter in sample_lambda_2d");
778 }
779 }
780 else {
781 for (i = 0; i < n; i++) {
782 if (lambda[i] > minMagThresh) {
783 /* minification */
784 switch (tObj->MinFilter) {
785 case GL_NEAREST:
786 sample_2d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
787 s[i], t[i], rgba[i]);
788 break;
789 case GL_LINEAR:
790 sample_2d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
791 s[i], t[i], rgba[i]);
792 break;
793 case GL_NEAREST_MIPMAP_NEAREST:
794 sample_2d_nearest_mipmap_nearest(ctx, tObj, s[i], t[i],
795 lambda[i], rgba[i]);
796 break;
797 case GL_LINEAR_MIPMAP_NEAREST:
798 sample_2d_linear_mipmap_nearest(ctx,tObj, s[i], t[i],
799 lambda[i], rgba[i]);
800 break;
801 case GL_NEAREST_MIPMAP_LINEAR:
802 sample_2d_nearest_mipmap_linear(ctx,tObj, s[i], t[i],
803 lambda[i], rgba[i]);
804 break;
805 case GL_LINEAR_MIPMAP_LINEAR:
806 sample_2d_linear_mipmap_linear(ctx,tObj, s[i], t[i],
807 lambda[i], rgba[i] );
808 break;
809 default:
810 _mesa_problem(NULL, "Bad min filter in sample_2d_texture");
811 return;
812 }
813 }
814 else {
815 /* magnification */
816 switch (tObj->MagFilter) {
817 case GL_NEAREST:
818 sample_2d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
819 s[i], t[i], rgba[i]);
820 break;
821 case GL_LINEAR:
822 sample_2d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
823 s[i], t[i], rgba[i] );
824 break;
825 default:
826 _mesa_problem(NULL, "Bad mag filter in sample_2d_texture");
827 }
828 }
829 }
830 }
831 }
832
833
834 /*
835 * Optimized 2-D texture sampling:
836 * S and T wrap mode == GL_REPEAT
837 * GL_NEAREST min/mag filter
838 * No border
839 * Format = GL_RGB
840 */
841 static void
842 opt_sample_rgb_2d( GLcontext *ctx, GLuint texUnit,
843 const struct gl_texture_object *tObj,
844 GLuint n, const GLfloat s[], const GLfloat t[],
845 const GLfloat u[], const GLfloat lambda[],
846 GLchan rgba[][4] )
847 {
848 const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel];
849 const GLfloat width = (GLfloat) img->Width;
850 const GLfloat height = (GLfloat) img->Height;
851 const GLint colMask = img->Width - 1;
852 const GLint rowMask = img->Height - 1;
853 const GLint shift = img->WidthLog2;
854 GLuint k;
855 (void) u;
856 (void) lambda;
857 ASSERT(tObj->WrapS==GL_REPEAT);
858 ASSERT(tObj->WrapT==GL_REPEAT);
859 ASSERT(tObj->MinFilter==GL_NEAREST);
860 ASSERT(tObj->MagFilter==GL_NEAREST);
861 ASSERT(img->Border==0);
862 ASSERT(img->Format==GL_RGB);
863
864 /* NOTE: negative float->int doesn't floor, add 10000 as to work-around */
865 for (k=0;k<n;k++) {
866 GLint i = (GLint) ((s[k] + 10000.0) * width) & colMask;
867 GLint j = (GLint) ((t[k] + 10000.0) * height) & rowMask;
868 GLint pos = (j << shift) | i;
869 GLchan *texel = ((GLchan *) img->Data) + pos + pos + pos; /* pos*3 */
870 rgba[k][RCOMP] = texel[0];
871 rgba[k][GCOMP] = texel[1];
872 rgba[k][BCOMP] = texel[2];
873 }
874 }
875
876
877 /*
878 * Optimized 2-D texture sampling:
879 * S and T wrap mode == GL_REPEAT
880 * GL_NEAREST min/mag filter
881 * No border
882 * Format = GL_RGBA
883 */
884 static void
885 opt_sample_rgba_2d( GLcontext *ctx, GLuint texUnit,
886 const struct gl_texture_object *tObj,
887 GLuint n, const GLfloat s[], const GLfloat t[],
888 const GLfloat u[], const GLfloat lambda[],
889 GLchan rgba[][4] )
890 {
891 const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel];
892 const GLfloat width = (GLfloat) img->Width;
893 const GLfloat height = (GLfloat) img->Height;
894 const GLint colMask = img->Width - 1;
895 const GLint rowMask = img->Height - 1;
896 const GLint shift = img->WidthLog2;
897 GLuint k;
898 (void) u;
899 (void) lambda;
900 ASSERT(tObj->WrapS==GL_REPEAT);
901 ASSERT(tObj->WrapT==GL_REPEAT);
902 ASSERT(tObj->MinFilter==GL_NEAREST);
903 ASSERT(tObj->MagFilter==GL_NEAREST);
904 ASSERT(img->Border==0);
905 ASSERT(img->Format==GL_RGBA);
906
907 /* NOTE: negative float->int doesn't floor, add 10000 as to work-around */
908 for (k=0;k<n;k++) {
909 GLint i = (GLint) ((s[k] + 10000.0) * width) & colMask;
910 GLint j = (GLint) ((t[k] + 10000.0) * height) & rowMask;
911 GLint pos = (j << shift) | i;
912 GLchan *texel = ((GLchan *) img->Data) + (pos << 2); /* pos*4 */
913 rgba[k][RCOMP] = texel[0];
914 rgba[k][GCOMP] = texel[1];
915 rgba[k][BCOMP] = texel[2];
916 rgba[k][ACOMP] = texel[3];
917 }
918 }
919
920
921
922 /**********************************************************************/
923 /* 3-D Texture Sampling Functions */
924 /**********************************************************************/
925
926 /*
927 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
928 */
929 static void
930 sample_3d_nearest(GLcontext *ctx,
931 const struct gl_texture_object *tObj,
932 const struct gl_texture_image *img,
933 GLfloat s, GLfloat t, GLfloat r,
934 GLchan rgba[4])
935 {
936 const GLint width = img->Width2; /* without border, power of two */
937 const GLint height = img->Height2; /* without border, power of two */
938 const GLint depth = img->Depth2; /* without border, power of two */
939 GLint i, j, k;
940
941 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, s, width, i);
942 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, t, height, j);
943 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapR, r, depth, k);
944
945 (*img->FetchTexel)(img, i, j, k, (GLvoid *) rgba);
946 if (img->Format == GL_COLOR_INDEX) {
947 palette_sample(ctx, tObj, rgba[0], rgba);
948 }
949 }
950
951
952
953 /*
954 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
955 */
956 static void
957 sample_3d_linear(GLcontext *ctx,
958 const struct gl_texture_object *tObj,
959 const struct gl_texture_image *img,
960 GLfloat s, GLfloat t, GLfloat r,
961 GLchan rgba[4])
962 {
963 const GLint width = img->Width2;
964 const GLint height = img->Height2;
965 const GLint depth = img->Depth2;
966 GLint i0, j0, k0, i1, j1, k1;
967 GLuint useBorderColor;
968 GLfloat u, v, w;
969
970 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, s, u, width, i0, i1);
971 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, t, v, height, j0, j1);
972 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapR, r, w, depth, k0, k1);
973
974 useBorderColor = 0;
975 if (img->Border) {
976 i0 += img->Border;
977 i1 += img->Border;
978 j0 += img->Border;
979 j1 += img->Border;
980 k0 += img->Border;
981 k1 += img->Border;
982 }
983 else {
984 /* check if sampling texture border color */
985 if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
986 if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
987 if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT;
988 if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT;
989 if (k0 < 0 || k0 >= depth) useBorderColor |= K0BIT;
990 if (k1 < 0 || k1 >= depth) useBorderColor |= K1BIT;
991 }
992
993 {
994 const GLfloat a = FRAC(u);
995 const GLfloat b = FRAC(v);
996 const GLfloat c = FRAC(w);
997 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
998 GLint w000 = IROUND((1.0F-a) * (1.0F-b) * (1.0F-c) * WEIGHT_SCALE);
999 GLint w100 = IROUND( a * (1.0F-b) * (1.0F-c) * WEIGHT_SCALE);
1000 GLint w010 = IROUND((1.0F-a) * b * (1.0F-c) * WEIGHT_SCALE);
1001 GLint w110 = IROUND( a * b * (1.0F-c) * WEIGHT_SCALE);
1002 GLint w001 = IROUND((1.0F-a) * (1.0F-b) * c * WEIGHT_SCALE);
1003 GLint w101 = IROUND( a * (1.0F-b) * c * WEIGHT_SCALE);
1004 GLint w011 = IROUND((1.0F-a) * b * c * WEIGHT_SCALE);
1005 GLint w111 = IROUND( a * b * c * WEIGHT_SCALE);
1006
1007 GLchan t000[4], t010[4], t001[4], t011[4];
1008 GLchan t100[4], t110[4], t101[4], t111[4];
1009
1010 if (useBorderColor & (I0BIT | J0BIT | K0BIT)) {
1011 COPY_CHAN4(t000, tObj->BorderColor);
1012 }
1013 else {
1014 (*img->FetchTexel)(img, i0, j0, k0, (GLvoid *) t000);
1015 if (img->Format == GL_COLOR_INDEX) {
1016 palette_sample(ctx, tObj, t000[0], t000);
1017 }
1018 }
1019 if (useBorderColor & (I1BIT | J0BIT | K0BIT)) {
1020 COPY_CHAN4(t100, tObj->BorderColor);
1021 }
1022 else {
1023 (*img->FetchTexel)(img, i1, j0, k0, (GLvoid *) t100);
1024 if (img->Format == GL_COLOR_INDEX) {
1025 palette_sample(ctx, tObj, t100[0], t100);
1026 }
1027 }
1028 if (useBorderColor & (I0BIT | J1BIT | K0BIT)) {
1029 COPY_CHAN4(t010, tObj->BorderColor);
1030 }
1031 else {
1032 (*img->FetchTexel)(img, i0, j1, k0, (GLvoid *) t010);
1033 if (img->Format == GL_COLOR_INDEX) {
1034 palette_sample(ctx, tObj, t010[0], t010);
1035 }
1036 }
1037 if (useBorderColor & (I1BIT | J1BIT | K0BIT)) {
1038 COPY_CHAN4(t110, tObj->BorderColor);
1039 }
1040 else {
1041 (*img->FetchTexel)(img, i1, j1, k0, (GLvoid *) t110);
1042 if (img->Format == GL_COLOR_INDEX) {
1043 palette_sample(ctx, tObj, t110[0], t110);
1044 }
1045 }
1046
1047 if (useBorderColor & (I0BIT | J0BIT | K1BIT)) {
1048 COPY_CHAN4(t001, tObj->BorderColor);
1049 }
1050 else {
1051 (*img->FetchTexel)(img, i0, j0, k1, (GLvoid *) t001);
1052 if (img->Format == GL_COLOR_INDEX) {
1053 palette_sample(ctx, tObj, t001[0], t001);
1054 }
1055 }
1056 if (useBorderColor & (I1BIT | J0BIT | K1BIT)) {
1057 COPY_CHAN4(t101, tObj->BorderColor);
1058 }
1059 else {
1060 (*img->FetchTexel)(img, i1, j0, k1, (GLvoid *) t101);
1061 if (img->Format == GL_COLOR_INDEX) {
1062 palette_sample(ctx, tObj, t101[0], t101);
1063 }
1064 }
1065 if (useBorderColor & (I0BIT | J1BIT | K1BIT)) {
1066 COPY_CHAN4(t011, tObj->BorderColor);
1067 }
1068 else {
1069 (*img->FetchTexel)(img, i0, j1, k1, (GLvoid *) t011);
1070 if (img->Format == GL_COLOR_INDEX) {
1071 palette_sample(ctx, tObj, t011[0], t011);
1072 }
1073 }
1074 if (useBorderColor & (I1BIT | J1BIT | K1BIT)) {
1075 COPY_CHAN4(t111, tObj->BorderColor);
1076 }
1077 else {
1078 (*img->FetchTexel)(img, i1, j1, k1, (GLvoid *) t111);
1079 if (img->Format == GL_COLOR_INDEX) {
1080 palette_sample(ctx, tObj, t111[0], t111);
1081 }
1082 }
1083
1084 rgba[0] = (GLchan) (
1085 (w000*t000[0] + w010*t010[0] + w001*t001[0] + w011*t011[0] +
1086 w100*t100[0] + w110*t110[0] + w101*t101[0] + w111*t111[0] )
1087 >> WEIGHT_SHIFT);
1088 rgba[1] = (GLchan) (
1089 (w000*t000[1] + w010*t010[1] + w001*t001[1] + w011*t011[1] +
1090 w100*t100[1] + w110*t110[1] + w101*t101[1] + w111*t111[1] )
1091 >> WEIGHT_SHIFT);
1092 rgba[2] = (GLchan) (
1093 (w000*t000[2] + w010*t010[2] + w001*t001[2] + w011*t011[2] +
1094 w100*t100[2] + w110*t110[2] + w101*t101[2] + w111*t111[2] )
1095 >> WEIGHT_SHIFT);
1096 rgba[3] = (GLchan) (
1097 (w000*t000[3] + w010*t010[3] + w001*t001[3] + w011*t011[3] +
1098 w100*t100[3] + w110*t110[3] + w101*t101[3] + w111*t111[3] )
1099 >> WEIGHT_SHIFT);
1100 }
1101 }
1102
1103
1104
1105 static void
1106 sample_3d_nearest_mipmap_nearest(GLcontext *ctx,
1107 const struct gl_texture_object *tObj,
1108 GLfloat s, GLfloat t, GLfloat r,
1109 GLfloat lambda, GLchan rgba[4] )
1110 {
1111 GLint level;
1112 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level);
1113 sample_3d_nearest(ctx, tObj, tObj->Image[level], s, t, r, rgba);
1114 }
1115
1116
1117 static void
1118 sample_3d_linear_mipmap_nearest(GLcontext *ctx,
1119 const struct gl_texture_object *tObj,
1120 GLfloat s, GLfloat t, GLfloat r,
1121 GLfloat lambda, GLchan rgba[4])
1122 {
1123 GLint level;
1124 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level);
1125 sample_3d_linear(ctx, tObj, tObj->Image[level], s, t, r, rgba);
1126 }
1127
1128
1129 static void
1130 sample_3d_nearest_mipmap_linear(GLcontext *ctx,
1131 const struct gl_texture_object *tObj,
1132 GLfloat s, GLfloat t, GLfloat r,
1133 GLfloat lambda, GLchan rgba[4])
1134 {
1135 GLint level;
1136
1137 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level);
1138
1139 if (level >= tObj->_MaxLevel) {
1140 sample_3d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel],
1141 s, t, r, rgba);
1142 }
1143 else {
1144 GLchan t0[4], t1[4]; /* texels */
1145 const GLfloat f = FRAC(lambda);
1146 sample_3d_nearest(ctx, tObj, tObj->Image[level ], s, t, r, t0);
1147 sample_3d_nearest(ctx, tObj, tObj->Image[level+1], s, t, r, t1);
1148 rgba[RCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
1149 rgba[GCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
1150 rgba[BCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
1151 rgba[ACOMP] = (GLchan) (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
1152 }
1153 }
1154
1155
1156 static void
1157 sample_3d_linear_mipmap_linear(GLcontext *ctx,
1158 const struct gl_texture_object *tObj,
1159 GLfloat s, GLfloat t, GLfloat r,
1160 GLfloat lambda, GLchan rgba[4] )
1161 {
1162 GLint level;
1163
1164 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level);
1165
1166 if (level >= tObj->_MaxLevel) {
1167 sample_3d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel], s, t, r, rgba);
1168 }
1169 else {
1170 GLchan t0[4], t1[4]; /* texels */
1171 const GLfloat f = FRAC(lambda);
1172 sample_3d_linear(ctx, tObj, tObj->Image[level ], s, t, r, t0);
1173 sample_3d_linear(ctx, tObj, tObj->Image[level+1], s, t, r, t1);
1174 rgba[RCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
1175 rgba[GCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
1176 rgba[BCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
1177 rgba[ACOMP] = (GLchan) (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
1178 }
1179 }
1180
1181
1182 static void
1183 sample_nearest_3d(GLcontext *ctx, GLuint texUnit,
1184 const struct gl_texture_object *tObj, GLuint n,
1185 const GLfloat s[], const GLfloat t[],
1186 const GLfloat u[], const GLfloat lambda[],
1187 GLchan rgba[][4])
1188 {
1189 GLuint i;
1190 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
1191 (void) lambda;
1192 for (i=0;i<n;i++) {
1193 sample_3d_nearest(ctx, tObj, image, s[i], t[i], u[i], rgba[i]);
1194 }
1195 }
1196
1197
1198
1199 static void
1200 sample_linear_3d( GLcontext *ctx, GLuint texUnit,
1201 const struct gl_texture_object *tObj, GLuint n,
1202 const GLfloat s[], const GLfloat t[],
1203 const GLfloat u[], const GLfloat lambda[],
1204 GLchan rgba[][4] )
1205 {
1206 GLuint i;
1207 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
1208 (void) lambda;
1209 for (i=0;i<n;i++) {
1210 sample_3d_linear(ctx, tObj, image, s[i], t[i], u[i], rgba[i]);
1211 }
1212 }
1213
1214
1215 /*
1216 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
1217 * return a texture sample.
1218 */
1219 static void
1220 sample_lambda_3d( GLcontext *ctx, GLuint texUnit,
1221 const struct gl_texture_object *tObj, GLuint n,
1222 const GLfloat s[], const GLfloat t[],
1223 const GLfloat u[], const GLfloat lambda[],
1224 GLchan rgba[][4] )
1225 {
1226 GLuint i;
1227 GLfloat MinMagThresh = SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit];
1228
1229 for (i=0;i<n;i++) {
1230
1231 if (lambda[i] > MinMagThresh) {
1232 /* minification */
1233 switch (tObj->MinFilter) {
1234 case GL_NEAREST:
1235 sample_3d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
1236 s[i], t[i], u[i], rgba[i]);
1237 break;
1238 case GL_LINEAR:
1239 sample_3d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
1240 s[i], t[i], u[i], rgba[i]);
1241 break;
1242 case GL_NEAREST_MIPMAP_NEAREST:
1243 sample_3d_nearest_mipmap_nearest(ctx, tObj, s[i], t[i], u[i],
1244 lambda[i], rgba[i]);
1245 break;
1246 case GL_LINEAR_MIPMAP_NEAREST:
1247 sample_3d_linear_mipmap_nearest(ctx, tObj, s[i], t[i], u[i],
1248 lambda[i], rgba[i]);
1249 break;
1250 case GL_NEAREST_MIPMAP_LINEAR:
1251 sample_3d_nearest_mipmap_linear(ctx, tObj, s[i], t[i], u[i],
1252 lambda[i], rgba[i]);
1253 break;
1254 case GL_LINEAR_MIPMAP_LINEAR:
1255 sample_3d_linear_mipmap_linear(ctx, tObj, s[i], t[i], u[i],
1256 lambda[i], rgba[i]);
1257 break;
1258 default:
1259 _mesa_problem(NULL, "Bad min filterin sample_3d_texture");
1260 }
1261 }
1262 else {
1263 /* magnification */
1264 switch (tObj->MagFilter) {
1265 case GL_NEAREST:
1266 sample_3d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
1267 s[i], t[i], u[i], rgba[i]);
1268 break;
1269 case GL_LINEAR:
1270 sample_3d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
1271 s[i], t[i], u[i], rgba[i]);
1272 break;
1273 default:
1274 _mesa_problem(NULL, "Bad mag filter in sample_3d_texture");
1275 }
1276 }
1277 }
1278 }
1279
1280
1281 /**********************************************************************/
1282 /* Texture Cube Map Sampling Functions */
1283 /**********************************************************************/
1284
1285 /*
1286 * Choose one of six sides of a texture cube map given the texture
1287 * coord (rx,ry,rz). Return pointer to corresponding array of texture
1288 * images.
1289 */
1290 static const struct gl_texture_image **
1291 choose_cube_face(const struct gl_texture_object *texObj,
1292 GLfloat rx, GLfloat ry, GLfloat rz,
1293 GLfloat *newS, GLfloat *newT)
1294 {
1295 /*
1296 major axis
1297 direction target sc tc ma
1298 ---------- ------------------------------- --- --- ---
1299 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
1300 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
1301 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
1302 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
1303 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
1304 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
1305 */
1306 const struct gl_texture_image **imgArray;
1307 const GLfloat arx = ABSF(rx), ary = ABSF(ry), arz = ABSF(rz);
1308 GLfloat sc, tc, ma;
1309
1310 if (arx > ary && arx > arz) {
1311 if (rx >= 0.0F) {
1312 imgArray = (const struct gl_texture_image **) texObj->Image;
1313 sc = -rz;
1314 tc = -ry;
1315 ma = arx;
1316 }
1317 else {
1318 imgArray = (const struct gl_texture_image **) texObj->NegX;
1319 sc = rz;
1320 tc = -ry;
1321 ma = arx;
1322 }
1323 }
1324 else if (ary > arx && ary > arz) {
1325 if (ry >= 0.0F) {
1326 imgArray = (const struct gl_texture_image **) texObj->PosY;
1327 sc = rx;
1328 tc = rz;
1329 ma = ary;
1330 }
1331 else {
1332 imgArray = (const struct gl_texture_image **) texObj->NegY;
1333 sc = rx;
1334 tc = -rz;
1335 ma = ary;
1336 }
1337 }
1338 else {
1339 if (rz > 0.0F) {
1340 imgArray = (const struct gl_texture_image **) texObj->PosZ;
1341 sc = rx;
1342 tc = -ry;
1343 ma = arz;
1344 }
1345 else {
1346 imgArray = (const struct gl_texture_image **) texObj->NegZ;
1347 sc = -rx;
1348 tc = -ry;
1349 ma = arz;
1350 }
1351 }
1352
1353 *newS = ( sc / ma + 1.0F ) * 0.5F;
1354 *newT = ( tc / ma + 1.0F ) * 0.5F;
1355 return imgArray;
1356 }
1357
1358
1359 static void
1360 sample_nearest_cube(GLcontext *ctx, GLuint texUnit,
1361 const struct gl_texture_object *tObj, GLuint n,
1362 const GLfloat s[], const GLfloat t[],
1363 const GLfloat u[], const GLfloat lambda[],
1364 GLchan rgba[][4])
1365 {
1366 GLuint i;
1367 (void) lambda;
1368 for (i = 0; i < n; i++) {
1369 const struct gl_texture_image **images;
1370 GLfloat newS, newT;
1371 images = choose_cube_face(tObj, s[i], t[i], u[i], &newS, &newT);
1372 sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel],
1373 newS, newT, rgba[i]);
1374 }
1375 }
1376
1377
1378 static void
1379 sample_linear_cube(GLcontext *ctx, GLuint texUnit,
1380 const struct gl_texture_object *tObj, GLuint n,
1381 const GLfloat s[], const GLfloat t[],
1382 const GLfloat u[], const GLfloat lambda[],
1383 GLchan rgba[][4])
1384 {
1385 GLuint i;
1386 (void) lambda;
1387 for (i = 0; i < n; i++) {
1388 const struct gl_texture_image **images;
1389 GLfloat newS, newT;
1390 images = choose_cube_face(tObj, s[i], t[i], u[i], &newS, &newT);
1391 sample_2d_linear(ctx, tObj, images[tObj->BaseLevel],
1392 newS, newT, rgba[i]);
1393 }
1394 }
1395
1396
1397 static void
1398 sample_cube_nearest_mipmap_nearest(GLcontext *ctx,
1399 const struct gl_texture_object *tObj,
1400 GLfloat s, GLfloat t, GLfloat u,
1401 GLfloat lambda, GLchan rgba[4])
1402 {
1403 const struct gl_texture_image **images;
1404 GLfloat newS, newT;
1405 GLint level;
1406
1407 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level);
1408
1409 images = choose_cube_face(tObj, s, t, u, &newS, &newT);
1410 sample_2d_nearest(ctx, tObj, images[level], newS, newT, rgba);
1411 }
1412
1413
1414 static void
1415 sample_cube_linear_mipmap_nearest(GLcontext *ctx,
1416 const struct gl_texture_object *tObj,
1417 GLfloat s, GLfloat t, GLfloat u,
1418 GLfloat lambda, GLchan rgba[4])
1419 {
1420 const struct gl_texture_image **images;
1421 GLfloat newS, newT;
1422 GLint level;
1423
1424 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level);
1425
1426 images = choose_cube_face(tObj, s, t, u, &newS, &newT);
1427 sample_2d_linear(ctx, tObj, images[level], newS, newT, rgba);
1428 }
1429
1430
1431 static void
1432 sample_cube_nearest_mipmap_linear(GLcontext *ctx,
1433 const struct gl_texture_object *tObj,
1434 GLfloat s, GLfloat t, GLfloat u,
1435 GLfloat lambda, GLchan rgba[4])
1436 {
1437 const struct gl_texture_image **images;
1438 GLfloat newS, newT;
1439 GLint level;
1440
1441 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level);
1442
1443 images = choose_cube_face(tObj, s, t, u, &newS, &newT);
1444
1445 if (level >= tObj->_MaxLevel) {
1446 sample_2d_nearest(ctx, tObj, images[tObj->_MaxLevel], newS, newT, rgba);
1447 }
1448 else {
1449 GLchan t0[4], t1[4]; /* texels */
1450 const GLfloat f = FRAC(lambda);
1451 sample_2d_nearest(ctx, tObj, images[level ], newS, newT, t0);
1452 sample_2d_nearest(ctx, tObj, images[level+1], newS, newT, t1);
1453 rgba[RCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
1454 rgba[GCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
1455 rgba[BCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
1456 rgba[ACOMP] = (GLchan) (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
1457 }
1458 }
1459
1460
1461 static void
1462 sample_cube_linear_mipmap_linear(GLcontext *ctx,
1463 const struct gl_texture_object *tObj,
1464 GLfloat s, GLfloat t, GLfloat u,
1465 GLfloat lambda, GLchan rgba[4])
1466 {
1467 const struct gl_texture_image **images;
1468 GLfloat newS, newT;
1469 GLint level;
1470
1471 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level);
1472
1473 images = choose_cube_face(tObj, s, t, u, &newS, &newT);
1474
1475 if (level >= tObj->_MaxLevel) {
1476 sample_2d_linear(ctx, tObj, images[tObj->_MaxLevel], newS, newT, rgba);
1477 }
1478 else {
1479 GLchan t0[4], t1[4];
1480 const GLfloat f = FRAC(lambda);
1481 sample_2d_linear(ctx, tObj, images[level ], newS, newT, t0);
1482 sample_2d_linear(ctx, tObj, images[level+1], newS, newT, t1);
1483 rgba[RCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
1484 rgba[GCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
1485 rgba[BCOMP] = (GLchan) (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
1486 rgba[ACOMP] = (GLchan) (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
1487 }
1488 }
1489
1490
1491 static void
1492 sample_lambda_cube( GLcontext *ctx, GLuint texUnit,
1493 const struct gl_texture_object *tObj, GLuint n,
1494 const GLfloat s[], const GLfloat t[],
1495 const GLfloat u[], const GLfloat lambda[],
1496 GLchan rgba[][4])
1497 {
1498 GLfloat MinMagThresh = SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit];
1499 GLuint i;
1500
1501 for (i = 0; i < n; i++) {
1502 if (lambda[i] > MinMagThresh) {
1503 /* minification */
1504 switch (tObj->MinFilter) {
1505 case GL_NEAREST:
1506 {
1507 const struct gl_texture_image **images;
1508 GLfloat newS, newT;
1509 images = choose_cube_face(tObj, s[i], t[i], u[i],
1510 &newS, &newT);
1511 sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel],
1512 newS, newT, rgba[i]);
1513 }
1514 break;
1515 case GL_LINEAR:
1516 {
1517 const struct gl_texture_image **images;
1518 GLfloat newS, newT;
1519 images = choose_cube_face(tObj, s[i], t[i], u[i],
1520 &newS, &newT);
1521 sample_2d_linear(ctx, tObj, images[tObj->BaseLevel],
1522 newS, newT, rgba[i]);
1523 }
1524 break;
1525 case GL_NEAREST_MIPMAP_NEAREST:
1526 sample_cube_nearest_mipmap_nearest(ctx, tObj, s[i], t[i], u[i],
1527 lambda[i], rgba[i]);
1528 break;
1529 case GL_LINEAR_MIPMAP_NEAREST:
1530 sample_cube_linear_mipmap_nearest(ctx, tObj, s[i], t[i], u[i],
1531 lambda[i], rgba[i]);
1532 break;
1533 case GL_NEAREST_MIPMAP_LINEAR:
1534 sample_cube_nearest_mipmap_linear(ctx, tObj, s[i], t[i], u[i],
1535 lambda[i], rgba[i]);
1536 break;
1537 case GL_LINEAR_MIPMAP_LINEAR:
1538 sample_cube_linear_mipmap_linear(ctx, tObj, s[i], t[i], u[i],
1539 lambda[i], rgba[i]);
1540 break;
1541 default:
1542 _mesa_problem(NULL, "Bad min filter in sample_lambda_cube");
1543 }
1544 }
1545 else {
1546 /* magnification */
1547 const struct gl_texture_image **images;
1548 GLfloat newS, newT;
1549 images = choose_cube_face(tObj, s[i], t[i], u[i],
1550 &newS, &newT);
1551 switch (tObj->MagFilter) {
1552 case GL_NEAREST:
1553 sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel],
1554 newS, newT, rgba[i]);
1555 break;
1556 case GL_LINEAR:
1557 sample_2d_linear(ctx, tObj, images[tObj->BaseLevel],
1558 newS, newT, rgba[i]);
1559 break;
1560 default:
1561 _mesa_problem(NULL, "Bad mag filter in sample_lambda_cube");
1562 }
1563 }
1564 }
1565 }
1566
1567 static void
1568 null_sample_func( GLcontext *ctx, GLuint texUnit,
1569 const struct gl_texture_object *tObj, GLuint n,
1570 const GLfloat s[], const GLfloat t[],
1571 const GLfloat u[], const GLfloat lambda[],
1572 GLchan rgba[][4])
1573 {
1574 }
1575
1576 /**********************************************************************/
1577 /* Texture Sampling Setup */
1578 /**********************************************************************/
1579
1580
1581 /*
1582 * Setup the texture sampling function for this texture object.
1583 */
1584 void
1585 _swrast_choose_texture_sample_func( GLcontext *ctx, GLuint texUnit,
1586 const struct gl_texture_object *t )
1587 {
1588 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1589
1590 if (!t->Complete) {
1591 swrast->TextureSample[texUnit] = null_sample_func;
1592 }
1593 else {
1594 GLboolean needLambda = (GLboolean) (t->MinFilter != t->MagFilter);
1595
1596 if (needLambda) {
1597 /* Compute min/mag filter threshold */
1598 if (t->MagFilter == GL_LINEAR
1599 && (t->MinFilter == GL_NEAREST_MIPMAP_NEAREST ||
1600 t->MinFilter == GL_NEAREST_MIPMAP_LINEAR)) {
1601 swrast->_MinMagThresh[texUnit] = 0.5F;
1602 }
1603 else {
1604 swrast->_MinMagThresh[texUnit] = 0.0F;
1605 }
1606 }
1607
1608 switch (t->Dimensions) {
1609 case 1:
1610 if (needLambda) {
1611 swrast->TextureSample[texUnit] = sample_lambda_1d;
1612 }
1613 else if (t->MinFilter==GL_LINEAR) {
1614 swrast->TextureSample[texUnit] = sample_linear_1d;
1615 }
1616 else {
1617 ASSERT(t->MinFilter==GL_NEAREST);
1618 swrast->TextureSample[texUnit] = sample_nearest_1d;
1619 }
1620 break;
1621 case 2:
1622 if (needLambda) {
1623 swrast->TextureSample[texUnit] = sample_lambda_2d;
1624 }
1625 else if (t->MinFilter==GL_LINEAR) {
1626 swrast->TextureSample[texUnit] = sample_linear_2d;
1627 }
1628 else {
1629 GLint baseLevel = t->BaseLevel;
1630 ASSERT(t->MinFilter==GL_NEAREST);
1631 if (t->WrapS == GL_REPEAT &&
1632 t->WrapT == GL_REPEAT &&
1633 t->Image[baseLevel]->Border == 0 &&
1634 t->Image[baseLevel]->Format == GL_RGB &&
1635 t->Image[baseLevel]->Type == CHAN_TYPE) {
1636 swrast->TextureSample[texUnit] = opt_sample_rgb_2d;
1637 }
1638 else if (t->WrapS == GL_REPEAT &&
1639 t->WrapT == GL_REPEAT &&
1640 t->Image[baseLevel]->Border == 0 &&
1641 t->Image[baseLevel]->Format==GL_RGBA &&
1642 t->Image[baseLevel]->Type == CHAN_TYPE) {
1643 swrast->TextureSample[texUnit] = opt_sample_rgba_2d;
1644 }
1645 else
1646 swrast->TextureSample[texUnit] = sample_nearest_2d;
1647 }
1648 break;
1649 case 3:
1650 if (needLambda) {
1651 swrast->TextureSample[texUnit] = sample_lambda_3d;
1652 }
1653 else if (t->MinFilter==GL_LINEAR) {
1654 swrast->TextureSample[texUnit] = sample_linear_3d;
1655 }
1656 else {
1657 ASSERT(t->MinFilter==GL_NEAREST);
1658 swrast->TextureSample[texUnit] = sample_nearest_3d;
1659 }
1660 break;
1661 case 6: /* cube map */
1662 if (needLambda) {
1663 swrast->TextureSample[texUnit] = sample_lambda_cube;
1664 }
1665 else if (t->MinFilter==GL_LINEAR) {
1666 swrast->TextureSample[texUnit] = sample_linear_cube;
1667 }
1668 else {
1669 ASSERT(t->MinFilter==GL_NEAREST);
1670 swrast->TextureSample[texUnit] = sample_nearest_cube;
1671 }
1672 break;
1673 default:
1674 _mesa_problem(NULL, "invalid dimensions in _mesa_set_texture_sampler");
1675 }
1676 }
1677 }
1678
1679
1680 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
1681 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
1682
1683 static INLINE void
1684 texture_combine(const GLcontext *ctx,
1685 const struct gl_texture_unit *textureUnit,
1686 GLuint n,
1687 CONST GLchan (*primary_rgba)[4],
1688 CONST GLchan (*texel)[4],
1689 GLchan (*rgba)[4])
1690 {
1691 GLchan ccolor [3][3*MAX_WIDTH][4];
1692 const GLchan (*argRGB [3])[4];
1693 const GLchan (*argA [3])[4];
1694 GLuint i, j;
1695 const GLuint RGBshift = textureUnit->CombineScaleShiftRGB;
1696 const GLuint Ashift = textureUnit->CombineScaleShiftA;
1697
1698 ASSERT(ctx->Extensions.EXT_texture_env_combine);
1699
1700 /*
1701 * Do operand setup for up to 3 operands. Loop over the terms.
1702 */
1703 for (j = 0; j < 3; j++) {
1704 switch (textureUnit->CombineSourceA[j]) {
1705 case GL_TEXTURE:
1706 argA[j] = texel;
1707 break;
1708 case GL_PRIMARY_COLOR_EXT:
1709 argA[j] = primary_rgba;
1710 break;
1711 case GL_PREVIOUS_EXT:
1712 argA[j] = (const GLchan (*)[4]) rgba;
1713 break;
1714 case GL_CONSTANT_EXT:
1715 {
1716 GLchan alpha, (*c)[4] = ccolor[j];
1717 UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]);
1718 for (i = 0; i < n; i++)
1719 c[i][ACOMP] = alpha;
1720 argA[j] = (const GLchan (*)[4]) ccolor[j];
1721 }
1722 break;
1723 default:
1724 _mesa_problem(NULL, "invalid combine source");
1725 }
1726
1727 switch (textureUnit->CombineSourceRGB[j]) {
1728 case GL_TEXTURE:
1729 argRGB[j] = texel;
1730 break;
1731 case GL_PRIMARY_COLOR_EXT:
1732 argRGB[j] = primary_rgba;
1733 break;
1734 case GL_PREVIOUS_EXT:
1735 argRGB[j] = (const GLchan (*)[4]) rgba;
1736 break;
1737 case GL_CONSTANT_EXT:
1738 {
1739 GLchan (*c)[4] = ccolor[j];
1740 GLchan red, green, blue;
1741 UNCLAMPED_FLOAT_TO_CHAN(red, textureUnit->EnvColor[0]);
1742 UNCLAMPED_FLOAT_TO_CHAN(green, textureUnit->EnvColor[1]);
1743 UNCLAMPED_FLOAT_TO_CHAN(blue, textureUnit->EnvColor[2]);
1744 for (i = 0; i < n; i++) {
1745 c[i][RCOMP] = red;
1746 c[i][GCOMP] = green;
1747 c[i][BCOMP] = blue;
1748 }
1749 argRGB[j] = (const GLchan (*)[4]) ccolor[j];
1750 }
1751 break;
1752 default:
1753 _mesa_problem(NULL, "invalid combine source");
1754 }
1755
1756 if (textureUnit->CombineOperandRGB[j] != GL_SRC_COLOR) {
1757 const GLchan (*src)[4] = argRGB[j];
1758 GLchan (*dst)[4] = ccolor[j];
1759
1760 argRGB[j] = (const GLchan (*)[4]) ccolor[j];
1761
1762 if (textureUnit->CombineOperandRGB[j] == GL_ONE_MINUS_SRC_COLOR) {
1763 for (i = 0; i < n; i++) {
1764 dst[i][RCOMP] = CHAN_MAX - src[i][RCOMP];
1765 dst[i][GCOMP] = CHAN_MAX - src[i][GCOMP];
1766 dst[i][BCOMP] = CHAN_MAX - src[i][BCOMP];
1767 }
1768 }
1769 else if (textureUnit->CombineOperandRGB[j] == GL_SRC_ALPHA) {
1770 src = (const GLchan (*)[4]) argA[j];
1771 for (i = 0; i < n; i++) {
1772 dst[i][RCOMP] = src[i][ACOMP];
1773 dst[i][GCOMP] = src[i][ACOMP];
1774 dst[i][BCOMP] = src[i][ACOMP];
1775 }
1776 }
1777 else {
1778 ASSERT(textureUnit->CombineOperandRGB[j] ==GL_ONE_MINUS_SRC_ALPHA);
1779 src = (const GLchan (*)[4]) argA[j];
1780 for (i = 0; i < n; i++) {
1781 dst[i][RCOMP] = CHAN_MAX - src[i][ACOMP];
1782 dst[i][GCOMP] = CHAN_MAX - src[i][ACOMP];
1783 dst[i][BCOMP] = CHAN_MAX - src[i][ACOMP];
1784 }
1785 }
1786 }
1787
1788 if (textureUnit->CombineOperandA[j] == GL_ONE_MINUS_SRC_ALPHA) {
1789 const GLchan (*src)[4] = argA[j];
1790 GLchan (*dst)[4] = ccolor[j];
1791 argA[j] = (const GLchan (*)[4]) ccolor[j];
1792 for (i = 0; i < n; i++) {
1793 dst[i][ACOMP] = CHAN_MAX - src[i][ACOMP];
1794 }
1795 }
1796
1797 if (textureUnit->CombineModeRGB == GL_REPLACE &&
1798 textureUnit->CombineModeA == GL_REPLACE) {
1799 break; /* done, we need only arg0 */
1800 }
1801
1802 if (j == 1 &&
1803 textureUnit->CombineModeRGB != GL_INTERPOLATE_EXT &&
1804 textureUnit->CombineModeA != GL_INTERPOLATE_EXT) {
1805 break; /* arg0 and arg1 are done. we don't need arg2. */
1806 }
1807 }
1808
1809 /*
1810 * Do the texture combine.
1811 */
1812 switch (textureUnit->CombineModeRGB) {
1813 case GL_REPLACE:
1814 {
1815 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
1816 if (RGBshift) {
1817 for (i = 0; i < n; i++) {
1818 GLuint r = (GLuint) arg0[i][RCOMP] << RGBshift;
1819 GLuint g = (GLuint) arg0[i][GCOMP] << RGBshift;
1820 GLuint b = (GLuint) arg0[i][BCOMP] << RGBshift;
1821 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
1822 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
1823 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
1824 }
1825 }
1826 else {
1827 for (i = 0; i < n; i++) {
1828 rgba[i][RCOMP] = arg0[i][RCOMP];
1829 rgba[i][GCOMP] = arg0[i][GCOMP];
1830 rgba[i][BCOMP] = arg0[i][BCOMP];
1831 }
1832 }
1833 }
1834 break;
1835 case GL_MODULATE:
1836 {
1837 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
1838 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
1839 const GLint shift = 8 - RGBshift;
1840 for (i = 0; i < n; i++) {
1841 GLuint r = PROD(arg0[i][0], arg1[i][RCOMP]) >> shift;
1842 GLuint g = PROD(arg0[i][1], arg1[i][GCOMP]) >> shift;
1843 GLuint b = PROD(arg0[i][2], arg1[i][BCOMP]) >> shift;
1844 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
1845 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
1846 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
1847 }
1848 }
1849 break;
1850 case GL_ADD:
1851 {
1852 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
1853 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
1854 for (i = 0; i < n; i++) {
1855 GLint r = ((GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP]) << RGBshift;
1856 GLint g = ((GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP]) << RGBshift;
1857 GLint b = ((GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP]) << RGBshift;
1858 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
1859 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
1860 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
1861 }
1862 }
1863 break;
1864 case GL_ADD_SIGNED_EXT:
1865 {
1866 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
1867 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
1868 for (i = 0; i < n; i++) {
1869 GLint r = (GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP] - 128;
1870 GLint g = (GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP] - 128;
1871 GLint b = (GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP] - 128;
1872 r = (r < 0) ? 0 : r << RGBshift;
1873 g = (g < 0) ? 0 : g << RGBshift;
1874 b = (b < 0) ? 0 : b << RGBshift;
1875 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
1876 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
1877 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
1878 }
1879 }
1880 break;
1881 case GL_INTERPOLATE_EXT:
1882 {
1883 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
1884 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
1885 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
1886 const GLint shift = 8 - RGBshift;
1887 for (i = 0; i < n; i++) {
1888 GLuint r = (PROD(arg0[i][RCOMP], arg2[i][RCOMP])
1889 + PROD(arg1[i][RCOMP], CHAN_MAX - arg2[i][RCOMP]))
1890 >> shift;
1891 GLuint g = (PROD(arg0[i][GCOMP], arg2[i][GCOMP])
1892 + PROD(arg1[i][GCOMP], CHAN_MAX - arg2[i][GCOMP]))
1893 >> shift;
1894 GLuint b = (PROD(arg0[i][BCOMP], arg2[i][BCOMP])
1895 + PROD(arg1[i][BCOMP], CHAN_MAX - arg2[i][BCOMP]))
1896 >> shift;
1897 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
1898 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
1899 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
1900 }
1901 }
1902 break;
1903 case GL_DOT3_RGB_EXT:
1904 case GL_DOT3_RGBA_EXT:
1905 case GL_DOT3_RGB_ARB:
1906 case GL_DOT3_RGBA_ARB:
1907 {
1908 const GLubyte (*arg0)[4] = (const GLubyte (*)[4]) argRGB[0];
1909 const GLubyte (*arg1)[4] = (const GLubyte (*)[4]) argRGB[1];
1910 /* ATI's EXT extension has a constant scale by 4. The ARB
1911 * one will likely remove this restriction, and we should
1912 * drop the EXT extension in favour of the ARB one.
1913 */
1914 for (i = 0; i < n; i++) {
1915 GLint dot = (S_PROD((GLint)arg0[i][RCOMP] - 128,
1916 (GLint)arg1[i][RCOMP] - 128) +
1917 S_PROD((GLint)arg0[i][GCOMP] - 128,
1918 (GLint)arg1[i][GCOMP] - 128) +
1919 S_PROD((GLint)arg0[i][BCOMP] - 128,
1920 (GLint)arg1[i][BCOMP] - 128)) >> 6;
1921 rgba[i][RCOMP] = (GLubyte) CLAMP(dot, 0, 255);
1922 rgba[i][GCOMP] = (GLubyte) CLAMP(dot, 0, 255);
1923 rgba[i][BCOMP] = (GLubyte) CLAMP(dot, 0, 255);
1924 }
1925 }
1926 break;
1927 default:
1928 _mesa_problem(NULL, "invalid combine mode");
1929 }
1930
1931 switch (textureUnit->CombineModeA) {
1932 case GL_REPLACE:
1933 {
1934 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
1935 if (Ashift) {
1936 for (i = 0; i < n; i++) {
1937 GLuint a = (GLuint) arg0[i][ACOMP] << Ashift;
1938 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
1939 }
1940 }
1941 else {
1942 for (i = 0; i < n; i++) {
1943 rgba[i][ACOMP] = arg0[i][ACOMP];
1944 }
1945 }
1946 }
1947 break;
1948 case GL_MODULATE:
1949 {
1950 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
1951 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
1952 const GLint shift = 8 - Ashift;
1953 for (i = 0; i < n; i++) {
1954 GLuint a = (PROD(arg0[i][ACOMP], arg1[i][ACOMP]) >> shift);
1955 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
1956 }
1957 }
1958 break;
1959 case GL_ADD:
1960 {
1961 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
1962 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
1963 for (i = 0; i < n; i++) {
1964 GLint a = ((GLint) arg0[i][ACOMP] + arg1[i][ACOMP]) << Ashift;
1965 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
1966 }
1967 }
1968 break;
1969 case GL_ADD_SIGNED_EXT:
1970 {
1971 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
1972 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
1973 for (i = 0; i < n; i++) {
1974 GLint a = (GLint) arg0[i][ACOMP] + (GLint) arg1[i][ACOMP] - 128;
1975 a = (a < 0) ? 0 : a << Ashift;
1976 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
1977 }
1978 }
1979 break;
1980 case GL_INTERPOLATE_EXT:
1981 {
1982 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
1983 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
1984 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
1985 const GLint shift = 8 - Ashift;
1986 for (i=0; i<n; i++) {
1987 GLuint a = (PROD(arg0[i][ACOMP], arg2[i][ACOMP])
1988 + PROD(arg1[i][ACOMP], CHAN_MAX - arg2[i][ACOMP]))
1989 >> shift;
1990 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
1991 }
1992 }
1993 break;
1994 default:
1995 _mesa_problem(NULL, "invalid combine mode");
1996 }
1997
1998 /* Fix the alpha component for GL_DOT3_RGBA_EXT combining.
1999 */
2000 if (textureUnit->CombineModeRGB == GL_DOT3_RGBA_EXT ||
2001 textureUnit->CombineModeRGB == GL_DOT3_RGBA_ARB) {
2002 for (i = 0; i < n; i++) {
2003 rgba[i][ACOMP] = rgba[i][RCOMP];
2004 }
2005 }
2006 }
2007 #undef PROD
2008
2009
2010
2011 /**********************************************************************/
2012 /* Texture Application */
2013 /**********************************************************************/
2014
2015
2016 /*
2017 * Combine incoming fragment color with texel color to produce output color.
2018 * Input: textureUnit - pointer to texture unit to apply
2019 * format - base internal texture format
2020 * n - number of fragments
2021 * primary_rgba - primary colors (may alias rgba for single texture)
2022 * texels - array of texel colors
2023 * InOut: rgba - incoming fragment colors modified by texel colors
2024 * according to the texture environment mode.
2025 */
2026 static void
2027 apply_texture( const GLcontext *ctx,
2028 const struct gl_texture_unit *texUnit,
2029 GLuint n,
2030 CONST GLchan primary_rgba[][4], CONST GLchan texel[][4],
2031 GLchan rgba[][4] )
2032 {
2033 GLint baseLevel;
2034 GLuint i;
2035 GLint Rc, Gc, Bc, Ac;
2036 GLenum format;
2037
2038 ASSERT(texUnit);
2039 ASSERT(texUnit->_Current);
2040
2041 baseLevel = texUnit->_Current->BaseLevel;
2042 ASSERT(texUnit->_Current->Image[baseLevel]);
2043
2044 format = texUnit->_Current->Image[baseLevel]->Format;
2045
2046 if (format==GL_COLOR_INDEX || format==GL_DEPTH_COMPONENT) {
2047 format = GL_RGBA; /* XXXX a hack! */
2048 }
2049
2050 switch (texUnit->EnvMode) {
2051 case GL_REPLACE:
2052 switch (format) {
2053 case GL_ALPHA:
2054 for (i=0;i<n;i++) {
2055 /* Cv = Cf */
2056 /* Av = At */
2057 rgba[i][ACOMP] = texel[i][ACOMP];
2058 }
2059 break;
2060 case GL_LUMINANCE:
2061 for (i=0;i<n;i++) {
2062 /* Cv = Lt */
2063 GLchan Lt = texel[i][RCOMP];
2064 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
2065 /* Av = Af */
2066 }
2067 break;
2068 case GL_LUMINANCE_ALPHA:
2069 for (i=0;i<n;i++) {
2070 GLchan Lt = texel[i][RCOMP];
2071 /* Cv = Lt */
2072 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
2073 /* Av = At */
2074 rgba[i][ACOMP] = texel[i][ACOMP];
2075 }
2076 break;
2077 case GL_INTENSITY:
2078 for (i=0;i<n;i++) {
2079 /* Cv = It */
2080 GLchan It = texel[i][RCOMP];
2081 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = It;
2082 /* Av = It */
2083 rgba[i][ACOMP] = It;
2084 }
2085 break;
2086 case GL_RGB:
2087 for (i=0;i<n;i++) {
2088 /* Cv = Ct */
2089 rgba[i][RCOMP] = texel[i][RCOMP];
2090 rgba[i][GCOMP] = texel[i][GCOMP];
2091 rgba[i][BCOMP] = texel[i][BCOMP];
2092 /* Av = Af */
2093 }
2094 break;
2095 case GL_RGBA:
2096 for (i=0;i<n;i++) {
2097 /* Cv = Ct */
2098 rgba[i][RCOMP] = texel[i][RCOMP];
2099 rgba[i][GCOMP] = texel[i][GCOMP];
2100 rgba[i][BCOMP] = texel[i][BCOMP];
2101 /* Av = At */
2102 rgba[i][ACOMP] = texel[i][ACOMP];
2103 }
2104 break;
2105 default:
2106 _mesa_problem(ctx, "Bad format (GL_REPLACE) in apply_texture");
2107 return;
2108 }
2109 break;
2110
2111 case GL_MODULATE:
2112 switch (format) {
2113 case GL_ALPHA:
2114 for (i=0;i<n;i++) {
2115 /* Cv = Cf */
2116 /* Av = AfAt */
2117 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
2118 }
2119 break;
2120 case GL_LUMINANCE:
2121 for (i=0;i<n;i++) {
2122 /* Cv = LtCf */
2123 GLchan Lt = texel[i][RCOMP];
2124 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt );
2125 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt );
2126 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt );
2127 /* Av = Af */
2128 }
2129 break;
2130 case GL_LUMINANCE_ALPHA:
2131 for (i=0;i<n;i++) {
2132 /* Cv = CfLt */
2133 GLchan Lt = texel[i][RCOMP];
2134 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt );
2135 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt );
2136 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt );
2137 /* Av = AfAt */
2138 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
2139 }
2140 break;
2141 case GL_INTENSITY:
2142 for (i=0;i<n;i++) {
2143 /* Cv = CfIt */
2144 GLchan It = texel[i][RCOMP];
2145 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], It );
2146 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], It );
2147 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], It );
2148 /* Av = AfIt */
2149 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], It );
2150 }
2151 break;
2152 case GL_RGB:
2153 for (i=0;i<n;i++) {
2154 /* Cv = CfCt */
2155 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] );
2156 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] );
2157 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] );
2158 /* Av = Af */
2159 }
2160 break;
2161 case GL_RGBA:
2162 for (i=0;i<n;i++) {
2163 /* Cv = CfCt */
2164 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] );
2165 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] );
2166 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] );
2167 /* Av = AfAt */
2168 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
2169 }
2170 break;
2171 default:
2172 _mesa_problem(ctx, "Bad format (GL_MODULATE) in apply_texture");
2173 return;
2174 }
2175 break;
2176
2177 case GL_DECAL:
2178 switch (format) {
2179 case GL_ALPHA:
2180 case GL_LUMINANCE:
2181 case GL_LUMINANCE_ALPHA:
2182 case GL_INTENSITY:
2183 /* undefined */
2184 break;
2185 case GL_RGB:
2186 for (i=0;i<n;i++) {
2187 /* Cv = Ct */
2188 rgba[i][RCOMP] = texel[i][RCOMP];
2189 rgba[i][GCOMP] = texel[i][GCOMP];
2190 rgba[i][BCOMP] = texel[i][BCOMP];
2191 /* Av = Af */
2192 }
2193 break;
2194 case GL_RGBA:
2195 for (i=0;i<n;i++) {
2196 /* Cv = Cf(1-At) + CtAt */
2197 GLint t = texel[i][ACOMP], s = CHAN_MAX - t;
2198 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(texel[i][RCOMP],t);
2199 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(texel[i][GCOMP],t);
2200 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(texel[i][BCOMP],t);
2201 /* Av = Af */
2202 }
2203 break;
2204 default:
2205 _mesa_problem(ctx, "Bad format (GL_DECAL) in apply_texture");
2206 return;
2207 }
2208 break;
2209
2210 case GL_BLEND:
2211 Rc = (GLint) (texUnit->EnvColor[0] * CHAN_MAXF);
2212 Gc = (GLint) (texUnit->EnvColor[1] * CHAN_MAXF);
2213 Bc = (GLint) (texUnit->EnvColor[2] * CHAN_MAXF);
2214 Ac = (GLint) (texUnit->EnvColor[3] * CHAN_MAXF);
2215 switch (format) {
2216 case GL_ALPHA:
2217 for (i=0;i<n;i++) {
2218 /* Cv = Cf */
2219 /* Av = AfAt */
2220 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
2221 }
2222 break;
2223 case GL_LUMINANCE:
2224 for (i=0;i<n;i++) {
2225 /* Cv = Cf(1-Lt) + CcLt */
2226 GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt;
2227 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt);
2228 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt);
2229 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt);
2230 /* Av = Af */
2231 }
2232 break;
2233 case GL_LUMINANCE_ALPHA:
2234 for (i=0;i<n;i++) {
2235 /* Cv = Cf(1-Lt) + CcLt */
2236 GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt;
2237 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt);
2238 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt);
2239 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt);
2240 /* Av = AfAt */
2241 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]);
2242 }
2243 break;
2244 case GL_INTENSITY:
2245 for (i=0;i<n;i++) {
2246 /* Cv = Cf(1-It) + CcLt */
2247 GLchan It = texel[i][RCOMP], s = CHAN_MAX - It;
2248 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, It);
2249 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, It);
2250 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, It);
2251 /* Av = Af(1-It) + Ac*It */
2252 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], s) + CHAN_PRODUCT(Ac, It);
2253 }
2254 break;
2255 case GL_RGB:
2256 for (i=0;i<n;i++) {
2257 /* Cv = Cf(1-Ct) + CcCt */
2258 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]);
2259 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]);
2260 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]);
2261 /* Av = Af */
2262 }
2263 break;
2264 case GL_RGBA:
2265 for (i=0;i<n;i++) {
2266 /* Cv = Cf(1-Ct) + CcCt */
2267 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]);
2268 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]);
2269 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]);
2270 /* Av = AfAt */
2271 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]);
2272 }
2273 break;
2274 default:
2275 _mesa_problem(ctx, "Bad format (GL_BLEND) in apply_texture");
2276 return;
2277 }
2278 break;
2279
2280 case GL_ADD: /* GL_EXT_texture_add_env */
2281 switch (format) {
2282 case GL_ALPHA:
2283 for (i=0;i<n;i++) {
2284 /* Rv = Rf */
2285 /* Gv = Gf */
2286 /* Bv = Bf */
2287 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
2288 }
2289 break;
2290 case GL_LUMINANCE:
2291 for (i=0;i<n;i++) {
2292 GLuint Lt = texel[i][RCOMP];
2293 GLuint r = rgba[i][RCOMP] + Lt;
2294 GLuint g = rgba[i][GCOMP] + Lt;
2295 GLuint b = rgba[i][BCOMP] + Lt;
2296 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
2297 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
2298 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
2299 /* Av = Af */
2300 }
2301 break;
2302 case GL_LUMINANCE_ALPHA:
2303 for (i=0;i<n;i++) {
2304 GLuint Lt = texel[i][RCOMP];
2305 GLuint r = rgba[i][RCOMP] + Lt;
2306 GLuint g = rgba[i][GCOMP] + Lt;
2307 GLuint b = rgba[i][BCOMP] + Lt;
2308 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
2309 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
2310 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
2311 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
2312 }
2313 break;
2314 case GL_INTENSITY:
2315 for (i=0;i<n;i++) {
2316 GLchan It = texel[i][RCOMP];
2317 GLuint r = rgba[i][RCOMP] + It;
2318 GLuint g = rgba[i][GCOMP] + It;
2319 GLuint b = rgba[i][BCOMP] + It;
2320 GLuint a = rgba[i][ACOMP] + It;
2321 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
2322 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
2323 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
2324 rgba[i][ACOMP] = MIN2(a, CHAN_MAX);
2325 }
2326 break;
2327 case GL_RGB:
2328 for (i=0;i<n;i++) {
2329 GLuint r = rgba[i][RCOMP] + texel[i][RCOMP];
2330 GLuint g = rgba[i][GCOMP] + texel[i][GCOMP];
2331 GLuint b = rgba[i][BCOMP] + texel[i][BCOMP];
2332 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
2333 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
2334 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
2335 /* Av = Af */
2336 }
2337 break;
2338 case GL_RGBA:
2339 for (i=0;i<n;i++) {
2340 GLuint r = rgba[i][RCOMP] + texel[i][RCOMP];
2341 GLuint g = rgba[i][GCOMP] + texel[i][GCOMP];
2342 GLuint b = rgba[i][BCOMP] + texel[i][BCOMP];
2343 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
2344 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
2345 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
2346 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
2347 }
2348 break;
2349 default:
2350 _mesa_problem(ctx, "Bad format (GL_ADD) in apply_texture");
2351 return;
2352 }
2353 break;
2354
2355 case GL_COMBINE_EXT:
2356 texture_combine(ctx, texUnit, n, primary_rgba, texel, rgba);
2357 break;
2358
2359 default:
2360 _mesa_problem(ctx, "Bad env mode in apply_texture");
2361 return;
2362 }
2363 }
2364
2365
2366
2367 /*
2368 * Sample a shadow/depth texture.
2369 * Input: ctx - context
2370 * texUnit - the texture unit
2371 * n - number of samples
2372 * s,t,r - array [n] of texture coordinates
2373 * In/Out: rgba - array [n] of texel colors.
2374 */
2375 static void
2376 sample_depth_texture(const GLcontext *ctx,
2377 const struct gl_texture_unit *texUnit,
2378 GLuint n,
2379 const GLfloat s[], const GLfloat t[], const GLfloat r[],
2380 GLchan texel[][4])
2381 {
2382 const struct gl_texture_object *texObj = texUnit->_Current;
2383 const GLint baseLevel = texObj->BaseLevel;
2384 const struct gl_texture_image *texImage = texObj->Image[baseLevel];
2385 const GLuint width = texImage->Width;
2386 const GLuint height = texImage->Height;
2387 const GLchan ambient = texObj->ShadowAmbient;
2388 GLboolean lequal, gequal;
2389
2390 if (texObj->Dimensions != 2) {
2391 _mesa_problem(ctx, "only 2-D depth textures supported at this time");
2392 return;
2393 }
2394
2395 if (texObj->MinFilter != texObj->MagFilter) {
2396 _mesa_problem(ctx, "mipmapped depth textures not supported at this time");
2397 return;
2398 }
2399
2400 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2401 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2402 * isn't a depth texture.
2403 */
2404 if (texImage->Format != GL_DEPTH_COMPONENT) {
2405 _mesa_problem(ctx,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2406 return;
2407 }
2408
2409 if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) {
2410 lequal = GL_TRUE;
2411 gequal = GL_FALSE;
2412 }
2413 else {
2414 lequal = GL_FALSE;
2415 gequal = GL_TRUE;
2416 }
2417
2418 if (texObj->MagFilter == GL_NEAREST) {
2419 GLuint i;
2420 for (i = 0; i < n; i++) {
2421 GLfloat depthSample;
2422 GLint col, row;
2423 COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapS, s[i], width, col);
2424 COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, t[i], height, row);
2425 depthSample = *((const GLfloat *) texImage->Data + row * width + col);
2426 if ((r[i] <= depthSample && lequal) ||
2427 (r[i] >= depthSample && gequal)) {
2428 texel[i][RCOMP] = CHAN_MAX;
2429 texel[i][GCOMP] = CHAN_MAX;
2430 texel[i][BCOMP] = CHAN_MAX;
2431 texel[i][ACOMP] = CHAN_MAX;
2432 }
2433 else {
2434 texel[i][RCOMP] = ambient;
2435 texel[i][GCOMP] = ambient;
2436 texel[i][BCOMP] = ambient;
2437 texel[i][ACOMP] = CHAN_MAX;
2438 }
2439 }
2440 }
2441 else {
2442 GLuint i;
2443 ASSERT(texObj->MagFilter == GL_LINEAR);
2444 for (i = 0; i < n; i++) {
2445 GLfloat depth00, depth01, depth10, depth11;
2446 GLint i0, i1, j0, j1;
2447 GLfloat u, v;
2448 GLuint useBorderTexel;
2449
2450 COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj->WrapS, s[i], u, width, i0, i1);
2451 COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj->WrapT, t[i], v, height,j0, j1);
2452
2453 useBorderTexel = 0;
2454 if (texImage->Border) {
2455 i0 += texImage->Border;
2456 i1 += texImage->Border;
2457 j0 += texImage->Border;
2458 j1 += texImage->Border;
2459 }
2460 else {
2461 if (i0 < 0 || i0 >= (GLint) width) useBorderTexel |= I0BIT;
2462 if (i1 < 0 || i1 >= (GLint) width) useBorderTexel |= I1BIT;
2463 if (j0 < 0 || j0 >= (GLint) height) useBorderTexel |= J0BIT;
2464 if (j1 < 0 || j1 >= (GLint) height) useBorderTexel |= J1BIT;
2465 }
2466
2467 /* get four depth samples from the texture */
2468 if (useBorderTexel & (I0BIT | J0BIT)) {
2469 depth00 = 1.0;
2470 }
2471 else {
2472 depth00 = *((const GLfloat *) texImage->Data + j0 * width + i0);
2473 }
2474 if (useBorderTexel & (I1BIT | J0BIT)) {
2475 depth10 = 1.0;
2476 }
2477 else {
2478 depth10 = *((const GLfloat *) texImage->Data + j0 * width + i1);
2479 }
2480 if (useBorderTexel & (I0BIT | J1BIT)) {
2481 depth01 = 1.0;
2482 }
2483 else {
2484 depth01 = *((const GLfloat *) texImage->Data + j1 * width + i0);
2485 }
2486 if (useBorderTexel & (I1BIT | J1BIT)) {
2487 depth11 = 1.0;
2488 }
2489 else {
2490 depth11 = *((const GLfloat *) texImage->Data + j1 * width + i1);
2491 }
2492
2493 if (0) {
2494 /* compute a single weighted depth sample and do one comparison */
2495 const GLfloat a = FRAC(u);
2496 const GLfloat b = FRAC(v);
2497 const GLfloat w00 = (1.0F - a) * (1.0F - b);
2498 const GLfloat w10 = ( a) * (1.0F - b);
2499 const GLfloat w01 = (1.0F - a) * ( b);
2500 const GLfloat w11 = ( a) * ( b);
2501 const GLfloat depthSample = w00 * depth00 + w10 * depth10
2502 + w01 * depth01 + w11 * depth11;
2503 if ((depthSample <= r[i] && lequal) ||
2504 (depthSample >= r[i] && gequal)) {
2505 texel[i][RCOMP] = ambient;
2506 texel[i][GCOMP] = ambient;
2507 texel[i][BCOMP] = ambient;
2508 texel[i][ACOMP] = CHAN_MAX;
2509 }
2510 else {
2511 texel[i][RCOMP] = CHAN_MAX;
2512 texel[i][GCOMP] = CHAN_MAX;
2513 texel[i][BCOMP] = CHAN_MAX;
2514 texel[i][ACOMP] = CHAN_MAX;
2515 }
2516 }
2517 else {
2518 /* Do four depth/R comparisons and compute a weighted result.
2519 * If this touches on somebody's I.P., I'll remove this code
2520 * upon request.
2521 */
2522 const GLfloat d = (CHAN_MAXF - (GLfloat) ambient) * 0.25F;
2523 GLfloat luminance = CHAN_MAXF;
2524 GLchan lum;
2525 if (lequal) {
2526 if (depth00 <= r[i]) luminance -= d;
2527 if (depth01 <= r[i]) luminance -= d;
2528 if (depth10 <= r[i]) luminance -= d;
2529 if (depth11 <= r[i]) luminance -= d;
2530 }
2531 else {
2532 if (depth00 >= r[i]) luminance -= d;
2533 if (depth01 >= r[i]) luminance -= d;
2534 if (depth10 >= r[i]) luminance -= d;
2535 if (depth11 >= r[i]) luminance -= d;
2536 }
2537 lum = (GLchan) luminance;
2538 texel[i][RCOMP] = lum;
2539 texel[i][GCOMP] = lum;
2540 texel[i][BCOMP] = lum;
2541 texel[i][ACOMP] = CHAN_MAX;
2542 }
2543 }
2544 }
2545 }
2546
2547
2548 #if 0
2549 /*
2550 * Experimental depth texture sampling function.
2551 */
2552 static void
2553 sample_depth_texture2(const GLcontext *ctx,
2554 const struct gl_texture_unit *texUnit,
2555 GLuint n,
2556 const GLfloat s[], const GLfloat t[], const GLfloat r[],
2557 GLchan texel[][4])
2558 {
2559 const struct gl_texture_object *texObj = texUnit->_Current;
2560 const GLint baseLevel = texObj->BaseLevel;
2561 const struct gl_texture_image *texImage = texObj->Image[baseLevel];
2562 const GLuint width = texImage->Width;
2563 const GLuint height = texImage->Height;
2564 const GLchan ambient = texObj->ShadowAmbient;
2565 GLboolean lequal, gequal;
2566
2567 if (texObj->Dimensions != 2) {
2568 _mesa_problem(ctx, "only 2-D depth textures supported at this time");
2569 return;
2570 }
2571
2572 if (texObj->MinFilter != texObj->MagFilter) {
2573 _mesa_problem(ctx, "mipmapped depth textures not supported at this time");
2574 return;
2575 }
2576
2577 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2578 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2579 * isn't a depth texture.
2580 */
2581 if (texImage->Format != GL_DEPTH_COMPONENT) {
2582 _mesa_problem(ctx,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2583 return;
2584 }
2585
2586 if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) {
2587 lequal = GL_TRUE;
2588 gequal = GL_FALSE;
2589 }
2590 else {
2591 lequal = GL_FALSE;
2592 gequal = GL_TRUE;
2593 }
2594
2595 {
2596 GLuint i;
2597 for (i = 0; i < n; i++) {
2598 const GLint K = 3;
2599 GLint col, row, ii, jj, imin, imax, jmin, jmax, samples, count;
2600 GLfloat w;
2601 GLchan lum;
2602 COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapS, s[i], width, col);
2603 COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, t[i], height, row);
2604
2605 imin = col - K;
2606 imax = col + K;
2607 jmin = row - K;
2608 jmax = row + K;
2609
2610 if (imin < 0) imin = 0;
2611 if (imax >= width) imax = width - 1;
2612 if (jmin < 0) jmin = 0;
2613 if (jmax >= height) jmax = height - 1;
2614
2615 samples = (imax - imin + 1) * (jmax - jmin + 1);
2616 count = 0;
2617 for (jj = jmin; jj <= jmax; jj++) {
2618 for (ii = imin; ii <= imax; ii++) {
2619 GLfloat depthSample = *((const GLfloat *) texImage->Data
2620 + jj * width + ii);
2621 if ((depthSample <= r[i] && lequal) ||
2622 (depthSample >= r[i] && gequal)) {
2623 count++;
2624 }
2625 }
2626 }
2627
2628 w = (GLfloat) count / (GLfloat) samples;
2629 w = CHAN_MAXF - w * (CHAN_MAXF - (GLfloat) ambient);
2630 lum = (GLint) w;
2631
2632 texel[i][RCOMP] = lum;
2633 texel[i][GCOMP] = lum;
2634 texel[i][BCOMP] = lum;
2635 texel[i][ACOMP] = CHAN_MAX;
2636 }
2637 }
2638 }
2639 #endif
2640
2641
2642 /*
2643 * Apply a unit of texture mapping to the incoming fragments.
2644 */
2645 void
2646 _swrast_texture_fragments( GLcontext *ctx, GLuint texUnit, GLuint n,
2647 const GLfloat s[], const GLfloat t[],
2648 const GLfloat r[], GLfloat lambda[],
2649 CONST GLchan primary_rgba[][4], GLchan rgba[][4] )
2650 {
2651 const GLuint mask = TEXTURE0_ANY << (texUnit * 4);
2652
2653 if (ctx->Texture._ReallyEnabled & mask) {
2654 const struct gl_texture_unit *textureUnit = &ctx->Texture.Unit[texUnit];
2655
2656 if (textureUnit->_Current) { /* XXX need this? */
2657 GLchan texel[PB_SIZE][4];
2658
2659 if (textureUnit->LodBias != 0.0F) {
2660 /* apply LOD bias, but don't clamp yet */
2661 GLuint i;
2662 for (i=0;i<n;i++) {
2663 lambda[i] += textureUnit->LodBias;
2664 }
2665 }
2666
2667 if ((textureUnit->_Current->MinLod != -1000.0
2668 || textureUnit->_Current->MaxLod != 1000.0)
2669 && lambda) {
2670 /* apply LOD clamping to lambda */
2671 const GLfloat min = textureUnit->_Current->MinLod;
2672 const GLfloat max = textureUnit->_Current->MaxLod;
2673 GLuint i;
2674 for (i=0;i<n;i++) {
2675 GLfloat l = lambda[i];
2676 lambda[i] = CLAMP(l, min, max);
2677 }
2678 }
2679
2680 /* Sample the texture. */
2681 if (textureUnit->_Current->CompareFlag) {
2682 /* depth texture */
2683 sample_depth_texture(ctx, textureUnit, n, s, t, r, texel);
2684 }
2685 else {
2686 /* color texture */
2687 SWRAST_CONTEXT(ctx)->TextureSample[texUnit]( ctx, texUnit,
2688 textureUnit->_Current,
2689 n, s, t, r,
2690 lambda, texel );
2691 }
2692 apply_texture( ctx, textureUnit, n, primary_rgba,
2693 (const GLchan (*)[4]) texel, rgba );
2694 }
2695 }
2696 }