Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
57 pj 1
/* $Id: s_texture.c,v 1.1 2003-02-28 11:49:43 pj Exp $ */
2
 
3
/*
4
 * Mesa 3-D graphics library
5
 * Version:  5.0
6
 *
7
 * Copyright (C) 1999-2002  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_ARB
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_ARB) {                      \
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_ARB) {                       \
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_ARB) {                       \
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_ARB) {                       \
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
/*
301
 * Get texture palette entry.
302
 */
303
static void
304
palette_sample(const GLcontext *ctx,
305
               const struct gl_texture_object *tObj,
306
               GLint index, GLchan rgba[4] )
307
{
308
   const GLchan *palette;
309
   GLenum format;
310
 
311
   if (ctx->Texture.SharedPalette) {
312
      ASSERT(!ctx->Texture.Palette.FloatTable);
313
      palette = (const GLchan *) ctx->Texture.Palette.Table;
314
      format = ctx->Texture.Palette.Format;
315
   }
316
   else {
317
      ASSERT(!tObj->Palette.FloatTable);
318
      palette = (const GLchan *) tObj->Palette.Table;
319
      format = tObj->Palette.Format;
320
   }
321
 
322
   switch (format) {
323
      case GL_ALPHA:
324
         rgba[ACOMP] = palette[index];
325
         return;
326
      case GL_LUMINANCE:
327
      case GL_INTENSITY:
328
         rgba[RCOMP] = palette[index];
329
         return;
330
      case GL_LUMINANCE_ALPHA:
331
         rgba[RCOMP] = palette[(index << 1) + 0];
332
         rgba[ACOMP] = palette[(index << 1) + 1];
333
         return;
334
      case GL_RGB:
335
         rgba[RCOMP] = palette[index * 3 + 0];
336
         rgba[GCOMP] = palette[index * 3 + 1];
337
         rgba[BCOMP] = palette[index * 3 + 2];
338
         return;
339
      case GL_RGBA:
340
         rgba[RCOMP] = palette[(index << 2) + 0];
341
         rgba[GCOMP] = palette[(index << 2) + 1];
342
         rgba[BCOMP] = palette[(index << 2) + 2];
343
         rgba[ACOMP] = palette[(index << 2) + 3];
344
         return;
345
      default:
346
         _mesa_problem(ctx, "Bad palette format in palette_sample");
347
   }
348
}
349
 
350
 
351
/*
352
 * The lambda[] array values are always monotonic.  Either the whole span
353
 * will be minified, magnified, or split between the two.  This function
354
 * determines the subranges in [0, n-1] that are to be minified or magnified.
355
 */
356
static INLINE void
357
compute_min_mag_ranges( GLfloat minMagThresh, GLuint n, const GLfloat lambda[],
358
                        GLuint *minStart, GLuint *minEnd,
359
                        GLuint *magStart, GLuint *magEnd )
360
{
361
   ASSERT(lambda != NULL);
362
#if 0
363
   /* Verify that lambda[] is monotonous.
364
    * We can't really use this because the inaccuracy in the LOG2 function
365
    * causes this test to fail, yet the resulting texturing is correct.
366
    */
367
   if (n > 1) {
368
      GLuint i;
369
      printf("lambda delta = %g\n", lambda[0] - lambda[n-1]);
370
      if (lambda[0] >= lambda[n-1]) { /* decreasing */
371
         for (i = 0; i < n - 1; i++) {
372
            ASSERT((GLint) (lambda[i] * 10) >= (GLint) (lambda[i+1] * 10));
373
         }
374
      }
375
      else { /* increasing */
376
         for (i = 0; i < n - 1; i++) {
377
            ASSERT((GLint) (lambda[i] * 10) <= (GLint) (lambda[i+1] * 10));
378
         }
379
      }
380
   }
381
#endif /* DEBUG */
382
 
383
   /* since lambda is monotonous-array use this check first */
384
   if (lambda[0] <= minMagThresh && lambda[n-1] <= minMagThresh) {
385
      /* magnification for whole span */
386
      *magStart = 0;
387
      *magEnd = n;
388
      *minStart = *minEnd = 0;
389
   }
390
   else if (lambda[0] > minMagThresh && lambda[n-1] > minMagThresh) {
391
      /* minification for whole span */
392
      *minStart = 0;
393
      *minEnd = n;
394
      *magStart = *magEnd = 0;
395
   }
396
   else {
397
      /* a mix of minification and magnification */
398
      GLuint i;
399
      if (lambda[0] > minMagThresh) {
400
         /* start with minification */
401
         for (i = 1; i < n; i++) {
402
            if (lambda[i] <= minMagThresh)
403
               break;
404
         }
405
         *minStart = 0;
406
         *minEnd = i;
407
         *magStart = i;
408
         *magEnd = n;
409
      }
410
      else {
411
         /* start with magnification */
412
         for (i = 1; i < n; i++) {
413
            if (lambda[i] > minMagThresh)
414
               break;
415
         }
416
         *magStart = 0;
417
         *magEnd = i;
418
         *minStart = i;
419
         *minEnd = n;
420
      }
421
   }
422
 
423
#if 0
424
   /* Verify the min/mag Start/End values
425
    * We don't use this either (see above)
426
    */
427
   {
428
      GLint i;
429
      for (i = 0; i < n; i++) {
430
         if (lambda[i] > minMagThresh) {
431
            /* minification */
432
            ASSERT(i >= *minStart);
433
            ASSERT(i < *minEnd);
434
         }
435
         else {
436
            /* magnification */
437
            ASSERT(i >= *magStart);
438
            ASSERT(i < *magEnd);
439
         }
440
      }
441
   }
442
#endif
443
}
444
 
445
 
446
/**********************************************************************/
447
/*                    1-D Texture Sampling Functions                  */
448
/**********************************************************************/
449
 
450
/*
451
 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
452
 */
453
static void
454
sample_1d_nearest(GLcontext *ctx,
455
                  const struct gl_texture_object *tObj,
456
                  const struct gl_texture_image *img,
457
                  const GLfloat texcoord[4], GLchan rgba[4])
458
{
459
   const GLint width = img->Width2;  /* without border, power of two */
460
   GLint i;
461
 
462
   COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoord[0], width, i);
463
 
464
   /* skip over the border, if any */
465
   i += img->Border;
466
 
467
   if (i < 0 || i >= (GLint) img->Width) {
468
      /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
469
      COPY_CHAN4(rgba, tObj->_BorderChan);
470
   }
471
   else {
472
      (*img->FetchTexel)(img, i, 0, 0, (GLvoid *) rgba);
473
      if (img->Format == GL_COLOR_INDEX) {
474
         palette_sample(ctx, tObj, rgba[0], rgba);
475
      }
476
   }
477
}
478
 
479
 
480
 
481
/*
482
 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
483
 */
484
static void
485
sample_1d_linear(GLcontext *ctx,
486
                 const struct gl_texture_object *tObj,
487
                 const struct gl_texture_image *img,
488
                 const GLfloat texcoord[4], GLchan rgba[4])
489
{
490
   const GLint width = img->Width2;
491
   GLint i0, i1;
492
   GLfloat u;
493
   GLuint useBorderColor;
494
 
495
   COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoord[0], u, width, i0, i1);
496
 
497
   useBorderColor = 0;
498
   if (img->Border) {
499
      i0 += img->Border;
500
      i1 += img->Border;
501
   }
502
   else {
503
      if (i0 < 0 || i0 >= width)   useBorderColor |= I0BIT;
504
      if (i1 < 0 || i1 >= width)   useBorderColor |= I1BIT;
505
   }
506
 
507
   {
508
      const GLfloat a = FRAC(u);
509
 
510
#if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
511
      const GLfloat w0 = (1.0F-a);
512
      const GLfloat w1 =       a ;
513
#else /* CHAN_BITS == 8 */
514
      /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
515
      const GLint w0 = IROUND_POS((1.0F - a) * WEIGHT_SCALE);
516
      const GLint w1 = IROUND_POS(        a  * WEIGHT_SCALE);
517
#endif
518
      GLchan t0[4], t1[4];  /* texels */
519
 
520
      if (useBorderColor & I0BIT) {
521
         COPY_CHAN4(t0, tObj->_BorderChan);
522
      }
523
      else {
524
         (*img->FetchTexel)(img, i0, 0, 0, (GLvoid *) t0);
525
         if (img->Format == GL_COLOR_INDEX) {
526
            palette_sample(ctx, tObj, t0[0], t0);
527
         }
528
      }
529
      if (useBorderColor & I1BIT) {
530
         COPY_CHAN4(t1, tObj->_BorderChan);
531
      }
532
      else {
533
         (*img->FetchTexel)(img, i1, 0, 0, (GLvoid *) t1);
534
         if (img->Format == GL_COLOR_INDEX) {
535
            palette_sample(ctx, tObj, t1[0], t1);
536
         }
537
      }
538
 
539
#if CHAN_TYPE == GL_FLOAT
540
      rgba[0] = w0 * t0[0] + w1 * t1[0];
541
      rgba[1] = w0 * t0[1] + w1 * t1[1];
542
      rgba[2] = w0 * t0[2] + w1 * t1[2];
543
      rgba[3] = w0 * t0[3] + w1 * t1[3];
544
#elif CHAN_TYPE == GL_UNSIGNED_SHORT
545
      rgba[0] = (GLchan) (w0 * t0[0] + w1 * t1[0] + 0.5);
546
      rgba[1] = (GLchan) (w0 * t0[1] + w1 * t1[1] + 0.5);
547
      rgba[2] = (GLchan) (w0 * t0[2] + w1 * t1[2] + 0.5);
548
      rgba[3] = (GLchan) (w0 * t0[3] + w1 * t1[3] + 0.5);
549
#else /* CHAN_BITS == 8 */
550
      rgba[0] = (GLchan) ((w0 * t0[0] + w1 * t1[0]) >> WEIGHT_SHIFT);
551
      rgba[1] = (GLchan) ((w0 * t0[1] + w1 * t1[1]) >> WEIGHT_SHIFT);
552
      rgba[2] = (GLchan) ((w0 * t0[2] + w1 * t1[2]) >> WEIGHT_SHIFT);
553
      rgba[3] = (GLchan) ((w0 * t0[3] + w1 * t1[3]) >> WEIGHT_SHIFT);
554
#endif
555
 
556
   }
557
}
558
 
559
 
560
static void
561
sample_1d_nearest_mipmap_nearest(GLcontext *ctx,
562
                                 const struct gl_texture_object *tObj,
563
                                 GLuint n, GLfloat texcoord[][4],
564
                                 const GLfloat lambda[], GLchan rgba[][4])
565
{
566
   GLuint i;
567
   ASSERT(lambda != NULL);
568
   for (i = 0; i < n; i++) {
569
      GLint level;
570
      COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
571
      sample_1d_nearest(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
572
   }
573
}
574
 
575
 
576
static void
577
sample_1d_linear_mipmap_nearest(GLcontext *ctx,
578
                                const struct gl_texture_object *tObj,
579
                                GLuint n, GLfloat texcoord[][4],
580
                                const GLfloat lambda[], GLchan rgba[][4])
581
{
582
   GLuint i;
583
   ASSERT(lambda != NULL);
584
   for (i = 0; i < n; i++) {
585
      GLint level;
586
      COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
587
      sample_1d_linear(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
588
   }
589
}
590
 
591
 
592
 
593
/*
594
 * This is really just needed in order to prevent warnings with some compilers.
595
 */
596
#if CHAN_TYPE == GL_FLOAT
597
#define CHAN_CAST
598
#else
599
#define CHAN_CAST (GLchan) (GLint)
600
#endif
601
 
602
 
603
static void
604
sample_1d_nearest_mipmap_linear(GLcontext *ctx,
605
                                const struct gl_texture_object *tObj,
606
                                GLuint n, GLfloat texcoord[][4],
607
                                const GLfloat lambda[], GLchan rgba[][4])
608
{
609
   GLuint i;
610
   ASSERT(lambda != NULL);
611
   for (i = 0; i < n; i++) {
612
      GLint level;
613
      COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
614
      if (level >= tObj->_MaxLevel) {
615
         sample_1d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel],
616
                           texcoord[i], rgba[i]);
617
      }
618
      else {
619
         GLchan t0[4], t1[4];
620
         const GLfloat f = FRAC(lambda[i]);
621
         sample_1d_nearest(ctx, tObj, tObj->Image[level  ], texcoord[i], t0);
622
         sample_1d_nearest(ctx, tObj, tObj->Image[level+1], texcoord[i], t1);
623
         rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
624
         rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
625
         rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
626
         rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
627
      }
628
   }
629
}
630
 
631
 
632
 
633
static void
634
sample_1d_linear_mipmap_linear(GLcontext *ctx,
635
                               const struct gl_texture_object *tObj,
636
                               GLuint n, GLfloat texcoord[][4],
637
                               const GLfloat lambda[], GLchan rgba[][4])
638
{
639
   GLuint i;
640
   ASSERT(lambda != NULL);
641
   for (i = 0; i < n; i++) {
642
      GLint level;
643
      COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
644
      if (level >= tObj->_MaxLevel) {
645
         sample_1d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel],
646
                          texcoord[i], rgba[i]);
647
      }
648
      else {
649
         GLchan t0[4], t1[4];
650
         const GLfloat f = FRAC(lambda[i]);
651
         sample_1d_linear(ctx, tObj, tObj->Image[level  ], texcoord[i], t0);
652
         sample_1d_linear(ctx, tObj, tObj->Image[level+1], texcoord[i], t1);
653
         rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
654
         rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
655
         rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
656
         rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
657
      }
658
   }
659
}
660
 
661
 
662
 
663
static void
664
sample_nearest_1d( GLcontext *ctx, GLuint texUnit,
665
                   const struct gl_texture_object *tObj, GLuint n,
666
                   GLfloat texcoords[][4], const GLfloat lambda[],
667
                   GLchan rgba[][4] )
668
{
669
   GLuint i;
670
   struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
671
   (void) lambda;
672
   for (i=0;i<n;i++) {
673
      sample_1d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
674
   }
675
}
676
 
677
 
678
 
679
static void
680
sample_linear_1d( GLcontext *ctx, GLuint texUnit,
681
                  const struct gl_texture_object *tObj, GLuint n,
682
                  GLfloat texcoords[][4], const GLfloat lambda[],
683
                  GLchan rgba[][4] )
684
{
685
   GLuint i;
686
   struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
687
   (void) lambda;
688
   for (i=0;i<n;i++) {
689
      sample_1d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
690
   }
691
}
692
 
693
 
694
/*
695
 * Given an (s) texture coordinate and lambda (level of detail) value,
696
 * return a texture sample.
697
 *
698
 */
699
static void
700
sample_lambda_1d( GLcontext *ctx, GLuint texUnit,
701
                  const struct gl_texture_object *tObj, GLuint n,
702
                  GLfloat texcoords[][4],
703
                  const GLfloat lambda[], GLchan rgba[][4] )
704
{
705
   GLuint minStart, minEnd;  /* texels with minification */
706
   GLuint magStart, magEnd;  /* texels with magnification */
707
   GLuint i;
708
 
709
   ASSERT(lambda != NULL);
710
   compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit],
711
                          n, lambda, &minStart, &minEnd, &magStart, &magEnd);
712
 
713
   if (minStart < minEnd) {
714
      /* do the minified texels */
715
      const GLuint m = minEnd - minStart;
716
      switch (tObj->MinFilter) {
717
      case GL_NEAREST:
718
         for (i = minStart; i < minEnd; i++)
719
            sample_1d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
720
                              texcoords[i], rgba[i]);
721
         break;
722
      case GL_LINEAR:
723
         for (i = minStart; i < minEnd; i++)
724
            sample_1d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
725
                             texcoords[i], rgba[i]);
726
         break;
727
      case GL_NEAREST_MIPMAP_NEAREST:
728
         sample_1d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
729
                                          lambda + minStart, rgba + minStart);
730
         break;
731
      case GL_LINEAR_MIPMAP_NEAREST:
732
         sample_1d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
733
                                         lambda + minStart, rgba + minStart);
734
         break;
735
      case GL_NEAREST_MIPMAP_LINEAR:
736
         sample_1d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
737
                                         lambda + minStart, rgba + minStart);
738
         break;
739
      case GL_LINEAR_MIPMAP_LINEAR:
740
         sample_1d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
741
                                        lambda + minStart, rgba + minStart);
742
         break;
743
      default:
744
         _mesa_problem(ctx, "Bad min filter in sample_1d_texture");
745
         return;
746
      }
747
   }
748
 
749
   if (magStart < magEnd) {
750
      /* do the magnified texels */
751
      switch (tObj->MagFilter) {
752
      case GL_NEAREST:
753
         for (i = magStart; i < magEnd; i++)
754
            sample_1d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
755
                              texcoords[i], rgba[i]);
756
         break;
757
      case GL_LINEAR:
758
         for (i = magStart; i < magEnd; i++)
759
            sample_1d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
760
                             texcoords[i], rgba[i]);
761
         break;
762
      default:
763
         _mesa_problem(ctx, "Bad mag filter in sample_1d_texture");
764
         return;
765
      }
766
   }
767
}
768
 
769
 
770
/**********************************************************************/
771
/*                    2-D Texture Sampling Functions                  */
772
/**********************************************************************/
773
 
774
 
775
/*
776
 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
777
 */
778
static INLINE void
779
sample_2d_nearest(GLcontext *ctx,
780
                  const struct gl_texture_object *tObj,
781
                  const struct gl_texture_image *img,
782
                  const GLfloat texcoord[4],
783
                  GLchan rgba[])
784
{
785
   const GLint width = img->Width2;    /* without border, power of two */
786
   const GLint height = img->Height2;  /* without border, power of two */
787
   GLint i, j;
788
 
789
   COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoord[0], width,  i);
790
   COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, texcoord[1], height, j);
791
 
792
   /* skip over the border, if any */
793
   i += img->Border;
794
   j += img->Border;
795
 
