#include "texstate.h"
#include "mtypes.h"
#include "program/prog_instruction.h"
+#include "texturebindless.h"
struct gl_texture_object *
_mesa_lookup_texture_err(struct gl_context *ctx, GLuint id, const char* func)
{
- struct gl_texture_object *texObj;
+ struct gl_texture_object *texObj = NULL;
- texObj = _mesa_lookup_texture(ctx, id); /* Returns NULL if not found. */
+ if (id > 0)
+ texObj = _mesa_lookup_texture(ctx, id); /* Returns NULL if not found. */
if (!texObj)
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(texture)", func);
return texObj;
}
-void
-_mesa_begin_texture_lookups(struct gl_context *ctx)
-{
- _mesa_HashLockMutex(ctx->Shared->TexObjects);
-}
-
-
-void
-_mesa_end_texture_lookups(struct gl_context *ctx)
-{
- _mesa_HashUnlockMutex(ctx->Shared->TexObjects);
-}
-
struct gl_texture_object *
_mesa_lookup_texture_locked(struct gl_context *ctx, GLuint id)
* \return pointer to new texture object.
*/
struct gl_texture_object *
-_mesa_new_texture_object( struct gl_context *ctx, GLuint name, GLenum target )
+_mesa_new_texture_object(struct gl_context *ctx, GLuint name, GLenum target)
{
struct gl_texture_object *obj;
- (void) ctx;
+
obj = MALLOC_STRUCT(gl_texture_object);
+ if (!obj)
+ return NULL;
+
_mesa_initialize_texture_object(ctx, obj, name, target);
return obj;
}
obj->DepthMode = ctx->API == API_OPENGL_CORE ? GL_RED : GL_LUMINANCE;
obj->StencilSampling = false;
obj->Sampler.CubeMapSeamless = GL_FALSE;
+ obj->Sampler.HandleAllocated = GL_FALSE;
obj->Swizzle[0] = GL_RED;
obj->Swizzle[1] = GL_GREEN;
obj->Swizzle[2] = GL_BLUE;
obj->BufferObjectFormat = GL_R8;
obj->_BufferObjectFormat = MESA_FORMAT_R_UNORM8;
obj->ImageFormatCompatibilityType = GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE;
+
+ /* GL_ARB_bindless_texture */
+ _mesa_init_texture_handles(obj);
}
*/
static void
finish_texture_init(struct gl_context *ctx, GLenum target,
- struct gl_texture_object *obj)
+ struct gl_texture_object *obj, int targetIndex)
{
GLenum filter = GL_LINEAR;
assert(obj->Target == 0);
obj->Target = target;
- obj->TargetIndex = _mesa_tex_target_to_index(ctx, target);
+ obj->TargetIndex = targetIndex;
assert(obj->TargetIndex < NUM_TEXTURE_TARGETS);
switch (target) {
}
}
+ /* Delete all texture/image handles. */
+ _mesa_delete_texture_handles(ctx, texObj);
+
_mesa_reference_buffer_object(ctx, &texObj->BufferObject, NULL);
/* destroy the mutex -- it may have allocated memory (eg on bsd) */
/* reference new texture */
assert(valid_texture_object(tex));
mtx_lock(&tex->Mutex);
- if (tex->RefCount == 0) {
- /* this texture's being deleted (look just above) */
- /* Not sure this can every really happen. Warn if it does. */
- _mesa_problem(NULL, "referencing deleted texture object");
- *ptr = NULL;
- }
- else {
- tex->RefCount++;
- *ptr = tex;
- }
+ assert(tex->RefCount > 0);
+
+ tex->RefCount++;
+ *ptr = tex;
mtx_unlock(&tex->Mutex);
}
}
{
texObj->_BaseComplete = GL_FALSE;
texObj->_MipmapComplete = GL_FALSE;
- ctx->NewState |= _NEW_TEXTURE;
+ ctx->NewState |= _NEW_TEXTURE_OBJECT;
}
GLuint first;
GLint i;
- if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "%s %d\n", caller, n);
-
- if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", caller);
- return;
- }
-
if (!textures)
return;
texObj = ctx->Driver.NewTextureObject(ctx, name, target);
if (!texObj) {
_mesa_HashUnlockMutex(ctx->Shared->TexObjects);
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "gl%sTextures", caller);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
return;
}
_mesa_HashUnlockMutex(ctx->Shared->TexObjects);
}
+
+static void
+create_textures_err(struct gl_context *ctx, GLenum target,
+ GLsizei n, GLuint *textures, const char *caller)
+{
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "%s %d\n", caller, n);
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", caller);
+ return;
+ }
+
+ create_textures(ctx, target, n, textures, caller);
+}
+
/*@}*/
_mesa_GenTextures(GLsizei n, GLuint *textures)
{
GET_CURRENT_CONTEXT(ctx);
- create_textures(ctx, 0, n, textures, "glGenTextures");
+ create_textures_err(ctx, 0, n, textures, "glGenTextures");
}
/**
return;
}
- create_textures(ctx, target, n, textures, "glCreateTextures");
+ create_textures_err(ctx, target, n, textures, "glCreateTextures");
}
/**
ctx->Driver.BindTexture(ctx, unit, 0, texObj);
texUnit->_BoundTextures &= ~(1 << index);
- ctx->NewState |= _NEW_TEXTURE;
+ ctx->NewState |= _NEW_TEXTURE_OBJECT;
}
}
*/
unbind_texobj_from_image_units(ctx, delObj);
+ /* Make all handles that reference this texture object non-resident
+ * in the current context.
+ */
+ _mesa_make_texture_handles_non_resident(ctx, delObj);
+
_mesa_unlock_texture(ctx, delObj);
- ctx->NewState |= _NEW_TEXTURE;
+ ctx->NewState |= _NEW_TEXTURE_OBJECT;
/* The texture _name_ is now free for re-use.
* Remove it from the hash table now.
}
}
-/**
- * This deletes a texObj without altering the hash table.
- */
-void
-_mesa_delete_nameless_texture(struct gl_context *ctx,
- struct gl_texture_object *texObj)
-{
- if (!texObj)
- return;
-
- FLUSH_VERTICES(ctx, 0);
-
- _mesa_lock_texture(ctx, texObj);
- {
- /* Check if texture is bound to any framebuffer objects.
- * If so, unbind.
- * See section 4.4.2.3 of GL_EXT_framebuffer_object.
- */
- unbind_texobj_from_fbo(ctx, texObj);
-
- /* Check if this texture is currently bound to any texture units.
- * If so, unbind it.
- */
- unbind_texobj_from_texunits(ctx, texObj);
-
- /* Check if this texture is currently bound to any shader
- * image unit. If so, unbind it.
- * See section 3.9.X of GL_ARB_shader_image_load_store.
- */
- unbind_texobj_from_image_units(ctx, texObj);
- }
- _mesa_unlock_texture(ctx, texObj);
-
- ctx->NewState |= _NEW_TEXTURE;
-
- /* Unreference the texobj. If refcount hits zero, the texture
- * will be deleted.
- */
- _mesa_reference_texobj(&texObj, NULL);
-}
-
/**
* Convert a GL texture target enum such as GL_TEXTURE_2D or GL_TEXTURE_3D
assert(targetIndex < NUM_TEXTURE_TARGETS);
/* Check if this texture is only used by this context and is already bound.
- * If so, just return.
+ * If so, just return. For GL_OES_image_external, rebinding the texture
+ * always must invalidate cached resources.
*/
- {
+ if (targetIndex != TEXTURE_EXTERNAL_INDEX) {
bool early_out;
mtx_lock(&ctx->Shared->Mutex);
early_out = ((ctx->Shared->RefCount == 1)
}
/* flush before changing binding */
- FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT);
/* If the refcount on the previously bound texture is decremented to
* zero, it'll be deleted here.
{
GET_CURRENT_CONTEXT(ctx);
struct gl_texture_object *newTexObj = NULL;
- GLint targetIndex;
if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
_mesa_debug(ctx, "glBindTexture %s %d\n",
_mesa_enum_to_string(target), (GLint) texName);
- targetIndex = _mesa_tex_target_to_index(ctx, target);
+ int targetIndex = _mesa_tex_target_to_index(ctx, target);
if (targetIndex < 0) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBindTexture(target)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBindTexture(target = %s)",
+ _mesa_enum_to_string(target));
return;
}
assert(targetIndex < NUM_TEXTURE_TARGETS);
return;
}
if (newTexObj->Target == 0) {
- finish_texture_init(ctx, target, newTexObj);
+ finish_texture_init(ctx, target, newTexObj, targetIndex);
}
}
else {
* If the named texture is not 0 or a recognized texture name, this throws
* GL_INVALID_OPERATION.
*/
-void GLAPIENTRY
-_mesa_BindTextureUnit(GLuint unit, GLuint texture)
+static ALWAYS_INLINE void
+bind_texture_unit(struct gl_context *ctx, GLuint unit, GLuint texture,
+ bool no_error)
{
- GET_CURRENT_CONTEXT(ctx);
struct gl_texture_object *texObj;
- if (unit >= _mesa_max_tex_unit(ctx)) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBindTextureUnit(unit=%u)", unit);
- return;
- }
-
- if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
- _mesa_debug(ctx, "glBindTextureUnit %s %d\n",
- _mesa_enum_to_string(GL_TEXTURE0+unit), (GLint) texture);
-
/* Section 8.1 (Texture Objects) of the OpenGL 4.5 core profile spec
* (20141030) says:
* "When texture is zero, each of the targets enumerated at the
/* Get the non-default texture object */
texObj = _mesa_lookup_texture(ctx, texture);
+ if (!no_error) {
+ /* Error checking */
+ if (!texObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBindTextureUnit(non-gen name)");
+ return;
+ }
- /* Error checking */
- if (!texObj) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBindTextureUnit(non-gen name)");
- return;
- }
- if (texObj->Target == 0) {
- /* Texture object was gen'd but never bound so the target is not set */
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBindTextureUnit(target)");
- return;
+ if (texObj->Target == 0) {
+ /* Texture object was gen'd but never bound so the target is not set */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBindTextureUnit(target)");
+ return;
+ }
}
+
assert(valid_texture_object(texObj));
bind_texture(ctx, unit, texObj);
}
+void GLAPIENTRY
+_mesa_BindTextureUnit_no_error(GLuint unit, GLuint texture)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ bind_texture_unit(ctx, unit, texture, true);
+}
+
+
+void GLAPIENTRY
+_mesa_BindTextureUnit(GLuint unit, GLuint texture)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (unit >= _mesa_max_tex_unit(ctx)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glBindTextureUnit(unit=%u)", unit);
+ return;
+ }
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glBindTextureUnit %s %d\n",
+ _mesa_enum_to_string(GL_TEXTURE0+unit), (GLint) texture);
+
+ bind_texture_unit(ctx, unit, texture, false);
+}
+
+
/**
* OpenGL 4.4 / GL_ARB_multi_bind glBindTextures().
*/
* their parameters are valid and no other error occurs."
*/
- _mesa_begin_texture_lookups(ctx);
+ _mesa_HashLockMutex(ctx->Shared->TexObjects);
for (i = 0; i < count; i++) {
if (textures[i] != 0) {
}
}
- _mesa_end_texture_lookups(ctx);
+ _mesa_HashUnlockMutex(ctx->Shared->TexObjects);
} else {
/* Unbind all textures in the range <first> through <first>+<count>-1 */
for (i = 0; i < count; i++)
}
}
- ctx->NewState |= _NEW_TEXTURE;
+ ctx->NewState |= _NEW_TEXTURE_OBJECT;
}
mtx_lock(&ctx->Shared->TexMutex);
if (ctx->Shared->TextureStateStamp != ctx->TextureStateTimestamp) {
- ctx->NewState |= _NEW_TEXTURE;
+ ctx->NewState |= _NEW_TEXTURE_OBJECT;
ctx->TextureStateTimestamp = ctx->Shared->TextureStateStamp;
}
}