/** * Binds the given program string to GL_FRAGMENT_PROGRAM_ARB, caching the * program object. */ void meta_set_fragment_program(struct dri_metaops *meta, struct gl_fragment_program **prog, const char *prog_string) { GLcontext *ctx = meta->ctx; assert(meta->saved_fp == NULL); _mesa_reference_fragprog(ctx, &meta->saved_fp, ctx->FragmentProgram.Current); if (*prog == NULL) { GLuint prog_name; _mesa_GenPrograms(1, &prog_name); _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, prog_name); _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(prog_string), (const GLubyte *)prog_string); _mesa_reference_fragprog(ctx, prog, ctx->FragmentProgram.Current); /* Note that DeletePrograms unbinds the program on us */ _mesa_DeletePrograms(1, &prog_name); } FLUSH_VERTICES(ctx, _NEW_PROGRAM); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, *prog); ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, &((*prog)->Base)); meta->saved_fp_enable = ctx->FragmentProgram.Enabled; _mesa_Enable(GL_FRAGMENT_PROGRAM_ARB); }
/** * Delete a list of programs. * \note Not compiled into display lists. * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB. */ void GLAPIENTRY _mesa_DeletePrograms(GLsizei n, const GLuint *ids) { GLint i; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (n < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" ); return; } for (i = 0; i < n; i++) { if (ids[i] != 0) { struct program *prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, ids[i]); if (prog) { if (prog->Target == GL_VERTEX_PROGRAM_NV || prog->Target == GL_VERTEX_STATE_PROGRAM_NV) { if (ctx->VertexProgram.Current && ctx->VertexProgram.Current->Base.Id == ids[i]) { /* unbind this currently bound program */ _mesa_BindProgram(prog->Target, 0); } } else if (prog->Target == GL_FRAGMENT_PROGRAM_NV || prog->Target == GL_FRAGMENT_PROGRAM_ARB) { if (ctx->FragmentProgram.Current && ctx->FragmentProgram.Current->Base.Id == ids[i]) { /* unbind this currently bound program */ _mesa_BindProgram(prog->Target, 0); } } else { _mesa_problem(ctx, "bad target in glDeleteProgramsNV"); return; } prog->RefCount--; if (prog->RefCount <= 0) { _mesa_delete_program(ctx, prog); } /* always remove from hash table */ _mesa_HashRemove(ctx->Shared->Programs, ids[i]); } } } }
/** * Delete a list of programs. * \note Not compiled into display lists. * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB. */ void GLAPIENTRY _mesa_DeletePrograms(GLsizei n, const GLuint *ids) { GLint i; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (n < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" ); return; } for (i = 0; i < n; i++) { if (ids[i] != 0) { struct gl_program *prog = _mesa_lookup_program(ctx, ids[i]); if (prog == &_mesa_DummyProgram) { _mesa_HashRemove(ctx->Shared->Programs, ids[i]); } else if (prog) { /* Unbind program if necessary */ if (prog->Target == GL_VERTEX_PROGRAM_ARB || /* == GL_VERTEX_PROGRAM_NV */ prog->Target == GL_VERTEX_STATE_PROGRAM_NV) { if (ctx->VertexProgram.Current && ctx->VertexProgram.Current->Base.Id == ids[i]) { /* unbind this currently bound program */ _mesa_BindProgram(prog->Target, 0); } } else if (prog->Target == GL_FRAGMENT_PROGRAM_NV || prog->Target == GL_FRAGMENT_PROGRAM_ARB) { if (ctx->FragmentProgram.Current && ctx->FragmentProgram.Current->Base.Id == ids[i]) { /* unbind this currently bound program */ _mesa_BindProgram(prog->Target, 0); } } else { _mesa_problem(ctx, "bad target in glDeleteProgramsNV"); return; } /* The ID is immediately available for re-use now */ _mesa_HashRemove(ctx->Shared->Programs, ids[i]); _mesa_reference_program(ctx, &prog, NULL); } } } }
/** * Set up a vertex program to pass through the position and first texcoord * for pixel path. */ void meta_set_passthrough_vertex_program(struct dri_metaops *meta) { GLcontext *ctx = meta->ctx; static const char *vp = "!!ARBvp1.0\n" "TEMP vertexClip;\n" "DP4 vertexClip.x, state.matrix.mvp.row[0], vertex.position;\n" "DP4 vertexClip.y, state.matrix.mvp.row[1], vertex.position;\n" "DP4 vertexClip.z, state.matrix.mvp.row[2], vertex.position;\n" "DP4 vertexClip.w, state.matrix.mvp.row[3], vertex.position;\n" "MOV result.position, vertexClip;\n" "MOV result.texcoord[0], vertex.texcoord[0];\n" "MOV result.color, vertex.color;\n" "END\n"; assert(meta->saved_vp == NULL); _mesa_reference_vertprog(ctx, &meta->saved_vp, ctx->VertexProgram.Current); if (meta->passthrough_vp == NULL) { GLuint prog_name; _mesa_GenPrograms(1, &prog_name); _mesa_BindProgram(GL_VERTEX_PROGRAM_ARB, prog_name); _mesa_ProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(vp), (const GLubyte *)vp); _mesa_reference_vertprog(ctx, &meta->passthrough_vp, ctx->VertexProgram.Current); _mesa_DeletePrograms(1, &prog_name); } FLUSH_VERTICES(ctx, _NEW_PROGRAM); _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, meta->passthrough_vp); ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB, &meta->passthrough_vp->Base); meta->saved_vp_enable = ctx->VertexProgram.Enabled; _mesa_Enable(GL_VERTEX_PROGRAM_ARB); }