mesa: use enums for TEXTURE_x_INDEX values
[mesa.git] / src / mesa / main / texstate.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.1
4 *
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file texstate.c
27 *
28 * Texture state handling.
29 */
30
31 #include "glheader.h"
32 #include "colormac.h"
33 #if FEATURE_colortable
34 #include "colortab.h"
35 #endif
36 #include "context.h"
37 #include "enums.h"
38 #include "macros.h"
39 #include "texcompress.h"
40 #include "texobj.h"
41 #include "teximage.h"
42 #include "texstate.h"
43 #include "texenvprogram.h"
44 #include "mtypes.h"
45
46
47
48 /**
49 * Default texture combine environment state. This is used to initialize
50 * a context's texture units and as the basis for converting "classic"
51 * texture environmnets to ARB_texture_env_combine style values.
52 */
53 static const struct gl_tex_env_combine_state default_combine_state = {
54 GL_MODULATE, GL_MODULATE,
55 { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT, GL_CONSTANT },
56 { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT, GL_CONSTANT },
57 { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_ALPHA, GL_SRC_ALPHA },
58 { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA },
59 0, 0,
60 2, 2
61 };
62
63
64
65 /**
66 * Used by glXCopyContext to copy texture state from one context to another.
67 */
68 void
69 _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
70 {
71 GLuint i, tex;
72
73 ASSERT(src);
74 ASSERT(dst);
75
76 dst->Texture.CurrentUnit = src->Texture.CurrentUnit;
77 dst->Texture._GenFlags = src->Texture._GenFlags;
78 dst->Texture._TexGenEnabled = src->Texture._TexGenEnabled;
79 dst->Texture._TexMatEnabled = src->Texture._TexMatEnabled;
80 dst->Texture.SharedPalette = src->Texture.SharedPalette;
81
82 /* per-unit state */
83 for (i = 0; i < src->Const.MaxTextureImageUnits; i++) {
84 dst->Texture.Unit[i].Enabled = src->Texture.Unit[i].Enabled;
85 dst->Texture.Unit[i].EnvMode = src->Texture.Unit[i].EnvMode;
86 COPY_4V(dst->Texture.Unit[i].EnvColor, src->Texture.Unit[i].EnvColor);
87 dst->Texture.Unit[i].TexGenEnabled = src->Texture.Unit[i].TexGenEnabled;
88 dst->Texture.Unit[i].GenS = src->Texture.Unit[i].GenS;
89 dst->Texture.Unit[i].GenT = src->Texture.Unit[i].GenT;
90 dst->Texture.Unit[i].GenR = src->Texture.Unit[i].GenR;
91 dst->Texture.Unit[i].GenQ = src->Texture.Unit[i].GenQ;
92 dst->Texture.Unit[i].LodBias = src->Texture.Unit[i].LodBias;
93
94 /* GL_EXT_texture_env_combine */
95 dst->Texture.Unit[i].Combine.ModeRGB = src->Texture.Unit[i].Combine.ModeRGB;
96 dst->Texture.Unit[i].Combine.ModeA = src->Texture.Unit[i].Combine.ModeA;
97 COPY_3V(dst->Texture.Unit[i].Combine.SourceRGB, src->Texture.Unit[i].Combine.SourceRGB);
98 COPY_3V(dst->Texture.Unit[i].Combine.SourceA, src->Texture.Unit[i].Combine.SourceA);
99 COPY_3V(dst->Texture.Unit[i].Combine.OperandRGB, src->Texture.Unit[i].Combine.OperandRGB);
100 COPY_3V(dst->Texture.Unit[i].Combine.OperandA, src->Texture.Unit[i].Combine.OperandA);
101 dst->Texture.Unit[i].Combine.ScaleShiftRGB = src->Texture.Unit[i].Combine.ScaleShiftRGB;
102 dst->Texture.Unit[i].Combine.ScaleShiftA = src->Texture.Unit[i].Combine.ScaleShiftA;
103
104 /* copy texture object bindings, not contents of texture objects */
105 _mesa_lock_context_textures(dst);
106
107 for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
108 _mesa_reference_texobj(&dst->Texture.Unit[i].CurrentTex[tex],
109 src->Texture.Unit[i].CurrentTex[tex]);
110 }
111
112 _mesa_unlock_context_textures(dst);
113 }
114 }
115
116
117 /*
118 * For debugging
119 */
120 void
121 _mesa_print_texunit_state( GLcontext *ctx, GLuint unit )
122 {
123 const struct gl_texture_unit *texUnit = ctx->Texture.Unit + unit;
124 _mesa_printf("Texture Unit %d\n", unit);
125 _mesa_printf(" GL_TEXTURE_ENV_MODE = %s\n", _mesa_lookup_enum_by_nr(texUnit->EnvMode));
126 _mesa_printf(" GL_COMBINE_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeRGB));
127 _mesa_printf(" GL_COMBINE_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeA));
128 _mesa_printf(" GL_SOURCE0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[0]));
129 _mesa_printf(" GL_SOURCE1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[1]));
130 _mesa_printf(" GL_SOURCE2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[2]));
131 _mesa_printf(" GL_SOURCE0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[0]));
132 _mesa_printf(" GL_SOURCE1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[1]));
133 _mesa_printf(" GL_SOURCE2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[2]));
134 _mesa_printf(" GL_OPERAND0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[0]));
135 _mesa_printf(" GL_OPERAND1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[1]));
136 _mesa_printf(" GL_OPERAND2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[2]));
137 _mesa_printf(" GL_OPERAND0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[0]));
138 _mesa_printf(" GL_OPERAND1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[1]));
139 _mesa_printf(" GL_OPERAND2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[2]));
140 _mesa_printf(" GL_RGB_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftRGB);
141 _mesa_printf(" GL_ALPHA_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftA);
142 _mesa_printf(" GL_TEXTURE_ENV_COLOR = (%f, %f, %f, %f)\n", texUnit->EnvColor[0], texUnit->EnvColor[1], texUnit->EnvColor[2], texUnit->EnvColor[3]);
143 }
144
145
146
147 /**********************************************************************/
148 /* Texture Environment */
149 /**********************************************************************/
150
151 /**
152 * Convert "classic" texture environment to ARB_texture_env_combine style
153 * environments.
154 *
155 * \param state texture_env_combine state vector to be filled-in.
156 * \param mode Classic texture environment mode (i.e., \c GL_REPLACE,
157 * \c GL_BLEND, \c GL_DECAL, etc.).
158 * \param texBaseFormat Base format of the texture associated with the
159 * texture unit.
160 */
161 static void
162 calculate_derived_texenv( struct gl_tex_env_combine_state *state,
163 GLenum mode, GLenum texBaseFormat )
164 {
165 GLenum mode_rgb;
166 GLenum mode_a;
167
168 *state = default_combine_state;
169
170 switch (texBaseFormat) {
171 case GL_ALPHA:
172 state->SourceRGB[0] = GL_PREVIOUS;
173 break;
174
175 case GL_LUMINANCE_ALPHA:
176 case GL_INTENSITY:
177 case GL_RGBA:
178 break;
179
180 case GL_LUMINANCE:
181 case GL_RGB:
182 case GL_YCBCR_MESA:
183 state->SourceA[0] = GL_PREVIOUS;
184 break;
185
186 default:
187 _mesa_problem(NULL, "Invalid texBaseFormat in calculate_derived_texenv");
188 return;
189 }
190
191 if (mode == GL_REPLACE_EXT)
192 mode = GL_REPLACE;
193
194 switch (mode) {
195 case GL_REPLACE:
196 case GL_MODULATE:
197 mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : mode;
198 mode_a = mode;
199 break;
200
201 case GL_DECAL:
202 mode_rgb = GL_INTERPOLATE;
203 mode_a = GL_REPLACE;
204
205 state->SourceA[0] = GL_PREVIOUS;
206
207 /* Having alpha / luminance / intensity textures replace using the
208 * incoming fragment color matches the definition in NV_texture_shader.
209 * The 1.5 spec simply marks these as "undefined".
210 */
211 switch (texBaseFormat) {
212 case GL_ALPHA:
213 case GL_LUMINANCE:
214 case GL_LUMINANCE_ALPHA:
215 case GL_INTENSITY:
216 state->SourceRGB[0] = GL_PREVIOUS;
217 break;
218 case GL_RGB:
219 case GL_YCBCR_MESA:
220 mode_rgb = GL_REPLACE;
221 break;
222 case GL_RGBA:
223 state->SourceRGB[2] = GL_TEXTURE;
224 break;
225 }
226 break;
227
228 case GL_BLEND:
229 mode_rgb = GL_INTERPOLATE;
230 mode_a = GL_MODULATE;
231
232 switch (texBaseFormat) {
233 case GL_ALPHA:
234 mode_rgb = GL_REPLACE;
235 break;
236 case GL_INTENSITY:
237 mode_a = GL_INTERPOLATE;
238 state->SourceA[0] = GL_CONSTANT;
239 state->OperandA[2] = GL_SRC_ALPHA;
240 /* FALLTHROUGH */
241 case GL_LUMINANCE:
242 case GL_RGB:
243 case GL_LUMINANCE_ALPHA:
244 case GL_RGBA:
245 case GL_YCBCR_MESA:
246 state->SourceRGB[2] = GL_TEXTURE;
247 state->SourceA[2] = GL_TEXTURE;
248 state->SourceRGB[0] = GL_CONSTANT;
249 state->OperandRGB[2] = GL_SRC_COLOR;
250 break;
251 }
252 break;
253
254 case GL_ADD:
255 mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : GL_ADD;
256 mode_a = (texBaseFormat == GL_INTENSITY) ? GL_ADD : GL_MODULATE;
257 break;
258
259 default:
260 _mesa_problem(NULL,
261 "Invalid texture env mode in calculate_derived_texenv");
262 return;
263 }
264
265 state->ModeRGB = (state->SourceRGB[0] != GL_PREVIOUS)
266 ? mode_rgb : GL_REPLACE;
267 state->ModeA = (state->SourceA[0] != GL_PREVIOUS)
268 ? mode_a : GL_REPLACE;
269 }
270
271
272
273
274 /* GL_ARB_multitexture */
275 void GLAPIENTRY
276 _mesa_ActiveTextureARB(GLenum texture)
277 {
278 GET_CURRENT_CONTEXT(ctx);
279 const GLuint texUnit = texture - GL_TEXTURE0;
280 ASSERT_OUTSIDE_BEGIN_END(ctx);
281
282 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
283 _mesa_debug(ctx, "glActiveTexture %s\n",
284 _mesa_lookup_enum_by_nr(texture));
285
286 if (texUnit >= ctx->Const.MaxTextureImageUnits) {
287 _mesa_error(ctx, GL_INVALID_ENUM, "glActiveTexture(texture)");
288 return;
289 }
290
291 if (ctx->Texture.CurrentUnit == texUnit)
292 return;
293
294 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
295
296 ctx->Texture.CurrentUnit = texUnit;
297 if (ctx->Transform.MatrixMode == GL_TEXTURE) {
298 /* update current stack pointer */
299 ctx->CurrentStack = &ctx->TextureMatrixStack[texUnit];
300 }
301
302 if (ctx->Driver.ActiveTexture) {
303 (*ctx->Driver.ActiveTexture)( ctx, (GLuint) texUnit );
304 }
305 }
306
307
308 /* GL_ARB_multitexture */
309 void GLAPIENTRY
310 _mesa_ClientActiveTextureARB(GLenum texture)
311 {
312 GET_CURRENT_CONTEXT(ctx);
313 GLuint texUnit = texture - GL_TEXTURE0;
314 ASSERT_OUTSIDE_BEGIN_END(ctx);
315
316 if (texUnit >= ctx->Const.MaxTextureCoordUnits) {
317 _mesa_error(ctx, GL_INVALID_ENUM, "glClientActiveTexture(texture)");
318 return;
319 }
320
321 FLUSH_VERTICES(ctx, _NEW_ARRAY);
322 ctx->Array.ActiveTexture = texUnit;
323 }
324
325
326
327 /**********************************************************************/
328 /***** State management *****/
329 /**********************************************************************/
330
331
332 /**
333 * \note This routine refers to derived texture attribute values to
334 * compute the ENABLE_TEXMAT flags, but is only called on
335 * _NEW_TEXTURE_MATRIX. On changes to _NEW_TEXTURE, the ENABLE_TEXMAT
336 * flags are updated by _mesa_update_textures(), below.
337 *
338 * \param ctx GL context.
339 */
340 static void
341 update_texture_matrices( GLcontext *ctx )
342 {
343 GLuint i;
344
345 ctx->Texture._TexMatEnabled = 0;
346
347 for (i=0; i < ctx->Const.MaxTextureCoordUnits; i++) {
348 if (_math_matrix_is_dirty(ctx->TextureMatrixStack[i].Top)) {
349 _math_matrix_analyse( ctx->TextureMatrixStack[i].Top );
350
351 if (ctx->Texture.Unit[i]._ReallyEnabled &&
352 ctx->TextureMatrixStack[i].Top->type != MATRIX_IDENTITY)
353 ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(i);
354
355 if (ctx->Driver.TextureMatrix)
356 ctx->Driver.TextureMatrix( ctx, i, ctx->TextureMatrixStack[i].Top);
357 }
358 }
359 }
360
361
362 /**
363 * Update texture object's _Function field. We need to do this
364 * whenever any of the texture object's shadow-related fields change
365 * or when we start/stop using a fragment program.
366 *
367 * This function could be expanded someday to update additional per-object
368 * fields that depend on assorted state changes.
369 */
370 static void
371 update_texture_compare_function(GLcontext *ctx,
372 struct gl_texture_object *tObj)
373 {
374 /* XXX temporarily disable this test since it breaks the GLSL
375 * shadow2D(), etc. functions.
376 */
377 if (0 /*ctx->FragmentProgram._Current*/) {
378 /* Texel/coordinate comparison is ignored for programs.
379 * See GL_ARB_fragment_program/shader spec for details.
380 */
381 tObj->_Function = GL_NONE;
382 }
383 else if (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
384 /* GL_ARB_shadow */
385 tObj->_Function = tObj->CompareFunc;
386 }
387 else {
388 tObj->_Function = GL_NONE; /* pass depth through as grayscale */
389 }
390 }
391
392
393 /**
394 * Helper function for determining which texture object (1D, 2D, cube, etc)
395 * should actually be used.
396 */
397 static void
398 texture_override(GLcontext *ctx,
399 struct gl_texture_unit *texUnit, GLbitfield enableBits,
400 struct gl_texture_object *texObj, GLuint textureBit)
401 {
402 if (!texUnit->_ReallyEnabled && (enableBits & textureBit)) {
403 if (!texObj->_Complete) {
404 _mesa_test_texobj_completeness(ctx, texObj);
405 }
406 if (texObj->_Complete) {
407 texUnit->_ReallyEnabled = textureBit;
408 texUnit->_Current = texObj;
409 update_texture_compare_function(ctx, texObj);
410 }
411 }
412 }
413
414
415 /**
416 * Examine texture unit's combine/env state to update derived state.
417 */
418 static void
419 update_tex_combine(GLcontext *ctx, struct gl_texture_unit *texUnit)
420 {
421 /* Set the texUnit->_CurrentCombine field to point to the user's combiner
422 * state, or the combiner state which is derived from traditional texenv
423 * mode.
424 */
425 if (texUnit->EnvMode == GL_COMBINE ||
426 texUnit->EnvMode == GL_COMBINE4_NV) {
427 texUnit->_CurrentCombine = & texUnit->Combine;
428 }
429 else {
430 const struct gl_texture_object *texObj = texUnit->_Current;
431 GLenum format = texObj->Image[0][texObj->BaseLevel]->_BaseFormat;
432 if (format == GL_COLOR_INDEX) {
433 format = GL_RGBA; /* a bit of a hack */
434 }
435 else if (format == GL_DEPTH_COMPONENT ||
436 format == GL_DEPTH_STENCIL_EXT) {
437 format = texObj->DepthMode;
438 }
439 calculate_derived_texenv(&texUnit->_EnvMode, texUnit->EnvMode, format);
440 texUnit->_CurrentCombine = & texUnit->_EnvMode;
441 }
442
443 /* Determine number of source RGB terms in the combiner function */
444 switch (texUnit->_CurrentCombine->ModeRGB) {
445 case GL_REPLACE:
446 texUnit->_CurrentCombine->_NumArgsRGB = 1;
447 break;
448 case GL_ADD:
449 case GL_ADD_SIGNED:
450 if (texUnit->EnvMode == GL_COMBINE4_NV)
451 texUnit->_CurrentCombine->_NumArgsRGB = 4;
452 else
453 texUnit->_CurrentCombine->_NumArgsRGB = 2;
454 break;
455 case GL_MODULATE:
456 case GL_SUBTRACT:
457 case GL_DOT3_RGB:
458 case GL_DOT3_RGBA:
459 case GL_DOT3_RGB_EXT:
460 case GL_DOT3_RGBA_EXT:
461 texUnit->_CurrentCombine->_NumArgsRGB = 2;
462 break;
463 case GL_INTERPOLATE:
464 case GL_MODULATE_ADD_ATI:
465 case GL_MODULATE_SIGNED_ADD_ATI:
466 case GL_MODULATE_SUBTRACT_ATI:
467 texUnit->_CurrentCombine->_NumArgsRGB = 3;
468 break;
469 default:
470 texUnit->_CurrentCombine->_NumArgsRGB = 0;
471 _mesa_problem(ctx, "invalid RGB combine mode in update_texture_state");
472 return;
473 }
474
475 /* Determine number of source Alpha terms in the combiner function */
476 switch (texUnit->_CurrentCombine->ModeA) {
477 case GL_REPLACE:
478 texUnit->_CurrentCombine->_NumArgsA = 1;
479 break;
480 case GL_ADD:
481 case GL_ADD_SIGNED:
482 if (texUnit->EnvMode == GL_COMBINE4_NV)
483 texUnit->_CurrentCombine->_NumArgsA = 4;
484 else
485 texUnit->_CurrentCombine->_NumArgsA = 2;
486 break;
487 case GL_MODULATE:
488 case GL_SUBTRACT:
489 texUnit->_CurrentCombine->_NumArgsA = 2;
490 break;
491 case GL_INTERPOLATE:
492 case GL_MODULATE_ADD_ATI:
493 case GL_MODULATE_SIGNED_ADD_ATI:
494 case GL_MODULATE_SUBTRACT_ATI:
495 texUnit->_CurrentCombine->_NumArgsA = 3;
496 break;
497 default:
498 texUnit->_CurrentCombine->_NumArgsA = 0;
499 _mesa_problem(ctx, "invalid Alpha combine mode in update_texture_state");
500 break;
501 }
502 }
503
504
505 /**
506 * \note This routine refers to derived texture matrix values to
507 * compute the ENABLE_TEXMAT flags, but is only called on
508 * _NEW_TEXTURE. On changes to _NEW_TEXTURE_MATRIX, the ENABLE_TEXMAT
509 * flags are updated by _mesa_update_texture_matrices, above.
510 *
511 * \param ctx GL context.
512 */
513 static void
514 update_texture_state( GLcontext *ctx )
515 {
516 GLuint unit;
517 struct gl_fragment_program *fprog = NULL;
518 struct gl_vertex_program *vprog = NULL;
519
520 if (ctx->Shader.CurrentProgram &&
521 ctx->Shader.CurrentProgram->LinkStatus) {
522 fprog = ctx->Shader.CurrentProgram->FragmentProgram;
523 vprog = ctx->Shader.CurrentProgram->VertexProgram;
524 }
525 else {
526 if (ctx->FragmentProgram._Enabled) {
527 fprog = ctx->FragmentProgram.Current;
528 }
529 if (ctx->VertexProgram._Enabled) {
530 /* XXX enable this if/when non-shader vertex programs get
531 * texture fetches:
532 vprog = ctx->VertexProgram.Current;
533 */
534 }
535 }
536
537 /* TODO: only set this if there are actual changes */
538 ctx->NewState |= _NEW_TEXTURE;
539
540 ctx->Texture._EnabledUnits = 0;
541 ctx->Texture._GenFlags = 0;
542 ctx->Texture._TexMatEnabled = 0;
543 ctx->Texture._TexGenEnabled = 0;
544
545 /*
546 * Update texture unit state.
547 */
548 for (unit = 0; unit < ctx->Const.MaxTextureImageUnits; unit++) {
549 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
550 GLbitfield enableBits;
551 GLuint texIndex;
552
553 texUnit->_Current = NULL;
554 texUnit->_ReallyEnabled = 0;
555 texUnit->_GenFlags = 0;
556
557 /* Get the bitmask of texture target enables.
558 * enableBits will be a mask of the TEXTURE_*_BIT flags indicating
559 * which texture targets are enabled (fixed function) or referenced
560 * by a fragment shader/program. When multiple flags are set, we'll
561 * settle on the one with highest priority (see texture_override below).
562 */
563 enableBits = 0x0;
564 if (vprog) {
565 enableBits |= vprog->Base.TexturesUsed[unit];
566 }
567 if (fprog) {
568 enableBits |= fprog->Base.TexturesUsed[unit];
569 }
570 else {
571 /* fixed-function fragment program */
572 enableBits |= texUnit->Enabled;
573 }
574
575 if (enableBits == 0x0)
576 continue;
577
578 /* Look for the highest-priority texture target that's enabled and
579 * complete. That's the one we'll use for texturing. If we're using
580 * a fragment program we're guaranteed that bitcount(enabledBits) <= 1.
581 * Note that the TEXTURE_x_INDEX values are in high to low priority.
582 */
583 for (texIndex = 0; texIndex < NUM_TEXTURE_TARGETS; texIndex++) {
584 texture_override(ctx, texUnit, enableBits,
585 texUnit->CurrentTex[texIndex], 1 << texIndex);
586 }
587
588 if (!texUnit->_ReallyEnabled) {
589 continue;
590 }
591
592 /* if we get here, we know this texture unit is enabled */
593
594 ctx->Texture._EnabledUnits |= (1 << unit);
595
596 update_tex_combine(ctx, texUnit);
597 }
598
599
600 /* Determine which texture coordinate sets are actually needed */
601 if (fprog) {
602 const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1;
603 ctx->Texture._EnabledCoordUnits
604 = (fprog->Base.InputsRead >> FRAG_ATTRIB_TEX0) & coordMask;
605 }
606 else {
607 ctx->Texture._EnabledCoordUnits = ctx->Texture._EnabledUnits;
608 }
609
610 /* Setup texgen for those texture coordinate sets that are in use */
611 for (unit = 0; unit < ctx->Const.MaxTextureCoordUnits; unit++) {
612 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
613
614 if (!(ctx->Texture._EnabledCoordUnits & (1 << unit)))
615 continue;
616
617 if (texUnit->TexGenEnabled) {
618 if (texUnit->TexGenEnabled & S_BIT) {
619 texUnit->_GenFlags |= texUnit->GenS._ModeBit;
620 }
621 if (texUnit->TexGenEnabled & T_BIT) {
622 texUnit->_GenFlags |= texUnit->GenT._ModeBit;
623 }
624 if (texUnit->TexGenEnabled & R_BIT) {
625 texUnit->_GenFlags |= texUnit->GenR._ModeBit;
626 }
627 if (texUnit->TexGenEnabled & Q_BIT) {
628 texUnit->_GenFlags |= texUnit->GenQ._ModeBit;
629 }
630
631 ctx->Texture._TexGenEnabled |= ENABLE_TEXGEN(unit);
632 ctx->Texture._GenFlags |= texUnit->_GenFlags;
633 }
634
635 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY)
636 ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(unit);
637 }
638 }
639
640
641 /**
642 * Update texture-related derived state.
643 */
644 void
645 _mesa_update_texture( GLcontext *ctx, GLuint new_state )
646 {
647 if (new_state & _NEW_TEXTURE_MATRIX)
648 update_texture_matrices( ctx );
649
650 if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM))
651 update_texture_state( ctx );
652 }
653
654
655 /**********************************************************************/
656 /***** Initialization *****/
657 /**********************************************************************/
658
659 /**
660 * Allocate the proxy textures for the given context.
661 *
662 * \param ctx the context to allocate proxies for.
663 *
664 * \return GL_TRUE on success, or GL_FALSE on failure
665 *
666 * If run out of memory part way through the allocations, clean up and return
667 * GL_FALSE.
668 */
669 static GLboolean
670 alloc_proxy_textures( GLcontext *ctx )
671 {
672 static const GLenum targets[] = {
673 GL_TEXTURE_1D,
674 GL_TEXTURE_2D,
675 GL_TEXTURE_3D,
676 GL_TEXTURE_CUBE_MAP_ARB,
677 GL_TEXTURE_RECTANGLE_NV,
678 GL_TEXTURE_1D_ARRAY_EXT,
679 GL_TEXTURE_2D_ARRAY_EXT
680 };
681 GLint tgt;
682
683 ASSERT(Elements(targets) == NUM_TEXTURE_TARGETS);
684
685 for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
686 if (!(ctx->Texture.ProxyTex[tgt]
687 = ctx->Driver.NewTextureObject(ctx, 0, targets[tgt]))) {
688 /* out of memory, free what we did allocate */
689 while (--tgt >= 0) {
690 ctx->Driver.DeleteTexture(ctx, ctx->Texture.ProxyTex[tgt]);
691 }
692 return GL_FALSE;
693 }
694 }
695
696 assert(ctx->Texture.ProxyTex[0]->RefCount == 1); /* sanity check */
697 return GL_TRUE;
698 }
699
700
701 /**
702 * Initialize a texture unit.
703 *
704 * \param ctx GL context.
705 * \param unit texture unit number to be initialized.
706 */
707 static void
708 init_texture_unit( GLcontext *ctx, GLuint unit )
709 {
710 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
711 GLuint tex;
712
713 texUnit->EnvMode = GL_MODULATE;
714 ASSIGN_4V( texUnit->EnvColor, 0.0, 0.0, 0.0, 0.0 );
715
716 texUnit->Combine = default_combine_state;
717 texUnit->_EnvMode = default_combine_state;
718 texUnit->_CurrentCombine = & texUnit->_EnvMode;
719
720 texUnit->TexGenEnabled = 0;
721 texUnit->GenS.Mode = GL_EYE_LINEAR;
722 texUnit->GenT.Mode = GL_EYE_LINEAR;
723 texUnit->GenR.Mode = GL_EYE_LINEAR;
724 texUnit->GenQ.Mode = GL_EYE_LINEAR;
725 texUnit->GenS._ModeBit = TEXGEN_EYE_LINEAR;
726 texUnit->GenT._ModeBit = TEXGEN_EYE_LINEAR;
727 texUnit->GenR._ModeBit = TEXGEN_EYE_LINEAR;
728 texUnit->GenQ._ModeBit = TEXGEN_EYE_LINEAR;
729
730 /* Yes, these plane coefficients are correct! */
731 ASSIGN_4V( texUnit->GenS.ObjectPlane, 1.0, 0.0, 0.0, 0.0 );
732 ASSIGN_4V( texUnit->GenT.ObjectPlane, 0.0, 1.0, 0.0, 0.0 );
733 ASSIGN_4V( texUnit->GenR.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
734 ASSIGN_4V( texUnit->GenQ.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
735 ASSIGN_4V( texUnit->GenS.EyePlane, 1.0, 0.0, 0.0, 0.0 );
736 ASSIGN_4V( texUnit->GenT.EyePlane, 0.0, 1.0, 0.0, 0.0 );
737 ASSIGN_4V( texUnit->GenR.EyePlane, 0.0, 0.0, 0.0, 0.0 );
738 ASSIGN_4V( texUnit->GenQ.EyePlane, 0.0, 0.0, 0.0, 0.0 );
739
740 /* initialize current texture object ptrs to the shared default objects */
741 for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
742 _mesa_reference_texobj(&texUnit->CurrentTex[tex],
743 ctx->Shared->DefaultTex[tex]);
744 }
745 }
746
747
748 /**
749 * Initialize texture state for the given context.
750 */
751 GLboolean
752 _mesa_init_texture(GLcontext *ctx)
753 {
754 GLuint i;
755
756 assert(MAX_TEXTURE_LEVELS >= MAX_3D_TEXTURE_LEVELS);
757 assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS);
758
759 /* Texture group */
760 ctx->Texture.CurrentUnit = 0; /* multitexture */
761 ctx->Texture._EnabledUnits = 0;
762 ctx->Texture.SharedPalette = GL_FALSE;
763 #if FEATURE_colortable
764 _mesa_init_colortable(&ctx->Texture.Palette);
765 #endif
766
767 for (i = 0; i < MAX_TEXTURE_UNITS; i++)
768 init_texture_unit( ctx, i );
769
770 /* After we're done initializing the context's texture state the default
771 * texture objects' refcounts should be at least MAX_TEXTURE_UNITS + 1.
772 */
773 assert(ctx->Shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount
774 >= MAX_TEXTURE_UNITS + 1);
775
776 /* Allocate proxy textures */
777 if (!alloc_proxy_textures( ctx ))
778 return GL_FALSE;
779
780 return GL_TRUE;
781 }
782
783
784 /**
785 * Free dynamically-allocted texture data attached to the given context.
786 */
787 void
788 _mesa_free_texture_data(GLcontext *ctx)
789 {
790 GLuint u, tgt;
791
792 /* unreference current textures */
793 for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) {
794 struct gl_texture_unit *unit = ctx->Texture.Unit + u;
795 for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
796 _mesa_reference_texobj(&unit->CurrentTex[tgt], NULL);
797 }
798 }
799
800 /* Free proxy texture objects */
801 for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++)
802 ctx->Driver.DeleteTexture(ctx, ctx->Texture.ProxyTex[tgt]);
803
804 #if FEATURE_colortable
805 {
806 GLuint i;
807 for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
808 _mesa_free_colortable_data( &ctx->Texture.Unit[i].ColorTable );
809 }
810 #endif
811 }
812
813
814 /**
815 * Update the default texture objects in the given context to reference those
816 * specified in the shared state and release those referencing the old
817 * shared state.
818 */
819 void
820 _mesa_update_default_objects_texture(GLcontext *ctx)
821 {
822 GLuint i, tex;
823
824 for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
825 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
826 for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
827 _mesa_reference_texobj(&texUnit->CurrentTex[tex],
828 ctx->Shared->DefaultTex[tex]);
829 }
830 }
831 }