void _mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader) { struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, program); GLuint n; GLuint i, j; if (!shProg) { _mesa_error(ctx, GL_INVALID_VALUE, "glDetachShader(bad program or shader name)"); return; } n = shProg->NumShaders; for (i = 0; i < n; i++) { if (shProg->Shaders[i]->Name == shader) { /* found it */ struct gl_shader **newList; /* derefernce */ _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL); /* alloc new, smaller array */ newList = (struct gl_shader **) _mesa_malloc((n - 1) * sizeof(struct gl_shader *)); if (!newList) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader"); return; } for (j = 0; j < i; j++) { newList[j] = shProg->Shaders[j]; } while (++i < n) newList[j++] = shProg->Shaders[i]; _mesa_free(shProg->Shaders); shProg->Shaders = newList; shProg->NumShaders = n - 1; #ifdef DEBUG /* sanity check */ { for (j = 0; j < shProg->NumShaders; j++) { assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER || shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER); assert(shProg->Shaders[j]->RefCount > 0); } } #endif return; } } /* not found */ _mesa_error(ctx, GL_INVALID_VALUE, "glDetachShader(shader not found)"); }
/** * Free all the data that hangs off a shader program object, but not the * object itself. */ void _mesa_free_shader_program_data(GLcontext *ctx, struct gl_shader_program *shProg) { GLuint i; assert(shProg->Type == GL_SHADER_PROGRAM_MESA); _mesa_clear_shader_program_data(ctx, shProg); if (shProg->Attributes) { _mesa_free_parameter_list(shProg->Attributes); shProg->Attributes = NULL; } /* detach shaders */ for (i = 0; i < shProg->NumShaders; i++) { _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL); } shProg->NumShaders = 0; if (shProg->Shaders) { _mesa_free(shProg->Shaders); shProg->Shaders = NULL; } if (shProg->InfoLog) { _mesa_free(shProg->InfoLog); shProg->InfoLog = NULL; } }
/** * Attach shader to a shader program. */ static void attach_shader(struct gl_context *ctx, GLuint program, GLuint shader) { struct gl_shader_program *shProg; struct gl_shader *sh; GLuint i, n; const bool same_type_disallowed = _mesa_is_gles(ctx); shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader"); if (!shProg) return; sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader"); if (!sh) { return; } n = shProg->NumShaders; for (i = 0; i < n; i++) { if (shProg->Shaders[i] == sh) { /* The shader is already attched to this program. The * GL_ARB_shader_objects spec says: * * "The error INVALID_OPERATION is generated by AttachObjectARB * if <obj> is already attached to <containerObj>." */ _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader"); return; } else if (same_type_disallowed && shProg->Shaders[i]->Type == sh->Type) { /* Shader with the same type is already attached to this program, * OpenGL ES 2.0 and 3.0 specs say: * * "Multiple shader objects of the same type may not be attached * to a single program object. [...] The error INVALID_OPERATION * is generated if [...] another shader object of the same type * as shader is already attached to program." */ _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader"); 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++; }
/** * Free all the data that hangs off a shader program object, but not the * object itself. */ void _mesa_free_shader_program_data(struct gl_context *ctx, struct gl_shader_program *shProg) { GLuint i; gl_shader_stage sh; assert(shProg->Type == GL_SHADER_PROGRAM_MESA); _mesa_clear_shader_program_data(shProg); if (shProg->AttributeBindings) { string_to_uint_map_dtor(shProg->AttributeBindings); shProg->AttributeBindings = NULL; } if (shProg->FragDataBindings) { string_to_uint_map_dtor(shProg->FragDataBindings); shProg->FragDataBindings = NULL; } if (shProg->FragDataIndexBindings) { string_to_uint_map_dtor(shProg->FragDataIndexBindings); shProg->FragDataIndexBindings = NULL; } /* detach shaders */ for (i = 0; i < shProg->NumShaders; i++) { _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL); } shProg->NumShaders = 0; free(shProg->Shaders); shProg->Shaders = NULL; /* Transform feedback varying vars */ for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) { free(shProg->TransformFeedback.VaryingNames[i]); } free(shProg->TransformFeedback.VaryingNames); shProg->TransformFeedback.VaryingNames = NULL; shProg->TransformFeedback.NumVarying = 0; for (sh = 0; sh < MESA_SHADER_STAGES; sh++) { if (shProg->_LinkedShaders[sh] != NULL) { _mesa_delete_shader(ctx, shProg->_LinkedShaders[sh]); shProg->_LinkedShaders[sh] = NULL; } } free(shProg->Label); shProg->Label = NULL; }
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); }
static void delete_shader(struct gl_context *ctx, GLuint shader) { struct gl_shader *sh; sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader"); if (!sh) return; sh->DeletePending = GL_TRUE; /* effectively, decr sh's refcount */ _mesa_reference_shader(ctx, &sh, NULL); }
/** * Attach shader to a shader program. */ static void attach_shader(struct gl_context *ctx, GLuint program, GLuint shader) { struct gl_shader_program *shProg; struct gl_shader *sh; GLuint i, n; shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader"); if (!shProg) return; sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader"); if (!sh) { return; } n = shProg->NumShaders; for (i = 0; i < n; i++) { if (shProg->Shaders[i] == sh) { /* The shader is already attched to this program. The * GL_ARB_shader_objects spec says: * * "The error INVALID_OPERATION is generated by AttachObjectARB * if <obj> is already attached to <containerObj>." */ _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader"); 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++; }
/** * 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 void detach_shader(struct gl_context *ctx, GLuint program, GLuint shader) { struct gl_shader_program *shProg; GLuint n; GLuint i, j; shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader"); if (!shProg) return; n = shProg->NumShaders; for (i = 0; i < n; i++) { if (shProg->Shaders[i]->Name == shader) { /* found it */ struct gl_shader **newList; /* release */ _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL); /* alloc new, smaller array */ newList = (struct gl_shader **) malloc((n - 1) * sizeof(struct gl_shader *)); if (!newList) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader"); return; } for (j = 0; j < i; j++) { newList[j] = shProg->Shaders[j]; } while (++i < n) newList[j++] = shProg->Shaders[i]; free(shProg->Shaders); shProg->Shaders = newList; shProg->NumShaders = n - 1; #ifdef DEBUG /* sanity check */ { for (j = 0; j < shProg->NumShaders; j++) { assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER || shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER); assert(shProg->Shaders[j]->RefCount > 0); } } #endif return; } } /* not found */ { GLenum err; if (is_shader(ctx, shader)) err = GL_INVALID_OPERATION; else if (is_program(ctx, shader)) err = GL_INVALID_OPERATION; else err = GL_INVALID_VALUE; _mesa_error(ctx, err, "glDetachProgram(shader)"); return; } }