texstate.c revision ac997013
17117f1b4Smrg/*
27117f1b4Smrg * Mesa 3-D graphics library
356e89960Smrg * Version:  7.5
47117f1b4Smrg *
57117f1b4Smrg * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
67117f1b4Smrg *
77117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a
87117f1b4Smrg * copy of this software and associated documentation files (the "Software"),
97117f1b4Smrg * to deal in the Software without restriction, including without limitation
107117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
117117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the
127117f1b4Smrg * Software is furnished to do so, subject to the following conditions:
137117f1b4Smrg *
147117f1b4Smrg * The above copyright notice and this permission notice shall be included
157117f1b4Smrg * in all copies or substantial portions of the Software.
167117f1b4Smrg *
177117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
187117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
197117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
207117f1b4Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
217117f1b4Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
227117f1b4Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
237117f1b4Smrg */
247117f1b4Smrg
257117f1b4Smrg/**
267117f1b4Smrg * \file texstate.c
277117f1b4Smrg *
287117f1b4Smrg * Texture state handling.
297117f1b4Smrg */
307117f1b4Smrg
317117f1b4Smrg#include "glheader.h"
3256e89960Smrg#include "mfeatures.h"
33ac997013Sriastradh#include "bufferobj.h"
347117f1b4Smrg#include "colormac.h"
357117f1b4Smrg#include "colortab.h"
367117f1b4Smrg#include "context.h"
377117f1b4Smrg#include "enums.h"
387117f1b4Smrg#include "macros.h"
397117f1b4Smrg#include "texobj.h"
407117f1b4Smrg#include "teximage.h"
417117f1b4Smrg#include "texstate.h"
427117f1b4Smrg#include "mtypes.h"
437117f1b4Smrg
447117f1b4Smrg
457117f1b4Smrg
467117f1b4Smrg/**
477117f1b4Smrg * Default texture combine environment state.  This is used to initialize
487117f1b4Smrg * a context's texture units and as the basis for converting "classic"
497117f1b4Smrg * texture environmnets to ARB_texture_env_combine style values.
507117f1b4Smrg */
517117f1b4Smrgstatic const struct gl_tex_env_combine_state default_combine_state = {
527117f1b4Smrg   GL_MODULATE, GL_MODULATE,
5356e89960Smrg   { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT, GL_CONSTANT },
5456e89960Smrg   { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT, GL_CONSTANT },
5556e89960Smrg   { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_ALPHA, GL_SRC_ALPHA },
5656e89960Smrg   { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA },
577117f1b4Smrg   0, 0,
587117f1b4Smrg   2, 2
597117f1b4Smrg};
607117f1b4Smrg
617117f1b4Smrg
627117f1b4Smrg
637117f1b4Smrg/**
647117f1b4Smrg * Used by glXCopyContext to copy texture state from one context to another.
657117f1b4Smrg */
667117f1b4Smrgvoid
67ac997013Sriastradh_mesa_copy_texture_state( const struct gl_context *src, struct gl_context *dst )
687117f1b4Smrg{
6956e89960Smrg   GLuint u, tex;
707117f1b4Smrg
717117f1b4Smrg   ASSERT(src);
727117f1b4Smrg   ASSERT(dst);
737117f1b4Smrg
747117f1b4Smrg   dst->Texture.CurrentUnit = src->Texture.CurrentUnit;
757117f1b4Smrg   dst->Texture._GenFlags = src->Texture._GenFlags;
767117f1b4Smrg   dst->Texture._TexGenEnabled = src->Texture._TexGenEnabled;
777117f1b4Smrg   dst->Texture._TexMatEnabled = src->Texture._TexMatEnabled;
787117f1b4Smrg   dst->Texture.SharedPalette = src->Texture.SharedPalette;
797117f1b4Smrg
807117f1b4Smrg   /* per-unit state */
811f16d945Smrg   for (u = 0; u < src->Const.MaxCombinedTextureImageUnits; u++) {
8256e89960Smrg      dst->Texture.Unit[u].Enabled = src->Texture.Unit[u].Enabled;
8356e89960Smrg      dst->Texture.Unit[u].EnvMode = src->Texture.Unit[u].EnvMode;
8456e89960Smrg      COPY_4V(dst->Texture.Unit[u].EnvColor, src->Texture.Unit[u].EnvColor);
8556e89960Smrg      dst->Texture.Unit[u].TexGenEnabled = src->Texture.Unit[u].TexGenEnabled;
8656e89960Smrg      dst->Texture.Unit[u].GenS = src->Texture.Unit[u].GenS;
8756e89960Smrg      dst->Texture.Unit[u].GenT = src->Texture.Unit[u].GenT;
8856e89960Smrg      dst->Texture.Unit[u].GenR = src->Texture.Unit[u].GenR;
8956e89960Smrg      dst->Texture.Unit[u].GenQ = src->Texture.Unit[u].GenQ;
9056e89960Smrg      dst->Texture.Unit[u].LodBias = src->Texture.Unit[u].LodBias;
917117f1b4Smrg
927117f1b4Smrg      /* GL_EXT_texture_env_combine */
9356e89960Smrg      dst->Texture.Unit[u].Combine = src->Texture.Unit[u].Combine;
947117f1b4Smrg
9556e89960Smrg      /* GL_ATI_envmap_bumpmap - need this? */
9656e89960Smrg      dst->Texture.Unit[u].BumpTarget = src->Texture.Unit[u].BumpTarget;
9756e89960Smrg      COPY_4V(dst->Texture.Unit[u].RotMatrix, src->Texture.Unit[u].RotMatrix);
9856e89960Smrg
9956e89960Smrg      /*
10056e89960Smrg       * XXX strictly speaking, we should compare texture names/ids and
10156e89960Smrg       * bind textures in the dest context according to id.  For now, only
10256e89960Smrg       * copy bindings if the contexts share the same pool of textures to
10356e89960Smrg       * avoid refcounting bugs.
10456e89960Smrg       */
10556e89960Smrg      if (dst->Shared == src->Shared) {
10656e89960Smrg         /* copy texture object bindings, not contents of texture objects */
10756e89960Smrg         _mesa_lock_context_textures(dst);
1087117f1b4Smrg
10956e89960Smrg         for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
11056e89960Smrg            _mesa_reference_texobj(&dst->Texture.Unit[u].CurrentTex[tex],
11156e89960Smrg                                   src->Texture.Unit[u].CurrentTex[tex]);
11256e89960Smrg         }
11356e89960Smrg         _mesa_unlock_context_textures(dst);
11456e89960Smrg      }
1157117f1b4Smrg   }
1167117f1b4Smrg}
1177117f1b4Smrg
1187117f1b4Smrg
1197117f1b4Smrg/*
1207117f1b4Smrg * For debugging
1217117f1b4Smrg */
1227117f1b4Smrgvoid
123ac997013Sriastradh_mesa_print_texunit_state( struct gl_context *ctx, GLuint unit )
1247117f1b4Smrg{
1257117f1b4Smrg   const struct gl_texture_unit *texUnit = ctx->Texture.Unit + unit;
1261f16d945Smrg   printf("Texture Unit %d\n", unit);
1271f16d945Smrg   printf("  GL_TEXTURE_ENV_MODE = %s\n", _mesa_lookup_enum_by_nr(texUnit->EnvMode));
1281f16d945Smrg   printf("  GL_COMBINE_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeRGB));
1291f16d945Smrg   printf("  GL_COMBINE_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeA));
1301f16d945Smrg   printf("  GL_SOURCE0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[0]));
1311f16d945Smrg   printf("  GL_SOURCE1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[1]));
1321f16d945Smrg   printf("  GL_SOURCE2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[2]));
1331f16d945Smrg   printf("  GL_SOURCE0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[0]));
1341f16d945Smrg   printf("  GL_SOURCE1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[1]));
1351f16d945Smrg   printf("  GL_SOURCE2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[2]));
1361f16d945Smrg   printf("  GL_OPERAND0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[0]));
1371f16d945Smrg   printf("  GL_OPERAND1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[1]));
1381f16d945Smrg   printf("  GL_OPERAND2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[2]));
1391f16d945Smrg   printf("  GL_OPERAND0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[0]));
1401f16d945Smrg   printf("  GL_OPERAND1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[1]));
1411f16d945Smrg   printf("  GL_OPERAND2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[2]));
1421f16d945Smrg   printf("  GL_RGB_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftRGB);
1431f16d945Smrg   printf("  GL_ALPHA_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftA);
1441f16d945Smrg   printf("  GL_TEXTURE_ENV_COLOR = (%f, %f, %f, %f)\n", texUnit->EnvColor[0], texUnit->EnvColor[1], texUnit->EnvColor[2], texUnit->EnvColor[3]);
145c1f859d4Smrg}
1467117f1b4Smrg
1477117f1b4Smrg
1487117f1b4Smrg
149c1f859d4Smrg/**********************************************************************/
150c1f859d4Smrg/*                       Texture Environment                          */
151c1f859d4Smrg/**********************************************************************/
1527117f1b4Smrg
153c1f859d4Smrg/**
154c1f859d4Smrg * Convert "classic" texture environment to ARB_texture_env_combine style
155c1f859d4Smrg * environments.
156c1f859d4Smrg *
157c1f859d4Smrg * \param state  texture_env_combine state vector to be filled-in.
158c1f859d4Smrg * \param mode   Classic texture environment mode (i.e., \c GL_REPLACE,
159c1f859d4Smrg *               \c GL_BLEND, \c GL_DECAL, etc.).
160c1f859d4Smrg * \param texBaseFormat  Base format of the texture associated with the
161c1f859d4Smrg *               texture unit.
162c1f859d4Smrg */
163c1f859d4Smrgstatic void
164c1f859d4Smrgcalculate_derived_texenv( struct gl_tex_env_combine_state *state,
165c1f859d4Smrg			  GLenum mode, GLenum texBaseFormat )
166c1f859d4Smrg{
167c1f859d4Smrg   GLenum mode_rgb;
168c1f859d4Smrg   GLenum mode_a;
1697117f1b4Smrg
170c1f859d4Smrg   *state = default_combine_state;
1717117f1b4Smrg
172c1f859d4Smrg   switch (texBaseFormat) {
173c1f859d4Smrg   case GL_ALPHA:
174c1f859d4Smrg      state->SourceRGB[0] = GL_PREVIOUS;
175c1f859d4Smrg      break;
1767117f1b4Smrg
177c1f859d4Smrg   case GL_LUMINANCE_ALPHA:
178c1f859d4Smrg   case GL_INTENSITY:
179c1f859d4Smrg   case GL_RGBA:
180c1f859d4Smrg      break;
1817117f1b4Smrg
182c1f859d4Smrg   case GL_LUMINANCE:
183ac997013Sriastradh   case GL_RED:
184ac997013Sriastradh   case GL_RG:
185c1f859d4Smrg   case GL_RGB:
186c1f859d4Smrg   case GL_YCBCR_MESA:
18756e89960Smrg   case GL_DUDV_ATI:
188c1f859d4Smrg      state->SourceA[0] = GL_PREVIOUS;
189c1f859d4Smrg      break;
190c1f859d4Smrg
191c1f859d4Smrg   default:
19256e89960Smrg      _mesa_problem(NULL,
19356e89960Smrg                    "Invalid texBaseFormat 0x%x in calculate_derived_texenv",
19456e89960Smrg                    texBaseFormat);
1957117f1b4Smrg      return;
1967117f1b4Smrg   }
1977117f1b4Smrg
198c1f859d4Smrg   if (mode == GL_REPLACE_EXT)
199c1f859d4Smrg      mode = GL_REPLACE;
2007117f1b4Smrg
201c1f859d4Smrg   switch (mode) {
202c1f859d4Smrg   case GL_REPLACE:
203c1f859d4Smrg   case GL_MODULATE:
204c1f859d4Smrg      mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : mode;
205c1f859d4Smrg      mode_a   = mode;
206c1f859d4Smrg      break;
207c1f859d4Smrg
208c1f859d4Smrg   case GL_DECAL:
209c1f859d4Smrg      mode_rgb = GL_INTERPOLATE;
210c1f859d4Smrg      mode_a   = GL_REPLACE;
211c1f859d4Smrg
212c1f859d4Smrg      state->SourceA[0] = GL_PREVIOUS;
213c1f859d4Smrg
214c1f859d4Smrg      /* Having alpha / luminance / intensity textures replace using the
215c1f859d4Smrg       * incoming fragment color matches the definition in NV_texture_shader.
216c1f859d4Smrg       * The 1.5 spec simply marks these as "undefined".
217c1f859d4Smrg       */
218c1f859d4Smrg      switch (texBaseFormat) {
219c1f859d4Smrg      case GL_ALPHA:
220c1f859d4Smrg      case GL_LUMINANCE:
221c1f859d4Smrg      case GL_LUMINANCE_ALPHA:
222c1f859d4Smrg      case GL_INTENSITY:
223c1f859d4Smrg	 state->SourceRGB[0] = GL_PREVIOUS;
2247117f1b4Smrg	 break;
225ac997013Sriastradh      case GL_RED:
226ac997013Sriastradh      case GL_RG:
227c1f859d4Smrg      case GL_RGB:
228c1f859d4Smrg      case GL_YCBCR_MESA:
22956e89960Smrg      case GL_DUDV_ATI:
230c1f859d4Smrg	 mode_rgb = GL_REPLACE;
2317117f1b4Smrg	 break;
232c1f859d4Smrg      case GL_RGBA:
233c1f859d4Smrg	 state->SourceRGB[2] = GL_TEXTURE;
2347117f1b4Smrg	 break;
235c1f859d4Smrg      }
236c1f859d4Smrg      break;
2377117f1b4Smrg
238c1f859d4Smrg   case GL_BLEND:
239c1f859d4Smrg      mode_rgb = GL_INTERPOLATE;
240c1f859d4Smrg      mode_a   = GL_MODULATE;
2417117f1b4Smrg
242c1f859d4Smrg      switch (texBaseFormat) {
243c1f859d4Smrg      case GL_ALPHA:
244c1f859d4Smrg	 mode_rgb = GL_REPLACE;
245c1f859d4Smrg	 break;
246c1f859d4Smrg      case GL_INTENSITY:
247c1f859d4Smrg	 mode_a = GL_INTERPOLATE;
248c1f859d4Smrg	 state->SourceA[0] = GL_CONSTANT;
249c1f859d4Smrg	 state->OperandA[2] = GL_SRC_ALPHA;
250c1f859d4Smrg	 /* FALLTHROUGH */
251c1f859d4Smrg      case GL_LUMINANCE:
252ac997013Sriastradh      case GL_RED:
253ac997013Sriastradh      case GL_RG:
254c1f859d4Smrg      case GL_RGB:
255c1f859d4Smrg      case GL_LUMINANCE_ALPHA:
256c1f859d4Smrg      case GL_RGBA:
257c1f859d4Smrg      case GL_YCBCR_MESA:
25856e89960Smrg      case GL_DUDV_ATI:
259c1f859d4Smrg	 state->SourceRGB[2] = GL_TEXTURE;
260c1f859d4Smrg	 state->SourceA[2]   = GL_TEXTURE;
261c1f859d4Smrg	 state->SourceRGB[0] = GL_CONSTANT;
262c1f859d4Smrg	 state->OperandRGB[2] = GL_SRC_COLOR;
263c1f859d4Smrg	 break;
264c1f859d4Smrg      }
265c1f859d4Smrg      break;
2667117f1b4Smrg
267c1f859d4Smrg   case GL_ADD:
268c1f859d4Smrg      mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : GL_ADD;
269c1f859d4Smrg      mode_a   = (texBaseFormat == GL_INTENSITY) ? GL_ADD : GL_MODULATE;
270c1f859d4Smrg      break;
2717117f1b4Smrg
272c1f859d4Smrg   default:
273c1f859d4Smrg      _mesa_problem(NULL,
27456e89960Smrg                    "Invalid texture env mode 0x%x in calculate_derived_texenv",
27556e89960Smrg                    mode);
2767117f1b4Smrg      return;
2777117f1b4Smrg   }
278c1f859d4Smrg
279c1f859d4Smrg   state->ModeRGB = (state->SourceRGB[0] != GL_PREVIOUS)
280c1f859d4Smrg       ? mode_rgb : GL_REPLACE;
281c1f859d4Smrg   state->ModeA   = (state->SourceA[0]   != GL_PREVIOUS)
282c1f859d4Smrg       ? mode_a   : GL_REPLACE;
283c1f859d4Smrg}
2847117f1b4Smrg
2857117f1b4Smrg
2867117f1b4Smrg
2877117f1b4Smrg
2887117f1b4Smrg/* GL_ARB_multitexture */
2897117f1b4Smrgvoid GLAPIENTRY
2907117f1b4Smrg_mesa_ActiveTextureARB(GLenum texture)
2917117f1b4Smrg{
2927117f1b4Smrg   const GLuint texUnit = texture - GL_TEXTURE0;
2931f16d945Smrg   GLuint k;
2941f16d945Smrg   GET_CURRENT_CONTEXT(ctx);
2951f16d945Smrg
2961f16d945Smrg   /* See OpenGL spec for glActiveTexture: */
2971f16d945Smrg   k = MAX2(ctx->Const.MaxCombinedTextureImageUnits,
2981f16d945Smrg            ctx->Const.MaxTextureCoordUnits);
2991f16d945Smrg
3001f16d945Smrg   ASSERT(k <= Elements(ctx->Texture.Unit));
3011f16d945Smrg
3027117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
3037117f1b4Smrg
3047117f1b4Smrg   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
3057117f1b4Smrg      _mesa_debug(ctx, "glActiveTexture %s\n",
3067117f1b4Smrg                  _mesa_lookup_enum_by_nr(texture));
3077117f1b4Smrg
3081f16d945Smrg   if (texUnit >= k) {
3091f16d945Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glActiveTexture(texture=%s)",
3101f16d945Smrg                  _mesa_lookup_enum_by_nr(texture));
3117117f1b4Smrg      return;
3127117f1b4Smrg   }
3137117f1b4Smrg
3147117f1b4Smrg   if (ctx->Texture.CurrentUnit == texUnit)
3157117f1b4Smrg      return;
3167117f1b4Smrg
3177117f1b4Smrg   FLUSH_VERTICES(ctx, _NEW_TEXTURE);
3187117f1b4Smrg
3197117f1b4Smrg   ctx->Texture.CurrentUnit = texUnit;
3207117f1b4Smrg   if (ctx->Transform.MatrixMode == GL_TEXTURE) {
3217117f1b4Smrg      /* update current stack pointer */
3227117f1b4Smrg      ctx->CurrentStack = &ctx->TextureMatrixStack[texUnit];
3237117f1b4Smrg   }
3247117f1b4Smrg}
3257117f1b4Smrg
3267117f1b4Smrg
3277117f1b4Smrg/* GL_ARB_multitexture */
3287117f1b4Smrgvoid GLAPIENTRY
3297117f1b4Smrg_mesa_ClientActiveTextureARB(GLenum texture)
3307117f1b4Smrg{
3317117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
3327117f1b4Smrg   GLuint texUnit = texture - GL_TEXTURE0;
3337117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
3347117f1b4Smrg
33556e89960Smrg   if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE))
33656e89960Smrg      _mesa_debug(ctx, "glClientActiveTexture %s\n",
33756e89960Smrg                  _mesa_lookup_enum_by_nr(texture));
33856e89960Smrg
3397117f1b4Smrg   if (texUnit >= ctx->Const.MaxTextureCoordUnits) {
3407117f1b4Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glClientActiveTexture(texture)");
3417117f1b4Smrg      return;
3427117f1b4Smrg   }
3437117f1b4Smrg
34456e89960Smrg   if (ctx->Array.ActiveTexture == texUnit)
34556e89960Smrg      return;
34656e89960Smrg
3477117f1b4Smrg   FLUSH_VERTICES(ctx, _NEW_ARRAY);
3487117f1b4Smrg   ctx->Array.ActiveTexture = texUnit;
3497117f1b4Smrg}
3507117f1b4Smrg
3517117f1b4Smrg
3527117f1b4Smrg
3537117f1b4Smrg/**********************************************************************/
3547117f1b4Smrg/*****                    State management                        *****/
3557117f1b4Smrg/**********************************************************************/
3567117f1b4Smrg
3577117f1b4Smrg
3587117f1b4Smrg/**
3597117f1b4Smrg * \note This routine refers to derived texture attribute values to
3607117f1b4Smrg * compute the ENABLE_TEXMAT flags, but is only called on
3617117f1b4Smrg * _NEW_TEXTURE_MATRIX.  On changes to _NEW_TEXTURE, the ENABLE_TEXMAT
3627117f1b4Smrg * flags are updated by _mesa_update_textures(), below.
3637117f1b4Smrg *
3647117f1b4Smrg * \param ctx GL context.
3657117f1b4Smrg */
3667117f1b4Smrgstatic void
367ac997013Sriastradhupdate_texture_matrices( struct gl_context *ctx )
3687117f1b4Smrg{
36956e89960Smrg   GLuint u;
3707117f1b4Smrg
37156e89960Smrg   ctx->Texture._TexMatEnabled = 0x0;
3727117f1b4Smrg
37356e89960Smrg   for (u = 0; u < ctx->Const.MaxTextureCoordUnits; u++) {
3741f16d945Smrg      ASSERT(u < Elements(ctx->TextureMatrixStack));
37556e89960Smrg      if (_math_matrix_is_dirty(ctx->TextureMatrixStack[u].Top)) {
37656e89960Smrg	 _math_matrix_analyse( ctx->TextureMatrixStack[u].Top );
3777117f1b4Smrg
37856e89960Smrg	 if (ctx->Texture.Unit[u]._ReallyEnabled &&
37956e89960Smrg	     ctx->TextureMatrixStack[u].Top->type != MATRIX_IDENTITY)
38056e89960Smrg	    ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(u);
3817117f1b4Smrg      }
3827117f1b4Smrg   }
3837117f1b4Smrg}
3847117f1b4Smrg
3857117f1b4Smrg
386c1f859d4Smrg/**
38756e89960Smrg * Examine texture unit's combine/env state to update derived state.
388c1f859d4Smrg */
389c1f859d4Smrgstatic void
390ac997013Sriastradhupdate_tex_combine(struct gl_context *ctx, struct gl_texture_unit *texUnit)
391c1f859d4Smrg{
39256e89960Smrg   struct gl_tex_env_combine_state *combine;
39356e89960Smrg
39456e89960Smrg   /* Set the texUnit->_CurrentCombine field to point to the user's combiner
39556e89960Smrg    * state, or the combiner state which is derived from traditional texenv
39656e89960Smrg    * mode.
397c1f859d4Smrg    */
39856e89960Smrg   if (texUnit->EnvMode == GL_COMBINE ||
39956e89960Smrg       texUnit->EnvMode == GL_COMBINE4_NV) {
40056e89960Smrg      texUnit->_CurrentCombine = & texUnit->Combine;
401c1f859d4Smrg   }
40256e89960Smrg   else {
40356e89960Smrg      const struct gl_texture_object *texObj = texUnit->_Current;
40456e89960Smrg      GLenum format = texObj->Image[0][texObj->BaseLevel]->_BaseFormat;
40556e89960Smrg      if (format == GL_COLOR_INDEX) {
40656e89960Smrg         format = GL_RGBA;  /* a bit of a hack */
407c1f859d4Smrg      }
40856e89960Smrg      else if (format == GL_DEPTH_COMPONENT ||
40956e89960Smrg               format == GL_DEPTH_STENCIL_EXT) {
410ac997013Sriastradh         format = texObj->Sampler.DepthMode;
411c1f859d4Smrg      }
41256e89960Smrg      calculate_derived_texenv(&texUnit->_EnvMode, texUnit->EnvMode, format);
41356e89960Smrg      texUnit->_CurrentCombine = & texUnit->_EnvMode;
414c1f859d4Smrg   }
415c1f859d4Smrg
41656e89960Smrg   combine = texUnit->_CurrentCombine;
417c1f859d4Smrg
41856e89960Smrg   /* Determine number of source RGB terms in the combiner function */
41956e89960Smrg   switch (combine->ModeRGB) {
42056e89960Smrg   case GL_REPLACE:
42156e89960Smrg      combine->_NumArgsRGB = 1;
42256e89960Smrg      break;
42356e89960Smrg   case GL_ADD:
42456e89960Smrg   case GL_ADD_SIGNED:
42556e89960Smrg      if (texUnit->EnvMode == GL_COMBINE4_NV)
42656e89960Smrg         combine->_NumArgsRGB = 4;
42756e89960Smrg      else
42856e89960Smrg         combine->_NumArgsRGB = 2;
42956e89960Smrg      break;
43056e89960Smrg   case GL_MODULATE:
43156e89960Smrg   case GL_SUBTRACT:
43256e89960Smrg   case GL_DOT3_RGB:
43356e89960Smrg   case GL_DOT3_RGBA:
43456e89960Smrg   case GL_DOT3_RGB_EXT:
43556e89960Smrg   case GL_DOT3_RGBA_EXT:
43656e89960Smrg      combine->_NumArgsRGB = 2;
43756e89960Smrg      break;
43856e89960Smrg   case GL_INTERPOLATE:
43956e89960Smrg   case GL_MODULATE_ADD_ATI:
44056e89960Smrg   case GL_MODULATE_SIGNED_ADD_ATI:
44156e89960Smrg   case GL_MODULATE_SUBTRACT_ATI:
44256e89960Smrg      combine->_NumArgsRGB = 3;
44356e89960Smrg      break;
44456e89960Smrg   case GL_BUMP_ENVMAP_ATI:
44556e89960Smrg      /* no real arguments for this case */
44656e89960Smrg      combine->_NumArgsRGB = 0;
44756e89960Smrg      break;
44856e89960Smrg   default:
44956e89960Smrg      combine->_NumArgsRGB = 0;
45056e89960Smrg      _mesa_problem(ctx, "invalid RGB combine mode in update_texture_state");
45156e89960Smrg      return;
45256e89960Smrg   }
45356e89960Smrg
45456e89960Smrg   /* Determine number of source Alpha terms in the combiner function */
45556e89960Smrg   switch (combine->ModeA) {
45656e89960Smrg   case GL_REPLACE:
45756e89960Smrg      combine->_NumArgsA = 1;
45856e89960Smrg      break;
45956e89960Smrg   case GL_ADD:
46056e89960Smrg   case GL_ADD_SIGNED:
46156e89960Smrg      if (texUnit->EnvMode == GL_COMBINE4_NV)
46256e89960Smrg         combine->_NumArgsA = 4;
46356e89960Smrg      else
46456e89960Smrg         combine->_NumArgsA = 2;
46556e89960Smrg      break;
46656e89960Smrg   case GL_MODULATE:
46756e89960Smrg   case GL_SUBTRACT:
46856e89960Smrg      combine->_NumArgsA = 2;
46956e89960Smrg      break;
47056e89960Smrg   case GL_INTERPOLATE:
47156e89960Smrg   case GL_MODULATE_ADD_ATI:
47256e89960Smrg   case GL_MODULATE_SIGNED_ADD_ATI:
47356e89960Smrg   case GL_MODULATE_SUBTRACT_ATI:
47456e89960Smrg      combine->_NumArgsA = 3;
47556e89960Smrg      break;
47656e89960Smrg   default:
47756e89960Smrg      combine->_NumArgsA = 0;
47856e89960Smrg      _mesa_problem(ctx, "invalid Alpha combine mode in update_texture_state");
47956e89960Smrg      break;
4807117f1b4Smrg   }
4817117f1b4Smrg}
4827117f1b4Smrg
4837117f1b4Smrg
4847117f1b4Smrg/**
4857117f1b4Smrg * \note This routine refers to derived texture matrix values to
4867117f1b4Smrg * compute the ENABLE_TEXMAT flags, but is only called on
4877117f1b4Smrg * _NEW_TEXTURE.  On changes to _NEW_TEXTURE_MATRIX, the ENABLE_TEXMAT
4887117f1b4Smrg * flags are updated by _mesa_update_texture_matrices, above.
4897117f1b4Smrg *
4907117f1b4Smrg * \param ctx GL context.
4917117f1b4Smrg */
4927117f1b4Smrgstatic void
493ac997013Sriastradhupdate_texture_state( struct gl_context *ctx )
4947117f1b4Smrg{
4957117f1b4Smrg   GLuint unit;
4967117f1b4Smrg   struct gl_fragment_program *fprog = NULL;
4977117f1b4Smrg   struct gl_vertex_program *vprog = NULL;
49856e89960Smrg   GLbitfield enabledFragUnits = 0x0;
4997117f1b4Smrg
500ac997013Sriastradh   if (ctx->Shader.CurrentVertexProgram &&
501ac997013Sriastradh       ctx->Shader.CurrentVertexProgram->LinkStatus) {
502ac997013Sriastradh      vprog = ctx->Shader.CurrentVertexProgram->VertexProgram;
503ac997013Sriastradh   } else if (ctx->VertexProgram._Enabled) {
504ac997013Sriastradh      /* XXX enable this if/when non-shader vertex programs get
505ac997013Sriastradh       * texture fetches:
506ac997013Sriastradh       vprog = ctx->VertexProgram.Current;
507ac997013Sriastradh       */
5087117f1b4Smrg   }
509ac997013Sriastradh
510ac997013Sriastradh   if (ctx->Shader.CurrentFragmentProgram &&
511ac997013Sriastradh       ctx->Shader.CurrentFragmentProgram->LinkStatus) {
512ac997013Sriastradh      fprog = ctx->Shader.CurrentFragmentProgram->FragmentProgram;
513ac997013Sriastradh   }
514ac997013Sriastradh   else if (ctx->FragmentProgram._Enabled) {
515ac997013Sriastradh      fprog = ctx->FragmentProgram.Current;
5167117f1b4Smrg   }
5177117f1b4Smrg
518ac997013Sriastradh   /* FINISHME: Geometry shader texture accesses should also be considered
519ac997013Sriastradh    * FINISHME: here.
520ac997013Sriastradh    */
521ac997013Sriastradh
52256e89960Smrg   /* TODO: only set this if there are actual changes */
52356e89960Smrg   ctx->NewState |= _NEW_TEXTURE;
5247117f1b4Smrg
52556e89960Smrg   ctx->Texture._EnabledUnits = 0x0;
52656e89960Smrg   ctx->Texture._GenFlags = 0x0;
52756e89960Smrg   ctx->Texture._TexMatEnabled = 0x0;
52856e89960Smrg   ctx->Texture._TexGenEnabled = 0x0;
5297117f1b4Smrg
5307117f1b4Smrg   /*
5317117f1b4Smrg    * Update texture unit state.
5327117f1b4Smrg    */
5331f16d945Smrg   for (unit = 0; unit < ctx->Const.MaxCombinedTextureImageUnits; unit++) {
5347117f1b4Smrg      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
53556e89960Smrg      GLbitfield enabledVertTargets = 0x0;
53656e89960Smrg      GLbitfield enabledFragTargets = 0x0;
53756e89960Smrg      GLbitfield enabledTargets = 0x0;
53856e89960Smrg      GLuint texIndex;
5397117f1b4Smrg
540c1f859d4Smrg      /* Get the bitmask of texture target enables.
5417117f1b4Smrg       * enableBits will be a mask of the TEXTURE_*_BIT flags indicating
5427117f1b4Smrg       * which texture targets are enabled (fixed function) or referenced
543ac997013Sriastradh       * by a fragment program/program.  When multiple flags are set, we'll
54456e89960Smrg       * settle on the one with highest priority (see below).
5457117f1b4Smrg       */
546c1f859d4Smrg      if (vprog) {
54756e89960Smrg         enabledVertTargets |= vprog->Base.TexturesUsed[unit];
548c1f859d4Smrg      }
54956e89960Smrg
550c1f859d4Smrg      if (fprog) {
55156e89960Smrg         enabledFragTargets |= fprog->Base.TexturesUsed[unit];
5527117f1b4Smrg      }
5537117f1b4Smrg      else {
554c1f859d4Smrg         /* fixed-function fragment program */
55556e89960Smrg         enabledFragTargets |= texUnit->Enabled;
556c1f859d4Smrg      }
557c1f859d4Smrg
55856e89960Smrg      enabledTargets = enabledVertTargets | enabledFragTargets;
559c1f859d4Smrg
56056e89960Smrg      texUnit->_ReallyEnabled = 0x0;
56156e89960Smrg
56256e89960Smrg      if (enabledTargets == 0x0) {
56356e89960Smrg         /* neither vertex nor fragment processing uses this unit */
56456e89960Smrg         continue;
5657117f1b4Smrg      }
5667117f1b4Smrg
56756e89960Smrg      /* Look for the highest priority texture target that's enabled (or used
56856e89960Smrg       * by the vert/frag shaders) and "complete".  That's the one we'll use
56956e89960Smrg       * for texturing.  If we're using vert/frag program we're guaranteed
57056e89960Smrg       * that bitcount(enabledBits) <= 1.
57156e89960Smrg       * Note that the TEXTURE_x_INDEX values are in high to low priority.
5727117f1b4Smrg       */
57356e89960Smrg      for (texIndex = 0; texIndex < NUM_TEXTURE_TARGETS; texIndex++) {
57456e89960Smrg         if (enabledTargets & (1 << texIndex)) {
57556e89960Smrg            struct gl_texture_object *texObj = texUnit->CurrentTex[texIndex];
57656e89960Smrg            if (!texObj->_Complete) {
57756e89960Smrg               _mesa_test_texobj_completeness(ctx, texObj);
57856e89960Smrg            }
57956e89960Smrg            if (texObj->_Complete) {
58056e89960Smrg               texUnit->_ReallyEnabled = 1 << texIndex;
58156e89960Smrg               _mesa_reference_texobj(&texUnit->_Current, texObj);
58256e89960Smrg               break;
58356e89960Smrg            }
58456e89960Smrg         }
585c1f859d4Smrg      }
5867117f1b4Smrg
5877117f1b4Smrg      if (!texUnit->_ReallyEnabled) {
58856e89960Smrg         if (fprog) {
58956e89960Smrg            /* If we get here it means the shader is expecting a texture
59056e89960Smrg             * object, but there isn't one (or it's incomplete).  Use the
59156e89960Smrg             * fallback texture.
59256e89960Smrg             */
59356e89960Smrg            struct gl_texture_object *texObj = _mesa_get_fallback_texture(ctx);
59456e89960Smrg            texUnit->_ReallyEnabled = 1 << TEXTURE_2D_INDEX;
59556e89960Smrg            _mesa_reference_texobj(&texUnit->_Current, texObj);
5967117f1b4Smrg         }
59756e89960Smrg         else {
59856e89960Smrg            /* fixed-function: texture unit is really disabled */
59956e89960Smrg            continue;
6007117f1b4Smrg         }
6017117f1b4Smrg      }
6027117f1b4Smrg
60356e89960Smrg      /* if we get here, we know this texture unit is enabled */
6047117f1b4Smrg
60556e89960Smrg      ctx->Texture._EnabledUnits |= (1 << unit);
60656e89960Smrg
60756e89960Smrg      if (enabledFragTargets)
60856e89960Smrg         enabledFragUnits |= (1 << unit);
60956e89960Smrg
61056e89960Smrg      update_tex_combine(ctx, texUnit);
611c1f859d4Smrg   }
612c1f859d4Smrg
61356e89960Smrg
614c1f859d4Smrg   /* Determine which texture coordinate sets are actually needed */
615c1f859d4Smrg   if (fprog) {
616c1f859d4Smrg      const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1;
617c1f859d4Smrg      ctx->Texture._EnabledCoordUnits
618c1f859d4Smrg         = (fprog->Base.InputsRead >> FRAG_ATTRIB_TEX0) & coordMask;
619c1f859d4Smrg   }
620c1f859d4Smrg   else {
62156e89960Smrg      ctx->Texture._EnabledCoordUnits = enabledFragUnits;
622c1f859d4Smrg   }
623c1f859d4Smrg
624c1f859d4Smrg   /* Setup texgen for those texture coordinate sets that are in use */
625c1f859d4Smrg   for (unit = 0; unit < ctx->Const.MaxTextureCoordUnits; unit++) {
626c1f859d4Smrg      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
627c1f859d4Smrg
62856e89960Smrg      texUnit->_GenFlags = 0x0;
62956e89960Smrg
630c1f859d4Smrg      if (!(ctx->Texture._EnabledCoordUnits & (1 << unit)))
631c1f859d4Smrg	 continue;
6327117f1b4Smrg
6337117f1b4Smrg      if (texUnit->TexGenEnabled) {
6347117f1b4Smrg	 if (texUnit->TexGenEnabled & S_BIT) {
63556e89960Smrg	    texUnit->_GenFlags |= texUnit->GenS._ModeBit;
6367117f1b4Smrg	 }
6377117f1b4Smrg	 if (texUnit->TexGenEnabled & T_BIT) {
63856e89960Smrg	    texUnit->_GenFlags |= texUnit->GenT._ModeBit;
6397117f1b4Smrg	 }
6407117f1b4Smrg	 if (texUnit->TexGenEnabled & R_BIT) {
64156e89960Smrg	    texUnit->_GenFlags |= texUnit->GenR._ModeBit;
64256e89960Smrg	 }
64356e89960Smrg	 if (texUnit->TexGenEnabled & Q_BIT) {
64456e89960Smrg	    texUnit->_GenFlags |= texUnit->GenQ._ModeBit;
6457117f1b4Smrg	 }
6467117f1b4Smrg
6477117f1b4Smrg	 ctx->Texture._TexGenEnabled |= ENABLE_TEXGEN(unit);
6487117f1b4Smrg	 ctx->Texture._GenFlags |= texUnit->_GenFlags;
6497117f1b4Smrg      }
6507117f1b4Smrg
6511f16d945Smrg      ASSERT(unit < Elements(ctx->TextureMatrixStack));
6527117f1b4Smrg      if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY)
6537117f1b4Smrg	 ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(unit);
6547117f1b4Smrg   }
6557117f1b4Smrg}
6567117f1b4Smrg
6577117f1b4Smrg
6587117f1b4Smrg/**
6597117f1b4Smrg * Update texture-related derived state.
6607117f1b4Smrg */
6617117f1b4Smrgvoid
662ac997013Sriastradh_mesa_update_texture( struct gl_context *ctx, GLuint new_state )
6637117f1b4Smrg{
6647117f1b4Smrg   if (new_state & _NEW_TEXTURE_MATRIX)
6657117f1b4Smrg      update_texture_matrices( ctx );
6667117f1b4Smrg
6677117f1b4Smrg   if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM))
6687117f1b4Smrg      update_texture_state( ctx );
6697117f1b4Smrg}
6707117f1b4Smrg
6717117f1b4Smrg
6727117f1b4Smrg/**********************************************************************/
6737117f1b4Smrg/*****                      Initialization                        *****/
6747117f1b4Smrg/**********************************************************************/
6757117f1b4Smrg
6767117f1b4Smrg/**
6777117f1b4Smrg * Allocate the proxy textures for the given context.
6787117f1b4Smrg *
6797117f1b4Smrg * \param ctx the context to allocate proxies for.
6807117f1b4Smrg *
6817117f1b4Smrg * \return GL_TRUE on success, or GL_FALSE on failure
6827117f1b4Smrg *
6837117f1b4Smrg * If run out of memory part way through the allocations, clean up and return
6847117f1b4Smrg * GL_FALSE.
6857117f1b4Smrg */
6867117f1b4Smrgstatic GLboolean
687ac997013Sriastradhalloc_proxy_textures( struct gl_context *ctx )
6887117f1b4Smrg{
689c1f859d4Smrg   static const GLenum targets[] = {
690c1f859d4Smrg      GL_TEXTURE_1D,
691c1f859d4Smrg      GL_TEXTURE_2D,
692c1f859d4Smrg      GL_TEXTURE_3D,
693c1f859d4Smrg      GL_TEXTURE_CUBE_MAP_ARB,
694c1f859d4Smrg      GL_TEXTURE_RECTANGLE_NV,
695c1f859d4Smrg      GL_TEXTURE_1D_ARRAY_EXT,
696ac997013Sriastradh      GL_TEXTURE_2D_ARRAY_EXT,
697ac997013Sriastradh      GL_TEXTURE_BUFFER
698c1f859d4Smrg   };
699c1f859d4Smrg   GLint tgt;
7007117f1b4Smrg
701c1f859d4Smrg   ASSERT(Elements(targets) == NUM_TEXTURE_TARGETS);
7027117f1b4Smrg
703c1f859d4Smrg   for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
704c1f859d4Smrg      if (!(ctx->Texture.ProxyTex[tgt]
705c1f859d4Smrg            = ctx->Driver.NewTextureObject(ctx, 0, targets[tgt]))) {
706c1f859d4Smrg         /* out of memory, free what we did allocate */
707c1f859d4Smrg         while (--tgt >= 0) {
708c1f859d4Smrg            ctx->Driver.DeleteTexture(ctx, ctx->Texture.ProxyTex[tgt]);
709c1f859d4Smrg         }
710c1f859d4Smrg         return GL_FALSE;
711c1f859d4Smrg      }
712c1f859d4Smrg   }
7137117f1b4Smrg
714c1f859d4Smrg   assert(ctx->Texture.ProxyTex[0]->RefCount == 1); /* sanity check */
7157117f1b4Smrg   return GL_TRUE;
7167117f1b4Smrg}
7177117f1b4Smrg
7187117f1b4Smrg
7197117f1b4Smrg/**
7207117f1b4Smrg * Initialize a texture unit.
7217117f1b4Smrg *
7227117f1b4Smrg * \param ctx GL context.
7237117f1b4Smrg * \param unit texture unit number to be initialized.
7247117f1b4Smrg */
7257117f1b4Smrgstatic void
726ac997013Sriastradhinit_texture_unit( struct gl_context *ctx, GLuint unit )
7277117f1b4Smrg{
7287117f1b4Smrg   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
729c1f859d4Smrg   GLuint tex;
7307117f1b4Smrg
7317117f1b4Smrg   texUnit->EnvMode = GL_MODULATE;
7327117f1b4Smrg   ASSIGN_4V( texUnit->EnvColor, 0.0, 0.0, 0.0, 0.0 );
7337117f1b4Smrg
7347117f1b4Smrg   texUnit->Combine = default_combine_state;
7357117f1b4Smrg   texUnit->_EnvMode = default_combine_state;
7367117f1b4Smrg   texUnit->_CurrentCombine = & texUnit->_EnvMode;
73756e89960Smrg   texUnit->BumpTarget = GL_TEXTURE0;
73856e89960Smrg
73956e89960Smrg   texUnit->TexGenEnabled = 0x0;
74056e89960Smrg   texUnit->GenS.Mode = GL_EYE_LINEAR;
74156e89960Smrg   texUnit->GenT.Mode = GL_EYE_LINEAR;
74256e89960Smrg   texUnit->GenR.Mode = GL_EYE_LINEAR;
74356e89960Smrg   texUnit->GenQ.Mode = GL_EYE_LINEAR;
74456e89960Smrg   texUnit->GenS._ModeBit = TEXGEN_EYE_LINEAR;
74556e89960Smrg   texUnit->GenT._ModeBit = TEXGEN_EYE_LINEAR;
74656e89960Smrg   texUnit->GenR._ModeBit = TEXGEN_EYE_LINEAR;
74756e89960Smrg   texUnit->GenQ._ModeBit = TEXGEN_EYE_LINEAR;
7487117f1b4Smrg
7497117f1b4Smrg   /* Yes, these plane coefficients are correct! */
75056e89960Smrg   ASSIGN_4V( texUnit->GenS.ObjectPlane, 1.0, 0.0, 0.0, 0.0 );
75156e89960Smrg   ASSIGN_4V( texUnit->GenT.ObjectPlane, 0.0, 1.0, 0.0, 0.0 );
75256e89960Smrg   ASSIGN_4V( texUnit->GenR.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
75356e89960Smrg   ASSIGN_4V( texUnit->GenQ.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
75456e89960Smrg   ASSIGN_4V( texUnit->GenS.EyePlane, 1.0, 0.0, 0.0, 0.0 );
75556e89960Smrg   ASSIGN_4V( texUnit->GenT.EyePlane, 0.0, 1.0, 0.0, 0.0 );
75656e89960Smrg   ASSIGN_4V( texUnit->GenR.EyePlane, 0.0, 0.0, 0.0, 0.0 );
75756e89960Smrg   ASSIGN_4V( texUnit->GenQ.EyePlane, 0.0, 0.0, 0.0, 0.0 );
75856e89960Smrg
75956e89960Smrg   /* no mention of this in spec, but maybe id matrix expected? */
76056e89960Smrg   ASSIGN_4V( texUnit->RotMatrix, 1.0, 0.0, 0.0, 1.0 );
7617117f1b4Smrg
7627117f1b4Smrg   /* initialize current texture object ptrs to the shared default objects */
763c1f859d4Smrg   for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
764c1f859d4Smrg      _mesa_reference_texobj(&texUnit->CurrentTex[tex],
765c1f859d4Smrg                             ctx->Shared->DefaultTex[tex]);
766c1f859d4Smrg   }
7677117f1b4Smrg}
7687117f1b4Smrg
7697117f1b4Smrg
7707117f1b4Smrg/**
7717117f1b4Smrg * Initialize texture state for the given context.
7727117f1b4Smrg */
7737117f1b4SmrgGLboolean
774ac997013Sriastradh_mesa_init_texture(struct gl_context *ctx)
7757117f1b4Smrg{
77656e89960Smrg   GLuint u;
7777117f1b4Smrg
7787117f1b4Smrg   /* Texture group */
7797117f1b4Smrg   ctx->Texture.CurrentUnit = 0;      /* multitexture */
78056e89960Smrg   ctx->Texture._EnabledUnits = 0x0;
7817117f1b4Smrg   ctx->Texture.SharedPalette = GL_FALSE;
7827117f1b4Smrg   _mesa_init_colortable(&ctx->Texture.Palette);
7837117f1b4Smrg
7841f16d945Smrg   for (u = 0; u < Elements(ctx->Texture.Unit); u++)
78556e89960Smrg      init_texture_unit(ctx, u);
7867117f1b4Smrg
7877117f1b4Smrg   /* After we're done initializing the context's texture state the default
7881f16d945Smrg    * texture objects' refcounts should be at least
7891f16d945Smrg    * MAX_COMBINED_TEXTURE_IMAGE_UNITS + 1.
7907117f1b4Smrg    */
791c1f859d4Smrg   assert(ctx->Shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount
7921f16d945Smrg          >= MAX_COMBINED_TEXTURE_IMAGE_UNITS + 1);
7937117f1b4Smrg
7947117f1b4Smrg   /* Allocate proxy textures */
7957117f1b4Smrg   if (!alloc_proxy_textures( ctx ))
7967117f1b4Smrg      return GL_FALSE;
7977117f1b4Smrg
798ac997013Sriastradh   /* GL_ARB_texture_buffer_object */
799ac997013Sriastradh   _mesa_reference_buffer_object(ctx, &ctx->Texture.BufferObject,
800ac997013Sriastradh                                 ctx->Shared->NullBufferObj);
801ac997013Sriastradh
8027117f1b4Smrg   return GL_TRUE;
8037117f1b4Smrg}
8047117f1b4Smrg
8057117f1b4Smrg
8067117f1b4Smrg/**
807c1f859d4Smrg * Free dynamically-allocted texture data attached to the given context.
8087117f1b4Smrg */
8097117f1b4Smrgvoid
810ac997013Sriastradh_mesa_free_texture_data(struct gl_context *ctx)
8117117f1b4Smrg{
812c1f859d4Smrg   GLuint u, tgt;
8137117f1b4Smrg
8147117f1b4Smrg   /* unreference current textures */
8151f16d945Smrg   for (u = 0; u < Elements(ctx->Texture.Unit); u++) {
816c1f859d4Smrg      /* The _Current texture could account for another reference */
817c1f859d4Smrg      _mesa_reference_texobj(&ctx->Texture.Unit[u]._Current, NULL);
818c1f859d4Smrg
819c1f859d4Smrg      for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
82056e89960Smrg         _mesa_reference_texobj(&ctx->Texture.Unit[u].CurrentTex[tgt], NULL);
821c1f859d4Smrg      }
8227117f1b4Smrg   }
8237117f1b4Smrg
8247117f1b4Smrg   /* Free proxy texture objects */
825c1f859d4Smrg   for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++)
826c1f859d4Smrg      ctx->Driver.DeleteTexture(ctx, ctx->Texture.ProxyTex[tgt]);
827c1f859d4Smrg
828ac997013Sriastradh   /* GL_ARB_texture_buffer_object */
829ac997013Sriastradh   _mesa_reference_buffer_object(ctx, &ctx->Texture.BufferObject, NULL);
830ac997013Sriastradh
831ac997013Sriastradh#if FEATURE_sampler_objects
832ac997013Sriastradh   for (u = 0; u < Elements(ctx->Texture.Unit); u++) {
833ac997013Sriastradh      _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[u].Sampler, NULL);
834ac997013Sriastradh   }
835ac997013Sriastradh#endif
836c1f859d4Smrg}
837c1f859d4Smrg
8387117f1b4Smrg
839c1f859d4Smrg/**
840c1f859d4Smrg * Update the default texture objects in the given context to reference those
841c1f859d4Smrg * specified in the shared state and release those referencing the old
842c1f859d4Smrg * shared state.
843c1f859d4Smrg */
844c1f859d4Smrgvoid
845ac997013Sriastradh_mesa_update_default_objects_texture(struct gl_context *ctx)
846c1f859d4Smrg{
84756e89960Smrg   GLuint u, tex;
8487117f1b4Smrg
8491f16d945Smrg   for (u = 0; u < Elements(ctx->Texture.Unit); u++) {
85056e89960Smrg      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[u];
851c1f859d4Smrg      for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
852c1f859d4Smrg         _mesa_reference_texobj(&texUnit->CurrentTex[tex],
853c1f859d4Smrg                                ctx->Shared->DefaultTex[tex]);
854c1f859d4Smrg      }
855c1f859d4Smrg   }
8567117f1b4Smrg}
857