796
   if (i < 0 || i >= (GLint) img->Width || j < 0 || j >= (GLint) img->Height) {
797
      /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
798
      COPY_CHAN4(rgba, tObj->_BorderChan);
799
   }
800
   else {
801
      (*img->FetchTexel)(img, i, j, 0, (GLvoid *) rgba);
802
      if (img->Format == GL_COLOR_INDEX) {
803
         palette_sample(ctx, tObj, rgba[0], rgba);
804
      }
805
   }
806
}
807
 
808
 
809
 
810
/*
811
 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
812
 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
813
 */
814
static INLINE void
815
sample_2d_linear(GLcontext *ctx,
816
                 const struct gl_texture_object *tObj,
817
                 const struct gl_texture_image *img,
818
                 const GLfloat texcoord[4],
819
                 GLchan rgba[])
820
{
821
   const GLint width = img->Width2;
822
   const GLint height = img->Height2;
823
   GLint i0, j0, i1, j1;
824
   GLuint useBorderColor;
825
   GLfloat u, v;
826
 
827
   COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoord[0], u, width,  i0, i1);
828
   COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, texcoord[1], v, height, j0, j1);
829
 
830
   useBorderColor = 0;
831
   if (img->Border) {
832
      i0 += img->Border;
833
      i1 += img->Border;
834
      j0 += img->Border;
835
      j1 += img->Border;
836
   }
837
   else {
838
      if (i0 < 0 || i0 >= width)   useBorderColor |= I0BIT;
839
      if (i1 < 0 || i1 >= width)   useBorderColor |= I1BIT;
840
      if (j0 < 0 || j0 >= height)  useBorderColor |= J0BIT;
841
      if (j1 < 0 || j1 >= height)  useBorderColor |= J1BIT;
842
   }
843
 
844
   {
845
      const GLfloat a = FRAC(u);
846
      const GLfloat b = FRAC(v);
847
 
848
#if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
849
      const GLfloat w00 = (1.0F-a) * (1.0F-b);
850
      const GLfloat w10 =       a  * (1.0F-b);
851
      const GLfloat w01 = (1.0F-a) *       b ;
852
      const GLfloat w11 =       a  *       b ;
853
#else /* CHAN_BITS == 8 */
854
      /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
855
      const GLint w00 = IROUND_POS((1.0F-a) * (1.0F-b) * WEIGHT_SCALE);
856
      const GLint w10 = IROUND_POS(      a  * (1.0F-b) * WEIGHT_SCALE);
857
      const GLint w01 = IROUND_POS((1.0F-a) *       b  * WEIGHT_SCALE);
858
      const GLint w11 = IROUND_POS(      a  *       b  * WEIGHT_SCALE);
859
#endif
860
      GLchan t00[4];
861
      GLchan t10[4];
862
      GLchan t01[4];
863
      GLchan t11[4];
864
 
865
      if (useBorderColor & (I0BIT | J0BIT)) {
866
         COPY_CHAN4(t00, tObj->_BorderChan);
867
      }
868
      else {
869
         (*img->FetchTexel)(img, i0, j0, 0, (GLvoid *) t00);
870
         if (img->Format == GL_COLOR_INDEX) {
871
            palette_sample(ctx, tObj, t00[0], t00);
872
         }
873
      }
874
      if (useBorderColor & (I1BIT | J0BIT)) {
875
         COPY_CHAN4(t10, tObj->_BorderChan);
876
      }
877
      else {
878
         (*img->FetchTexel)(img, i1, j0, 0, (GLvoid *) t10);
879
         if (img->Format == GL_COLOR_INDEX) {
880
            palette_sample(ctx, tObj, t10[0], t10);
881
         }
882
      }
883
      if (useBorderColor & (I0BIT | J1BIT)) {
884
         COPY_CHAN4(t01, tObj->_BorderChan);
885
      }
886
      else {
887
         (*img->FetchTexel)(img, i0, j1, 0, (GLvoid *) t01);
888
         if (img->Format == GL_COLOR_INDEX) {
889
            palette_sample(ctx, tObj, t01[0], t01);
890
         }
891
      }
892
      if (useBorderColor & (I1BIT | J1BIT)) {
893
         COPY_CHAN4(t11, tObj->_BorderChan);
894
      }
895
      else {
896
         (*img->FetchTexel)(img, i1, j1, 0, (GLvoid *) t11);
897
         if (img->Format == GL_COLOR_INDEX) {
898
            palette_sample(ctx, tObj, t11[0], t11);
899
         }
900
      }
901
#if CHAN_TYPE == GL_FLOAT
902
      rgba[0] = w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0];
903
      rgba[1] = w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1];
904
      rgba[2] = w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2];
905
      rgba[3] = w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3];
906
#elif CHAN_TYPE == GL_UNSIGNED_SHORT
907
      rgba[0] = (GLchan) (w00 * t00[0] + w10 * t10[0] +
908
                          w01 * t01[0] + w11 * t11[0] + 0.5);
909
      rgba[1] = (GLchan) (w00 * t00[1] + w10 * t10[1] +
910
                          w01 * t01[1] + w11 * t11[1] + 0.5);
911
      rgba[2] = (GLchan) (w00 * t00[2] + w10 * t10[2] +
912
                          w01 * t01[2] + w11 * t11[2] + 0.5);
913
      rgba[3] = (GLchan) (w00 * t00[3] + w10 * t10[3] +
914
                          w01 * t01[3] + w11 * t11[3] + 0.5);
915
#else /* CHAN_BITS == 8 */
916
      rgba[0] = (GLchan) ((w00 * t00[0] + w10 * t10[0] +
917
                           w01 * t01[0] + w11 * t11[0]) >> WEIGHT_SHIFT);
918
      rgba[1] = (GLchan) ((w00 * t00[1] + w10 * t10[1] +
919
                           w01 * t01[1] + w11 * t11[1]) >> WEIGHT_SHIFT);
920
      rgba[2] = (GLchan) ((w00 * t00[2] + w10 * t10[2] +
921
                           w01 * t01[2] + w11 * t11[2]) >> WEIGHT_SHIFT);
922
      rgba[3] = (GLchan) ((w00 * t00[3] + w10 * t10[3] +
923
                           w01 * t01[3] + w11 * t11[3]) >> WEIGHT_SHIFT);
924
#endif
925
 
926
   }
927
 
928
}
929
 
930
 
931
/*
932
 * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT
933
 * and we're not using a paletted texture.
934
 */
935
static INLINE void
936
sample_2d_linear_repeat(GLcontext *ctx,
937
                        const struct gl_texture_object *tObj,
938
                        const struct gl_texture_image *img,
939
                        const GLfloat texcoord[4],
940
                        GLchan rgba[])
941
{
942
   const GLint width = img->Width2;
943
   const GLint height = img->Height2;
944
   GLint i0, j0, i1, j1;
945
   GLfloat u, v;
946
 
947
   ASSERT(tObj->WrapS == GL_REPEAT);
948
   ASSERT(tObj->WrapT == GL_REPEAT);
949
   ASSERT(img->Border == 0);
950
   ASSERT(img->Format != GL_COLOR_INDEX);
951
 
952
   COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord[0], u, width,  i0, i1);
953
   COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord[1], v, height, j0, j1);
954
 
955
   {
956
      const GLfloat a = FRAC(u);
957
      const GLfloat b = FRAC(v);
958
 
959
#if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
960
      const GLfloat w00 = (1.0F-a) * (1.0F-b);
961
      const GLfloat w10 =       a  * (1.0F-b);
962
      const GLfloat w01 = (1.0F-a) *       b ;
963
      const GLfloat w11 =       a  *       b ;
964
#else /* CHAN_BITS == 8 */
965
      /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
966
      const GLint w00 = IROUND_POS((1.0F-a) * (1.0F-b) * WEIGHT_SCALE);
967
      const GLint w10 = IROUND_POS(      a  * (1.0F-b) * WEIGHT_SCALE);
968
      const GLint w01 = IROUND_POS((1.0F-a) *       b  * WEIGHT_SCALE);
969
      const GLint w11 = IROUND_POS(      a  *       b  * WEIGHT_SCALE);
970
#endif
971
      GLchan t00[4];
972
      GLchan t10[4];
973
      GLchan t01[4];
974
      GLchan t11[4];
975
 
976
      (*img->FetchTexel)(img, i0, j0, 0, (GLvoid *) t00);
977
      (*img->FetchTexel)(img, i1, j0, 0, (GLvoid *) t10);
978
      (*img->FetchTexel)(img, i0, j1, 0, (GLvoid *) t01);
979
      (*img->FetchTexel)(img, i1, j1, 0, (GLvoid *) t11);
980
 
981
#if CHAN_TYPE == GL_FLOAT
982
      rgba[0] = w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0];
983
      rgba[1] = w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1];
984
      rgba[2] = w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2];
985
      rgba[3] = w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3];
986
#elif CHAN_TYPE == GL_UNSIGNED_SHORT
987
      rgba[0] = (GLchan) (w00 * t00[0] + w10 * t10[0] +
988
                          w01 * t01[0] + w11 * t11[0] + 0.5);
989
      rgba[1] = (GLchan) (w00 * t00[1] + w10 * t10[1] +
990
                          w01 * t01[1] + w11 * t11[1] + 0.5);
991
      rgba[2] = (GLchan) (w00 * t00[2] + w10 * t10[2] +
992
                          w01 * t01[2] + w11 * t11[2] + 0.5);
993
      rgba[3] = (GLchan) (w00 * t00[3] + w10 * t10[3] +
994
                          w01 * t01[3] + w11 * t11[3] + 0.5);
995
#else /* CHAN_BITS == 8 */
996
      rgba[0] = (GLchan) ((w00 * t00[0] + w10 * t10[0] +
997
                           w01 * t01[0] + w11 * t11[0]) >> WEIGHT_SHIFT);
998
      rgba[1] = (GLchan) ((w00 * t00[1] + w10 * t10[1] +
999
                           w01 * t01[1] + w11 * t11[1]) >> WEIGHT_SHIFT);
1000
      rgba[2] = (GLchan) ((w00 * t00[2] + w10 * t10[2] +
1001
                           w01 * t01[2] + w11 * t11[2]) >> WEIGHT_SHIFT);
1002
      rgba[3] = (GLchan) ((w00 * t00[3] + w10 * t10[3] +
1003
                           w01 * t01[3] + w11 * t11[3]) >> WEIGHT_SHIFT);
1004
#endif
1005
 
1006
   }
1007
 
1008
}
1009
 
1010
 
1011
 
1012
static void
1013
sample_2d_nearest_mipmap_nearest(GLcontext *ctx,
1014
                                 const struct gl_texture_object *tObj,
1015
                                 GLuint n, GLfloat texcoord[][4],
1016
                                 const GLfloat lambda[], GLchan rgba[][4])
1017
{
1018
   GLuint i;
1019
   for (i = 0; i < n; i++) {
1020
      GLint level;
1021
      COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
1022
      sample_2d_nearest(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
1023
   }
1024
}
1025
 
1026
 
1027
 
1028
static void
1029
sample_2d_linear_mipmap_nearest(GLcontext *ctx,
1030
                                const struct gl_texture_object *tObj,
1031
                                GLuint n, GLfloat texcoord[][4],
1032
                                const GLfloat lambda[], GLchan rgba[][4])
1033
{
1034
   GLuint i;
1035
   ASSERT(lambda != NULL);
1036
   for (i = 0; i < n; i++) {
1037
      GLint level;
1038
      COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
1039
      sample_2d_linear(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
1040
   }
1041
}
1042
 
1043
 
1044
 
1045
static void
1046
sample_2d_nearest_mipmap_linear(GLcontext *ctx,
1047
                                const struct gl_texture_object *tObj,
1048
                                GLuint n, GLfloat texcoord[][4],
1049
                                const GLfloat lambda[], GLchan rgba[][4])
1050
{
1051
   GLuint i;
1052
   ASSERT(lambda != NULL);
1053
   for (i = 0; i < n; i++) {
1054
      GLint level;
1055
      COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
1056
      if (level >= tObj->_MaxLevel) {
1057
         sample_2d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel],
1058
                           texcoord[i], rgba[i]);
1059
      }
1060
      else {
1061
         GLchan t0[4], t1[4];  /* texels */
1062
         const GLfloat f = FRAC(lambda[i]);
1063
         sample_2d_nearest(ctx, tObj, tObj->Image[level  ], texcoord[i], t0);
1064
         sample_2d_nearest(ctx, tObj, tObj->Image[level+1], texcoord[i], t1);
1065
         rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
1066
         rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
1067
         rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
1068
         rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
1069
      }
1070
   }
1071
}
1072
 
1073
 
1074
 
1075
/* Trilinear filtering */
1076
static void
1077
sample_2d_linear_mipmap_linear( GLcontext *ctx,
1078
                                const struct gl_texture_object *tObj,
1079
                                GLuint n, GLfloat texcoord[][4],
1080
                                const GLfloat lambda[], GLchan rgba[][4] )
1081
{
1082
   GLuint i;
1083
   ASSERT(lambda != NULL);
1084
   for (i = 0; i < n; i++) {
1085
      GLint level;
1086
      COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
1087
      if (level >= tObj->_MaxLevel) {
1088
         sample_2d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel],
1089
                          texcoord[i], rgba[i]);
1090
      }
1091
      else {
1092
         GLchan t0[4], t1[4];  /* texels */
1093
         const GLfloat f = FRAC(lambda[i]);
1094
         sample_2d_linear(ctx, tObj, tObj->Image[level  ], texcoord[i], t0);
1095
         sample_2d_linear(ctx, tObj, tObj->Image[level+1], texcoord[i], t1);
1096
         rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
1097
         rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
1098
         rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
1099
         rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
1100
      }
1101
   }
1102
}
1103
 
1104
 
1105
static void
1106
sample_2d_linear_mipmap_linear_repeat( GLcontext *ctx,
1107
                                       const struct gl_texture_object *tObj,
1108
                                       GLuint n, GLfloat texcoord[][4],
1109
                                       const GLfloat lambda[], GLchan rgba[][4] )
1110
{
1111
   GLuint i;
1112
   ASSERT(lambda != NULL);
1113
   ASSERT(tObj->WrapS == GL_REPEAT);
1114
   ASSERT(tObj->WrapT == GL_REPEAT);
1115
   for (i = 0; i < n; i++) {
1116
      GLint level;
1117
      COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
1118
      if (level >= tObj->_MaxLevel) {
1119
         sample_2d_linear_repeat(ctx, tObj, tObj->Image[tObj->_MaxLevel],
1120
                                 texcoord[i], rgba[i]);
1121
      }
1122
      else {
1123
         GLchan t0[4], t1[4];  /* texels */
1124
         const GLfloat f = FRAC(lambda[i]);
1125
         sample_2d_linear_repeat(ctx, tObj, tObj->Image[level  ], texcoord[i], t0);
1126
         sample_2d_linear_repeat(ctx, tObj, tObj->Image[level+1], texcoord[i], t1);
1127
         rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
1128
         rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
1129
         rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
1130
         rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
1131
      }
1132
   }
1133
}
1134
 
1135
 
1136
static void
1137
sample_nearest_2d( GLcontext *ctx, GLuint texUnit,
1138
                   const struct gl_texture_object *tObj, GLuint n,
1139
                   GLfloat texcoords[][4],
1140
                   const GLfloat lambda[], GLchan rgba[][4] )
1141
{
1142
   GLuint i;
1143
   struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
1144
   (void) lambda;
1145
   for (i=0;i<n;i++) {
1146
      sample_2d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
1147
   }
1148
}
1149
 
1150
 
1151
 
1152
static void
1153
sample_linear_2d( GLcontext *ctx, GLuint texUnit,
1154
                  const struct gl_texture_object *tObj, GLuint n,
1155
                  GLfloat texcoords[][4],
1156
                  const GLfloat lambda[], GLchan rgba[][4] )
1157
{
1158
   GLuint i;
1159
   struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
1160
   (void) lambda;
1161
   for (i=0;i<n;i++) {
1162
      sample_2d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
1163
   }
1164
}
1165
 
1166
 
1167
/*
1168
 * Optimized 2-D texture sampling:
1169
 *    S and T wrap mode == GL_REPEAT
1170
 *    GL_NEAREST min/mag filter
1171
 *    No border,
1172
 *    RowStride == Width,
1173
 *    Format = GL_RGB
1174
 */
1175
static void
1176
opt_sample_rgb_2d( GLcontext *ctx, GLuint texUnit,
1177
                   const struct gl_texture_object *tObj,
1178
                   GLuint n, GLfloat texcoords[][4],
1179
                   const GLfloat lambda[], GLchan rgba[][4] )
1180
{
1181
   const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel];
1182
   const GLfloat width = (GLfloat) img->Width;
1183
   const GLfloat height = (GLfloat) img->Height;
1184
   const GLint colMask = img->Width - 1;
1185
   const GLint rowMask = img->Height - 1;
1186
   const GLint shift = img->WidthLog2;
1187
   GLuint k;
1188
   (void) lambda;
1189
   ASSERT(tObj->WrapS==GL_REPEAT);
1190
   ASSERT(tObj->WrapT==GL_REPEAT);
1191
   ASSERT(img->Border==0);
1192
   ASSERT(img->Format==GL_RGB);
1193
 
1194
   for (k=0; k<n; k++) {
1195
      GLint i = IFLOOR(texcoords[k][0] * width) & colMask;
1196
      GLint j = IFLOOR(texcoords[k][1] * height) & rowMask;
1197
      GLint pos = (j << shift) | i;
1198
      GLchan *texel = ((GLchan *) img->Data) + 3*pos;
1199
      rgba[k][RCOMP] = texel[0];
1200
      rgba[k][GCOMP] = texel[1];
1201
      rgba[k][BCOMP] = texel[2];
1202
   }
1203
}
1204
 
1205
 
1206
/*
1207
 * Optimized 2-D texture sampling:
1208
 *    S and T wrap mode == GL_REPEAT
1209
 *    GL_NEAREST min/mag filter
1210
 *    No border
1211
 *    RowStride == Width,
1212
 *    Format = GL_RGBA
1213
 */
