replace | with & (Laurent Desnogues)
[mesa.git] / src / mesa / swrast / s_texture.c
1 /* $Id: s_texture.c,v 1.79 2003/02/06 13:44:55 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 5.1
6 *
7 * Copyright (C) 1999-2003 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 "imports.h"
34 #include "texformat.h"
35 #include "teximage.h"
36
37 #include "s_context.h"
38 #include "s_texture.h"
39
40
41 /*
42 * These values are used in the fixed-point arithmetic used
43 * for linear filtering.
44 */
45 #define WEIGHT_SCALE 65536.0F
46 #define WEIGHT_SHIFT 16
47
48
49 /*
50 * Used to compute texel locations for linear sampling.
51 * Input:
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
55 * Output:
56 * U = texcoord in [0, width]
57 * I0, I1 = two nearest texel indexes
58 */
59 #define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1) \
60 { \
61 if (wrapMode == GL_REPEAT) { \
62 U = S * SIZE - 0.5F; \
63 I0 = IFLOOR(U) & (SIZE - 1); \
64 I1 = (I0 + 1) & (SIZE - 1); \
65 } \
66 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
67 if (S <= 0.0F) \
68 U = 0.0F; \
69 else if (S >= 1.0F) \
70 U = (GLfloat) SIZE; \
71 else \
72 U = S * SIZE; \
73 U -= 0.5F; \
74 I0 = IFLOOR(U); \
75 I1 = I0 + 1; \
76 if (I0 < 0) \
77 I0 = 0; \
78 if (I1 >= (GLint) SIZE) \
79 I1 = SIZE - 1; \
80 } \
81 else if (wrapMode == GL_CLAMP_TO_BORDER) { \
82 const GLfloat min = -1.0F / (2.0F * SIZE); \
83 const GLfloat max = 1.0F - min; \
84 if (S <= min) \
85 U = min * SIZE; \
86 else if (S >= max) \
87 U = max * SIZE; \
88 else \
89 U = S * SIZE; \
90 U -= 0.5F; \
91 I0 = IFLOOR(U); \
92 I1 = I0 + 1; \
93 } \
94 else if (wrapMode == GL_MIRRORED_REPEAT) { \
95 const GLint flr = IFLOOR(S); \
96 if (flr & 1) \
97 U = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
98 else \
99 U = S - (GLfloat) flr; /* flr is even */ \
100 U = (U * SIZE) - 0.5F; \
101 I0 = IFLOOR(U); \
102 I1 = I0 + 1; \
103 if (I0 < 0) \
104 I0 = 0; \
105 if (I1 >= (GLint) SIZE) \
106 I1 = SIZE - 1; \
107 } \
108 else if (wrapMode == GL_MIRROR_CLAMP_ATI) { \
109 U = (GLfloat) fabs(S); \
110 if (U >= 1.0F) \
111 U = (GLfloat) SIZE; \
112 else \
113 U *= SIZE; \
114 U -= 0.5F; \
115 I0 = IFLOOR(U); \
116 I1 = I0 + 1; \
117 } \
118 else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_ATI) { \
119 U = (GLfloat) fabs(S); \
120 if (U >= 1.0F) \
121 U = (GLfloat) SIZE; \
122 else \
123 U *= SIZE; \
124 U -= 0.5F; \
125 I0 = IFLOOR(U); \
126 I1 = I0 + 1; \
127 if (I0 < 0) \
128 I0 = 0; \
129 if (I1 >= (GLint) SIZE) \
130 I1 = SIZE - 1; \
131 } \
132 else { \
133 ASSERT(wrapMode == GL_CLAMP); \
134 if (S <= 0.0F) \
135 U = 0.0F; \
136 else if (S >= 1.0F) \
137 U = (GLfloat) SIZE; \
138 else \
139 U = S * SIZE; \
140 U -= 0.5F; \
141 I0 = IFLOOR(U); \
142 I1 = I0 + 1; \
143 } \
144 }
145
146
147 /*
148 * Used to compute texel location for nearest sampling.
149 */
150 #define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I) \
151 { \
152 if (wrapMode == GL_REPEAT) { \
153 /* s limited to [0,1) */ \
154 /* i limited to [0,size-1] */ \
155 I = IFLOOR(S * SIZE); \
156 I &= (SIZE - 1); \
157 } \
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; \
163 if (S < min) \
164 I = 0; \
165 else if (S > max) \
166 I = SIZE - 1; \
167 else \
168 I = IFLOOR(S * SIZE); \
169 } \
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; \
175 if (S <= min) \
176 I = -1; \
177 else if (S >= max) \
178 I = SIZE; \
179 else \
180 I = IFLOOR(S * SIZE); \
181 } \
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); \
186 GLfloat u; \
187 if (flr & 1) \
188 u = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
189 else \
190 u = S - (GLfloat) flr; /* flr is even */ \
191 if (u < min) \
192 I = 0; \
193 else if (u > max) \
194 I = SIZE - 1; \
195 else \
196 I = IFLOOR(u * SIZE); \
197 } \
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); \
202 if (u <= 0.0F) \
203 I = 0; \
204 else if (u >= 1.0F) \
205 I = SIZE - 1; \
206 else \
207 I = IFLOOR(u * SIZE); \
208 } \
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); \
215 if (u < min) \
216 I = 0; \
217 else if (u > max) \
218 I = SIZE - 1; \
219 else \
220 I = IFLOOR(u * SIZE); \
221 } \
222 else { \
223 ASSERT(wrapMode == GL_CLAMP); \
224 /* s limited to [0,1] */ \
225 /* i limited to [0,size-1] */ \
226 if (S <= 0.0F) \
227 I = 0; \
228 else if (S >= 1.0F) \
229 I = SIZE - 1; \
230 else \
231 I = IFLOOR(S * SIZE); \
232 } \
233 }
234
235
236 #define COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(S, U, SIZE, I0, I1) \
237 { \
238 U = S * SIZE - 0.5F; \
239 I0 = IFLOOR(U) & (SIZE - 1); \
240 I1 = (I0 + 1) & (SIZE - 1); \
241 }
242
243
244 /*
245 * Compute linear mipmap levels for given lambda.
246 */
247 #define COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level) \
248 { \
249 if (lambda < 0.0F) \
250 level = tObj->BaseLevel; \
251 else if (lambda > tObj->_MaxLambda) \
252 level = (GLint) (tObj->BaseLevel + tObj->_MaxLambda); \
253 else \
254 level = (GLint) (tObj->BaseLevel + lambda); \
255 }
256
257
258 /*
259 * Compute nearest mipmap level for given lambda.
260 */
261 #define COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level) \
262 { \
263 GLfloat l; \
264 if (lambda <= 0.5F) \
265 l = 0.0F; \
266 else if (lambda > tObj->_MaxLambda + 0.4999F) \
267 l = tObj->_MaxLambda + 0.4999F; \
268 else \
269 l = lambda; \
270 level = (GLint) (tObj->BaseLevel + l + 0.5F); \
271 if (level > tObj->_MaxLevel) \
272 level = tObj->_MaxLevel; \
273 }
274
275
276
277 /*
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).
283 */
284 #define FRAC(f) ((f) - IFLOOR(f))
285
286
287
288 /*
289 * Bitflags for texture border color sampling.
290 */
291 #define I0BIT 1
292 #define I1BIT 2
293 #define J0BIT 4
294 #define J1BIT 8
295 #define K0BIT 16
296 #define K1BIT 32
297
298
299 /*
300 * Do the lookup for GL_SGI_texture_color_table.
301 */
302 void
303 _swrast_texture_table_lookup(const struct gl_color_table *table,
304 GLuint n, GLchan rgba[][4])
305 {
306 if (!table->Table || table->Size == 0)
307 return;
308
309 switch (table->Format) {
310 case GL_INTENSITY:
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;
315 GLuint i;
316 for (i = 0; i < n; i++) {
317 GLint j = IROUND((GLfloat) rgba[i][RCOMP] * scale);
318 GLchan c;
319 CLAMPED_FLOAT_TO_CHAN(c, lut[j]);
320 rgba[i][RCOMP] = rgba[i][GCOMP] =
321 rgba[i][BCOMP] = rgba[i][ACOMP] = c;
322 }
323 }
324 else {
325 if (CHAN_TYPE == GL_UNSIGNED_BYTE && table->Size == 256) {
326 /* common case */
327 const GLchan *lut = (const GLchan *) table->Table;
328 GLuint i;
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;
333 }
334 }
335 else {
336 const GLfloat scale = (GLfloat) (table->Size - 1) / CHAN_MAXF;
337 const GLchan *lut = (const GLchan *) table->Table;
338 GLuint i;
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];
343 }
344 }
345 }
346 break;
347 case GL_LUMINANCE:
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;
352 GLuint i;
353 for (i = 0; i < n; i++) {
354 GLint j = IROUND((GLfloat) rgba[i][RCOMP] * scale);
355 GLchan c;
356 CLAMPED_FLOAT_TO_CHAN(c, lut[j]);
357 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = c;
358 }
359 }
360 else {
361 if (CHAN_TYPE == GL_UNSIGNED_BYTE && table->Size == 256) {
362 /* common case */
363 const GLchan *lut = (const GLchan *) table->Table;
364 GLuint i;
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;
368 }
369 }
370 else {
371 const GLfloat scale = (GLfloat) (table->Size - 1) / CHAN_MAXF;
372 const GLchan *lut = (const GLchan *) table->Table;
373 GLuint i;
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];
377 }
378 }
379 }
380 break;
381 case GL_ALPHA:
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;
386 GLuint i;
387 for (i = 0; i < n; i++) {
388 GLint j = IROUND((GLfloat) rgba[i][ACOMP] * scale);
389 GLchan c;
390 CLAMPED_FLOAT_TO_CHAN(c, lut[j]);
391 rgba[i][ACOMP] = c;
392 }
393 }
394 else {
395 if (CHAN_TYPE == GL_UNSIGNED_BYTE && table->Size == 256) {
396 /* common case */
397 const GLchan *lut = (const GLchan *) table->Table;
398 GLuint i;
399 for (i = 0; i < n; i++) {
400 rgba[i][ACOMP] = lut[rgba[i][ACOMP]];
401 }
402 }
403 else {
404 const GLfloat scale = (GLfloat) (table->Size - 1) / CHAN_MAXF;
405 const GLchan *lut = (const GLchan *) table->Table;
406 GLuint i;
407 for (i = 0; i < n; i++) {
408 GLint j = IROUND((GLfloat) rgba[i][ACOMP] * scale);
409 rgba[i][ACOMP] = lut[j];
410 }
411 }
412 }
413 break;
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;
419 GLuint i;
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;;
428 }
429 }
430 else {
431 if (CHAN_TYPE == GL_UNSIGNED_BYTE && table->Size == 256) {
432 /* common case */
433 const GLchan *lut = (const GLchan *) table->Table;
434 GLuint i;
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;
439 rgba[i][ACOMP] = a;
440 }
441 }
442 else {
443 const GLfloat scale = (GLfloat) (table->Size - 1) / CHAN_MAXF;
444 const GLchan *lut = (const GLchan *) table->Table;
445 GLuint i;
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;
453 }
454 }
455 }
456 break;
457 case GL_RGB:
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;
462 GLuint i;
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]);
470 }
471 }
472 else {
473 if (CHAN_TYPE == GL_UNSIGNED_BYTE && table->Size == 256) {
474 /* common case */
475 const GLchan *lut = (const GLchan *) table->Table;
476 GLuint i;
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];
481 }
482 }
483 else {
484 const GLfloat scale = (GLfloat) (table->Size - 1) / CHAN_MAXF;
485 const GLchan *lut = (const GLchan *) table->Table;
486 GLuint i;
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];
494 }
495 }
496 }
497 break;
498 case GL_RGBA:
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;
503 GLuint i;
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];
513 }
514 }
515 else {
516 if (CHAN_TYPE == GL_UNSIGNED_BYTE && table->Size == 256) {
517 /* common case */
518 const GLchan *lut = (const GLchan *) table->Table;
519 GLuint i;
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];
525 }
526 }
527 else {
528 const GLfloat scale = (GLfloat) (table->Size - 1) / CHAN_MAXF;
529 const GLfloat *lut = (const GLfloat *) table->Table;
530 GLuint i;
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]);
540 }
541 }
542 }
543 break;
544 default:
545 _mesa_problem(NULL, "Bad format in _swrast_texture_table_lookup");
546 return;
547 }
548 }
549
550
551
552 /*
553 * Get texture palette entry.
554 */
555 static void
556 palette_sample(const GLcontext *ctx,
557 const struct gl_texture_object *tObj,
558 GLint index, GLchan rgba[4] )
559 {
560 const GLchan *palette;
561 GLenum format;
562
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;
567 }
568 else {
569 ASSERT(!tObj->Palette.FloatTable);
570 palette = (const GLchan *) tObj->Palette.Table;
571 format = tObj->Palette.Format;
572 }
573
574 switch (format) {
575 case GL_ALPHA:
576 rgba[ACOMP] = palette[index];
577 return;
578 case GL_LUMINANCE:
579 case GL_INTENSITY:
580 rgba[RCOMP] = palette[index];
581 return;
582 case GL_LUMINANCE_ALPHA:
583 rgba[RCOMP] = palette[(index << 1) + 0];
584 rgba[ACOMP] = palette[(index << 1) + 1];
585 return;
586 case GL_RGB:
587 rgba[RCOMP] = palette[index * 3 + 0];
588 rgba[GCOMP] = palette[index * 3 + 1];
589 rgba[BCOMP] = palette[index * 3 + 2];
590 return;
591 case GL_RGBA:
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];
596 return;
597 default:
598 _mesa_problem(ctx, "Bad palette format in palette_sample");
599 }
600 }
601
602
603 /*
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.
607 */
608 static INLINE void
609 compute_min_mag_ranges( GLfloat minMagThresh, GLuint n, const GLfloat lambda[],
610 GLuint *minStart, GLuint *minEnd,
611 GLuint *magStart, GLuint *magEnd )
612 {
613 ASSERT(lambda != NULL);
614 #if 0
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.
618 */
619 if (n > 1) {
620 GLuint i;
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));
625 }
626 }
627 else { /* increasing */
628 for (i = 0; i < n - 1; i++) {
629 ASSERT((GLint) (lambda[i] * 10) <= (GLint) (lambda[i+1] * 10));
630 }
631 }
632 }
633 #endif /* DEBUG */
634
635 /* since lambda is monotonous-array use this check first */
636 if (lambda[0] <= minMagThresh && lambda[n-1] <= minMagThresh) {
637 /* magnification for whole span */
638 *magStart = 0;
639 *magEnd = n;
640 *minStart = *minEnd = 0;
641 }
642 else if (lambda[0] > minMagThresh && lambda[n-1] > minMagThresh) {
643 /* minification for whole span */
644 *minStart = 0;
645 *minEnd = n;
646 *magStart = *magEnd = 0;
647 }
648 else {
649 /* a mix of minification and magnification */
650 GLuint i;
651 if (lambda[0] > minMagThresh) {
652 /* start with minification */
653 for (i = 1; i < n; i++) {
654 if (lambda[i] <= minMagThresh)
655 break;
656 }
657 *minStart = 0;
658 *minEnd = i;
659 *magStart = i;
660 *magEnd = n;
661 }
662 else {
663 /* start with magnification */
664 for (i = 1; i < n; i++) {
665 if (lambda[i] > minMagThresh)
666 break;
667 }
668 *magStart = 0;
669 *magEnd = i;
670 *minStart = i;
671 *minEnd = n;
672 }
673 }
674
675 #if 0
676 /* Verify the min/mag Start/End values
677 * We don't use this either (see above)
678 */
679 {
680 GLint i;
681 for (i = 0; i < n; i++) {
682 if (lambda[i] > minMagThresh) {
683 /* minification */
684 ASSERT(i >= *minStart);
685 ASSERT(i < *minEnd);
686 }
687 else {
688 /* magnification */
689 ASSERT(i >= *magStart);
690 ASSERT(i < *magEnd);
691 }
692 }
693 }
694 #endif
695 }
696
697
698 /**********************************************************************/
699 /* 1-D Texture Sampling Functions */
700 /**********************************************************************/
701
702 /*
703 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
704 */
705 static void
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])
710 {
711 const GLint width = img->Width2; /* without border, power of two */
712 GLint i;
713
714 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoord[0], width, i);
715
716 /* skip over the border, if any */
717 i += img->Border;
718
719 if (i < 0 || i >= (GLint) img->Width) {
720 /* Need this test for GL_CLAMP_TO_BORDER mode */
721 COPY_CHAN4(rgba, tObj->_BorderChan);
722 }
723 else {
724 (*img->FetchTexel)(img, i, 0, 0, (GLvoid *) rgba);
725 if (img->Format == GL_COLOR_INDEX) {
726 palette_sample(ctx, tObj, rgba[0], rgba);
727 }
728 }
729 }
730
731
732
733 /*
734 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
735 */
736 static void
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])
741 {
742 const GLint width = img->Width2;
743 GLint i0, i1;
744 GLfloat u;
745 GLuint useBorderColor;
746
747 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoord[0], u, width, i0, i1);
748
749 useBorderColor = 0;
750 if (img->Border) {
751 i0 += img->Border;
752 i1 += img->Border;
753 }
754 else {
755 if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
756 if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
757 }
758
759 {
760 const GLfloat a = FRAC(u);
761
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);
769 #endif
770 GLchan t0[4], t1[4]; /* texels */
771
772 if (useBorderColor & I0BIT) {
773 COPY_CHAN4(t0, tObj->_BorderChan);
774 }
775 else {
776 (*img->FetchTexel)(img, i0, 0, 0, (GLvoid *) t0);
777 if (img->Format == GL_COLOR_INDEX) {
778 palette_sample(ctx, tObj, t0[0], t0);
779 }
780 }
781 if (useBorderColor & I1BIT) {
782 COPY_CHAN4(t1, tObj->_BorderChan);
783 }
784 else {
785 (*img->FetchTexel)(img, i1, 0, 0, (GLvoid *) t1);
786 if (img->Format == GL_COLOR_INDEX) {
787 palette_sample(ctx, tObj, t1[0], t1);
788 }
789 }
790
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);
806 #endif
807
808 }
809 }
810
811
812 static void
813 sample_1d_nearest_mipmap_nearest(GLcontext *ctx,
814 const struct gl_texture_object *tObj,
815 GLuint n, GLfloat texcoord[][4],
816 const GLfloat lambda[], GLchan rgba[][4])
817 {
818 GLuint i;
819 ASSERT(lambda != NULL);
820 for (i = 0; i < n; i++) {
821 GLint level;
822 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
823 sample_1d_nearest(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
824 }
825 }
826
827
828 static void
829 sample_1d_linear_mipmap_nearest(GLcontext *ctx,
830 const struct gl_texture_object *tObj,
831 GLuint n, GLfloat texcoord[][4],
832 const GLfloat lambda[], GLchan rgba[][4])
833 {
834 GLuint i;
835 ASSERT(lambda != NULL);
836 for (i = 0; i < n; i++) {
837 GLint level;
838 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
839 sample_1d_linear(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
840 }
841 }
842
843
844
845 /*
846 * This is really just needed in order to prevent warnings with some compilers.
847 */
848 #if CHAN_TYPE == GL_FLOAT
849 #define CHAN_CAST
850 #else
851 #define CHAN_CAST (GLchan) (GLint)
852 #endif
853
854
855 static void
856 sample_1d_nearest_mipmap_linear(GLcontext *ctx,
857 const struct gl_texture_object *tObj,
858 GLuint n, GLfloat texcoord[][4],
859 const GLfloat lambda[], GLchan rgba[][4])
860 {
861 GLuint i;
862 ASSERT(lambda != NULL);
863 for (i = 0; i < n; i++) {
864 GLint level;
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]);
869 }
870 else {
871 GLchan t0[4], t1[4];
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]);
879 }
880 }
881 }
882
883
884
885 static void
886 sample_1d_linear_mipmap_linear(GLcontext *ctx,
887 const struct gl_texture_object *tObj,
888 GLuint n, GLfloat texcoord[][4],
889 const GLfloat lambda[], GLchan rgba[][4])
890 {
891 GLuint i;
892 ASSERT(lambda != NULL);
893 for (i = 0; i < n; i++) {
894 GLint level;
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]);
899 }
900 else {
901 GLchan t0[4], t1[4];
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]);
909 }
910 }
911 }
912
913
914
915 static void
916 sample_nearest_1d( GLcontext *ctx, GLuint texUnit,
917 const struct gl_texture_object *tObj, GLuint n,
918 GLfloat texcoords[][4], const GLfloat lambda[],
919 GLchan rgba[][4] )
920 {
921 GLuint i;
922 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
923 (void) lambda;
924 for (i=0;i<n;i++) {
925 sample_1d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
926 }
927 }
928
929
930
931 static void
932 sample_linear_1d( GLcontext *ctx, GLuint texUnit,
933 const struct gl_texture_object *tObj, GLuint n,
934 GLfloat texcoords[][4], const GLfloat lambda[],
935 GLchan rgba[][4] )
936 {
937 GLuint i;
938 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
939 (void) lambda;
940 for (i=0;i<n;i++) {
941 sample_1d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
942 }
943 }
944
945
946 /*
947 * Given an (s) texture coordinate and lambda (level of detail) value,
948 * return a texture sample.
949 *
950 */
951 static void
952 sample_lambda_1d( GLcontext *ctx, GLuint texUnit,
953 const struct gl_texture_object *tObj, GLuint n,
954 GLfloat texcoords[][4],
955 const GLfloat lambda[], GLchan rgba[][4] )
956 {
957 GLuint minStart, minEnd; /* texels with minification */
958 GLuint magStart, magEnd; /* texels with magnification */
959 GLuint i;
960
961 ASSERT(lambda != NULL);
962 compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit],
963 n, lambda, &minStart, &minEnd, &magStart, &magEnd);
964
965 if (minStart < minEnd) {
966 /* do the minified texels */
967 const GLuint m = minEnd - minStart;
968 switch (tObj->MinFilter) {
969 case GL_NEAREST:
970 for (i = minStart; i < minEnd; i++)
971 sample_1d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
972 texcoords[i], rgba[i]);
973 break;
974 case GL_LINEAR:
975 for (i = minStart; i < minEnd; i++)
976 sample_1d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
977 texcoords[i], rgba[i]);
978 break;
979 case GL_NEAREST_MIPMAP_NEAREST:
980 sample_1d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
981 lambda + minStart, rgba + minStart);
982 break;
983 case GL_LINEAR_MIPMAP_NEAREST:
984 sample_1d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
985 lambda + minStart, rgba + minStart);
986 break;
987 case GL_NEAREST_MIPMAP_LINEAR:
988 sample_1d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
989 lambda + minStart, rgba + minStart);
990 break;
991 case GL_LINEAR_MIPMAP_LINEAR:
992 sample_1d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
993 lambda + minStart, rgba + minStart);
994 break;
995 default:
996 _mesa_problem(ctx, "Bad min filter in sample_1d_texture");
997 return;
998 }
999 }
1000
1001 if (magStart < magEnd) {
1002 /* do the magnified texels */
1003 switch (tObj->MagFilter) {
1004 case GL_NEAREST:
1005 for (i = magStart; i < magEnd; i++)
1006 sample_1d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
1007 texcoords[i], rgba[i]);
1008 break;
1009 case GL_LINEAR:
1010 for (i = magStart; i < magEnd; i++)
1011 sample_1d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
1012 texcoords[i], rgba[i]);
1013 break;
1014 default:
1015 _mesa_problem(ctx, "Bad mag filter in sample_1d_texture");
1016 return;
1017 }
1018 }
1019 }
1020
1021
1022 /**********************************************************************/
1023 /* 2-D Texture Sampling Functions */
1024 /**********************************************************************/
1025
1026
1027 /*
1028 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
1029 */
1030 static INLINE void
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],
1035 GLchan rgba[])
1036 {
1037 const GLint width = img->Width2; /* without border, power of two */
1038 const GLint height = img->Height2; /* without border, power of two */
1039 GLint i, j;
1040
1041 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoord[0], width, i);
1042 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, texcoord[1], height, j);
1043
1044 /* skip over the border, if any */
1045 i += img->Border;
1046 j += img->Border;
1047
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);
1051 }
1052 else {
1053 (*img->FetchTexel)(img, i, j, 0, (GLvoid *) rgba);
1054 if (img->Format == GL_COLOR_INDEX) {
1055 palette_sample(ctx, tObj, rgba[0], rgba);
1056 }
1057 }
1058 }
1059
1060
1061
1062 /*
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>.
1065 */
1066 static INLINE void
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],
1071 GLchan rgba[])
1072 {
1073 const GLint width = img->Width2;
1074 const GLint height = img->Height2;
1075 GLint i0, j0, i1, j1;
1076 GLuint useBorderColor;
1077 GLfloat u, v;
1078
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);
1081
1082 useBorderColor = 0;
1083 if (img->Border) {
1084 i0 += img->Border;
1085 i1 += img->Border;
1086 j0 += img->Border;
1087 j1 += img->Border;
1088 }
1089 else {
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;
1094 }
1095
1096 {
1097 const GLfloat a = FRAC(u);
1098 const GLfloat b = FRAC(v);
1099
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);
1111 #endif
1112 GLchan t00[4];
1113 GLchan t10[4];
1114 GLchan t01[4];
1115 GLchan t11[4];
1116
1117 if (useBorderColor & (I0BIT | J0BIT)) {
1118 COPY_CHAN4(t00, tObj->_BorderChan);
1119 }
1120 else {
1121 (*img->FetchTexel)(img, i0, j0, 0, (GLvoid *) t00);
1122 if (img->Format == GL_COLOR_INDEX) {
1123 palette_sample(ctx, tObj, t00[0], t00);
1124 }
1125 }
1126 if (useBorderColor & (I1BIT | J0BIT)) {
1127 COPY_CHAN4(t10, tObj->_BorderChan);
1128 }
1129 else {
1130 (*img->FetchTexel)(img, i1, j0, 0, (GLvoid *) t10);
1131 if (img->Format == GL_COLOR_INDEX) {
1132 palette_sample(ctx, tObj, t10[0], t10);
1133 }
1134 }
1135 if (useBorderColor & (I0BIT | J1BIT)) {
1136 COPY_CHAN4(t01, tObj->_BorderChan);
1137 }
1138 else {
1139 (*img->FetchTexel)(img, i0, j1, 0, (GLvoid *) t01);
1140 if (img->Format == GL_COLOR_INDEX) {
1141 palette_sample(ctx, tObj, t01[0], t01);
1142 }
1143 }
1144 if (useBorderColor & (I1BIT | J1BIT)) {
1145 COPY_CHAN4(t11, tObj->_BorderChan);
1146 }
1147 else {
1148 (*img->FetchTexel)(img, i1, j1, 0, (GLvoid *) t11);
1149 if (img->Format == GL_COLOR_INDEX) {
1150 palette_sample(ctx, tObj, t11[0], t11);
1151 }
1152 }
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);
1176 #endif
1177
1178 }
1179
1180 }
1181
1182
1183 /*
1184 * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT
1185 * and we're not using a paletted texture.
1186 */
1187 static INLINE void
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],
1192 GLchan rgba[])
1193 {
1194 const GLint width = img->Width2;
1195 const GLint height = img->Height2;
1196 GLint i0, j0, i1, j1;
1197 GLfloat u, v;
1198
1199 ASSERT(tObj->WrapS == GL_REPEAT);
1200 ASSERT(tObj->WrapT == GL_REPEAT);
1201 ASSERT(img->Border == 0);
1202 ASSERT(img->Format != GL_COLOR_INDEX);
1203
1204 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord[0], u, width, i0, i1);
1205 COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord[1], v, height, j0, j1);
1206
1207 {
1208 const GLfloat a = FRAC(u);
1209 const GLfloat b = FRAC(v);
1210
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);
1222 #endif
1223 GLchan t00[4];
1224 GLchan t10[4];
1225 GLchan t01[4];
1226 GLchan t11[4];
1227
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);
1232
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);
1256 #endif
1257
1258 }
1259
1260 }
1261
1262
1263
1264 static void
1265 sample_2d_nearest_mipmap_nearest(GLcontext *ctx,
1266 const struct gl_texture_object *tObj,
1267 GLuint n, GLfloat texcoord[][4],
1268 const GLfloat lambda[], GLchan rgba[][4])
1269 {
1270 GLuint i;
1271 for (i = 0; i < n; i++) {
1272 GLint level;
1273 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
1274 sample_2d_nearest(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
1275 }
1276 }
1277
1278
1279
1280 static void
1281 sample_2d_linear_mipmap_nearest(GLcontext *ctx,
1282 const struct gl_texture_object *tObj,
1283 GLuint n, GLfloat texcoord[][4],
1284 const GLfloat lambda[], GLchan rgba[][4])
1285 {
1286 GLuint i;
1287 ASSERT(lambda != NULL);
1288 for (i = 0; i < n; i++) {
1289 GLint level;
1290 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
1291 sample_2d_linear(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
1292 }
1293 }
1294
1295
1296
1297 static void
1298 sample_2d_nearest_mipmap_linear(GLcontext *ctx,
1299 const struct gl_texture_object *tObj,
1300 GLuint n, GLfloat texcoord[][4],
1301 const GLfloat lambda[], GLchan rgba[][4])
1302 {
1303 GLuint i;
1304 ASSERT(lambda != NULL);
1305 for (i = 0; i < n; i++) {
1306 GLint level;
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]);
1311 }
1312 else {
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]);
1321 }
1322 }
1323 }
1324
1325
1326
1327 /* Trilinear filtering */
1328 static void
1329 sample_2d_linear_mipmap_linear( GLcontext *ctx,
1330 const struct gl_texture_object *tObj,
1331 GLuint n, GLfloat texcoord[][4],
1332 const GLfloat lambda[], GLchan rgba[][4] )
1333 {
1334 GLuint i;
1335 ASSERT(lambda != NULL);
1336 for (i = 0; i < n; i++) {
1337 GLint level;
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]);
1342 }
1343 else {
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]);
1352 }
1353 }
1354 }
1355
1356
1357 static void
1358 sample_2d_linear_mipmap_linear_repeat( GLcontext *ctx,
1359 const struct gl_texture_object *tObj,
1360 GLuint n, GLfloat texcoord[][4],
1361 const GLfloat lambda[], GLchan rgba[][4] )
1362 {
1363 GLuint i;
1364 ASSERT(lambda != NULL);
1365 ASSERT(tObj->WrapS == GL_REPEAT);
1366 ASSERT(tObj->WrapT == GL_REPEAT);
1367 for (i = 0; i < n; i++) {
1368 GLint level;
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]);
1373 }
1374 else {
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]);
1383 }
1384 }
1385 }
1386
1387
1388 static void
1389 sample_nearest_2d( GLcontext *ctx, GLuint texUnit,
1390 const struct gl_texture_object *tObj, GLuint n,
1391 GLfloat texcoords[][4],
1392 const GLfloat lambda[], GLchan rgba[][4] )
1393 {
1394 GLuint i;
1395 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
1396 (void) lambda;
1397 for (i=0;i<n;i++) {
1398 sample_2d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
1399 }
1400 }
1401
1402
1403
1404 static void
1405 sample_linear_2d( GLcontext *ctx, GLuint texUnit,
1406 const struct gl_texture_object *tObj, GLuint n,
1407 GLfloat texcoords[][4],
1408 const GLfloat lambda[], GLchan rgba[][4] )
1409 {
1410 GLuint i;
1411 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
1412 (void) lambda;
1413 for (i=0;i<n;i++) {
1414 sample_2d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
1415 }
1416 }
1417
1418
1419 /*
1420 * Optimized 2-D texture sampling:
1421 * S and T wrap mode == GL_REPEAT
1422 * GL_NEAREST min/mag filter
1423 * No border,
1424 * RowStride == Width,
1425 * Format = GL_RGB
1426 */
1427 static void
1428 opt_sample_rgb_2d( GLcontext *ctx, GLuint texUnit,
1429 const struct gl_texture_object *tObj,
1430 GLuint n, GLfloat texcoords[][4],
1431 const GLfloat lambda[], GLchan rgba[][4] )
1432 {
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;
1439 GLuint k;
1440 (void) lambda;
1441 ASSERT(tObj->WrapS==GL_REPEAT);
1442 ASSERT(tObj->WrapT==GL_REPEAT);
1443 ASSERT(img->Border==0);
1444 ASSERT(img->Format==GL_RGB);
1445
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];
1454 }
1455 }
1456
1457
1458 /*
1459 * Optimized 2-D texture sampling:
1460 * S and T wrap mode == GL_REPEAT
1461 * GL_NEAREST min/mag filter
1462 * No border
1463 * RowStride == Width,
1464 * Format = GL_RGBA
1465 */
1466 static void
1467 opt_sample_rgba_2d( GLcontext *ctx, GLuint texUnit,
1468 const struct gl_texture_object *tObj,
1469 GLuint n, GLfloat texcoords[][4],
1470 const GLfloat lambda[], GLchan rgba[][4] )
1471 {
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;
1478 GLuint i;
1479 (void) lambda;
1480 ASSERT(tObj->WrapS==GL_REPEAT);
1481 ASSERT(tObj->WrapT==GL_REPEAT);
1482 ASSERT(img->Border==0);
1483 ASSERT(img->Format==GL_RGBA);
1484
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);
1491 }
1492 }
1493
1494
1495 /*
1496 * Given an array of texture coordinate and lambda (level of detail)
1497 * values, return an array of texture sample.
1498 */
1499 static void
1500 sample_lambda_2d( GLcontext *ctx, GLuint texUnit,
1501 const struct gl_texture_object *tObj,
1502 GLuint n, GLfloat texcoords[][4],
1503 const GLfloat lambda[], GLchan rgba[][4] )
1504 {
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 */
1508
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);
1513
1514 ASSERT(lambda != NULL);
1515 compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit],
1516 n, lambda, &minStart, &minEnd, &magStart, &magEnd);
1517
1518 if (minStart < minEnd) {
1519 /* do the minified texels */
1520 const GLuint m = minEnd - minStart;
1521 switch (tObj->MinFilter) {
1522 case GL_NEAREST:
1523 if (repeatNoBorder) {
1524 switch (tImg->Format) {
1525 case GL_RGB:
1526 opt_sample_rgb_2d(ctx, texUnit, tObj, m, texcoords + minStart,
1527 NULL, rgba + minStart);
1528 break;
1529 case GL_RGBA:
1530 opt_sample_rgba_2d(ctx, texUnit, tObj, m, texcoords + minStart,
1531 NULL, rgba + minStart);
1532 break;
1533 default:
1534 sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + minStart,
1535 NULL, rgba + minStart );
1536 }
1537 }
1538 else {
1539 sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + minStart,
1540 NULL, rgba + minStart);
1541 }
1542 break;
1543 case GL_LINEAR:
1544 sample_linear_2d(ctx, texUnit, tObj, m, texcoords + minStart,
1545 NULL, rgba + minStart);
1546 break;
1547 case GL_NEAREST_MIPMAP_NEAREST:
1548 sample_2d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
1549 lambda + minStart, rgba + minStart);
1550 break;
1551 case GL_LINEAR_MIPMAP_NEAREST:
1552 sample_2d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
1553 lambda + minStart, rgba + minStart);
1554 break;
1555 case GL_NEAREST_MIPMAP_LINEAR:
1556 sample_2d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
1557 lambda + minStart, rgba + minStart);
1558 break;
1559 case GL_LINEAR_MIPMAP_LINEAR:
1560 if (repeatNoBorder)
1561 sample_2d_linear_mipmap_linear_repeat(ctx, tObj, m,
1562 texcoords + minStart, lambda + minStart, rgba + minStart);
1563 else
1564 sample_2d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
1565 lambda + minStart, rgba + minStart);
1566 break;
1567 default:
1568 _mesa_problem(ctx, "Bad min filter in sample_2d_texture");
1569 return;
1570 }
1571 }
1572
1573 if (magStart < magEnd) {
1574 /* do the magnified texels */
1575 const GLuint m = magEnd - magStart;
1576
1577 switch (tObj->MagFilter) {
1578 case GL_NEAREST:
1579 if (repeatNoBorder) {
1580 switch (tImg->Format) {
1581 case GL_RGB:
1582 opt_sample_rgb_2d(ctx, texUnit, tObj, m, texcoords + magStart,
1583 NULL, rgba + magStart);
1584 break;
1585 case GL_RGBA:
1586 opt_sample_rgba_2d(ctx, texUnit, tObj, m, texcoords + magStart,
1587 NULL, rgba + magStart);
1588 break;
1589 default:
1590 sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + magStart,
1591 NULL, rgba + magStart );
1592 }
1593 }
1594 else {
1595 sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + magStart,
1596 NULL, rgba + magStart);
1597 }
1598 break;
1599 case GL_LINEAR:
1600 sample_linear_2d(ctx, texUnit, tObj, m, texcoords + magStart,
1601 NULL, rgba + magStart);
1602 break;
1603 default:
1604 _mesa_problem(ctx, "Bad mag filter in sample_lambda_2d");
1605 }
1606 }
1607 }
1608
1609
1610
1611 /**********************************************************************/
1612 /* 3-D Texture Sampling Functions */
1613 /**********************************************************************/
1614
1615 /*
1616 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1617 */
1618 static void
1619 sample_3d_nearest(GLcontext *ctx,
1620 const struct gl_texture_object *tObj,
1621 const struct gl_texture_image *img,
1622 const GLfloat texcoord[4],
1623 GLchan rgba[4])
1624 {
1625 const GLint width = img->Width2; /* without border, power of two */
1626 const GLint height = img->Height2; /* without border, power of two */
1627 const GLint depth = img->Depth2; /* without border, power of two */
1628 GLint i, j, k;
1629
1630 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoord[0], width, i);
1631 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, texcoord[1], height, j);
1632 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapR, texcoord[2], depth, k);
1633
1634 if (i < 0 || i >= (GLint) img->Width ||
1635 j < 0 || j >= (GLint) img->Height ||
1636 k < 0 || k >= (GLint) img->Depth) {
1637 /* Need this test for GL_CLAMP_TO_BORDER mode */
1638 COPY_CHAN4(rgba, tObj->_BorderChan);
1639 }
1640 else {
1641 (*img->FetchTexel)(img, i, j, k, (GLvoid *) rgba);
1642 if (img->Format == GL_COLOR_INDEX) {
1643 palette_sample(ctx, tObj, rgba[0], rgba);
1644 }
1645 }
1646 }
1647
1648
1649
1650 /*
1651 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1652 */
1653 static void
1654 sample_3d_linear(GLcontext *ctx,
1655 const struct gl_texture_object *tObj,
1656 const struct gl_texture_image *img,
1657 const GLfloat texcoord[4],
1658 GLchan rgba[4])
1659 {
1660 const GLint width = img->Width2;
1661 const GLint height = img->Height2;
1662 const GLint depth = img->Depth2;
1663 GLint i0, j0, k0, i1, j1, k1;
1664 GLuint useBorderColor;
1665 GLfloat u, v, w;
1666
1667 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoord[0], u, width, i0, i1);
1668 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, texcoord[1], v, height, j0, j1);
1669 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapR, texcoord[2], w, depth, k0, k1);
1670
1671 useBorderColor = 0;
1672 if (img->Border) {
1673 i0 += img->Border;
1674 i1 += img->Border;
1675 j0 += img->Border;
1676 j1 += img->Border;
1677 k0 += img->Border;
1678 k1 += img->Border;
1679 }
1680 else {
1681 /* check if sampling texture border color */
1682 if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
1683 if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
1684 if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT;
1685 if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT;
1686 if (k0 < 0 || k0 >= depth) useBorderColor |= K0BIT;
1687 if (k1 < 0 || k1 >= depth) useBorderColor |= K1BIT;
1688 }
1689
1690 {
1691 const GLfloat a = FRAC(u);
1692 const GLfloat b = FRAC(v);
1693 const GLfloat c = FRAC(w);
1694
1695 #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1696 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1697 GLfloat w000 = (1.0F-a) * (1.0F-b) * (1.0F-c);
1698 GLfloat w100 = a * (1.0F-b) * (1.0F-c);
1699 GLfloat w010 = (1.0F-a) * b * (1.0F-c);
1700 GLfloat w110 = a * b * (1.0F-c);
1701 GLfloat w001 = (1.0F-a) * (1.0F-b) * c ;
1702 GLfloat w101 = a * (1.0F-b) * c ;
1703 GLfloat w011 = (1.0F-a) * b * c ;
1704 GLfloat w111 = a * b * c ;
1705 #else /* CHAN_BITS == 8 */
1706 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1707 GLint w000 = IROUND_POS((1.0F-a) * (1.0F-b) * (1.0F-c) * WEIGHT_SCALE);
1708 GLint w100 = IROUND_POS( a * (1.0F-b) * (1.0F-c) * WEIGHT_SCALE);
1709 GLint w010 = IROUND_POS((1.0F-a) * b * (1.0F-c) * WEIGHT_SCALE);
1710 GLint w110 = IROUND_POS( a * b * (1.0F-c) * WEIGHT_SCALE);
1711 GLint w001 = IROUND_POS((1.0F-a) * (1.0F-b) * c * WEIGHT_SCALE);
1712 GLint w101 = IROUND_POS( a * (1.0F-b) * c * WEIGHT_SCALE);
1713 GLint w011 = IROUND_POS((1.0F-a) * b * c * WEIGHT_SCALE);
1714 GLint w111 = IROUND_POS( a * b * c * WEIGHT_SCALE);
1715 #endif
1716
1717 GLchan t000[4], t010[4], t001[4], t011[4];
1718 GLchan t100[4], t110[4], t101[4], t111[4];
1719
1720 if (useBorderColor & (I0BIT | J0BIT | K0BIT)) {
1721 COPY_CHAN4(t000, tObj->_BorderChan);
1722 }
1723 else {
1724 (*img->FetchTexel)(img, i0, j0, k0, (GLvoid *) t000);
1725 if (img->Format == GL_COLOR_INDEX) {
1726 palette_sample(ctx, tObj, t000[0], t000);
1727 }
1728 }
1729 if (useBorderColor & (I1BIT | J0BIT | K0BIT)) {
1730 COPY_CHAN4(t100, tObj->_BorderChan);
1731 }
1732 else {
1733 (*img->FetchTexel)(img, i1, j0, k0, (GLvoid *) t100);
1734 if (img->Format == GL_COLOR_INDEX) {
1735 palette_sample(ctx, tObj, t100[0], t100);
1736 }
1737 }
1738 if (useBorderColor & (I0BIT | J1BIT | K0BIT)) {
1739 COPY_CHAN4(t010, tObj->_BorderChan);
1740 }
1741 else {
1742 (*img->FetchTexel)(img, i0, j1, k0, (GLvoid *) t010);
1743 if (img->Format == GL_COLOR_INDEX) {
1744 palette_sample(ctx, tObj, t010[0], t010);
1745 }
1746 }
1747 if (useBorderColor & (I1BIT | J1BIT | K0BIT)) {
1748 COPY_CHAN4(t110, tObj->_BorderChan);
1749 }
1750 else {
1751 (*img->FetchTexel)(img, i1, j1, k0, (GLvoid *) t110);
1752 if (img->Format == GL_COLOR_INDEX) {
1753 palette_sample(ctx, tObj, t110[0], t110);
1754 }
1755 }
1756
1757 if (useBorderColor & (I0BIT | J0BIT | K1BIT)) {
1758 COPY_CHAN4(t001, tObj->_BorderChan);
1759 }
1760 else {
1761 (*img->FetchTexel)(img, i0, j0, k1, (GLvoid *) t001);
1762 if (img->Format == GL_COLOR_INDEX) {
1763 palette_sample(ctx, tObj, t001[0], t001);
1764 }
1765 }
1766 if (useBorderColor & (I1BIT | J0BIT | K1BIT)) {
1767 COPY_CHAN4(t101, tObj->_BorderChan);
1768 }
1769 else {
1770 (*img->FetchTexel)(img, i1, j0, k1, (GLvoid *) t101);
1771 if (img->Format == GL_COLOR_INDEX) {
1772 palette_sample(ctx, tObj, t101[0], t101);
1773 }
1774 }
1775 if (useBorderColor & (I0BIT | J1BIT | K1BIT)) {
1776 COPY_CHAN4(t011, tObj->_BorderChan);
1777 }
1778 else {
1779 (*img->FetchTexel)(img, i0, j1, k1, (GLvoid *) t011);
1780 if (img->Format == GL_COLOR_INDEX) {
1781 palette_sample(ctx, tObj, t011[0], t011);
1782 }
1783 }
1784 if (useBorderColor & (I1BIT | J1BIT | K1BIT)) {
1785 COPY_CHAN4(t111, tObj->_BorderChan);
1786 }
1787 else {
1788 (*img->FetchTexel)(img, i1, j1, k1, (GLvoid *) t111);
1789 if (img->Format == GL_COLOR_INDEX) {
1790 palette_sample(ctx, tObj, t111[0], t111);
1791 }
1792 }
1793
1794 #if CHAN_TYPE == GL_FLOAT
1795 rgba[0] = w000*t000[0] + w010*t010[0] + w001*t001[0] + w011*t011[0] +
1796 w100*t100[0] + w110*t110[0] + w101*t101[0] + w111*t111[0];
1797 rgba[1] = w000*t000[1] + w010*t010[1] + w001*t001[1] + w011*t011[1] +
1798 w100*t100[1] + w110*t110[1] + w101*t101[1] + w111*t111[1];
1799 rgba[2] = w000*t000[2] + w010*t010[2] + w001*t001[2] + w011*t011[2] +
1800 w100*t100[2] + w110*t110[2] + w101*t101[2] + w111*t111[2];
1801 rgba[3] = w000*t000[3] + w010*t010[3] + w001*t001[3] + w011*t011[3] +
1802 w100*t100[3] + w110*t110[3] + w101*t101[3] + w111*t111[3];
1803 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
1804 rgba[0] = (GLchan) (w000*t000[0] + w010*t010[0] +
1805 w001*t001[0] + w011*t011[0] +
1806 w100*t100[0] + w110*t110[0] +
1807 w101*t101[0] + w111*t111[0] + 0.5);
1808 rgba[1] = (GLchan) (w000*t000[1] + w010*t010[1] +
1809 w001*t001[1] + w011*t011[1] +
1810 w100*t100[1] + w110*t110[1] +
1811 w101*t101[1] + w111*t111[1] + 0.5);
1812 rgba[2] = (GLchan) (w000*t000[2] + w010*t010[2] +
1813 w001*t001[2] + w011*t011[2] +
1814 w100*t100[2] + w110*t110[2] +
1815 w101*t101[2] + w111*t111[2] + 0.5);
1816 rgba[3] = (GLchan) (w000*t000[3] + w010*t010[3] +
1817 w001*t001[3] + w011*t011[3] +
1818 w100*t100[3] + w110*t110[3] +
1819 w101*t101[3] + w111*t111[3] + 0.5);
1820 #else /* CHAN_BITS == 8 */
1821 rgba[0] = (GLchan) (
1822 (w000*t000[0] + w010*t010[0] + w001*t001[0] + w011*t011[0] +
1823 w100*t100[0] + w110*t110[0] + w101*t101[0] + w111*t111[0] )
1824 >> WEIGHT_SHIFT);
1825 rgba[1] = (GLchan) (
1826 (w000*t000[1] + w010*t010[1] + w001*t001[1] + w011*t011[1] +
1827 w100*t100[1] + w110*t110[1] + w101*t101[1] + w111*t111[1] )
1828 >> WEIGHT_SHIFT);
1829 rgba[2] = (GLchan) (
1830 (w000*t000[2] + w010*t010[2] + w001*t001[2] + w011*t011[2] +
1831 w100*t100[2] + w110*t110[2] + w101*t101[2] + w111*t111[2] )
1832 >> WEIGHT_SHIFT);
1833 rgba[3] = (GLchan) (
1834 (w000*t000[3] + w010*t010[3] + w001*t001[3] + w011*t011[3] +
1835 w100*t100[3] + w110*t110[3] + w101*t101[3] + w111*t111[3] )
1836 >> WEIGHT_SHIFT);
1837 #endif
1838
1839 }
1840 }
1841
1842
1843
1844 static void
1845 sample_3d_nearest_mipmap_nearest(GLcontext *ctx,
1846 const struct gl_texture_object *tObj,
1847 GLuint n, GLfloat texcoord[][4],
1848 const GLfloat lambda[], GLchan rgba[][4] )
1849 {
1850 GLuint i;
1851 for (i = 0; i < n; i++) {
1852 GLint level;
1853 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
1854 sample_3d_nearest(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
1855 }
1856 }
1857
1858
1859 static void
1860 sample_3d_linear_mipmap_nearest(GLcontext *ctx,
1861 const struct gl_texture_object *tObj,
1862 GLuint n, GLfloat texcoord[][4],
1863 const GLfloat lambda[], GLchan rgba[][4])
1864 {
1865 GLuint i;
1866 ASSERT(lambda != NULL);
1867 for (i = 0; i < n; i++) {
1868 GLint level;
1869 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
1870 sample_3d_linear(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
1871 }
1872 }
1873
1874
1875 static void
1876 sample_3d_nearest_mipmap_linear(GLcontext *ctx,
1877 const struct gl_texture_object *tObj,
1878 GLuint n, GLfloat texcoord[][4],
1879 const GLfloat lambda[], GLchan rgba[][4])
1880 {
1881 GLuint i;
1882 ASSERT(lambda != NULL);
1883 for (i = 0; i < n; i++) {
1884 GLint level;
1885 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
1886 if (level >= tObj->_MaxLevel) {
1887 sample_3d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel],
1888 texcoord[i], rgba[i]);
1889 }
1890 else {
1891 GLchan t0[4], t1[4]; /* texels */
1892 const GLfloat f = FRAC(lambda[i]);
1893 sample_3d_nearest(ctx, tObj, tObj->Image[level ], texcoord[i], t0);
1894 sample_3d_nearest(ctx, tObj, tObj->Image[level+1], texcoord[i], t1);
1895 rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
1896 rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
1897 rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
1898 rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
1899 }
1900 }
1901 }
1902
1903
1904 static void
1905 sample_3d_linear_mipmap_linear(GLcontext *ctx,
1906 const struct gl_texture_object *tObj,
1907 GLuint n, GLfloat texcoord[][4],
1908 const GLfloat lambda[], GLchan rgba[][4])
1909 {
1910 GLuint i;
1911 ASSERT(lambda != NULL);
1912 for (i = 0; i < n; i++) {
1913 GLint level;
1914 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
1915 if (level >= tObj->_MaxLevel) {
1916 sample_3d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel],
1917 texcoord[i], rgba[i]);
1918 }
1919 else {
1920 GLchan t0[4], t1[4]; /* texels */
1921 const GLfloat f = FRAC(lambda[i]);
1922 sample_3d_linear(ctx, tObj, tObj->Image[level ], texcoord[i], t0);
1923 sample_3d_linear(ctx, tObj, tObj->Image[level+1], texcoord[i], t1);
1924 rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
1925 rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
1926 rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
1927 rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
1928 }
1929 }
1930 }
1931
1932
1933 static void
1934 sample_nearest_3d(GLcontext *ctx, GLuint texUnit,
1935 const struct gl_texture_object *tObj, GLuint n,
1936 GLfloat texcoords[][4], const GLfloat lambda[],
1937 GLchan rgba[][4])
1938 {
1939 GLuint i;
1940 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
1941 (void) lambda;
1942 for (i=0;i<n;i++) {
1943 sample_3d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
1944 }
1945 }
1946
1947
1948
1949 static void
1950 sample_linear_3d( GLcontext *ctx, GLuint texUnit,
1951 const struct gl_texture_object *tObj, GLuint n,
1952 GLfloat texcoords[][4],
1953 const GLfloat lambda[], GLchan rgba[][4] )
1954 {
1955 GLuint i;
1956 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
1957 (void) lambda;
1958 for (i=0;i<n;i++) {
1959 sample_3d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
1960 }
1961 }
1962
1963
1964 /*
1965 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
1966 * return a texture sample.
1967 */
1968 static void
1969 sample_lambda_3d( GLcontext *ctx, GLuint texUnit,
1970 const struct gl_texture_object *tObj, GLuint n,
1971 GLfloat texcoords[][4], const GLfloat lambda[],
1972 GLchan rgba[][4] )
1973 {
1974 GLuint minStart, minEnd; /* texels with minification */
1975 GLuint magStart, magEnd; /* texels with magnification */
1976 GLuint i;
1977
1978 ASSERT(lambda != NULL);
1979 compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit],
1980 n, lambda, &minStart, &minEnd, &magStart, &magEnd);
1981
1982 if (minStart < minEnd) {
1983 /* do the minified texels */
1984 GLuint m = minEnd - minStart;
1985 switch (tObj->MinFilter) {
1986 case GL_NEAREST:
1987 for (i = minStart; i < minEnd; i++)
1988 sample_3d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
1989 texcoords[i], rgba[i]);
1990 break;
1991 case GL_LINEAR:
1992 for (i = minStart; i < minEnd; i++)
1993 sample_3d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
1994 texcoords[i], rgba[i]);
1995 break;
1996 case GL_NEAREST_MIPMAP_NEAREST:
1997 sample_3d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
1998 lambda + minStart, rgba + minStart);
1999 break;
2000 case GL_LINEAR_MIPMAP_NEAREST:
2001 sample_3d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
2002 lambda + minStart, rgba + minStart);
2003 break;
2004 case GL_NEAREST_MIPMAP_LINEAR:
2005 sample_3d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
2006 lambda + minStart, rgba + minStart);
2007 break;
2008 case GL_LINEAR_MIPMAP_LINEAR:
2009 sample_3d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
2010 lambda + minStart, rgba + minStart);
2011 break;
2012 default:
2013 _mesa_problem(ctx, "Bad min filter in sample_3d_texture");
2014 return;
2015 }
2016 }
2017
2018 if (magStart < magEnd) {
2019 /* do the magnified texels */
2020 switch (tObj->MagFilter) {
2021 case GL_NEAREST:
2022 for (i = magStart; i < magEnd; i++)
2023 sample_3d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
2024 texcoords[i], rgba[i]);
2025 break;
2026 case GL_LINEAR:
2027 for (i = magStart; i < magEnd; i++)
2028 sample_3d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
2029 texcoords[i], rgba[i]);
2030 break;
2031 default:
2032 _mesa_problem(ctx, "Bad mag filter in sample_3d_texture");
2033 return;
2034 }
2035 }
2036 }
2037
2038
2039 /**********************************************************************/
2040 /* Texture Cube Map Sampling Functions */
2041 /**********************************************************************/
2042
2043 /*
2044 * Choose one of six sides of a texture cube map given the texture
2045 * coord (rx,ry,rz). Return pointer to corresponding array of texture
2046 * images.
2047 */
2048 static const struct gl_texture_image **
2049 choose_cube_face(const struct gl_texture_object *texObj,
2050 const GLfloat texcoord[4], GLfloat newCoord[4])
2051 {
2052 /*
2053 major axis
2054 direction target sc tc ma
2055 ---------- ------------------------------- --- --- ---
2056 +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
2057 -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
2058 +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
2059 -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
2060 +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
2061 -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
2062 */
2063 const GLfloat rx = texcoord[0];
2064 const GLfloat ry = texcoord[1];
2065 const GLfloat rz = texcoord[2];
2066 const struct gl_texture_image **imgArray;
2067 const GLfloat arx = ABSF(rx), ary = ABSF(ry), arz = ABSF(rz);
2068 GLfloat sc, tc, ma;
2069
2070 if (arx > ary && arx > arz) {
2071 if (rx >= 0.0F) {
2072 imgArray = (const struct gl_texture_image **) texObj->Image;
2073 sc = -rz;
2074 tc = -ry;
2075 ma = arx;
2076 }
2077 else {
2078 imgArray = (const struct gl_texture_image **) texObj->NegX;
2079 sc = rz;
2080 tc = -ry;
2081 ma = arx;
2082 }
2083 }
2084 else if (ary > arx && ary > arz) {
2085 if (ry >= 0.0F) {
2086 imgArray = (const struct gl_texture_image **) texObj->PosY;
2087 sc = rx;
2088 tc = rz;
2089 ma = ary;
2090 }
2091 else {
2092 imgArray = (const struct gl_texture_image **) texObj->NegY;
2093 sc = rx;
2094 tc = -rz;
2095 ma = ary;
2096 }
2097 }
2098 else {
2099 if (rz > 0.0F) {
2100 imgArray = (const struct gl_texture_image **) texObj->PosZ;
2101 sc = rx;
2102 tc = -ry;
2103 ma = arz;
2104 }
2105 else {
2106 imgArray = (const struct gl_texture_image **) texObj->NegZ;
2107 sc = -rx;
2108 tc = -ry;
2109 ma = arz;
2110 }
2111 }
2112
2113 newCoord[0] = ( sc / ma + 1.0F ) * 0.5F;
2114 newCoord[1] = ( tc / ma + 1.0F ) * 0.5F;
2115 return imgArray;
2116 }
2117
2118
2119 static void
2120 sample_nearest_cube(GLcontext *ctx, GLuint texUnit,
2121 const struct gl_texture_object *tObj, GLuint n,
2122 GLfloat texcoords[][4], const GLfloat lambda[],
2123 GLchan rgba[][4])
2124 {
2125 GLuint i;
2126 (void) lambda;
2127 for (i = 0; i < n; i++) {
2128 const struct gl_texture_image **images;
2129 GLfloat newCoord[4];
2130 images = choose_cube_face(tObj, texcoords[i], newCoord);
2131 sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel],
2132 newCoord, rgba[i]);
2133 }
2134 }
2135
2136
2137 static void
2138 sample_linear_cube(GLcontext *ctx, GLuint texUnit,
2139 const struct gl_texture_object *tObj, GLuint n,
2140 GLfloat texcoords[][4],
2141 const GLfloat lambda[], GLchan rgba[][4])
2142 {
2143 GLuint i;
2144 (void) lambda;
2145 for (i = 0; i < n; i++) {
2146 const struct gl_texture_image **images;
2147 GLfloat newCoord[4];
2148 images = choose_cube_face(tObj, texcoords[i], newCoord);
2149 sample_2d_linear(ctx, tObj, images[tObj->BaseLevel],
2150 newCoord, rgba[i]);
2151 }
2152 }
2153
2154
2155 static void
2156 sample_cube_nearest_mipmap_nearest(GLcontext *ctx, GLuint texUnit,
2157 const struct gl_texture_object *tObj,
2158 GLuint n, GLfloat texcoord[][4],
2159 const GLfloat lambda[], GLchan rgba[][4])
2160 {
2161 GLuint i;
2162 ASSERT(lambda != NULL);
2163 for (i = 0; i < n; i++) {
2164 const struct gl_texture_image **images;
2165 GLfloat newCoord[4];
2166 GLint level;
2167 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
2168 images = choose_cube_face(tObj, texcoord[i], newCoord);
2169 sample_2d_nearest(ctx, tObj, images[level], newCoord, rgba[i]);
2170 }
2171 }
2172
2173
2174 static void
2175 sample_cube_linear_mipmap_nearest(GLcontext *ctx, GLuint texUnit,
2176 const struct gl_texture_object *tObj,
2177 GLuint n, GLfloat texcoord[][4],
2178 const GLfloat lambda[], GLchan rgba[][4])
2179 {
2180 GLuint i;
2181 ASSERT(lambda != NULL);
2182 for (i = 0; i < n; i++) {
2183 const struct gl_texture_image **images;
2184 GLfloat newCoord[4];
2185 GLint level;
2186 COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
2187 images = choose_cube_face(tObj, texcoord[i], newCoord);
2188 sample_2d_linear(ctx, tObj, images[level], newCoord, rgba[i]);
2189 }
2190 }
2191
2192
2193 static void
2194 sample_cube_nearest_mipmap_linear(GLcontext *ctx, GLuint texUnit,
2195 const struct gl_texture_object *tObj,
2196 GLuint n, GLfloat texcoord[][4],
2197 const GLfloat lambda[], GLchan rgba[][4])
2198 {
2199 GLuint i;
2200 ASSERT(lambda != NULL);
2201 for (i = 0; i < n; i++) {
2202 const struct gl_texture_image **images;
2203 GLfloat newCoord[4];
2204 GLint level;
2205 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
2206 images = choose_cube_face(tObj, texcoord[i], newCoord);
2207 if (level >= tObj->_MaxLevel) {
2208 sample_2d_nearest(ctx, tObj, images[tObj->_MaxLevel],
2209 newCoord, rgba[i]);
2210 }
2211 else {
2212 GLchan t0[4], t1[4]; /* texels */
2213 const GLfloat f = FRAC(lambda[i]);
2214 sample_2d_nearest(ctx, tObj, images[level ], newCoord, t0);
2215 sample_2d_nearest(ctx, tObj, images[level+1], newCoord, t1);
2216 rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
2217 rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
2218 rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
2219 rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
2220 }
2221 }
2222 }
2223
2224
2225 static void
2226 sample_cube_linear_mipmap_linear(GLcontext *ctx, GLuint texUnit,
2227 const struct gl_texture_object *tObj,
2228 GLuint n, GLfloat texcoord[][4],
2229 const GLfloat lambda[], GLchan rgba[][4])
2230 {
2231 GLuint i;
2232 ASSERT(lambda != NULL);
2233 for (i = 0; i < n; i++) {
2234 const struct gl_texture_image **images;
2235 GLfloat newCoord[4];
2236 GLint level;
2237 COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
2238 images = choose_cube_face(tObj, texcoord[i], newCoord);
2239 if (level >= tObj->_MaxLevel) {
2240 sample_2d_linear(ctx, tObj, images[tObj->_MaxLevel],
2241 newCoord, rgba[i]);
2242 }
2243 else {
2244 GLchan t0[4], t1[4];
2245 const GLfloat f = FRAC(lambda[i]);
2246 sample_2d_linear(ctx, tObj, images[level ], newCoord, t0);
2247 sample_2d_linear(ctx, tObj, images[level+1], newCoord, t1);
2248 rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
2249 rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
2250 rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
2251 rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
2252 }
2253 }
2254 }
2255
2256
2257 static void
2258 sample_lambda_cube( GLcontext *ctx, GLuint texUnit,
2259 const struct gl_texture_object *tObj, GLuint n,
2260 GLfloat texcoords[][4], const GLfloat lambda[],
2261 GLchan rgba[][4])
2262 {
2263 GLuint minStart, minEnd; /* texels with minification */
2264 GLuint magStart, magEnd; /* texels with magnification */
2265
2266 ASSERT(lambda != NULL);
2267 compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit],
2268 n, lambda, &minStart, &minEnd, &magStart, &magEnd);
2269
2270 if (minStart < minEnd) {
2271 /* do the minified texels */
2272 const GLuint m = minEnd - minStart;
2273 switch (tObj->MinFilter) {
2274 case GL_NEAREST:
2275 sample_nearest_cube(ctx, texUnit, tObj, m, texcoords + minStart,
2276 lambda + minStart, rgba + minStart);
2277 break;
2278 case GL_LINEAR:
2279 sample_linear_cube(ctx, texUnit, tObj, m, texcoords + minStart,
2280 lambda + minStart, rgba + minStart);
2281 break;
2282 case GL_NEAREST_MIPMAP_NEAREST:
2283 sample_cube_nearest_mipmap_nearest(ctx, texUnit, tObj, m,
2284 texcoords + minStart,
2285 lambda + minStart, rgba + minStart);
2286 break;
2287 case GL_LINEAR_MIPMAP_NEAREST:
2288 sample_cube_linear_mipmap_nearest(ctx, texUnit, tObj, m,
2289 texcoords + minStart,
2290 lambda + minStart, rgba + minStart);
2291 break;
2292 case GL_NEAREST_MIPMAP_LINEAR:
2293 sample_cube_nearest_mipmap_linear(ctx, texUnit, tObj, m,
2294 texcoords + minStart,
2295 lambda + minStart, rgba + minStart);
2296 break;
2297 case GL_LINEAR_MIPMAP_LINEAR:
2298 sample_cube_linear_mipmap_linear(ctx, texUnit, tObj, m,
2299 texcoords + minStart,
2300 lambda + minStart, rgba + minStart);
2301 break;
2302 default:
2303 _mesa_problem(ctx, "Bad min filter in sample_lambda_cube");
2304 }
2305 }
2306
2307 if (magStart < magEnd) {
2308 /* do the magnified texels */
2309 const GLuint m = magEnd - magStart;
2310 switch (tObj->MagFilter) {
2311 case GL_NEAREST:
2312 sample_nearest_cube(ctx, texUnit, tObj, m, texcoords + magStart,
2313 lambda + magStart, rgba + magStart);
2314 break;
2315 case GL_LINEAR:
2316 sample_linear_cube(ctx, texUnit, tObj, m, texcoords + magStart,
2317 lambda + magStart, rgba + magStart);
2318 break;
2319 default:
2320 _mesa_problem(ctx, "Bad mag filter in sample_lambda_cube");
2321 }
2322 }
2323 }
2324
2325
2326 /**********************************************************************/
2327 /* Texture Rectangle Sampling Functions */
2328 /**********************************************************************/
2329
2330 static void
2331 sample_nearest_rect(GLcontext *ctx, GLuint texUnit,
2332 const struct gl_texture_object *tObj, GLuint n,
2333 GLfloat texcoords[][4], const GLfloat lambda[],
2334 GLchan rgba[][4])
2335 {
2336 const struct gl_texture_image *img = tObj->Image[0];
2337 const GLfloat width = (GLfloat) img->Width;
2338 const GLfloat height = (GLfloat) img->Height;
2339 const GLint width_minus_1 = img->Width - 1;
2340 const GLint height_minus_1 = img->Height - 1;
2341 GLuint i;
2342
2343 (void) texUnit;
2344 (void) lambda;
2345
2346 ASSERT(tObj->WrapS == GL_CLAMP ||
2347 tObj->WrapS == GL_CLAMP_TO_EDGE ||
2348 tObj->WrapS == GL_CLAMP_TO_BORDER);
2349 ASSERT(tObj->WrapT == GL_CLAMP ||
2350 tObj->WrapT == GL_CLAMP_TO_EDGE ||
2351 tObj->WrapT == GL_CLAMP_TO_BORDER);
2352 ASSERT(img->Format != GL_COLOR_INDEX);
2353
2354 /* XXX move Wrap mode tests outside of loops for common cases */
2355 for (i = 0; i < n; i++) {
2356 GLint row, col;
2357 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2358 if (tObj->WrapS == GL_CLAMP) {
2359 col = IFLOOR( CLAMP(texcoords[i][0], 0.0F, width) );
2360 }
2361 else if (tObj->WrapS == GL_CLAMP_TO_EDGE) {
2362 col = IFLOOR( CLAMP(texcoords[i][0], 0.5F, width - 0.5F) );
2363 }
2364 else {
2365 col = IFLOOR( CLAMP(texcoords[i][0], -0.5F, width + 0.5F) );
2366 }
2367 if (tObj->WrapT == GL_CLAMP) {
2368 row = IFLOOR( CLAMP(texcoords[i][1], 0.0F, height) );
2369 }
2370 else if (tObj->WrapT == GL_CLAMP_TO_EDGE) {
2371 row = IFLOOR( CLAMP(texcoords[i][1], 0.5F, height - 0.5F) );
2372 }
2373 else {
2374 row = IFLOOR( CLAMP(texcoords[i][1], -0.5F, height + 0.5F) );
2375 }
2376
2377 col = CLAMP(col, 0, width_minus_1);
2378 row = CLAMP(row, 0, height_minus_1);
2379
2380 (*img->FetchTexel)(img, col, row, 0, (GLvoid *) rgba[i]);
2381 }
2382 }
2383
2384
2385 static void
2386 sample_linear_rect(GLcontext *ctx, GLuint texUnit,
2387 const struct gl_texture_object *tObj, GLuint n,
2388 GLfloat texcoords[][4],
2389 const GLfloat lambda[], GLchan rgba[][4])
2390 {
2391 const struct gl_texture_image *img = tObj->Image[0];
2392 const GLfloat width = (GLfloat) img->Width;
2393 const GLfloat height = (GLfloat) img->Height;
2394 const GLint width_minus_1 = img->Width - 1;
2395 const GLint height_minus_1 = img->Height - 1;
2396 GLuint i;
2397
2398 (void) texUnit;
2399 (void) lambda;
2400
2401 ASSERT(tObj->WrapS == GL_CLAMP ||
2402 tObj->WrapS == GL_CLAMP_TO_EDGE ||
2403 tObj->WrapS == GL_CLAMP_TO_BORDER);
2404 ASSERT(tObj->WrapT == GL_CLAMP ||
2405 tObj->WrapT == GL_CLAMP_TO_EDGE ||
2406 tObj->WrapT == GL_CLAMP_TO_BORDER);
2407 ASSERT(img->Format != GL_COLOR_INDEX);
2408
2409 /* XXX lots of opportunity for optimization in this loop */
2410 for (i = 0; i < n; i++) {
2411 GLfloat frow, fcol;
2412 GLint row0, col0, row1, col1;
2413 GLchan t00[4], t01[4], t10[4], t11[4];
2414 GLfloat a, b, w00, w01, w10, w11;
2415
2416 /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2417 if (tObj->WrapS == GL_CLAMP) {
2418 fcol = CLAMP(texcoords[i][0], 0.0F, width);
2419 }
2420 else if (tObj->WrapS == GL_CLAMP_TO_EDGE) {
2421 fcol = CLAMP(texcoords[i][0], 0.5F, width - 0.5F);
2422 }
2423 else {
2424 fcol = CLAMP(texcoords[i][0], -0.5F, width + 0.5F);
2425 }
2426 if (tObj->WrapT == GL_CLAMP) {
2427 frow = CLAMP(texcoords[i][1], 0.0F, height);
2428 }
2429 else if (tObj->WrapT == GL_CLAMP_TO_EDGE) {
2430 frow = CLAMP(texcoords[i][1], 0.5F, height - 0.5F);
2431 }
2432 else {
2433 frow = CLAMP(texcoords[i][1], -0.5F, height + 0.5F);
2434 }
2435
2436 /* compute integer rows/columns */
2437 col0 = IFLOOR(fcol);
2438 col1 = col0 + 1;
2439 col0 = CLAMP(col0, 0, width_minus_1);
2440 col1 = CLAMP(col1, 0, width_minus_1);
2441 row0 = IFLOOR(frow);
2442 row1 = row0 + 1;
2443 row0 = CLAMP(row0, 0, height_minus_1);
2444 row1 = CLAMP(row1, 0, height_minus_1);
2445
2446 /* get four texel samples */
2447 (*img->FetchTexel)(img, col0, row0, 0, (GLvoid *) t00);
2448 (*img->FetchTexel)(img, col1, row0, 0, (GLvoid *) t10);
2449 (*img->FetchTexel)(img, col0, row1, 0, (GLvoid *) t01);
2450 (*img->FetchTexel)(img, col1, row1, 0, (GLvoid *) t11);
2451
2452 /* compute sample weights */
2453 a = FRAC(fcol);
2454 b = FRAC(frow);
2455 w00 = (1.0F-a) * (1.0F-b);
2456 w10 = a * (1.0F-b);
2457 w01 = (1.0F-a) * b ;
2458 w11 = a * b ;
2459
2460 /* compute weighted average of samples */
2461 rgba[i][0] =
2462 (GLchan) (w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0]);
2463 rgba[i][1] =
2464 (GLchan) (w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1]);
2465 rgba[i][2] =
2466 (GLchan) (w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2]);
2467 rgba[i][3] =
2468 (GLchan) (w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3]);
2469 }
2470 }
2471
2472
2473 static void
2474 sample_lambda_rect( GLcontext *ctx, GLuint texUnit,
2475 const struct gl_texture_object *tObj, GLuint n,
2476 GLfloat texcoords[][4], const GLfloat lambda[],
2477 GLchan rgba[][4])
2478 {
2479 GLuint minStart, minEnd, magStart, magEnd;
2480
2481 /* We only need lambda to decide between minification and magnification.
2482 * There is no mipmapping with rectangular textures.
2483 */
2484 compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit],
2485 n, lambda, &minStart, &minEnd, &magStart, &magEnd);
2486
2487 if (minStart < minEnd) {
2488 if (tObj->MinFilter == GL_NEAREST) {
2489 sample_nearest_rect( ctx, texUnit, tObj, minEnd - minStart,
2490 texcoords + minStart, NULL, rgba + minStart);
2491 }
2492 else {
2493 sample_linear_rect( ctx, texUnit, tObj, minEnd - minStart,
2494 texcoords + minStart, NULL, rgba + minStart);
2495 }
2496 }
2497 if (magStart < magEnd) {
2498 if (tObj->MagFilter == GL_NEAREST) {
2499 sample_nearest_rect( ctx, texUnit, tObj, magEnd - magStart,
2500 texcoords + magStart, NULL, rgba + magStart);
2501 }
2502 else {
2503 sample_linear_rect( ctx, texUnit, tObj, magEnd - magStart,
2504 texcoords + magStart, NULL, rgba + magStart);
2505 }
2506 }
2507 }
2508
2509
2510
2511 /*
2512 * Sample a shadow/depth texture.
2513 */
2514 static void
2515 sample_depth_texture( GLcontext *ctx, GLuint unit,
2516 const struct gl_texture_object *tObj, GLuint n,
2517 GLfloat texcoords[][4], const GLfloat lambda[],
2518 GLchan texel[][4] )
2519 {
2520 const GLint baseLevel = tObj->BaseLevel;
2521 const struct gl_texture_image *texImage = tObj->Image[baseLevel];
2522 const GLuint width = texImage->Width;
2523 const GLuint height = texImage->Height;
2524 GLchan ambient;
2525 GLenum function;
2526 GLchan result;
2527
2528 (void) unit;
2529
2530 ASSERT(tObj->Image[tObj->BaseLevel]->Format == GL_DEPTH_COMPONENT);
2531 ASSERT(tObj->Target == GL_TEXTURE_1D ||
2532 tObj->Target == GL_TEXTURE_2D ||
2533 tObj->Target == GL_TEXTURE_RECTANGLE_NV);
2534
2535 UNCLAMPED_FLOAT_TO_CHAN(ambient, tObj->ShadowAmbient);
2536
2537 /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
2538
2539 /* XXX this could be precomputed and saved in the texture object */
2540 if (tObj->CompareFlag) {
2541 /* GL_SGIX_shadow */
2542 if (tObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) {
2543 function = GL_LEQUAL;
2544 }
2545 else {
2546 ASSERT(tObj->CompareOperator == GL_TEXTURE_GEQUAL_R_SGIX);
2547 function = GL_GEQUAL;
2548 }
2549 }
2550 else if (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
2551 /* GL_ARB_shadow */
2552 function = tObj->CompareFunc;
2553 }
2554 else {
2555 function = GL_NONE; /* pass depth through as grayscale */
2556 }
2557
2558 if (tObj->MagFilter == GL_NEAREST) {
2559 GLuint i;
2560 for (i = 0; i < n; i++) {
2561 GLfloat depthSample;
2562 GLint col, row;
2563 /* XXX fix for texture rectangle! */
2564 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoords[i][0], width, col);
2565 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, texcoords[i][1], height, row);
2566 depthSample = *((const GLfloat *) texImage->Data + row * width + col);
2567
2568 switch (function) {
2569 case GL_LEQUAL:
2570 result = (texcoords[i][2] <= depthSample) ? CHAN_MAX : ambient;
2571 break;
2572 case GL_GEQUAL:
2573 result = (texcoords[i][2] >= depthSample) ? CHAN_MAX : ambient;
2574 break;
2575 case GL_LESS:
2576 result = (texcoords[i][2] < depthSample) ? CHAN_MAX : ambient;
2577 break;
2578 case GL_GREATER:
2579 result = (texcoords[i][2] > depthSample) ? CHAN_MAX : ambient;
2580 break;
2581 case GL_EQUAL:
2582 result = (texcoords[i][2] == depthSample) ? CHAN_MAX : ambient;
2583 break;
2584 case GL_NOTEQUAL:
2585 result = (texcoords[i][2] != depthSample) ? CHAN_MAX : ambient;
2586 break;
2587 case GL_ALWAYS:
2588 result = CHAN_MAX;
2589 break;
2590 case GL_NEVER:
2591 result = ambient;
2592 break;
2593 case GL_NONE:
2594 CLAMPED_FLOAT_TO_CHAN(result, depthSample);
2595 break;
2596 default:
2597 _mesa_problem(ctx, "Bad compare func in sample_depth_texture");
2598 return;
2599 }
2600
2601 switch (tObj->DepthMode) {
2602 case GL_LUMINANCE:
2603 texel[i][RCOMP] = result;
2604 texel[i][GCOMP] = result;
2605 texel[i][BCOMP] = result;
2606 texel[i][ACOMP] = CHAN_MAX;
2607 break;
2608 case GL_INTENSITY:
2609 texel[i][RCOMP] = result;
2610 texel[i][GCOMP] = result;
2611 texel[i][BCOMP] = result;
2612 texel[i][ACOMP] = result;
2613 break;
2614 case GL_ALPHA:
2615 texel[i][RCOMP] = 0;
2616 texel[i][GCOMP] = 0;
2617 texel[i][BCOMP] = 0;
2618 texel[i][ACOMP] = result;
2619 break;
2620 default:
2621 _mesa_problem(ctx, "Bad depth texture mode");
2622 }
2623 }
2624 }
2625 else {
2626 GLuint i;
2627 ASSERT(tObj->MagFilter == GL_LINEAR);
2628 for (i = 0; i < n; i++) {
2629 GLfloat depth00, depth01, depth10, depth11;
2630 GLint i0, i1, j0, j1;
2631 GLfloat u, v;
2632 GLuint useBorderTexel;
2633
2634 /* XXX fix for texture rectangle! */
2635 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoords[i][0], u, width, i0, i1);
2636 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, texcoords[i][1], v, height,j0, j1);
2637
2638 useBorderTexel = 0;
2639 if (texImage->Border) {
2640 i0 += texImage->Border;
2641 i1 += texImage->Border;
2642 j0 += texImage->Border;
2643 j1 += texImage->Border;
2644 }
2645 else {
2646 if (i0 < 0 || i0 >= (GLint) width) useBorderTexel |= I0BIT;
2647 if (i1 < 0 || i1 >= (GLint) width) useBorderTexel |= I1BIT;
2648 if (j0 < 0 || j0 >= (GLint) height) useBorderTexel |= J0BIT;
2649 if (j1 < 0 || j1 >= (GLint) height) useBorderTexel |= J1BIT;
2650 }
2651
2652 /* get four depth samples from the texture */
2653 if (useBorderTexel & (I0BIT | J0BIT)) {
2654 depth00 = 1.0;
2655 }
2656 else {
2657 depth00 = *((const GLfloat *) texImage->Data + j0 * width + i0);
2658 }
2659 if (useBorderTexel & (I1BIT | J0BIT)) {
2660 depth10 = 1.0;
2661 }
2662 else {
2663 depth10 = *((const GLfloat *) texImage->Data + j0 * width + i1);
2664 }
2665 if (useBorderTexel & (I0BIT | J1BIT)) {
2666 depth01 = 1.0;
2667 }
2668 else {
2669 depth01 = *((const GLfloat *) texImage->Data + j1 * width + i0);
2670 }
2671 if (useBorderTexel & (I1BIT | J1BIT)) {
2672 depth11 = 1.0;
2673 }
2674 else {
2675 depth11 = *((const GLfloat *) texImage->Data + j1 * width + i1);
2676 }
2677
2678 if (0) {
2679 /* compute a single weighted depth sample and do one comparison */
2680 const GLfloat a = FRAC(u + 1.0F);
2681 const GLfloat b = FRAC(v + 1.0F);
2682 const GLfloat w00 = (1.0F - a) * (1.0F - b);
2683 const GLfloat w10 = ( a) * (1.0F - b);
2684 const GLfloat w01 = (1.0F - a) * ( b);
2685 const GLfloat w11 = ( a) * ( b);
2686 const GLfloat depthSample = w00 * depth00 + w10 * depth10
2687 + w01 * depth01 + w11 * depth11;
2688 if ((depthSample <= texcoords[i][2] && function == GL_LEQUAL) ||
2689 (depthSample >= texcoords[i][2] && function == GL_GEQUAL)) {
2690 result = ambient;
2691 }
2692 else {
2693 result = CHAN_MAX;
2694 }
2695 }
2696 else {
2697 /* Do four depth/R comparisons and compute a weighted result.
2698 * If this touches on somebody's I.P., I'll remove this code
2699 * upon request.
2700 */
2701 const GLfloat d = (CHAN_MAXF - (GLfloat) ambient) * 0.25F;
2702 GLfloat luminance = CHAN_MAXF;
2703
2704 switch (function) {
2705 case GL_LEQUAL:
2706 if (depth00 <= texcoords[i][2]) luminance -= d;
2707 if (depth01 <= texcoords[i][2]) luminance -= d;
2708 if (depth10 <= texcoords[i][2]) luminance -= d;
2709 if (depth11 <= texcoords[i][2]) luminance -= d;
2710 result = (GLchan) luminance;
2711 break;
2712 case GL_GEQUAL:
2713 if (depth00 >= texcoords[i][2]) luminance -= d;
2714 if (depth01 >= texcoords[i][2]) luminance -= d;
2715 if (depth10 >= texcoords[i][2]) luminance -= d;
2716 if (depth11 >= texcoords[i][2]) luminance -= d;
2717 result = (GLchan) luminance;
2718 break;
2719 case GL_LESS:
2720 if (depth00 < texcoords[i][2]) luminance -= d;
2721 if (depth01 < texcoords[i][2]) luminance -= d;
2722 if (depth10 < texcoords[i][2]) luminance -= d;
2723 if (depth11 < texcoords[i][2]) luminance -= d;
2724 result = (GLchan) luminance;
2725 break;
2726 case GL_GREATER:
2727 if (depth00 > texcoords[i][2]) luminance -= d;
2728 if (depth01 > texcoords[i][2]) luminance -= d;
2729 if (depth10 > texcoords[i][2]) luminance -= d;
2730 if (depth11 > texcoords[i][2]) luminance -= d;
2731 result = (GLchan) luminance;
2732 break;
2733 case GL_EQUAL:
2734 if (depth00 == texcoords[i][2]) luminance -= d;
2735 if (depth01 == texcoords[i][2]) luminance -= d;
2736 if (depth10 == texcoords[i][2]) luminance -= d;
2737 if (depth11 == texcoords[i][2]) luminance -= d;
2738 result = (GLchan) luminance;
2739 break;
2740 case GL_NOTEQUAL:
2741 if (depth00 != texcoords[i][2]) luminance -= d;
2742 if (depth01 != texcoords[i][2]) luminance -= d;
2743 if (depth10 != texcoords[i][2]) luminance -= d;
2744 if (depth11 != texcoords[i][2]) luminance -= d;
2745 result = (GLchan) luminance;
2746 break;
2747 case GL_ALWAYS:
2748 result = 0;
2749 break;
2750 case GL_NEVER:
2751 result = CHAN_MAX;
2752 break;
2753 case GL_NONE:
2754 /* ordinary bilinear filtering */
2755 {
2756 const GLfloat a = FRAC(u + 1.0F);
2757 const GLfloat b = FRAC(v + 1.0F);
2758 const GLfloat w00 = (1.0F - a) * (1.0F - b);
2759 const GLfloat w10 = ( a) * (1.0F - b);
2760 const GLfloat w01 = (1.0F - a) * ( b);
2761 const GLfloat w11 = ( a) * ( b);
2762 const GLfloat depthSample = w00 * depth00 + w10 * depth10
2763 + w01 * depth01 + w11 * depth11;
2764 CLAMPED_FLOAT_TO_CHAN(result, depthSample);
2765 }
2766 break;
2767 default:
2768 _mesa_problem(ctx, "Bad compare func in sample_depth_texture");
2769 return;
2770 }
2771 }
2772
2773 switch (tObj->DepthMode) {
2774 case GL_LUMINANCE:
2775 texel[i][RCOMP] = result;
2776 texel[i][GCOMP] = result;
2777 texel[i][BCOMP] = result;
2778 texel[i][ACOMP] = CHAN_MAX;
2779 break;
2780 case GL_INTENSITY:
2781 texel[i][RCOMP] = result;
2782 texel[i][GCOMP] = result;
2783 texel[i][BCOMP] = result;
2784 texel[i][ACOMP] = result;
2785 break;
2786 case GL_ALPHA:
2787 texel[i][RCOMP] = 0;
2788 texel[i][GCOMP] = 0;
2789 texel[i][BCOMP] = 0;
2790 texel[i][ACOMP] = result;
2791 break;
2792 default:
2793 _mesa_problem(ctx, "Bad depth texture mode");
2794 }
2795 } /* for */
2796 } /* if filter */
2797 }
2798
2799
2800 #if 0
2801 /*
2802 * Experimental depth texture sampling function.
2803 */
2804 static void
2805 sample_depth_texture2(const GLcontext *ctx,
2806 const struct gl_texture_unit *texUnit,
2807 GLuint n, GLfloat texcoords[][4],
2808 GLchan texel[][4])
2809 {
2810 const struct gl_texture_object *texObj = texUnit->_Current;
2811 const GLint baseLevel = texObj->BaseLevel;
2812 const struct gl_texture_image *texImage = texObj->Image[baseLevel];
2813 const GLuint width = texImage->Width;
2814 const GLuint height = texImage->Height;
2815 GLchan ambient;
2816 GLboolean lequal, gequal;
2817
2818 if (texObj->Target != GL_TEXTURE_2D) {
2819 _mesa_problem(ctx, "only 2-D depth textures supported at this time");
2820 return;
2821 }
2822
2823 if (texObj->MinFilter != texObj->MagFilter) {
2824 _mesa_problem(ctx, "mipmapped depth textures not supported at this time");
2825 return;
2826 }
2827
2828 /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2829 * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2830 * isn't a depth texture.
2831 */
2832 if (texImage->Format != GL_DEPTH_COMPONENT) {
2833 _mesa_problem(ctx,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2834 return;
2835 }
2836
2837 UNCLAMPED_FLOAT_TO_CHAN(ambient, tObj->ShadowAmbient);
2838
2839 if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) {
2840 lequal = GL_TRUE;
2841 gequal = GL_FALSE;
2842 }
2843 else {
2844 lequal = GL_FALSE;
2845 gequal = GL_TRUE;
2846 }
2847
2848 {
2849 GLuint i;
2850 for (i = 0; i < n; i++) {
2851 const GLint K = 3;
2852 GLint col, row, ii, jj, imin, imax, jmin, jmax, samples, count;
2853 GLfloat w;
2854 GLchan lum;
2855 COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapS, texcoords[i][0],
2856 width, col);
2857 COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, texcoords[i][1],
2858 height, row);
2859
2860 imin = col - K;
2861 imax = col + K;
2862 jmin = row - K;
2863 jmax = row + K;
2864
2865 if (imin < 0) imin = 0;
2866 if (imax >= width) imax = width - 1;
2867 if (jmin < 0) jmin = 0;
2868 if (jmax >= height) jmax = height - 1;
2869
2870 samples = (imax - imin + 1) * (jmax - jmin + 1);
2871 count = 0;
2872 for (jj = jmin; jj <= jmax; jj++) {
2873 for (ii = imin; ii <= imax; ii++) {
2874 GLfloat depthSample = *((const GLfloat *) texImage->Data
2875 + jj * width + ii);
2876 if ((depthSample <= r[i] && lequal) ||
2877 (depthSample >= r[i] && gequal)) {
2878 count++;
2879 }
2880 }
2881 }
2882
2883 w = (GLfloat) count / (GLfloat) samples;
2884 w = CHAN_MAXF - w * (CHAN_MAXF - (GLfloat) ambient);
2885 lum = (GLint) w;
2886
2887 texel[i][RCOMP] = lum;
2888 texel[i][GCOMP] = lum;
2889 texel[i][BCOMP] = lum;
2890 texel[i][ACOMP] = CHAN_MAX;
2891 }
2892 }
2893 }
2894 #endif
2895
2896
2897 /**
2898 * We use this function when a texture object is in an "incomplete" state.
2899 */
2900 static void
2901 null_sample_func( GLcontext *ctx, GLuint texUnit,
2902 const struct gl_texture_object *tObj, GLuint n,
2903 GLfloat texcoords[][4], const GLfloat lambda[],
2904 GLchan rgba[][4])
2905 {
2906 }
2907
2908
2909
2910 /**
2911 * Setup the texture sampling function for this texture object.
2912 */
2913 void
2914 _swrast_choose_texture_sample_func( GLcontext *ctx, GLuint texUnit,
2915 const struct gl_texture_object *t )
2916 {
2917 SWcontext *swrast = SWRAST_CONTEXT(ctx);
2918
2919 if (!t->Complete) {
2920 swrast->TextureSample[texUnit] = null_sample_func;
2921 }
2922 else {
2923 const GLboolean needLambda = (GLboolean) (t->MinFilter != t->MagFilter);
2924 const GLenum format = t->Image[t->BaseLevel]->Format;
2925
2926 if (needLambda) {
2927 /* Compute min/mag filter threshold */
2928 if (t->MagFilter == GL_LINEAR
2929 && (t->MinFilter == GL_NEAREST_MIPMAP_NEAREST ||
2930 t->MinFilter == GL_NEAREST_MIPMAP_LINEAR)) {
2931 swrast->_MinMagThresh[texUnit] = 0.5F;
2932 }
2933 else {
2934 swrast->_MinMagThresh[texUnit] = 0.0F;
2935 }
2936 }
2937
2938 switch (t->Target) {
2939 case GL_TEXTURE_1D:
2940 if (format == GL_DEPTH_COMPONENT) {
2941 swrast->TextureSample[texUnit] = sample_depth_texture;
2942 }
2943 else if (needLambda) {
2944 swrast->TextureSample[texUnit] = sample_lambda_1d;
2945 }
2946 else if (t->MinFilter == GL_LINEAR) {
2947 swrast->TextureSample[texUnit] = sample_linear_1d;
2948 }
2949 else {
2950 ASSERT(t->MinFilter == GL_NEAREST);
2951 swrast->TextureSample[texUnit] = sample_nearest_1d;
2952 }
2953 break;
2954 case GL_TEXTURE_2D:
2955 if (format == GL_DEPTH_COMPONENT) {
2956 swrast->TextureSample[texUnit] = sample_depth_texture;
2957 }
2958 else if (needLambda) {
2959 swrast->TextureSample[texUnit] = sample_lambda_2d;
2960 }
2961 else if (t->MinFilter == GL_LINEAR) {
2962 swrast->TextureSample[texUnit] = sample_linear_2d;
2963 }
2964 else {
2965 GLint baseLevel = t->BaseLevel;
2966 ASSERT(t->MinFilter == GL_NEAREST);
2967 if (t->WrapS == GL_REPEAT &&
2968 t->WrapT == GL_REPEAT &&
2969 t->Image[baseLevel]->Border == 0 &&
2970 t->Image[baseLevel]->TexFormat->MesaFormat == MESA_FORMAT_RGB) {
2971 swrast->TextureSample[texUnit] = opt_sample_rgb_2d;
2972 }
2973 else if (t->WrapS == GL_REPEAT &&
2974 t->WrapT == GL_REPEAT &&
2975 t->Image[baseLevel]->Border == 0 &&
2976 t->Image[baseLevel]->TexFormat->MesaFormat == MESA_FORMAT_RGBA) {
2977 swrast->TextureSample[texUnit] = opt_sample_rgba_2d;
2978 }
2979 else
2980 swrast->TextureSample[texUnit] = sample_nearest_2d;
2981 }
2982 break;
2983 case GL_TEXTURE_3D:
2984 if (needLambda) {
2985 swrast->TextureSample[texUnit] = sample_lambda_3d;
2986 }
2987 else if (t->MinFilter == GL_LINEAR) {
2988 swrast->TextureSample[texUnit] = sample_linear_3d;
2989 }
2990 else {
2991 ASSERT(t->MinFilter == GL_NEAREST);
2992 swrast->TextureSample[texUnit] = sample_nearest_3d;
2993 }
2994 break;
2995 case GL_TEXTURE_CUBE_MAP:
2996 if (needLambda) {
2997 swrast->TextureSample[texUnit] = sample_lambda_cube;
2998 }
2999 else if (t->MinFilter == GL_LINEAR) {
3000 swrast->TextureSample[texUnit] = sample_linear_cube;
3001 }
3002 else {
3003 ASSERT(t->MinFilter == GL_NEAREST);
3004 swrast->TextureSample[texUnit] = sample_nearest_cube;
3005 }
3006 break;
3007 case GL_TEXTURE_RECTANGLE_NV:
3008 if (needLambda) {
3009 swrast->TextureSample[texUnit] = sample_lambda_rect;
3010 }
3011 else if (t->MinFilter == GL_LINEAR) {
3012 swrast->TextureSample[texUnit] = sample_linear_rect;
3013 }
3014 else {
3015 ASSERT(t->MinFilter == GL_NEAREST);
3016 swrast->TextureSample[texUnit] = sample_nearest_rect;
3017 }
3018 break;
3019 default:
3020 _mesa_problem(ctx, "invalid target in _swrast_choose_texture_sample_func");
3021 }
3022 }
3023 }
3024
3025
3026 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
3027 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
3028
3029
3030 /**
3031 * Do texture application for GL_ARB/EXT_texture_env_combine.
3032 * This function also supports GL_{EXT,ARB}_texture_env_dot3 and
3033 * GL_ATI_texture_env_combine3
3034 *
3035 * \param ctx rendering context
3036 * \param textureUnit the texture unit to apply
3037 * \param n number of fragments to process (span width)
3038 * \param primary_rgba incoming fragment color array
3039 * \param texelBuffer pointer to texel colors for all texture units
3040 *
3041 * \param rgba incoming colors, which get modified here
3042 */
3043 static INLINE void
3044 texture_combine( const GLcontext *ctx, GLuint unit, GLuint n,
3045 CONST GLchan (*primary_rgba)[4],
3046 CONST GLchan *texelBuffer,
3047 GLchan (*rgba)[4] )
3048 {
3049 const struct gl_texture_unit *textureUnit = &(ctx->Texture.Unit[unit]);
3050 const GLchan (*argRGB [3])[4];
3051 const GLchan (*argA [3])[4];
3052 const GLuint RGBshift = textureUnit->CombineScaleShiftRGB;
3053 const GLuint Ashift = textureUnit->CombineScaleShiftA;
3054 #if CHAN_TYPE == GL_FLOAT
3055 const GLchan RGBmult = (GLfloat) (1 << RGBshift);
3056 const GLchan Amult = (GLfloat) (1 << Ashift);
3057 static const GLchan one[4] = { 1.0, 1.0, 1.0, 1.0 };
3058 static const GLchan zero[4] = { 0.0, 0.0, 0.0, 0.0 };
3059 #else
3060 const GLint half = (CHAN_MAX + 1) / 2;
3061 static const GLchan one[4] = { CHAN_MAX, CHAN_MAX, CHAN_MAX, CHAN_MAX };
3062 static const GLchan zero[4] = { 0, 0, 0, 0 };
3063 #endif
3064 GLuint i, j;
3065 GLuint numColorArgs;
3066 GLuint numAlphaArgs;
3067
3068 /* GLchan ccolor[3][4]; */
3069 DEFMNARRAY(GLchan, ccolor, 3, 3 * MAX_WIDTH, 4); /* mac 32k limitation */
3070 CHECKARRAY(ccolor, return); /* mac 32k limitation */
3071
3072 ASSERT(ctx->Extensions.EXT_texture_env_combine ||
3073 ctx->Extensions.ARB_texture_env_combine);
3074 ASSERT(SWRAST_CONTEXT(ctx)->_AnyTextureCombine);
3075
3076
3077 /*
3078 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
3079 textureUnit->CombineModeRGB,
3080 textureUnit->CombineModeA,
3081 textureUnit->CombineSourceRGB[0],
3082 textureUnit->CombineSourceA[0],
3083 textureUnit->CombineSourceRGB[1],
3084 textureUnit->CombineSourceA[1]);
3085 */
3086
3087 /*
3088 * Do operand setup for up to 3 operands. Loop over the terms.
3089 */
3090 switch (textureUnit->CombineModeRGB) {
3091 case GL_REPLACE:
3092 numColorArgs = 1;
3093 break;
3094 case GL_MODULATE:
3095 case GL_ADD:
3096 case GL_ADD_SIGNED:
3097 case GL_SUBTRACT:
3098 case GL_DOT3_RGB:
3099 case GL_DOT3_RGBA:
3100 case GL_DOT3_RGB_EXT:
3101 case GL_DOT3_RGBA_EXT:
3102 numColorArgs = 2;
3103 break;
3104 case GL_INTERPOLATE:
3105 case GL_MODULATE_ADD_ATI:
3106 case GL_MODULATE_SIGNED_ADD_ATI:
3107 case GL_MODULATE_SUBTRACT_ATI:
3108 numColorArgs = 3;
3109 break;
3110 default:
3111 numColorArgs = 0;
3112 ASSERT(0);
3113 break;
3114 }
3115
3116 switch (textureUnit->CombineModeA) {
3117 case GL_REPLACE:
3118 numAlphaArgs = 1;
3119 break;
3120 case GL_MODULATE:
3121 case GL_ADD:
3122 case GL_ADD_SIGNED:
3123 case GL_SUBTRACT:
3124 numAlphaArgs = 2;
3125 break;
3126 case GL_INTERPOLATE:
3127 case GL_MODULATE_ADD_ATI:
3128 case GL_MODULATE_SIGNED_ADD_ATI:
3129 case GL_MODULATE_SUBTRACT_ATI:
3130 numAlphaArgs = 3;
3131 break;
3132 default:
3133 numAlphaArgs = 0;
3134 ASSERT(0);
3135 break;
3136 }
3137
3138 for (j = 0; j < numColorArgs; j++) {
3139 const GLenum srcRGB = textureUnit->CombineSourceRGB[j];
3140
3141
3142 switch (srcRGB) {
3143 case GL_TEXTURE:
3144 argRGB[j] = (const GLchan (*)[4])
3145 (texelBuffer + unit * (n * 4 * sizeof(GLchan)));
3146 break;
3147 case GL_PRIMARY_COLOR:
3148 argRGB[j] = primary_rgba;
3149 break;
3150 case GL_PREVIOUS:
3151 argRGB[j] = (const GLchan (*)[4]) rgba;
3152 break;
3153 case GL_CONSTANT:
3154 {
3155 GLchan (*c)[4] = ccolor[j];
3156 GLchan red, green, blue, alpha;
3157 UNCLAMPED_FLOAT_TO_CHAN(red, textureUnit->EnvColor[0]);
3158 UNCLAMPED_FLOAT_TO_CHAN(green, textureUnit->EnvColor[1]);
3159 UNCLAMPED_FLOAT_TO_CHAN(blue, textureUnit->EnvColor[2]);
3160 UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]);
3161 for (i = 0; i < n; i++) {
3162 c[i][RCOMP] = red;
3163 c[i][GCOMP] = green;
3164 c[i][BCOMP] = blue;
3165 c[i][ACOMP] = alpha;
3166 }
3167 argRGB[j] = (const GLchan (*)[4]) ccolor[j];
3168 }
3169 break;
3170 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
3171 */
3172 case GL_ZERO:
3173 argRGB[j] = & zero;
3174 break;
3175 case GL_ONE:
3176 argRGB[j] = & one;
3177 break;
3178 default:
3179 /* ARB_texture_env_crossbar source */
3180 {
3181 const GLuint srcUnit = srcRGB - GL_TEXTURE0;
3182 ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
3183 if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
3184 return;
3185 argRGB[j] = (const GLchan (*)[4])
3186 (texelBuffer + srcUnit * (n * 4 * sizeof(GLchan)));
3187 }
3188 }
3189
3190 if (textureUnit->CombineOperandRGB[j] != GL_SRC_COLOR) {
3191 const GLchan (*src)[4] = argRGB[j];
3192 GLchan (*dst)[4] = ccolor[j];
3193
3194 /* point to new arg[j] storage */
3195 argRGB[j] = (const GLchan (*)[4]) ccolor[j];
3196
3197 if (textureUnit->CombineOperandRGB[j] == GL_ONE_MINUS_SRC_COLOR) {
3198 for (i = 0; i < n; i++) {
3199 dst[i][RCOMP] = CHAN_MAX - src[i][RCOMP];
3200 dst[i][GCOMP] = CHAN_MAX - src[i][GCOMP];
3201 dst[i][BCOMP] = CHAN_MAX - src[i][BCOMP];
3202 }
3203 }
3204 else if (textureUnit->CombineOperandRGB[j] == GL_SRC_ALPHA) {
3205 for (i = 0; i < n; i++) {
3206 dst[i][RCOMP] = src[i][ACOMP];
3207 dst[i][GCOMP] = src[i][ACOMP];
3208 dst[i][BCOMP] = src[i][ACOMP];
3209 }
3210 }
3211 else {
3212 ASSERT(textureUnit->CombineOperandRGB[j] ==GL_ONE_MINUS_SRC_ALPHA);
3213 for (i = 0; i < n; i++) {
3214 dst[i][RCOMP] = CHAN_MAX - src[i][ACOMP];
3215 dst[i][GCOMP] = CHAN_MAX - src[i][ACOMP];
3216 dst[i][BCOMP] = CHAN_MAX - src[i][ACOMP];
3217 }
3218 }
3219 }
3220 }
3221
3222
3223 for (j = 0; j < numAlphaArgs; j++) {
3224 const GLenum srcA = textureUnit->CombineSourceA[j];
3225
3226 switch (srcA) {
3227 case GL_TEXTURE:
3228 argA[j] = (const GLchan (*)[4])
3229 (texelBuffer + unit * (n * 4 * sizeof(GLchan)));
3230 break;
3231 case GL_PRIMARY_COLOR:
3232 argA[j] = primary_rgba;
3233 break;
3234 case GL_PREVIOUS:
3235 argA[j] = (const GLchan (*)[4]) rgba;
3236 break;
3237 case GL_CONSTANT:
3238 {
3239 GLchan alpha, (*c)[4] = ccolor[j];
3240 UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]);
3241 for (i = 0; i < n; i++)
3242 c[i][ACOMP] = alpha;
3243 argA[j] = (const GLchan (*)[4]) ccolor[j];
3244 }
3245 break;
3246 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
3247 */
3248 case GL_ZERO:
3249 argA[j] = & zero;
3250 break;
3251 case GL_ONE:
3252 argA[j] = & one;
3253 break;
3254 default:
3255 /* ARB_texture_env_crossbar source */
3256 {
3257 const GLuint srcUnit = srcA - GL_TEXTURE0;
3258 ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
3259 if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
3260 return;
3261 argA[j] = (const GLchan (*)[4])
3262 (texelBuffer + srcUnit * (n * 4 * sizeof(GLchan)));
3263 }
3264 }
3265
3266 if (textureUnit->CombineOperandA[j] == GL_ONE_MINUS_SRC_ALPHA) {
3267 const GLchan (*src)[4] = argA[j];
3268 GLchan (*dst)[4] = ccolor[j];
3269 argA[j] = (const GLchan (*)[4]) ccolor[j];
3270 for (i = 0; i < n; i++) {
3271 dst[i][ACOMP] = CHAN_MAX - src[i][ACOMP];
3272 }
3273 }
3274 }
3275
3276 /*
3277 * Do the texture combine.
3278 */
3279 switch (textureUnit->CombineModeRGB) {
3280 case GL_REPLACE:
3281 {
3282 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
3283 if (RGBshift) {
3284 for (i = 0; i < n; i++) {
3285 #if CHAN_TYPE == GL_FLOAT
3286 rgba[i][RCOMP] = arg0[i][RCOMP] * RGBmult;
3287 rgba[i][GCOMP] = arg0[i][GCOMP] * RGBmult;
3288 rgba[i][BCOMP] = arg0[i][BCOMP] * RGBmult;
3289 #else
3290 GLuint r = (GLuint) arg0[i][RCOMP] << RGBshift;
3291 GLuint g = (GLuint) arg0[i][GCOMP] << RGBshift;
3292 GLuint b = (GLuint) arg0[i][BCOMP] << RGBshift;
3293 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
3294 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
3295 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
3296 #endif
3297 }
3298 }
3299 else {
3300 for (i = 0; i < n; i++) {
3301 rgba[i][RCOMP] = arg0[i][RCOMP];
3302 rgba[i][GCOMP] = arg0[i][GCOMP];
3303 rgba[i][BCOMP] = arg0[i][BCOMP];
3304 }
3305 }
3306 }
3307 break;
3308 case GL_MODULATE:
3309 {
3310 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
3311 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
3312 #if CHAN_TYPE != GL_FLOAT
3313 const GLint shift = CHAN_BITS - RGBshift;
3314 #endif
3315 for (i = 0; i < n; i++) {
3316 #if CHAN_TYPE == GL_FLOAT
3317 rgba[i][RCOMP] = arg0[i][RCOMP] * arg1[i][RCOMP] * RGBmult;
3318 rgba[i][GCOMP] = arg0[i][GCOMP] * arg1[i][GCOMP] * RGBmult;
3319 rgba[i][BCOMP] = arg0[i][BCOMP] * arg1[i][BCOMP] * RGBmult;
3320 #else
3321 GLuint r = PROD(arg0[i][RCOMP], arg1[i][RCOMP]) >> shift;
3322 GLuint g = PROD(arg0[i][GCOMP], arg1[i][GCOMP]) >> shift;
3323 GLuint b = PROD(arg0[i][BCOMP], arg1[i][BCOMP]) >> shift;
3324 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
3325 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
3326 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
3327 #endif
3328 }
3329 }
3330 break;
3331 case GL_ADD:
3332 {
3333 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
3334 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
3335 for (i = 0; i < n; i++) {
3336 #if CHAN_TYPE == GL_FLOAT
3337 rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP]) * RGBmult;
3338 rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP]) * RGBmult;
3339 rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP]) * RGBmult;
3340 #else
3341 GLint r = ((GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP]) << RGBshift;
3342 GLint g = ((GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP]) << RGBshift;
3343 GLint b = ((GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP]) << RGBshift;
3344 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
3345 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
3346 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
3347 #endif
3348 }
3349 }
3350 break;
3351 case GL_ADD_SIGNED:
3352 {
3353 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
3354 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
3355 for (i = 0; i < n; i++) {
3356 #if CHAN_TYPE == GL_FLOAT
3357 rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] - 0.5) * RGBmult;
3358 rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] - 0.5) * RGBmult;
3359 rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] - 0.5) * RGBmult;
3360 #else
3361 GLint r = (GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP] -half;
3362 GLint g = (GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP] -half;
3363 GLint b = (GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP] -half;
3364 r = (r < 0) ? 0 : r << RGBshift;
3365 g = (g < 0) ? 0 : g << RGBshift;
3366 b = (b < 0) ? 0 : b << RGBshift;
3367 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
3368 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
3369 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
3370 #endif
3371 }
3372 }
3373 break;
3374 case GL_INTERPOLATE:
3375 {
3376 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
3377 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
3378 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
3379 #if CHAN_TYPE != GL_FLOAT
3380 const GLint shift = CHAN_BITS - RGBshift;
3381 #endif
3382 for (i = 0; i < n; i++) {
3383 #if CHAN_TYPE == GL_FLOAT
3384 rgba[i][RCOMP] = (arg0[i][RCOMP] * arg2[i][RCOMP] +
3385 arg1[i][RCOMP] * (CHAN_MAXF - arg2[i][RCOMP])) * RGBmult;
3386 rgba[i][GCOMP] = (arg0[i][GCOMP] * arg2[i][GCOMP] +
3387 arg1[i][GCOMP] * (CHAN_MAXF - arg2[i][GCOMP])) * RGBmult;
3388 rgba[i][BCOMP] = (arg0[i][BCOMP] * arg2[i][BCOMP] +
3389 arg1[i][BCOMP] * (CHAN_MAXF - arg2[i][BCOMP])) * RGBmult;
3390 #else
3391 GLuint r = (PROD(arg0[i][RCOMP], arg2[i][RCOMP])
3392 + PROD(arg1[i][RCOMP], CHAN_MAX - arg2[i][RCOMP]))
3393 >> shift;
3394 GLuint g = (PROD(arg0[i][GCOMP], arg2[i][GCOMP])
3395 + PROD(arg1[i][GCOMP], CHAN_MAX - arg2[i][GCOMP]))
3396 >> shift;
3397 GLuint b = (PROD(arg0[i][BCOMP], arg2[i][BCOMP])
3398 + PROD(arg1[i][BCOMP], CHAN_MAX - arg2[i][BCOMP]))
3399 >> shift;
3400 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
3401 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
3402 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
3403 #endif
3404 }
3405 }
3406 break;
3407 case GL_SUBTRACT:
3408 {
3409 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
3410 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
3411 for (i = 0; i < n; i++) {
3412 #if CHAN_TYPE == GL_FLOAT
3413 rgba[i][RCOMP] = (arg0[i][RCOMP] - arg1[i][RCOMP]) * RGBmult;
3414 rgba[i][GCOMP] = (arg0[i][GCOMP] - arg1[i][GCOMP]) * RGBmult;
3415 rgba[i][BCOMP] = (arg0[i][BCOMP] - arg1[i][BCOMP]) * RGBmult;
3416 #else
3417 GLint r = ((GLint) arg0[i][RCOMP] - (GLint) arg1[i][RCOMP]) << RGBshift;
3418 GLint g = ((GLint) arg0[i][GCOMP] - (GLint) arg1[i][GCOMP]) << RGBshift;
3419 GLint b = ((GLint) arg0[i][BCOMP] - (GLint) arg1[i][BCOMP]) << RGBshift;
3420 rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
3421 rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
3422 rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
3423 #endif
3424 }
3425 }
3426 break;
3427 case GL_DOT3_RGB_EXT:
3428 case GL_DOT3_RGBA_EXT:
3429 {
3430 /* Do not scale the result by 1 2 or 4 */
3431 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
3432 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
3433 for (i = 0; i < n; i++) {
3434 #if CHAN_TYPE == GL_FLOAT
3435 GLchan dot = ((arg0[i][RCOMP]-0.5F) * (arg1[i][RCOMP]-0.5F) +
3436 (arg0[i][GCOMP]-0.5F) * (arg1[i][GCOMP]-0.5F) +
3437 (arg0[i][BCOMP]-0.5F) * (arg1[i][BCOMP]-0.5F))
3438 * 4.0F;
3439 dot = CLAMP(dot, 0.0F, CHAN_MAXF);
3440 #else
3441 GLint dot = (S_PROD((GLint)arg0[i][RCOMP] - half,
3442 (GLint)arg1[i][RCOMP] - half) +
3443 S_PROD((GLint)arg0[i][GCOMP] - half,
3444 (GLint)arg1[i][GCOMP] - half) +
3445 S_PROD((GLint)arg0[i][BCOMP] - half,
3446 (GLint)arg1[i][BCOMP] - half)) >> 6;
3447 dot = CLAMP(dot, 0, CHAN_MAX);
3448 #endif
3449 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = (GLchan) dot;
3450 }
3451 }
3452 break;
3453 case GL_DOT3_RGB:
3454 case GL_DOT3_RGBA:
3455 {
3456 /* DO scale the result by 1 2 or 4 */
3457 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
3458 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
3459 for (i = 0; i < n; i++) {
3460 #if CHAN_TYPE == GL_FLOAT
3461 GLchan dot = ((arg0[i][RCOMP]-0.5F) * (arg1[i][RCOMP]-0.5F) +
3462 (arg0[i][GCOMP]-0.5F) * (arg1[i][GCOMP]-0.5F) +
3463 (arg0[i][BCOMP]-0.5F) * (arg1[i][BCOMP]-0.5F))
3464 * 4.0F * RGBmult;
3465 dot = CLAMP(dot, 0.0, CHAN_MAXF);
3466 #else
3467 GLint dot = (S_PROD((GLint)arg0[i][RCOMP] - half,
3468 (GLint)arg1[i][RCOMP] - half) +
3469 S_PROD((GLint)arg0[i][GCOMP] - half,
3470 (GLint)arg1[i][GCOMP] - half) +
3471 S_PROD((GLint)arg0[i][BCOMP] - half,
3472 (GLint)arg1[i][BCOMP] - half)) >> 6;
3473 dot <<= RGBshift;
3474 dot = CLAMP(dot, 0, CHAN_MAX);
3475 #endif
3476 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = (GLchan) dot;
3477 }
3478 }
3479 break;
3480 case GL_MODULATE_ADD_ATI:
3481 {
3482 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
3483 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
3484 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
3485 #if CHAN_TYPE != GL_FLOAT
3486 const GLint shift = CHAN_BITS - RGBshift;
3487 #endif
3488 for (i = 0; i < n; i++) {
3489 #if CHAN_TYPE == GL_FLOAT
3490 rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) + arg1[i][RCOMP]) * RGBmult;
3491 rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) + arg1[i][GCOMP]) * RGBmult;
3492 rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) + arg1[i][BCOMP]) * RGBmult;
3493 #else
3494 GLuint r = (PROD(arg0[i][RCOMP], arg2[i][RCOMP])
3495 + ((GLuint) arg1[i][RCOMP] << CHAN_BITS)) >> shift;
3496 GLuint g = (PROD(arg0[i][GCOMP], arg2[i][GCOMP])
3497 + ((GLuint) arg1[i][GCOMP] << CHAN_BITS)) >> shift;
3498 GLuint b = (PROD(arg0[i][BCOMP], arg2[i][BCOMP])
3499 + ((GLuint) arg1[i][BCOMP] << CHAN_BITS)) >> shift;
3500 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
3501 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
3502 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
3503 #endif
3504 }
3505 }
3506 break;
3507 case GL_MODULATE_SIGNED_ADD_ATI:
3508 {
3509 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
3510 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
3511 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
3512 #if CHAN_TYPE != GL_FLOAT
3513 const GLint shift = CHAN_BITS - RGBshift;
3514 #endif
3515 for (i = 0; i < n; i++) {
3516 #if CHAN_TYPE == GL_FLOAT
3517 rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) + arg1[i][RCOMP] - 0.5) * RGBmult;
3518 rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) + arg1[i][GCOMP] - 0.5) * RGBmult;
3519 rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) + arg1[i][BCOMP] - 0.5) * RGBmult;
3520 #else
3521 GLint r = (S_PROD(arg0[i][RCOMP], arg2[i][RCOMP])
3522 + (((GLint) arg1[i][RCOMP] - half) << CHAN_BITS))
3523 >> shift;
3524 GLint g = (S_PROD(arg0[i][GCOMP], arg2[i][GCOMP])
3525 + (((GLint) arg1[i][GCOMP] - half) << CHAN_BITS))
3526 >> shift;
3527 GLint b = (S_PROD(arg0[i][BCOMP], arg2[i][BCOMP])
3528 + (((GLint) arg1[i][BCOMP] - half) << CHAN_BITS))
3529 >> shift;
3530 rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
3531 rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
3532 rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
3533 #endif
3534 }
3535 }
3536 break;
3537 case GL_MODULATE_SUBTRACT_ATI:
3538 {
3539 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
3540 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
3541 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
3542 #if CHAN_TYPE != GL_FLOAT
3543 const GLint shift = CHAN_BITS - RGBshift;
3544 #endif
3545 for (i = 0; i < n; i++) {
3546 #if CHAN_TYPE == GL_FLOAT
3547 rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) - arg1[i][RCOMP]) * RGBmult;
3548 rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) - arg1[i][GCOMP]) * RGBmult;
3549 rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) - arg1[i][BCOMP]) * RGBmult;
3550 #else
3551 GLint r = (S_PROD(arg0[i][RCOMP], arg2[i][RCOMP])
3552 - ((GLint) arg1[i][RCOMP] << CHAN_BITS))
3553 >> shift;
3554 GLint g = (S_PROD(arg0[i][GCOMP], arg2[i][GCOMP])
3555 - ((GLint) arg1[i][GCOMP] << CHAN_BITS))
3556 >> shift;
3557 GLint b = (S_PROD(arg0[i][BCOMP], arg2[i][BCOMP])
3558 - ((GLint) arg1[i][BCOMP] << CHAN_BITS))
3559 >> shift;
3560 rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
3561 rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
3562 rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
3563 #endif
3564 }
3565 }
3566 break;
3567 default:
3568 _mesa_problem(ctx, "invalid combine mode");
3569 }
3570
3571 switch (textureUnit->CombineModeA) {
3572 case GL_REPLACE:
3573 {
3574 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
3575 if (Ashift) {
3576 for (i = 0; i < n; i++) {
3577 #if CHAN_TYPE == GL_FLOAT
3578 GLchan a = arg0[i][ACOMP] * Amult;
3579 #else
3580 GLuint a = (GLuint) arg0[i][ACOMP] << Ashift;
3581 #endif
3582 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
3583 }
3584 }
3585 else {
3586 for (i = 0; i < n; i++) {
3587 rgba[i][ACOMP] = arg0[i][ACOMP];
3588 }
3589 }
3590 }
3591 break;
3592 case GL_MODULATE:
3593 {
3594 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
3595 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
3596 #if CHAN_TYPE != GL_FLOAT
3597 const GLint shift = CHAN_BITS - Ashift;
3598 #endif
3599 for (i = 0; i < n; i++) {
3600 #if CHAN_TYPE == GL_FLOAT
3601 rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * Amult;
3602 #else
3603 GLuint a = (PROD(arg0[i][ACOMP], arg1[i][ACOMP]) >> shift);
3604 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
3605 #endif
3606 }
3607 }
3608 break;
3609 case GL_ADD:
3610 {
3611 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
3612 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
3613 for (i = 0; i < n; i++) {
3614 #if CHAN_TYPE == GL_FLOAT
3615 rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * Amult;
3616 #else
3617 GLint a = ((GLint) arg0[i][ACOMP] + arg1[i][ACOMP]) << Ashift;
3618 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
3619 #endif
3620 }
3621 }
3622 break;
3623 case GL_ADD_SIGNED:
3624 {
3625 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
3626 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
3627 for (i = 0; i < n; i++) {
3628 #if CHAN_TYPE == GL_FLOAT
3629 rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * Amult;
3630 #else
3631 GLint a = (GLint) arg0[i][ACOMP] + (GLint) arg1[i][ACOMP] -half;
3632 a = (a < 0) ? 0 : a << Ashift;
3633 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
3634 #endif
3635 }
3636 }
3637 break;
3638 case GL_INTERPOLATE:
3639 {
3640 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
3641 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
3642 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
3643 #if CHAN_TYPE != GL_FLOAT
3644 const GLint shift = CHAN_BITS - Ashift;
3645 #endif
3646 for (i=0; i<n; i++) {
3647 #if CHAN_TYPE == GL_FLOAT
3648 rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] +
3649 arg1[i][ACOMP] * (CHAN_MAXF - arg2[i][ACOMP]))
3650 * Amult;
3651 #else
3652 GLuint a = (PROD(arg0[i][ACOMP], arg2[i][ACOMP])
3653 + PROD(arg1[i][ACOMP], CHAN_MAX - arg2[i][ACOMP]))
3654 >> shift;
3655 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
3656 #endif
3657 }
3658 }
3659 break;
3660 case GL_SUBTRACT:
3661 {
3662 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
3663 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
3664 for (i = 0; i < n; i++) {
3665 #if CHAN_TYPE == GL_FLOAT
3666 rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * Amult;
3667 #else
3668 GLint a = ((GLint) arg0[i][ACOMP] - (GLint) arg1[i][ACOMP]) << Ashift;
3669 rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
3670 #endif
3671 }
3672 }
3673 break;
3674 case GL_MODULATE_ADD_ATI:
3675 {
3676 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
3677 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
3678 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
3679 #if CHAN_TYPE != GL_FLOAT
3680 const GLint shift = CHAN_BITS - Ashift;
3681 #endif
3682 for (i = 0; i < n; i++) {
3683 #if CHAN_TYPE == GL_FLOAT
3684 rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) + arg1[i][ACOMP]) * Amult;
3685 #else
3686 GLuint a = (PROD(arg0[i][ACOMP], arg2[i][ACOMP])
3687 + ((GLuint) arg1[i][ACOMP] << CHAN_BITS))
3688 >> shift;
3689 rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
3690 #endif
3691 }
3692 }
3693 break;
3694 case GL_MODULATE_SIGNED_ADD_ATI:
3695 {
3696 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
3697 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
3698 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
3699 #if CHAN_TYPE != GL_FLOAT
3700 const GLint shift = CHAN_BITS - Ashift;
3701 #endif
3702 for (i = 0; i < n; i++) {
3703 #if CHAN_TYPE == GL_FLOAT
3704 rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) + arg1[i][ACOMP] - 0.5F) * Amult;
3705 #else
3706 GLint a = (S_PROD(arg0[i][ACOMP], arg2[i][ACOMP])
3707 + (((GLint) arg1[i][ACOMP] - half) << CHAN_BITS))
3708 >> shift;
3709 rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
3710 #endif
3711 }
3712 }
3713 break;
3714 case GL_MODULATE_SUBTRACT_ATI:
3715 {
3716 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
3717 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
3718 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
3719 #if CHAN_TYPE != GL_FLOAT
3720 const GLint shift = CHAN_BITS - Ashift;
3721 #endif
3722 for (i = 0; i < n; i++) {
3723 #if CHAN_TYPE == GL_FLOAT
3724 rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) - arg1[i][ACOMP]) * Amult;
3725 #else
3726 GLint a = (S_PROD(arg0[i][ACOMP], arg2[i][ACOMP])
3727 - ((GLint) arg1[i][ACOMP] << CHAN_BITS))
3728 >> shift;
3729 rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
3730 #endif
3731 }
3732 }
3733 break;
3734 default:
3735 _mesa_problem(ctx, "invalid combine mode");
3736 }
3737
3738 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
3739 * This is kind of a kludge. It would have been better if the spec
3740 * were written such that the GL_COMBINE_ALPHA value could be set to
3741 * GL_DOT3.
3742 */
3743 if (textureUnit->CombineModeRGB == GL_DOT3_RGBA_EXT ||
3744 textureUnit->CombineModeRGB == GL_DOT3_RGBA) {
3745 for (i = 0; i < n; i++) {
3746 rgba[i][ACOMP] = rgba[i][RCOMP];
3747 }
3748 }
3749 UNDEFARRAY(ccolor); /* mac 32k limitation */
3750 }
3751 #undef PROD
3752
3753
3754 /**
3755 * Implement NVIDIA's GL_NV_texture_env_combine4 extension when
3756 * texUnit->EnvMode == GL_COMBINE4_NV.
3757 */
3758 static INLINE void
3759 texture_combine4( const GLcontext *ctx, GLuint unit, GLuint n,
3760 CONST GLchan (*primary_rgba)[4],
3761 CONST GLchan *texelBuffer,
3762 GLchan (*rgba)[4] )
3763 {
3764 }
3765
3766
3767
3768 /**
3769 * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND,
3770 * MODULATE, or DECAL) to an array of fragments.
3771 * Input: textureUnit - pointer to texture unit to apply
3772 * format - base internal texture format
3773 * n - number of fragments
3774 * primary_rgba - primary colors (may alias rgba for single texture)
3775 * texels - array of texel colors
3776 * InOut: rgba - incoming fragment colors modified by texel colors
3777 * according to the texture environment mode.
3778 */
3779 static void
3780 texture_apply( const GLcontext *ctx,
3781 const struct gl_texture_unit *texUnit,
3782 GLuint n,
3783 CONST GLchan primary_rgba[][4], CONST GLchan texel[][4],
3784 GLchan rgba[][4] )
3785 {
3786 GLint baseLevel;
3787 GLuint i;
3788 GLint Rc, Gc, Bc, Ac;
3789 GLenum format;
3790
3791 ASSERT(texUnit);
3792 ASSERT(texUnit->_Current);
3793
3794 baseLevel = texUnit->_Current->BaseLevel;
3795 ASSERT(texUnit->_Current->Image[baseLevel]);
3796
3797 format = texUnit->_Current->Image[baseLevel]->Format;
3798
3799 if (format == GL_COLOR_INDEX || format == GL_DEPTH_COMPONENT
3800 || format == GL_YCBCR_MESA) {
3801 format = GL_RGBA; /* a bit of a hack */
3802 }
3803
3804 switch (texUnit->EnvMode) {
3805 case GL_REPLACE:
3806 switch (format) {
3807 case GL_ALPHA:
3808 for (i=0;i<n;i++) {
3809 /* Cv = Cf */
3810 /* Av = At */
3811 rgba[i][ACOMP] = texel[i][ACOMP];
3812 }
3813 break;
3814 case GL_LUMINANCE:
3815 for (i=0;i<n;i++) {
3816 /* Cv = Lt */
3817 GLchan Lt = texel[i][RCOMP];
3818 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
3819 /* Av = Af */
3820 }
3821 break;
3822 case GL_LUMINANCE_ALPHA:
3823 for (i=0;i<n;i++) {
3824 GLchan Lt = texel[i][RCOMP];
3825 /* Cv = Lt */
3826 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
3827 /* Av = At */
3828 rgba[i][ACOMP] = texel[i][ACOMP];
3829 }
3830 break;
3831 case GL_INTENSITY:
3832 for (i=0;i<n;i++) {
3833 /* Cv = It */
3834 GLchan It = texel[i][RCOMP];
3835 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = It;
3836 /* Av = It */
3837 rgba[i][ACOMP] = It;
3838 }
3839 break;
3840 case GL_RGB:
3841 for (i=0;i<n;i++) {
3842 /* Cv = Ct */
3843 rgba[i][RCOMP] = texel[i][RCOMP];
3844 rgba[i][GCOMP] = texel[i][GCOMP];
3845 rgba[i][BCOMP] = texel[i][BCOMP];
3846 /* Av = Af */
3847 }
3848 break;
3849 case GL_RGBA:
3850 for (i=0;i<n;i++) {
3851 /* Cv = Ct */
3852 rgba[i][RCOMP] = texel[i][RCOMP];
3853 rgba[i][GCOMP] = texel[i][GCOMP];
3854 rgba[i][BCOMP] = texel[i][BCOMP];
3855 /* Av = At */
3856 rgba[i][ACOMP] = texel[i][ACOMP];
3857 }
3858 break;
3859 default:
3860 _mesa_problem(ctx, "Bad format (GL_REPLACE) in texture_apply");
3861 return;
3862 }
3863 break;
3864
3865 case GL_MODULATE:
3866 switch (format) {
3867 case GL_ALPHA:
3868 for (i=0;i<n;i++) {
3869 /* Cv = Cf */
3870 /* Av = AfAt */
3871 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
3872 }
3873 break;
3874 case GL_LUMINANCE:
3875 for (i=0;i<n;i++) {
3876 /* Cv = LtCf */
3877 GLchan Lt = texel[i][RCOMP];
3878 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt );
3879 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt );
3880 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt );
3881 /* Av = Af */
3882 }
3883 break;
3884 case GL_LUMINANCE_ALPHA:
3885 for (i=0;i<n;i++) {
3886 /* Cv = CfLt */
3887 GLchan Lt = texel[i][RCOMP];
3888 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt );
3889 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt );
3890 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt );
3891 /* Av = AfAt */
3892 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
3893 }
3894 break;
3895 case GL_INTENSITY:
3896 for (i=0;i<n;i++) {
3897 /* Cv = CfIt */
3898 GLchan It = texel[i][RCOMP];
3899 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], It );
3900 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], It );
3901 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], It );
3902 /* Av = AfIt */
3903 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], It );
3904 }
3905 break;
3906 case GL_RGB:
3907 for (i=0;i<n;i++) {
3908 /* Cv = CfCt */
3909 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] );
3910 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] );
3911 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] );
3912 /* Av = Af */
3913 }
3914 break;
3915 case GL_RGBA:
3916 for (i=0;i<n;i++) {
3917 /* Cv = CfCt */
3918 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] );
3919 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] );
3920 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] );
3921 /* Av = AfAt */
3922 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
3923 }
3924 break;
3925 default:
3926 _mesa_problem(ctx, "Bad format (GL_MODULATE) in texture_apply");
3927 return;
3928 }
3929 break;
3930
3931 case GL_DECAL:
3932 switch (format) {
3933 case GL_ALPHA:
3934 case GL_LUMINANCE:
3935 case GL_LUMINANCE_ALPHA:
3936 case GL_INTENSITY:
3937 /* undefined */
3938 break;
3939 case GL_RGB:
3940 for (i=0;i<n;i++) {
3941 /* Cv = Ct */
3942 rgba[i][RCOMP] = texel[i][RCOMP];
3943 rgba[i][GCOMP] = texel[i][GCOMP];
3944 rgba[i][BCOMP] = texel[i][BCOMP];
3945 /* Av = Af */
3946 }
3947 break;
3948 case GL_RGBA:
3949 for (i=0;i<n;i++) {
3950 /* Cv = Cf(1-At) + CtAt */
3951 GLint t = texel[i][ACOMP], s = CHAN_MAX - t;
3952 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(texel[i][RCOMP],t);
3953 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(texel[i][GCOMP],t);
3954 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(texel[i][BCOMP],t);
3955 /* Av = Af */
3956 }
3957 break;
3958 default:
3959 _mesa_problem(ctx, "Bad format (GL_DECAL) in texture_apply");
3960 return;
3961 }
3962 break;
3963
3964 case GL_BLEND:
3965 Rc = (GLint) (texUnit->EnvColor[0] * CHAN_MAXF);
3966 Gc = (GLint) (texUnit->EnvColor[1] * CHAN_MAXF);
3967 Bc = (GLint) (texUnit->EnvColor[2] * CHAN_MAXF);
3968 Ac = (GLint) (texUnit->EnvColor[3] * CHAN_MAXF);
3969 switch (format) {
3970 case GL_ALPHA:
3971 for (i=0;i<n;i++) {
3972 /* Cv = Cf */
3973 /* Av = AfAt */
3974 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
3975 }
3976 break;
3977 case GL_LUMINANCE:
3978 for (i=0;i<n;i++) {
3979 /* Cv = Cf(1-Lt) + CcLt */
3980 GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt;
3981 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt);
3982 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt);
3983 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt);
3984 /* Av = Af */
3985 }
3986 break;
3987 case GL_LUMINANCE_ALPHA:
3988 for (i=0;i<n;i++) {
3989 /* Cv = Cf(1-Lt) + CcLt */
3990 GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt;
3991 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt);
3992 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt);
3993 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt);
3994 /* Av = AfAt */
3995 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]);
3996 }
3997 break;
3998 case GL_INTENSITY:
3999 for (i=0;i<n;i++) {
4000 /* Cv = Cf(1-It) + CcLt */
4001 GLchan It = texel[i][RCOMP], s = CHAN_MAX - It;
4002 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, It);
4003 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, It);
4004 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, It);
4005 /* Av = Af(1-It) + Ac*It */
4006 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], s) + CHAN_PRODUCT(Ac, It);
4007 }
4008 break;
4009 case GL_RGB:
4010 for (i=0;i<n;i++) {
4011 /* Cv = Cf(1-Ct) + CcCt */
4012 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]);
4013 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]);
4014 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]);
4015 /* Av = Af */
4016 }
4017 break;
4018 case GL_RGBA:
4019 for (i=0;i<n;i++) {
4020 /* Cv = Cf(1-Ct) + CcCt */
4021 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]);
4022 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]);
4023 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]);
4024 /* Av = AfAt */
4025 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]);
4026 }
4027 break;
4028 default:
4029 _mesa_problem(ctx, "Bad format (GL_BLEND) in texture_apply");
4030 return;
4031 }
4032 break;
4033
4034 /* XXX don't clamp results if GLchan is float??? */
4035
4036 case GL_ADD: /* GL_EXT_texture_add_env */
4037 switch (format) {
4038 case GL_ALPHA:
4039 for (i=0;i<n;i++) {
4040 /* Rv = Rf */
4041 /* Gv = Gf */
4042 /* Bv = Bf */
4043 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
4044 }
4045 break;
4046 case GL_LUMINANCE:
4047 for (i=0;i<n;i++) {
4048 GLuint Lt = texel[i][RCOMP];
4049 GLuint r = rgba[i][RCOMP] + Lt;
4050 GLuint g = rgba[i][GCOMP] + Lt;
4051 GLuint b = rgba[i][BCOMP] + Lt;
4052 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
4053 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
4054 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
4055 /* Av = Af */
4056 }
4057 break;
4058 case GL_LUMINANCE_ALPHA:
4059 for (i=0;i<n;i++) {
4060 GLuint Lt = texel[i][RCOMP];
4061 GLuint r = rgba[i][RCOMP] + Lt;
4062 GLuint g = rgba[i][GCOMP] + Lt;
4063 GLuint b = rgba[i][BCOMP] + Lt;
4064 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
4065 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
4066 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
4067 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
4068 }
4069 break;
4070 case GL_INTENSITY:
4071 for (i=0;i<n;i++) {
4072 GLchan It = texel[i][RCOMP];
4073 GLuint r = rgba[i][RCOMP] + It;
4074 GLuint g = rgba[i][GCOMP] + It;
4075 GLuint b = rgba[i][BCOMP] + It;
4076 GLuint a = rgba[i][ACOMP] + It;
4077 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
4078 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
4079 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
4080 rgba[i][ACOMP] = MIN2(a, CHAN_MAX);
4081 }
4082 break;
4083 case GL_RGB:
4084 for (i=0;i<n;i++) {
4085 GLuint r = rgba[i][RCOMP] + texel[i][RCOMP];
4086 GLuint g = rgba[i][GCOMP] + texel[i][GCOMP];
4087 GLuint b = rgba[i][BCOMP] + texel[i][BCOMP];
4088 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
4089 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
4090 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
4091 /* Av = Af */
4092 }
4093 break;
4094 case GL_RGBA:
4095 for (i=0;i<n;i++) {
4096 GLuint r = rgba[i][RCOMP] + texel[i][RCOMP];
4097 GLuint g = rgba[i][GCOMP] + texel[i][GCOMP];
4098 GLuint b = rgba[i][BCOMP] + texel[i][BCOMP];
4099 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
4100 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
4101 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
4102 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
4103 }
4104 break;
4105 default:
4106 _mesa_problem(ctx, "Bad format (GL_ADD) in texture_apply");
4107 return;
4108 }
4109 break;
4110
4111 default:
4112 _mesa_problem(ctx, "Bad env mode in texture_apply");
4113 return;
4114 }
4115 }
4116
4117
4118
4119 /**
4120 * Apply texture mapping to a span of fragments.
4121 */
4122 void
4123 _swrast_texture_span( GLcontext *ctx, struct sw_span *span )
4124 {
4125 SWcontext *swrast = SWRAST_CONTEXT(ctx);
4126 GLchan primary_rgba[MAX_WIDTH][4];
4127 GLuint unit;
4128
4129 ASSERT(span->end < MAX_WIDTH);
4130 ASSERT(span->arrayMask & SPAN_TEXTURE);
4131
4132 /*
4133 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
4134 */
4135 if (swrast->_AnyTextureCombine)
4136 MEMCPY(primary_rgba, span->array->rgba, 4 * span->end * sizeof(GLchan));
4137
4138 /*
4139 * Must do all texture sampling before combining in order to
4140 * accomodate GL_ARB_texture_env_crossbar.
4141 */
4142 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
4143 if (ctx->Texture.Unit[unit]._ReallyEnabled) {
4144 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
4145 const struct gl_texture_object *curObj = texUnit->_Current;
4146 GLfloat *lambda = span->array->lambda[unit];
4147 GLchan (*texels)[4] = (GLchan (*)[4])
4148 (swrast->TexelBuffer + unit * (span->end * 4 * sizeof(GLchan)));
4149
4150 /* adjust texture lod (lambda) */
4151 if (span->arrayMask & SPAN_LAMBDA) {
4152 if (texUnit->LodBias != 0.0F) {
4153 /* apply LOD bias, but don't clamp yet */
4154 GLuint i;
4155 for (i = 0; i < span->end; i++) {
4156 lambda[i] += texUnit->LodBias;
4157 }
4158 }
4159
4160 if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) {
4161 /* apply LOD clamping to lambda */
4162 const GLfloat min = curObj->MinLod;
4163 const GLfloat max = curObj->MaxLod;
4164 GLuint i;
4165 for (i = 0; i < span->end; i++) {
4166 GLfloat l = lambda[i];
4167 lambda[i] = CLAMP(l, min, max);
4168 }
4169 }
4170 }
4171
4172 /* Sample the texture (span->end fragments) */
4173 swrast->TextureSample[unit]( ctx, unit, texUnit->_Current,
4174 span->end, span->array->texcoords[unit],
4175 lambda, texels );
4176 /* GL_SGI_texture_color_table */
4177 if (texUnit->ColorTableEnabled) {
4178 _swrast_texture_table_lookup(&texUnit->ColorTable, span->end, texels);
4179 }
4180 }
4181 }
4182
4183 /*
4184 * OK, now apply the texture (aka texture combine/blend).
4185 * We modify the span->color.rgba values.
4186 */
4187 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
4188 if (ctx->Texture.Unit[unit]._ReallyEnabled) {
4189 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
4190 if (texUnit->EnvMode == GL_COMBINE) {
4191 /* GL_ARB/EXT_texture_env_combine */
4192 texture_combine( ctx, unit, span->end,
4193 (CONST GLchan (*)[4]) primary_rgba,
4194 swrast->TexelBuffer,
4195 span->array->rgba );
4196 }
4197 else if (texUnit->EnvMode == GL_COMBINE4_NV) {
4198 /* GL_NV_texture_env_combine4 */
4199 texture_combine4( ctx, unit, span->end,
4200 (CONST GLchan (*)[4]) primary_rgba,
4201 swrast->TexelBuffer,
4202 span->array->rgba );
4203 }
4204 else {
4205 /* conventional texture blend */
4206 const GLchan (*texels)[4] = (const GLchan (*)[4])
4207 (swrast->TexelBuffer + unit *
4208 (span->end * 4 * sizeof(GLchan)));
4209 texture_apply( ctx, texUnit, span->end,
4210 (CONST GLchan (*)[4]) primary_rgba, texels,
4211 span->array->rgba );
4212 }
4213 }
4214 }
4215 }