static GLboolean
r700ProgramStringNotify(GLcontext * ctx, GLenum target, struct gl_program *prog)
{
	struct r700_vertex_program_cont *vpc = (struct r700_vertex_program_cont *)prog;
	struct r700_fragment_program * fp = (struct r700_fragment_program*)prog;

	switch (target) {
	case GL_VERTEX_PROGRAM_ARB:
		freeVertProgCache(ctx, vpc);
		vpc->progs = NULL;
		break;
	case GL_FRAGMENT_PROGRAM_ARB:
		r600DeleteShader(ctx, fp->shaderbo);

        if(NULL != fp->constbo0)
        {
		    r600DeleteShader(ctx, fp->constbo0);
		    fp->constbo0   = NULL;
        }

		Clean_Up_Assembler(&(fp->r700AsmCode));
		Clean_Up_Shader(&(fp->r700Shader));
		fp->translated = GL_FALSE;
		fp->loaded     = GL_FALSE;
		fp->shaderbo   = NULL;
		break;
	}
		
	/* XXX check if program is legal, within limits */
	return GL_TRUE;
}
static void r700DeleteProgram(GLcontext * ctx, struct gl_program *prog)
{
    struct r700_vertex_program_cont *vpc = (struct r700_vertex_program_cont *)prog;
    struct r700_fragment_program * fp;

	radeon_print(RADEON_SHADER, RADEON_VERBOSE,
			"%s %p\n", __func__, prog);

    switch (prog->Target) 
    {
    case GL_VERTEX_STATE_PROGRAM_NV:
    case GL_VERTEX_PROGRAM_ARB:	    
	    freeVertProgCache(ctx, vpc);
	    break;
    case GL_FRAGMENT_PROGRAM_NV:
    case GL_FRAGMENT_PROGRAM_ARB:
		fp = (struct r700_fragment_program*)prog;
        /* Release DMA region */

        r600DeleteShader(ctx, fp->shaderbo);

        /* Clean up */
        Clean_Up_Assembler(&(fp->r700AsmCode));
        Clean_Up_Shader(&(fp->r700Shader));
	    break;
    default:
	    _mesa_problem(ctx, "Bad target in r700NewProgram");
    }

	_mesa_delete_program(ctx, prog);
}
static void freeVertProgCache(GLcontext *ctx, struct r700_vertex_program_cont *cache)
{
	struct r700_vertex_program *tmp, *vp = cache->progs;

	while (vp) {
		tmp = vp->next;
		/* Release DMA region */
		r600DeleteShader(ctx, vp->shaderbo);

        if(NULL != vp->constbo0)
        {
		    r600DeleteShader(ctx, vp->constbo0);
        }

		/* Clean up */
		Clean_Up_Assembler(&(vp->r700AsmCode));
		Clean_Up_Shader(&(vp->r700Shader));
		
		_mesa_reference_vertprog(ctx, &vp->mesa_program, NULL);
		free(vp);
		vp = tmp;
	}
}
static void
r700ProgramStringNotify(GLcontext * ctx, GLenum target, struct gl_program *prog)
{
	struct r700_vertex_program_cont *vpc = (struct r700_vertex_program_cont *)prog;
	struct r700_fragment_program * fp = (struct r700_fragment_program*)prog;

	switch (target) {
	case GL_VERTEX_PROGRAM_ARB:
		freeVertProgCache(ctx, vpc);
		vpc->progs = NULL;
		break;
	case GL_FRAGMENT_PROGRAM_ARB:
		r600DeleteShader(ctx, fp->shaderbo);
		Clean_Up_Assembler(&(fp->r700AsmCode));
		Clean_Up_Shader(&(fp->r700Shader));
		fp->translated = GL_FALSE;
		fp->loaded     = GL_FALSE;
		fp->shaderbo   = NULL;
		break;
	}
		
}