void GLAPIENTRY _mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len, const GLvoid *string) { struct gl_program *base; bool failed; GET_CURRENT_CONTEXT(ctx); FLUSH_VERTICES(ctx, _NEW_PROGRAM); if (!ctx->Extensions.ARB_vertex_program && !ctx->Extensions.ARB_fragment_program) { _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramStringARB()"); return; } if (format != GL_PROGRAM_FORMAT_ASCII_ARB) { _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(format)"); return; } if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) { struct gl_vertex_program *prog = ctx->VertexProgram.Current; _mesa_parse_arb_vertex_program(ctx, target, string, len, prog); base = & prog->Base; } else if (target == GL_FRAGMENT_PROGRAM_ARB && ctx->Extensions.ARB_fragment_program) { struct gl_fragment_program *prog = ctx->FragmentProgram.Current; _mesa_parse_arb_fragment_program(ctx, target, string, len, prog); base = & prog->Base; } else { _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)"); return; } failed = ctx->Program.ErrorPos != -1; if (!failed) { /* finally, give the program to the driver for translation/checking */ if (!ctx->Driver.ProgramStringNotify(ctx, target, base)) { failed = true; _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramStringARB(rejected by driver"); } } if (ctx->_Shader->Flags & GLSL_DUMP) { const char *shader_type = target == GL_FRAGMENT_PROGRAM_ARB ? "fragment" : "vertex"; fprintf(stderr, "ARB_%s_program source for program %d:\n", shader_type, base->Id); fprintf(stderr, "%s\n", (const char *) string); if (failed) { fprintf(stderr, "ARB_%s_program %d failed to compile.\n", shader_type, base->Id); } else { fprintf(stderr, "Mesa IR for ARB_%s_program %d:\n", shader_type, base->Id); _mesa_print_program(base); fprintf(stderr, "\n"); } fflush(stderr); } /* Capture vp-*.shader_test/fp-*.shader_test files. */ const char *capture_path = _mesa_get_shader_capture_path(); if (capture_path != NULL) { FILE *file; const char *shader_type = target == GL_FRAGMENT_PROGRAM_ARB ? "fragment" : "vertex"; char *filename = ralloc_asprintf(NULL, "%s/%cp-%u.shader_test", capture_path, shader_type[0], base->Id); file = fopen(filename, "w"); if (file) { fprintf(file, "[require]\nGL_ARB_%s_program\n\n[%s program]\n%s\n", shader_type, shader_type, (const char *) string); fclose(file); } else { _mesa_warning(ctx, "Failed to open %s", filename); } ralloc_free(filename); } }
/** * Load/parse/compile a program. * \note Called from the GL API dispatcher. */ void GLAPIENTRY _mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len, const GLubyte *program) { struct gl_program *prog; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (!ctx->Extensions.NV_vertex_program && !ctx->Extensions.NV_fragment_program) { _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV()"); return; } if (id == 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(id)"); return; } if (len < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(len)"); return; } FLUSH_VERTICES(ctx, _NEW_PROGRAM); prog = _mesa_lookup_program(ctx, id); if (prog && prog->Target != 0 && prog->Target != target) { _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target)"); return; } if ((target == GL_VERTEX_PROGRAM_NV || target == GL_VERTEX_STATE_PROGRAM_NV) && ctx->Extensions.NV_vertex_program) { struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog; if (!vprog || prog == &_mesa_DummyProgram) { vprog = (struct gl_vertex_program *) ctx->Driver.NewProgram(ctx, target, id); if (!vprog) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); return; } _mesa_HashInsert(ctx->Shared->Programs, id, vprog); } if (ctx->Extensions.ARB_vertex_program && (strncmp((char *) program, "!!ARB", 5) == 0)) { _mesa_parse_arb_vertex_program(ctx, target, program, len, vprog); } else { _mesa_parse_nv_vertex_program(ctx, target, program, len, vprog); } } else if (target == GL_FRAGMENT_PROGRAM_NV && ctx->Extensions.NV_fragment_program) { struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog; if (!fprog || prog == &_mesa_DummyProgram) { fprog = (struct gl_fragment_program *) ctx->Driver.NewProgram(ctx, target, id); if (!fprog) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); return; } _mesa_HashInsert(ctx->Shared->Programs, id, fprog); } _mesa_parse_nv_fragment_program(ctx, target, program, len, fprog); } else if (target == GL_FRAGMENT_PROGRAM_ARB && ctx->Extensions.ARB_fragment_program) { struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog; if (!fprog || prog == &_mesa_DummyProgram) { fprog = (struct gl_fragment_program *) ctx->Driver.NewProgram(ctx, target, id); if (!fprog) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); return; } _mesa_HashInsert(ctx->Shared->Programs, id, fprog); } _mesa_parse_arb_fragment_program(ctx, target, program, len, fprog); } else { _mesa_error(ctx, GL_INVALID_ENUM, "glLoadProgramNV(target)"); } }