source: trunk/src/opengl/mesa/texture.c@ 2961

Last change on this file since 2961 was 2938, checked in by sandervl, 25 years ago

created

File size: 68.9 KB
Line 
1/* $Id: texture.c,v 1.1 2000-02-29 00:50:12 sandervl Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version: 3.1
6 *
7 * Copyright (C) 1999 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#ifdef PC_HEADER
29#include "all.h"
30#else
31#ifndef XFree86Server
32#include <math.h>
33#include <stdlib.h>
34#include <stdio.h>
35#else
36#include "GL/xf86glx.h"
37#endif
38#include "context.h"
39#include "macros.h"
40#include "mmath.h"
41#include "pb.h"
42#include "texture.h"
43#include "types.h"
44#include "xform.h"
45#endif
46
47/***********************************************************************
48 * Automatic texture coordinate generation (texgen) code.
49 */
50
51static GLuint all_bits[5] = {
52 0,
53 VEC_SIZE_1,
54 VEC_SIZE_2,
55 VEC_SIZE_3,
56 VEC_SIZE_4,
57};
58
59
60static texgen_func texgen_generic_tab[4];
61static texgen_func texgen_reflection_map_nv_tab[4];
62static texgen_func texgen_normal_map_nv_tab[4];
63static texgen_func texgen_sphere_map_tab[4];
64
65
66typedef void (*build_m_func)(GLfloat f[][3],
67 GLfloat m[],
68 const GLvector3f *normals,
69 const GLvector4f *coord_vec,
70 const GLuint flags[],
71 const GLubyte cullmask[] );
72
73
74typedef void (*build_f_func)( GLfloat *f,
75 GLuint fstride,
76 const GLvector3f *normal_vec,
77 const GLvector4f *coord_vec,
78 const GLuint flags[],
79 const GLubyte cullmask[] );
80
81
82/* KW: compacted vs. coindexed normals don't bring any performance
83 * gains to texture generation, but it is still necessary to cope
84 * with the two different formats.
85 */
86#define TAG(x) x
87#define FIRST_NORMAL normals->start
88#define NEXT_NORMAL STRIDE_F(normal, normals->stride)
89#define LOCAL_VARS
90#define CHECK
91#define IDX 0
92#include "texgen_tmp.h"
93
94
95#define TAG(x) x##_compacted
96#define FIRST_NORMAL normals->start
97#define NEXT_NORMAL ((flags[i]&VERT_NORM) ? (normal=first_normal[i]) : (normal))
98#define CHECK
99#define IDX 2
100#define LOCAL_VARS \
101 GLfloat (*first_normal)[3] = (GLfloat (*)[3]) FIRST_NORMAL;
102
103#include "texgen_tmp.h"
104
105#define TAG(x) x##_masked
106#define FIRST_NORMAL normals->start
107#define NEXT_NORMAL STRIDE_F(normal, normals->stride)
108#define LOCAL_VARS
109#define CHECK if (cullmask[i])
110#define IDX 1
111#include "texgen_tmp.h"
112
113#define TAG(x) x##_compacted_masked
114#define FIRST_NORMAL normals->start
115#define NEXT_NORMAL ((flags[i]&VERT_NORM) ? normal=first_normal[i] : 0)
116#define CHECK if (cullmask[i])
117#define IDX 3
118#define LOCAL_VARS \
119 GLfloat (*first_normal)[3] = (GLfloat (*)[3]) FIRST_NORMAL;
120
121#include "texgen_tmp.h"
122
123
124/*
125 * End texgen code
126 ***********************************************************************
127 */
128
129
130
131/*
132 * One time inits for texture mapping.
133 * Called by one_time_init() in context.c
134 */
135void gl_init_texture( void )
136{
137 init_texgen();
138 init_texgen_compacted();
139 init_texgen_masked();
140 init_texgen_compacted_masked();
141}
142
143/*
144 * Paletted texture sampling.
145 * Input: tObj - the texture object
146 * index - the palette index (8-bit only)
147 * Output: red, green, blue, alpha - the texel color
148 */
149static void palette_sample(const struct gl_texture_object *tObj,
150 GLubyte index, GLubyte rgba[4] )
151{
152 GLcontext *ctx = gl_get_current_context(); /* THIS IS A HACK */
153 GLint i = index;
154 const GLubyte *palette;
155
156 if (ctx->Texture.SharedPalette) {
157 palette = ctx->Texture.Palette;
158 }
159 else {
160 palette = tObj->Palette;
161 }
162
163 switch (tObj->PaletteFormat) {
164 case GL_ALPHA:
165 rgba[ACOMP] = tObj->Palette[index];
166 return;
167 case GL_LUMINANCE:
168 case GL_INTENSITY:
169 rgba[RCOMP] = palette[index];
170 return;
171 case GL_LUMINANCE_ALPHA:
172 rgba[RCOMP] = palette[(index << 1) + 0];
173 rgba[ACOMP] = palette[(index << 1) + 1];
174 return;
175 case GL_RGB:
176 rgba[RCOMP] = palette[index * 3 + 0];
177 rgba[GCOMP] = palette[index * 3 + 1];
178 rgba[BCOMP] = palette[index * 3 + 2];
179 return;
180 case GL_RGBA:
181 rgba[RCOMP] = palette[(i << 2) + 0];
182 rgba[GCOMP] = palette[(i << 2) + 1];
183 rgba[BCOMP] = palette[(i << 2) + 2];
184 rgba[ACOMP] = palette[(i << 2) + 3];
185 return;
186 default:
187 gl_problem(NULL, "Bad palette format in palette_sample");
188 }
189}
190
191
192
193/*
194 * These values are used in the fixed-point arithmetic used
195 * for linear filtering.
196 */
197#define WEIGHT_SCALE 65536.0F
198#define WEIGHT_SHIFT 16
199
200
201/*
202 * Used to compute texel locations for linear sampling.
203 */
204#define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1) \
205{ \
206 if (wrapMode == GL_REPEAT) { \
207 U = S * SIZE - 0.5F; \
208 I0 = ((GLint) myFloor(U)) & (SIZE - 1); \
209 I1 = (I0 + 1) & (SIZE - 1); \
210 } \
211 else { \
212 U = S * SIZE; \
213 if (U < 0.0F) \
214 U = 0.0F; \
215 else if (U >= SIZE) \
216 U = SIZE; \
217 U -= 0.5F; \
218 I0 = (GLint) myFloor(U); \
219 I1 = I0 + 1; \
220 if (wrapMode == GL_CLAMP_TO_EDGE) { \
221 if (I0 < 0) \
222 I0 = 0; \
223 if (I1 >= SIZE) \
224 I1 = SIZE - 1; \
225 } \
226 } \
227}
228
229
230/*
231 * Used to compute texel location for nearest sampling.
232 */
233#define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I) \
234{ \
235 if (wrapMode == GL_REPEAT) { \
236 /* s limited to [0,1) */ \
237 /* i limited to [0,width-1] */ \
238 I = (GLint) (S * SIZE); \
239 if (S < 0.0F) \
240 I -= 1; \
241 I &= (SIZE - 1); \
242 } \
243 else if (wrapMode == GL_CLAMP_TO_EDGE) { \
244 const GLfloat min = 1.0F / (2.0F * SIZE); \
245 const GLfloat max = 1.0F - min; \
246 if (S < min) \
247 I = 0; \
248 else if (S > max) \
249 I = SIZE - 1; \
250 else \
251 I = (GLint) (S * SIZE); \
252 } \
253 else { \
254 ASSERT(wrapMode == GL_CLAMP); \
255 /* s limited to [0,1] */ \
256 /* i limited to [0,width-1] */ \
257 if (S <= 0.0F) \
258 I = 0; \
259 else if (S >= 1.0F) \
260 I = SIZE - 1; \
261 else \
262 I = (GLint) (S * SIZE); \
263 } \
264}
265
266
267/*
268 * Bitflags for texture border color sampling.
269 */
270#define I0BIT 1
271#define I1BIT 2
272#define J0BIT 4
273#define J1BIT 8
274#define K0BIT 16
275#define K1BIT 32
276
277
278
279/**********************************************************************/
280/* 1-D Texture Sampling Functions */
281/**********************************************************************/
282
283
284/*
285 * Return floor of x, being careful of negative values.
286 */
287static GLfloat myFloor(GLfloat x)
288{
289 if (x < 0.0F)
290 return (GLfloat) ((GLint) x - 1);
291 else
292 return (GLfloat) (GLint) x;
293}
294
295
296/*
297 * Return the fractional part of x.
298 */
299#define myFrac(x) ( (x) - myFloor(x) )
300
301
302
303
304/*
305 * Given 1-D texture image and an (i) texel column coordinate, return the
306 * texel color.
307 */
308static void get_1d_texel( const struct gl_texture_object *tObj,
309 const struct gl_texture_image *img, GLint i,
310 GLubyte rgba[4] )
311{
312 const GLubyte *texel;
313
314#ifdef DEBUG
315 GLint width = img->Width;
316 assert(i >= 0);
317 assert(i < width);
318#endif
319
320 switch (img->Format) {
321 case GL_COLOR_INDEX:
322 {
323 GLubyte index = img->Data[i];
324 palette_sample(tObj, index, rgba);
325 return;
326 }
327 case GL_ALPHA:
328 rgba[ACOMP] = img->Data[ i ];
329 return;
330 case GL_LUMINANCE:
331 case GL_INTENSITY:
332 rgba[RCOMP] = img->Data[ i ];
333 return;
334 case GL_LUMINANCE_ALPHA:
335 texel = img->Data + i * 2;
336 rgba[RCOMP] = texel[0];
337 rgba[ACOMP] = texel[1];
338 return;
339 case GL_RGB:
340 texel = img->Data + i * 3;
341 rgba[RCOMP] = texel[0];
342 rgba[GCOMP] = texel[1];
343 rgba[BCOMP] = texel[2];
344 return;
345 case GL_RGBA:
346 texel = img->Data + i * 4;
347 rgba[RCOMP] = texel[0];
348 rgba[GCOMP] = texel[1];
349 rgba[BCOMP] = texel[2];
350 rgba[ACOMP] = texel[3];
351 return;
352 default:
353 gl_problem(NULL, "Bad format in get_1d_texel");
354 return;
355 }
356}
357
358
359
360/*
361 * Return the texture sample for coordinate (s) using GL_NEAREST filter.
362 */
363static void sample_1d_nearest( const struct gl_texture_object *tObj,
364 const struct gl_texture_image *img,
365 GLfloat s, GLubyte rgba[4] )
366{
367 const GLint width = img->Width2; /* without border, power of two */
368 const GLubyte *texel;
369 GLint i;
370
371 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, s, width, i);
372
373 /* skip over the border, if any */
374 i += img->Border;
375
376 /* Get the texel */
377 switch (img->Format) {
378 case GL_COLOR_INDEX:
379 {
380 GLubyte index = img->Data[i];
381 palette_sample(tObj, index, rgba );
382 return;
383 }
384 case GL_ALPHA:
385 rgba[ACOMP] = img->Data[i];
386 return;
387 case GL_LUMINANCE:
388 case GL_INTENSITY:
389 rgba[RCOMP] = img->Data[i];
390 return;
391 case GL_LUMINANCE_ALPHA:
392 texel = img->Data + i * 2;
393 rgba[RCOMP] = texel[0];
394 rgba[ACOMP] = texel[1];
395 return;
396 case GL_RGB:
397 texel = img->Data + i * 3;
398 rgba[RCOMP] = texel[0];
399 rgba[GCOMP] = texel[1];
400 rgba[BCOMP] = texel[2];
401 return;
402 case GL_RGBA:
403 texel = img->Data + i * 4;
404 rgba[RCOMP] = texel[0];
405 rgba[GCOMP] = texel[1];
406 rgba[BCOMP] = texel[2];
407 rgba[ACOMP] = texel[3];
408 return;
409 default:
410 gl_problem(NULL, "Bad format in sample_1d_nearest");
411 }
412}
413
414
415
416/*
417 * Return the texture sample for coordinate (s) using GL_LINEAR filter.
418 */
419static void sample_1d_linear( const struct gl_texture_object *tObj,
420 const struct gl_texture_image *img,
421 GLfloat s,
422 GLubyte rgba[4] )
423{
424 const GLint width = img->Width2;
425 GLint i0, i1;
426 GLfloat u;
427 GLuint useBorderColor;
428
429 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, s, u, width, i0, i1);
430
431 useBorderColor = 0;
432 if (img->Border) {
433 i0 += img->Border;
434 i1 += img->Border;
435 }
436 else {
437 if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
438 if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
439 }
440
441 {
442 GLfloat a = myFrac(u);
443 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
444 GLint w0 = (GLint) ((1.0F-a) * WEIGHT_SCALE + 0.5F);
445 GLint w1 = (GLint) ( a * WEIGHT_SCALE + 0.5F);
446
447 GLubyte t0[4], t1[4]; /* texels */
448
449 if (useBorderColor & I0BIT) {
450 t0[RCOMP] = tObj->BorderColor[0];
451 t0[GCOMP] = tObj->BorderColor[1];
452 t0[BCOMP] = tObj->BorderColor[2];
453 t0[ACOMP] = tObj->BorderColor[3];
454 }
455 else {
456 get_1d_texel( tObj, img, i0, t0 );
457 }
458 if (useBorderColor & I1BIT) {
459 t1[RCOMP] = tObj->BorderColor[0];
460 t1[GCOMP] = tObj->BorderColor[1];
461 t1[BCOMP] = tObj->BorderColor[2];
462 t1[ACOMP] = tObj->BorderColor[3];
463 }
464 else {
465 get_1d_texel( tObj, img, i1, t1 );
466 }
467
468 rgba[0] = (GLubyte) ((w0 * t0[0] + w1 * t1[0]) >> WEIGHT_SHIFT);
469 rgba[1] = (GLubyte) ((w0 * t0[1] + w1 * t1[1]) >> WEIGHT_SHIFT);
470 rgba[2] = (GLubyte) ((w0 * t0[2] + w1 * t1[2]) >> WEIGHT_SHIFT);
471 rgba[3] = (GLubyte) ((w0 * t0[3] + w1 * t1[3]) >> WEIGHT_SHIFT);
472 }
473}
474
475
476static void
477sample_1d_nearest_mipmap_nearest( const struct gl_texture_object *tObj,
478 GLfloat s, GLfloat lambda,
479 GLubyte rgba[4] )
480{
481 GLint level;
482 if (lambda <= 0.5F)
483 lambda = 0.0F;
484 else if (lambda > tObj->M + 0.4999F)
485 lambda = tObj->M + 0.4999F;
486 level = (GLint) (tObj->BaseLevel + lambda + 0.5F);
487 if (level > tObj->P)
488 level = tObj->P;
489
490 sample_1d_nearest( tObj, tObj->Image[level], s, rgba );
491}
492
493
494static void
495sample_1d_linear_mipmap_nearest( const struct gl_texture_object *tObj,
496 GLfloat s, GLfloat lambda,
497 GLubyte rgba[4] )
498{
499 GLint level;
500 if (lambda <= 0.5F)
501 lambda = 0.0F;
502 else if (lambda > tObj->M + 0.4999F)
503 lambda = tObj->M + 0.4999F;
504 level = (GLint) (tObj->BaseLevel + lambda + 0.5F);
505 if (level > tObj->P)
506 level = tObj->P;
507
508 sample_1d_linear( tObj, tObj->Image[level], s, rgba );
509}
510
511
512
513static void
514sample_1d_nearest_mipmap_linear( const struct gl_texture_object *tObj,
515 GLfloat s, GLfloat lambda,
516 GLubyte rgba[4] )
517{
518 GLint level;
519 if (lambda < 0.0F)
520 lambda = 0.0F;
521 else if (lambda > tObj->M)
522 lambda = tObj->M;
523 level = (GLint) (tObj->BaseLevel + lambda);
524
525 if (level >= tObj->P) {
526 sample_1d_nearest( tObj, tObj->Image[tObj->P], s, rgba );
527 }
528 else {
529 GLubyte t0[4], t1[4];
530 GLfloat f = myFrac(lambda);
531 sample_1d_nearest( tObj, tObj->Image[level ], s, t0 );
532 sample_1d_nearest( tObj, tObj->Image[level+1], s, t1 );
533 rgba[RCOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
534 rgba[GCOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
535 rgba[BCOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
536 rgba[ACOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
537 }
538}
539
540
541
542static void
543sample_1d_linear_mipmap_linear( const struct gl_texture_object *tObj,
544 GLfloat s, GLfloat lambda,
545 GLubyte rgba[4] )
546{
547 GLint level;
548 if (lambda < 0.0F)
549 lambda = 0.0F;
550 else if (lambda > tObj->M)
551 lambda = tObj->M;
552 level = (GLint) (tObj->BaseLevel + lambda);
553
554 if (level >= tObj->P) {
555 sample_1d_linear( tObj, tObj->Image[tObj->P], s, rgba );
556 }
557 else {
558 GLubyte t0[4], t1[4];
559 GLfloat f = myFrac(lambda);
560 sample_1d_linear( tObj, tObj->Image[level ], s, t0 );
561 sample_1d_linear( tObj, tObj->Image[level+1], s, t1 );
562 rgba[RCOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
563 rgba[GCOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
564 rgba[BCOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
565 rgba[ACOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
566 }
567}
568
569
570
571static void sample_nearest_1d( const struct gl_texture_object *tObj, GLuint n,
572 const GLfloat s[], const GLfloat t[],
573 const GLfloat u[], const GLfloat lambda[],
574 GLubyte rgba[][4] )
575{
576 GLuint i;
577 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
578 (void) t;
579 (void) u;
580 (void) lambda;
581 for (i=0;i<n;i++) {
582 sample_1d_nearest( tObj, image, s[i], rgba[i] );
583 }
584}
585
586
587
588static void sample_linear_1d( const struct gl_texture_object *tObj, GLuint n,
589 const GLfloat s[], const GLfloat t[],
590 const GLfloat u[], const GLfloat lambda[],
591 GLubyte rgba[][4] )
592{
593 GLuint i;
594 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
595 (void) t;
596 (void) u;
597 (void) lambda;
598 for (i=0;i<n;i++) {
599 sample_1d_linear( tObj, image, s[i], rgba[i] );
600 }
601}
602
603
604/*
605 * Given an (s) texture coordinate and lambda (level of detail) value,
606 * return a texture sample.
607 *
608 */
609static void sample_lambda_1d( const struct gl_texture_object *tObj, GLuint n,
610 const GLfloat s[], const GLfloat t[],
611 const GLfloat u[], const GLfloat lambda[],
612 GLubyte rgba[][4] )
613{
614 GLuint i;
615
616 (void) t;
617 (void) u;
618
619 for (i=0;i<n;i++) {
620 if (lambda[i] > tObj->MinMagThresh) {
621 /* minification */
622 switch (tObj->MinFilter) {
623 case GL_NEAREST:
624 sample_1d_nearest( tObj, tObj->Image[tObj->BaseLevel], s[i], rgba[i] );
625 break;
626 case GL_LINEAR:
627 sample_1d_linear( tObj, tObj->Image[tObj->BaseLevel], s[i], rgba[i] );
628 break;
629 case GL_NEAREST_MIPMAP_NEAREST:
630 sample_1d_nearest_mipmap_nearest( tObj, lambda[i], s[i], rgba[i] );
631 break;
632 case GL_LINEAR_MIPMAP_NEAREST:
633 sample_1d_linear_mipmap_nearest( tObj, s[i], lambda[i], rgba[i] );
634 break;
635 case GL_NEAREST_MIPMAP_LINEAR:
636 sample_1d_nearest_mipmap_linear( tObj, s[i], lambda[i], rgba[i] );
637 break;
638 case GL_LINEAR_MIPMAP_LINEAR:
639 sample_1d_linear_mipmap_linear( tObj, s[i], lambda[i], rgba[i] );
640 break;
641 default:
642 gl_problem(NULL, "Bad min filter in sample_1d_texture");
643 return;
644 }
645 }
646 else {
647 /* magnification */
648 switch (tObj->MagFilter) {
649 case GL_NEAREST:
650 sample_1d_nearest( tObj, tObj->Image[tObj->BaseLevel], s[i], rgba[i] );
651 break;
652 case GL_LINEAR:
653 sample_1d_linear( tObj, tObj->Image[tObj->BaseLevel], s[i], rgba[i] );
654 break;
655 default:
656 gl_problem(NULL, "Bad mag filter in sample_1d_texture");
657 return;
658 }
659 }
660 }
661}
662
663
664
665
666/**********************************************************************/
667/* 2-D Texture Sampling Functions */
668/**********************************************************************/
669
670
671/*
672 * Given a texture image and an (i,j) integer texel coordinate, return the
673 * texel color.
674 */
675static void get_2d_texel( const struct gl_texture_object *tObj,
676 const struct gl_texture_image *img, GLint i, GLint j,
677 GLubyte rgba[4] )
678{
679 const GLint width = img->Width; /* includes border */
680 const GLubyte *texel;
681
682#ifdef DEBUG
683 const GLint height = img->Height; /* includes border */
684 assert(i >= 0);
685 assert(i < width);
686 assert(j >= 0);
687 assert(j < height);
688#endif
689
690 switch (img->Format) {
691 case GL_COLOR_INDEX:
692 {
693 GLubyte index = img->Data[ width *j + i ];
694 palette_sample(tObj, index, rgba );
695 return;
696 }
697 case GL_ALPHA:
698 rgba[ACOMP] = img->Data[ width * j + i ];
699 return;
700 case GL_LUMINANCE:
701 case GL_INTENSITY:
702 rgba[RCOMP] = img->Data[ width * j + i ];
703 return;
704 case GL_LUMINANCE_ALPHA:
705 texel = img->Data + (width * j + i) * 2;
706 rgba[RCOMP] = texel[0];
707 rgba[ACOMP] = texel[1];
708 return;
709 case GL_RGB:
710 texel = img->Data + (width * j + i) * 3;
711 rgba[RCOMP] = texel[0];
712 rgba[GCOMP] = texel[1];
713 rgba[BCOMP] = texel[2];
714 return;
715 case GL_RGBA:
716 texel = img->Data + (width * j + i) * 4;
717 rgba[RCOMP] = texel[0];
718 rgba[GCOMP] = texel[1];
719 rgba[BCOMP] = texel[2];
720 rgba[ACOMP] = texel[3];
721 return;
722 default:
723 gl_problem(NULL, "Bad format in get_2d_texel");
724 }
725}
726
727
728
729/*
730 * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
731 */
732static void sample_2d_nearest( const struct gl_texture_object *tObj,
733 const struct gl_texture_image *img,
734 GLfloat s, GLfloat t,
735 GLubyte rgba[] )
736{
737 const GLint imgWidth = img->Width; /* includes border */
738 const GLint width = img->Width2; /* without border, power of two */
739 const GLint height = img->Height2; /* without border, power of two */
740 const GLubyte *texel;
741 GLint i, j;
742
743 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, s, width, i);
744 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, t, height, j);
745
746 /* skip over the border, if any */
747 i += img->Border;
748 j += img->Border;
749
750 switch (img->Format) {
751 case GL_COLOR_INDEX:
752 {
753 GLubyte index = img->Data[ j * imgWidth + i ];
754 palette_sample(tObj, index, rgba);
755 return;
756 }
757 case GL_ALPHA:
758 rgba[ACOMP] = img->Data[ j * imgWidth + i ];
759 return;
760 case GL_LUMINANCE:
761 case GL_INTENSITY:
762 rgba[RCOMP] = img->Data[ j * imgWidth + i ];
763 return;
764 case GL_LUMINANCE_ALPHA:
765 texel = img->Data + ((j * imgWidth + i) << 1);
766 rgba[RCOMP] = texel[0];
767 rgba[ACOMP] = texel[1];
768 return;
769 case GL_RGB:
770 texel = img->Data + (j * imgWidth + i) * 3;
771 rgba[RCOMP] = texel[0];
772 rgba[GCOMP] = texel[1];
773 rgba[BCOMP] = texel[2];
774 return;
775 case GL_RGBA:
776 texel = img->Data + ((j * imgWidth + i) << 2);
777 rgba[RCOMP] = texel[0];
778 rgba[GCOMP] = texel[1];
779 rgba[BCOMP] = texel[2];
780 rgba[ACOMP] = texel[3];
781 return;
782 default:
783 gl_problem(NULL, "Bad format in sample_2d_nearest");
784 }
785}
786
787
788
789/*
790 * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
791 * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
792 */
793static void sample_2d_linear( const struct gl_texture_object *tObj,
794 const struct gl_texture_image *img,
795 GLfloat s, GLfloat t,
796 GLubyte rgba[] )
797{
798 const GLint width = img->Width2;
799 const GLint height = img->Height2;
800 GLint i0, j0, i1, j1;
801 GLuint useBorderColor;
802 GLfloat u, v;
803
804 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, s, u, width, i0, i1);
805 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, t, v, height, j0, j1);
806
807 useBorderColor = 0;
808 if (img->Border) {
809 i0 += img->Border;
810 i1 += img->Border;
811 j0 += img->Border;
812 j1 += img->Border;
813 }
814 else {
815 if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
816 if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
817 if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT;
818 if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT;
819 }
820
821 {
822 GLfloat a = myFrac(u);
823 GLfloat b = myFrac(v);
824 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
825 GLint w00 = (GLint) ((1.0F-a)*(1.0F-b) * WEIGHT_SCALE + 0.5F);
826 GLint w10 = (GLint) ( a *(1.0F-b) * WEIGHT_SCALE + 0.5F);
827 GLint w01 = (GLint) ((1.0F-a)* b * WEIGHT_SCALE + 0.5F);
828 GLint w11 = (GLint) ( a * b * WEIGHT_SCALE + 0.5F);
829 GLubyte t00[4];
830 GLubyte t10[4];
831 GLubyte t01[4];
832 GLubyte t11[4];
833
834 if (useBorderColor & (I0BIT | J0BIT)) {
835 t00[RCOMP] = tObj->BorderColor[0];
836 t00[GCOMP] = tObj->BorderColor[1];
837 t00[BCOMP] = tObj->BorderColor[2];
838 t00[ACOMP] = tObj->BorderColor[3];
839 }
840 else {
841 get_2d_texel( tObj, img, i0, j0, t00 );
842 }
843 if (useBorderColor & (I1BIT | J0BIT)) {
844 t10[RCOMP] = tObj->BorderColor[0];
845 t10[GCOMP] = tObj->BorderColor[1];
846 t10[BCOMP] = tObj->BorderColor[2];
847 t10[ACOMP] = tObj->BorderColor[3];
848 }
849 else {
850 get_2d_texel( tObj, img, i1, j0, t10 );
851 }
852 if (useBorderColor & (I0BIT | J1BIT)) {
853 t01[RCOMP] = tObj->BorderColor[0];
854 t01[GCOMP] = tObj->BorderColor[1];
855 t01[BCOMP] = tObj->BorderColor[2];
856 t01[ACOMP] = tObj->BorderColor[3];
857 }
858 else {
859 get_2d_texel( tObj, img, i0, j1, t01 );
860 }
861 if (useBorderColor & (I1BIT | J1BIT)) {
862 t11[RCOMP] = tObj->BorderColor[0];
863 t11[GCOMP] = tObj->BorderColor[1];
864 t11[BCOMP] = tObj->BorderColor[2];
865 t11[ACOMP] = tObj->BorderColor[3];
866 }
867 else {
868 get_2d_texel( tObj, img, i1, j1, t11 );
869 }
870
871 rgba[0] = (GLubyte) ((w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0]) >> WEIGHT_SHIFT);
872 rgba[1] = (GLubyte) ((w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1]) >> WEIGHT_SHIFT);
873 rgba[2] = (GLubyte) ((w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2]) >> WEIGHT_SHIFT);
874 rgba[3] = (GLubyte) ((w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3]) >> WEIGHT_SHIFT);
875 }
876
877}
878
879
880
881static void
882sample_2d_nearest_mipmap_nearest( const struct gl_texture_object *tObj,
883 GLfloat s, GLfloat t, GLfloat lambda,
884 GLubyte rgba[4] )
885{
886 GLint level;
887 if (lambda <= 0.5F)
888 lambda = 0.0F;
889 else if (lambda > tObj->M + 0.4999F)
890 lambda = tObj->M + 0.4999F;
891 level = (GLint) (tObj->BaseLevel + lambda + 0.5F);
892 if (level > tObj->P)
893 level = tObj->P;
894
895 sample_2d_nearest( tObj, tObj->Image[level], s, t, rgba );
896}
897
898
899
900static void
901sample_2d_linear_mipmap_nearest( const struct gl_texture_object *tObj,
902 GLfloat s, GLfloat t, GLfloat lambda,
903 GLubyte rgba[4] )
904{
905 GLint level;
906 if (lambda <= 0.5F)
907 lambda = 0.0F;
908 else if (lambda > tObj->M + 0.4999F)
909 lambda = tObj->M + 0.4999F;
910 level = (GLint) (tObj->BaseLevel + lambda + 0.5F);
911 if (level > tObj->P)
912 level = tObj->P;
913
914 sample_2d_linear( tObj, tObj->Image[level], s, t, rgba );
915}
916
917
918
919static void
920sample_2d_nearest_mipmap_linear( const struct gl_texture_object *tObj,
921 GLfloat s, GLfloat t, GLfloat lambda,
922 GLubyte rgba[4] )
923{
924 GLint level;
925 if (lambda < 0.0F)
926 lambda = 0.0F;
927 else if (lambda > tObj->M)
928 lambda = tObj->M;
929 level = (GLint) (tObj->BaseLevel + lambda);
930
931 if (level >= tObj->P) {
932 sample_2d_nearest( tObj, tObj->Image[tObj->P], s, t, rgba );
933 }
934 else {
935 GLubyte t0[4], t1[4]; /* texels */
936 GLfloat f = myFrac(lambda);
937 sample_2d_nearest( tObj, tObj->Image[level ], s, t, t0 );
938 sample_2d_nearest( tObj, tObj->Image[level+1], s, t, t1 );
939 rgba[RCOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
940 rgba[GCOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
941 rgba[BCOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
942 rgba[ACOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
943 }
944}
945
946
947
948static void
949sample_2d_linear_mipmap_linear( const struct gl_texture_object *tObj,
950 GLfloat s, GLfloat t, GLfloat lambda,
951 GLubyte rgba[4] )
952{
953 GLint level;
954 if (lambda < 0.0F)
955 lambda = 0.0F;
956 else if (lambda > tObj->M)
957 lambda = tObj->M;
958 level = (GLint) (tObj->BaseLevel + lambda);
959
960 if (level >= tObj->P) {
961 sample_2d_linear( tObj, tObj->Image[tObj->P], s, t, rgba );
962 }
963 else {
964 GLubyte t0[4], t1[4]; /* texels */
965 GLfloat f = myFrac(lambda);
966 sample_2d_linear( tObj, tObj->Image[level ], s, t, t0 );
967 sample_2d_linear( tObj, tObj->Image[level+1], s, t, t1 );
968 rgba[RCOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
969 rgba[GCOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
970 rgba[BCOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
971 rgba[ACOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
972 }
973}
974
975
976
977static void sample_nearest_2d( const struct gl_texture_object *tObj, GLuint n,
978 const GLfloat s[], const GLfloat t[],
979 const GLfloat u[], const GLfloat lambda[],
980 GLubyte rgba[][4] )
981{
982 GLuint i;
983 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
984 (void) u;
985 (void) lambda;
986 for (i=0;i<n;i++) {
987 sample_2d_nearest( tObj, image, s[i], t[i], rgba[i] );
988 }
989}
990
991
992
993static void sample_linear_2d( const struct gl_texture_object *tObj, GLuint n,
994 const GLfloat s[], const GLfloat t[],
995 const GLfloat u[], const GLfloat lambda[],
996 GLubyte rgba[][4] )
997{
998 GLuint i;
999 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
1000 (void) u;
1001 (void) lambda;
1002 for (i=0;i<n;i++) {
1003 sample_2d_linear( tObj, image, s[i], t[i], rgba[i] );
1004 }
1005}
1006
1007
1008/*
1009 * Given an (s,t) texture coordinate and lambda (level of detail) value,
1010 * return a texture sample.
1011 */
1012static void sample_lambda_2d( const struct gl_texture_object *tObj,
1013 GLuint n,
1014 const GLfloat s[], const GLfloat t[],
1015 const GLfloat u[], const GLfloat lambda[],
1016 GLubyte rgba[][4] )
1017{
1018 GLuint i;
1019 (void) u;
1020 for (i=0;i<n;i++) {
1021 if (lambda[i] > tObj->MinMagThresh) {
1022 /* minification */
1023 switch (tObj->MinFilter) {
1024 case GL_NEAREST:
1025 sample_2d_nearest( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], rgba[i] );
1026 break;
1027 case GL_LINEAR:
1028 sample_2d_linear( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], rgba[i] );
1029 break;
1030 case GL_NEAREST_MIPMAP_NEAREST:
1031 sample_2d_nearest_mipmap_nearest( tObj, s[i], t[i], lambda[i], rgba[i] );
1032 break;
1033 case GL_LINEAR_MIPMAP_NEAREST:
1034 sample_2d_linear_mipmap_nearest( tObj, s[i], t[i], lambda[i], rgba[i] );
1035 break;
1036 case GL_NEAREST_MIPMAP_LINEAR:
1037 sample_2d_nearest_mipmap_linear( tObj, s[i], t[i], lambda[i], rgba[i] );
1038 break;
1039 case GL_LINEAR_MIPMAP_LINEAR:
1040 sample_2d_linear_mipmap_linear( tObj, s[i], t[i], lambda[i], rgba[i] );
1041 break;
1042 default:
1043 gl_problem(NULL, "Bad min filter in sample_2d_texture");
1044 return;
1045 }
1046 }
1047 else {
1048 /* magnification */
1049 switch (tObj->MagFilter) {
1050 case GL_NEAREST:
1051 sample_2d_nearest( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], rgba[i] );
1052 break;
1053 case GL_LINEAR:
1054 sample_2d_linear( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], rgba[i] );
1055 break;
1056 default:
1057 gl_problem(NULL, "Bad mag filter in sample_2d_texture");
1058 }
1059 }
1060 }
1061}
1062
1063
1064/*
1065 * Optimized 2-D texture sampling:
1066 * S and T wrap mode == GL_REPEAT
1067 * GL_NEAREST min/mag filter
1068 * No border
1069 * Format = GL_RGB
1070 */
1071static void opt_sample_rgb_2d( const struct gl_texture_object *tObj,
1072 GLuint n, const GLfloat s[], const GLfloat t[],
1073 const GLfloat u[], const GLfloat lambda[],
1074 GLubyte rgba[][4] )
1075{
1076 const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel];
1077 const GLfloat width = (GLfloat) img->Width;
1078 const GLfloat height = (GLfloat) img->Height;
1079 const GLint colMask = img->Width - 1;
1080 const GLint rowMask = img->Height - 1;
1081 const GLint shift = img->WidthLog2;
1082 GLuint k;
1083 (void) u;
1084 (void) lambda;
1085 ASSERT(tObj->WrapS==GL_REPEAT);
1086 ASSERT(tObj->WrapT==GL_REPEAT);
1087 ASSERT(tObj->MinFilter==GL_NEAREST);
1088 ASSERT(tObj->MagFilter==GL_NEAREST);
1089 ASSERT(img->Border==0);
1090 ASSERT(img->Format==GL_RGB);
1091
1092 /* NOTE: negative float->int doesn't floor, add 10000 as to work-around */
1093 for (k=0;k<n;k++) {
1094 GLint i = (GLint) ((s[k] + 10000.0) * width) & colMask;
1095 GLint j = (GLint) ((t[k] + 10000.0) * height) & rowMask;
1096 GLint pos = (j << shift) | i;
1097 GLubyte *texel = img->Data + pos + pos + pos; /* pos*3 */
1098 rgba[k][RCOMP] = texel[0];
1099 rgba[k][GCOMP] = texel[1];
1100 rgba[k][BCOMP] = texel[2];
1101 }
1102}
1103
1104
1105/*
1106 * Optimized 2-D texture sampling:
1107 * S and T wrap mode == GL_REPEAT
1108 * GL_NEAREST min/mag filter
1109 * No border
1110 * Format = GL_RGBA
1111 */
1112static void opt_sample_rgba_2d( const struct gl_texture_object *tObj,
1113 GLuint n, const GLfloat s[], const GLfloat t[],
1114 const GLfloat u[], const GLfloat lambda[],
1115 GLubyte rgba[][4] )
1116{
1117 const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel];
1118 const GLfloat width = (GLfloat) img->Width;
1119 const GLfloat height = (GLfloat) img->Height;
1120 const GLint colMask = img->Width - 1;
1121 const GLint rowMask = img->Height - 1;
1122 const GLint shift = img->WidthLog2;
1123 GLuint k;
1124 (void) u;
1125 (void) lambda;
1126 ASSERT(tObj->WrapS==GL_REPEAT);
1127 ASSERT(tObj->WrapT==GL_REPEAT);
1128 ASSERT(tObj->MinFilter==GL_NEAREST);
1129 ASSERT(tObj->MagFilter==GL_NEAREST);
1130 ASSERT(img->Border==0);
1131 ASSERT(img->Format==GL_RGBA);
1132
1133 /* NOTE: negative float->int doesn't floor, add 10000 as to work-around */
1134 for (k=0;k<n;k++) {
1135 GLint i = (GLint) ((s[k] + 10000.0) * width) & colMask;
1136 GLint j = (GLint) ((t[k] + 10000.0) * height) & rowMask;
1137 GLint pos = (j << shift) | i;
1138 GLubyte *texel = img->Data + (pos << 2); /* pos*4 */
1139 rgba[k][RCOMP] = texel[0];
1140 rgba[k][GCOMP] = texel[1];
1141 rgba[k][BCOMP] = texel[2];
1142 rgba[k][ACOMP] = texel[3];
1143 }
1144}
1145
1146
1147
1148/**********************************************************************/
1149/* 3-D Texture Sampling Functions */
1150/**********************************************************************/
1151
1152/*
1153 * Given a texture image and an (i,j,k) integer texel coordinate, return the
1154 * texel color.
1155 */
1156static void get_3d_texel( const struct gl_texture_object *tObj,
1157 const struct gl_texture_image *img,
1158 GLint i, GLint j, GLint k,
1159 GLubyte rgba[4] )
1160{
1161 const GLint width = img->Width; /* includes border */
1162 const GLint height = img->Height; /* includes border */
1163 const GLint rectarea = width * height;
1164 const GLubyte *texel;
1165
1166#ifdef DEBUG
1167 const GLint depth = img->Depth; /* includes border */
1168 assert(i >= 0);
1169 assert(i < width);
1170 assert(j >= 0);
1171 assert(j < height);
1172 assert(k >= 0);
1173 assert(k < depth);
1174#endif
1175
1176 switch (img->Format) {
1177 case GL_COLOR_INDEX:
1178 {
1179 GLubyte index = img->Data[ rectarea * k + width * j + i ];
1180 palette_sample(tObj, index, rgba );
1181 return;
1182 }
1183 case GL_ALPHA:
1184 rgba[ACOMP] = img->Data[ rectarea * k + width * j + i ];
1185 return;
1186 case GL_LUMINANCE:
1187 case GL_INTENSITY:
1188 rgba[RCOMP] = img->Data[ rectarea * k + width * j + i ];
1189 return;
1190 case GL_LUMINANCE_ALPHA:
1191 texel = img->Data + ( rectarea * k + width * j + i) * 2;
1192 rgba[RCOMP] = texel[0];
1193 rgba[ACOMP] = texel[1];
1194 return;
1195 case GL_RGB:
1196 texel = img->Data + (rectarea * k + width * j + i) * 3;
1197 rgba[RCOMP] = texel[0];
1198 rgba[GCOMP] = texel[1];
1199 rgba[BCOMP] = texel[2];
1200 return;
1201 case GL_RGBA:
1202 texel = img->Data + (rectarea * k + width * j + i) * 4;
1203 rgba[RCOMP] = texel[0];
1204 rgba[GCOMP] = texel[1];
1205 rgba[BCOMP] = texel[2];
1206 rgba[ACOMP] = texel[3];
1207 return;
1208 default:
1209 gl_problem(NULL, "Bad format in get_3d_texel");
1210 }
1211}
1212
1213
1214/*
1215 * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
1216 */
1217static void sample_3d_nearest( const struct gl_texture_object *tObj,
1218 const struct gl_texture_image *img,
1219 GLfloat s, GLfloat t, GLfloat r,
1220 GLubyte rgba[4] )
1221{
1222 const GLint imgWidth = img->Width; /* includes border, if any */
1223 const GLint imgHeight = img->Height; /* includes border, if any */
1224 const GLint width = img->Width2; /* without border, power of two */
1225 const GLint height = img->Height2; /* without border, power of two */
1226 const GLint depth = img->Depth2; /* without border, power of two */
1227 const GLint rectarea = imgWidth * imgHeight;
1228 const GLubyte *texel;
1229 GLint i, j, k;
1230
1231 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, s, width, i);
1232 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, t, height, j);
1233 COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapR, r, depth, k);
1234
1235 switch (tObj->Image[0]->Format) {
1236 case GL_COLOR_INDEX:
1237 {
1238 GLubyte index = img->Data[ rectarea * k + j * imgWidth + i ];
1239 palette_sample(tObj, index, rgba );
1240 return;
1241 }
1242 case GL_ALPHA:
1243 rgba[ACOMP] = img->Data[ rectarea * k + j * imgWidth + i ];
1244 return;
1245 case GL_LUMINANCE:
1246 case GL_INTENSITY:
1247 rgba[RCOMP] = img->Data[ rectarea * k + j * imgWidth + i ];
1248 return;
1249 case GL_LUMINANCE_ALPHA:
1250 texel = img->Data + ((rectarea * k + j * imgWidth + i) << 1);
1251 rgba[RCOMP] = texel[0];
1252 rgba[ACOMP] = texel[1];
1253 return;
1254 case GL_RGB:
1255 texel = img->Data + ( rectarea * k + j * imgWidth + i) * 3;
1256 rgba[RCOMP] = texel[0];
1257 rgba[GCOMP] = texel[1];
1258 rgba[BCOMP] = texel[2];
1259 return;
1260 case GL_RGBA:
1261 texel = img->Data + ((rectarea * k + j * imgWidth + i) << 2);
1262 rgba[RCOMP] = texel[0];
1263 rgba[GCOMP] = texel[1];
1264 rgba[BCOMP] = texel[2];
1265 rgba[ACOMP] = texel[3];
1266 return;
1267 default:
1268 gl_problem(NULL, "Bad format in sample_3d_nearest");
1269 }
1270}
1271
1272
1273
1274/*
1275 * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
1276 */
1277static void sample_3d_linear( const struct gl_texture_object *tObj,
1278 const struct gl_texture_image *img,
1279 GLfloat s, GLfloat t, GLfloat r,
1280 GLubyte rgba[4] )
1281{
1282 const GLint width = img->Width2;
1283 const GLint height = img->Height2;
1284 const GLint depth = img->Depth2;
1285 GLint i0, j0, k0, i1, j1, k1;
1286 GLuint useBorderColor;
1287 GLfloat u, v, w;
1288
1289 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, s, u, width, i0, i1);
1290 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, t, v, height, j0, j1);
1291 COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapR, r, w, depth, k0, k1);
1292
1293 useBorderColor = 0;
1294 if (img->Border) {
1295 i0 += img->Border;
1296 i1 += img->Border;
1297 j0 += img->Border;
1298 j1 += img->Border;
1299 k0 += img->Border;
1300 k1 += img->Border;
1301 }
1302 else {
1303 /* check if sampling texture border color */
1304 if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
1305 if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
1306 if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT;
1307 if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT;
1308 if (k0 < 0 || k0 >= depth) useBorderColor |= K0BIT;
1309 if (k1 < 0 || k1 >= depth) useBorderColor |= K1BIT;
1310 }
1311
1312 {
1313 GLfloat a = myFrac(u);
1314 GLfloat b = myFrac(v);
1315 GLfloat c = myFrac(w);
1316 /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
1317 GLint w000 = (GLint) ((1.0F-a)*(1.0F-b)*(1.0F-c) * WEIGHT_SCALE + 0.5F);
1318 GLint w100 = (GLint) ( a *(1.0F-b)*(1.0F-c) * WEIGHT_SCALE + 0.5F);
1319 GLint w010 = (GLint) ((1.0F-a)* b *(1.0F-c) * WEIGHT_SCALE + 0.5F);
1320 GLint w110 = (GLint) ( a * b *(1.0F-c) * WEIGHT_SCALE + 0.5F);
1321 GLint w001 = (GLint) ((1.0F-a)*(1.0F-b)* c * WEIGHT_SCALE + 0.5F);
1322 GLint w101 = (GLint) ( a *(1.0F-b)* c * WEIGHT_SCALE + 0.5F);
1323 GLint w011 = (GLint) ((1.0F-a)* b * c * WEIGHT_SCALE + 0.5F);
1324 GLint w111 = (GLint) ( a * b * c * WEIGHT_SCALE + 0.5F);
1325
1326 GLubyte t000[4], t010[4], t001[4], t011[4];
1327 GLubyte t100[4], t110[4], t101[4], t111[4];
1328
1329 if (useBorderColor & (I0BIT | J0BIT | K0BIT)) {
1330 t000[RCOMP] = tObj->BorderColor[0];
1331 t000[GCOMP] = tObj->BorderColor[1];
1332 t000[BCOMP] = tObj->BorderColor[2];
1333 t000[ACOMP] = tObj->BorderColor[3];
1334 }
1335 else {
1336 get_3d_texel( tObj, img, i0, j0, k0, t000 );
1337 }
1338 if (useBorderColor & (I1BIT | J0BIT | K0BIT)) {
1339 t100[RCOMP] = tObj->BorderColor[0];
1340 t100[GCOMP] = tObj->BorderColor[1];
1341 t100[BCOMP] = tObj->BorderColor[2];
1342 t100[ACOMP] = tObj->BorderColor[3];
1343 }
1344 else {
1345 get_3d_texel( tObj, img, i1, j0, k0, t100 );
1346 }
1347 if (useBorderColor & (I0BIT | J1BIT | K0BIT)) {
1348 t010[RCOMP] = tObj->BorderColor[0];
1349 t010[GCOMP] = tObj->BorderColor[1];
1350 t010[BCOMP] = tObj->BorderColor[2];
1351 t010[ACOMP] = tObj->BorderColor[3];
1352 }
1353 else {
1354 get_3d_texel( tObj, img, i0, j1, k0, t010 );
1355 }
1356 if (useBorderColor & (I1BIT | J1BIT | K0BIT)) {
1357 t110[RCOMP] = tObj->BorderColor[0];
1358 t110[GCOMP] = tObj->BorderColor[1];
1359 t110[BCOMP] = tObj->BorderColor[2];
1360 t110[ACOMP] = tObj->BorderColor[3];
1361 }
1362 else {
1363 get_3d_texel( tObj, img, i1, j1, k0, t110 );
1364 }
1365
1366 if (useBorderColor & (I0BIT | J0BIT | K1BIT)) {
1367 t001[RCOMP] = tObj->BorderColor[0];
1368 t001[GCOMP] = tObj->BorderColor[1];
1369 t001[BCOMP] = tObj->BorderColor[2];
1370 t001[ACOMP] = tObj->BorderColor[3];
1371 }
1372 else {
1373 get_3d_texel( tObj, img, i0, j0, k1, t001 );
1374 }
1375 if (useBorderColor & (I1BIT | J0BIT | K1BIT)) {
1376 t101[RCOMP] = tObj->BorderColor[0];
1377 t101[GCOMP] = tObj->BorderColor[1];
1378 t101[BCOMP] = tObj->BorderColor[2];
1379 t101[ACOMP] = tObj->BorderColor[3];
1380 }
1381 else {
1382 get_3d_texel( tObj, img, i1, j0, k1, t101 );
1383 }
1384 if (useBorderColor & (I0BIT | J1BIT | K1BIT)) {
1385 t011[RCOMP] = tObj->BorderColor[0];
1386 t011[GCOMP] = tObj->BorderColor[1];
1387 t011[BCOMP] = tObj->BorderColor[2];
1388 t011[ACOMP] = tObj->BorderColor[3];
1389 }
1390 else {
1391 get_3d_texel( tObj, img, i0, j1, k1, t011 );
1392 }
1393 if (useBorderColor & (I1BIT | J1BIT | K1BIT)) {
1394 t111[RCOMP] = tObj->BorderColor[0];
1395 t111[GCOMP] = tObj->BorderColor[1];
1396 t111[BCOMP] = tObj->BorderColor[2];
1397 t111[ACOMP] = tObj->BorderColor[3];
1398 }
1399 else {
1400 get_3d_texel( tObj, img, i1, j1, k1, t111 );
1401 }
1402
1403 rgba[0] = (GLubyte) (
1404 (w000*t000[0] + w010*t010[0] + w001*t001[0] + w011*t011[0] +
1405 w100*t100[0] + w110*t110[0] + w101*t101[0] + w111*t111[0] )
1406 >> WEIGHT_SHIFT);
1407 rgba[1] = (GLubyte) (
1408 (w000*t000[1] + w010*t010[1] + w001*t001[1] + w011*t011[1] +
1409 w100*t100[1] + w110*t110[1] + w101*t101[1] + w111*t111[1] )
1410 >> WEIGHT_SHIFT);
1411 rgba[2] = (GLubyte) (
1412 (w000*t000[2] + w010*t010[2] + w001*t001[2] + w011*t011[2] +
1413 w100*t100[2] + w110*t110[2] + w101*t101[2] + w111*t111[2] )
1414 >> WEIGHT_SHIFT);
1415 rgba[3] = (GLubyte) (
1416 (w000*t000[3] + w010*t010[3] + w001*t001[3] + w011*t011[3] +
1417 w100*t100[3] + w110*t110[3] + w101*t101[3] + w111*t111[3] )
1418 >> WEIGHT_SHIFT);
1419 }
1420}
1421
1422
1423
1424static void
1425sample_3d_nearest_mipmap_nearest( const struct gl_texture_object *tObj,
1426 GLfloat s, GLfloat t, GLfloat r,
1427 GLfloat lambda, GLubyte rgba[4] )
1428{
1429 GLint level;
1430 if (lambda <= 0.5F)
1431 lambda = 0.0F;
1432 else if (lambda > tObj->M + 0.4999F)
1433 lambda = tObj->M + 0.4999F;
1434 level = (GLint) (tObj->BaseLevel + lambda + 0.5F);
1435 if (level > tObj->P)
1436 level = tObj->P;
1437
1438 sample_3d_nearest( tObj, tObj->Image[level], s, t, r, rgba );
1439}
1440
1441
1442static void
1443sample_3d_linear_mipmap_nearest( const struct gl_texture_object *tObj,
1444 GLfloat s, GLfloat t, GLfloat r,
1445 GLfloat lambda, GLubyte rgba[4] )
1446{
1447 GLint level;
1448 if (lambda <= 0.5F)
1449 lambda = 0.0F;
1450 else if (lambda > tObj->M + 0.4999F)
1451 lambda = tObj->M + 0.4999F;
1452 level = (GLint) (tObj->BaseLevel + lambda + 0.5F);
1453 if (level > tObj->P)
1454 level = tObj->P;
1455
1456 sample_3d_linear( tObj, tObj->Image[level], s, t, r, rgba );
1457}
1458
1459
1460static void
1461sample_3d_nearest_mipmap_linear( const struct gl_texture_object *tObj,
1462 GLfloat s, GLfloat t, GLfloat r,
1463 GLfloat lambda, GLubyte rgba[4] )
1464{
1465 GLint level;
1466 if (lambda < 0.0F)
1467 lambda = 0.0F;
1468 else if (lambda > tObj->M)
1469 lambda = tObj->M;
1470 level = (GLint) (tObj->BaseLevel + lambda);
1471
1472 if (level >= tObj->P) {
1473 sample_3d_nearest( tObj, tObj->Image[tObj->P], s, t, r, rgba );
1474 }
1475 else {
1476 GLubyte t0[4], t1[4]; /* texels */
1477 GLfloat f = myFrac(lambda);
1478 sample_3d_nearest( tObj, tObj->Image[level ], s, t, r, t0 );
1479 sample_3d_nearest( tObj, tObj->Image[level+1], s, t, r, t1 );
1480 rgba[RCOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
1481 rgba[GCOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
1482 rgba[BCOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
1483 rgba[ACOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
1484 }
1485}
1486
1487
1488static void
1489sample_3d_linear_mipmap_linear( const struct gl_texture_object *tObj,
1490 GLfloat s, GLfloat t, GLfloat r,
1491 GLfloat lambda, GLubyte rgba[4] )
1492{
1493 GLint level;
1494 if (lambda < 0.0F)
1495 lambda = 0.0F;
1496 else if (lambda > tObj->M)
1497 lambda = tObj->M;
1498 level = (GLint) (tObj->BaseLevel + lambda);
1499
1500 if (level >= tObj->P) {
1501 sample_3d_linear( tObj, tObj->Image[tObj->P], s, t, r, rgba );
1502 }
1503 else {
1504 GLubyte t0[4], t1[4]; /* texels */
1505 GLfloat f = myFrac(lambda);
1506 sample_3d_linear( tObj, tObj->Image[level ], s, t, r, t0 );
1507 sample_3d_linear( tObj, tObj->Image[level+1], s, t, r, t1 );
1508 rgba[RCOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
1509 rgba[GCOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
1510 rgba[BCOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
1511 rgba[ACOMP] = (GLubyte) (GLint) ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
1512 }
1513}
1514
1515
1516static void sample_nearest_3d( const struct gl_texture_object *tObj, GLuint n,
1517 const GLfloat s[], const GLfloat t[],
1518 const GLfloat u[], const GLfloat lambda[],
1519 GLubyte rgba[][4] )
1520{
1521 GLuint i;
1522 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
1523 (void) lambda;
1524 for (i=0;i<n;i++) {
1525 sample_3d_nearest( tObj, image, s[i], t[i], u[i], rgba[i] );
1526 }
1527}
1528
1529
1530
1531static void sample_linear_3d( const struct gl_texture_object *tObj, GLuint n,
1532 const GLfloat s[], const GLfloat t[],
1533 const GLfloat u[], const GLfloat lambda[],
1534 GLubyte rgba[][4] )
1535{
1536 GLuint i;
1537 struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
1538 (void) lambda;
1539 for (i=0;i<n;i++) {
1540 sample_3d_linear( tObj, image, s[i], t[i], u[i], rgba[i] );
1541 }
1542}
1543
1544
1545/*
1546 * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
1547 * return a texture sample.
1548 */
1549static void sample_lambda_3d( const struct gl_texture_object *tObj, GLuint n,
1550 const GLfloat s[], const GLfloat t[],
1551 const GLfloat u[], const GLfloat lambda[],
1552 GLubyte rgba[][4] )
1553{
1554 GLuint i;
1555
1556 for (i=0;i<n;i++) {
1557
1558 if (lambda[i] > tObj->MinMagThresh) {
1559 /* minification */
1560 switch (tObj->MinFilter) {
1561 case GL_NEAREST:
1562 sample_3d_nearest( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], u[i], rgba[i] );
1563 break;
1564 case GL_LINEAR:
1565 sample_3d_linear( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], u[i], rgba[i] );
1566 break;
1567 case GL_NEAREST_MIPMAP_NEAREST:
1568 sample_3d_nearest_mipmap_nearest( tObj, s[i], t[i], u[i], lambda[i], rgba[i] );
1569 break;
1570 case GL_LINEAR_MIPMAP_NEAREST:
1571 sample_3d_linear_mipmap_nearest( tObj, s[i], t[i], u[i], lambda[i], rgba[i] );
1572 break;
1573 case GL_NEAREST_MIPMAP_LINEAR:
1574 sample_3d_nearest_mipmap_linear( tObj, s[i], t[i], u[i], lambda[i], rgba[i] );
1575 break;
1576 case GL_LINEAR_MIPMAP_LINEAR:
1577 sample_3d_linear_mipmap_linear( tObj, s[i], t[i], u[i], lambda[i], rgba[i] );
1578 break;
1579 default:
1580 gl_problem(NULL, "Bad min filterin sample_3d_texture");
1581 }
1582 }
1583 else {
1584 /* magnification */
1585 switch (tObj->MagFilter) {
1586 case GL_NEAREST:
1587 sample_3d_nearest( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], u[i], rgba[i] );
1588 break;
1589 case GL_LINEAR:
1590 sample_3d_linear( tObj, tObj->Image[tObj->BaseLevel], s[i], t[i], u[i], rgba[i] );
1591 break;
1592 default:
1593 gl_problem(NULL, "Bad mag filter in sample_3d_texture");
1594 }
1595 }
1596 }
1597}
1598
1599
1600
1601/**********************************************************************/
1602/* Texture Sampling Setup */
1603/**********************************************************************/
1604
1605
1606/*
1607 * Setup the texture sampling function for this texture object.
1608 */
1609void gl_set_texture_sampler( struct gl_texture_object *t )
1610{
1611 if (!t->Complete) {
1612 t->SampleFunc = NULL;
1613 }
1614 else {
1615 GLboolean needLambda = (GLboolean) (t->MinFilter != t->MagFilter);
1616
1617 if (needLambda) {
1618 /* Compute min/mag filter threshold */
1619 if (t->MagFilter==GL_LINEAR
1620 && (t->MinFilter==GL_NEAREST_MIPMAP_NEAREST ||
1621 t->MinFilter==GL_LINEAR_MIPMAP_NEAREST)) {
1622 t->MinMagThresh = 0.5F;
1623 }
1624 else {
1625 t->MinMagThresh = 0.0F;
1626 }
1627 }
1628
1629 switch (t->Dimensions) {
1630 case 1:
1631 if (needLambda) {
1632 t->SampleFunc = sample_lambda_1d;
1633 }
1634 else if (t->MinFilter==GL_LINEAR) {
1635 t->SampleFunc = sample_linear_1d;
1636 }
1637 else {
1638 ASSERT(t->MinFilter==GL_NEAREST);
1639 t->SampleFunc = sample_nearest_1d;
1640 }
1641 break;
1642 case 2:
1643 if (needLambda) {
1644 t->SampleFunc = sample_lambda_2d;
1645 }
1646 else if (t->MinFilter==GL_LINEAR) {
1647 t->SampleFunc = sample_linear_2d;
1648 }
1649 else {
1650 ASSERT(t->MinFilter==GL_NEAREST);
1651 if (t->WrapS==GL_REPEAT && t->WrapT==GL_REPEAT
1652 && t->Image[0]->Border==0 && t->Image[0]->Format==GL_RGB) {
1653 t->SampleFunc = opt_sample_rgb_2d;
1654 }
1655 else if (t->WrapS==GL_REPEAT && t->WrapT==GL_REPEAT
1656 && t->Image[0]->Border==0 && t->Image[0]->Format==GL_RGBA) {
1657 t->SampleFunc = opt_sample_rgba_2d;
1658 }
1659 else
1660 t->SampleFunc = sample_nearest_2d;
1661 }
1662 break;
1663 case 3:
1664 if (needLambda) {
1665 t->SampleFunc = sample_lambda_3d;
1666 }
1667 else if (t->MinFilter==GL_LINEAR) {
1668 t->SampleFunc = sample_linear_3d;
1669 }
1670 else {
1671 ASSERT(t->MinFilter==GL_NEAREST);
1672 t->SampleFunc = sample_nearest_3d;
1673 }
1674 break;
1675 default:
1676 gl_problem(NULL, "invalid dimensions in gl_set_texture_sampler");
1677 }
1678 }
1679}
1680
1681
1682
1683/**********************************************************************/
1684/* Texture Application */
1685/**********************************************************************/
1686
1687
1688/*
1689 * Combine incoming fragment color with texel color to produce output color.
1690 * Input: textureUnit - pointer to texture unit to apply
1691 * format - base internal texture format
1692 * n - number of fragments
1693 * texels - array of texel colors
1694 * InOut: rgba - incoming fragment colors modified by texel colors
1695 * according to the texture environment mode.
1696 */
1697
1698
1699static void apply_texture( const GLcontext *ctx,
1700 const struct gl_texture_unit *texUnit,
1701 GLuint n,
1702 GLubyte rgba[][4], CONST GLubyte texel[][4] )
1703{
1704 GLuint i;
1705 GLint Rc, Gc, Bc, Ac;
1706 GLenum format;
1707
1708/*
1709 * Use (A*(B+1)) >> 8 as a fast approximation of (A*B)/255 for A
1710 * and B in [0,255]
1711 */
1712
1713#define PROD(A,B) ( (GLubyte) (((GLint)(A) * ((GLint)(B)+1)) >> 8) )
1714
1715 ASSERT(texUnit);
1716 ASSERT(texUnit->Current);
1717 ASSERT(texUnit->Current->Image[0]);
1718
1719 format = texUnit->Current->Image[0]->Format;
1720
1721 if (format==GL_COLOR_INDEX) {
1722 format = GL_RGBA; /* XXXX a hack! */
1723 }
1724
1725 switch (texUnit->EnvMode) {
1726 case GL_REPLACE:
1727 switch (format) {
1728 case GL_ALPHA:
1729 for (i=0;i<n;i++) {
1730 /* Cv = Cf */
1731 /* Av = At */
1732 rgba[i][ACOMP] = texel[i][ACOMP];
1733 }
1734 break;
1735 case GL_LUMINANCE:
1736 for (i=0;i<n;i++) {
1737 /* Cv = Lt */
1738 GLubyte Lt = texel[i][RCOMP];
1739 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
1740 /* Av = Af */
1741 }
1742 break;
1743 case GL_LUMINANCE_ALPHA:
1744 for (i=0;i<n;i++) {
1745 GLubyte Lt = texel[i][RCOMP];
1746 /* Cv = Lt */
1747 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
1748 /* Av = At */
1749 rgba[i][ACOMP] = texel[i][ACOMP];
1750 }
1751 break;
1752 case GL_INTENSITY:
1753 for (i=0;i<n;i++) {
1754 /* Cv = It */
1755 GLubyte It = texel[i][RCOMP];
1756 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = It;
1757 /* Av = It */
1758 rgba[i][ACOMP] = It;
1759 }
1760 break;
1761 case GL_RGB:
1762 for (i=0;i<n;i++) {
1763 /* Cv = Ct */
1764 rgba[i][RCOMP] = texel[i][RCOMP];
1765 rgba[i][GCOMP] = texel[i][GCOMP];
1766 rgba[i][BCOMP] = texel[i][BCOMP];
1767 /* Av = Af */
1768 }
1769 break;
1770 case GL_RGBA:
1771 for (i=0;i<n;i++) {
1772 /* Cv = Ct */
1773 rgba[i][RCOMP] = texel[i][RCOMP];
1774 rgba[i][GCOMP] = texel[i][GCOMP];
1775 rgba[i][BCOMP] = texel[i][BCOMP];
1776 /* Av = At */
1777 rgba[i][ACOMP] = texel[i][ACOMP];
1778 }
1779 break;
1780 default:
1781 gl_problem(ctx, "Bad format in apply_texture");
1782 return;
1783 }
1784 break;
1785
1786 case GL_MODULATE:
1787 switch (format) {
1788 case GL_ALPHA:
1789 for (i=0;i<n;i++) {
1790 /* Cv = Cf */
1791 /* Av = AfAt */
1792 rgba[i][ACOMP] = PROD( rgba[i][ACOMP], texel[i][ACOMP] );
1793 }
1794 break;
1795 case GL_LUMINANCE:
1796 for (i=0;i<n;i++) {
1797 /* Cv = LtCf */
1798 GLubyte Lt = texel[i][RCOMP];
1799 rgba[i][RCOMP] = PROD( rgba[i][RCOMP], Lt );
1800 rgba[i][GCOMP] = PROD( rgba[i][GCOMP], Lt );
1801 rgba[i][BCOMP] = PROD( rgba[i][BCOMP], Lt );
1802 /* Av = Af */
1803 }
1804 break;
1805 case GL_LUMINANCE_ALPHA:
1806 for (i=0;i<n;i++) {
1807 /* Cv = CfLt */
1808 GLubyte Lt = texel[i][RCOMP];
1809 rgba[i][RCOMP] = PROD( rgba[i][RCOMP], Lt );
1810 rgba[i][GCOMP] = PROD( rgba[i][GCOMP], Lt );
1811 rgba[i][BCOMP] = PROD( rgba[i][BCOMP], Lt );
1812 /* Av = AfAt */
1813 rgba[i][ACOMP] = PROD( rgba[i][ACOMP], texel[i][ACOMP] );
1814 }
1815 break;
1816 case GL_INTENSITY:
1817 for (i=0;i<n;i++) {
1818 /* Cv = CfIt */
1819 GLubyte It = texel[i][RCOMP];
1820 rgba[i][RCOMP] = PROD( rgba[i][RCOMP], It );
1821 rgba[i][GCOMP] = PROD( rgba[i][GCOMP], It );
1822 rgba[i][BCOMP] = PROD( rgba[i][BCOMP], It );
1823 /* Av = AfIt */
1824 rgba[i][ACOMP] = PROD( rgba[i][ACOMP], It );
1825 }
1826 break;
1827 case GL_RGB:
1828 for (i=0;i<n;i++) {
1829 /* Cv = CfCt */
1830 rgba[i][RCOMP] = PROD( rgba[i][RCOMP], texel[i][RCOMP] );
1831 rgba[i][GCOMP] = PROD( rgba[i][GCOMP], texel[i][GCOMP] );
1832 rgba[i][BCOMP] = PROD( rgba[i][BCOMP], texel[i][BCOMP] );
1833 /* Av = Af */
1834 }
1835 break;
1836 case GL_RGBA:
1837 for (i=0;i<n;i++) {
1838 /* Cv = CfCt */
1839 rgba[i][RCOMP] = PROD( rgba[i][RCOMP], texel[i][RCOMP] );
1840 rgba[i][GCOMP] = PROD( rgba[i][GCOMP], texel[i][GCOMP] );
1841 rgba[i][BCOMP] = PROD( rgba[i][BCOMP], texel[i][BCOMP] );
1842 /* Av = AfAt */
1843 rgba[i][ACOMP] = PROD( rgba[i][ACOMP], texel[i][ACOMP] );
1844 }
1845 break;
1846 default:
1847 gl_problem(ctx, "Bad format (2) in apply_texture");
1848 return;
1849 }
1850 break;
1851
1852 case GL_DECAL:
1853 switch (format) {
1854 case GL_ALPHA:
1855 case GL_LUMINANCE:
1856 case GL_LUMINANCE_ALPHA:
1857 case GL_INTENSITY:
1858 /* undefined */
1859 break;
1860 case GL_RGB:
1861 for (i=0;i<n;i++) {
1862 /* Cv = Ct */
1863 rgba[i][RCOMP] = texel[i][RCOMP];
1864 rgba[i][GCOMP] = texel[i][GCOMP];
1865 rgba[i][BCOMP] = texel[i][BCOMP];
1866 /* Av = Af */
1867 }
1868 break;
1869 case GL_RGBA:
1870 for (i=0;i<n;i++) {
1871 /* Cv = Cf(1-At) + CtAt */
1872 GLint t = texel[i][ACOMP], s = 255 - t;
1873 rgba[i][RCOMP] = PROD(rgba[i][RCOMP], s) + PROD(texel[i][RCOMP],t);
1874 rgba[i][GCOMP] = PROD(rgba[i][GCOMP], s) + PROD(texel[i][GCOMP],t);
1875 rgba[i][BCOMP] = PROD(rgba[i][BCOMP], s) + PROD(texel[i][BCOMP],t);
1876 /* Av = Af */
1877 }
1878 break;
1879 default:
1880 gl_problem(ctx, "Bad format (3) in apply_texture");
1881 return;
1882 }
1883 break;
1884
1885 case GL_BLEND:
1886 Rc = (GLint) (texUnit->EnvColor[0] * 255.0F);
1887 Gc = (GLint) (texUnit->EnvColor[1] * 255.0F);
1888 Bc = (GLint) (texUnit->EnvColor[2] * 255.0F);
1889 Ac = (GLint) (texUnit->EnvColor[3] * 255.0F);
1890 switch (format) {
1891 case GL_ALPHA:
1892 for (i=0;i<n;i++) {
1893 /* Cv = Cf */
1894 /* Av = AfAt */
1895 rgba[i][ACOMP] = PROD(rgba[i][ACOMP], texel[i][ACOMP]);
1896 }
1897 break;
1898 case GL_LUMINANCE:
1899 for (i=0;i<n;i++) {
1900 /* Cv = Cf(1-Lt) + CcLt */
1901 GLubyte Lt = texel[i][RCOMP], s = 255 - Lt;
1902 rgba[i][RCOMP] = PROD(rgba[i][RCOMP], s) + PROD(Rc, Lt);
1903 rgba[i][GCOMP] = PROD(rgba[i][GCOMP], s) + PROD(Gc, Lt);
1904 rgba[i][BCOMP] = PROD(rgba[i][BCOMP], s) + PROD(Bc, Lt);
1905 /* Av = Af */
1906 }
1907 break;
1908 case GL_LUMINANCE_ALPHA:
1909 for (i=0;i<n;i++) {
1910 /* Cv = Cf(1-Lt) + CcLt */
1911 GLubyte Lt = texel[i][RCOMP], s = 255 - Lt;
1912 rgba[i][RCOMP] = PROD(rgba[i][RCOMP], s) + PROD(Rc, Lt);
1913 rgba[i][GCOMP] = PROD(rgba[i][GCOMP], s) + PROD(Gc, Lt);
1914 rgba[i][BCOMP] = PROD(rgba[i][BCOMP], s) + PROD(Bc, Lt);
1915 /* Av = AfAt */
1916 rgba[i][ACOMP] = PROD(rgba[i][ACOMP],texel[i][ACOMP]);
1917 }
1918 break;
1919 case GL_INTENSITY:
1920 for (i=0;i<n;i++) {
1921 /* Cv = Cf(1-It) + CcLt */
1922 GLubyte It = texel[i][RCOMP], s = 255 - It;
1923 rgba[i][RCOMP] = PROD(rgba[i][RCOMP], s) + PROD(Rc, It);
1924 rgba[i][GCOMP] = PROD(rgba[i][GCOMP], s) + PROD(Gc, It);
1925 rgba[i][BCOMP] = PROD(rgba[i][BCOMP], s) + PROD(Bc, It);
1926 /* Av = Af(1-It) + Ac*It */
1927 rgba[i][ACOMP] = PROD(rgba[i][ACOMP], s) + PROD(Ac, It);
1928 }
1929 break;
1930 case GL_RGB:
1931 for (i=0;i<n;i++) {
1932 /* Cv = Cf(1-Ct) + CcCt */
1933 rgba[i][RCOMP] = PROD(rgba[i][RCOMP], (255-texel[i][RCOMP])) + PROD(Rc,texel[i][RCOMP]);
1934 rgba[i][GCOMP] = PROD(rgba[i][GCOMP], (255-texel[i][GCOMP])) + PROD(Gc,texel[i][GCOMP]);
1935 rgba[i][BCOMP] = PROD(rgba[i][BCOMP], (255-texel[i][BCOMP])) + PROD(Bc,texel[i][BCOMP]);
1936 /* Av = Af */
1937 }
1938 break;
1939 case GL_RGBA:
1940 for (i=0;i<n;i++) {
1941 /* Cv = Cf(1-Ct) + CcCt */
1942 rgba[i][RCOMP] = PROD(rgba[i][RCOMP], (255-texel[i][RCOMP])) + PROD(Rc,texel[i][RCOMP]);
1943 rgba[i][GCOMP] = PROD(rgba[i][GCOMP], (255-texel[i][GCOMP])) + PROD(Gc,texel[i][GCOMP]);
1944 rgba[i][BCOMP] = PROD(rgba[i][BCOMP], (255-texel[i][BCOMP])) + PROD(Bc,texel[i][BCOMP]);
1945 /* Av = AfAt */
1946 rgba[i][ACOMP] = PROD(rgba[i][ACOMP],texel[i][ACOMP]);
1947 }
1948 break;
1949 default:
1950 gl_problem(ctx, "Bad format (4) in apply_texture");
1951 return;
1952 }
1953 break;
1954
1955 default:
1956 gl_problem(ctx, "Bad env mode in apply_texture");
1957 return;
1958 }
1959#undef PROD
1960}
1961
1962
1963
1964/*
1965 * Apply a unit of texture mapping to the incoming fragments.
1966 */
1967void gl_texture_pixels( GLcontext *ctx, GLuint texUnit, GLuint n,
1968 const GLfloat s[], const GLfloat t[],
1969 const GLfloat r[], GLfloat lambda[],
1970 GLubyte rgba[][4] )
1971{
1972 GLuint mask = (TEXTURE0_1D | TEXTURE0_2D | TEXTURE0_3D) << (texUnit * 4);
1973 if (ctx->Texture.Enabled & mask) {
1974 const struct gl_texture_unit *textureUnit = &ctx->Texture.Unit[texUnit];
1975 if (textureUnit->Current && textureUnit->Current->SampleFunc) {
1976
1977 GLubyte texel[PB_SIZE][4];
1978
1979 if (textureUnit->Current->MinLod != -1000.0
1980 || textureUnit->Current->MaxLod != 1000.0) {
1981 /* apply LOD clamping to lambda */
1982 GLfloat min = textureUnit->Current->MinLod;
1983 GLfloat max = textureUnit->Current->MaxLod;
1984 GLuint i;
1985 for (i=0;i<n;i++) {
1986 GLfloat l = lambda[i];
1987 lambda[i] = CLAMP(l, min, max);
1988 }
1989 }
1990
1991 /* Sample the texture. */
1992 (*textureUnit->Current->SampleFunc)( textureUnit->Current, n,
1993 s, t, r, lambda, texel );
1994
1995 apply_texture( ctx, textureUnit, n,
1996 rgba, (const GLubyte (*)[4])texel );
1997 }
1998 }
1999}
2000
2001/*
2002 * After state changes to texturing we call this function to update
2003 * intermediate and derived state.
2004 * Called by gl_update_state().
2005 */
2006void gl_update_texture_unit( GLcontext *ctx, struct gl_texture_unit *texUnit )
2007{
2008 (void) ctx;
2009
2010 if ((texUnit->Enabled & TEXTURE0_3D) && texUnit->CurrentD[3]->Complete) {
2011 texUnit->ReallyEnabled = TEXTURE0_3D;
2012 texUnit->Current = texUnit->CurrentD[3];
2013 texUnit->CurrentDimension = 3;
2014 }
2015 else if ((texUnit->Enabled & TEXTURE0_2D) && texUnit->CurrentD[2]->Complete) {
2016 texUnit->ReallyEnabled = TEXTURE0_2D;
2017 texUnit->Current = texUnit->CurrentD[2];
2018 texUnit->CurrentDimension = 2;
2019 }
2020 else if ((texUnit->Enabled & TEXTURE0_1D) && texUnit->CurrentD[1]->Complete) {
2021 texUnit->ReallyEnabled = TEXTURE0_1D;
2022 texUnit->Current = texUnit->CurrentD[1];
2023 texUnit->CurrentDimension = 1;
2024 }
2025 else {
2026 /* if (MESA_VERBOSE & VERBOSE_TEXTURE) {
2027 switch (texUnit->Enabled) {
2028 case TEXTURE0_3D:
2029 fprintf(stderr, "Using incomplete 3d texture %u\n",
2030 texUnit->CurrentD[3]->Name);
2031 break;
2032 case TEXTURE0_2D:
2033 fprintf(stderr, "Using incomplete 2d texture %u\n",
2034 texUnit->CurrentD[2]->Name);
2035 break;
2036 case TEXTURE0_1D:
2037 fprintf(stderr, "Using incomplete 1d texture %u\n",
2038 texUnit->CurrentD[1]->Name);
2039 break;
2040 default:
2041 fprintf(stderr, "Bad value for texUnit->Enabled %x\n",
2042 texUnit->Enabled);
2043 break;
2044 }
2045 }*/
2046
2047 texUnit->ReallyEnabled = 0;
2048 texUnit->Current = NULL;
2049 texUnit->CurrentDimension = 0;
2050 return;
2051 }
2052
2053 texUnit->GenFlags = 0;
2054
2055 if (texUnit->TexGenEnabled) {
2056 GLuint sz = 0;
2057
2058 if (texUnit->TexGenEnabled & S_BIT) {
2059 sz = 1;
2060 texUnit->GenFlags |= texUnit->GenBitS;
2061 }
2062 if (texUnit->TexGenEnabled & T_BIT) {
2063 sz = 2;
2064 texUnit->GenFlags |= texUnit->GenBitT;
2065 }
2066 if (texUnit->TexGenEnabled & Q_BIT) {
2067 sz = 3;
2068 texUnit->GenFlags |= texUnit->GenBitQ;
2069 }
2070 if (texUnit->TexGenEnabled & R_BIT) {
2071 sz = 4;
2072 texUnit->GenFlags |= texUnit->GenBitR;
2073 }
2074
2075 texUnit->TexgenSize = sz;
2076 texUnit->Holes = (GLubyte) (all_bits[sz] & ~texUnit->TexGenEnabled);
2077 texUnit->func = texgen_generic_tab;
2078
2079 if (texUnit->TexGenEnabled == (S_BIT|T_BIT|R_BIT)) {
2080 if (texUnit->GenFlags == TEXGEN_REFLECTION_MAP_NV) {
2081 texUnit->func = texgen_reflection_map_nv_tab;
2082 }
2083 else if (texUnit->GenFlags == TEXGEN_NORMAL_MAP_NV) {
2084 texUnit->func = texgen_normal_map_nv_tab;
2085 }
2086 }
2087 else if (texUnit->TexGenEnabled == (S_BIT|T_BIT) &&
2088 texUnit->GenFlags == TEXGEN_SPHERE_MAP) {
2089 texUnit->func = texgen_sphere_map_tab;
2090 }
2091 }
2092}
Note: See TracBrowser for help on using the repository browser.