summaryrefslogtreecommitdiff
path: root/src/mesa/main/texstate.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/main/texstate.c')
-rw-r--r--src/mesa/main/texstate.c350
1 files changed, 348 insertions, 2 deletions
diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c
index 9359c7b1b1..59fd7a9928 100644
--- a/src/mesa/main/texstate.c
+++ b/src/mesa/main/texstate.c
@@ -25,10 +25,12 @@
#include "glheader.h"
#include "colormac.h"
+#include "colortab.h"
#include "context.h"
#include "enums.h"
#include "extensions.h"
#include "macros.h"
+#include "nvfragprog.h"
#include "texobj.h"
#include "teximage.h"
#include "texstate.h"
@@ -1909,7 +1911,7 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
/* Texture Coord Generation */
/**********************************************************************/
-
+#if FEATURE_texgen
void
_mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
{
@@ -2458,7 +2460,7 @@ _mesa_GetTexGeniv( GLenum coord, GLenum pname, GLint *params )
return;
}
}
-
+#endif
/* GL_ARB_multitexture */
void
@@ -2643,3 +2645,347 @@ _mesa_GetPixelTexGenParameterivSGIS(GLenum target, GLint *value)
_mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelTexGenParameterivSGIS(target)");
}
}
+
+
+
+/**********************************************************************/
+/***** State management *****/
+/**********************************************************************/
+
+
+/**
+ * \note This routine refers to derived texture attribute values to
+ * compute the ENABLE_TEXMAT flags, but is only called on
+ * _NEW_TEXTURE_MATRIX. On changes to _NEW_TEXTURE, the ENABLE_TEXMAT
+ * flags are updated by _mesa_update_textures(), below.
+ *
+ * \param ctx GL context.
+ */
+static void
+update_texture_matrices( GLcontext *ctx )
+{
+ GLuint i;
+
+ ctx->Texture._TexMatEnabled = 0;
+
+ for (i=0; i < ctx->Const.MaxTextureUnits; i++) {
+ if (ctx->TextureMatrixStack[i].Top->flags & MAT_DIRTY) {
+ _math_matrix_analyse( ctx->TextureMatrixStack[i].Top );
+
+ if (ctx->Texture.Unit[i]._ReallyEnabled &&
+ ctx->TextureMatrixStack[i].Top->type != MATRIX_IDENTITY)
+ ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(i);
+
+ if (ctx->Driver.TextureMatrix)
+ ctx->Driver.TextureMatrix( ctx, i, ctx->TextureMatrixStack[i].Top);
+ }
+ }
+}
+
+
+
+
+/**
+ * \note This routine refers to derived texture matrix values to
+ * compute the ENABLE_TEXMAT flags, but is only called on
+ * _NEW_TEXTURE. On changes to _NEW_TEXTURE_MATRIX, the ENABLE_TEXMAT
+ * flags are updated by _mesa_update_texture_matrices, above.
+ *
+ * \param ctx GL context.
+ */
+static void
+update_texture_state( GLcontext *ctx )
+{
+ GLuint unit;
+
+ ctx->Texture._EnabledUnits = 0;
+ ctx->Texture._GenFlags = 0;
+ ctx->Texture._TexMatEnabled = 0;
+ ctx->Texture._TexGenEnabled = 0;
+
+ /* Update texture unit state.
+ * XXX this loop should probably be broken into separate loops for
+ * texture coord units and texture image units.
+ */
+ for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ GLuint enableBits;
+
+ texUnit->_ReallyEnabled = 0;
+ texUnit->_GenFlags = 0;
+
+ /* Get the bitmask of texture enables */
+ if (ctx->FragmentProgram.Enabled && ctx->FragmentProgram.Current) {
+ enableBits = ctx->FragmentProgram.Current->TexturesUsed[unit];
+ }
+ else {
+ if (!texUnit->Enabled)
+ continue;
+ enableBits = texUnit->Enabled;
+ }
+
+ /* Look for the highest-priority texture target that's enabled and
+ * complete. That's the one we'll use for texturing. If we're using
+ * a fragment program we're guaranteed that bitcount(enabledBits) <= 1.
+ */
+ if (texUnit->Enabled & TEXTURE_CUBE_BIT) {
+ struct gl_texture_object *texObj = texUnit->CurrentCubeMap;
+ if (!texObj->Complete) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ }
+ if (texObj->Complete) {
+ texUnit->_ReallyEnabled = TEXTURE_CUBE_BIT;
+ texUnit->_Current = texObj;
+ }
+ }
+
+ if (!texUnit->_ReallyEnabled && (texUnit->Enabled & TEXTURE_3D_BIT)) {
+ struct gl_texture_object *texObj = texUnit->Current3D;
+ if (!texObj->Complete) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ }
+ if (texObj->Complete) {
+ texUnit->_ReallyEnabled = TEXTURE_3D_BIT;
+ texUnit->_Current = texObj;
+ }
+ }
+
+ if (!texUnit->_ReallyEnabled && (texUnit->Enabled & TEXTURE_RECT_BIT)) {
+ struct gl_texture_object *texObj = texUnit->CurrentRect;
+ if (!texObj->Complete) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ }
+ if (texObj->Complete) {
+ texUnit->_ReallyEnabled = TEXTURE_RECT_BIT;
+ texUnit->_Current = texObj;
+ }
+ }
+
+ if (!texUnit->_ReallyEnabled && (texUnit->Enabled & TEXTURE_2D_BIT)) {
+ struct gl_texture_object *texObj = texUnit->Current2D;
+ if (!texObj->Complete) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ }
+ if (texObj->Complete) {
+ texUnit->_ReallyEnabled = TEXTURE_2D_BIT;
+ texUnit->_Current = texObj;
+ }
+ }
+
+ if (!texUnit->_ReallyEnabled && (texUnit->Enabled & TEXTURE_1D_BIT)) {
+ struct gl_texture_object *texObj = texUnit->Current1D;
+ if (!texObj->Complete) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ }
+ if (texObj->Complete) {
+ texUnit->_ReallyEnabled = TEXTURE_1D_BIT;
+ texUnit->_Current = texObj;
+ }
+ }
+
+ if (!texUnit->_ReallyEnabled) {
+ texUnit->_Current = NULL;
+ continue;
+ }
+
+ if (texUnit->_ReallyEnabled)
+ ctx->Texture._EnabledUnits |= (1 << unit);
+
+ if (texUnit->TexGenEnabled) {
+ if (texUnit->TexGenEnabled & S_BIT) {
+ texUnit->_GenFlags |= texUnit->_GenBitS;
+ }
+ if (texUnit->TexGenEnabled & T_BIT) {
+ texUnit->_GenFlags |= texUnit->_GenBitT;
+ }
+ if (texUnit->TexGenEnabled & Q_BIT) {
+ texUnit->_GenFlags |= texUnit->_GenBitQ;
+ }
+ if (texUnit->TexGenEnabled & R_BIT) {
+ texUnit->_GenFlags |= texUnit->_GenBitR;
+ }
+
+ ctx->Texture._TexGenEnabled |= ENABLE_TEXGEN(unit);
+ ctx->Texture._GenFlags |= texUnit->_GenFlags;
+ }
+
+ if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY)
+ ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(unit);
+ }
+
+ ctx->Texture._EnabledCoordUnits = ctx->Texture._EnabledUnits;
+ /* Fragment programs may need texture coordinates but not the
+ * corresponding texture images.
+ */
+ if (ctx->FragmentProgram.Enabled && ctx->FragmentProgram.Current) {
+ ctx->Texture._EnabledCoordUnits |=
+ (ctx->FragmentProgram.Current->InputsRead >> FRAG_ATTRIB_TEX0);
+ }
+}
+
+
+void _mesa_update_texture( GLcontext *ctx, GLuint new_state )
+{
+ if (new_state & _NEW_TEXTURE_MATRIX)
+ update_texture_matrices( ctx );
+
+ if (new_state & _NEW_TEXTURE)
+ update_texture_state( ctx );
+}
+
+/**********************************************************************/
+/***** Initialization *****/
+/**********************************************************************/
+
+/**
+ * Allocate the proxy textures for the given context.
+ *
+ * \param ctx the context to allocate proxies for.
+ *
+ * \return GL_TRUE on success, or GL_FALSE on failure
+ *
+ * If run out of memory part way through the allocations, clean up and return
+ * GL_FALSE.
+ */
+static GLboolean
+alloc_proxy_textures( GLcontext *ctx )
+{
+ ctx->Texture.Proxy1D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_1D);
+ if (!ctx->Texture.Proxy1D)
+ goto cleanup;
+
+ ctx->Texture.Proxy2D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_2D);
+ if (!ctx->Texture.Proxy2D)
+ goto cleanup;
+
+ ctx->Texture.Proxy3D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_3D);
+ if (!ctx->Texture.Proxy3D)
+ goto cleanup;
+
+ ctx->Texture.ProxyCubeMap = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_CUBE_MAP_ARB);
+ if (!ctx->Texture.ProxyCubeMap)
+ goto cleanup;
+
+ ctx->Texture.ProxyRect = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_RECTANGLE_NV);
+ if (!ctx->Texture.ProxyRect)
+ goto cleanup;
+
+ return GL_TRUE;
+
+ cleanup:
+ if (ctx->Texture.Proxy1D)
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy1D);
+ if (ctx->Texture.Proxy2D)
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy2D);
+ if (ctx->Texture.Proxy3D)
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy3D);
+ if (ctx->Texture.ProxyCubeMap)
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyCubeMap);
+ if (ctx->Texture.ProxyRect)
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyRect);
+ return GL_FALSE;
+}
+
+
+/**
+ * Initialize a texture unit.
+ *
+ * \param ctx GL context.
+ * \param unit texture unit number to be initialized.
+ */
+static void
+init_texture_unit( GLcontext *ctx, GLuint unit )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+ texUnit->EnvMode = GL_MODULATE;
+ ASSIGN_4V( texUnit->EnvColor, 0.0, 0.0, 0.0, 0.0 );
+
+ texUnit->CombineModeRGB = GL_MODULATE;
+ texUnit->CombineModeA = GL_MODULATE;
+ texUnit->CombineSourceRGB[0] = GL_TEXTURE;
+ texUnit->CombineSourceRGB[1] = GL_PREVIOUS_EXT;
+ texUnit->CombineSourceRGB[2] = GL_CONSTANT_EXT;
+ texUnit->CombineSourceA[0] = GL_TEXTURE;
+ texUnit->CombineSourceA[1] = GL_PREVIOUS_EXT;
+ texUnit->CombineSourceA[2] = GL_CONSTANT_EXT;
+ texUnit->CombineOperandRGB[0] = GL_SRC_COLOR;
+ texUnit->CombineOperandRGB[1] = GL_SRC_COLOR;
+ texUnit->CombineOperandRGB[2] = GL_SRC_ALPHA;
+ texUnit->CombineOperandA[0] = GL_SRC_ALPHA;
+ texUnit->CombineOperandA[1] = GL_SRC_ALPHA;
+ texUnit->CombineOperandA[2] = GL_SRC_ALPHA;
+ texUnit->CombineScaleShiftRGB = 0;
+ texUnit->CombineScaleShiftA = 0;
+
+ texUnit->TexGenEnabled = 0;
+ texUnit->GenModeS = GL_EYE_LINEAR;
+ texUnit->GenModeT = GL_EYE_LINEAR;
+ texUnit->GenModeR = GL_EYE_LINEAR;
+ texUnit->GenModeQ = GL_EYE_LINEAR;
+ texUnit->_GenBitS = TEXGEN_EYE_LINEAR;
+ texUnit->_GenBitT = TEXGEN_EYE_LINEAR;
+ texUnit->_GenBitR = TEXGEN_EYE_LINEAR;
+ texUnit->_GenBitQ = TEXGEN_EYE_LINEAR;
+
+ /* Yes, these plane coefficients are correct! */
+ ASSIGN_4V( texUnit->ObjectPlaneS, 1.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->ObjectPlaneT, 0.0, 1.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->ObjectPlaneR, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->ObjectPlaneQ, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->EyePlaneS, 1.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->EyePlaneT, 0.0, 1.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->EyePlaneR, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->EyePlaneQ, 0.0, 0.0, 0.0, 0.0 );
+
+ texUnit->Current1D = ctx->Shared->Default1D;
+ texUnit->Current2D = ctx->Shared->Default2D;
+ texUnit->Current3D = ctx->Shared->Default3D;
+ texUnit->CurrentCubeMap = ctx->Shared->DefaultCubeMap;
+ texUnit->CurrentRect = ctx->Shared->DefaultRect;
+}
+
+
+GLboolean _mesa_init_texture( GLcontext * ctx )
+{
+ int i;
+
+ assert(MAX_TEXTURE_LEVELS >= MAX_3D_TEXTURE_LEVELS);
+ assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS);
+
+ /* Effectively bind the default textures to all texture units */
+ ctx->Shared->Default1D->RefCount += MAX_TEXTURE_UNITS;
+ ctx->Shared->Default2D->RefCount += MAX_TEXTURE_UNITS;
+ ctx->Shared->Default3D->RefCount += MAX_TEXTURE_UNITS;
+ ctx->Shared->DefaultCubeMap->RefCount += MAX_TEXTURE_UNITS;
+ ctx->Shared->DefaultRect->RefCount += MAX_TEXTURE_UNITS;
+
+ /* Texture group */
+ ctx->Texture.CurrentUnit = 0; /* multitexture */
+ ctx->Texture._EnabledUnits = 0;
+ for (i=0; i<MAX_TEXTURE_UNITS; i++)
+ init_texture_unit( ctx, i );
+ ctx->Texture.SharedPalette = GL_FALSE;
+ _mesa_init_one_colortable(&ctx->Texture.Palette);
+
+ /* Allocate proxy textures */
+ if (!alloc_proxy_textures( ctx ))
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+void _mesa_free_texture_data( GLcontext *ctx )
+{
+ int i;
+
+ /* Free proxy texture objects */
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy1D );
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy2D );
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy3D );
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyCubeMap );
+ (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyRect );
+
+ for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
+ _mesa_free_colortable_data( &ctx->Texture.Unit[i].ColorTable );
+}