1214
static void
1215
opt_sample_rgba_2d( GLcontext *ctx, GLuint texUnit,
1216
                    const struct gl_texture_object *tObj,
1217
                    GLuint n, GLfloat texcoords[][4],
1218
                    const GLfloat lambda[], GLchan rgba[][4] )
1219
{
1220
   const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel];
1221
   const GLfloat width = (GLfloat) img->Width;
1222
   const GLfloat height = (GLfloat) img->Height;
1223
   const GLint colMask = img->Width - 1;
1224
   const GLint rowMask = img->Height - 1;
1225
   const GLint shift = img->WidthLog2;
1226
   GLuint i;
1227
   (void) lambda;
1228
   ASSERT(tObj->WrapS==GL_REPEAT);
1229
   ASSERT(tObj->WrapT==GL_REPEAT);
1230
   ASSERT(img->Border==0);
1231
   ASSERT(img->Format==GL_RGBA);
1232
 
1233
   for (i = 0; i < n; i++) {
1234
      const GLint col = IFLOOR(texcoords[i][0] * width) & colMask;
1235
      const GLint row = IFLOOR(texcoords[i][1] * height) & rowMask;
1236
      const GLint pos = (row << shift) | col;
1237
      const GLchan *texel = ((GLchan *) img->Data) + (pos << 2);    /* pos*4 */
1238
      COPY_CHAN4(rgba[i], texel);
1239
   }
1240
}
1241
 
1242
 
1243
/*
1244
 * Given an array of texture coordinate and lambda (level of detail)
1245
 * values, return an array of texture sample.
1246
 */
1247
static void
1248
sample_lambda_2d( GLcontext *ctx, GLuint texUnit,
1249
                  const struct gl_texture_object *tObj,
1250
                  GLuint n, GLfloat texcoords[][4],
1251
                  const GLfloat lambda[], GLchan rgba[][4] )
1252
{
1253
   const struct gl_texture_image *tImg = tObj->Image[tObj->BaseLevel];
1254
   GLuint minStart, minEnd;  /* texels with minification */
1255
   GLuint magStart, magEnd;  /* texels with magnification */
1256
 
1257
   const GLboolean repeatNoBorder = (tObj->WrapS == GL_REPEAT)
1258
      && (tObj->WrapT == GL_REPEAT)
1259
      && (tImg->Border == 0 && (tImg->Width == tImg->RowStride))
1260
      && (tImg->Format != GL_COLOR_INDEX);
1261
 
1262
   ASSERT(lambda != NULL);
1263
   compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit],
1264
                          n, lambda, &minStart, &minEnd, &magStart, &magEnd);
1265
 
1266
   if (minStart < minEnd) {
1267
      /* do the minified texels */
1268
      const GLuint m = minEnd - minStart;
1269
      switch (tObj->MinFilter) {
1270
      case GL_NEAREST:
1271
         if (repeatNoBorder) {
1272
            switch (tImg->Format) {
1273
            case GL_RGB:
1274
               opt_sample_rgb_2d(ctx, texUnit, tObj, m, texcoords + minStart,
1275
                                 NULL, rgba + minStart);
1276
               break;
1277
            case GL_RGBA:
1278
               opt_sample_rgba_2d(ctx, texUnit, tObj, m, texcoords + minStart,
1279
                                  NULL, rgba + minStart);
1280
               break;
1281
            default:
1282
               sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + minStart,
1283
                                 NULL, rgba + minStart );
1284
            }
1285
         }
1286
         else {
1287
            sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + minStart,
1288
                              NULL, rgba + minStart);
1289
         }
1290
         break;
1291
      case GL_LINEAR:
1292
         sample_linear_2d(ctx, texUnit, tObj, m, texcoords + minStart,
1293
                          NULL, rgba + minStart);
1294
         break;
1295
      case GL_NEAREST_MIPMAP_NEAREST:
1296
         sample_2d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
1297
                                          lambda + minStart, rgba + minStart);
1298
         break;
1299
      case GL_LINEAR_MIPMAP_NEAREST:
1300
         sample_2d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
1301
                                         lambda + minStart, rgba + minStart);
1302
         break;
1303
      case GL_NEAREST_MIPMAP_LINEAR:
1304
         sample_2d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
1305
                                         lambda + minStart, rgba + minStart);
1306
         break;
1307
      case GL_LINEAR_MIPMAP_LINEAR:
1308
         if (repeatNoBorder)
1309
            sample_2d_linear_mipmap_linear_repeat(ctx, tObj, m,
1310
                  texcoords + minStart, lambda + minStart, rgba + minStart);
1311
         else
1312
            sample_2d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
1313
                                        lambda + minStart, rgba + minStart);
1314
         break;
1315
      default:
1316
         _mesa_problem(ctx, "Bad min filter in sample_2d_texture");
1317
         return;
1318
      }
1319
   }
1320
 
1321
   if (magStart < magEnd) {
1322
      /* do the magnified texels */
1323
      const GLuint m = magEnd - magStart;
1324
 
1325
      switch (tObj->MagFilter) {
1326
      case GL_NEAREST:
1327
         if (repeatNoBorder) {
1328
            switch (tImg->Format) {
1329
            case GL_RGB:
1330
               opt_sample_rgb_2d(ctx, texUnit, tObj, m, texcoords + magStart,
1331
                                 NULL, rgba + magStart);
1332
               break;
1333
            case GL_RGBA:
1334
               opt_sample_rgba_2d(ctx, texUnit, tObj, m, texcoords + magStart,
1335
                                  NULL, rgba + magStart);
1336
               break;
1337
            default:
1338
               sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + magStart,
1339
                                 NULL, rgba + magStart );
1340
            }
1341
         }
1342
         else {
1343
            sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + magStart,
1344
                              NULL, rgba + magStart);
1345
         }
1346
         break;
1347
      case GL_LINEAR:
1348
         sample_linear_2d(ctx, texUnit, tObj, m, texcoords + magStart,
1349
                          NULL, rgba + magStart);
1350
         break;
1351
      default:
1352
         _mesa_problem(ctx, "Bad mag filter in sample_lambda_2d");
1353
      }
1354
   }
1355
}
1356
 
1357
 
1358
 
1359
/**********************************************************************/
1360
/*                    3-D Texture Sampling Functions                  */
1361
/**********************************************************************/
1362
 
1363
/*
1364
 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1365
 */
1366
static void
1367
sample_3d_nearest(GLcontext *ctx,
1368
                  const struct gl_texture_object *tObj,
1369
                  const struct gl_texture_image *img,
1370
                  const GLfloat texcoord[4],
1371
                  GLchan rgba[4])
1372
{
1373
   const GLint width = img->Width2;     /* without border, power of two */
1374
   const GLint height = img->Height2;   /* without border, power of two */
1375
   const GLint depth = img->Depth2;     /* without border, power of two */
1376
   GLint i, j, k;
1377
 
1378
   COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoord[0], width,  i);
1379
   COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, texcoord[1], height, j);
1380
   COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapR, texcoord[2], depth,  k);
1381
 
1382
   if (i < 0 || i >= (GLint) img->Width ||
1383
       j < 0 || j >= (GLint) img->Height ||
1384
       k < 0 || k >= (GLint) img->Depth) {
1385
      /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
1386
      COPY_CHAN4(rgba, tObj->_BorderChan);
1387
   }
1388
   else {
1389
      (*img->FetchTexel)(img, i, j, k, (GLvoid *) rgba);
1390
      if (img->Format == GL_COLOR_INDEX) {
1391
         palette_sample(ctx, tObj, rgba[0], rgba);
1392
      }
1393
   }
1394
}
1395
 
1396
 
1397
 
1398
/*
1399
 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1400
 */
1401
static void
1402
sample_3d_linear(GLcontext *ctx,
1403
                 const struct gl_texture_object *tObj,
1404
                 const struct gl_texture_image *img,
1405
                 const GLfloat texcoord[4],
1406
                 GLchan rgba[4])
1407
{
1408
   const GLint width = img->Width2;
1409
   const GLint height = img->Height2;
1410
   const GLint depth = img->Depth2;
1411
   GLint i0, j0, k0, i1, j1, k1;
1412
   GLuint useBorderColor;
1413
   GLfloat u, v, w;
1414
 
1415
   COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoord[0], u, width,  i0, i1);
1416
   COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, texcoord[1], v, height, j0, j1);
1417
   COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapR, texcoord[2], w, depth,  k0, k1);
1418
 
1419
   useBorderColor = 0;
1420
   if (img->Border) {
1421
      i0 += img->Border;
1422
      i1 += img->Border;
1423
      j0 += img->Border;
1424
      j1 += img->Border;
1425
      k0 += img->Border;
1426
      k1 += img->Border;
1427
   }
1428
   else {
1429
      /* check if sampling texture border color */
1430
      if (i0 < 0 || i0 >= width)   useBorderColor |= I0BIT;
1431
      if (i1 < 0 || i1 >= width)   useBorderColor |= I1BIT;
1432
      if (j0 < 0 || j0 >= height)  useBorderColor |= J0BIT;
1433
      if (j1 < 0 || j1 >= height)  useBorderColor |= J1BIT;
1434
      if (k0 < 0 || k0 >= depth)   useBorderColor |= K0BIT;
1435
      if (k1 < 0 || k1 >= depth)   useBorderColor |= K1BIT;
1436
   }
1437
 
1438
   {
1439
      const GLfloat a = FRAC(u);
1440
      const GLfloat b = FRAC(v);
1441
      const GLfloat c = FRAC(w);
1442
 
1443
#if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
1444
      /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1445
      GLfloat w000 = (1.0F-a) * (1.0F-b) * (1.0F-c);
1446
      GLfloat w100 =       a  * (1.0F-b) * (1.0F-c);
1447
      GLfloat w010 = (1.0F-a) *       b  * (1.0F-c);
1448
      GLfloat w110 =       a  *       b  * (1.0F-c);
1449
      GLfloat w001 = (1.0F-a) * (1.0F-b) *       c ;
1450
      GLfloat w101 =       a  * (1.0F-b) *       c ;
1451
      GLfloat w011 = (1.0F-a) *       b  *       c ;
1452
      GLfloat w111 =       a  *       b  *       c ;
1453
#else /* CHAN_BITS == 8 */
1454
      /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1455
      GLint w000 = IROUND_POS((1.0F-a) * (1.0F-b) * (1.0F-c) * WEIGHT_SCALE);
1456
      GLint w100 = IROUND_POS(      a  * (1.0F-b) * (1.0F-c) * WEIGHT_SCALE);
1457
      GLint w010 = IROUND_POS((1.0F-a) *       b  * (1.0F-c) * WEIGHT_SCALE);
1458
      GLint w110 = IROUND_POS(      a  *       b  * (1.0F-c) * WEIGHT_SCALE);
1459
      GLint w001 = IROUND_POS((1.0F-a) * (1.0F-b) *       c  * WEIGHT_SCALE);
1460
      GLint w101 = IROUND_POS(      a  * (1.0F-b) *       c  * WEIGHT_SCALE);
1461
      GLint w011 = IROUND_POS((1.0F-a) *       b  *       c  * WEIGHT_SCALE);
1462
      GLint w111 = IROUND_POS(      a  *       b  *       c  * WEIGHT_SCALE);
1463
#endif
1464
 
1465
      GLchan t000[4], t010[4], t001[4], t011[4];
1466
      GLchan t100[4], t110[4], t101[4], t111[4];
1467
 
1468
      if (useBorderColor & (I0BIT | J0BIT | K0BIT)) {
1469
         COPY_CHAN4(t000, tObj->_BorderChan);
1470
      }
1471
      else {
1472
         (*img->FetchTexel)(img, i0, j0, k0, (GLvoid *) t000);
1473
         if (img->Format == GL_COLOR_INDEX) {
1474
            palette_sample(ctx, tObj, t000[0], t000);
1475
         }
1476
      }
1477
      if (useBorderColor & (I1BIT | J0BIT | K0BIT)) {
1478
         COPY_CHAN4(t100, tObj->_BorderChan);
1479
      }
1480
      else {
1481
         (*img->FetchTexel)(img, i1, j0, k0, (GLvoid *) t100);
1482
         if (img->Format == GL_COLOR_INDEX) {
1483
            palette_sample(ctx, tObj, t100[0], t100);
1484
         }
1485
      }
1486
      if (useBorderColor & (I0BIT | J1BIT | K0BIT)) {
1487
         COPY_CHAN4(t010, tObj->_BorderChan);
1488
      }
1489
      else {
1490
         (*img->FetchTexel)(img, i0, j1, k0, (GLvoid *) t010);
1491
         if (img->Format == GL_COLOR_INDEX) {
1492
            palette_sample(ctx, tObj, t010[0], t010);
1493
         }
1494
      }
1495
      if (useBorderColor & (I1BIT | J1BIT | K0BIT)) {
1496
         COPY_CHAN4(t110, tObj->_BorderChan);
1497
      }
1498
      else {
1499
         (*img->FetchTexel)(img, i1, j1, k0, (GLvoid *) t110);
1500
         if (img->Format == GL_COLOR_INDEX) {
1501
            palette_sample(ctx, tObj, t110[0], t110);
1502
         }
1503
      }
1504
 
1505
      if (useBorderColor & (I0BIT | J0BIT | K1BIT)) {
1506
         COPY_CHAN4(t001, tObj->_BorderChan);
1507
      }
1508
      else {
1509
         (*img->FetchTexel)(img, i0, j0, k1, (GLvoid *) t001);
1510
         if (img->Format == GL_COLOR_INDEX) {
1511
            palette_sample(ctx, tObj, t001[0], t001);
1512
         }
1513
      }
1514
      if (useBorderColor & (I1BIT | J0BIT | K1BIT)) {
1515
         COPY_CHAN4(t101, tObj->_BorderChan);
1516
      }
1517
      else {
1518
         (*img->FetchTexel)(img, i1, j0, k1, (GLvoid *) t101);
1519
         if (img->Format == GL_COLOR_INDEX) {
1520
            palette_sample(ctx, tObj, t101[0], t101);
1521
         }
1522
      }
1523
      if (useBorderColor & (I0BIT | J1BIT | K1BIT)) {
1524
         COPY_CHAN4(t011, tObj->_BorderChan);
1525
      }
1526
      else {
1527
         (*img->FetchTexel)(img, i0, j1, k1, (GLvoid *) t011);
1528
         if (img->Format == GL_COLOR_INDEX) {
1529
            palette_sample(ctx, tObj, t011[0], t011);
1530
         }
1531
      }
1532
      if (useBorderColor & (I1BIT | J1BIT | K1BIT)) {
1533
         COPY_CHAN4(t111, tObj->_BorderChan);
1534
      }
1535
      else {
1536
         (*img->FetchTexel)(img, i1, j1, k1, (GLvoid *) t111);
1537
         if (img->Format == GL_COLOR_INDEX) {
1538
            palette_sample(ctx, tObj, t111[0], t111);
1539
         }
1540
      }
1541
 
1542
#if CHAN_TYPE == GL_FLOAT
1543
      rgba[0] = w000*t000[0] + w010*t010[0] + w001*t001[0] + w011*t011[0] +
1544
                w100*t100[0] + w110*t110[0] + w101*t101[0] + w111*t111[0];
1545
      rgba[1] = w000*t000[1] + w010*t010[1] + w001*t001[1] + w011*t011[1] +
1546
                w100*t100[1] + w110*t110[1] + w101*t101[1] + w111*t111[1];
1547
      rgba[2] = w000*t000[2] + w010*t010[2] + w001*t001[2] + w011*t011[2] +
1548
                w100*t100[2] + w110*t110[2] + w101*t101[2] + w111*t111[2];
1549
      rgba[3] = w000*t000[3] + w010*t010[3] + w001*t001[3] + w011*t011[3] +
1550
                w100*t100[3] + w110*t110[3] + w101*t101[3] + w111*t111[3];
1551
#elif CHAN_TYPE == GL_UNSIGNED_SHORT
1552
      rgba[0] = (GLchan) (w000*t000[0] + w010*t010[0] +
1553
                          w001*t001[0] + w011*t011[0] +
1554
                          w100*t100[0] + w110*t110[0] +
1555
                          w101*t101[0] + w111*t111[0] + 0.5);
1556
      rgba[1] = (GLchan) (w000*t000[1] + w010*t010[1] +
1557
                          w001*t001[1] + w011*t011[1] +
1558
                          w100*t100[1] + w110*t110[1] +
1559
                          w101*t101[1] + w111*t111[1] + 0.5);
1560
      rgba[2] = (GLchan) (w000*t000[2] + w010*t010[2] +
1561
                          w001*t001[2] + w011*t011[2] +
1562
                          w100*t100[2] + w110*t110[2] +
1563
                          w101*t101[2] + w111*t111[2] + 0.5);
1564
      rgba[3] = (GLchan) (w000*t000[3] + w010*t010[3] +
1565
                          w001*t001[3] + w011*t011[3] +
1566
                          w100*t100[3] + w110*t110[3] +
1567
                          w101*t101[3] + w111*t111[3] + 0.5);
1568
#else /* CHAN_BITS == 8 */
1569
      rgba[0] = (GLchan) (
1570
                 (w000*t000[0] + w010*t010[0] + w001*t001[0] + w011*t011[0] +
1571
                  w100*t100[0] + w110*t110[0] + w101*t101[0] + w111*t111[0] )
1572
                 >> WEIGHT_SHIFT);
1573
      rgba[1] = (GLchan) (
1574
                 (w000*t000[1] + w010*t010[1] + w001*t001[1] + w011*t011[1] +
1575
                  w100*t100[1] + w110*t110[1] + w101*t101[1] + w111*t111[1] )
1576
                 >> WEIGHT_SHIFT);
1577
      rgba[2] = (GLchan) (
1578
                 (w000*t000[2] + w010*t010[2] + w001*t001[2] + w011*t011[2] +
1579
                  w100*t100[2] + w110*t110[2] + w101*t101[2] + w111*t111[2] )
1580
                 >> WEIGHT_SHIFT);
1581
      rgba[3] = (GLchan) (
1582
                 (w000*t000[3] + w010*t010[3] + w001*t001[3] + w011*t011[3] +
1583
                  w100*t100[3] + w110*t110[3] + w101*t101[3] + w111*t111[3] )
1584
                 >> WEIGHT_SHIFT);
1585
#endif
1586
 
1587
   }
