summaryrefslogtreecommitdiff
path: root/src/mesa
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa')
-rwxr-xr-xsrc/mesa/main/context.c42
-rw-r--r--src/mesa/main/ffvertex_prog.c43
-rw-r--r--src/mesa/main/imports.c36
-rw-r--r--src/mesa/main/mtypes.h4
-rw-r--r--src/mesa/main/state.c32
-rw-r--r--src/mesa/shader/prog_cache.c5
-rw-r--r--src/mesa/shader/program.c103
-rw-r--r--src/mesa/shader/program.h22
-rw-r--r--src/mesa/shader/shader_api.c6
-rw-r--r--src/mesa/shader/slang/slang_link.c12
-rw-r--r--src/mesa/state_tracker/st_atom.h28
-rw-r--r--src/mesa/state_tracker/st_atom_shader.c7
-rw-r--r--src/mesa/state_tracker/st_cb_texture.c2
-rw-r--r--src/mesa/state_tracker/st_context.c3
-rw-r--r--src/mesa/state_tracker/st_program.h24
15 files changed, 237 insertions, 132 deletions
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index 7b8d934170..893c79f28c 100755
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -150,8 +150,6 @@ int MESA_DEBUG_FLAGS = 0;
/* ubyte -> float conversion */
GLfloat _mesa_ubyte_to_float_color_tab[256];
-static void
-free_shared_state( GLcontext *ctx, struct gl_shared_state *ss );
/**
@@ -423,12 +421,14 @@ alloc_shared_state( GLcontext *ctx )
#endif
#if FEATURE_ARB_vertex_program
- ss->DefaultVertexProgram = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
+ ss->DefaultVertexProgram = (struct gl_vertex_program *)
+ ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
if (!ss->DefaultVertexProgram)
goto cleanup;
#endif
#if FEATURE_ARB_fragment_program
- ss->DefaultFragmentProgram = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
+ ss->DefaultFragmentProgram = (struct gl_fragment_program *)
+ ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
if (!ss->DefaultFragmentProgram)
goto cleanup;
#endif
@@ -513,12 +513,10 @@ alloc_shared_state( GLcontext *ctx )
_mesa_DeleteHashTable(ss->Programs);
#endif
#if FEATURE_ARB_vertex_program
- if (ss->DefaultVertexProgram)
- ctx->Driver.DeleteProgram(ctx, ss->DefaultVertexProgram);
+ _mesa_reference_vertprog(ctx, &ss->DefaultVertexProgram, NULL);
#endif
#if FEATURE_ARB_fragment_program
- if (ss->DefaultFragmentProgram)
- ctx->Driver.DeleteProgram(ctx, ss->DefaultFragmentProgram);
+ _mesa_reference_fragprog(ctx, &ss->DefaultFragmentProgram, NULL);
#endif
#if FEATURE_ATI_fragment_shader
if (ss->DefaultFragmentShader)
@@ -633,6 +631,21 @@ delete_arrayobj_cb(GLuint id, void *data, void *userData)
}
/**
+ * Callback for freeing shader program data. Call it before delete_shader_cb
+ * to avoid memory access error.
+ */
+static void
+free_shader_program_data_cb(GLuint id, void *data, void *userData)
+{
+ GLcontext *ctx = (GLcontext *) userData;
+ struct gl_shader_program *shProg = (struct gl_shader_program *) data;
+
+ if (shProg->Type == GL_SHADER_PROGRAM_MESA) {
+ _mesa_free_shader_program_data(ctx, shProg);
+ }
+}
+
+/**
* Callback for deleting shader and shader programs objects.
* Called by _mesa_HashDeleteAll().
*/
@@ -695,10 +708,10 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss )
_mesa_DeleteHashTable(ss->Programs);
#endif
#if FEATURE_ARB_vertex_program
- ctx->Driver.DeleteProgram(ctx, ss->DefaultVertexProgram);
+ _mesa_reference_vertprog(ctx, &ss->DefaultVertexProgram, NULL);
#endif
#if FEATURE_ARB_fragment_program
- ctx->Driver.DeleteProgram(ctx, ss->DefaultFragmentProgram);
+ _mesa_reference_fragprog(ctx, &ss->DefaultFragmentProgram, NULL);
#endif
#if FEATURE_ATI_fragment_shader
@@ -716,6 +729,7 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss )
_mesa_DeleteHashTable(ss->ArrayObjects);
#if FEATURE_ARB_shader_objects
+ _mesa_HashWalk(ss->ShaderObjects, free_shader_program_data_cb, ctx);
_mesa_HashDeleteAll(ss->ShaderObjects, delete_shader_cb, ctx);
_mesa_DeleteHashTable(ss->ShaderObjects);
#endif
@@ -1190,6 +1204,14 @@ _mesa_free_context_data( GLcontext *ctx )
_mesa_unreference_framebuffer(&ctx->ReadBuffer);
}
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL);
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL);
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, NULL);
+
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL);
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL);
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL);
+
_mesa_free_lighting_data( ctx );
_mesa_free_eval_data( ctx );
_mesa_free_texture_data( ctx );
diff --git a/src/mesa/main/ffvertex_prog.c b/src/mesa/main/ffvertex_prog.c
index f648d081c0..810af9e33e 100644
--- a/src/mesa/main/ffvertex_prog.c
+++ b/src/mesa/main/ffvertex_prog.c
@@ -946,35 +946,33 @@ static void build_lighting( struct tnl_program *p )
_bfc1 = _bfc0;
}
-
/* If no lights, still need to emit the scenecolor.
*/
- {
- struct ureg res0 = register_output( p, VERT_RESULT_COL0 );
- emit_op1(p, OPCODE_MOV, res0, 0, _col0);
- }
+ {
+ struct ureg res0 = register_output( p, VERT_RESULT_COL0 );
+ emit_op1(p, OPCODE_MOV, res0, 0, _col0);
+ }
- if (separate) {
- struct ureg res1 = register_output( p, VERT_RESULT_COL1 );
- emit_op1(p, OPCODE_MOV, res1, 0, _col1);
- }
+ if (separate) {
+ struct ureg res1 = register_output( p, VERT_RESULT_COL1 );
+ emit_op1(p, OPCODE_MOV, res1, 0, _col1);
+ }
- if (twoside) {
- struct ureg res0 = register_output( p, VERT_RESULT_BFC0 );
- emit_op1(p, OPCODE_MOV, res0, 0, _bfc0);
- }
+ if (twoside) {
+ struct ureg res0 = register_output( p, VERT_RESULT_BFC0 );
+ emit_op1(p, OPCODE_MOV, res0, 0, _bfc0);
+ }
- if (twoside && separate) {
- struct ureg res1 = register_output( p, VERT_RESULT_BFC1 );
- emit_op1(p, OPCODE_MOV, res1, 0, _bfc1);
- }
+ if (twoside && separate) {
+ struct ureg res1 = register_output( p, VERT_RESULT_BFC1 );
+ emit_op1(p, OPCODE_MOV, res1, 0, _bfc1);
+ }
if (nr_lights == 0) {
release_temps(p);
return;
}
-
for (i = 0; i < MAX_LIGHTS; i++) {
if (p->state->unit[i].light_enabled) {
struct ureg half = undef;
@@ -1006,7 +1004,7 @@ static void build_lighting( struct tnl_program *p )
VPpli = get_temp(p);
half = get_temp(p);
- /* Calulate VPpli vector
+ /* Calculate VPpli vector
*/
emit_op2(p, OPCODE_SUB, VPpli, 0, Ppli, V);
@@ -1017,15 +1015,13 @@ static void build_lighting( struct tnl_program *p )
emit_op1(p, OPCODE_RSQ, dist, 0, dist);
emit_op2(p, OPCODE_MUL, VPpli, 0, VPpli, dist);
-
- /* Calculate attenuation:
+ /* Calculate attenuation:
*/
if (!p->state->unit[i].light_spotcutoff_is_180 ||
p->state->unit[i].light_attenuated) {
att = calculate_light_attenuation(p, i, VPpli, dist);
}
-
-
+
/* Calculate viewer direction, or use infinite viewer:
*/
if (p->state->light_local_viewer) {
@@ -1047,7 +1043,6 @@ static void build_lighting( struct tnl_program *p )
emit_op2(p, OPCODE_DP3, dots, WRITEMASK_X, normal, VPpli);
emit_op2(p, OPCODE_DP3, dots, WRITEMASK_Y, normal, half);
-
/* Front face lighting:
*/
{
diff --git a/src/mesa/main/imports.c b/src/mesa/main/imports.c
index d8d35af15e..d798f80e25 100644
--- a/src/mesa/main/imports.c
+++ b/src/mesa/main/imports.c
@@ -542,26 +542,24 @@ int
_mesa_ffs(int i)
{
#if (defined(_WIN32) && !defined(__MINGW32__) ) || defined(__IBMC__) || defined(__IBMCPP__)
- register int bit = 0;
- if (i != 0) {
- if ((i & 0xffff) == 0) {
- bit += 16;
- i >>= 16;
- }
- if ((i & 0xff) == 0) {
- bit += 8;
- i >>= 8;
- }
- if ((i & 0xf) == 0) {
- bit += 4;
- i >>= 4;
- }
- while ((i & 1) == 0) {
- bit++;
- i >>= 1;
- }
+ register int bit = 1;
+ if ((i & 0xffff) == 0) {
+ bit += 16;
+ i >>= 16;
+ }
+ if ((i & 0xff) == 0) {
+ bit += 8;
+ i >>= 8;
+ }
+ if ((i & 0xf) == 0) {
+ bit += 4;
+ i >>= 4;
+ }
+ if ((i & 0x3) == 0) {
+ bit += 2;
+ i >>= 2;
}
- return bit;
+ return (i) ? (bit + ((i + 1) & 0x01)) : 0;
#else
return ffs(i);
#endif
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 50b22d25bf..463142fe39 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2203,10 +2203,10 @@ struct gl_shared_state
/*@{*/
struct _mesa_HashTable *Programs; /**< All vertex/fragment programs */
#if FEATURE_ARB_vertex_program
- struct gl_program *DefaultVertexProgram;
+ struct gl_vertex_program *DefaultVertexProgram;
#endif
#if FEATURE_ARB_fragment_program
- struct gl_program *DefaultFragmentProgram;
+ struct gl_fragment_program *DefaultFragmentProgram;
#endif
/*@}*/
diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c
index 0b1c56fdd5..90379a1772 100644
--- a/src/mesa/main/state.c
+++ b/src/mesa/main/state.c
@@ -982,16 +982,20 @@ update_program(GLcontext *ctx)
#endif
if (shProg && shProg->LinkStatus && shProg->FragmentProgram) {
/* user-defined fragment shader */
- ctx->FragmentProgram._Current = shProg->FragmentProgram;
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
+ shProg->FragmentProgram);
}
else if (ctx->FragmentProgram._Enabled) {
/* use user-defined fragment program */
- ctx->FragmentProgram._Current = ctx->FragmentProgram.Current;
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
+ ctx->FragmentProgram.Current);
}
else if (ctx->FragmentProgram._MaintainTexEnvProgram) {
/* fragment program generated from fixed-function state */
- ctx->FragmentProgram._Current = _mesa_get_fixed_func_fragment_program(ctx);
- ctx->FragmentProgram._TexEnvProgram = ctx->FragmentProgram._Current;
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
+ _mesa_get_fixed_func_fragment_program(ctx));
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram,
+ ctx->FragmentProgram._Current);
/* XXX get rid of this confusing stuff someday? */
ctx->FragmentProgram._Active = ctx->FragmentProgram._Enabled;
@@ -1000,7 +1004,7 @@ update_program(GLcontext *ctx)
}
else {
/* no fragment program */
- ctx->FragmentProgram._Current = NULL;
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL);
}
if (ctx->FragmentProgram._Current != prevFP && ctx->Driver.BindProgram) {
@@ -1013,29 +1017,33 @@ update_program(GLcontext *ctx)
**/
#if 1
/* XXX get rid of this someday? */
- ctx->VertexProgram._TnlProgram = NULL;
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, NULL);
#endif
if (shProg && shProg->LinkStatus && shProg->VertexProgram) {
/* user-defined vertex shader */
- ctx->VertexProgram._Current = shProg->VertexProgram;
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current,
+ shProg->VertexProgram);
}
else if (ctx->VertexProgram._Enabled) {
/* use user-defined vertex program */
- ctx->VertexProgram._Current = ctx->VertexProgram.Current;
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current,
+ ctx->VertexProgram.Current);
}
else if (ctx->VertexProgram._MaintainTnlProgram) {
/* vertex program generated from fixed-function state */
- ctx->VertexProgram._Current = _mesa_get_fixed_func_vertex_program(ctx);
- ctx->VertexProgram._TnlProgram = ctx->VertexProgram._Current;
+ _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 / used fixed-function code */
- ctx->VertexProgram._Current = NULL;
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL);
}
if (ctx->VertexProgram._Current != prevVP && ctx->Driver.BindProgram) {
ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
- (struct gl_program *) ctx->VertexProgram._Current);
+ (struct gl_program *) ctx->VertexProgram._Current);
}
}
diff --git a/src/mesa/shader/prog_cache.c b/src/mesa/shader/prog_cache.c
index dd0241ef24..36a25377c5 100644
--- a/src/mesa/shader/prog_cache.c
+++ b/src/mesa/shader/prog_cache.c
@@ -30,6 +30,7 @@
#include "main/mtypes.h"
#include "main/imports.h"
#include "shader/prog_cache.h"
+#include "shader/program.h"
struct cache_item
@@ -109,7 +110,7 @@ clear_cache(GLcontext *ctx, struct gl_program_cache *cache)
for (c = cache->items[i]; c; c = next) {
next = c->next;
_mesa_free(c->key);
- ctx->Driver.DeleteProgram(ctx, c->program);
+ _mesa_reference_program(ctx, &c->program, NULL);
_mesa_free(c);
}
cache->items[i] = NULL;
@@ -177,7 +178,7 @@ _mesa_program_cache_insert(GLcontext *ctx,
c->key = _mesa_malloc(keysize);
memcpy(c->key, key, keysize);
- c->program = program;
+ c->program = program; /* no refcount change */
if (cache->n_items > cache->size * 1.5) {
if (cache->size < 1000)
diff --git a/src/mesa/shader/program.c b/src/mesa/shader/program.c
index 0ed7f833d2..9a23c5d7d3 100644
--- a/src/mesa/shader/program.c
+++ b/src/mesa/shader/program.c
@@ -60,9 +60,9 @@ _mesa_init_program(GLcontext *ctx)
ctx->VertexProgram.Enabled = GL_FALSE;
ctx->VertexProgram.PointSizeEnabled = GL_FALSE;
ctx->VertexProgram.TwoSideEnabled = GL_FALSE;
- ctx->VertexProgram.Current = (struct gl_vertex_program *) ctx->Shared->DefaultVertexProgram;
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
+ ctx->Shared->DefaultVertexProgram);
assert(ctx->VertexProgram.Current);
- ctx->VertexProgram.Current->Base.RefCount++;
for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) {
ctx->VertexProgram.TrackMatrix[i] = GL_NONE;
ctx->VertexProgram.TrackMatrixTransform[i] = GL_IDENTITY_NV;
@@ -72,9 +72,9 @@ _mesa_init_program(GLcontext *ctx)
#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
ctx->FragmentProgram.Enabled = GL_FALSE;
- ctx->FragmentProgram.Current = (struct gl_fragment_program *) ctx->Shared->DefaultFragmentProgram;
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
+ ctx->Shared->DefaultFragmentProgram);
assert(ctx->FragmentProgram.Current);
- ctx->FragmentProgram.Current->Base.RefCount++;
ctx->FragmentProgram.Cache = _mesa_new_program_cache();
#endif
@@ -96,19 +96,11 @@ void
_mesa_free_program_data(GLcontext *ctx)
{
#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
- if (ctx->VertexProgram.Current) {
- ctx->VertexProgram.Current->Base.RefCount--;
- if (ctx->VertexProgram.Current->Base.RefCount <= 0)
- ctx->Driver.DeleteProgram(ctx, &(ctx->VertexProgram.Current->Base));
- }
+ _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
- if (ctx->FragmentProgram.Current) {
- ctx->FragmentProgram.Current->Base.RefCount--;
- if (ctx->FragmentProgram.Current->Base.RefCount <= 0)
- ctx->Driver.DeleteProgram(ctx, &(ctx->FragmentProgram.Current->Base));
- }
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL);
_mesa_delete_program_cache(ctx, ctx->FragmentProgram.Cache);
#endif
/* XXX probably move this stuff */
@@ -326,6 +318,59 @@ _mesa_lookup_program(GLcontext *ctx, GLuint id)
/**
+ * Reference counting for vertex/fragment programs
+ */
+void
+_mesa_reference_program(GLcontext *ctx,
+ struct gl_program **ptr,
+ struct gl_program *prog)
+{
+ assert(ptr);
+ if (*ptr && prog) {
+ /* sanity check */
+ ASSERT((*ptr)->Target == prog->Target);
+ }
+ if (*ptr == prog) {
+ return; /* no change */
+ }
+ if (*ptr) {
+ GLboolean deleteFlag;
+
+ /*_glthread_LOCK_MUTEX((*ptr)->Mutex);*/
+#if 0
+ printf("Program %p %u 0x%x Refcount-- to %d\n",
+ *ptr, (*ptr)->Id, (*ptr)->Target, (*ptr)->RefCount - 1);
+#endif
+ ASSERT((*ptr)->RefCount > 0);
+ (*ptr)->RefCount--;
+
+ deleteFlag = ((*ptr)->RefCount == 0);
+ /*_glthread_UNLOCK_MUTEX((*ptr)->Mutex);*/
+
+ if (deleteFlag) {
+ ASSERT(ctx);
+ ctx->Driver.DeleteProgram(ctx, *ptr);
+ }
+
+ *ptr = NULL;
+ }
+
+ assert(!*ptr);
+ if (prog) {
+ /*_glthread_LOCK_MUTEX(prog->Mutex);*/
+ prog->RefCount++;
+#if 0
+ printf("Program %p %u 0x%x Refcount++ to %d\n",
+ prog, prog->Id, prog->Target, prog->RefCount);
+#endif
+ /*_glthread_UNLOCK_MUTEX(prog->Mutex);*/
+ }
+
+ *ptr = prog;
+}
+
+
+/**
* Return a copy of a program.
* XXX Problem here if the program object is actually OO-derivation
* made by a device driver.
@@ -340,8 +385,9 @@ _mesa_clone_program(GLcontext *ctx, const struct gl_program *prog)
return NULL;
assert(clone->Target == prog->Target);
+ assert(clone->RefCount == 1);
+
clone->String = (GLubyte *) _mesa_strdup((char *) prog->String);
- clone->RefCount = 1;
clone->Format = prog->Format;
clone->Instructions = _mesa_alloc_instructions(prog->NumInstructions);
if (!clone->Instructions) {
@@ -704,9 +750,9 @@ _mesa_BindProgram(GLenum target, GLuint id)
/* Bind a default program */
newProg = NULL;
if (target == GL_VERTEX_PROGRAM_ARB) /* == GL_VERTEX_PROGRAM_NV */
- newProg = ctx->Shared->DefaultVertexProgram;
+ newProg = &ctx->Shared->DefaultVertexProgram->Base;
else
- newProg = ctx->Shared->DefaultFragmentProgram;
+ newProg = &ctx->Shared->DefaultFragmentProgram->Base;
}
else {
/* Bind a user program */
@@ -734,26 +780,16 @@ _mesa_BindProgram(GLenum target, GLuint id)
return;
}
- /* unbind/delete oldProg */
- if (curProg->Id != 0) {
- /* decrement refcount on previously bound fragment program */
- curProg->RefCount--;
- /* and delete if refcount goes below one */
- if (curProg->RefCount <= 0) {
- /* the program ID was already removed from the hash table */
- ctx->Driver.DeleteProgram(ctx, curProg);
- }
- }
-
/* bind newProg */
if (target == GL_VERTEX_PROGRAM_ARB) { /* == GL_VERTEX_PROGRAM_NV */
- ctx->VertexProgram.Current = (struct gl_vertex_program *) newProg;
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
+ (struct gl_vertex_program *) newProg);
}
else if (target == GL_FRAGMENT_PROGRAM_NV ||
target == GL_FRAGMENT_PROGRAM_ARB) {
- ctx->FragmentProgram.Current = (struct gl_fragment_program *) newProg;
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
+ (struct gl_fragment_program *) newProg);
}
- newProg->RefCount++;
/* Never null pointers */
ASSERT(ctx->VertexProgram.Current);
@@ -811,10 +847,7 @@ _mesa_DeletePrograms(GLsizei n, const GLuint *ids)
}
/* The ID is immediately available for re-use now */
_mesa_HashRemove(ctx->Shared->Programs, ids[i]);
- prog->RefCount--;
- if (prog->RefCount <= 0) {
- ctx->Driver.DeleteProgram(ctx, prog);
- }
+ _mesa_reference_program(ctx, &prog, NULL);
}
}
}
diff --git a/src/mesa/shader/program.h b/src/mesa/shader/program.h
index 414a57d39c..08fe576afc 100644
--- a/src/mesa/shader/program.h
+++ b/src/mesa/shader/program.h
@@ -83,6 +83,28 @@ _mesa_delete_program(GLcontext *ctx, struct gl_program *prog);
extern struct gl_program *
_mesa_lookup_program(GLcontext *ctx, GLuint id);
+extern void
+_mesa_reference_program(GLcontext *ctx,
+ struct gl_program **ptr,
+ struct gl_program *prog);
+
+static INLINE void
+_mesa_reference_vertprog(GLcontext *ctx,
+ struct gl_vertex_program **ptr,
+ struct gl_vertex_program *prog)
+{
+ _mesa_reference_program(ctx, (struct gl_program **) ptr,
+ (struct gl_program *) prog);
+}
+
+static INLINE void
+_mesa_reference_fragprog(GLcontext *ctx,
+ struct gl_fragment_program **ptr,
+ struct gl_fragment_program *prog)
+{
+ _mesa_reference_program(ctx, (struct gl_program **) ptr,
+ (struct gl_program *) prog);
+}
extern struct gl_program *
_mesa_clone_program(GLcontext *ctx, const struct gl_program *prog);
diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c
index 9c419c9903..f12fa28d97 100644
--- a/src/mesa/shader/shader_api.c
+++ b/src/mesa/shader/shader_api.c
@@ -80,8 +80,7 @@ _mesa_clear_shader_program_data(GLcontext *ctx,
* original/unlinked program.
*/
shProg->VertexProgram->Base.Parameters = NULL;
- ctx->Driver.DeleteProgram(ctx, &shProg->VertexProgram->Base);
- shProg->VertexProgram = NULL;
+ _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
}
if (shProg->FragmentProgram) {
@@ -89,8 +88,7 @@ _mesa_clear_shader_program_data(GLcontext *ctx,
* original/unlinked program.
*/
shProg->FragmentProgram->Base.Parameters = NULL;
- ctx->Driver.DeleteProgram(ctx, &shProg->FragmentProgram->Base);
- shProg->FragmentProgram = NULL;
+ _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
}
if (shProg->Uniforms) {
diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c
index addff20421..ae581553dc 100644
--- a/src/mesa/shader/slang/slang_link.c
+++ b/src/mesa/shader/slang/slang_link.c
@@ -410,19 +410,19 @@ _slang_link(GLcontext *ctx,
* changing src/dst registers after merging the uniforms and varying vars.
*/
if (vertProg) {
- shProg->VertexProgram
- = vertex_program(_mesa_clone_program(ctx, &vertProg->Base));
+ _mesa_reference_vertprog(ctx, &shProg->VertexProgram,
+ vertex_program(_mesa_clone_program(ctx, &vertProg->Base)));
}
else {
- shProg->VertexProgram = NULL;
+ _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
}
if (fragProg) {
- shProg->FragmentProgram
- = fragment_program(_mesa_clone_program(ctx, &fragProg->Base));
+ _mesa_reference_fragprog(ctx, &shProg->FragmentProgram,
+ fragment_program(_mesa_clone_program(ctx, &fragProg->Base)));
}
else {
- shProg->FragmentProgram = NULL;
+ _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
}
/* link varying vars */
diff --git a/src/mesa/state_tracker/st_atom.h b/src/mesa/state_tracker/st_atom.h
index 3a63e2dec0..c6c6eba812 100644
--- a/src/mesa/state_tracker/st_atom.h
+++ b/src/mesa/state_tracker/st_atom.h
@@ -44,20 +44,20 @@ void st_destroy_atoms( struct st_context *st );
void st_validate_state( struct st_context *st );
-const struct st_tracked_state st_update_framebuffer;
-const struct st_tracked_state st_update_clip;
-const struct st_tracked_state st_update_depth_stencil_alpha;
-const struct st_tracked_state st_update_shader;
-const struct st_tracked_state st_update_rasterizer;
-const struct st_tracked_state st_update_polygon_stipple;
-const struct st_tracked_state st_update_viewport;
-const struct st_tracked_state st_update_scissor;
-const struct st_tracked_state st_update_blend;
-const struct st_tracked_state st_update_sampler;
-const struct st_tracked_state st_update_texture;
-const struct st_tracked_state st_update_fs_constants;
-const struct st_tracked_state st_update_vs_constants;
-const struct st_tracked_state st_update_pixel_transfer;
+extern const struct st_tracked_state st_update_framebuffer;
+extern const struct st_tracked_state st_update_clip;
+extern const struct st_tracked_state st_update_depth_stencil_alpha;
+extern const struct st_tracked_state st_update_shader;
+extern const struct st_tracked_state st_update_rasterizer;
+extern const struct st_tracked_state st_update_polygon_stipple;
+extern const struct st_tracked_state st_update_viewport;
+extern const struct st_tracked_state st_update_scissor;
+extern const struct st_tracked_state st_update_blend;
+extern const struct st_tracked_state st_update_sampler;
+extern const struct st_tracked_state st_update_texture;
+extern const struct st_tracked_state st_update_fs_constants;
+extern const struct st_tracked_state st_update_vs_constants;
+extern const struct st_tracked_state st_update_pixel_transfer;
uint st_compare_func_to_pipe(GLenum func);
diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c
index 652500f52a..7745591afb 100644
--- a/src/mesa/state_tracker/st_atom_shader.c
+++ b/src/mesa/state_tracker/st_atom_shader.c
@@ -39,6 +39,7 @@
#include "main/imports.h"
#include "main/mtypes.h"
+#include "shader/program.h"
#include "pipe/p_context.h"
#include "pipe/p_shader_tokens.h"
@@ -264,14 +265,16 @@ update_linkage( struct st_context *st )
*/
assert(st->ctx->VertexProgram._Current);
stvp = st_vertex_program(st->ctx->VertexProgram._Current);
+ assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB);
assert(st->ctx->FragmentProgram._Current);
stfp = st_fragment_program(st->ctx->FragmentProgram._Current);
+ assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB);
xvp = find_translated_vp(st, stvp, stfp);
- st->vp = stvp;
- st->fp = stfp;
+ st_reference_vertprog(st, &st->vp, stvp);
+ st_reference_fragprog(st, &st->fp, stfp);
cso_set_vertex_shader_handle(st->cso_context, stvp->driver_shader);
cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader);
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index 02ef961e4d..866683c23e 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -1366,7 +1366,7 @@ calculate_first_last_level(struct st_texture_object *stObj)
}
else {
firstLevel = 0;
- lastLevel = MIN2(tObj->MaxLevel, tObj->Image[0][0]->WidthLog2);
+ lastLevel = MIN2(tObj->MaxLevel, tObj->Image[0][tObj->BaseLevel]->WidthLog2);
}
break;
case GL_TEXTURE_RECTANGLE_NV:
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
index c900064f2b..8db55a179f 100644
--- a/src/mesa/state_tracker/st_context.c
+++ b/src/mesa/state_tracker/st_context.c
@@ -158,6 +158,9 @@ static void st_destroy_context_priv( struct st_context *st )
{
uint i;
+ st_reference_fragprog(st, &st->fp, NULL);
+ st_reference_vertprog(st, &st->vp, NULL);
+
draw_destroy(st->draw);
st_destroy_atoms( st );
st_destroy_draw( st );
diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h
index d8f26da2ee..bf07a50789 100644
--- a/src/mesa/state_tracker/st_program.h
+++ b/src/mesa/state_tracker/st_program.h
@@ -34,7 +34,8 @@
#ifndef ST_PROGRAM_H
#define ST_PROGRAM_H
-#include "mtypes.h"
+#include "main/mtypes.h"
+#include "shader/program.h"
#include "pipe/p_shader_tokens.h"
@@ -115,6 +116,27 @@ st_vertex_program( struct gl_vertex_program *vp )
}
+static INLINE void
+st_reference_vertprog(struct st_context *st,
+ struct st_vertex_program **ptr,
+ struct st_vertex_program *prog)
+{
+ _mesa_reference_program(st->ctx,
+ (struct gl_program **) ptr,
+ (struct gl_program *) prog);
+}
+
+static INLINE void
+st_reference_fragprog(struct st_context *st,
+ struct st_fragment_program **ptr,
+ struct st_fragment_program *prog)
+{
+ _mesa_reference_program(st->ctx,
+ (struct gl_program **) ptr,
+ (struct gl_program *) prog);
+}
+
+
extern void
st_translate_fragment_program(struct st_context *st,
struct st_fragment_program *fp,