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

Last change on this file since 3830 was 3598, checked in by jeroen, 25 years ago

* empty log message *

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