1588
}
1589
 
1590
 
1591
 
1592
static void
1593
sample_3d_nearest_mipmap_nearest(GLcontext *ctx,
1594
                                 const struct gl_texture_object *tObj,
1595
                                 GLuint n, GLfloat texcoord[][4],
1596
                                 const GLfloat lambda[], GLchan rgba[][4] )
1597
{
1598
   GLuint i;
1599
   for (i = 0; i < n; i++) {
1600
      GLint level;
1601
      COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
1602
      sample_3d_nearest(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
1603
   }
1604
}
1605
 
1606
 
1607
static void
1608
sample_3d_linear_mipmap_nearest(GLcontext *ctx,
1609
                                const struct gl_texture_object *tObj,
1610
                                GLuint n, GLfloat texcoord[][4],
1611
                                const GLfloat lambda[], GLchan rgba[][4])
1612
{
1613
   GLuint i;
1614
   ASSERT(lambda != NULL);
1615
   for (i = 0; i < n; i++) {
1616
      GLint level;
1617
      COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
1618
      sample_3d_linear(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
1619
   }
1620
}
1621
 
1622
 
1623
static void
1624
sample_3d_nearest_mipmap_linear(GLcontext *ctx,
1625
                                const struct gl_texture_object *tObj,
1626
                                GLuint n, GLfloat texcoord[][4],
1627
                                const GLfloat lambda[], GLchan rgba[][4])
1628
{
1629
   GLuint i;
1630
   ASSERT(lambda != NULL);
1631
   for (i = 0; i < n; i++) {
1632
      GLint level;
1633
      COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
1634
      if (level >= tObj->_MaxLevel) {
1635
         sample_3d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel],
1636
                           texcoord[i], rgba[i]);
1637
      }
1638
      else {
1639
         GLchan t0[4], t1[4];  /* texels */
1640
         const GLfloat f = FRAC(lambda[i]);
1641
         sample_3d_nearest(ctx, tObj, tObj->Image[level  ], texcoord[i], t0);
1642
         sample_3d_nearest(ctx, tObj, tObj->Image[level+1], texcoord[i], t1);
1643
         rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
1644
         rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
1645
         rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
1646
         rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
1647
      }
1648
   }
1649
}
1650
 
1651
 
1652
static void
1653
sample_3d_linear_mipmap_linear(GLcontext *ctx,
1654
                               const struct gl_texture_object *tObj,
1655
                               GLuint n, GLfloat texcoord[][4],
1656
                               const GLfloat lambda[], GLchan rgba[][4])
1657
{
1658
   GLuint i;
1659
   ASSERT(lambda != NULL);
1660
   for (i = 0; i < n; i++) {
1661
      GLint level;
1662
      COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
1663
      if (level >= tObj->_MaxLevel) {
1664
         sample_3d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel],
1665
                          texcoord[i], rgba[i]);
1666
      }
1667
      else {
1668
         GLchan t0[4], t1[4];  /* texels */
1669
         const GLfloat f = FRAC(lambda[i]);
1670
         sample_3d_linear(ctx, tObj, tObj->Image[level  ], texcoord[i], t0);
1671
         sample_3d_linear(ctx, tObj, tObj->Image[level+1], texcoord[i], t1);
1672
         rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
1673
         rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
1674
         rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
1675
         rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
1676
      }
1677
   }
1678
}
1679
 
1680
 
1681
static void
1682
sample_nearest_3d(GLcontext *ctx, GLuint texUnit,
1683
                  const struct gl_texture_object *tObj, GLuint n,
1684
                  GLfloat texcoords[][4], const GLfloat lambda[],
1685
                  GLchan rgba[][4])
1686
{
1687
   GLuint i;
1688
   struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
1689
   (void) lambda;
1690
   for (i=0;i<n;i++) {
1691
      sample_3d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
1692
   }
1693
}
1694
 
1695
 
1696
 
1697
static void
1698
sample_linear_3d( GLcontext *ctx, GLuint texUnit,
1699
                  const struct gl_texture_object *tObj, GLuint n,
1700
                  GLfloat texcoords[][4],
1701
                  const GLfloat lambda[], GLchan rgba[][4] )
1702
{
1703
   GLuint i;
1704
   struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
1705
   (void) lambda;
1706
   for (i=0;i<n;i++) {
1707
      sample_3d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
1708
   }
1709
}
1710
 
1711
 
1712
/*
1713
 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
1714
 * return a texture sample.
1715
 */
1716
static void
1717
sample_lambda_3d( GLcontext *ctx, GLuint texUnit,
1718
                  const struct gl_texture_object *tObj, GLuint n,
1719
                  GLfloat texcoords[][4], const GLfloat lambda[],
1720
                  GLchan rgba[][4] )
1721
{
1722
   GLuint minStart, minEnd;  /* texels with minification */
1723
   GLuint magStart, magEnd;  /* texels with magnification */
1724
   GLuint i;
1725
 
1726
   ASSERT(lambda != NULL);
1727
   compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit],
1728
                          n, lambda, &minStart, &minEnd, &magStart, &magEnd);
1729
 
1730
   if (minStart < minEnd) {
1731
      /* do the minified texels */
1732
      GLuint m = minEnd - minStart;
1733
      switch (tObj->MinFilter) {
1734
      case GL_NEAREST:
1735
         for (i = minStart; i < minEnd; i++)
1736
            sample_3d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
1737
                              texcoords[i], rgba[i]);
1738
         break;
1739
      case GL_LINEAR:
1740
         for (i = minStart; i < minEnd; i++)
1741
            sample_3d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
1742
                             texcoords[i], rgba[i]);
1743
         break;
1744
      case GL_NEAREST_MIPMAP_NEAREST:
1745
         sample_3d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
1746
                                          lambda + minStart, rgba + minStart);
1747
         break;
1748
      case GL_LINEAR_MIPMAP_NEAREST:
1749
         sample_3d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
1750
                                         lambda + minStart, rgba + minStart);
1751
         break;
1752
      case GL_NEAREST_MIPMAP_LINEAR:
1753
         sample_3d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
1754
                                         lambda + minStart, rgba + minStart);
1755
         break;
1756
      case GL_LINEAR_MIPMAP_LINEAR:
1757
         sample_3d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
1758
                                        lambda + minStart, rgba + minStart);
1759
         break;
1760
      default:
1761
         _mesa_problem(ctx, "Bad min filter in sample_3d_texture");
1762
         return;
1763
      }
1764
   }
1765
 
1766
   if (magStart < magEnd) {
1767
      /* do the magnified texels */
1768
      switch (tObj->MagFilter) {
1769
      case GL_NEAREST:
1770
         for (i = magStart; i < magEnd; i++)
1771
            sample_3d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
1772
                              texcoords[i], rgba[i]);
1773
         break;
1774
      case GL_LINEAR:
1775
         for (i = magStart; i < magEnd; i++)
1776
            sample_3d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
1777
                             texcoords[i], rgba[i]);
1778
         break;
1779
      default:
1780
         _mesa_problem(ctx, "Bad mag filter in sample_3d_texture");
1781
         return;
1782
      }
1783
   }
1784
}
1785
 
1786
 
1787
/**********************************************************************/
1788
/*                Texture Cube Map Sampling Functions                 */
1789
/**********************************************************************/
1790
 
1791
/*
1792
 * Choose one of six sides of a texture cube map given the texture
1793
 * coord (rx,ry,rz).  Return pointer to corresponding array of texture
1794
 * images.
1795
 */
1796
static const struct gl_texture_image **
1797
choose_cube_face(const struct gl_texture_object *texObj,
1798
                 const GLfloat texcoord[4], GLfloat newCoord[4])
1799
{
1800
/*
1801
      major axis
1802
      direction     target                             sc     tc    ma
1803
      ----------    -------------------------------    ---    ---   ---
1804
       +rx          TEXTURE_CUBE_MAP_POSITIVE_X_EXT    -rz    -ry   rx
1805
       -rx          TEXTURE_CUBE_MAP_NEGATIVE_X_EXT    +rz    -ry   rx
1806
       +ry          TEXTURE_CUBE_MAP_POSITIVE_Y_EXT    +rx    +rz   ry
1807
       -ry          TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT    +rx    -rz   ry
1808
       +rz          TEXTURE_CUBE_MAP_POSITIVE_Z_EXT    +rx    -ry   rz
1809
       -rz          TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT    -rx    -ry   rz
1810
*/
1811
   const GLfloat rx = texcoord[0];
1812
   const GLfloat ry = texcoord[1];
1813
   const GLfloat rz = texcoord[2];
1814
   const struct gl_texture_image **imgArray;
1815
   const GLfloat arx = ABSF(rx),   ary = ABSF(ry),   arz = ABSF(rz);
1816
   GLfloat sc, tc, ma;
1817
 
1818
   if (arx > ary && arx > arz) {
1819
      if (rx >= 0.0F) {
1820
         imgArray = (const struct gl_texture_image **) texObj->Image;
1821
         sc = -rz;
1822
         tc = -ry;
1823
         ma = arx;
1824
      }
1825
      else {
1826
         imgArray = (const struct gl_texture_image **) texObj->NegX;
1827
         sc = rz;
1828
         tc = -ry;
1829
         ma = arx;
1830
      }
1831
   }
1832
   else if (ary > arx && ary > arz) {
1833
      if (ry >= 0.0F) {
1834
         imgArray = (const struct gl_texture_image **) texObj->PosY;
1835
         sc = rx;
1836
         tc = rz;
1837
         ma = ary;
1838
      }
1839
      else {
1840
         imgArray = (const struct gl_texture_image **) texObj->NegY;
1841
         sc = rx;
1842
         tc = -rz;
1843
         ma = ary;
1844
      }
1845
   }
1846
   else {
1847
      if (rz > 0.0F) {
1848
         imgArray = (const struct gl_texture_image **) texObj->PosZ;
1849
         sc = rx;
1850
         tc = -ry;
1851
         ma = arz;
1852
      }
1853
      else {
1854
         imgArray = (const struct gl_texture_image **) texObj->NegZ;
1855
         sc = -rx;
1856
         tc = -ry;
1857
         ma = arz;
1858
      }
1859
   }
1860
 
1861
   newCoord[0] = ( sc / ma + 1.0F ) * 0.5F;
1862
   newCoord[1] = ( tc / ma + 1.0F ) * 0.5F;
1863
   return imgArray;
1864
}
1865
 
1866
 
1867
static void
1868
sample_nearest_cube(GLcontext *ctx, GLuint texUnit,
1869
                    const struct gl_texture_object *tObj, GLuint n,
1870
                    GLfloat texcoords[][4], const GLfloat lambda[],
1871
                    GLchan rgba[][4])
1872
{
1873
   GLuint i;
1874
   (void) lambda;
1875
   for (i = 0; i < n; i++) {
1876
      const struct gl_texture_image **images;
1877
      GLfloat newCoord[4];
1878
      images = choose_cube_face(tObj, texcoords[i], newCoord);
1879
      sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel],
1880
                        newCoord, rgba[i]);
1881
   }
1882
}
1883
 
1884
 
1885
static void
1886
sample_linear_cube(GLcontext *ctx, GLuint texUnit,
1887
                   const struct gl_texture_object *tObj, GLuint n,
1888
                   GLfloat texcoords[][4],
1889
                   const GLfloat lambda[], GLchan rgba[][4])
1890
{
1891
   GLuint i;
1892
   (void) lambda;
1893
   for (i = 0; i < n; i++) {
1894
      const struct gl_texture_image **images;
1895
      GLfloat newCoord[4];
1896
      images = choose_cube_face(tObj, texcoords[i], newCoord);
1897
      sample_2d_linear(ctx, tObj, images[tObj->BaseLevel],
1898
                       newCoord, rgba[i]);
1899
   }
1900
}
1901
 
1902
 
1903
static void
1904
sample_cube_nearest_mipmap_nearest(GLcontext *ctx,
1905
                                   const struct gl_texture_object *tObj,
1906
                                   GLuint n, GLfloat texcoord[][4],
1907
                                   const GLfloat lambda[], GLchan rgba[][4])
1908
{
1909
   GLuint i;
1910
   ASSERT(lambda != NULL);
1911
   for (i = 0; i < n; i++) {
1912
      const struct gl_texture_image **images;
1913
      GLfloat newCoord[4];
1914
      GLint level;
1915
      COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
1916
      images = choose_cube_face(tObj, texcoord[i], newCoord);
1917
      sample_2d_nearest(ctx, tObj, images[level], newCoord, rgba[i]);
1918
   }
1919
}
1920
 
1921
 
1922
static void
1923
sample_cube_linear_mipmap_nearest(GLcontext *ctx,
1924
                                  const struct gl_texture_object *tObj,
1925
                                  GLuint n, GLfloat texcoord[][4],
1926
                                  const GLfloat lambda[], GLchan rgba[][4])
1927
{
1928
   GLuint i;
1929
   ASSERT(lambda != NULL);
1930
   for (i = 0; i < n; i++) {
1931
      const struct gl_texture_image **images;
1932
      GLfloat newCoord[4];
1933
      GLint level;
1934
      COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
1935
      images = choose_cube_face(tObj, texcoord[i], newCoord);
1936
      sample_2d_linear(ctx, tObj, images[level], newCoord, rgba[i]);
1937
   }
1938
}
1939
 
1940
 
1941
static void
1942
sample_cube_nearest_mipmap_linear(GLcontext *ctx,
1943
                                  const struct gl_texture_object *tObj,
1944
                                  GLuint n, GLfloat texcoord[][4],
1945
                                  const GLfloat lambda[], GLchan rgba[][4])
1946
{
1947
   GLuint i;
1948
   ASSERT(lambda != NULL);
1949
   for (i = 0; i < n; i++) {
1950
      const struct gl_texture_image **images;
1951
      GLfloat newCoord[4];
1952
      GLint level;
1953
      COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
1954
      images = choose_cube_face(tObj, texcoord[i], newCoord);
1955
      if (level >= tObj->_MaxLevel) {
1956
         sample_2d_nearest(ctx, tObj, images[tObj->_MaxLevel],
1957
                           newCoord, rgba[i]);
1958
      }
1959
      else {
1960
         GLchan t0[4], t1[4];  /* texels */
1961
         const GLfloat f = FRAC(lambda[i]);
1962
         sample_2d_nearest(ctx, tObj, images[level  ], newCoord, t0);
1963
         sample_2d_nearest(ctx, tObj, images[level+1], newCoord, t1);
1964
         rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
1965
         rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
1966
         rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
1967
         rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
1968
      }
1969
   }
1970
}
1971
 
1972
 
1973
static void
1974
sample_cube_linear_mipmap_linear(GLcontext *ctx,
1975
                                 const struct gl_texture_object *tObj,
1976
                                 GLuint n, GLfloat texcoord[][4],
1977
                                 const GLfloat lambda[], GLchan rgba[][4])
1978
{
1979
   GLuint i;
1980
   ASSERT(lambda != NULL);
1981
   for (i = 0; i < n; i++) {
1982
      const struct gl_texture_image **images;
1983
      GLfloat newCoord[4];
1984
      GLint level;
1985
      COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
1986
      images = choose_cube_face(tObj, texcoord[i], newCoord);
1987
      if (level >= tObj->_MaxLevel) {
1988
         sample_2d_linear(ctx, tObj, images[tObj->_MaxLevel],
1989
                          newCoord, rgba[i]);
1990
      }
1991
      else {
1992
         GLchan t0[4], t1[4];
1993
         const GLfloat f = FRAC(lambda[i]);
1994
         sample_2d_linear(ctx, tObj, images[level  ], newCoord, t0);
1995
         sample_2d_linear(ctx, tObj, images[level+1], newCoord, t1);
1996
         rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
1997
         rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
1998
         rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
1999
         rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
2000
      }
2001
   }
2002
}
2003
 
2004
 
2005
static void
2006
sample_lambda_cube( GLcontext *ctx, GLuint texUnit,
2007
                    const struct gl_texture_object *tObj, GLuint n,
2008
                    GLfloat texcoords[][4], const GLfloat lambda[],
2009
                    GLchan rgba[][4])
2010
{
2011
   GLuint minStart, minEnd;  /* texels with minification */
2012
   GLuint magStart, magEnd;  /* texels with magnification */
2013
 
2014
   ASSERT(lambda != NULL);
2015
   compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit],
2016
                          n, lambda, &minStart, &minEnd, &magStart, &magEnd);
2017
 
2018
   if (minStart < minEnd) {
2019
      /* do the minified texels */
2020
      const GLuint m = minEnd - minStart;
2021
      switch (tObj->MinFilter) {
2022
      case GL_NEAREST:
2023
         sample_nearest_cube(ctx, texUnit, tObj, m, texcoords + minStart,
2024
                             lambda + minStart, rgba + minStart);
2025
         break;
2026
      case GL_LINEAR:
2027
         sample_linear_cube(ctx, texUnit, tObj, m, texcoords + minStart,
2028
                            lambda + minStart, rgba + minStart);
2029
         break;
2030
      case GL_NEAREST_MIPMAP_NEAREST:
2031
         sample_cube_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
2032
                                           lambda + minStart, rgba + minStart);
2033
         break;
2034
      case GL_LINEAR_MIPMAP_NEAREST:
2035
         sample_cube_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
2036
                                           lambda + minStart, rgba + minStart);
2037
         break;
2038
      case GL_NEAREST_MIPMAP_LINEAR:
2039
         sample_cube_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
2040
                                           lambda + minStart, rgba + minStart);
2041
         break;
2042
      case GL_LINEAR_MIPMAP_LINEAR:
2043
         sample_cube_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
2044
                                          lambda + minStart, rgba + minStart);
2045
         break;
2046
      default:
2047
         _mesa_problem(ctx, "Bad min filter in sample_lambda_cube");
