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