void _mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params) { struct gl_shader *shader = _mesa_lookup_shader(ctx, name); if (!shader) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)"); return; } switch (pname) { case GL_SHADER_TYPE: *params = shader->Type; break; case GL_DELETE_STATUS: *params = shader->DeletePending; break; case GL_COMPILE_STATUS: *params = shader->CompileStatus; break; case GL_INFO_LOG_LENGTH: *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0; break; case GL_SHADER_SOURCE_LENGTH: *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)"); return; } }
static void PrintShaderInstructions(GLuint shader, FILE *f) { GET_CURRENT_CONTEXT(ctx); struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); struct gl_program *prog = sh->Program; _mesa_fprint_program_opt(stdout, prog, Options.Mode, Options.LineNumbers); if (Options.Params) _mesa_print_program_parameters(ctx, prog); }
static void get_shader_info_log(struct gl_context *ctx, GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) { struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); if (!sh) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)"); return; } _mesa_copy_string(infoLog, bufSize, length, sh->InfoLog); }
/** * Called via ctx->Driver.CompileShader() */ void _mesa_compile_shader(GLcontext *ctx, GLuint shaderObj) { struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj); if (!sh) { _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)"); return; } sh->CompileStatus = _slang_compile(ctx, sh); }
void _mesa_delete_shader(GLcontext *ctx, GLuint shader) { struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); if (!sh) { return; } sh->DeletePending = GL_TRUE; /* effectively, decr sh's refcount */ _mesa_reference_shader(ctx, &sh, NULL); }
/** * Called via ctx->Driver.GetShaderSource(). */ void _mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *sourceOut) { struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); if (!sh) { GLenum err; if (_mesa_lookup_shader_program(ctx, shader)) err = GL_INVALID_OPERATION; else err = GL_INVALID_VALUE; _mesa_error(ctx, err, "glGetShaderSource(shader)"); return; } copy_string(sourceOut, maxLength, length, sh->Source); }
/** * 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; }
/** * Called via ctx->Driver.ShaderSource() */ void _mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source) { struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); if (!sh) { GLenum err; if (_mesa_lookup_shader_program(ctx, shader)) err = GL_INVALID_OPERATION; else err = GL_INVALID_VALUE; _mesa_error(ctx, err, "glShaderSource(shaderObj)"); return; } /* free old shader source string and install new one */ if (sh->Source) { _mesa_free((void *) sh->Source); } sh->Source = source; sh->CompileStatus = GL_FALSE; }
/** * Called via ctx->Driver.AttachShader() */ void _mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader) { struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, program); struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); GLuint n; GLuint i; if (!shProg || !sh) { _mesa_error(ctx, GL_INVALID_VALUE, "glAttachShader(bad program or shader name)"); return; } n = shProg->NumShaders; for (i = 0; i < n; i++) { if (shProg->Shaders[i] == sh) { /* already attached */ return; } } /* grow list */ shProg->Shaders = (struct gl_shader **) _mesa_realloc(shProg->Shaders, n * sizeof(struct gl_shader *), (n + 1) * sizeof(struct gl_shader *)); if (!shProg->Shaders) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader"); return; } /* append */ shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */ _mesa_reference_shader(ctx, &shProg->Shaders[n], sh); shProg->NumShaders++; }
static GLboolean is_shader(struct gl_context *ctx, GLuint name) { struct gl_shader *shader = _mesa_lookup_shader(ctx, name); return shader ? GL_TRUE : GL_FALSE; }
/** * 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); }