static void delete_samplers(struct gl_context *ctx, GLsizei count, const GLuint *samplers) { FLUSH_VERTICES(ctx, 0); _mesa_HashLockMutex(ctx->Shared->SamplerObjects); for (GLsizei i = 0; i < count; i++) { if (samplers[i]) { GLuint j; struct gl_sampler_object *sampObj = lookup_samplerobj_locked(ctx, samplers[i]); if (sampObj) { /* If the sampler is currently bound, unbind it. */ for (j = 0; j < ctx->Const.MaxCombinedTextureImageUnits; j++) { if (ctx->Texture.Unit[j].Sampler == sampObj) { FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT); _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[j].Sampler, NULL); } } /* The ID is immediately freed for re-use */ _mesa_HashRemoveLocked(ctx->Shared->SamplerObjects, samplers[i]); /* But the object exists until its reference count goes to zero */ _mesa_reference_sampler_object(ctx, &sampObj, NULL); } } } _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects); }
static void create_samplers(struct gl_context *ctx, GLsizei count, GLuint *samplers, const char *caller) { GLuint first; GLint i; if (!samplers) return; _mesa_HashLockMutex(ctx->Shared->SamplerObjects); first = _mesa_HashFindFreeKeyBlock(ctx->Shared->SamplerObjects, count); /* Insert the ID and pointer to new sampler object into hash table */ for (i = 0; i < count; i++) { struct gl_sampler_object *sampObj; GLuint name = first + i; sampObj = ctx->Driver.NewSamplerObject(ctx, name); if (!sampObj) { _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects); _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); return; } _mesa_HashInsertLocked(ctx->Shared->SamplerObjects, name, sampObj); samplers[i] = name; } _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects); }
/** * Generate a list of new program identifiers. * \note Not compiled into display lists. * \note Called by both glGenProgramsNV and glGenProgramsARB. */ void GLAPIENTRY _mesa_GenProgramsARB(GLsizei n, GLuint *ids) { GLuint first; GLuint i; GET_CURRENT_CONTEXT(ctx); if (n < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glGenPrograms"); return; } if (!ids) return; _mesa_HashLockMutex(ctx->Shared->Programs); first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n); /* Insert pointer to dummy program as placeholder */ for (i = 0; i < (GLuint) n; i++) { _mesa_HashInsertLocked(ctx->Shared->Programs, first + i, &_mesa_DummyProgram); } _mesa_HashUnlockMutex(ctx->Shared->Programs); /* Return the program names */ for (i = 0; i < (GLuint) n; i++) { ids[i] = first + i; } }
static ALWAYS_INLINE void bind_samplers(struct gl_context *ctx, GLuint first, GLsizei count, const GLuint *samplers, bool no_error) { GLsizei i; FLUSH_VERTICES(ctx, 0); if (samplers) { /* Note that the error semantics for multi-bind commands differ from * those of other GL commands. * * The Issues section in the ARB_multi_bind spec says: * * "(11) Typically, OpenGL specifies that if an error is generated by * a command, that command has no effect. This is somewhat * unfortunate for multi-bind commands, because it would require * a first pass to scan the entire list of bound objects for * errors and then a second pass to actually perform the * bindings. Should we have different error semantics? * * RESOLVED: Yes. In this specification, when the parameters for * one of the <count> binding points are invalid, that binding * point is not updated and an error will be generated. However, * other binding points in the same command will be updated if * their parameters are valid and no other error occurs." */ _mesa_HashLockMutex(ctx->Shared->SamplerObjects); for (i = 0; i < count; i++) { const GLuint unit = first + i; struct gl_sampler_object * const currentSampler = ctx->Texture.Unit[unit].Sampler; struct gl_sampler_object *sampObj; if (samplers[i] != 0) { if (currentSampler && currentSampler->Name == samplers[i]) sampObj = currentSampler; else sampObj = lookup_samplerobj_locked(ctx, samplers[i]); /* The ARB_multi_bind spec says: * * "An INVALID_OPERATION error is generated if any value * in <samplers> is not zero or the name of an existing * sampler object (per binding)." */ if (!no_error && !sampObj) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBindSamplers(samplers[%d]=%u is not zero or " "the name of an existing sampler object)", i, samplers[i]); continue; } } else { sampObj = NULL; } /* Bind the new sampler */ if (sampObj != currentSampler) { _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[unit].Sampler, sampObj); ctx->NewState |= _NEW_TEXTURE_OBJECT; } } _mesa_HashUnlockMutex(ctx->Shared->SamplerObjects); } else { /* Unbind all samplers in the range <first> through <first>+<count>-1 */ for (i = 0; i < count; i++) { const GLuint unit = first + i; if (ctx->Texture.Unit[unit].Sampler) { _mesa_reference_sampler_object(ctx, &ctx->Texture.Unit[unit].Sampler, NULL); ctx->NewState |= _NEW_TEXTURE_OBJECT; } } } }
static inline void begin_samplerobj_lookups(struct gl_context *ctx) { _mesa_HashLockMutex(ctx->Shared->SamplerObjects); }