2048
      }
2049
   }
2050
 
2051
   if (magStart < magEnd) {
2052
      /* do the magnified texels */
2053
      const GLuint m = magEnd - magStart;
2054
      switch (tObj->MagFilter) {
2055
      case GL_NEAREST:
2056
         sample_nearest_cube(ctx, texUnit, tObj, m, texcoords + magStart,
2057
                             lambda + magStart, rgba + magStart);
2058
         break;
2059
      case GL_LINEAR:
2060
         sample_linear_cube(ctx, texUnit, tObj, m, texcoords + magStart,
2061
                            lambda + magStart, rgba + magStart);
2062
         break;
2063
      default:
2064
         _mesa_problem(ctx, "Bad mag filter in sample_lambda_cube");
2065
      }
2066
   }
2067
}
2068
 
2069
 
2070
/**********************************************************************/
2071
/*               Texture Rectangle Sampling Functions                 */
2072
/**********************************************************************/
2073
 
2074
static void
2075
sample_nearest_rect(GLcontext *ctx, GLuint texUnit,
2076
                    const struct gl_texture_object *tObj, GLuint n,
2077
                    GLfloat texcoords[][4], const GLfloat lambda[],
2078
                    GLchan rgba[][4])
2079
{
2080
   const struct gl_texture_image *img = tObj->Image[0];
2081
   const GLfloat width = (GLfloat) img->Width;
2082
   const GLfloat height = (GLfloat) img->Height;
2083
   const GLint width_minus_1 = img->Width - 1;
2084
   const GLint height_minus_1 = img->Height - 1;
2085
   GLuint i;
2086
 
2087
   (void) texUnit;
2088
   (void) lambda;
2089
 
2090
   ASSERT(tObj->WrapS == GL_CLAMP ||
2091
          tObj->WrapS == GL_CLAMP_TO_EDGE ||
2092
          tObj->WrapS == GL_CLAMP_TO_BORDER_ARB);
2093
   ASSERT(tObj->WrapT == GL_CLAMP ||
2094
          tObj->WrapT == GL_CLAMP_TO_EDGE ||
2095
          tObj->WrapT == GL_CLAMP_TO_BORDER_ARB);
2096
   ASSERT(img->Format != GL_COLOR_INDEX);
2097
 
2098
   /* XXX move Wrap mode tests outside of loops for common cases */
2099
   for (i = 0; i < n; i++) {
2100
      GLint row, col;
2101
      /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2102
      if (tObj->WrapS == GL_CLAMP) {
2103
         col = IFLOOR( CLAMP(texcoords[i][0], 0.0F, width) );
2104
      }
2105
      else if (tObj->WrapS == GL_CLAMP_TO_EDGE) {
2106
         col = IFLOOR( CLAMP(texcoords[i][0], 0.5F, width - 0.5F) );
2107
      }
2108
      else {
2109
         col = IFLOOR( CLAMP(texcoords[i][0], -0.5F, width + 0.5F) );
2110
      }
2111
      if (tObj->WrapT == GL_CLAMP) {
2112
         row = IFLOOR( CLAMP(texcoords[i][1], 0.0F, height) );
2113
      }
2114
      else if (tObj->WrapT == GL_CLAMP_TO_EDGE) {
2115
         row = IFLOOR( CLAMP(texcoords[i][1], 0.5F, height - 0.5F) );
2116
      }
2117
      else {
2118
         row = IFLOOR( CLAMP(texcoords[i][1], -0.5F, height + 0.5F) );
2119
      }
2120
 
2121
      col = CLAMP(col, 0, width_minus_1);
2122
      row = CLAMP(row, 0, height_minus_1);
2123
 
2124
      (*img->FetchTexel)(img, col, row, 0, (GLvoid *) rgba[i]);
2125
   }
2126
}
2127
 
2128
 
2129
static void
2130
sample_linear_rect(GLcontext *ctx, GLuint texUnit,
2131
                   const struct gl_texture_object *tObj, GLuint n,
2132
                   GLfloat texcoords[][4],
2133
                   const GLfloat lambda[], GLchan rgba[][4])
2134
{
2135
   const struct gl_texture_image *img = tObj->Image[0];
2136
   const GLfloat width = (GLfloat) img->Width;
2137
   const GLfloat height = (GLfloat) img->Height;
2138
   const GLint width_minus_1 = img->Width - 1;
2139
   const GLint height_minus_1 = img->Height - 1;
2140
   GLuint i;
2141
 
2142
   (void) texUnit;
2143
   (void) lambda;
2144
 
2145
   ASSERT(tObj->WrapS == GL_CLAMP ||
2146
          tObj->WrapS == GL_CLAMP_TO_EDGE ||
2147
          tObj->WrapS == GL_CLAMP_TO_BORDER_ARB);
2148
   ASSERT(tObj->WrapT == GL_CLAMP ||
2149
          tObj->WrapT == GL_CLAMP_TO_EDGE ||
2150
          tObj->WrapT == GL_CLAMP_TO_BORDER_ARB);
2151
   ASSERT(img->Format != GL_COLOR_INDEX);
2152
 
2153
   /* XXX lots of opportunity for optimization in this loop */
2154
   for (i = 0; i < n; i++) {
2155
      GLfloat frow, fcol;
2156
      GLint row0, col0, row1, col1;
2157
      GLchan t00[4], t01[4], t10[4], t11[4];
2158
      GLfloat a, b, w00, w01, w10, w11;
2159
 
2160
      /* NOTE: we DO NOT use [0, 1] texture coordinates! */
2161
      if (tObj->WrapS == GL_CLAMP) {
2162
         fcol = CLAMP(texcoords[i][0], 0.0F, width);
2163
      }
2164
      else if (tObj->WrapS == GL_CLAMP_TO_EDGE) {
2165
         fcol = CLAMP(texcoords[i][0], 0.5F, width - 0.5F);
2166
      }
2167
      else {
2168
         fcol = CLAMP(texcoords[i][0], -0.5F, width + 0.5F);
2169
      }
2170
      if (tObj->WrapT == GL_CLAMP) {
2171
         frow = CLAMP(texcoords[i][1], 0.0F, height);
2172
      }
2173
      else if (tObj->WrapT == GL_CLAMP_TO_EDGE) {
2174
         frow = CLAMP(texcoords[i][1], 0.5F, height - 0.5F);
2175
      }
2176
      else {
2177
         frow = CLAMP(texcoords[i][1], -0.5F, height + 0.5F);
2178
      }
2179
 
2180
      /* compute integer rows/columns */
2181
      col0 = IFLOOR(fcol);
2182
      col1 = col0 + 1;
2183
      col0 = CLAMP(col0, 0, width_minus_1);
2184
      col1 = CLAMP(col1, 0, width_minus_1);
2185
      row0 = IFLOOR(frow);
2186
      row1 = row0 + 1;
2187
      row0 = CLAMP(row0, 0, height_minus_1);
2188
      row1 = CLAMP(row1, 0, height_minus_1);
2189
 
2190
      /* get four texel samples */
2191
      (*img->FetchTexel)(img, col0, row0, 0, (GLvoid *) t00);
2192
      (*img->FetchTexel)(img, col1, row0, 0, (GLvoid *) t10);
2193
      (*img->FetchTexel)(img, col0, row1, 0, (GLvoid *) t01);
2194
      (*img->FetchTexel)(img, col1, row1, 0, (GLvoid *) t11);
2195
 
2196
      /* compute sample weights */
2197
      a = FRAC(fcol);
2198
      b = FRAC(frow);
2199
      w00 = (1.0F-a) * (1.0F-b);
2200
      w10 =       a  * (1.0F-b);
2201
      w01 = (1.0F-a) *       b ;
2202
      w11 =       a  *       b ;
2203
 
2204
      /* compute weighted average of samples */
2205
      rgba[i][0] =
2206
          (GLchan) (w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0]);
2207
      rgba[i][1] =
2208
          (GLchan) (w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1]);
2209
      rgba[i][2] =
2210
          (GLchan) (w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2]);
2211
      rgba[i][3] =
2212
          (GLchan) (w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3]);
2213
   }
2214
}
2215
 
2216
 
2217
static void
2218
sample_lambda_rect( GLcontext *ctx, GLuint texUnit,
2219
                    const struct gl_texture_object *tObj, GLuint n,
2220
                    GLfloat texcoords[][4], const GLfloat lambda[],
2221
                    GLchan rgba[][4])
2222
{
2223
   GLuint minStart, minEnd, magStart, magEnd;
2224
 
2225
   /* We only need lambda to decide between minification and magnification.
2226
    * There is no mipmapping with rectangular textures.
2227
    */
2228
   compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit],
2229
                          n, lambda, &minStart, &minEnd, &magStart, &magEnd);
2230
 
2231
   if (minStart < minEnd) {
2232
      if (tObj->MinFilter == GL_NEAREST) {
2233
         sample_nearest_rect( ctx, texUnit, tObj, minEnd - minStart,
2234
                              texcoords + minStart, NULL, rgba + minStart);
2235
      }
2236
      else {
2237
         sample_linear_rect( ctx, texUnit, tObj, minEnd - minStart,
2238
                             texcoords + minStart, NULL, rgba + minStart);
2239
      }
2240
   }
2241
   if (magStart < magEnd) {
2242
      if (tObj->MagFilter == GL_NEAREST) {
2243
         sample_nearest_rect( ctx, texUnit, tObj, magEnd - magStart,
2244
                              texcoords + magStart, NULL, rgba + magStart);
2245
      }
2246
      else {
2247
         sample_linear_rect( ctx, texUnit, tObj, magEnd - magStart,
2248
                             texcoords + magStart, NULL, rgba + magStart);
2249
      }
2250
   }
2251
}
2252
 
2253
 
2254
 
2255
/*
2256
 * Sample a shadow/depth texture.
2257
 */
2258
static void
2259
sample_depth_texture( GLcontext *ctx, GLuint unit,
2260
                      const struct gl_texture_object *tObj, GLuint n,
2261
                      GLfloat texcoords[][4], const GLfloat lambda[],
2262
                      GLchan texel[][4] )
2263
{
2264
   const GLint baseLevel = tObj->BaseLevel;
2265
   const struct gl_texture_image *texImage = tObj->Image[baseLevel];
2266
   const GLuint width = texImage->Width;
2267
   const GLuint height = texImage->Height;
2268
   GLchan ambient;
2269
   GLenum function;
2270
   GLchan result;
2271
 
2272
   (void) unit;
2273
 
2274
   ASSERT(tObj->Image[tObj->BaseLevel]->Format == GL_DEPTH_COMPONENT);
2275
   ASSERT(tObj->Target == GL_TEXTURE_1D ||
2276
          tObj->Target == GL_TEXTURE_2D ||
2277
          tObj->Target == GL_TEXTURE_RECTANGLE_NV);
2278
 
2279
   UNCLAMPED_FLOAT_TO_CHAN(ambient, tObj->ShadowAmbient);
2280
 
2281
   /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
2282
 
2283
   /* XXX this could be precomputed and saved in the texture object */
2284
   if (tObj->CompareFlag) {
2285
      /* GL_SGIX_shadow */
2286
      if (tObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) {
2287
         function = GL_LEQUAL;
2288
      }
2289
      else {
2290
         ASSERT(tObj->CompareOperator == GL_TEXTURE_GEQUAL_R_SGIX);
2291
         function = GL_GEQUAL;
2292
      }
2293
   }
2294
   else if (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
2295
      /* GL_ARB_shadow */
2296
      function = tObj->CompareFunc;
2297
   }
2298
   else {
2299
      function = GL_NONE;  /* pass depth through as grayscale */
2300
   }
2301
 
2302
   if (tObj->MagFilter == GL_NEAREST) {
2303
      GLuint i;
2304
      for (i = 0; i < n; i++) {
2305
         GLfloat depthSample;
2306
         GLint col, row;
2307
         /* XXX fix for texture rectangle! */
2308
         COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoords[i][0], width, col);
2309
         COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, texcoords[i][1], height, row);
2310
         depthSample = *((const GLfloat *) texImage->Data + row * width + col);
2311
 
2312
         switch (function) {
2313
         case GL_LEQUAL:
2314
            result = (texcoords[i][2] <= depthSample) ? CHAN_MAX : ambient;
2315
            break;
2316
         case GL_GEQUAL:
2317
            result = (texcoords[i][2] >= depthSample) ? CHAN_MAX : ambient;
2318
            break;
2319
         case GL_LESS:
2320
            result = (texcoords[i][2] < depthSample) ? CHAN_MAX : ambient;
2321
            break;
2322
         case GL_GREATER:
2323
            result = (texcoords[i][2] > depthSample) ? CHAN_MAX : ambient;
2324
            break;
2325
         case GL_EQUAL:
2326
            result = (texcoords[i][2] == depthSample) ? CHAN_MAX : ambient;
2327
            break;
2328
         case GL_NOTEQUAL:
2329
            result = (texcoords[i][2] != depthSample) ? CHAN_MAX : ambient;
2330
            break;
2331
         case GL_ALWAYS:
2332
            result = CHAN_MAX;
2333
            break;
2334
         case GL_NEVER:
2335
            result = ambient;
2336
            break;
2337
         case GL_NONE:
2338
            CLAMPED_FLOAT_TO_CHAN(result, depthSample);
2339
            break;
2340
         default:
2341
            _mesa_problem(ctx, "Bad compare func in sample_depth_texture");
2342
            return;
2343
         }
2344
 
2345
         switch (tObj->DepthMode) {
2346
         case GL_LUMINANCE:
2347
            texel[i][RCOMP] = result;
2348
            texel[i][GCOMP] = result;
2349
            texel[i][BCOMP] = result;
2350
            texel[i][ACOMP] = CHAN_MAX;
2351
            break;
2352
         case GL_INTENSITY:
2353
            texel[i][RCOMP] = result;
2354
            texel[i][GCOMP] = result;
2355
            texel[i][BCOMP] = result;
2356
            texel[i][ACOMP] = result;
2357
            break;
2358
         case GL_ALPHA:
2359
            texel[i][RCOMP] = 0;
2360
            texel[i][GCOMP] = 0;
2361
            texel[i][BCOMP] = 0;
2362
            texel[i][ACOMP] = result;
2363
            break;
2364
         default:
2365
            _mesa_problem(ctx, "Bad depth texture mode");
2366
         }
2367
      }
2368
   }
2369
   else {
2370
      GLuint i;
2371
      ASSERT(tObj->MagFilter == GL_LINEAR);
2372
      for (i = 0; i < n; i++) {
2373
         GLfloat depth00, depth01, depth10, depth11;
2374
         GLint i0, i1, j0, j1;
2375
         GLfloat u, v;
2376
         GLuint useBorderTexel;
2377
 
2378
         /* XXX fix for texture rectangle! */
2379
         COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoords[i][0], u, width, i0, i1);
2380
         COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, texcoords[i][1], v, height,j0, j1);
2381
 
2382
         useBorderTexel = 0;
2383
         if (texImage->Border) {
2384
            i0 += texImage->Border;
2385
            i1 += texImage->Border;
2386
            j0 += texImage->Border;
2387
            j1 += texImage->Border;
2388
         }
2389
         else {
2390
            if (i0 < 0 || i0 >= (GLint) width)   useBorderTexel |= I0BIT;
2391
            if (i1 < 0 || i1 >= (GLint) width)   useBorderTexel |= I1BIT;
2392
            if (j0 < 0 || j0 >= (GLint) height)  useBorderTexel |= J0BIT;
2393
            if (j1 < 0 || j1 >= (GLint) height)  useBorderTexel |= J1BIT;
2394
         }
2395
 
2396
         /* get four depth samples from the texture */
2397
         if (useBorderTexel & (I0BIT | J0BIT)) {
2398
            depth00 = 1.0;
2399
         }
2400
         else {
2401
            depth00 = *((const GLfloat *) texImage->Data + j0 * width + i0);
2402
         }
2403
         if (useBorderTexel & (I1BIT | J0BIT)) {
2404
            depth10 = 1.0;
2405
         }
2406
         else {
2407
            depth10 = *((const GLfloat *) texImage->Data + j0 * width + i1);
2408
         }
2409
         if (useBorderTexel & (I0BIT | J1BIT)) {
2410
            depth01 = 1.0;
2411
         }
2412
         else {
2413
            depth01 = *((const GLfloat *) texImage->Data + j1 * width + i0);
2414
         }
2415
         if (useBorderTexel & (I1BIT | J1BIT)) {
2416
            depth11 = 1.0;
2417
         }
2418
         else {
2419
            depth11 = *((const GLfloat *) texImage->Data + j1 * width + i1);
2420
         }
2421
 
2422
         if (0) {
2423
            /* compute a single weighted depth sample and do one comparison */
2424
            const GLfloat a = FRAC(u + 1.0F);
2425
            const GLfloat b = FRAC(v + 1.0F);
2426
            const GLfloat w00 = (1.0F - a) * (1.0F - b);
2427
            const GLfloat w10 = (       a) * (1.0F - b);
2428
            const GLfloat w01 = (1.0F - a) * (       b);
2429
            const GLfloat w11 = (       a) * (       b);
2430
            const GLfloat depthSample = w00 * depth00 + w10 * depth10
2431
                                      + w01 * depth01 + w11 * depth11;
2432
            if ((depthSample <= texcoords[i][2] && function == GL_LEQUAL) ||
2433
                (depthSample >= texcoords[i][2] && function == GL_GEQUAL)) {
2434
               result  = ambient;
2435
            }
2436
            else {
2437
               result = CHAN_MAX;
2438
            }
2439
         }
