X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fattrib.c;h=218e0aeb6b750913d1a75f995938423c88104418;hb=88e0b92a747d9b14885010029133fa1221696e5e;hp=339c40b9bdd5235eae40c21e2fb78b2d383ba4c3;hpb=7a6b71ef2944bae1718e8167b2faaceb8422071c;p=mesa.git diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c index 339c40b9bdd..218e0aeb6b7 100644 --- a/src/mesa/main/attrib.c +++ b/src/mesa/main/attrib.c @@ -1,8 +1,9 @@ /* * Mesa 3-D graphics library - * Version: 6.1 + * Version: 7.3 * - * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (C) 2009 VMware, Inc. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,10 +26,12 @@ #include "glheader.h" #include "imports.h" #include "accum.h" +#include "arrayobj.h" #include "attrib.h" #include "blend.h" #include "buffers.h" #include "bufferobj.h" +#include "clear.h" #include "colormac.h" #include "colortab.h" #include "context.h" @@ -40,17 +43,40 @@ #include "light.h" #include "lines.h" #include "matrix.h" +#include "multisample.h" #include "points.h" #include "polygon.h" +#include "scissor.h" #include "simple_list.h" #include "stencil.h" +#include "texenv.h" +#include "texgen.h" #include "texobj.h" +#include "texparam.h" #include "texstate.h" +#include "varray.h" #include "mtypes.h" #include "math/m_xform.h" +/** + * Special struct for saving/restoring texture state (GL_TEXTURE_BIT) + */ +struct texture_state +{ + struct gl_texture_attrib Texture; /**< The usual context state */ -/* + /** to save per texture object state (wrap modes, filters, etc): */ + struct gl_texture_object SavedObj[MAX_TEXTURE_UNITS][NUM_TEXTURE_TARGETS]; + + /** + * To save references to texture objects (so they don't get accidentally + * deleted while saved in the attribute stack). + */ + struct gl_texture_object *SavedTexRef[MAX_TEXTURE_UNITS][NUM_TEXTURE_TARGETS]; +}; + + +/** * Allocate a new attribute state node. These nodes have a * "kind" value and a pointer to a struct of state data. */ @@ -97,9 +123,13 @@ _mesa_PushAttrib(GLbitfield mask) } if (mask & GL_COLOR_BUFFER_BIT) { + GLuint i; struct gl_colorbuffer_attrib *attr; attr = MALLOC_STRUCT( gl_colorbuffer_attrib ); MEMCPY( attr, &ctx->Color, sizeof(struct gl_colorbuffer_attrib) ); + /* push the Draw FBO's DrawBuffer[] state, not ctx->Color.DrawBuffer[] */ + for (i = 0; i < ctx->Const.MaxDrawBuffers; i ++) + attr->DrawBuffer[i] = ctx->DrawBuffer->ColorDrawBuffer[i]; newnode = new_attrib_node( GL_COLOR_BUFFER_BIT ); newnode->data = attr; newnode->next = head; @@ -137,9 +167,9 @@ _mesa_PushAttrib(GLbitfield mask) attr->Blend = ctx->Color.BlendEnabled; attr->ClipPlanes = ctx->Transform.ClipPlanesEnabled; attr->ColorMaterial = ctx->Light.ColorMaterialEnabled; - attr->ColorTable = ctx->Pixel.ColorTableEnabled; - attr->PostColorMatrixColorTable = ctx->Pixel.PostColorMatrixColorTableEnabled; - attr->PostConvolutionColorTable = ctx->Pixel.PostConvolutionColorTableEnabled; + for (i = 0; i < COLORTABLE_MAX; i++) { + attr->ColorTable[i] = ctx->Pixel.ColorTableEnabled[i]; + } attr->Convolution1D = ctx->Pixel.Convolution1DEnabled; attr->Convolution2D = ctx->Pixel.Convolution2DEnabled; attr->Separable2D = ctx->Pixel.Separable2DEnabled; @@ -147,7 +177,7 @@ _mesa_PushAttrib(GLbitfield mask) attr->DepthTest = ctx->Depth.Test; attr->Dither = ctx->Color.DitherFlag; attr->Fog = ctx->Fog.Enabled; - for (i=0;iConst.MaxLights; i++) { attr->Light[i] = ctx->Light.Light[i].Enabled; } attr->Lighting = ctx->Light.Enabled; @@ -179,7 +209,6 @@ _mesa_PushAttrib(GLbitfield mask) MEMCPY(attr->Map2Attrib, ctx->Eval.Map2Attrib, sizeof(ctx->Eval.Map2Attrib)); attr->Normalize = ctx->Transform.Normalize; attr->RasterPositionUnclipped = ctx->Transform.RasterPositionUnclipped; - attr->PixelTexture = ctx->Pixel.PixelTextureEnabled; attr->PointSmooth = ctx->Point.SmoothFlag; attr->PointSprite = ctx->Point.PointSprite; attr->PolygonOffsetPoint = ctx->Polygon.OffsetPoint; @@ -190,12 +219,13 @@ _mesa_PushAttrib(GLbitfield mask) attr->RescaleNormals = ctx->Transform.RescaleNormals; attr->Scissor = ctx->Scissor.Enabled; attr->Stencil = ctx->Stencil.Enabled; + attr->StencilTwoSide = ctx->Stencil.TestTwoSide; attr->MultisampleEnabled = ctx->Multisample.Enabled; attr->SampleAlphaToCoverage = ctx->Multisample.SampleAlphaToCoverage; attr->SampleAlphaToOne = ctx->Multisample.SampleAlphaToOne; attr->SampleCoverage = ctx->Multisample.SampleCoverage; attr->SampleCoverageInvert = ctx->Multisample.SampleCoverageInvert; - for (i=0; iConst.MaxTextureUnits; i++) { attr->Texture[i] = ctx->Texture.Unit[i].Enabled; attr->TexGen[i] = ctx->Texture.Unit[i].TexGenEnabled; attr->TextureColorTable[i] = ctx->Texture.Unit[i].ColorTableEnabled; @@ -275,6 +305,8 @@ _mesa_PushAttrib(GLbitfield mask) struct gl_pixel_attrib *attr; attr = MALLOC_STRUCT( gl_pixel_attrib ); MEMCPY( attr, &ctx->Pixel, sizeof(struct gl_pixel_attrib) ); + /* push the Read FBO's ReadBuffer state, not ctx->Pixel.ReadBuffer */ + attr->ReadBuffer = ctx->ReadBuffer->ColorReadBuffer; newnode = new_attrib_node( GL_PIXEL_MODE_BIT ); newnode->data = attr; newnode->next = head; @@ -332,35 +364,61 @@ _mesa_PushAttrib(GLbitfield mask) } if (mask & GL_TEXTURE_BIT) { - struct gl_texture_attrib *attr; + struct texture_state *texstate = CALLOC_STRUCT(texture_state); GLuint u; - /* Bump the texture object reference counts so that they don't - * inadvertantly get deleted. + + if (!texstate) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib(GL_TEXTURE_BIT)"); + goto end; + } + + _mesa_lock_context_textures(ctx); + + /* copy/save the bulk of texture state here */ + _mesa_memcpy(&texstate->Texture, &ctx->Texture, sizeof(ctx->Texture)); + + /* Save references to the currently bound texture objects so they don't + * accidentally get deleted while referenced in the attribute stack. */ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { - ctx->Texture.Unit[u].Current1D->RefCount++; - ctx->Texture.Unit[u].Current2D->RefCount++; - ctx->Texture.Unit[u].Current3D->RefCount++; - ctx->Texture.Unit[u].CurrentCubeMap->RefCount++; - ctx->Texture.Unit[u].CurrentRect->RefCount++; + _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_1D_INDEX], + ctx->Texture.Unit[u].Current1D); + _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_2D_INDEX], + ctx->Texture.Unit[u].Current2D); + _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_3D_INDEX], + ctx->Texture.Unit[u].Current3D); + _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_CUBE_INDEX], + ctx->Texture.Unit[u].CurrentCubeMap); + _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_RECT_INDEX], + ctx->Texture.Unit[u].CurrentRect); + _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_1D_ARRAY_INDEX], + ctx->Texture.Unit[u].Current1DArray); + _mesa_reference_texobj(&texstate->SavedTexRef[u][TEXTURE_2D_ARRAY_INDEX], + ctx->Texture.Unit[u].Current2DArray); } - attr = MALLOC_STRUCT( gl_texture_attrib ); - MEMCPY( attr, &ctx->Texture, sizeof(struct gl_texture_attrib) ); - /* copy state of the currently bound texture objects */ + + /* copy state/contents of the currently bound texture objects */ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { - _mesa_copy_texture_object(&attr->Unit[u].Saved1D, - attr->Unit[u].Current1D); - _mesa_copy_texture_object(&attr->Unit[u].Saved2D, - attr->Unit[u].Current2D); - _mesa_copy_texture_object(&attr->Unit[u].Saved3D, - attr->Unit[u].Current3D); - _mesa_copy_texture_object(&attr->Unit[u].SavedCubeMap, - attr->Unit[u].CurrentCubeMap); - _mesa_copy_texture_object(&attr->Unit[u].SavedRect, - attr->Unit[u].CurrentRect); + _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_1D_INDEX], + ctx->Texture.Unit[u].Current1D); + _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_2D_INDEX], + ctx->Texture.Unit[u].Current2D); + _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_3D_INDEX], + ctx->Texture.Unit[u].Current3D); + _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_CUBE_INDEX], + ctx->Texture.Unit[u].CurrentCubeMap); + _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_RECT_INDEX], + ctx->Texture.Unit[u].CurrentRect); + _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_1D_ARRAY_INDEX], + ctx->Texture.Unit[u].Current1DArray); + _mesa_copy_texture_object(&texstate->SavedObj[u][TEXTURE_2D_ARRAY_INDEX], + ctx->Texture.Unit[u].Current2DArray); } + + _mesa_unlock_context_textures(ctx); + newnode = new_attrib_node( GL_TEXTURE_BIT ); - newnode->data = attr; + newnode->data = texstate; newnode->next = head; head = newnode; } @@ -396,6 +454,7 @@ _mesa_PushAttrib(GLbitfield mask) head = newnode; } +end: ctx->AttribStack[ctx->AttribStackDepth] = head; ctx->AttribStackDepth++; } @@ -424,14 +483,15 @@ pop_enable_group(GLcontext *ctx, const struct gl_enable_attrib *enable) TEST_AND_UPDATE(ctx->Light.ColorMaterialEnabled, enable->ColorMaterial, GL_COLOR_MATERIAL); - TEST_AND_UPDATE(ctx->Pixel.ColorTableEnabled, enable->ColorTable, + TEST_AND_UPDATE(ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION], + enable->ColorTable[COLORTABLE_PRECONVOLUTION], GL_COLOR_TABLE); - TEST_AND_UPDATE(ctx->Pixel.PostColorMatrixColorTableEnabled, - enable->PostColorMatrixColorTable, - GL_POST_COLOR_MATRIX_COLOR_TABLE); - TEST_AND_UPDATE(ctx->Pixel.PostConvolutionColorTableEnabled, - enable->PostConvolutionColorTable, + TEST_AND_UPDATE(ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION], + enable->ColorTable[COLORTABLE_POSTCONVOLUTION], GL_POST_CONVOLUTION_COLOR_TABLE); + TEST_AND_UPDATE(ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX], + enable->ColorTable[COLORTABLE_POSTCOLORMATRIX], + GL_POST_COLOR_MATRIX_COLOR_TABLE); TEST_AND_UPDATE(ctx->Polygon.CullFlag, enable->CullFace, GL_CULL_FACE); TEST_AND_UPDATE(ctx->Depth.Test, enable->DepthTest, GL_DEPTH_TEST); TEST_AND_UPDATE(ctx->Color.DitherFlag, enable->Dither, GL_DITHER); @@ -498,8 +558,6 @@ pop_enable_group(GLcontext *ctx, const struct gl_enable_attrib *enable) TEST_AND_UPDATE(ctx->Transform.RasterPositionUnclipped, enable->RasterPositionUnclipped, GL_RASTER_POSITION_UNCLIPPED_IBM); - TEST_AND_UPDATE(ctx->Pixel.PixelTextureEnabled, enable->PixelTexture, - GL_POINT_SMOOTH); TEST_AND_UPDATE(ctx->Point.SmoothFlag, enable->PointSmooth, GL_POINT_SMOOTH); if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite) { @@ -518,7 +576,9 @@ pop_enable_group(GLcontext *ctx, const struct gl_enable_attrib *enable) GL_POLYGON_STIPPLE); TEST_AND_UPDATE(ctx->Scissor.Enabled, enable->Scissor, GL_SCISSOR_TEST); TEST_AND_UPDATE(ctx->Stencil.Enabled, enable->Stencil, GL_STENCIL_TEST); - /* XXX two-sided stencil */ + if (ctx->Extensions.EXT_stencil_two_side) { + TEST_AND_UPDATE(ctx->Stencil.TestTwoSide, enable->StencilTwoSide, GL_STENCIL_TEST_TWO_SIDE_EXT); + } TEST_AND_UPDATE(ctx->Multisample.Enabled, enable->MultisampleEnabled, GL_MULTISAMPLE_ARB); TEST_AND_UPDATE(ctx->Multisample.SampleAlphaToCoverage, @@ -533,16 +593,16 @@ pop_enable_group(GLcontext *ctx, const struct gl_enable_attrib *enable) TEST_AND_UPDATE(ctx->Multisample.SampleCoverageInvert, enable->SampleCoverageInvert, GL_SAMPLE_COVERAGE_INVERT_ARB); - /* GL_NV_vertex_program */ + /* GL_ARB_vertex_program, GL_NV_vertex_program */ TEST_AND_UPDATE(ctx->VertexProgram.Enabled, enable->VertexProgram, - GL_VERTEX_PROGRAM_NV); + GL_VERTEX_PROGRAM_ARB); TEST_AND_UPDATE(ctx->VertexProgram.PointSizeEnabled, enable->VertexProgramPointSize, - GL_VERTEX_PROGRAM_POINT_SIZE_NV); + GL_VERTEX_PROGRAM_POINT_SIZE_ARB); TEST_AND_UPDATE(ctx->VertexProgram.TwoSideEnabled, enable->VertexProgramTwoSide, - GL_VERTEX_PROGRAM_TWO_SIDE_NV); + GL_VERTEX_PROGRAM_TWO_SIDE_ARB); #undef TEST_AND_UPDATE @@ -604,29 +664,34 @@ pop_enable_group(GLcontext *ctx, const struct gl_enable_attrib *enable) } +/** + * Pop/restore texture attribute/group state. + */ static void -pop_texture_group(GLcontext *ctx, const struct gl_texture_attrib *texAttrib) +pop_texture_group(GLcontext *ctx, struct texture_state *texstate) { GLuint u; + _mesa_lock_context_textures(ctx); + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { - const struct gl_texture_unit *unit = &texAttrib->Unit[u]; - GLuint i; + const struct gl_texture_unit *unit = &texstate->Texture.Unit[u]; + GLuint tgt; _mesa_ActiveTextureARB(GL_TEXTURE0_ARB + u); _mesa_set_enable(ctx, GL_TEXTURE_1D, - (GLboolean) (unit->Enabled & TEXTURE_1D_BIT ? GL_TRUE : GL_FALSE)); + (unit->Enabled & TEXTURE_1D_BIT) ? GL_TRUE : GL_FALSE); _mesa_set_enable(ctx, GL_TEXTURE_2D, - (GLboolean) (unit->Enabled & TEXTURE_2D_BIT ? GL_TRUE : GL_FALSE)); + (unit->Enabled & TEXTURE_2D_BIT) ? GL_TRUE : GL_FALSE); _mesa_set_enable(ctx, GL_TEXTURE_3D, - (GLboolean) (unit->Enabled & TEXTURE_3D_BIT ? GL_TRUE : GL_FALSE)); + (unit->Enabled & TEXTURE_3D_BIT) ? GL_TRUE : GL_FALSE); if (ctx->Extensions.ARB_texture_cube_map) { _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP_ARB, - (GLboolean) (unit->Enabled & TEXTURE_CUBE_BIT ? GL_TRUE : GL_FALSE)); + (unit->Enabled & TEXTURE_CUBE_BIT) ? GL_TRUE : GL_FALSE); } if (ctx->Extensions.NV_texture_rectangle) { _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE_NV, - (GLboolean) (unit->Enabled & TEXTURE_RECT_BIT ? GL_TRUE : GL_FALSE)); + (unit->Enabled & TEXTURE_RECT_BIT) ? GL_TRUE : GL_FALSE); } if (ctx->Extensions.SGI_texture_color_table) { _mesa_set_enable(ctx, GL_TEXTURE_COLOR_TABLE_SGI, @@ -642,10 +707,28 @@ pop_texture_group(GLcontext *ctx, const struct gl_texture_attrib *texAttrib) _mesa_TexGenfv(GL_T, GL_OBJECT_PLANE, unit->ObjectPlaneT); _mesa_TexGenfv(GL_R, GL_OBJECT_PLANE, unit->ObjectPlaneR); _mesa_TexGenfv(GL_Q, GL_OBJECT_PLANE, unit->ObjectPlaneQ); - _mesa_TexGenfv(GL_S, GL_EYE_PLANE, unit->EyePlaneS); - _mesa_TexGenfv(GL_T, GL_EYE_PLANE, unit->EyePlaneT); - _mesa_TexGenfv(GL_R, GL_EYE_PLANE, unit->EyePlaneR); - _mesa_TexGenfv(GL_Q, GL_EYE_PLANE, unit->EyePlaneQ); + /* Eye plane done differently to avoid re-transformation */ + { + struct gl_texture_unit *destUnit = &ctx->Texture.Unit[u]; + COPY_4FV(destUnit->EyePlaneS, unit->EyePlaneS); + COPY_4FV(destUnit->EyePlaneT, unit->EyePlaneT); + COPY_4FV(destUnit->EyePlaneR, unit->EyePlaneR); + COPY_4FV(destUnit->EyePlaneQ, unit->EyePlaneQ); + if (ctx->Driver.TexGen) { + ctx->Driver.TexGen(ctx, GL_S, GL_EYE_PLANE, unit->EyePlaneS); + ctx->Driver.TexGen(ctx, GL_T, GL_EYE_PLANE, unit->EyePlaneT); + ctx->Driver.TexGen(ctx, GL_R, GL_EYE_PLANE, unit->EyePlaneR); + ctx->Driver.TexGen(ctx, GL_Q, GL_EYE_PLANE, unit->EyePlaneQ); + } + } + _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, + ((unit->TexGenEnabled & S_BIT) ? GL_TRUE : GL_FALSE)); + _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, + ((unit->TexGenEnabled & T_BIT) ? GL_TRUE : GL_FALSE)); + _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, + ((unit->TexGenEnabled & R_BIT) ? GL_TRUE : GL_FALSE)); + _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, + ((unit->TexGenEnabled & Q_BIT) ? GL_TRUE : GL_FALSE)); if (ctx->Extensions.EXT_texture_lod_bias) { _mesa_TexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, unit->LodBias); @@ -686,40 +769,32 @@ pop_texture_group(GLcontext *ctx, const struct gl_texture_attrib *texAttrib) 1 << unit->Combine.ScaleShiftA); } - /* Restore texture object state */ - for (i = 0; i < NUM_TEXTURE_TARGETS; i++) { - GLenum target = 0; + /* Restore texture object state for each target */ + for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { const struct gl_texture_object *obj = NULL; GLfloat bordColor[4]; + GLenum target; - switch (i) { - case 0: - target = GL_TEXTURE_1D; - obj = &unit->Saved1D; - break; - case 1: - target = GL_TEXTURE_2D; - obj = &unit->Saved2D; - break; - case 2: - target = GL_TEXTURE_3D; - obj = &unit->Saved3D; - break; - case 3: - if (!ctx->Extensions.ARB_texture_cube_map) - continue; - target = GL_TEXTURE_CUBE_MAP_ARB; - obj = &unit->SavedCubeMap; - break; - case 4: - if (!ctx->Extensions.NV_texture_rectangle) - continue; - target = GL_TEXTURE_RECTANGLE_NV; - obj = &unit->SavedRect; - break; - default: - ; /* silence warnings */ + obj = &texstate->SavedObj[u][tgt]; + + /* don't restore state for unsupported targets to prevent + * raising GL errors. + */ + if (obj->Target == GL_TEXTURE_CUBE_MAP_ARB && + !ctx->Extensions.ARB_texture_cube_map) { + continue; } + else if (obj->Target == GL_TEXTURE_RECTANGLE_NV && + !ctx->Extensions.NV_texture_rectangle) { + continue; + } + else if ((obj->Target == GL_TEXTURE_1D_ARRAY_EXT || + obj->Target == GL_TEXTURE_2D_ARRAY_EXT) && + !ctx->Extensions.MESA_texture_array) { + continue; + } + + target = obj->Target; _mesa_BindTexture(target, obj->Name); @@ -728,8 +803,8 @@ pop_texture_group(GLcontext *ctx, const struct gl_texture_attrib *texAttrib) bordColor[2] = CHAN_TO_FLOAT(obj->BorderColor[2]); bordColor[3] = CHAN_TO_FLOAT(obj->BorderColor[3]); - _mesa_TexParameterf(target, GL_TEXTURE_PRIORITY, obj->Priority); _mesa_TexParameterfv(target, GL_TEXTURE_BORDER_COLOR, bordColor); + _mesa_TexParameterf(target, GL_TEXTURE_PRIORITY, obj->Priority); _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, obj->WrapS); _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, obj->WrapT); _mesa_TexParameteri(target, GL_TEXTURE_WRAP_R, obj->WrapR); @@ -737,39 +812,29 @@ pop_texture_group(GLcontext *ctx, const struct gl_texture_attrib *texAttrib) _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, obj->MagFilter); _mesa_TexParameterf(target, GL_TEXTURE_MIN_LOD, obj->MinLod); _mesa_TexParameterf(target, GL_TEXTURE_MAX_LOD, obj->MaxLod); + _mesa_TexParameterf(target, GL_TEXTURE_LOD_BIAS, obj->LodBias); _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, obj->BaseLevel); - _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, obj->MaxLevel); + if (target != GL_TEXTURE_RECTANGLE_ARB) + _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, obj->MaxLevel); if (ctx->Extensions.EXT_texture_filter_anisotropic) { _mesa_TexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, obj->MaxAnisotropy); } - if (ctx->Extensions.SGIX_shadow) { - _mesa_TexParameteri(target, GL_TEXTURE_COMPARE_SGIX, - obj->CompareFlag); - _mesa_TexParameteri(target, GL_TEXTURE_COMPARE_OPERATOR_SGIX, - obj->CompareOperator); - } - if (ctx->Extensions.SGIX_shadow_ambient) { - _mesa_TexParameterf(target, GL_SHADOW_AMBIENT_SGIX, - obj->ShadowAmbient); + if (ctx->Extensions.ARB_shadow_ambient) { + _mesa_TexParameterf(target, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, + obj->CompareFailValue); } + } + /* remove saved references to the texture objects */ + for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { + _mesa_reference_texobj(&texstate->SavedTexRef[u][tgt], NULL); } } - _mesa_ActiveTextureARB(GL_TEXTURE0_ARB - + texAttrib->CurrentUnit); - /* "un-bump" the texture object reference counts. We did that so they - * wouldn't inadvertantly get deleted while they were still referenced - * inside the attribute state stack. - */ - for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { - ctx->Texture.Unit[u].Current1D->RefCount--; - ctx->Texture.Unit[u].Current2D->RefCount--; - ctx->Texture.Unit[u].Current3D->RefCount--; - ctx->Texture.Unit[u].CurrentCubeMap->RefCount--; - ctx->Texture.Unit[u].CurrentRect->RefCount--; - } + _mesa_ActiveTextureARB(GL_TEXTURE0_ARB + texstate->Texture.CurrentUnit); + + _mesa_unlock_context_textures(ctx); } @@ -830,7 +895,35 @@ _mesa_PopAttrib(void) (GLboolean) (color->ColorMask[1] != 0), (GLboolean) (color->ColorMask[2] != 0), (GLboolean) (color->ColorMask[3] != 0)); - _mesa_DrawBuffer(color->DrawBuffer); + { + /* Need to determine if more than one color output is + * specified. If so, call glDrawBuffersARB, else call + * glDrawBuffer(). This is a subtle, but essential point + * since GL_FRONT (for example) is illegal for the former + * function, but legal for the later. + */ + GLboolean multipleBuffers = GL_FALSE; + GLuint i; + + for (i = 1; i < ctx->Const.MaxDrawBuffers; i++) { + if (color->DrawBuffer[i] != GL_NONE) { + multipleBuffers = GL_TRUE; + break; + } + } + /* Call the API_level functions, not _mesa_drawbuffers() + * since we need to do error checking on the pop'd + * GL_DRAW_BUFFER. + * Ex: if GL_FRONT were pushed, but we're popping with a + * user FBO bound, GL_FRONT will be illegal and we'll need + * to record that error. Per OpenGL ARB decision. + */ + if (multipleBuffers) + _mesa_DrawBuffersARB(ctx->Const.MaxDrawBuffers, + color->DrawBuffer); + else + _mesa_DrawBuffer(color->DrawBuffer[0]); + } _mesa_set_enable(ctx, GL_ALPHA_TEST, color->AlphaEnabled); _mesa_AlphaFunc(color->AlphaFunc, color->AlphaRef); _mesa_set_enable(ctx, GL_BLEND, color->BlendEnabled); @@ -873,9 +966,6 @@ _mesa_PopAttrib(void) _mesa_ClearDepth(depth->Clear); _mesa_set_enable(ctx, GL_DEPTH_TEST, depth->Test); _mesa_DepthMask(depth->Mask); - if (ctx->Extensions.HP_occlusion_test) - _mesa_set_enable(ctx, GL_OCCLUSION_TEST_HP, - depth->OcclusionTest); } break; case GL_ENABLE_BIT: @@ -915,9 +1005,8 @@ _mesa_PopAttrib(void) _mesa_Hint(GL_FOG_HINT, hint->Fog); _mesa_Hint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, hint->ClipVolumeClipping); - if (ctx->Extensions.ARB_texture_compression) - _mesa_Hint(GL_TEXTURE_COMPRESSION_HINT_ARB, - hint->TextureCompression); + _mesa_Hint(GL_TEXTURE_COMPRESSION_HINT_ARB, + hint->TextureCompression); } break; case GL_LIGHTING_BIT: @@ -928,30 +1017,25 @@ _mesa_PopAttrib(void) /* lighting enable */ _mesa_set_enable(ctx, GL_LIGHTING, light->Enabled); /* per-light state */ - - if (ctx->ModelviewMatrixStack.Top->flags & MAT_DIRTY_INVERSE) - _math_matrix_analyse( ctx->ModelviewMatrixStack.Top ); + if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) + _math_matrix_analyse( ctx->ModelviewMatrixStack.Top ); - for (i = 0; i < MAX_LIGHTS; i++) { - GLenum lgt = (GLenum) (GL_LIGHT0 + i); + for (i = 0; i < ctx->Const.MaxLights; i++) { const struct gl_light *l = &light->Light[i]; - GLfloat tmp[4]; - _mesa_set_enable(ctx, lgt, l->Enabled); - _mesa_Lightfv( lgt, GL_AMBIENT, l->Ambient ); - _mesa_Lightfv( lgt, GL_DIFFUSE, l->Diffuse ); - _mesa_Lightfv( lgt, GL_SPECULAR, l->Specular ); - TRANSFORM_POINT( tmp, ctx->ModelviewMatrixStack.Top->inv, l->EyePosition ); - _mesa_Lightfv( lgt, GL_POSITION, tmp ); - TRANSFORM_POINT( tmp, ctx->ModelviewMatrixStack.Top->m, l->EyeDirection ); - _mesa_Lightfv( lgt, GL_SPOT_DIRECTION, tmp ); - _mesa_Lightfv( lgt, GL_SPOT_EXPONENT, &l->SpotExponent ); - _mesa_Lightfv( lgt, GL_SPOT_CUTOFF, &l->SpotCutoff ); - _mesa_Lightfv( lgt, GL_CONSTANT_ATTENUATION, - &l->ConstantAttenuation ); - _mesa_Lightfv( lgt, GL_LINEAR_ATTENUATION, - &l->LinearAttenuation ); - _mesa_Lightfv( lgt, GL_QUADRATIC_ATTENUATION, - &l->QuadraticAttenuation ); + _mesa_set_enable(ctx, GL_LIGHT0 + i, l->Enabled); + _mesa_light(ctx, i, GL_AMBIENT, l->Ambient); + _mesa_light(ctx, i, GL_DIFFUSE, l->Diffuse); + _mesa_light(ctx, i, GL_SPECULAR, l->Specular ); + _mesa_light(ctx, i, GL_POSITION, l->EyePosition); + _mesa_light(ctx, i, GL_SPOT_DIRECTION, l->EyeDirection); + _mesa_light(ctx, i, GL_SPOT_EXPONENT, &l->SpotExponent); + _mesa_light(ctx, i, GL_SPOT_CUTOFF, &l->SpotCutoff); + _mesa_light(ctx, i, GL_CONSTANT_ATTENUATION, + &l->ConstantAttenuation); + _mesa_light(ctx, i, GL_LINEAR_ATTENUATION, + &l->LinearAttenuation); + _mesa_light(ctx, i, GL_QUADRATIC_ATTENUATION, + &l->QuadraticAttenuation); } /* light model */ _mesa_LightModelfv(GL_LIGHT_MODEL_AMBIENT, @@ -962,9 +1046,6 @@ _mesa_PopAttrib(void) (GLfloat) light->Model.TwoSide); _mesa_LightModelf(GL_LIGHT_MODEL_COLOR_CONTROL, (GLfloat) light->Model.ColorControl); - /* materials */ - MEMCPY(&ctx->Light.Material, &light->Material, - sizeof(struct gl_material)); /* shade model */ _mesa_ShadeModel(light->ShadeModel); /* color material */ @@ -972,6 +1053,9 @@ _mesa_PopAttrib(void) light->ColorMaterialMode); _mesa_set_enable(ctx, GL_COLOR_MATERIAL, light->ColorMaterialEnabled); + /* materials */ + MEMCPY(&ctx->Light.Material, &light->Material, + sizeof(struct gl_material)); } break; case GL_LINE_BIT: @@ -989,6 +1073,8 @@ _mesa_PopAttrib(void) break; case GL_PIXEL_MODE_BIT: MEMCPY( &ctx->Pixel, attr->data, sizeof(struct gl_pixel_attrib) ); + /* XXX what other pixel state needs to be set by function calls? */ + _mesa_ReadBuffer(ctx->Pixel.ReadBuffer); ctx->NewState |= _NEW_PIXEL; break; case GL_POINT_BIT: @@ -998,14 +1084,14 @@ _mesa_PopAttrib(void) _mesa_PointSize(point->Size); _mesa_set_enable(ctx, GL_POINT_SMOOTH, point->SmoothFlag); if (ctx->Extensions.EXT_point_parameters) { - _mesa_PointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, - point->Params); - _mesa_PointParameterfEXT(GL_POINT_SIZE_MIN_EXT, - point->MinSize); - _mesa_PointParameterfEXT(GL_POINT_SIZE_MAX_EXT, - point->MaxSize); - _mesa_PointParameterfEXT(GL_POINT_FADE_THRESHOLD_SIZE_EXT, - point->Threshold); + _mesa_PointParameterfv(GL_DISTANCE_ATTENUATION_EXT, + point->Params); + _mesa_PointParameterf(GL_POINT_SIZE_MIN_EXT, + point->MinSize); + _mesa_PointParameterf(GL_POINT_SIZE_MAX_EXT, + point->MaxSize); + _mesa_PointParameterf(GL_POINT_FADE_THRESHOLD_SIZE_EXT, + point->Threshold); } if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite) { @@ -1015,8 +1101,11 @@ _mesa_PopAttrib(void) (GLint) point->CoordReplace[u]); } _mesa_set_enable(ctx, GL_POINT_SPRITE_NV,point->PointSprite); - _mesa_PointParameteriNV(GL_POINT_SPRITE_R_MODE_NV, - ctx->Point.SpriteRMode); + if (ctx->Extensions.NV_point_sprite) + _mesa_PointParameteri(GL_POINT_SPRITE_R_MODE_NV, + ctx->Point.SpriteRMode); + _mesa_PointParameterf(GL_POINT_SPRITE_COORD_ORIGIN, + (GLfloat)ctx->Point.SpriteOrigin); } } break; @@ -1058,17 +1147,34 @@ _mesa_PopAttrib(void) break; case GL_STENCIL_BUFFER_BIT: { - const GLint face = 0; /* XXX stencil two side */ const struct gl_stencil_attrib *stencil; stencil = (const struct gl_stencil_attrib *) attr->data; _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled); _mesa_ClearStencil(stencil->Clear); - _mesa_StencilFunc(stencil->Function[face], stencil->Ref[face], - stencil->ValueMask[face]); - _mesa_StencilMask(stencil->WriteMask[face]); - _mesa_StencilOp(stencil->FailFunc[face], - stencil->ZFailFunc[face], - stencil->ZPassFunc[face]); + if (ctx->Extensions.EXT_stencil_two_side) { + _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT, + stencil->TestTwoSide); + _mesa_ActiveStencilFaceEXT(stencil->ActiveFace + ? GL_BACK : GL_FRONT); + } + /* front state */ + _mesa_StencilFuncSeparate(GL_FRONT, + stencil->Function[0], + stencil->Ref[0], + stencil->ValueMask[0]); + _mesa_StencilMaskSeparate(GL_FRONT, stencil->WriteMask[0]); + _mesa_StencilOpSeparate(GL_FRONT, stencil->FailFunc[0], + stencil->ZFailFunc[0], + stencil->ZPassFunc[0]); + /* back state */ + _mesa_StencilFuncSeparate(GL_BACK, + stencil->Function[1], + stencil->Ref[1], + stencil->ValueMask[1]); + _mesa_StencilMaskSeparate(GL_BACK, stencil->WriteMask[1]); + _mesa_StencilOpSeparate(GL_BACK, stencil->FailFunc[1], + stencil->ZFailFunc[1], + stencil->ZPassFunc[1]); } break; case GL_TRANSFORM_BIT: @@ -1077,8 +1183,7 @@ _mesa_PopAttrib(void) const struct gl_transform_attrib *xform; xform = (const struct gl_transform_attrib *) attr->data; _mesa_MatrixMode(xform->MatrixMode); - - if (ctx->ProjectionMatrixStack.Top->flags & MAT_DIRTY) + if (_math_matrix_is_dirty(ctx->ProjectionMatrixStack.Top)) _math_matrix_analyse( ctx->ProjectionMatrixStack.Top ); /* restore clip planes */ @@ -1107,9 +1212,9 @@ _mesa_PopAttrib(void) case GL_TEXTURE_BIT: /* Take care of texture object reference counters */ { - const struct gl_texture_attrib *texture; - texture = (const struct gl_texture_attrib *) attr->data; - pop_texture_group(ctx, texture); + struct texture_state *texstate + = (struct texture_state *) attr->data; + pop_texture_group(ctx, texstate); ctx->NewState |= _NEW_TEXTURE; } break; @@ -1151,20 +1256,40 @@ static void adjust_buffer_object_ref_counts(struct gl_array_attrib *array, GLint step) { GLuint i; - array->Vertex.BufferObj->RefCount += step; - array->Normal.BufferObj->RefCount += step; - array->Color.BufferObj->RefCount += step; - array->SecondaryColor.BufferObj->RefCount += step; - array->FogCoord.BufferObj->RefCount += step; - array->Index.BufferObj->RefCount += step; - array->EdgeFlag.BufferObj->RefCount += step; + array->ArrayObj->Vertex.BufferObj->RefCount += step; + array->ArrayObj->Normal.BufferObj->RefCount += step; + array->ArrayObj->Color.BufferObj->RefCount += step; + array->ArrayObj->SecondaryColor.BufferObj->RefCount += step; + array->ArrayObj->FogCoord.BufferObj->RefCount += step; + array->ArrayObj->Index.BufferObj->RefCount += step; + array->ArrayObj->EdgeFlag.BufferObj->RefCount += step; for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) - array->TexCoord[i].BufferObj->RefCount += step; + array->ArrayObj->TexCoord[i].BufferObj->RefCount += step; for (i = 0; i < VERT_ATTRIB_MAX; i++) - array->VertexAttrib[i].BufferObj->RefCount += step; + array->ArrayObj->VertexAttrib[i].BufferObj->RefCount += step; +} - array->ArrayBufferObj->RefCount += step; - array->ElementArrayBufferObj->RefCount += step; + +/** + * Copy gl_pixelstore_attrib from src to dst, updating buffer + * object refcounts. + */ +static void +copy_pixelstore(GLcontext *ctx, + struct gl_pixelstore_attrib *dst, + const struct gl_pixelstore_attrib *src) +{ + dst->Alignment = src->Alignment; + dst->RowLength = src->RowLength; + dst->SkipPixels = src->SkipPixels; + dst->SkipRows = src->SkipRows; + dst->ImageHeight = src->ImageHeight; + dst->SkipImages = src->SkipImages; + dst->SwapBytes = src->SwapBytes; + dst->LsbFirst = src->LsbFirst; + dst->ClientStorage = src->ClientStorage; + dst->Invert = src->Invert; + _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj); } @@ -1186,35 +1311,47 @@ _mesa_PushClientAttrib(GLbitfield mask) return; } - /* Build linked list of attribute nodes which save all attribute */ - /* groups specified by the mask. */ + /* Build linked list of attribute nodes which save all attribute + * groups specified by the mask. + */ head = NULL; if (mask & GL_CLIENT_PIXEL_STORE_BIT) { struct gl_pixelstore_attrib *attr; -#if FEATURE_EXT_pixel_buffer_object - ctx->Pack.BufferObj->RefCount++; - ctx->Unpack.BufferObj->RefCount++; -#endif /* packing attribs */ - attr = MALLOC_STRUCT( gl_pixelstore_attrib ); - MEMCPY( attr, &ctx->Pack, sizeof(struct gl_pixelstore_attrib) ); + attr = CALLOC_STRUCT( gl_pixelstore_attrib ); + copy_pixelstore(ctx, attr, &ctx->Pack); newnode = new_attrib_node( GL_CLIENT_PACK_BIT ); newnode->data = attr; newnode->next = head; head = newnode; /* unpacking attribs */ - attr = MALLOC_STRUCT( gl_pixelstore_attrib ); - MEMCPY( attr, &ctx->Unpack, sizeof(struct gl_pixelstore_attrib) ); + attr = CALLOC_STRUCT( gl_pixelstore_attrib ); + copy_pixelstore(ctx, attr, &ctx->Unpack); newnode = new_attrib_node( GL_CLIENT_UNPACK_BIT ); newnode->data = attr; newnode->next = head; head = newnode; } + if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) { struct gl_array_attrib *attr; + struct gl_array_object *obj; + attr = MALLOC_STRUCT( gl_array_attrib ); + obj = MALLOC_STRUCT( gl_array_object ); + +#if FEATURE_ARB_vertex_buffer_object + /* increment ref counts since we're copying pointers to these objects */ + ctx->Array.ArrayBufferObj->RefCount++; + ctx->Array.ElementArrayBufferObj->RefCount++; +#endif + MEMCPY( attr, &ctx->Array, sizeof(struct gl_array_attrib) ); + MEMCPY( obj, ctx->Array.ArrayObj, sizeof(struct gl_array_object) ); + + attr->ArrayObj = obj; + newnode = new_attrib_node( GL_CLIENT_VERTEX_ARRAY_BIT ); newnode->data = attr; newnode->next = head; @@ -1233,7 +1370,7 @@ _mesa_PushClientAttrib(GLbitfield mask) void GLAPIENTRY _mesa_PopClientAttrib(void) { - struct gl_attrib_node *attr, *next; + struct gl_attrib_node *node, *next; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); @@ -1244,50 +1381,107 @@ _mesa_PopClientAttrib(void) } ctx->ClientAttribStackDepth--; - attr = ctx->ClientAttribStack[ctx->ClientAttribStackDepth]; + node = ctx->ClientAttribStack[ctx->ClientAttribStackDepth]; - while (attr) { - switch (attr->kind) { + while (node) { + switch (node->kind) { case GL_CLIENT_PACK_BIT: -#if FEATURE_EXT_pixel_buffer_object - ctx->Pack.BufferObj->RefCount--; - if (ctx->Pack.BufferObj->RefCount <= 0) { - _mesa_remove_buffer_object( ctx, ctx->Pack.BufferObj ); - (*ctx->Driver.DeleteBuffer)( ctx, ctx->Pack.BufferObj ); + { + struct gl_pixelstore_attrib *store = + (struct gl_pixelstore_attrib *) node->data; + copy_pixelstore(ctx, &ctx->Pack, store); + _mesa_reference_buffer_object(ctx, &store->BufferObj, NULL); } -#endif - MEMCPY( &ctx->Pack, attr->data, - sizeof(struct gl_pixelstore_attrib) ); ctx->NewState |= _NEW_PACKUNPACK; break; case GL_CLIENT_UNPACK_BIT: -#if FEATURE_EXT_pixel_buffer_object - ctx->Unpack.BufferObj->RefCount--; - if (ctx->Unpack.BufferObj->RefCount <= 0) { - _mesa_remove_buffer_object( ctx, ctx->Unpack.BufferObj ); - (*ctx->Driver.DeleteBuffer)( ctx, ctx->Unpack.BufferObj ); + { + struct gl_pixelstore_attrib *store = + (struct gl_pixelstore_attrib *) node->data; + copy_pixelstore(ctx, &ctx->Unpack, store); + _mesa_reference_buffer_object(ctx, &store->BufferObj, NULL); } -#endif - MEMCPY( &ctx->Unpack, attr->data, - sizeof(struct gl_pixelstore_attrib) ); ctx->NewState |= _NEW_PACKUNPACK; break; - case GL_CLIENT_VERTEX_ARRAY_BIT: + case GL_CLIENT_VERTEX_ARRAY_BIT: { + struct gl_array_attrib * data = + (struct gl_array_attrib *) node->data; + adjust_buffer_object_ref_counts(&ctx->Array, -1); - MEMCPY( &ctx->Array, attr->data, - sizeof(struct gl_array_attrib) ); - /* decrement reference counts on buffer objects */ + + ctx->Array.ActiveTexture = data->ActiveTexture; + if (data->LockCount != 0) + _mesa_LockArraysEXT(data->LockFirst, data->LockCount); + else if (ctx->Array.LockCount) + _mesa_UnlockArraysEXT(); + + _mesa_BindVertexArrayAPPLE( data->ArrayObj->Name ); + +#if FEATURE_ARB_vertex_buffer_object + _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, + data->ArrayBufferObj->Name); + _mesa_BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, + data->ElementArrayBufferObj->Name); +#endif + + MEMCPY( ctx->Array.ArrayObj, data->ArrayObj, + sizeof( struct gl_array_object ) ); + + FREE( data->ArrayObj ); + + /* FIXME: Should some bits in ctx->Array->NewState also be set + * FIXME: here? It seems like it should be set to inclusive-or + * FIXME: of the old ArrayObj->_Enabled and the new _Enabled. + */ + ctx->NewState |= _NEW_ARRAY; break; + } default: _mesa_problem( ctx, "Bad attrib flag in PopClientAttrib"); break; } - next = attr->next; - FREE( attr->data ); - FREE( attr ); - attr = next; + next = node->next; + FREE( node->data ); + FREE( node ); + node = next; + } +} + + +/** + * Free any attribute state data that might be attached to the context. + */ +void +_mesa_free_attrib_data(GLcontext *ctx) +{ + while (ctx->AttribStackDepth > 0) { + struct gl_attrib_node *attr, *next; + + ctx->AttribStackDepth--; + attr = ctx->AttribStack[ctx->AttribStackDepth]; + + while (attr) { + if (attr->kind == GL_TEXTURE_BIT) { + struct texture_state *texstate = (struct texture_state*)attr->data; + GLuint u, tgt; + /* clear references to the saved texture objects */ + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { + _mesa_reference_texobj(&texstate->SavedTexRef[u][tgt], NULL); + } + } + } + else { + /* any other chunks of state that requires special handling? */ + } + + next = attr->next; + _mesa_free(attr->data); + _mesa_free(attr); + attr = next; + } } }