/** * Free a context's vertex/fragment program state */ void _mesa_free_program_data(struct gl_context *ctx) { #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL); _mesa_delete_program_cache(ctx, ctx->VertexProgram.Cache); #endif #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL); _mesa_delete_program_cache(ctx, ctx->FragmentProgram.Cache); #endif #if FEATURE_ARB_geometry_shader4 _mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current, NULL); _mesa_delete_program_cache(ctx, ctx->GeometryProgram.Cache); #endif /* XXX probably move this stuff */ #if FEATURE_ATI_fragment_shader if (ctx->ATIFragmentShader.Current) { ctx->ATIFragmentShader.Current->RefCount--; if (ctx->ATIFragmentShader.Current->RefCount <= 0) { free(ctx->ATIFragmentShader.Current); } } #endif free((void *) ctx->Program.ErrorString); }
/** * Update the default program objects in the given context to reference those * specified in the shared state and release those referencing the old * shared state. */ void _mesa_update_default_objects_program(struct gl_context *ctx) { #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, ctx->Shared->DefaultVertexProgram); assert(ctx->VertexProgram.Current); #endif #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, ctx->Shared->DefaultFragmentProgram); assert(ctx->FragmentProgram.Current); #endif #if FEATURE_ARB_geometry_shader4 _mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current, ctx->Shared->DefaultGeometryProgram); #endif /* XXX probably move this stuff */ #if FEATURE_ATI_fragment_shader if (ctx->ATIFragmentShader.Current) { ctx->ATIFragmentShader.Current->RefCount--; if (ctx->ATIFragmentShader.Current->RefCount <= 0) { free(ctx->ATIFragmentShader.Current); } } ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader; assert(ctx->ATIFragmentShader.Current); ctx->ATIFragmentShader.Current->RefCount++; #endif }
/** * Update the ctx->Vertex/Geometry/FragmentProgram._Current pointers to point * to the current/active programs. Then call ctx->Driver.BindProgram() to * tell the driver which programs to use. * * Programs may come from 3 sources: GLSL shaders, ARB/NV_vertex/fragment * programs or programs derived from fixed-function state. * * This function needs to be called after texture state validation in case * we're generating a fragment program from fixed-function texture state. * * \return bitfield which will indicate _NEW_PROGRAM state if a new vertex * or fragment program is being used. */ static GLbitfield update_program(struct gl_context *ctx) { const struct gl_shader_program *vsProg = ctx->Shader.CurrentVertexProgram; const struct gl_shader_program *gsProg = ctx->Shader.CurrentGeometryProgram; struct gl_shader_program *fsProg = ctx->Shader.CurrentFragmentProgram; const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current; const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current; const struct gl_geometry_program *prevGP = ctx->GeometryProgram._Current; GLbitfield new_state = 0x0; /* * Set the ctx->VertexProgram._Current and ctx->FragmentProgram._Current * pointers to the programs that should be used for rendering. If either * is NULL, use fixed-function code paths. * * These programs may come from several sources. The priority is as * follows: * 1. OpenGL 2.0/ARB vertex/fragment shaders * 2. ARB/NV vertex/fragment programs * 3. Programs derived from fixed-function state. * * Note: it's possible for a vertex shader to get used with a fragment * program (and vice versa) here, but in practice that shouldn't ever * come up, or matter. */ if (fsProg && fsProg->LinkStatus && fsProg->_LinkedShaders[MESA_SHADER_FRAGMENT]) { /* Use GLSL fragment shader */ _mesa_reference_shader_program(ctx, &ctx->Shader._CurrentFragmentProgram, fsProg); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, gl_fragment_program(fsProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program)); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL); } else if (ctx->FragmentProgram._Enabled) { /* Use user-defined fragment program */ _mesa_reference_shader_program(ctx, &ctx->Shader._CurrentFragmentProgram, NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, ctx->FragmentProgram.Current); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL); } else if (ctx->FragmentProgram._MaintainTexEnvProgram) { /* Use fragment program generated from fixed-function state */ struct gl_shader_program *f = _mesa_get_fixed_func_fragment_program(ctx); _mesa_reference_shader_program(ctx, &ctx->Shader._CurrentFragmentProgram, f); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, gl_fragment_program(f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program)); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, gl_fragment_program(f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program)); } else { /* No fragment program */ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL); } if (gsProg && gsProg->LinkStatus && gsProg->_LinkedShaders[MESA_SHADER_GEOMETRY]) { /* Use GLSL geometry shader */ _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, gl_geometry_program(gsProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program)); } else { /* No geometry program */ _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, NULL); } /* Examine vertex program after fragment program as * _mesa_get_fixed_func_vertex_program() needs to know active * fragprog inputs. */ if (vsProg && vsProg->LinkStatus && vsProg->_LinkedShaders[MESA_SHADER_VERTEX]) { /* Use GLSL vertex shader */ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, gl_vertex_program(vsProg->_LinkedShaders[MESA_SHADER_VERTEX]->Program)); } else if (ctx->VertexProgram._Enabled) { /* Use user-defined vertex program */ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, ctx->VertexProgram.Current); } else if (ctx->VertexProgram._MaintainTnlProgram) { /* Use vertex program generated from fixed-function state */ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, _mesa_get_fixed_func_vertex_program(ctx)); _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, ctx->VertexProgram._Current); } else { /* no vertex program */ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL); } /* Let the driver know what's happening: */ if (ctx->FragmentProgram._Current != prevFP) { new_state |= _NEW_PROGRAM; if (ctx->Driver.BindProgram) { ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, (struct gl_program *) ctx->FragmentProgram._Current); } } if (ctx->GeometryProgram._Current != prevGP) { new_state |= _NEW_PROGRAM; if (ctx->Driver.BindProgram) { ctx->Driver.BindProgram(ctx, MESA_GEOMETRY_PROGRAM, (struct gl_program *) ctx->GeometryProgram._Current); } } if (ctx->VertexProgram._Current != prevVP) { new_state |= _NEW_PROGRAM; if (ctx->Driver.BindProgram) { ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB, (struct gl_program *) ctx->VertexProgram._Current); } } return new_state; }
/** * Init context's vertex/fragment program state */ void _mesa_init_program(struct gl_context *ctx) { GLuint i; /* * If this assertion fails, we need to increase the field * size for register indexes (see INST_INDEX_BITS). */ ASSERT(ctx->Const.VertexProgram.MaxUniformComponents / 4 <= (1 << INST_INDEX_BITS)); ASSERT(ctx->Const.FragmentProgram.MaxUniformComponents / 4 <= (1 << INST_INDEX_BITS)); ASSERT(ctx->Const.VertexProgram.MaxTemps <= (1 << INST_INDEX_BITS)); ASSERT(ctx->Const.VertexProgram.MaxLocalParams <= (1 << INST_INDEX_BITS)); ASSERT(ctx->Const.FragmentProgram.MaxTemps <= (1 << INST_INDEX_BITS)); ASSERT(ctx->Const.FragmentProgram.MaxLocalParams <= (1 << INST_INDEX_BITS)); ASSERT(ctx->Const.VertexProgram.MaxUniformComponents <= 4 * MAX_UNIFORMS); ASSERT(ctx->Const.FragmentProgram.MaxUniformComponents <= 4 * MAX_UNIFORMS); /* If this fails, increase prog_instruction::TexSrcUnit size */ ASSERT(MAX_TEXTURE_UNITS < (1 << 5)); /* If this fails, increase prog_instruction::TexSrcTarget size */ ASSERT(NUM_TEXTURE_TARGETS < (1 << 3)); ctx->Program.ErrorPos = -1; ctx->Program.ErrorString = _mesa_strdup(""); #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program ctx->VertexProgram.Enabled = GL_FALSE; #if FEATURE_es2_glsl ctx->VertexProgram.PointSizeEnabled = (ctx->API == API_OPENGLES2) ? GL_TRUE : GL_FALSE; #else ctx->VertexProgram.PointSizeEnabled = GL_FALSE; #endif ctx->VertexProgram.TwoSideEnabled = GL_FALSE; _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, ctx->Shared->DefaultVertexProgram); assert(ctx->VertexProgram.Current); for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) { ctx->VertexProgram.TrackMatrix[i] = GL_NONE; ctx->VertexProgram.TrackMatrixTransform[i] = GL_IDENTITY_NV; } ctx->VertexProgram.Cache = _mesa_new_program_cache(); #endif #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program ctx->FragmentProgram.Enabled = GL_FALSE; _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, ctx->Shared->DefaultFragmentProgram); assert(ctx->FragmentProgram.Current); ctx->FragmentProgram.Cache = _mesa_new_program_cache(); #endif #if FEATURE_ARB_geometry_shader4 ctx->GeometryProgram.Enabled = GL_FALSE; /* right now by default we don't have a geometry program */ _mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current, NULL); ctx->GeometryProgram.Cache = _mesa_new_program_cache(); #endif /* XXX probably move this stuff */ #if FEATURE_ATI_fragment_shader ctx->ATIFragmentShader.Enabled = GL_FALSE; ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader; assert(ctx->ATIFragmentShader.Current); ctx->ATIFragmentShader.Current->RefCount++; #endif }