2440
         else {
2441
            /* Do four depth/R comparisons and compute a weighted result.
2442
             * If this touches on somebody's I.P., I'll remove this code
2443
             * upon request.
2444
             */
2445
            const GLfloat d = (CHAN_MAXF - (GLfloat) ambient) * 0.25F;
2446
            GLfloat luminance = CHAN_MAXF;
2447
 
2448
            switch (function) {
2449
            case GL_LEQUAL:
2450
               if (depth00 <= texcoords[i][2])  luminance -= d;
2451
               if (depth01 <= texcoords[i][2])  luminance -= d;
2452
               if (depth10 <= texcoords[i][2])  luminance -= d;
2453
               if (depth11 <= texcoords[i][2])  luminance -= d;
2454
               result = (GLchan) luminance;
2455
               break;
2456
            case GL_GEQUAL:
2457
               if (depth00 >= texcoords[i][2])  luminance -= d;
2458
               if (depth01 >= texcoords[i][2])  luminance -= d;
2459
               if (depth10 >= texcoords[i][2])  luminance -= d;
2460
               if (depth11 >= texcoords[i][2])  luminance -= d;
2461
               result = (GLchan) luminance;
2462
               break;
2463
            case GL_LESS:
2464
               if (depth00 < texcoords[i][2])  luminance -= d;
2465
               if (depth01 < texcoords[i][2])  luminance -= d;
2466
               if (depth10 < texcoords[i][2])  luminance -= d;
2467
               if (depth11 < texcoords[i][2])  luminance -= d;
2468
               result = (GLchan) luminance;
2469
               break;
2470
            case GL_GREATER:
2471
               if (depth00 > texcoords[i][2])  luminance -= d;
2472
               if (depth01 > texcoords[i][2])  luminance -= d;
2473
               if (depth10 > texcoords[i][2])  luminance -= d;
2474
               if (depth11 > texcoords[i][2])  luminance -= d;
2475
               result = (GLchan) luminance;
2476
               break;
2477
            case GL_EQUAL:
2478
               if (depth00 == texcoords[i][2])  luminance -= d;
2479
               if (depth01 == texcoords[i][2])  luminance -= d;
2480
               if (depth10 == texcoords[i][2])  luminance -= d;
2481
               if (depth11 == texcoords[i][2])  luminance -= d;
2482
               result = (GLchan) luminance;
2483
               break;
2484
            case GL_NOTEQUAL:
2485
               if (depth00 != texcoords[i][2])  luminance -= d;
2486
               if (depth01 != texcoords[i][2])  luminance -= d;
2487
               if (depth10 != texcoords[i][2])  luminance -= d;
2488
               if (depth11 != texcoords[i][2])  luminance -= d;
2489
               result = (GLchan) luminance;
2490
               break;
2491
            case GL_ALWAYS:
2492
               result = 0;
2493
               break;
2494
            case GL_NEVER:
2495
               result = CHAN_MAX;
2496
               break;
2497
            case GL_NONE:
2498
               /* ordinary bilinear filtering */
2499
               {
2500
                  const GLfloat a = FRAC(u + 1.0F);
2501
                  const GLfloat b = FRAC(v + 1.0F);
2502
                  const GLfloat w00 = (1.0F - a) * (1.0F - b);
2503
                  const GLfloat w10 = (       a) * (1.0F - b);
2504
                  const GLfloat w01 = (1.0F - a) * (       b);
2505
                  const GLfloat w11 = (       a) * (       b);
2506
                  const GLfloat depthSample = w00 * depth00 + w10 * depth10
2507
                                            + w01 * depth01 + w11 * depth11;
2508
                  CLAMPED_FLOAT_TO_CHAN(result, depthSample);
2509
               }
2510
               break;
2511
            default:
2512
               _mesa_problem(ctx, "Bad compare func in sample_depth_texture");
2513
               return;
2514
            }
2515
         }
2516
 
2517
         switch (tObj->DepthMode) {
2518
         case GL_LUMINANCE:
2519
            texel[i][RCOMP] = result;
2520
            texel[i][GCOMP] = result;
2521
            texel[i][BCOMP] = result;
2522
            texel[i][ACOMP] = CHAN_MAX;
2523
            break;
2524
         case GL_INTENSITY:
2525
            texel[i][RCOMP] = result;
2526
            texel[i][GCOMP] = result;
2527
            texel[i][BCOMP] = result;
2528
            texel[i][ACOMP] = result;
2529
            break;
2530
         case GL_ALPHA:
2531
            texel[i][RCOMP] = 0;
2532
            texel[i][GCOMP] = 0;
2533
            texel[i][BCOMP] = 0;
2534
            texel[i][ACOMP] = result;
2535
            break;
2536
         default:
2537
            _mesa_problem(ctx, "Bad depth texture mode");
2538
         }
2539
      }  /* for */
2540
   }  /* if filter */
2541
}
2542
 
2543
 
2544
#if 0
2545
/*
2546
 * Experimental depth texture sampling function.
2547
 */
2548
static void
2549
sample_depth_texture2(const GLcontext *ctx,
2550
                     const struct gl_texture_unit *texUnit,
2551
                     GLuint n, GLfloat texcoords[][4],
2552
                     GLchan texel[][4])
2553
{
2554
   const struct gl_texture_object *texObj = texUnit->_Current;
2555
   const GLint baseLevel = texObj->BaseLevel;
2556
   const struct gl_texture_image *texImage = texObj->Image[baseLevel];
2557
   const GLuint width = texImage->Width;
2558
   const GLuint height = texImage->Height;
2559
   GLchan ambient;
2560
   GLboolean lequal, gequal;
2561
 
2562
   if (texObj->Target != GL_TEXTURE_2D) {
2563
      _mesa_problem(ctx, "only 2-D depth textures supported at this time");
2564
      return;
2565
   }
2566
 
2567
   if (texObj->MinFilter != texObj->MagFilter) {
2568
      _mesa_problem(ctx, "mipmapped depth textures not supported at this time");
2569
      return;
2570
   }
2571
 
2572
   /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
2573
    * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
2574
    * isn't a depth texture.
2575
    */
2576
   if (texImage->Format != GL_DEPTH_COMPONENT) {
2577
      _mesa_problem(ctx,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
2578
      return;
2579
   }
2580
 
2581
   UNCLAMPED_FLOAT_TO_CHAN(ambient, tObj->ShadowAmbient);
2582
 
2583
   if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) {
2584
      lequal = GL_TRUE;
2585
      gequal = GL_FALSE;
2586
   }
2587
   else {
2588
      lequal = GL_FALSE;
2589
      gequal = GL_TRUE;
2590
   }
2591
 
2592
   {
2593
      GLuint i;
2594
      for (i = 0; i < n; i++) {
2595
         const GLint K = 3;
2596
         GLint col, row, ii, jj, imin, imax, jmin, jmax, samples, count;
2597
         GLfloat w;
2598
         GLchan lum;
2599
         COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapS, texcoords[i][0],
2600
                                        width, col);
2601
         COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, texcoords[i][1],
2602
                                        height, row);
2603
 
2604
         imin = col - K;
2605
         imax = col + K;
2606
         jmin = row - K;
2607
         jmax = row + K;
2608
 
2609
         if (imin < 0)  imin = 0;
2610
         if (imax >= width)  imax = width - 1;
2611
         if (jmin < 0)  jmin = 0;
2612
         if (jmax >= height) jmax = height - 1;
2613
 
2614
         samples = (imax - imin + 1) * (jmax - jmin + 1);
2615
         count = 0;
2616
         for (jj = jmin; jj <= jmax; jj++) {
2617
            for (ii = imin; ii <= imax; ii++) {
2618
               GLfloat depthSample = *((const GLfloat *) texImage->Data
2619
                                       + jj * width + ii);
2620
               if ((depthSample <= r[i] && lequal) ||
2621
                   (depthSample >= r[i] && gequal)) {
2622
                  count++;
2623
               }
2624
            }
2625
         }
2626
 
2627
         w = (GLfloat) count / (GLfloat) samples;
2628
         w = CHAN_MAXF - w * (CHAN_MAXF - (GLfloat) ambient);
2629
         lum = (GLint) w;
2630
 
2631
         texel[i][RCOMP] = lum;
2632
         texel[i][GCOMP] = lum;
2633
         texel[i][BCOMP] = lum;
2634
         texel[i][ACOMP] = CHAN_MAX;
2635
      }
2636
   }
2637
}
2638
#endif
2639
 
2640
 
2641
/**
2642
 * We use this function when a texture object is in an "incomplete" state.
2643
 */
2644
static void
2645
null_sample_func( GLcontext *ctx, GLuint texUnit,
2646
                  const struct gl_texture_object *tObj, GLuint n,
2647
                  GLfloat texcoords[][4], const GLfloat lambda[],
2648
                  GLchan rgba[][4])
2649
{
2650
}
2651
 
2652
 
2653
 
2654
/**
2655
 * Setup the texture sampling function for this texture object.
2656
 */
2657
void
2658
_swrast_choose_texture_sample_func( GLcontext *ctx, GLuint texUnit,
2659
                                    const struct gl_texture_object *t )
2660
{
2661
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
2662
 
2663
   if (!t->Complete) {
2664
      swrast->TextureSample[texUnit] = null_sample_func;
2665
   }
2666
   else {
2667
      const GLboolean needLambda = (GLboolean) (t->MinFilter != t->MagFilter);
2668
      const GLenum format = t->Image[t->BaseLevel]->Format;
2669
 
2670
      if (needLambda) {
2671
         /* Compute min/mag filter threshold */
2672
         if (t->MagFilter == GL_LINEAR
2673
             && (t->MinFilter == GL_NEAREST_MIPMAP_NEAREST ||
2674
                 t->MinFilter == GL_NEAREST_MIPMAP_LINEAR)) {
2675
            swrast->_MinMagThresh[texUnit] = 0.5F;
2676
         }
2677
         else {
2678
            swrast->_MinMagThresh[texUnit] = 0.0F;
2679
         }
2680
      }
2681
 
2682
      switch (t->Target) {
2683
         case GL_TEXTURE_1D:
2684
            if (format == GL_DEPTH_COMPONENT) {
2685
               swrast->TextureSample[texUnit] = sample_depth_texture;
2686
            }
2687
            else if (needLambda) {
2688
               swrast->TextureSample[texUnit] = sample_lambda_1d;
2689
            }
2690
            else if (t->MinFilter == GL_LINEAR) {
2691
               swrast->TextureSample[texUnit] = sample_linear_1d;
2692
            }
2693
            else {
2694
               ASSERT(t->MinFilter == GL_NEAREST);
2695
               swrast->TextureSample[texUnit] = sample_nearest_1d;
2696
            }
2697
            break;
2698
         case GL_TEXTURE_2D:
2699
            if (format == GL_DEPTH_COMPONENT) {
2700
               swrast->TextureSample[texUnit] = sample_depth_texture;
2701
            }
2702
            else if (needLambda) {
2703
               swrast->TextureSample[texUnit] = sample_lambda_2d;
2704
            }
2705
            else if (t->MinFilter == GL_LINEAR) {
2706
               swrast->TextureSample[texUnit] = sample_linear_2d;
2707
            }
2708
            else {
2709
               GLint baseLevel = t->BaseLevel;
2710
               ASSERT(t->MinFilter == GL_NEAREST);
2711
               if (t->WrapS == GL_REPEAT &&
2712
                   t->WrapT == GL_REPEAT &&
2713
                   t->Image[baseLevel]->Border == 0 &&
2714
                   t->Image[baseLevel]->TexFormat->MesaFormat == MESA_FORMAT_RGB) {
2715
                  swrast->TextureSample[texUnit] = opt_sample_rgb_2d;
2716
               }
2717
               else if (t->WrapS == GL_REPEAT &&
2718
                        t->WrapT == GL_REPEAT &&
2719
                        t->Image[baseLevel]->Border == 0 &&
2720
                        t->Image[baseLevel]->TexFormat->MesaFormat == MESA_FORMAT_RGBA) {
2721
                  swrast->TextureSample[texUnit] = opt_sample_rgba_2d;
2722
               }
2723
               else
2724
                  swrast->TextureSample[texUnit] = sample_nearest_2d;
2725
            }
2726
            break;
2727
         case GL_TEXTURE_3D:
2728
            if (needLambda) {
2729
               swrast->TextureSample[texUnit] = sample_lambda_3d;
2730
            }
2731
            else if (t->MinFilter == GL_LINEAR) {
2732
               swrast->TextureSample[texUnit] = sample_linear_3d;
2733
            }
2734
            else {
2735
               ASSERT(t->MinFilter == GL_NEAREST);
2736
               swrast->TextureSample[texUnit] = sample_nearest_3d;
2737
            }
2738
            break;
2739
         case GL_TEXTURE_CUBE_MAP_ARB:
2740
            if (needLambda) {
2741
               swrast->TextureSample[texUnit] = sample_lambda_cube;
2742
            }
2743
            else if (t->MinFilter == GL_LINEAR) {
2744
               swrast->TextureSample[texUnit] = sample_linear_cube;
2745
            }
2746
            else {
2747
               ASSERT(t->MinFilter == GL_NEAREST);
2748
               swrast->TextureSample[texUnit] = sample_nearest_cube;
2749
            }
2750
            break;
2751
         case GL_TEXTURE_RECTANGLE_NV:
2752
            if (needLambda) {
2753
               swrast->TextureSample[texUnit] = sample_lambda_rect;
2754
            }
2755
            else if (t->MinFilter == GL_LINEAR) {
2756
               swrast->TextureSample[texUnit] = sample_linear_rect;
2757
            }
2758
            else {
2759
               ASSERT(t->MinFilter == GL_NEAREST);
2760
               swrast->TextureSample[texUnit] = sample_nearest_rect;
2761
            }
2762
            break;
2763
         default:
2764
            _mesa_problem(ctx, "invalid target in _swrast_choose_texture_sample_func");
2765
      }
2766
   }
2767
}
2768
 
2769
 
2770
#define PROD(A,B)   ( (GLuint)(A) * ((GLuint)(B)+1) )
2771
#define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
2772
 
2773
 
2774
/**
2775
 * Do texture application for GL_ARB/EXT_texture_env_combine.
2776
 * Input:
2777
 *     ctx - rendering context
2778
 *     textureUnit - the texture unit to apply
2779
 *     n - number of fragments to process (span width)
2780
 *     primary_rgba - incoming fragment color array
2781
 *     texelBuffer - pointer to texel colors for all texture units
2782
 * Input/Output:
2783
 *     rgba - incoming colors, which get modified here
2784
 */
2785
static INLINE void
2786
texture_combine( const GLcontext *ctx, GLuint unit, GLuint n,
2787
                 CONST GLchan (*primary_rgba)[4],
2788
                 CONST GLchan *texelBuffer,
2789
                 GLchan (*rgba)[4] )
2790
{
2791
   const struct gl_texture_unit *textureUnit = &(ctx->Texture.Unit[unit]);
2792
   const GLchan (*argRGB [3])[4];
2793
   const GLchan (*argA [3])[4];
2794
   const GLuint RGBshift = textureUnit->CombineScaleShiftRGB;
2795
   const GLuint Ashift   = textureUnit->CombineScaleShiftA;
2796
#if CHAN_TYPE == GL_FLOAT
2797
   const GLchan RGBmult = (GLfloat) (1 << RGBshift);
2798
   const GLchan Amult = (GLfloat) (1 << Ashift);
2799
#else
2800
   const GLint half = (CHAN_MAX + 1) / 2;
2801
#endif
2802
   GLuint i, j;
2803
 
2804
   /* GLchan ccolor[3][4]; */
2805
   DEFMNARRAY(GLchan, ccolor, 3, 3 * MAX_WIDTH, 4);  /* mac 32k limitation */
2806
   CHECKARRAY(ccolor, return);  /* mac 32k limitation */
2807
 
2808
   ASSERT(ctx->Extensions.EXT_texture_env_combine ||
2809
          ctx->Extensions.ARB_texture_env_combine);
2810
   ASSERT(SWRAST_CONTEXT(ctx)->_AnyTextureCombine);
2811
 
2812
 
2813
   /*
2814
   printf("modeRGB 0x%x  modeA 0x%x  srcRGB1 0x%x  srcA1 0x%x  srcRGB2 0x%x  srcA2 0x%x\n",
2815
          textureUnit->CombineModeRGB,
2816
          textureUnit->CombineModeA,
2817
          textureUnit->CombineSourceRGB[0],
2818
          textureUnit->CombineSourceA[0],
2819
          textureUnit->CombineSourceRGB[1],
2820
          textureUnit->CombineSourceA[1]);
2821
   */
2822
 
2823
   /*
2824
    * Do operand setup for up to 3 operands.  Loop over the terms.
2825
    */
2826
   for (j = 0; j < 3; j++) {
2827
      const GLenum srcA = textureUnit->CombineSourceA[j];
2828
      const GLenum srcRGB = textureUnit->CombineSourceRGB[j];
2829
 
2830
      switch (srcA) {
2831
         case GL_TEXTURE:
2832
            argA[j] = (const GLchan (*)[4])
2833
               (texelBuffer + unit * (n * 4 * sizeof(GLchan)));
2834
            break;
2835
         case GL_PRIMARY_COLOR_EXT:
2836
            argA[j] = primary_rgba;
2837
            break;
2838
         case GL_PREVIOUS_EXT:
2839
            argA[j] = (const GLchan (*)[4]) rgba;
2840
            break;
2841
         case GL_CONSTANT_EXT:
2842
            {
2843
               GLchan alpha, (*c)[4] = ccolor[j];
2844
               UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]);
2845
               for (i = 0; i < n; i++)
2846
                  c[i][ACOMP] = alpha;
2847
               argA[j] = (const GLchan (*)[4]) ccolor[j];
2848
            }
2849
            break;
2850
         default:
2851
            /* ARB_texture_env_crossbar source */
2852
            {
2853
               const GLuint srcUnit = srcA - GL_TEXTURE0_ARB;
2854
               ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
2855
               if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
2856
                  return;
2857
               argA[j] = (const GLchan (*)[4])
2858
                  (texelBuffer + srcUnit * (n * 4 * sizeof(GLchan)));
2859
            }
2860
      }
2861
 
