/** * For GL_EXT_separate_shader_objects */ GLuint GLAPIENTRY _mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string) { GET_CURRENT_CONTEXT(ctx); const GLuint shader = create_shader(ctx, type); GLuint program = 0; if (shader) { shader_source(ctx, shader, _mesa_strdup(string)); compile_shader(ctx, shader); program = create_shader_program(ctx); if (program) { struct gl_shader_program *shProg; struct gl_shader *sh; GLint compiled = GL_FALSE; shProg = _mesa_lookup_shader_program(ctx, program); sh = _mesa_lookup_shader(ctx, shader); get_shaderiv(ctx, shader, GL_COMPILE_STATUS, &compiled); if (compiled) { attach_shader(ctx, program, shader); link_program(ctx, program); detach_shader(ctx, program, shader); #if 0 /* Possibly... */ if (active-user-defined-varyings-in-linked-program) { append-error-to-info-log; shProg->LinkStatus = GL_FALSE; } #endif } ralloc_strcat(&shProg->InfoLog, sh->InfoLog); } delete_shader(ctx, shader); } return program; }
/*!\fn const WRATHGLShader::shader_source& fragment_shader_source Provided as a conveniance, equivalent to calling shader_source(GLenum) const passing GL_FRAGMENT_SHADER as the argument */ const WRATHGLShader::shader_source& fragment_shader_source(void) const { return shader_source(GL_FRAGMENT_SHADER); }
/** * Called via glShaderSource() and glShaderSourceARB() API functions. * Basically, concatenate the source code strings into one long string * and pass it to _mesa_shader_source(). */ void GLAPIENTRY _mesa_ShaderSourceARB(GLhandleARB shaderObj, GLsizei count, const GLcharARB ** string, const GLint * length) { GET_CURRENT_CONTEXT(ctx); GLint *offsets; GLsizei i, totalLength; GLcharARB *source; GLuint checksum; if (!shaderObj || string == NULL) { _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSourceARB"); return; } /* * This array holds offsets of where the appropriate string ends, thus the * last element will be set to the total length of the source code. */ offsets = (GLint *) malloc(count * sizeof(GLint)); if (offsets == NULL) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB"); return; } for (i = 0; i < count; i++) { if (string[i] == NULL) { free((GLvoid *) offsets); _mesa_error(ctx, GL_INVALID_OPERATION, "glShaderSourceARB(null string)"); return; } if (length == NULL || length[i] < 0) offsets[i] = strlen(string[i]); else offsets[i] = length[i]; /* accumulate string lengths */ if (i > 0) offsets[i] += offsets[i - 1]; } /* Total length of source string is sum off all strings plus two. * One extra byte for terminating zero, another extra byte to silence * valgrind warnings in the parser/grammer code. */ totalLength = offsets[count - 1] + 2; source = (GLcharARB *) malloc(totalLength * sizeof(GLcharARB)); if (source == NULL) { free((GLvoid *) offsets); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB"); return; } for (i = 0; i < count; i++) { GLint start = (i > 0) ? offsets[i - 1] : 0; memcpy(source + start, string[i], (offsets[i] - start) * sizeof(GLcharARB)); } source[totalLength - 1] = '\0'; source[totalLength - 2] = '\0'; if (SHADER_SUBST) { /* Compute the shader's source code checksum then try to open a file * named newshader_<CHECKSUM>. If it exists, use it in place of the * original shader source code. For debugging. */ char filename[100]; GLcharARB *newSource; checksum = _mesa_str_checksum(source); _mesa_snprintf(filename, sizeof(filename), "newshader_%d", checksum); newSource = read_shader(filename); if (newSource) { fprintf(stderr, "Mesa: Replacing shader %u chksum=%d with %s\n", shaderObj, checksum, filename); free(source); source = newSource; } } shader_source(ctx, shaderObj, source); if (SHADER_SUBST) { struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj); if (sh) sh->SourceChecksum = checksum; /* save original checksum */ } free(offsets); }
/*!\fn const WRATHGLShader::shader_source& vertex_shader_source Provided as a conveniance, equivalent to calling shader_source(GLenum) const passing GL_VERTEX_SHADER as the argument */ const WRATHGLShader::shader_source& vertex_shader_source(void) const { return shader_source(GL_VERTEX_SHADER); }