+
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = hash_table_search(ctx->Shared->ImageHandles, id);
+ hash_table_remove(ctx->Shared->ImageHandles, entry);
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+
+ ctx->Driver.DeleteImageHandle(ctx, id);
+}
+
+/**
+ * Return TRUE if the texture handle is resident in the current context.
+ */
+static inline bool
+is_texture_handle_resident(struct gl_context *ctx, GLuint64 handle)
+{
+ return hash_table_search(ctx->ResidentTextureHandles, handle) !=
NULL;
+}
+
+/**
+ * Return TRUE if the image handle is resident in the current context.
+ */
+static inline bool
+is_image_handle_resident(struct gl_context *ctx, GLuint64 handle)
+{
+ return hash_table_search(ctx->ResidentImageHandles, handle) != NULL;
+}
+
+/**
+ * Make a texture handle resident/non-resident in the current context.
+ */
+static void
+make_texture_handle_resident(struct gl_context *ctx,
+ struct gl_texture_handle_object
*texHandleObj,
+ bool resident)
+{
+ GLuint64 handle = texHandleObj->handle;
+
+ if (resident) {
+ struct gl_sampler_object *sampObj = NULL;
+ struct gl_texture_object *texObj = NULL;
+
+ hash_table_insert(ctx->ResidentTextureHandles, handle,
texHandleObj);
+
+ ctx->Driver.MakeTextureHandleResident(ctx, handle, GL_TRUE);
+
+ /* Reference the texture object (and the separate sampler if
needed) to
+ * be sure it won't be deleted until it is not bound anywhere
and there
+ * are no handles using the object that are resident in any
context.
+ */
+ _mesa_reference_texobj(&texObj, texHandleObj->texObj);
+ if (texHandleObj->sampObj)
+ _mesa_reference_sampler_object(ctx, &sampObj,
texHandleObj->sampObj);
+ } else {
+ struct hash_entry *entry;
+
+ entry = hash_table_search(ctx->ResidentTextureHandles, handle);
+ hash_table_remove(ctx->ResidentTextureHandles, entry);
+
+ ctx->Driver.MakeTextureHandleResident(ctx, handle, GL_FALSE);
+
+ /* Unreference the texture object (and the separate sampler if
needed),
+ * if refcount hits zero, the texture and all handles will be
deleted.
+ */
+ _mesa_reference_texobj(&texHandleObj->texObj, NULL);
+ if (texHandleObj->sampObj)
+ _mesa_reference_sampler_object(ctx, &texHandleObj->sampObj,
NULL);
+ }
+}
+
+/**
+ * Make an image handle resident/non-resident in the current context.
+ */
+static void
+make_image_handle_resident(struct gl_context *ctx,
+ struct gl_image_handle_object *imgHandleObj,
+ GLenum access, bool resident)
+{
+ GLuint64 handle = imgHandleObj->handle;
+
+ if (resident) {
+ struct gl_texture_object *texObj = NULL;
+
+ hash_table_insert(ctx->ResidentImageHandles, handle,
imgHandleObj);
+
+ ctx->Driver.MakeImageHandleResident(ctx, handle, access, GL_TRUE);
+
+ /* Reference the texture object to be sure it won't be deleted
until it
+ * is not bound anywhere and there are no handles using the
object that
+ * are resident in any context.
+ */
+ _mesa_reference_texobj(&texObj, imgHandleObj->imgObj.TexObj);
+ } else {
+ struct hash_entry *entry;
+
+ entry = hash_table_search(ctx->ResidentImageHandles, handle);
+ hash_table_remove(ctx->ResidentImageHandles, entry);
+
+ ctx->Driver.MakeImageHandleResident(ctx, handle, access,
GL_FALSE);
+
+ /* Unreference the texture object, if refcount hits zero, the
texture and
+ * all handles will be deleted.
+ */
+ _mesa_reference_texobj(&imgHandleObj->imgObj.TexObj, NULL);
+ }
+}
+
+static struct gl_texture_handle_object *
+find_texhandleobj(struct gl_texture_object *texObj,
+ struct gl_sampler_object *sampObj)
+{
+ struct gl_texture_handle_object *texHandleObj;
+
+ u_vector_foreach(texHandleObj, &texObj->SamplerHandles) {
+ if (texHandleObj->sampObj == sampObj)
+ return texHandleObj;
+ }
+ return NULL;
+}
+
+static GLuint64
+get_texture_handle(struct gl_context *ctx, struct gl_texture_object
*texObj,
+ struct gl_sampler_object *sampObj)
+{
+ bool separate_sampler = &texObj->Sampler != sampObj;
+ struct gl_texture_handle_object *texHandleObj;
+ GLuint64 handle;
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The handle for each texture or texture/sampler pair is unique;
the same
+ * handle will be returned if GetTextureHandleARB is called
multiple times
+ * for the same texture or if GetTextureSamplerHandleARB is
called multiple
+ * times for the same texture/sampler pair."
+ */
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ texHandleObj = find_texhandleobj(texObj, separate_sampler ?
sampObj : NULL);
+ if (texHandleObj) {
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+ return texHandleObj->handle;
+ }
+
+ /* Request a new texture handle from the driver. */
+ handle = ctx->Driver.NewTextureHandle(ctx, texObj, sampObj);
+ if (!handle) {
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexture*HandleARB()");
+ return 0;
+ }
+
+ /* Store the handle into the texture object. */
+ texHandleObj = u_vector_add(&texObj->SamplerHandles);
+ texHandleObj->texObj = texObj;
+ texHandleObj->sampObj = separate_sampler ? sampObj : NULL;
+ texHandleObj->handle = handle;
+
+ if (&texObj->Sampler != sampObj) {
+ /* Store a reference to the handle into the separate sampler
object. */
+ struct gl_texture_handle_object **sampHandleObj;
+
+ sampHandleObj = u_vector_add(&sampObj->Handles);
+ *sampHandleObj = texHandleObj;
+ }
+
+ /* When referenced by one or more handles, texture objects are
immutable. */
+ texObj->HandleAllocated = true;
+ if (texObj->Target == GL_TEXTURE_BUFFER)
+ texObj->BufferObject->HandleAllocated = true;
+ sampObj->HandleAllocated = true;
+
+ /* Store the handle in the shared state for all contexts. */
+ hash_table_insert(ctx->Shared->TextureHandles, handle, texHandleObj);
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+
+ return (GLuint64)handle;
+}
+
+static struct gl_image_handle_object *
+find_imghandleobj(struct gl_texture_object *texObj, GLint level,
+ GLboolean layered, GLint layer, GLenum format)
+{
+ struct gl_image_handle_object *imgHandleObj;
+
+ u_vector_foreach(imgHandleObj, &texObj->ImageHandles) {
+ struct gl_image_unit *u = &imgHandleObj->imgObj;
+
+ if (u->Level == level && u->Layered == layered &&
+ u->Layer == layer && u->Format == format)
+ return imgHandleObj;
+ }
+ return NULL;
+}
+
+static GLuint64
+get_image_handle(struct gl_context *ctx, struct gl_texture_object
*texObj,
+ GLint level, GLboolean layered, GLint layer, GLenum
format)
+{
+ struct gl_image_handle_object *imgHandleObj;
+ struct gl_image_unit imgObj;
+ GLuint64 handle;
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The handle returned for each combination of <texture>, <level>,
+ * <layered>, <layer>, and <format> is unique; the same handle
will be
+ * returned if GetImageHandleARB is called multiple times with the
same
+ * parameters."
+ */
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ imgHandleObj = find_imghandleobj(texObj, level, layered, layer,
format);
+ if (imgHandleObj) {
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+ return imgHandleObj->handle;
+ }
+
+ imgObj.TexObj = texObj; /* weak reference */
+ imgObj.Level = level;
+ imgObj.Access = GL_READ_WRITE;
+ imgObj.Format = format;
+ imgObj._ActualFormat = _mesa_get_shader_image_format(format);
+
+ if (_mesa_tex_target_is_layered(texObj->Target)) {
+ imgObj.Layered = layered;
+ imgObj.Layer = layer;
+ imgObj._Layer = (imgObj.Layered ? 0 : imgObj.Layer);
+ } else {
+ imgObj.Layered = GL_FALSE;
+ imgObj.Layer = 0;
+ }
+
+ /* Request a new image handle from the driver. */
+ handle = ctx->Driver.NewImageHandle(ctx, &imgObj);
+ if (!handle) {
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetImageHandleARB()");
+ return 0;
+ }
+
+ /* Store the handle into the texture object. */
+ imgHandleObj = u_vector_add(&texObj->ImageHandles);
+ memcpy(&imgHandleObj->imgObj, &imgObj, sizeof(struct gl_image_unit));
+ imgHandleObj->handle = handle;
+
+ /* When referenced by one or more handles, texture objects are
immutable. */
+ texObj->HandleAllocated = true;
+ if (texObj->Target == GL_TEXTURE_BUFFER)
+ texObj->BufferObject->HandleAllocated = true;
+ texObj->Sampler.HandleAllocated = true;
+
+ /* Store the handle in the shared state for all contexts. */
+ hash_table_insert(ctx->Shared->ImageHandles, handle, imgHandleObj);
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+
+ return (GLuint64)handle;
+}
+
+/**
+ * Init/free resident handles per-context.
+ */
+void
+_mesa_init_resident_handles(struct gl_context *ctx)
+{
+#if !defined(MESA_ARCH_X86_64)
+ ctx->ResidentTextureHandles =
+ _mesa_hash_table_create(NULL, key_hash, key_equals);
+ ctx->ResidentImageHandles =
+ _mesa_hash_table_create(NULL, key_hash, key_equals);
+#else
+ ctx->ResidentTextureHandles =
+ _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+ ctx->ResidentImageHandles =
+ _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+#endif
+}
+
+void
+_mesa_free_resident_handles(struct gl_context *ctx)
+{
+ _mesa_hash_table_destroy(ctx->ResidentTextureHandles, NULL);
+ _mesa_hash_table_destroy(ctx->ResidentImageHandles, NULL);
+}
+
+/**
+ * Init/free shared handles.
+ */
+void
+_mesa_init_shared_handles(struct gl_shared_state *shared)
+{
+#if !defined(MESA_ARCH_X86_64)
+ shared->TextureHandles =
+ _mesa_hash_table_create(NULL, key_hash, key_equals);
+ shared->ImageHandles =
+ _mesa_hash_table_create(NULL, key_hash, key_equals);
+#else
+ shared->TextureHandles =
+ _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+ shared->ImageHandles =
+ _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+#endif
+ mtx_init(&shared->HandlesMutex, mtx_recursive);
+}
+
+void
+_mesa_free_shared_handles(struct gl_shared_state *shared)
+{
+ _mesa_hash_table_destroy(shared->TextureHandles, NULL);
+ _mesa_hash_table_destroy(shared->ImageHandles, NULL);
+ mtx_destroy(&shared->HandlesMutex);
+}
+
+/**
+ * Init/free texture/image handles per-texture object.
+ */
+void
+_mesa_init_texture_handles(struct gl_texture_object *texObj)
+{
+ uint32_t element_size;
+
+ element_size =
+ util_next_power_of_two(sizeof(struct gl_texture_handle_object));
+ u_vector_init(&texObj->SamplerHandles, element_size, 2 *
element_size);
+
+ element_size =
+ util_next_power_of_two(sizeof(struct gl_image_handle_object));
+ u_vector_init(&texObj->ImageHandles, element_size, 2 * element_size);
+}
+
+void
+_mesa_make_texture_handles_non_resident(struct gl_context *ctx,
+ struct gl_texture_object
*texObj)
+{
+ struct gl_texture_handle_object *texHandleObj;
+ struct gl_image_handle_object *imgHandleObj;
+
+ mtx_lock(&ctx->Shared->HandlesMutex);
+
+ u_vector_foreach(texHandleObj, &texObj->SamplerHandles) {
+ if (is_texture_handle_resident(ctx, texHandleObj->handle))
+ make_texture_handle_resident(ctx, texHandleObj, false);
+ }
+
+ u_vector_foreach(imgHandleObj, &texObj->ImageHandles) {
+ if (is_image_handle_resident(ctx, imgHandleObj->handle))
+ make_image_handle_resident(ctx, imgHandleObj, GL_READ_ONLY,
false);
+ }
+
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+}
+
+void
+_mesa_delete_texture_handles(struct gl_context *ctx,
+ struct gl_texture_object *texObj)
+{
+ struct gl_texture_handle_object *texHandleObj;
+ struct gl_image_handle_object *imgHandleObj;
+
+ /* Texture handles */
+ u_vector_foreach(texHandleObj, &texObj->SamplerHandles)
+ delete_texture_handle(ctx, texHandleObj->handle);
+ u_vector_finish(&texObj->SamplerHandles);
+
+ /* Image handles */
+ u_vector_foreach(imgHandleObj, &texObj->ImageHandles)
+ delete_image_handle(ctx, imgHandleObj->handle);
+ u_vector_finish(&texObj->ImageHandles);
+}
+
+/**
+ * Init/free texture handles per-sampler object.
+ */
+void
+_mesa_init_sampler_handles(struct gl_sampler_object *sampObj)
+{
+ uint32_t element_size;
+
+ element_size =
+ util_next_power_of_two(sizeof(struct gl_texture_handle_object));
+ u_vector_init(&sampObj->Handles, element_size, 2 * element_size);
+}
+
+void
+_mesa_delete_sampler_handles(struct gl_context *ctx,
+ struct gl_sampler_object *sampObj)
+{
+ struct gl_texture_handle_object **sampHandleObj;
+
+ u_vector_foreach(sampHandleObj, &sampObj->Handles)
+ delete_texture_handle(ctx, (*sampHandleObj)->handle);
+ u_vector_finish(&sampObj->Handles);
+}
+
+static GLboolean
+is_sampler_border_color_valid(struct gl_sampler_object *samp)
+{
+ static const GLfloat valid_float_border_colors[4][4] = {
+ { 0.0, 0.0, 0.0, 0.0 },
+ { 0.0, 0.0, 0.0, 1.0 },
+ { 1.0, 1.0, 1.0, 0.0 },
+ { 1.0, 1.0, 1.0, 1.0 },
+ };
+ static const GLint valid_integer_border_colors[4][4] = {
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 1 },
+ { 1, 1, 1, 0 },
+ { 1, 1, 1, 1 },
+ };
+ size_t size = sizeof(samp->BorderColor.ui);
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated if the border color
(taken from
+ * the embedded sampler for GetTextureHandleARB or from the
<sampler> for
+ * GetTextureSamplerHandleARB) is not one of the following
allowed values.
+ * If the texture's base internal format is signed or unsigned
integer,
+ * allowed values are (0,0,0,0), (0,0,0,1), (1,1,1,0), and
(1,1,1,1). If
+ * the base internal format is not integer, allowed values are
+ * (0.0,0.0,0.0,0.0), (0.0,0.0,0.0,1.0), (1.0,1.0,1.0,0.0), and
+ * (1.0,1.0,1.0,1.0)."
+ */
+ if (!memcmp(samp->BorderColor.f, valid_float_border_colors[0],
size) ||
+ !memcmp(samp->BorderColor.f, valid_float_border_colors[1],
size) ||
+ !memcmp(samp->BorderColor.f, valid_float_border_colors[2],
size) ||
+ !memcmp(samp->BorderColor.f, valid_float_border_colors[3], size))
+ return GL_TRUE;
+
+ if (!memcmp(samp->BorderColor.ui, valid_integer_border_colors[0],
size) ||
+ !memcmp(samp->BorderColor.ui, valid_integer_border_colors[1],
size) ||
+ !memcmp(samp->BorderColor.ui, valid_integer_border_colors[2],
size) ||
+ !memcmp(samp->BorderColor.ui, valid_integer_border_colors[3],
size))
+ return GL_TRUE;
+
+ return GL_FALSE;
+}
+
GLuint64 GLAPIENTRY
_mesa_GetTextureHandleARB(GLuint texture)
{
- return 0;
+ struct gl_texture_object *texObj = NULL;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureHandleARB(unsupported)");
+ return 0;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_VALUE is generated by GetTextureHandleARB or
+ * GetTextureSamplerHandleARB if <texture> is zero or not the
name of an
+ * existing texture object."
+ */
+ if (texture > 0)
+ texObj = _mesa_lookup_texture(ctx, texture);
+
+ if (!texObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
"glGetTextureHandleARB(texture)");
+ return 0;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated by
GetTextureHandleARB or
+ * GetTextureSamplerHandleARB if the texture object specified by
<texture>
+ * is not complete."
+ */
+ if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureHandleARB(incomplete texture)");
+ return 0;
+ }
+ }
+
+ if (!is_sampler_border_color_valid(&texObj->Sampler)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureHandleARB(invalid border color)");
+ return 0;
+ }
+
+ return get_texture_handle(ctx, texObj, &texObj->Sampler);
}
GLuint64 GLAPIENTRY
_mesa_GetTextureSamplerHandleARB(GLuint texture, GLuint sampler)
{
- return 0;
+ struct gl_texture_object *texObj = NULL;
+ struct gl_sampler_object *sampObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureSamplerHandleARB(unsupported)");
+ return 0;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_VALUE is generated by GetTextureHandleARB or
+ * GetTextureSamplerHandleARB if <texture> is zero or not the
name of an
+ * existing texture object."
+ */
+ if (texture > 0)
+ texObj = _mesa_lookup_texture(ctx, texture);
+
+ if (!texObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetTextureSamplerHandleARB(texture)");
+ return 0;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_VALUE is generated by
GetTextureSamplerHandleARB if
+ * <sampler> is zero or is not the name of an existing sampler
object."
+ */
+ sampObj = _mesa_lookup_samplerobj(ctx, sampler);
+ if (!sampObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetTextureSamplerHandleARB(sampler)");
+ return 0;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated by
GetTextureHandleARB or
+ * GetTextureSamplerHandleARB if the texture object specified by
<texture>
+ * is not complete."
+ */
+ if (!_mesa_is_texture_complete(texObj, sampObj)) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ if (!_mesa_is_texture_complete(texObj, sampObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureSamplerHandleARB(incomplete
texture)");
+ return 0;
+ }
+ }
+
+ if (!is_sampler_border_color_valid(sampObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureSamplerHandleARB(invalid border color)");
+ return 0;
+ }
+
+ return get_texture_handle(ctx, texObj, sampObj);
}
void GLAPIENTRY
_mesa_MakeTextureHandleResidentARB(GLuint64 handle)
{
+ struct gl_texture_handle_object *texHandleObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleResidentARB(unsupported)");
+ return;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated by
MakeTextureHandleResidentARB
+ * if <handle> is not a valid texture handle, or if <handle> is
already
+ * resident in the current GL context."
+ */
+ texHandleObj = lookup_texture_handle(ctx, handle);
+ if (!texHandleObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleResidentARB(handle)");
+ return;
+ }
+
+ if (is_texture_handle_resident(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleResidentARB(already resident)");
+ return;
+ }
+
+ make_texture_handle_resident(ctx, texHandleObj, true);
}
void GLAPIENTRY
_mesa_MakeTextureHandleNonResidentARB(GLuint64 handle)
{
+ struct gl_texture_handle_object *texHandleObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleNonResidentARB(unsupported)");
+ return;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated by
+ * MakeTextureHandleNonResidentARB if <handle> is not a valid
texture
+ * handle, or if <handle> is not resident in the current GL
context."
+ */
+ texHandleObj = lookup_texture_handle(ctx, handle);
+ if (!texHandleObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleNonResidentARB(handle)");
+ return;
+ }
+
+ if (!is_texture_handle_resident(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleNonResidentARB(not resident)");
+ return;
+ }
+
+ make_texture_handle_resident(ctx, texHandleObj, false);
}
GLuint64 GLAPIENTRY
_mesa_GetImageHandleARB(GLuint texture, GLint level, GLboolean layered,
GLint layer, GLenum format)
{
- return 0;
+ struct gl_texture_object *texObj = NULL;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx) ||
+ !_mesa_has_ARB_shader_image_load_store(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetImageHandleARB(unsupported)");
+ return 0;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_VALUE is generated by GetImageHandleARB if
<texture>
+ * is zero or not the name of an existing texture object, if the
image for
+ * <level> does not existing in <texture>, or if <layered> is
FALSE and
+ * <layer> is greater than or equal to the number of layers in
the image at
+ * <level>."
+ */
+ if (texture > 0)
+ texObj = _mesa_lookup_texture(ctx, texture);
+
+ if (!texObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
"glGetImageHandleARB(texture)");
+ return 0;
+ }
+
+ if (level < 0 || level >= _mesa_max_texture_levels(ctx,
texObj->Target)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(level)");
+ return 0;
+ }
+
+ if (!layered && layer > _mesa_get_texture_layers(texObj, level)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(layer)");
+ return 0;
+ }
+
+ if (!_mesa_is_shader_image_format_supported(ctx, format)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(format)");
+ return 0;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated by GetImageHandleARB
if the
+ * texture object <texture> is not complete or if <layered> is
TRUE and
+ * <texture> is not a three-dimensional, one-dimensional array, two
+ * dimensional array, cube map, or cube map array texture."
+ */
+ if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetImageHandleARB(incomplete texture)");
+ return 0;
+ }
+ }
+
+ if (layered && !_mesa_tex_target_is_layered(texObj->Target)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetImageHandleARB(not layered)");
+ return 0;
+ }
+
+ return get_image_handle(ctx, texObj, level, layered, layer, format);
}
void GLAPIENTRY
_mesa_MakeImageHandleResidentARB(GLuint64 handle, GLenum access)
{
+ struct gl_image_handle_object *imgHandleObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx) ||
+ !_mesa_has_ARB_shader_image_load_store(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleResidentARB(unsupported)");
+ return;
+ }
+
+ if (access != GL_READ_ONLY &&
+ access != GL_WRITE_ONLY &&
+ access != GL_READ_WRITE) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glMakeImageHandleResidentARB(access)");
+ return;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated by
MakeImageHandleResidentARB
+ * if <handle> is not a valid image handle, or if <handle> is
already
+ * resident in the current GL context."
+ */
+ imgHandleObj = lookup_image_handle(ctx, handle);
+ if (!imgHandleObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleResidentARB(handle)");
+ return;
+ }
+
+ if (is_image_handle_resident(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleResidentARB(already resident)");
+ return;
+ }
+
+ make_image_handle_resident(ctx, imgHandleObj, access, true);
}
void GLAPIENTRY
_mesa_MakeImageHandleNonResidentARB(GLuint64 handle)
{
+ struct gl_image_handle_object *imgHandleObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx) ||
+ !_mesa_has_ARB_shader_image_load_store(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleNonResidentARB(unsupported)");
+ return;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated by
+ * MakeImageHandleNonResidentARB if <handle> is not a valid image
handle,
+ * or if <handle> is not resident in the current GL context."
+ */
+ imgHandleObj = lookup_image_handle(ctx, handle);
+ if (!imgHandleObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleNonResidentARB(handle)");
+ return;
+ }
+
+ if (!is_image_handle_resident(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleNonResidentARB(not resident)");
+ return;
+ }
+
+ make_image_handle_resident(ctx, imgHandleObj, GL_READ_ONLY, false);
}
GLboolean GLAPIENTRY
_mesa_IsTextureHandleResidentARB(GLuint64 handle)
{
- return GL_FALSE;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glIsTextureHandleResidentARB(unsupported)");
+ return GL_FALSE;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION will be generated by
+ * IsTextureHandleResidentARB and IsImageHandleResidentARB if
<handle> is
+ * not a valid texture or image handle, respectively."
+ */
+ if (!lookup_texture_handle(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glIsTextureHandleResidentARB(handle)");
+ return GL_FALSE;
+ }
+
+ return is_texture_handle_resident(ctx, handle);
}
GLboolean GLAPIENTRY
_mesa_IsImageHandleResidentARB(GLuint64 handle)
{
- return GL_FALSE;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx) ||
+ !_mesa_has_ARB_shader_image_load_store(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glIsImageHandleResidentARB(unsupported)");
+ return GL_FALSE;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION will be generated by
+ * IsTextureHandleResidentARB and IsImageHandleResidentARB if
<handle> is
+ * not a valid texture or image handle, respectively."
+ */
+ if (!lookup_image_handle(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glIsImageHandleResidentARB(handle)");
+ return GL_FALSE;
+ }
+
+ return is_image_handle_resident(ctx, handle);
}
diff --git a/src/mesa/main/texturebindless.h
b/src/mesa/main/texturebindless.h
index 88b84ce275..d584f5cc0c 100644
--- a/src/mesa/main/texturebindless.h
+++ b/src/mesa/main/texturebindless.h
@@ -31,6 +31,38 @@ extern "C" {
#endif
/**
+ * \name Internal functions
+ */
+/*@{*/
+
+void
+_mesa_init_resident_handles(struct gl_context *ctx);
+void
+_mesa_free_resident_handles(struct gl_context *ctx);
+
+void
+_mesa_init_shared_handles(struct gl_shared_state *shared);
+void
+_mesa_free_shared_handles(struct gl_shared_state *shared);
+
+void
+_mesa_init_texture_handles(struct gl_texture_object *texObj);
+void
+_mesa_make_texture_handles_non_resident(struct gl_context *ctx,
+ struct gl_texture_object
*texObj);
+void
+_mesa_delete_texture_handles(struct gl_context *ctx,
+ struct gl_texture_object *texObj);
+
+void
+_mesa_init_sampler_handles(struct gl_sampler_object *sampObj);
+void
+_mesa_delete_sampler_handles(struct gl_context *ctx,
+ struct gl_sampler_object *sampObj);
+
+/*@}*/
+
+/**
* \name API functions
*/
/*@{*/