2862
      switch (srcRGB) {
2863
         case GL_TEXTURE:
2864
            argRGB[j] = (const GLchan (*)[4])
2865
               (texelBuffer + unit * (n * 4 * sizeof(GLchan)));
2866
            break;
2867
         case GL_PRIMARY_COLOR_EXT:
2868
            argRGB[j] = primary_rgba;
2869
            break;
2870
         case GL_PREVIOUS_EXT:
2871
            argRGB[j] = (const GLchan (*)[4]) rgba;
2872
            break;
2873
         case GL_CONSTANT_EXT:
2874
            {
2875
               GLchan (*c)[4] = ccolor[j];
2876
               GLchan red, green, blue, alpha;
2877
               UNCLAMPED_FLOAT_TO_CHAN(red,   textureUnit->EnvColor[0]);
2878
               UNCLAMPED_FLOAT_TO_CHAN(green, textureUnit->EnvColor[1]);
2879
               UNCLAMPED_FLOAT_TO_CHAN(blue,  textureUnit->EnvColor[2]);
2880
               UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]);
2881
               for (i = 0; i < n; i++) {
2882
                  c[i][RCOMP] = red;
2883
                  c[i][GCOMP] = green;
2884
                  c[i][BCOMP] = blue;
2885
                  c[i][ACOMP] = alpha;
2886
               }
2887
               argRGB[j] = (const GLchan (*)[4]) ccolor[j];
2888
            }
2889
            break;
2890
         default:
2891
            /* ARB_texture_env_crossbar source */
2892
            {
2893
               const GLuint srcUnit = srcRGB - GL_TEXTURE0_ARB;
2894
               ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
2895
               if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
2896
                  return;
2897
               argRGB[j] = (const GLchan (*)[4])
2898
                  (texelBuffer + srcUnit * (n * 4 * sizeof(GLchan)));
2899
            }
2900
      }
2901
 
2902
      if (textureUnit->CombineOperandRGB[j] != GL_SRC_COLOR) {
2903
         const GLchan (*src)[4] = argRGB[j];
2904
         GLchan (*dst)[4] = ccolor[j];
2905
 
2906
         /* point to new arg[j] storage */
2907
         argRGB[j] = (const GLchan (*)[4]) ccolor[j];
2908
 
2909
         if (textureUnit->CombineOperandRGB[j] == GL_ONE_MINUS_SRC_COLOR) {
2910
            for (i = 0; i < n; i++) {
2911
               dst[i][RCOMP] = CHAN_MAX - src[i][RCOMP];
2912
               dst[i][GCOMP] = CHAN_MAX - src[i][GCOMP];
2913
               dst[i][BCOMP] = CHAN_MAX - src[i][BCOMP];
2914
            }
2915
         }
2916
         else if (textureUnit->CombineOperandRGB[j] == GL_SRC_ALPHA) {
2917
            for (i = 0; i < n; i++) {
2918
               dst[i][RCOMP] = src[i][ACOMP];
2919
               dst[i][GCOMP] = src[i][ACOMP];
2920
               dst[i][BCOMP] = src[i][ACOMP];
2921
            }
2922
         }
2923
         else {
2924
            ASSERT(textureUnit->CombineOperandRGB[j] ==GL_ONE_MINUS_SRC_ALPHA);
2925
            for (i = 0; i < n; i++) {
2926
               dst[i][RCOMP] = CHAN_MAX - src[i][ACOMP];
2927
               dst[i][GCOMP] = CHAN_MAX - src[i][ACOMP];
2928
               dst[i][BCOMP] = CHAN_MAX - src[i][ACOMP];
2929
            }
2930
         }
2931
      }
2932
 
2933
      if (textureUnit->CombineOperandA[j] == GL_ONE_MINUS_SRC_ALPHA) {
2934
         const GLchan (*src)[4] = argA[j];
2935
         GLchan (*dst)[4] = ccolor[j];
2936
         argA[j] = (const GLchan (*)[4]) ccolor[j];
2937
         for (i = 0; i < n; i++) {
2938
            dst[i][ACOMP] = CHAN_MAX - src[i][ACOMP];
2939
         }
2940
      }
2941
 
2942
      if (textureUnit->CombineModeRGB == GL_REPLACE &&
2943
          textureUnit->CombineModeA == GL_REPLACE) {
2944
         break;      /*  done, we need only arg0  */
2945
      }
2946
 
2947
      if (j == 1 &&
2948
          textureUnit->CombineModeRGB != GL_INTERPOLATE_EXT &&
2949
          textureUnit->CombineModeA != GL_INTERPOLATE_EXT) {
2950
         break;      /*  arg0 and arg1 are done. we don't need arg2. */
2951
      }
2952
   }
2953
 
2954
   /*
2955
    * Do the texture combine.
2956
    */
2957
   switch (textureUnit->CombineModeRGB) {
2958
      case GL_REPLACE:
2959
         {
2960
            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
2961
            if (RGBshift) {
2962
               for (i = 0; i < n; i++) {
2963
#if CHAN_TYPE == GL_FLOAT
2964
                  rgba[i][RCOMP] = arg0[i][RCOMP] * RGBmult;
2965
                  rgba[i][GCOMP] = arg0[i][GCOMP] * RGBmult;
2966
                  rgba[i][BCOMP] = arg0[i][BCOMP] * RGBmult;
2967
#else
2968
                  GLuint r = (GLuint) arg0[i][RCOMP] << RGBshift;
2969
                  GLuint g = (GLuint) arg0[i][GCOMP] << RGBshift;
2970
                  GLuint b = (GLuint) arg0[i][BCOMP] << RGBshift;
2971
                  rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
2972
                  rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
2973
                  rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
2974
#endif
2975
               }
2976
            }
2977
            else {
2978
               for (i = 0; i < n; i++) {
2979
                  rgba[i][RCOMP] = arg0[i][RCOMP];
2980
                  rgba[i][GCOMP] = arg0[i][GCOMP];
2981
                  rgba[i][BCOMP] = arg0[i][BCOMP];
2982
               }
2983
            }
2984
         }
2985
         break;
2986
      case GL_MODULATE:
2987
         {
2988
            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
2989
            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
2990
#if CHAN_TYPE != GL_FLOAT
2991
            const GLint shift = CHAN_BITS - RGBshift;
2992
#endif
2993
            for (i = 0; i < n; i++) {
2994
#if CHAN_TYPE == GL_FLOAT
2995
               rgba[i][RCOMP] = arg0[i][RCOMP] * arg1[i][RCOMP] * RGBmult;
2996
               rgba[i][GCOMP] = arg0[i][GCOMP] * arg1[i][GCOMP] * RGBmult;
2997
               rgba[i][BCOMP] = arg0[i][BCOMP] * arg1[i][BCOMP] * RGBmult;
2998
#else
2999
               GLuint r = PROD(arg0[i][RCOMP], arg1[i][RCOMP]) >> shift;
3000
               GLuint g = PROD(arg0[i][GCOMP], arg1[i][GCOMP]) >> shift;
3001
               GLuint b = PROD(arg0[i][BCOMP], arg1[i][BCOMP]) >> shift;
3002
               rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
3003
               rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
3004
               rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
3005
#endif
3006
            }
3007
         }
3008
         break;
3009
      case GL_ADD:
3010
         {
3011
            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
3012
            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
3013
            for (i = 0; i < n; i++) {
3014
#if CHAN_TYPE == GL_FLOAT
3015
               rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP]) * RGBmult;
3016
               rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP]) * RGBmult;
3017
               rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP]) * RGBmult;
3018
#else
3019
               GLint r = ((GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP]) << RGBshift;
3020
               GLint g = ((GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP]) << RGBshift;
3021
               GLint b = ((GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP]) << RGBshift;
3022
               rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
3023
               rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
3024
               rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
3025
#endif
3026
            }
3027
         }
3028
         break;
3029
      case GL_ADD_SIGNED_EXT:
3030
         {
3031
            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
3032
            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
3033
            for (i = 0; i < n; i++) {
3034
#if CHAN_TYPE == GL_FLOAT
3035
               rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] - 0.5) * RGBmult;
3036
               rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] - 0.5) * RGBmult;
3037
               rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] - 0.5) * RGBmult;
3038
#else
3039
               GLint r = (GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP] -half;
3040
               GLint g = (GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP] -half;
3041
               GLint b = (GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP] -half;
3042
               r = (r < 0) ? 0 : r << RGBshift;
3043
               g = (g < 0) ? 0 : g << RGBshift;
3044
               b = (b < 0) ? 0 : b << RGBshift;
3045
               rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
3046
               rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
3047
               rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
3048
#endif
3049
            }
3050
         }
3051
         break;
3052
      case GL_INTERPOLATE_EXT:
3053
         {
3054
            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
3055
            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
3056
            const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
3057
#if CHAN_TYPE != GL_FLOAT
3058
            const GLint shift = CHAN_BITS - RGBshift;
3059
#endif
3060
            for (i = 0; i < n; i++) {
3061
#if CHAN_TYPE == GL_FLOAT
3062
               rgba[i][RCOMP] = (arg0[i][RCOMP] * arg2[i][RCOMP] +
3063
                      arg1[i][RCOMP] * (CHAN_MAXF - arg2[i][RCOMP])) * RGBmult;
3064
               rgba[i][GCOMP] = (arg0[i][GCOMP] * arg2[i][GCOMP] +
3065
                      arg1[i][GCOMP] * (CHAN_MAXF - arg2[i][GCOMP])) * RGBmult;
3066
               rgba[i][BCOMP] = (arg0[i][BCOMP] * arg2[i][BCOMP] +
3067
                      arg1[i][BCOMP] * (CHAN_MAXF - arg2[i][BCOMP])) * RGBmult;
3068
#else
3069
               GLuint r = (PROD(arg0[i][RCOMP], arg2[i][RCOMP])
3070
                           + PROD(arg1[i][RCOMP], CHAN_MAX - arg2[i][RCOMP]))
3071
                              >> shift;
3072
               GLuint g = (PROD(arg0[i][GCOMP], arg2[i][GCOMP])
3073
                           + PROD(arg1[i][GCOMP], CHAN_MAX - arg2[i][GCOMP]))
3074
                              >> shift;
3075
               GLuint b = (PROD(arg0[i][BCOMP], arg2[i][BCOMP])
3076
                           + PROD(arg1[i][BCOMP], CHAN_MAX - arg2[i][BCOMP]))
3077
                              >> shift;
3078
               rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
3079
               rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
3080
               rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
3081
#endif
3082
            }
3083
         }
3084
         break;
3085
      case GL_SUBTRACT_ARB:
3086
         {
3087
            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
3088
            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
3089
            for (i = 0; i < n; i++) {
3090
#if CHAN_TYPE == GL_FLOAT
3091
               rgba[i][RCOMP] = (arg0[i][RCOMP] - arg1[i][RCOMP]) * RGBmult;
3092
               rgba[i][GCOMP] = (arg0[i][GCOMP] - arg1[i][GCOMP]) * RGBmult;
3093
               rgba[i][BCOMP] = (arg0[i][BCOMP] - arg1[i][BCOMP]) * RGBmult;
3094
#else
3095
               GLint r = ((GLint) arg0[i][RCOMP] - (GLint) arg1[i][RCOMP]) << RGBshift;
3096
               GLint g = ((GLint) arg0[i][GCOMP] - (GLint) arg1[i][GCOMP]) << RGBshift;
3097
               GLint b = ((GLint) arg0[i][BCOMP] - (GLint) arg1[i][BCOMP]) << RGBshift;
3098
               rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
3099
               rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
3100
               rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
3101
#endif
3102
            }
3103
         }
3104
         break;
3105
      case GL_DOT3_RGB_EXT:
3106
      case GL_DOT3_RGBA_EXT:
3107
         {
3108
            /* Do not scale the result by 1 2 or 4 */
3109
            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
3110
            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
3111
            for (i = 0; i < n; i++) {
3112
#if CHAN_TYPE == GL_FLOAT
3113
               GLchan dot = ((arg0[i][RCOMP]-0.5F) * (arg1[i][RCOMP]-0.5F) +
3114
                             (arg0[i][GCOMP]-0.5F) * (arg1[i][GCOMP]-0.5F) +
3115
                             (arg0[i][BCOMP]-0.5F) * (arg1[i][BCOMP]-0.5F))
3116
                            * 4.0F;
3117
               dot = CLAMP(dot, 0.0F, CHAN_MAXF);
3118
#else
3119
               GLint dot = (S_PROD((GLint)arg0[i][RCOMP] - half,
3120
                                   (GLint)arg1[i][RCOMP] - half) +
3121
                            S_PROD((GLint)arg0[i][GCOMP] - half,
3122
                                   (GLint)arg1[i][GCOMP] - half) +
3123
                            S_PROD((GLint)arg0[i][BCOMP] - half,
3124
                                   (GLint)arg1[i][BCOMP] - half)) >> 6;
3125
               dot = CLAMP(dot, 0, CHAN_MAX);
3126
#endif
3127
               rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = (GLchan) dot;
3128
            }
3129
         }
3130
         break;
3131
      case GL_DOT3_RGB_ARB:
3132
      case GL_DOT3_RGBA_ARB:
3133
         {
3134
            /* DO scale the result by 1 2 or 4 */
3135
            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
3136
            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
3137
            for (i = 0; i < n; i++) {
3138
#if CHAN_TYPE == GL_FLOAT
3139
               GLchan dot = ((arg0[i][RCOMP]-0.5F) * (arg1[i][RCOMP]-0.5F) +
3140
                             (arg0[i][GCOMP]-0.5F) * (arg1[i][GCOMP]-0.5F) +
3141
                             (arg0[i][BCOMP]-0.5F) * (arg1[i][BCOMP]-0.5F))
3142
                            * 4.0F * RGBmult;
3143
               dot = CLAMP(dot, 0.0, CHAN_MAXF);
3144
#else
3145
               GLint dot = (S_PROD((GLint)arg0[i][RCOMP] - half,
3146
                                   (GLint)arg1[i][RCOMP] - half) +
3147
                            S_PROD((GLint)arg0[i][GCOMP] - half,
3148
                                   (GLint)arg1[i][GCOMP] - half) +
3149
                            S_PROD((GLint)arg0[i][BCOMP] - half,
3150
                                   (GLint)arg1[i][BCOMP] - half)) >> 6;
3151
               dot <<= RGBshift;
3152
               dot = CLAMP(dot, 0, CHAN_MAX);
3153
#endif
3154
               rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = (GLchan) dot;
3155
            }
3156
         }
3157
         break;
3158
      default:
3159
         _mesa_problem(ctx, "invalid combine mode");
3160
   }
3161
 
3162
   switch (textureUnit->CombineModeA) {
3163
      case GL_REPLACE:
3164
         {
3165
            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
3166
            if (Ashift) {
3167
               for (i = 0; i < n; i++) {
3168
#if CHAN_TYPE == GL_FLOAT
3169
                  GLchan a = arg0[i][ACOMP] * Amult;
3170
#else
3171
                  GLuint a = (GLuint) arg0[i][ACOMP] << Ashift;
3172
#endif
3173
                  rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
3174
               }
3175
            }
3176
            else {
3177
               for (i = 0; i < n; i++) {
3178
                  rgba[i][ACOMP] = arg0[i][ACOMP];
3179
               }
3180
            }
3181
         }
3182
         break;
3183
      case GL_MODULATE:
3184
         {
3185
            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
3186
            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
3187
#if CHAN_TYPE != GL_FLOAT
3188
            const GLint shift = CHAN_BITS - Ashift;
3189
#endif
3190
            for (i = 0; i < n; i++) {
3191
#if CHAN_TYPE == GL_FLOAT
3192
               rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * Amult;
3193
#else
3194
               GLuint a = (PROD(arg0[i][ACOMP], arg1[i][ACOMP]) >> shift);
3195
               rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
3196
#endif
3197
            }
3198
         }
3199
         break;
3200
      case GL_ADD:
3201
         {
3202
            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
3203
            const GLchan  (*arg1)[4] = (const GLchan (*)[4]) argA[1];
3204
            for (i = 0; i < n; i++) {
3205
#if CHAN_TYPE == GL_FLOAT
3206
               rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * Amult;
3207
#else
3208
               GLint a = ((GLint) arg0[i][ACOMP] + arg1[i][ACOMP]) << Ashift;
3209
               rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
3210
#endif
3211
            }
3212
         }
3213
         break;
3214
      case GL_ADD_SIGNED_EXT:
3215
         {
3216
            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
3217
            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
3218
            for (i = 0; i < n; i++) {
3219
#if CHAN_TYPE == GL_FLOAT
3220
               rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * Amult;
3221
#else
3222
               GLint a = (GLint) arg0[i][ACOMP] + (GLint) arg1[i][ACOMP] -half;
3223
               a = (a < 0) ? 0 : a << Ashift;
3224
               rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
3225
#endif
3226
            }
3227
         }
3228
         break;
3229
      case GL_INTERPOLATE_EXT:
3230
         {
3231
            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
3232
            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
3233
            const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
3234
#if CHAN_TYPE != GL_FLOAT
3235
            const GLint shift = CHAN_BITS - Ashift;
3236
#endif
3237
            for (i=0; i<n; i++) {
3238
#if CHAN_TYPE == GL_FLOAT
3239
               rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] +
3240
                                 arg1[i][ACOMP] * (CHAN_MAXF - arg2[i][ACOMP]))
3241
                                * Amult;
3242
#else
3243
               GLuint a = (PROD(arg0[i][ACOMP], arg2[i][ACOMP])
3244
                           + PROD(arg1[i][ACOMP], CHAN_MAX - arg2[i][ACOMP]))
3245
                              >> shift;
3246
               rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
3247
#endif
3248
            }
3249
         }
3250
         break;
3251
      case GL_SUBTRACT_ARB:
3252
         {
3253
            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
3254
            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
3255
            for (i = 0; i < n; i++) {
3256
#if CHAN_TYPE == GL_FLOAT
3257
               rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * Amult;
3258
#else
3259
               GLint a = ((GLint) arg0[i][ACOMP] - (GLint) arg1[i][ACOMP]) << Ashift;
3260
               rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
3261
#endif
3262
            }
3263
         }
3264
         break;
3265
 
3266
      default:
3267
         _mesa_problem(ctx, "invalid combine mode");
3268
   }
3269
 
3270
   /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
3271
    * This is kind of a kludge.  It would have been better if the spec
3272
    * were written such that the GL_COMBINE_ALPHA value could be set to
3273
    * GL_DOT3.
3274
    */
3275
   if (textureUnit->CombineModeRGB == GL_DOT3_RGBA_EXT ||
3276
       textureUnit->CombineModeRGB == GL_DOT3_RGBA_ARB) {
3277
      for (i = 0; i < n; i++) {
3278
         rgba[i][ACOMP] = rgba[i][RCOMP];
3279
      }
3280
   }
3281
   UNDEFARRAY(ccolor);  /* mac 32k limitation */
3282
}
3283
#undef PROD
3284
 
3285
 
3286
/**
3287
 * Implement NVIDIA's GL_NV_texture_env_combine4 extension when
3288
 * texUnit->EnvMode == GL_COMBINE4_NV.
3289
 */
3290
static INLINE void
3291
texture_combine4( const GLcontext *ctx, GLuint unit, GLuint n,
3292
                  CONST GLchan (*primary_rgba)[4],
3293
                  CONST GLchan *texelBuffer,
3294
                  GLchan (*rgba)[4] )
3295
{
3296
}
3297
 
3298
 
3299
 
3300
/**
3301
 * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND,
3302
 * MODULATE, or DECAL) to an array of fragments.
3303
 * Input:  textureUnit - pointer to texture unit to apply
3304
 *         format - base internal texture format
3305
 *         n - number of fragments
3306
 *         primary_rgba - primary colors (may alias rgba for single texture)
3307
 *         texels - array of texel colors
3308
 * InOut:  rgba - incoming fragment colors modified by texel colors
3309
 *                according to the texture environment mode.
3310
 */
3311
static void
3312
texture_apply( const GLcontext *ctx,
3313
               const struct gl_texture_unit *texUnit,
3314
               GLuint n,
3315
               CONST GLchan primary_rgba[][4], CONST GLchan texel[][4],
3316
               GLchan rgba[][4] )
3317
{
3318
   GLint baseLevel;
3319
   GLuint i;
3320
   GLint Rc, Gc, Bc, Ac;
3321
   GLenum format;
3322
 
3323
   ASSERT(texUnit);
3324
   ASSERT(texUnit->_Current);
3325
 
3326
   baseLevel = texUnit->_Current->BaseLevel;
3327
   ASSERT(texUnit->_Current->Image[baseLevel]);
3328
 
3329
   format = texUnit->_Current->Image[baseLevel]->Format;
3330
 
3331
   if (format == GL_COLOR_INDEX || format == GL_DEPTH_COMPONENT
3332
       || format == GL_YCBCR_MESA) {
3333
      format = GL_RGBA;  /* a bit of a hack */
3334
   }
3335
 
3336
   switch (texUnit->EnvMode) {
3337
      case GL_REPLACE:
3338
         switch (format) {
3339
            case GL_ALPHA:
3340
               for (i=0;i<n;i++) {
3341
                  /* Cv = Cf */
3342
                  /* Av = At */
3343
                  rgba[i][ACOMP] = texel[i][ACOMP];
3344
               }
3345
               break;
3346
            case GL_LUMINANCE:
3347
               for (i=0;i<n;i++) {
3348
                  /* Cv = Lt */
3349
                  GLchan Lt = texel[i][RCOMP];
3350
                  rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
3351
                  /* Av = Af */
3352
               }
3353
               break;
3354
            case GL_LUMINANCE_ALPHA:
3355
               for (i=0;i<n;i++) {
3356
                  GLchan Lt = texel[i][RCOMP];
3357
                  /* Cv = Lt */
3358
                  rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
3359
                  /* Av = At */
3360
                  rgba[i][ACOMP] = texel[i][ACOMP];
3361
               }
3362
               break;
3363
            case GL_INTENSITY:
3364
               for (i=0;i<n;i++) {
3365
                  /* Cv = It */
3366
                  GLchan It = texel[i][RCOMP];
3367
                  rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = It;
3368
                  /* Av = It */
3369
                  rgba[i][ACOMP] = It;
3370
               }
3371
               break;
3372
            case GL_RGB:
3373
               for (i=0;i<n;i++) {
3374
                  /* Cv = Ct */
3375
                  rgba[i][RCOMP] = texel[i][RCOMP];
3376
                  rgba[i][GCOMP] = texel[i][GCOMP];
3377
                  rgba[i][BCOMP] = texel[i][BCOMP];
3378
                  /* Av = Af */
3379
               }
3380
               break;
3381
            case GL_RGBA:
3382
               for (i=0;i<n;i++) {
3383
                  /* Cv = Ct */
3384
                  rgba[i][RCOMP] = texel[i][RCOMP];
3385
                  rgba[i][GCOMP] = texel[i][GCOMP];
3386
                  rgba[i][BCOMP] = texel[i][BCOMP];
3387
                  /* Av = At */
3388
                  rgba[i][ACOMP] = texel[i][ACOMP];
3389
               }
3390
               break;
3391
            default:
3392
               _mesa_problem(ctx, "Bad format (GL_REPLACE) in texture_apply");
3393
               return;
3394
         }
3395
         break;
3396
 
3397
      case GL_MODULATE:
3398
         switch (format) {
3399
            case GL_ALPHA:
3400
               for (i=0;i<n;i++) {
3401
                  /* Cv = Cf */
3402
                  /* Av = AfAt */
3403
                  rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
3404
               }
3405
               break;
3406
            case GL_LUMINANCE:
3407
               for (i=0;i<n;i++) {
3408
                  /* Cv = LtCf */
3409
                  GLchan Lt = texel[i][RCOMP];
3410
                  rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt );
3411
                  rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt );
3412
                  rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt );
3413
                  /* Av = Af */
3414
               }
3415
               break;
3416
            case GL_LUMINANCE_ALPHA:
3417
               for (i=0;i<n;i++) {
3418
                  /* Cv = CfLt */
3419
                  GLchan Lt = texel[i][RCOMP];
3420
                  rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt );
3421
                  rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt );
3422
                  rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt );
3423
                  /* Av = AfAt */
3424
                  rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
3425
               }
3426
               break;
3427
            case GL_INTENSITY:
3428
               for (i=0;i<n;i++) {
3429
                  /* Cv = CfIt */
3430
                  GLchan It = texel[i][RCOMP];
3431
                  rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], It );
3432
                  rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], It );
3433
                  rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], It );
3434
                  /* Av = AfIt */
3435
                  rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], It );
3436
               }
3437
               break;
3438
            case GL_RGB:
3439
               for (i=0;i<n;i++) {
3440
                  /* Cv = CfCt */
3441
                  rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] );
3442
                  rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] );
3443
                  rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] );
3444
                  /* Av = Af */
3445
               }
3446
               break;
3447
            case GL_RGBA:
3448
               for (i=0;i<n;i++) {
3449
                  /* Cv = CfCt */
3450
                  rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] );
3451
                  rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] );
3452
                  rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] );
3453
                  /* Av = AfAt */
3454
                  rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
3455
               }
3456
               break;
3457
            default:
3458
               _mesa_problem(ctx, "Bad format (GL_MODULATE) in texture_apply");
3459
               return;
3460
         }
3461
         break;
3462
 
3463
      case GL_DECAL:
3464
         switch (format) {
3465
            case GL_ALPHA:
3466
            case GL_LUMINANCE:
3467
            case GL_LUMINANCE_ALPHA:
3468
            case GL_INTENSITY:
3469
               /* undefined */
3470
               break;
3471
            case GL_RGB:
3472
               for (i=0;i<n;i++) {
3473
                  /* Cv = Ct */
3474
                  rgba[i][RCOMP] = texel[i][RCOMP];
3475
                  rgba[i][GCOMP] = texel[i][GCOMP];
3476
                  rgba[i][BCOMP] = texel[i][BCOMP];
3477
                  /* Av = Af */
3478
               }
3479
               break;
3480
            case GL_RGBA:
3481
               for (i=0;i<n;i++) {
3482
                  /* Cv = Cf(1-At) + CtAt */
3483
                  GLint t = texel[i][ACOMP], s = CHAN_MAX - t;
3484
                  rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(texel[i][RCOMP],t);
3485
                  rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(texel[i][GCOMP],t);
3486
                  rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(texel[i][BCOMP],t);
3487
                  /* Av = Af */
3488
               }
3489
               break;
3490
            default:
3491
               _mesa_problem(ctx, "Bad format (GL_DECAL) in texture_apply");
3492
               return;
3493
         }
3494
         break;
3495
 
3496
      case GL_BLEND:
3497
         Rc = (GLint) (texUnit->EnvColor[0] * CHAN_MAXF);
3498
         Gc = (GLint) (texUnit->EnvColor[1] * CHAN_MAXF);
3499
         Bc = (GLint) (texUnit->EnvColor[2] * CHAN_MAXF);
3500
         Ac = (GLint) (texUnit->EnvColor[3] * CHAN_MAXF);
3501
         switch (format) {
3502
            case GL_ALPHA:
3503
               for (i=0;i<n;i++) {
3504
                  /* Cv = Cf */
3505
                  /* Av = AfAt */
3506
                  rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
3507
               }
3508
               break;
3509
            case GL_LUMINANCE:
3510
               for (i=0;i<n;i++) {
3511
                  /* Cv = Cf(1-Lt) + CcLt */
3512
                  GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt;
3513
                  rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt);
3514
                  rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt);
3515
                  rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt);
3516
                  /* Av = Af */
3517
               }
3518
               break;
3519
            case GL_LUMINANCE_ALPHA:
3520
               for (i=0;i<n;i++) {
3521
                  /* Cv = Cf(1-Lt) + CcLt */
3522
                  GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt;
3523
                  rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt);
3524
                  rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt);
3525
                  rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt);
3526
                  /* Av = AfAt */
3527
                  rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]);
3528
               }
3529
               break;
3530
            case GL_INTENSITY:
3531
               for (i=0;i<n;i++) {
3532
                  /* Cv = Cf(1-It) + CcLt */
3533
                  GLchan It = texel[i][RCOMP], s = CHAN_MAX - It;
3534
                  rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, It);
3535
                  rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, It);
3536
                  rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, It);
3537
                  /* Av = Af(1-It) + Ac*It */
3538
                  rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], s) + CHAN_PRODUCT(Ac, It);
3539
               }
3540
               break;
3541
            case GL_RGB:
3542
               for (i=0;i<n;i++) {
3543
                  /* Cv = Cf(1-Ct) + CcCt */
3544
                  rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]);
3545
                  rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]);
3546
                  rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]);
3547
                  /* Av = Af */
3548
               }
3549
               break;
3550
            case GL_RGBA:
3551
               for (i=0;i<n;i++) {
3552
                  /* Cv = Cf(1-Ct) + CcCt */
3553
                  rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]);
3554
                  rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]);
3555
                  rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]);
3556
                  /* Av = AfAt */
3557
                  rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]);
3558
               }
3559
               break;
3560
            default:
3561
               _mesa_problem(ctx, "Bad format (GL_BLEND) in texture_apply");
3562
               return;
3563
         }
3564
         break;
3565
 
3566
     /* XXX don't clamp results if GLchan is float??? */
3567
 
3568
      case GL_ADD:  /* GL_EXT_texture_add_env */
3569
         switch (format) {
3570
            case GL_ALPHA:
3571
               for (i=0;i<n;i++) {
3572
                  /* Rv = Rf */
3573
                  /* Gv = Gf */
3574
                  /* Bv = Bf */
3575
                  rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
3576
               }
3577
               break;
3578
            case GL_LUMINANCE:
3579
               for (i=0;i<n;i++) {
3580
                  GLuint Lt = texel[i][RCOMP];
3581
                  GLuint r = rgba[i][RCOMP] + Lt;
3582
                  GLuint g = rgba[i][GCOMP] + Lt;
3583
                  GLuint b = rgba[i][BCOMP] + Lt;
3584
                  rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
3585
                  rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
3586
                  rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
3587
                  /* Av = Af */
3588
               }
3589
               break;
3590
            case GL_LUMINANCE_ALPHA:
3591
               for (i=0;i<n;i++) {
3592
                  GLuint Lt = texel[i][RCOMP];
3593
                  GLuint r = rgba[i][RCOMP] + Lt;
3594
                  GLuint g = rgba[i][GCOMP] + Lt;
3595
                  GLuint b = rgba[i][BCOMP] + Lt;
3596
                  rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
3597
                  rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
3598
                  rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
3599
                  rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
3600
               }
3601
               break;
3602
            case GL_INTENSITY:
3603
               for (i=0;i<n;i++) {
3604
                  GLchan It = texel[i][RCOMP];
3605
                  GLuint r = rgba[i][RCOMP] + It;
3606
                  GLuint g = rgba[i][GCOMP] + It;
3607
                  GLuint b = rgba[i][BCOMP] + It;
3608
                  GLuint a = rgba[i][ACOMP] + It;
3609
                  rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
3610
                  rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
3611
                  rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
3612
                  rgba[i][ACOMP] = MIN2(a, CHAN_MAX);
3613
               }
3614
               break;
3615
            case GL_RGB:
3616
               for (i=0;i<n;i++) {
3617
                  GLuint r = rgba[i][RCOMP] + texel[i][RCOMP];
3618
                  GLuint g = rgba[i][GCOMP] + texel[i][GCOMP];
3619
                  GLuint b = rgba[i][BCOMP] + texel[i][BCOMP];
3620
                  rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
3621
                  rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
3622
                  rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
3623
                  /* Av = Af */
3624
               }
3625
               break;
3626
            case GL_RGBA:
3627
               for (i=0;i<n;i++) {
3628
                  GLuint r = rgba[i][RCOMP] + texel[i][RCOMP];
3629
                  GLuint g = rgba[i][GCOMP] + texel[i][GCOMP];
3630
                  GLuint b = rgba[i][BCOMP] + texel[i][BCOMP];
3631
                  rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
3632
                  rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
3633
                  rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
3634
                  rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
3635
               }
3636
               break;
3637
            default:
3638
               _mesa_problem(ctx, "Bad format (GL_ADD) in texture_apply");
3639
               return;
3640
         }
3641
         break;
3642
 
3643
      default:
3644
         _mesa_problem(ctx, "Bad env mode in texture_apply");
3645
         return;
3646
   }
3647
}
3648
 
3649
 
3650
 
3651
/**
3652
 * Apply texture mapping to a span of fragments.
3653
 */
3654
void
3655
_swrast_texture_span( GLcontext *ctx, struct sw_span *span )
3656
{
3657
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
3658
   GLchan primary_rgba[MAX_WIDTH][4];
3659
   GLuint unit;
3660
 
3661
   ASSERT(span->end < MAX_WIDTH);
3662
   ASSERT(span->arrayMask & SPAN_TEXTURE);
3663
 
3664
   /*
3665
    * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
3666
    */
3667
   if (swrast->_AnyTextureCombine)
3668
      MEMCPY(primary_rgba, span->array->rgba, 4 * span->end * sizeof(GLchan));
3669
 
3670
   /*
3671
    * Must do all texture sampling before combining in order to
3672
    * accomodate GL_ARB_texture_env_crossbar.
3673
    */
3674
   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
3675
      if (ctx->Texture.Unit[unit]._ReallyEnabled) {
3676
         const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
3677
         const struct gl_texture_object *curObj = texUnit->_Current;
3678
         GLfloat *lambda = span->array->lambda[unit];
3679
         GLchan (*texels)[4] = (GLchan (*)[4])
3680
            (swrast->TexelBuffer + unit * (span->end * 4 * sizeof(GLchan)));
3681
 
3682
         /* adjust texture lod (lambda) */
3683
         if (span->arrayMask | SPAN_LAMBDA) {
3684
            if (texUnit->LodBias != 0.0F) {
3685
               /* apply LOD bias, but don't clamp yet */
3686
               GLuint i;
3687
               for (i = 0; i < span->end; i++) {
3688
                  lambda[i] += texUnit->LodBias;
3689
               }
3690
            }
3691
 
3692
            if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) {
3693
               /* apply LOD clamping to lambda */
3694
               const GLfloat min = curObj->MinLod;
3695
               const GLfloat max = curObj->MaxLod;
3696
               GLuint i;
3697
               for (i = 0; i < span->end; i++) {
3698
                  GLfloat l = lambda[i];
3699
                  lambda[i] = CLAMP(l, min, max);
3700
               }
3701
            }
3702
         }
3703
 
3704
         /* Sample the texture (span->end fragments) */
3705
         swrast->TextureSample[unit]( ctx, unit, texUnit->_Current,
3706
                                      span->end, span->array->texcoords[unit],
3707
                                      lambda, texels );
3708
      }
3709
   }
3710
 
3711
   /*
3712
    * OK, now apply the texture (aka texture combine/blend).
3713
    * We modify the span->color.rgba values.
3714
    */
3715
   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
3716
      if (ctx->Texture.Unit[unit]._ReallyEnabled) {
3717
         const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
3718
         if (texUnit->EnvMode == GL_COMBINE_EXT) {
3719
            /* GL_ARB/EXT_texture_env_combine */
3720
            texture_combine( ctx, unit, span->end,
3721
                             (CONST GLchan (*)[4]) primary_rgba,
3722
                             swrast->TexelBuffer,
3723
                             span->array->rgba );
3724
         }
3725
         else if (texUnit->EnvMode == GL_COMBINE4_NV) {
3726
            /* GL_NV_texture_env_combine4 */
3727
            texture_combine4( ctx, unit, span->end,
3728
                              (CONST GLchan (*)[4]) primary_rgba,
3729
                              swrast->TexelBuffer,
3730
                              span->array->rgba );
3731
         }
3732
         else {
3733
            /* conventional texture blend */
3734
            const GLchan (*texels)[4] = (const GLchan (*)[4])
3735
               (swrast->TexelBuffer + unit *
3736
                (span->end * 4 * sizeof(GLchan)));
3737
            texture_apply( ctx, texUnit, span->end,
3738
                           (CONST GLchan (*)[4]) primary_rgba, texels,
3739
                           span->array->rgba );
3740
         }
3741
      }
3742
   }
3743
}