texturebindless.c revision 01e04c3f
101e04c3fSmrg/*
201e04c3fSmrg * Copyright © 2017 Valve Corporation.
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the next
1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg * Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2101e04c3fSmrg * DEALINGS IN THE SOFTWARE.
2201e04c3fSmrg */
2301e04c3fSmrg
2401e04c3fSmrg#include "glheader.h"
2501e04c3fSmrg#include "context.h"
2601e04c3fSmrg#include "enums.h"
2701e04c3fSmrg#include "imports.h"
2801e04c3fSmrg#include "hash.h"
2901e04c3fSmrg#include "mtypes.h"
3001e04c3fSmrg#include "shaderimage.h"
3101e04c3fSmrg#include "teximage.h"
3201e04c3fSmrg#include "texobj.h"
3301e04c3fSmrg#include "texturebindless.h"
3401e04c3fSmrg
3501e04c3fSmrg#include "util/hash_table.h"
3601e04c3fSmrg
3701e04c3fSmrg/**
3801e04c3fSmrg * Return the gl_texture_handle_object for a given 64-bit handle.
3901e04c3fSmrg */
4001e04c3fSmrgstatic struct gl_texture_handle_object *
4101e04c3fSmrglookup_texture_handle(struct gl_context *ctx, GLuint64 id)
4201e04c3fSmrg{
4301e04c3fSmrg   struct gl_texture_handle_object *texHandleObj;
4401e04c3fSmrg
4501e04c3fSmrg   mtx_lock(&ctx->Shared->HandlesMutex);
4601e04c3fSmrg   texHandleObj = (struct gl_texture_handle_object *)
4701e04c3fSmrg      _mesa_hash_table_u64_search(ctx->Shared->TextureHandles, id);
4801e04c3fSmrg   mtx_unlock(&ctx->Shared->HandlesMutex);
4901e04c3fSmrg
5001e04c3fSmrg   return texHandleObj;
5101e04c3fSmrg}
5201e04c3fSmrg
5301e04c3fSmrg/**
5401e04c3fSmrg * Return the gl_image_handle_object for a given 64-bit handle.
5501e04c3fSmrg */
5601e04c3fSmrgstatic struct gl_image_handle_object *
5701e04c3fSmrglookup_image_handle(struct gl_context *ctx, GLuint64 id)
5801e04c3fSmrg{
5901e04c3fSmrg   struct gl_image_handle_object *imgHandleObj;
6001e04c3fSmrg
6101e04c3fSmrg   mtx_lock(&ctx->Shared->HandlesMutex);
6201e04c3fSmrg   imgHandleObj = (struct gl_image_handle_object *)
6301e04c3fSmrg      _mesa_hash_table_u64_search(ctx->Shared->ImageHandles, id);
6401e04c3fSmrg   mtx_unlock(&ctx->Shared->HandlesMutex);
6501e04c3fSmrg
6601e04c3fSmrg   return imgHandleObj;
6701e04c3fSmrg}
6801e04c3fSmrg
6901e04c3fSmrg/**
7001e04c3fSmrg * Delete a texture handle in the shared state.
7101e04c3fSmrg */
7201e04c3fSmrgstatic void
7301e04c3fSmrgdelete_texture_handle(struct gl_context *ctx, GLuint64 id)
7401e04c3fSmrg{
7501e04c3fSmrg   mtx_lock(&ctx->Shared->HandlesMutex);
7601e04c3fSmrg   _mesa_hash_table_u64_remove(ctx->Shared->TextureHandles, id);
7701e04c3fSmrg   mtx_unlock(&ctx->Shared->HandlesMutex);
7801e04c3fSmrg
7901e04c3fSmrg   ctx->Driver.DeleteTextureHandle(ctx, id);
8001e04c3fSmrg}
8101e04c3fSmrg
8201e04c3fSmrg/**
8301e04c3fSmrg * Delete an image handle in the shared state.
8401e04c3fSmrg */
8501e04c3fSmrgstatic void
8601e04c3fSmrgdelete_image_handle(struct gl_context *ctx, GLuint64 id)
8701e04c3fSmrg{
8801e04c3fSmrg   mtx_lock(&ctx->Shared->HandlesMutex);
8901e04c3fSmrg   _mesa_hash_table_u64_remove(ctx->Shared->ImageHandles, id);
9001e04c3fSmrg   mtx_unlock(&ctx->Shared->HandlesMutex);
9101e04c3fSmrg
9201e04c3fSmrg   ctx->Driver.DeleteImageHandle(ctx, id);
9301e04c3fSmrg}
9401e04c3fSmrg
9501e04c3fSmrg/**
9601e04c3fSmrg * Return TRUE if the texture handle is resident in the current context.
9701e04c3fSmrg */
9801e04c3fSmrgstatic inline bool
9901e04c3fSmrgis_texture_handle_resident(struct gl_context *ctx, GLuint64 handle)
10001e04c3fSmrg{
10101e04c3fSmrg   return _mesa_hash_table_u64_search(ctx->ResidentTextureHandles,
10201e04c3fSmrg                                      handle) != NULL;
10301e04c3fSmrg}
10401e04c3fSmrg
10501e04c3fSmrg/**
10601e04c3fSmrg * Return TRUE if the image handle is resident in the current context.
10701e04c3fSmrg */
10801e04c3fSmrgstatic inline bool
10901e04c3fSmrgis_image_handle_resident(struct gl_context *ctx, GLuint64 handle)
11001e04c3fSmrg{
11101e04c3fSmrg   return _mesa_hash_table_u64_search(ctx->ResidentImageHandles,
11201e04c3fSmrg                                      handle) != NULL;
11301e04c3fSmrg}
11401e04c3fSmrg
11501e04c3fSmrg/**
11601e04c3fSmrg * Make a texture handle resident/non-resident in the current context.
11701e04c3fSmrg */
11801e04c3fSmrgstatic void
11901e04c3fSmrgmake_texture_handle_resident(struct gl_context *ctx,
12001e04c3fSmrg                             struct gl_texture_handle_object *texHandleObj,
12101e04c3fSmrg                             bool resident)
12201e04c3fSmrg{
12301e04c3fSmrg   struct gl_sampler_object *sampObj = NULL;
12401e04c3fSmrg   struct gl_texture_object *texObj = NULL;
12501e04c3fSmrg   GLuint64 handle = texHandleObj->handle;
12601e04c3fSmrg
12701e04c3fSmrg   if (resident) {
12801e04c3fSmrg      assert(!is_texture_handle_resident(ctx, handle));
12901e04c3fSmrg
13001e04c3fSmrg      _mesa_hash_table_u64_insert(ctx->ResidentTextureHandles, handle,
13101e04c3fSmrg                                  texHandleObj);
13201e04c3fSmrg
13301e04c3fSmrg      ctx->Driver.MakeTextureHandleResident(ctx, handle, GL_TRUE);
13401e04c3fSmrg
13501e04c3fSmrg      /* Reference the texture object (and the separate sampler if needed) to
13601e04c3fSmrg       * be sure it won't be deleted until it is not bound anywhere and there
13701e04c3fSmrg       * are no handles using the object that are resident in any context.
13801e04c3fSmrg       */
13901e04c3fSmrg      _mesa_reference_texobj(&texObj, texHandleObj->texObj);
14001e04c3fSmrg      if (texHandleObj->sampObj)
14101e04c3fSmrg         _mesa_reference_sampler_object(ctx, &sampObj, texHandleObj->sampObj);
14201e04c3fSmrg   } else {
14301e04c3fSmrg      assert(is_texture_handle_resident(ctx, handle));
14401e04c3fSmrg
14501e04c3fSmrg      _mesa_hash_table_u64_remove(ctx->ResidentTextureHandles, handle);
14601e04c3fSmrg
14701e04c3fSmrg      ctx->Driver.MakeTextureHandleResident(ctx, handle, GL_FALSE);
14801e04c3fSmrg
14901e04c3fSmrg      /* Unreference the texture object but keep the pointer intact, if
15001e04c3fSmrg       * refcount hits zero, the texture and all handles will be deleted.
15101e04c3fSmrg       */
15201e04c3fSmrg      texObj = texHandleObj->texObj;
15301e04c3fSmrg      _mesa_reference_texobj(&texObj, NULL);
15401e04c3fSmrg
15501e04c3fSmrg      /* Unreference the separate sampler object but keep the pointer intact,
15601e04c3fSmrg       * if refcount hits zero, the sampler and all handles will be deleted.
15701e04c3fSmrg       */
15801e04c3fSmrg      if (texHandleObj->sampObj) {
15901e04c3fSmrg         sampObj = texHandleObj->sampObj;
16001e04c3fSmrg         _mesa_reference_sampler_object(ctx, &sampObj, NULL);
16101e04c3fSmrg      }
16201e04c3fSmrg   }
16301e04c3fSmrg}
16401e04c3fSmrg
16501e04c3fSmrg/**
16601e04c3fSmrg * Make an image handle resident/non-resident in the current context.
16701e04c3fSmrg */
16801e04c3fSmrgstatic void
16901e04c3fSmrgmake_image_handle_resident(struct gl_context *ctx,
17001e04c3fSmrg                           struct gl_image_handle_object *imgHandleObj,
17101e04c3fSmrg                           GLenum access, bool resident)
17201e04c3fSmrg{
17301e04c3fSmrg   struct gl_texture_object *texObj = NULL;
17401e04c3fSmrg   GLuint64 handle = imgHandleObj->handle;
17501e04c3fSmrg
17601e04c3fSmrg   if (resident) {
17701e04c3fSmrg      assert(!is_image_handle_resident(ctx, handle));
17801e04c3fSmrg
17901e04c3fSmrg      _mesa_hash_table_u64_insert(ctx->ResidentImageHandles, handle,
18001e04c3fSmrg                                  imgHandleObj);
18101e04c3fSmrg
18201e04c3fSmrg      ctx->Driver.MakeImageHandleResident(ctx, handle, access, GL_TRUE);
18301e04c3fSmrg
18401e04c3fSmrg      /* Reference the texture object to be sure it won't be deleted until it
18501e04c3fSmrg       * is not bound anywhere and there are no handles using the object that
18601e04c3fSmrg       * are resident in any context.
18701e04c3fSmrg       */
18801e04c3fSmrg      _mesa_reference_texobj(&texObj, imgHandleObj->imgObj.TexObj);
18901e04c3fSmrg   } else {
19001e04c3fSmrg      assert(is_image_handle_resident(ctx, handle));
19101e04c3fSmrg
19201e04c3fSmrg      _mesa_hash_table_u64_remove(ctx->ResidentImageHandles, handle);
19301e04c3fSmrg
19401e04c3fSmrg      ctx->Driver.MakeImageHandleResident(ctx, handle, access, GL_FALSE);
19501e04c3fSmrg
19601e04c3fSmrg      /* Unreference the texture object but keep the pointer intact, if
19701e04c3fSmrg       * refcount hits zero, the texture and all handles will be deleted.
19801e04c3fSmrg       */
19901e04c3fSmrg      texObj = imgHandleObj->imgObj.TexObj;
20001e04c3fSmrg      _mesa_reference_texobj(&texObj, NULL);
20101e04c3fSmrg   }
20201e04c3fSmrg}
20301e04c3fSmrg
20401e04c3fSmrgstatic struct gl_texture_handle_object *
20501e04c3fSmrgfind_texhandleobj(struct gl_texture_object *texObj,
20601e04c3fSmrg                  struct gl_sampler_object *sampObj)
20701e04c3fSmrg{
20801e04c3fSmrg   util_dynarray_foreach(&texObj->SamplerHandles,
20901e04c3fSmrg                         struct gl_texture_handle_object *, texHandleObj) {
21001e04c3fSmrg      if ((*texHandleObj)->sampObj == sampObj)
21101e04c3fSmrg         return *texHandleObj;
21201e04c3fSmrg   }
21301e04c3fSmrg   return NULL;
21401e04c3fSmrg}
21501e04c3fSmrg
21601e04c3fSmrgstatic GLuint64
21701e04c3fSmrgget_texture_handle(struct gl_context *ctx, struct gl_texture_object *texObj,
21801e04c3fSmrg                   struct gl_sampler_object *sampObj)
21901e04c3fSmrg{
22001e04c3fSmrg   bool separate_sampler = &texObj->Sampler != sampObj;
22101e04c3fSmrg   struct gl_texture_handle_object *texHandleObj;
22201e04c3fSmrg   GLuint64 handle;
22301e04c3fSmrg
22401e04c3fSmrg   /* The ARB_bindless_texture spec says:
22501e04c3fSmrg    *
22601e04c3fSmrg    * "The handle for each texture or texture/sampler pair is unique; the same
22701e04c3fSmrg    *  handle will be returned if GetTextureHandleARB is called multiple times
22801e04c3fSmrg    *  for the same texture or if GetTextureSamplerHandleARB is called multiple
22901e04c3fSmrg    *  times for the same texture/sampler pair."
23001e04c3fSmrg    */
23101e04c3fSmrg   mtx_lock(&ctx->Shared->HandlesMutex);
23201e04c3fSmrg   texHandleObj = find_texhandleobj(texObj, separate_sampler ? sampObj : NULL);
23301e04c3fSmrg   if (texHandleObj) {
23401e04c3fSmrg      mtx_unlock(&ctx->Shared->HandlesMutex);
23501e04c3fSmrg      return texHandleObj->handle;
23601e04c3fSmrg   }
23701e04c3fSmrg
23801e04c3fSmrg   /* Request a new texture handle from the driver. */
23901e04c3fSmrg   handle = ctx->Driver.NewTextureHandle(ctx, texObj, sampObj);
24001e04c3fSmrg   if (!handle) {
24101e04c3fSmrg      mtx_unlock(&ctx->Shared->HandlesMutex);
24201e04c3fSmrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexture*HandleARB()");
24301e04c3fSmrg      return 0;
24401e04c3fSmrg   }
24501e04c3fSmrg
24601e04c3fSmrg   texHandleObj = CALLOC_STRUCT(gl_texture_handle_object);
24701e04c3fSmrg   if (!texHandleObj) {
24801e04c3fSmrg      mtx_unlock(&ctx->Shared->HandlesMutex);
24901e04c3fSmrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexture*HandleARB()");
25001e04c3fSmrg      return 0;
25101e04c3fSmrg   }
25201e04c3fSmrg
25301e04c3fSmrg   /* Store the handle into the texture object. */
25401e04c3fSmrg   texHandleObj->texObj = texObj;
25501e04c3fSmrg   texHandleObj->sampObj = separate_sampler ? sampObj : NULL;
25601e04c3fSmrg   texHandleObj->handle = handle;
25701e04c3fSmrg   util_dynarray_append(&texObj->SamplerHandles,
25801e04c3fSmrg                        struct gl_texture_handle_object *, texHandleObj);
25901e04c3fSmrg
26001e04c3fSmrg   if (separate_sampler) {
26101e04c3fSmrg      /* Store the handle into the separate sampler if needed. */
26201e04c3fSmrg      util_dynarray_append(&sampObj->Handles,
26301e04c3fSmrg                           struct gl_texture_handle_object *, texHandleObj);
26401e04c3fSmrg   }
26501e04c3fSmrg
26601e04c3fSmrg   /* When referenced by one or more handles, texture objects are immutable. */
26701e04c3fSmrg   texObj->HandleAllocated = true;
26801e04c3fSmrg   if (texObj->Target == GL_TEXTURE_BUFFER)
26901e04c3fSmrg      texObj->BufferObject->HandleAllocated = true;
27001e04c3fSmrg   sampObj->HandleAllocated = true;
27101e04c3fSmrg
27201e04c3fSmrg   /* Store the handle in the shared state for all contexts. */
27301e04c3fSmrg   _mesa_hash_table_u64_insert(ctx->Shared->TextureHandles, handle,
27401e04c3fSmrg                               texHandleObj);
27501e04c3fSmrg   mtx_unlock(&ctx->Shared->HandlesMutex);
27601e04c3fSmrg
27701e04c3fSmrg   return handle;
27801e04c3fSmrg}
27901e04c3fSmrg
28001e04c3fSmrgstatic struct gl_image_handle_object *
28101e04c3fSmrgfind_imghandleobj(struct gl_texture_object *texObj, GLint level,
28201e04c3fSmrg                  GLboolean layered, GLint layer, GLenum format)
28301e04c3fSmrg{
28401e04c3fSmrg   util_dynarray_foreach(&texObj->ImageHandles,
28501e04c3fSmrg                         struct gl_image_handle_object *, imgHandleObj) {
28601e04c3fSmrg      struct gl_image_unit *u = &(*imgHandleObj)->imgObj;
28701e04c3fSmrg
28801e04c3fSmrg      if (u->TexObj == texObj && u->Level == level && u->Layered == layered &&
28901e04c3fSmrg          u->Layer == layer && u->Format == format)
29001e04c3fSmrg         return *imgHandleObj;
29101e04c3fSmrg   }
29201e04c3fSmrg   return NULL;
29301e04c3fSmrg}
29401e04c3fSmrg
29501e04c3fSmrgstatic GLuint64
29601e04c3fSmrgget_image_handle(struct gl_context *ctx, struct gl_texture_object *texObj,
29701e04c3fSmrg                 GLint level, GLboolean layered, GLint layer, GLenum format)
29801e04c3fSmrg{
29901e04c3fSmrg   struct gl_image_handle_object *imgHandleObj;
30001e04c3fSmrg   struct gl_image_unit imgObj;
30101e04c3fSmrg   GLuint64 handle;
30201e04c3fSmrg
30301e04c3fSmrg   /* The ARB_bindless_texture spec says:
30401e04c3fSmrg    *
30501e04c3fSmrg    * "The handle returned for each combination of <texture>, <level>,
30601e04c3fSmrg    * <layered>, <layer>, and <format> is unique; the same handle will be
30701e04c3fSmrg    * returned if GetImageHandleARB is called multiple times with the same
30801e04c3fSmrg    * parameters."
30901e04c3fSmrg    */
31001e04c3fSmrg   mtx_lock(&ctx->Shared->HandlesMutex);
31101e04c3fSmrg   imgHandleObj = find_imghandleobj(texObj, level, layered, layer, format);
31201e04c3fSmrg   if (imgHandleObj) {
31301e04c3fSmrg      mtx_unlock(&ctx->Shared->HandlesMutex);
31401e04c3fSmrg      return imgHandleObj->handle;
31501e04c3fSmrg   }
31601e04c3fSmrg
31701e04c3fSmrg   imgObj.TexObj = texObj; /* weak reference */
31801e04c3fSmrg   imgObj.Level = level;
31901e04c3fSmrg   imgObj.Access = GL_READ_WRITE;
32001e04c3fSmrg   imgObj.Format = format;
32101e04c3fSmrg   imgObj._ActualFormat = _mesa_get_shader_image_format(format);
32201e04c3fSmrg
32301e04c3fSmrg   if (_mesa_tex_target_is_layered(texObj->Target)) {
32401e04c3fSmrg      imgObj.Layered = layered;
32501e04c3fSmrg      imgObj.Layer = layer;
32601e04c3fSmrg      imgObj._Layer = (imgObj.Layered ? 0 : imgObj.Layer);
32701e04c3fSmrg   } else {
32801e04c3fSmrg      imgObj.Layered = GL_FALSE;
32901e04c3fSmrg      imgObj.Layer = 0;
33001e04c3fSmrg      imgObj._Layer = 0;
33101e04c3fSmrg   }
33201e04c3fSmrg
33301e04c3fSmrg   /* Request a new image handle from the driver. */
33401e04c3fSmrg   handle = ctx->Driver.NewImageHandle(ctx, &imgObj);
33501e04c3fSmrg   if (!handle) {
33601e04c3fSmrg      mtx_unlock(&ctx->Shared->HandlesMutex);
33701e04c3fSmrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetImageHandleARB()");
33801e04c3fSmrg      return 0;
33901e04c3fSmrg   }
34001e04c3fSmrg
34101e04c3fSmrg   imgHandleObj = CALLOC_STRUCT(gl_image_handle_object);
34201e04c3fSmrg   if (!imgHandleObj) {
34301e04c3fSmrg      mtx_unlock(&ctx->Shared->HandlesMutex);
34401e04c3fSmrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetImageHandleARB()");
34501e04c3fSmrg      return 0;
34601e04c3fSmrg   }
34701e04c3fSmrg
34801e04c3fSmrg   /* Store the handle into the texture object. */
34901e04c3fSmrg   memcpy(&imgHandleObj->imgObj, &imgObj, sizeof(struct gl_image_unit));
35001e04c3fSmrg   imgHandleObj->handle = handle;
35101e04c3fSmrg   util_dynarray_append(&texObj->ImageHandles,
35201e04c3fSmrg                        struct gl_image_handle_object *, imgHandleObj);
35301e04c3fSmrg
35401e04c3fSmrg   /* When referenced by one or more handles, texture objects are immutable. */
35501e04c3fSmrg   texObj->HandleAllocated = true;
35601e04c3fSmrg   if (texObj->Target == GL_TEXTURE_BUFFER)
35701e04c3fSmrg      texObj->BufferObject->HandleAllocated = true;
35801e04c3fSmrg   texObj->Sampler.HandleAllocated = true;
35901e04c3fSmrg
36001e04c3fSmrg   /* Store the handle in the shared state for all contexts. */
36101e04c3fSmrg   _mesa_hash_table_u64_insert(ctx->Shared->ImageHandles, handle, imgHandleObj);
36201e04c3fSmrg   mtx_unlock(&ctx->Shared->HandlesMutex);
36301e04c3fSmrg
36401e04c3fSmrg   return handle;
36501e04c3fSmrg}
36601e04c3fSmrg
36701e04c3fSmrg/**
36801e04c3fSmrg * Init/free per-context resident handles.
36901e04c3fSmrg */
37001e04c3fSmrgvoid
37101e04c3fSmrg_mesa_init_resident_handles(struct gl_context *ctx)
37201e04c3fSmrg{
37301e04c3fSmrg   ctx->ResidentTextureHandles = _mesa_hash_table_u64_create(NULL);
37401e04c3fSmrg   ctx->ResidentImageHandles = _mesa_hash_table_u64_create(NULL);
37501e04c3fSmrg}
37601e04c3fSmrg
37701e04c3fSmrgvoid
37801e04c3fSmrg_mesa_free_resident_handles(struct gl_context *ctx)
37901e04c3fSmrg{
38001e04c3fSmrg   _mesa_hash_table_u64_destroy(ctx->ResidentTextureHandles, NULL);
38101e04c3fSmrg   _mesa_hash_table_u64_destroy(ctx->ResidentImageHandles, NULL);
38201e04c3fSmrg}
38301e04c3fSmrg
38401e04c3fSmrg/**
38501e04c3fSmrg * Init/free shared allocated handles.
38601e04c3fSmrg */
38701e04c3fSmrgvoid
38801e04c3fSmrg_mesa_init_shared_handles(struct gl_shared_state *shared)
38901e04c3fSmrg{
39001e04c3fSmrg   shared->TextureHandles = _mesa_hash_table_u64_create(NULL);
39101e04c3fSmrg   shared->ImageHandles = _mesa_hash_table_u64_create(NULL);
39201e04c3fSmrg   mtx_init(&shared->HandlesMutex, mtx_recursive);
39301e04c3fSmrg}
39401e04c3fSmrg
39501e04c3fSmrgvoid
39601e04c3fSmrg_mesa_free_shared_handles(struct gl_shared_state *shared)
39701e04c3fSmrg{
39801e04c3fSmrg   if (shared->TextureHandles)
39901e04c3fSmrg      _mesa_hash_table_u64_destroy(shared->TextureHandles, NULL);
40001e04c3fSmrg
40101e04c3fSmrg   if (shared->ImageHandles)
40201e04c3fSmrg      _mesa_hash_table_u64_destroy(shared->ImageHandles, NULL);
40301e04c3fSmrg
40401e04c3fSmrg   mtx_destroy(&shared->HandlesMutex);
40501e04c3fSmrg}
40601e04c3fSmrg
40701e04c3fSmrg/**
40801e04c3fSmrg * Init/free texture/image handles per-texture object.
40901e04c3fSmrg */
41001e04c3fSmrgvoid
41101e04c3fSmrg_mesa_init_texture_handles(struct gl_texture_object *texObj)
41201e04c3fSmrg{
41301e04c3fSmrg   util_dynarray_init(&texObj->SamplerHandles, NULL);
41401e04c3fSmrg   util_dynarray_init(&texObj->ImageHandles, NULL);
41501e04c3fSmrg}
41601e04c3fSmrg
41701e04c3fSmrgvoid
41801e04c3fSmrg_mesa_make_texture_handles_non_resident(struct gl_context *ctx,
41901e04c3fSmrg                                        struct gl_texture_object *texObj)
42001e04c3fSmrg{
42101e04c3fSmrg   mtx_lock(&ctx->Shared->HandlesMutex);
42201e04c3fSmrg
42301e04c3fSmrg   /* Texture handles */
42401e04c3fSmrg   util_dynarray_foreach(&texObj->SamplerHandles,
42501e04c3fSmrg                         struct gl_texture_handle_object *, texHandleObj) {
42601e04c3fSmrg      if (is_texture_handle_resident(ctx, (*texHandleObj)->handle))
42701e04c3fSmrg         make_texture_handle_resident(ctx, *texHandleObj, false);
42801e04c3fSmrg   }
42901e04c3fSmrg
43001e04c3fSmrg   /* Image handles */
43101e04c3fSmrg   util_dynarray_foreach(&texObj->ImageHandles,
43201e04c3fSmrg                         struct gl_image_handle_object *, imgHandleObj) {
43301e04c3fSmrg      if (is_image_handle_resident(ctx, (*imgHandleObj)->handle))
43401e04c3fSmrg         make_image_handle_resident(ctx, *imgHandleObj, GL_READ_ONLY, false);
43501e04c3fSmrg   }
43601e04c3fSmrg
43701e04c3fSmrg   mtx_unlock(&ctx->Shared->HandlesMutex);
43801e04c3fSmrg}
43901e04c3fSmrg
44001e04c3fSmrgvoid
44101e04c3fSmrg_mesa_delete_texture_handles(struct gl_context *ctx,
44201e04c3fSmrg                             struct gl_texture_object *texObj)
44301e04c3fSmrg{
44401e04c3fSmrg   /* Texture handles */
44501e04c3fSmrg   util_dynarray_foreach(&texObj->SamplerHandles,
44601e04c3fSmrg                         struct gl_texture_handle_object *, texHandleObj) {
44701e04c3fSmrg      struct gl_sampler_object *sampObj = (*texHandleObj)->sampObj;
44801e04c3fSmrg
44901e04c3fSmrg      if (sampObj) {
45001e04c3fSmrg         /* Delete the handle in the separate sampler object. */
45101e04c3fSmrg         util_dynarray_delete_unordered(&sampObj->Handles,
45201e04c3fSmrg                                        struct gl_texture_handle_object *,
45301e04c3fSmrg                                        *texHandleObj);
45401e04c3fSmrg      }
45501e04c3fSmrg      delete_texture_handle(ctx, (*texHandleObj)->handle);
45601e04c3fSmrg      free(*texHandleObj);
45701e04c3fSmrg   }
45801e04c3fSmrg   util_dynarray_fini(&texObj->SamplerHandles);
45901e04c3fSmrg
46001e04c3fSmrg   /* Image handles */
46101e04c3fSmrg   util_dynarray_foreach(&texObj->ImageHandles,
46201e04c3fSmrg                         struct gl_image_handle_object *, imgHandleObj) {
46301e04c3fSmrg      delete_image_handle(ctx, (*imgHandleObj)->handle);
46401e04c3fSmrg      free(*imgHandleObj);
46501e04c3fSmrg   }
46601e04c3fSmrg   util_dynarray_fini(&texObj->ImageHandles);
46701e04c3fSmrg}
46801e04c3fSmrg
46901e04c3fSmrg/**
47001e04c3fSmrg * Init/free texture handles per-sampler object.
47101e04c3fSmrg */
47201e04c3fSmrgvoid
47301e04c3fSmrg_mesa_init_sampler_handles(struct gl_sampler_object *sampObj)
47401e04c3fSmrg{
47501e04c3fSmrg   util_dynarray_init(&sampObj->Handles, NULL);
47601e04c3fSmrg}
47701e04c3fSmrg
47801e04c3fSmrgvoid
47901e04c3fSmrg_mesa_delete_sampler_handles(struct gl_context *ctx,
48001e04c3fSmrg                             struct gl_sampler_object *sampObj)
48101e04c3fSmrg{
48201e04c3fSmrg   util_dynarray_foreach(&sampObj->Handles,
48301e04c3fSmrg                         struct gl_texture_handle_object *, texHandleObj) {
48401e04c3fSmrg      struct gl_texture_object *texObj = (*texHandleObj)->texObj;
48501e04c3fSmrg
48601e04c3fSmrg      /* Delete the handle in the texture object. */
48701e04c3fSmrg      util_dynarray_delete_unordered(&texObj->SamplerHandles,
48801e04c3fSmrg                                     struct gl_texture_handle_object *,
48901e04c3fSmrg                                     *texHandleObj);
49001e04c3fSmrg
49101e04c3fSmrg      delete_texture_handle(ctx, (*texHandleObj)->handle);
49201e04c3fSmrg      free(*texHandleObj);
49301e04c3fSmrg   }
49401e04c3fSmrg   util_dynarray_fini(&sampObj->Handles);
49501e04c3fSmrg}
49601e04c3fSmrg
49701e04c3fSmrgstatic GLboolean
49801e04c3fSmrgis_sampler_border_color_valid(struct gl_sampler_object *samp)
49901e04c3fSmrg{
50001e04c3fSmrg   static const GLfloat valid_float_border_colors[4][4] = {
50101e04c3fSmrg      { 0.0, 0.0, 0.0, 0.0 },
50201e04c3fSmrg      { 0.0, 0.0, 0.0, 1.0 },
50301e04c3fSmrg      { 1.0, 1.0, 1.0, 0.0 },
50401e04c3fSmrg      { 1.0, 1.0, 1.0, 1.0 },
50501e04c3fSmrg   };
50601e04c3fSmrg   static const GLint valid_integer_border_colors[4][4] = {
50701e04c3fSmrg      { 0, 0, 0, 0 },
50801e04c3fSmrg      { 0, 0, 0, 1 },
50901e04c3fSmrg      { 1, 1, 1, 0 },
51001e04c3fSmrg      { 1, 1, 1, 1 },
51101e04c3fSmrg   };
51201e04c3fSmrg   size_t size = sizeof(samp->BorderColor.ui);
51301e04c3fSmrg
51401e04c3fSmrg   /* The ARB_bindless_texture spec says:
51501e04c3fSmrg    *
51601e04c3fSmrg    * "The error INVALID_OPERATION is generated if the border color (taken from
51701e04c3fSmrg    *  the embedded sampler for GetTextureHandleARB or from the <sampler> for
51801e04c3fSmrg    *  GetTextureSamplerHandleARB) is not one of the following allowed values.
51901e04c3fSmrg    *  If the texture's base internal format is signed or unsigned integer,
52001e04c3fSmrg    *  allowed values are (0,0,0,0), (0,0,0,1), (1,1,1,0), and (1,1,1,1). If
52101e04c3fSmrg    *  the base internal format is not integer, allowed values are
52201e04c3fSmrg    *  (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
52301e04c3fSmrg    *  (1.0,1.0,1.0,1.0)."
52401e04c3fSmrg    */
52501e04c3fSmrg   if (!memcmp(samp->BorderColor.f, valid_float_border_colors[0], size) ||
52601e04c3fSmrg       !memcmp(samp->BorderColor.f, valid_float_border_colors[1], size) ||
52701e04c3fSmrg       !memcmp(samp->BorderColor.f, valid_float_border_colors[2], size) ||
52801e04c3fSmrg       !memcmp(samp->BorderColor.f, valid_float_border_colors[3], size))
52901e04c3fSmrg      return GL_TRUE;
53001e04c3fSmrg
53101e04c3fSmrg   if (!memcmp(samp->BorderColor.ui, valid_integer_border_colors[0], size) ||
53201e04c3fSmrg       !memcmp(samp->BorderColor.ui, valid_integer_border_colors[1], size) ||
53301e04c3fSmrg       !memcmp(samp->BorderColor.ui, valid_integer_border_colors[2], size) ||
53401e04c3fSmrg       !memcmp(samp->BorderColor.ui, valid_integer_border_colors[3], size))
53501e04c3fSmrg      return GL_TRUE;
53601e04c3fSmrg
53701e04c3fSmrg   return GL_FALSE;
53801e04c3fSmrg}
53901e04c3fSmrg
54001e04c3fSmrgGLuint64 GLAPIENTRY
54101e04c3fSmrg_mesa_GetTextureHandleARB_no_error(GLuint texture)
54201e04c3fSmrg{
54301e04c3fSmrg   struct gl_texture_object *texObj;
54401e04c3fSmrg
54501e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
54601e04c3fSmrg
54701e04c3fSmrg   texObj = _mesa_lookup_texture(ctx, texture);
54801e04c3fSmrg   if (!_mesa_is_texture_complete(texObj, &texObj->Sampler))
54901e04c3fSmrg      _mesa_test_texobj_completeness(ctx, texObj);
55001e04c3fSmrg
55101e04c3fSmrg   return get_texture_handle(ctx, texObj, &texObj->Sampler);
55201e04c3fSmrg}
55301e04c3fSmrg
55401e04c3fSmrgGLuint64 GLAPIENTRY
55501e04c3fSmrg_mesa_GetTextureHandleARB(GLuint texture)
55601e04c3fSmrg{
55701e04c3fSmrg   struct gl_texture_object *texObj = NULL;
55801e04c3fSmrg
55901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
56001e04c3fSmrg
56101e04c3fSmrg   if (!_mesa_has_ARB_bindless_texture(ctx)) {
56201e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
56301e04c3fSmrg                  "glGetTextureHandleARB(unsupported)");
56401e04c3fSmrg      return 0;
56501e04c3fSmrg   }
56601e04c3fSmrg
56701e04c3fSmrg   /* The ARB_bindless_texture spec says:
56801e04c3fSmrg    *
56901e04c3fSmrg    * "The error INVALID_VALUE is generated by GetTextureHandleARB or
57001e04c3fSmrg    *  GetTextureSamplerHandleARB if <texture> is zero or not the name of an
57101e04c3fSmrg    *  existing texture object."
57201e04c3fSmrg    */
57301e04c3fSmrg   if (texture > 0)
57401e04c3fSmrg      texObj = _mesa_lookup_texture(ctx, texture);
57501e04c3fSmrg
57601e04c3fSmrg   if (!texObj) {
57701e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetTextureHandleARB(texture)");
57801e04c3fSmrg      return 0;
57901e04c3fSmrg   }
58001e04c3fSmrg
58101e04c3fSmrg   /* The ARB_bindless_texture spec says:
58201e04c3fSmrg    *
58301e04c3fSmrg    * "The error INVALID_OPERATION is generated by GetTextureHandleARB or
58401e04c3fSmrg    *  GetTextureSamplerHandleARB if the texture object specified by <texture>
58501e04c3fSmrg    *  is not complete."
58601e04c3fSmrg    */
58701e04c3fSmrg   if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
58801e04c3fSmrg      _mesa_test_texobj_completeness(ctx, texObj);
58901e04c3fSmrg      if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
59001e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION,
59101e04c3fSmrg                     "glGetTextureHandleARB(incomplete texture)");
59201e04c3fSmrg         return 0;
59301e04c3fSmrg      }
59401e04c3fSmrg   }
59501e04c3fSmrg
59601e04c3fSmrg   if (!is_sampler_border_color_valid(&texObj->Sampler)) {
59701e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
59801e04c3fSmrg                  "glGetTextureHandleARB(invalid border color)");
59901e04c3fSmrg      return 0;
60001e04c3fSmrg   }
60101e04c3fSmrg
60201e04c3fSmrg   return get_texture_handle(ctx, texObj, &texObj->Sampler);
60301e04c3fSmrg}
60401e04c3fSmrg
60501e04c3fSmrgGLuint64 GLAPIENTRY
60601e04c3fSmrg_mesa_GetTextureSamplerHandleARB_no_error(GLuint texture, GLuint sampler)
60701e04c3fSmrg{
60801e04c3fSmrg   struct gl_texture_object *texObj;
60901e04c3fSmrg   struct gl_sampler_object *sampObj;
61001e04c3fSmrg
61101e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
61201e04c3fSmrg
61301e04c3fSmrg   texObj = _mesa_lookup_texture(ctx, texture);
61401e04c3fSmrg   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
61501e04c3fSmrg
61601e04c3fSmrg   if (!_mesa_is_texture_complete(texObj, sampObj))
61701e04c3fSmrg      _mesa_test_texobj_completeness(ctx, texObj);
61801e04c3fSmrg
61901e04c3fSmrg   return get_texture_handle(ctx, texObj, sampObj);
62001e04c3fSmrg}
62101e04c3fSmrg
62201e04c3fSmrgGLuint64 GLAPIENTRY
62301e04c3fSmrg_mesa_GetTextureSamplerHandleARB(GLuint texture, GLuint sampler)
62401e04c3fSmrg{
62501e04c3fSmrg   struct gl_texture_object *texObj = NULL;
62601e04c3fSmrg   struct gl_sampler_object *sampObj;
62701e04c3fSmrg
62801e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
62901e04c3fSmrg
63001e04c3fSmrg   if (!_mesa_has_ARB_bindless_texture(ctx)) {
63101e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
63201e04c3fSmrg                  "glGetTextureSamplerHandleARB(unsupported)");
63301e04c3fSmrg      return 0;
63401e04c3fSmrg   }
63501e04c3fSmrg
63601e04c3fSmrg   /* The ARB_bindless_texture spec says:
63701e04c3fSmrg    *
63801e04c3fSmrg    * "The error INVALID_VALUE is generated by GetTextureHandleARB or
63901e04c3fSmrg    *  GetTextureSamplerHandleARB if <texture> is zero or not the name of an
64001e04c3fSmrg    *  existing texture object."
64101e04c3fSmrg    */
64201e04c3fSmrg   if (texture > 0)
64301e04c3fSmrg      texObj = _mesa_lookup_texture(ctx, texture);
64401e04c3fSmrg
64501e04c3fSmrg   if (!texObj) {
64601e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
64701e04c3fSmrg                  "glGetTextureSamplerHandleARB(texture)");
64801e04c3fSmrg      return 0;
64901e04c3fSmrg   }
65001e04c3fSmrg
65101e04c3fSmrg   /* The ARB_bindless_texture spec says:
65201e04c3fSmrg    *
65301e04c3fSmrg    * "The error INVALID_VALUE is generated by GetTextureSamplerHandleARB if
65401e04c3fSmrg    *  <sampler> is zero or is not the name of an existing sampler object."
65501e04c3fSmrg    */
65601e04c3fSmrg   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
65701e04c3fSmrg   if (!sampObj) {
65801e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
65901e04c3fSmrg                  "glGetTextureSamplerHandleARB(sampler)");
66001e04c3fSmrg      return 0;
66101e04c3fSmrg   }
66201e04c3fSmrg
66301e04c3fSmrg   /* The ARB_bindless_texture spec says:
66401e04c3fSmrg    *
66501e04c3fSmrg    * "The error INVALID_OPERATION is generated by GetTextureHandleARB or
66601e04c3fSmrg    *  GetTextureSamplerHandleARB if the texture object specified by <texture>
66701e04c3fSmrg    *  is not complete."
66801e04c3fSmrg    */
66901e04c3fSmrg   if (!_mesa_is_texture_complete(texObj, sampObj)) {
67001e04c3fSmrg      _mesa_test_texobj_completeness(ctx, texObj);
67101e04c3fSmrg      if (!_mesa_is_texture_complete(texObj, sampObj)) {
67201e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION,
67301e04c3fSmrg                     "glGetTextureSamplerHandleARB(incomplete texture)");
67401e04c3fSmrg         return 0;
67501e04c3fSmrg      }
67601e04c3fSmrg   }
67701e04c3fSmrg
67801e04c3fSmrg   if (!is_sampler_border_color_valid(sampObj)) {
67901e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
68001e04c3fSmrg                  "glGetTextureSamplerHandleARB(invalid border color)");
68101e04c3fSmrg      return 0;
68201e04c3fSmrg   }
68301e04c3fSmrg
68401e04c3fSmrg   return get_texture_handle(ctx, texObj, sampObj);
68501e04c3fSmrg}
68601e04c3fSmrg
68701e04c3fSmrgvoid GLAPIENTRY
68801e04c3fSmrg_mesa_MakeTextureHandleResidentARB_no_error(GLuint64 handle)
68901e04c3fSmrg{
69001e04c3fSmrg   struct gl_texture_handle_object *texHandleObj;
69101e04c3fSmrg
69201e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
69301e04c3fSmrg
69401e04c3fSmrg   texHandleObj = lookup_texture_handle(ctx, handle);
69501e04c3fSmrg   make_texture_handle_resident(ctx, texHandleObj, true);
69601e04c3fSmrg}
69701e04c3fSmrg
69801e04c3fSmrgvoid GLAPIENTRY
69901e04c3fSmrg_mesa_MakeTextureHandleResidentARB(GLuint64 handle)
70001e04c3fSmrg{
70101e04c3fSmrg   struct gl_texture_handle_object *texHandleObj;
70201e04c3fSmrg
70301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
70401e04c3fSmrg
70501e04c3fSmrg   if (!_mesa_has_ARB_bindless_texture(ctx)) {
70601e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
70701e04c3fSmrg                  "glMakeTextureHandleResidentARB(unsupported)");
70801e04c3fSmrg      return;
70901e04c3fSmrg   }
71001e04c3fSmrg
71101e04c3fSmrg   /* The ARB_bindless_texture spec says:
71201e04c3fSmrg    *
71301e04c3fSmrg    * "The error INVALID_OPERATION is generated by MakeTextureHandleResidentARB
71401e04c3fSmrg    *  if <handle> is not a valid texture handle, or if <handle> is already
71501e04c3fSmrg    *  resident in the current GL context."
71601e04c3fSmrg    */
71701e04c3fSmrg   texHandleObj = lookup_texture_handle(ctx, handle);
71801e04c3fSmrg   if (!texHandleObj) {
71901e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
72001e04c3fSmrg                  "glMakeTextureHandleResidentARB(handle)");
72101e04c3fSmrg      return;
72201e04c3fSmrg   }
72301e04c3fSmrg
72401e04c3fSmrg   if (is_texture_handle_resident(ctx, handle)) {
72501e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
72601e04c3fSmrg                  "glMakeTextureHandleResidentARB(already resident)");
72701e04c3fSmrg      return;
72801e04c3fSmrg   }
72901e04c3fSmrg
73001e04c3fSmrg   make_texture_handle_resident(ctx, texHandleObj, true);
73101e04c3fSmrg}
73201e04c3fSmrg
73301e04c3fSmrgvoid GLAPIENTRY
73401e04c3fSmrg_mesa_MakeTextureHandleNonResidentARB_no_error(GLuint64 handle)
73501e04c3fSmrg{
73601e04c3fSmrg   struct gl_texture_handle_object *texHandleObj;
73701e04c3fSmrg
73801e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
73901e04c3fSmrg
74001e04c3fSmrg   texHandleObj = lookup_texture_handle(ctx, handle);
74101e04c3fSmrg   make_texture_handle_resident(ctx, texHandleObj, false);
74201e04c3fSmrg}
74301e04c3fSmrg
74401e04c3fSmrgvoid GLAPIENTRY
74501e04c3fSmrg_mesa_MakeTextureHandleNonResidentARB(GLuint64 handle)
74601e04c3fSmrg{
74701e04c3fSmrg   struct gl_texture_handle_object *texHandleObj;
74801e04c3fSmrg
74901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
75001e04c3fSmrg
75101e04c3fSmrg   if (!_mesa_has_ARB_bindless_texture(ctx)) {
75201e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
75301e04c3fSmrg                  "glMakeTextureHandleNonResidentARB(unsupported)");
75401e04c3fSmrg      return;
75501e04c3fSmrg   }
75601e04c3fSmrg
75701e04c3fSmrg   /* The ARB_bindless_texture spec says:
75801e04c3fSmrg    *
75901e04c3fSmrg    * "The error INVALID_OPERATION is generated by
76001e04c3fSmrg    *  MakeTextureHandleNonResidentARB if <handle> is not a valid texture
76101e04c3fSmrg    *  handle, or if <handle> is not resident in the current GL context."
76201e04c3fSmrg    */
76301e04c3fSmrg   texHandleObj = lookup_texture_handle(ctx, handle);
76401e04c3fSmrg   if (!texHandleObj) {
76501e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
76601e04c3fSmrg                  "glMakeTextureHandleNonResidentARB(handle)");
76701e04c3fSmrg      return;
76801e04c3fSmrg   }
76901e04c3fSmrg
77001e04c3fSmrg   if (!is_texture_handle_resident(ctx, handle)) {
77101e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
77201e04c3fSmrg                  "glMakeTextureHandleNonResidentARB(not resident)");
77301e04c3fSmrg      return;
77401e04c3fSmrg   }
77501e04c3fSmrg
77601e04c3fSmrg   make_texture_handle_resident(ctx, texHandleObj, false);
77701e04c3fSmrg}
77801e04c3fSmrg
77901e04c3fSmrgGLuint64 GLAPIENTRY
78001e04c3fSmrg_mesa_GetImageHandleARB_no_error(GLuint texture, GLint level, GLboolean layered,
78101e04c3fSmrg                                 GLint layer, GLenum format)
78201e04c3fSmrg{
78301e04c3fSmrg   struct gl_texture_object *texObj;
78401e04c3fSmrg
78501e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
78601e04c3fSmrg
78701e04c3fSmrg   texObj = _mesa_lookup_texture(ctx, texture);
78801e04c3fSmrg   if (!_mesa_is_texture_complete(texObj, &texObj->Sampler))
78901e04c3fSmrg      _mesa_test_texobj_completeness(ctx, texObj);
79001e04c3fSmrg
79101e04c3fSmrg   return get_image_handle(ctx, texObj, level, layered, layer, format);
79201e04c3fSmrg}
79301e04c3fSmrg
79401e04c3fSmrgGLuint64 GLAPIENTRY
79501e04c3fSmrg_mesa_GetImageHandleARB(GLuint texture, GLint level, GLboolean layered,
79601e04c3fSmrg                        GLint layer, GLenum format)
79701e04c3fSmrg{
79801e04c3fSmrg   struct gl_texture_object *texObj = NULL;
79901e04c3fSmrg
80001e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
80101e04c3fSmrg
80201e04c3fSmrg   if (!_mesa_has_ARB_bindless_texture(ctx) ||
80301e04c3fSmrg       !_mesa_has_ARB_shader_image_load_store(ctx)) {
80401e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
80501e04c3fSmrg                  "glGetImageHandleARB(unsupported)");
80601e04c3fSmrg      return 0;
80701e04c3fSmrg   }
80801e04c3fSmrg
80901e04c3fSmrg   /* The ARB_bindless_texture spec says:
81001e04c3fSmrg    *
81101e04c3fSmrg    * "The error INVALID_VALUE is generated by GetImageHandleARB if <texture>
81201e04c3fSmrg    *  is zero or not the name of an existing texture object, if the image for
81301e04c3fSmrg    *  <level> does not existing in <texture>, or if <layered> is FALSE and
81401e04c3fSmrg    *  <layer> is greater than or equal to the number of layers in the image at
81501e04c3fSmrg    *  <level>."
81601e04c3fSmrg    */
81701e04c3fSmrg   if (texture > 0)
81801e04c3fSmrg      texObj = _mesa_lookup_texture(ctx, texture);
81901e04c3fSmrg
82001e04c3fSmrg   if (!texObj) {
82101e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(texture)");
82201e04c3fSmrg      return 0;
82301e04c3fSmrg   }
82401e04c3fSmrg
82501e04c3fSmrg   if (level < 0 || level >= _mesa_max_texture_levels(ctx, texObj->Target)) {
82601e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(level)");
82701e04c3fSmrg      return 0;
82801e04c3fSmrg   }
82901e04c3fSmrg
83001e04c3fSmrg   if (!layered && layer > _mesa_get_texture_layers(texObj, level)) {
83101e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(layer)");
83201e04c3fSmrg      return 0;
83301e04c3fSmrg   }
83401e04c3fSmrg
83501e04c3fSmrg   if (!_mesa_is_shader_image_format_supported(ctx, format)) {
83601e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(format)");
83701e04c3fSmrg      return 0;
83801e04c3fSmrg   }
83901e04c3fSmrg
84001e04c3fSmrg   /* The ARB_bindless_texture spec says:
84101e04c3fSmrg    *
84201e04c3fSmrg    * "The error INVALID_OPERATION is generated by GetImageHandleARB if the
84301e04c3fSmrg    *  texture object <texture> is not complete or if <layered> is TRUE and
84401e04c3fSmrg    *  <texture> is not a three-dimensional, one-dimensional array, two
84501e04c3fSmrg    *  dimensional array, cube map, or cube map array texture."
84601e04c3fSmrg    */
84701e04c3fSmrg   if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
84801e04c3fSmrg      _mesa_test_texobj_completeness(ctx, texObj);
84901e04c3fSmrg      if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
85001e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION,
85101e04c3fSmrg                     "glGetImageHandleARB(incomplete texture)");
85201e04c3fSmrg         return 0;
85301e04c3fSmrg      }
85401e04c3fSmrg   }
85501e04c3fSmrg
85601e04c3fSmrg   if (layered && !_mesa_tex_target_is_layered(texObj->Target)) {
85701e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
85801e04c3fSmrg                  "glGetImageHandleARB(not layered)");
85901e04c3fSmrg      return 0;
86001e04c3fSmrg   }
86101e04c3fSmrg
86201e04c3fSmrg   return get_image_handle(ctx, texObj, level, layered, layer, format);
86301e04c3fSmrg}
86401e04c3fSmrg
86501e04c3fSmrgvoid GLAPIENTRY
86601e04c3fSmrg_mesa_MakeImageHandleResidentARB_no_error(GLuint64 handle, GLenum access)
86701e04c3fSmrg{
86801e04c3fSmrg   struct gl_image_handle_object *imgHandleObj;
86901e04c3fSmrg
87001e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
87101e04c3fSmrg
87201e04c3fSmrg   imgHandleObj = lookup_image_handle(ctx, handle);
87301e04c3fSmrg   make_image_handle_resident(ctx, imgHandleObj, access, true);
87401e04c3fSmrg}
87501e04c3fSmrg
87601e04c3fSmrgvoid GLAPIENTRY
87701e04c3fSmrg_mesa_MakeImageHandleResidentARB(GLuint64 handle, GLenum access)
87801e04c3fSmrg{
87901e04c3fSmrg   struct gl_image_handle_object *imgHandleObj;
88001e04c3fSmrg
88101e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
88201e04c3fSmrg
88301e04c3fSmrg   if (!_mesa_has_ARB_bindless_texture(ctx) ||
88401e04c3fSmrg       !_mesa_has_ARB_shader_image_load_store(ctx)) {
88501e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
88601e04c3fSmrg                  "glMakeImageHandleResidentARB(unsupported)");
88701e04c3fSmrg      return;
88801e04c3fSmrg   }
88901e04c3fSmrg
89001e04c3fSmrg   if (access != GL_READ_ONLY &&
89101e04c3fSmrg       access != GL_WRITE_ONLY &&
89201e04c3fSmrg       access != GL_READ_WRITE) {
89301e04c3fSmrg      _mesa_error(ctx, GL_INVALID_ENUM,
89401e04c3fSmrg                  "glMakeImageHandleResidentARB(access)");
89501e04c3fSmrg      return;
89601e04c3fSmrg   }
89701e04c3fSmrg
89801e04c3fSmrg   /* The ARB_bindless_texture spec says:
89901e04c3fSmrg    *
90001e04c3fSmrg    * "The error INVALID_OPERATION is generated by MakeImageHandleResidentARB
90101e04c3fSmrg    *  if <handle> is not a valid image handle, or if <handle> is already
90201e04c3fSmrg    *  resident in the current GL context."
90301e04c3fSmrg    */
90401e04c3fSmrg   imgHandleObj = lookup_image_handle(ctx, handle);
90501e04c3fSmrg   if (!imgHandleObj) {
90601e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
90701e04c3fSmrg                  "glMakeImageHandleResidentARB(handle)");
90801e04c3fSmrg      return;
90901e04c3fSmrg   }
91001e04c3fSmrg
91101e04c3fSmrg   if (is_image_handle_resident(ctx, handle)) {
91201e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
91301e04c3fSmrg                  "glMakeImageHandleResidentARB(already resident)");
91401e04c3fSmrg      return;
91501e04c3fSmrg   }
91601e04c3fSmrg
91701e04c3fSmrg   make_image_handle_resident(ctx, imgHandleObj, access, true);
91801e04c3fSmrg}
91901e04c3fSmrg
92001e04c3fSmrgvoid GLAPIENTRY
92101e04c3fSmrg_mesa_MakeImageHandleNonResidentARB_no_error(GLuint64 handle)
92201e04c3fSmrg{
92301e04c3fSmrg   struct gl_image_handle_object *imgHandleObj;
92401e04c3fSmrg
92501e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
92601e04c3fSmrg
92701e04c3fSmrg   imgHandleObj = lookup_image_handle(ctx, handle);
92801e04c3fSmrg   make_image_handle_resident(ctx, imgHandleObj, GL_READ_ONLY, false);
92901e04c3fSmrg}
93001e04c3fSmrg
93101e04c3fSmrgvoid GLAPIENTRY
93201e04c3fSmrg_mesa_MakeImageHandleNonResidentARB(GLuint64 handle)
93301e04c3fSmrg{
93401e04c3fSmrg   struct gl_image_handle_object *imgHandleObj;
93501e04c3fSmrg
93601e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
93701e04c3fSmrg
93801e04c3fSmrg   if (!_mesa_has_ARB_bindless_texture(ctx) ||
93901e04c3fSmrg       !_mesa_has_ARB_shader_image_load_store(ctx)) {
94001e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
94101e04c3fSmrg                  "glMakeImageHandleNonResidentARB(unsupported)");
94201e04c3fSmrg      return;
94301e04c3fSmrg   }
94401e04c3fSmrg
94501e04c3fSmrg   /* The ARB_bindless_texture spec says:
94601e04c3fSmrg    *
94701e04c3fSmrg    * "The error INVALID_OPERATION is generated by
94801e04c3fSmrg    *  MakeImageHandleNonResidentARB if <handle> is not a valid image handle,
94901e04c3fSmrg    *  or if <handle> is not resident in the current GL context."
95001e04c3fSmrg    */
95101e04c3fSmrg   imgHandleObj = lookup_image_handle(ctx, handle);
95201e04c3fSmrg   if (!imgHandleObj) {
95301e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
95401e04c3fSmrg                  "glMakeImageHandleNonResidentARB(handle)");
95501e04c3fSmrg      return;
95601e04c3fSmrg   }
95701e04c3fSmrg
95801e04c3fSmrg   if (!is_image_handle_resident(ctx, handle)) {
95901e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
96001e04c3fSmrg                  "glMakeImageHandleNonResidentARB(not resident)");
96101e04c3fSmrg      return;
96201e04c3fSmrg   }
96301e04c3fSmrg
96401e04c3fSmrg   make_image_handle_resident(ctx, imgHandleObj, GL_READ_ONLY, false);
96501e04c3fSmrg}
96601e04c3fSmrg
96701e04c3fSmrgGLboolean GLAPIENTRY
96801e04c3fSmrg_mesa_IsTextureHandleResidentARB_no_error(GLuint64 handle)
96901e04c3fSmrg{
97001e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
97101e04c3fSmrg   return is_texture_handle_resident(ctx, handle);
97201e04c3fSmrg}
97301e04c3fSmrg
97401e04c3fSmrgGLboolean GLAPIENTRY
97501e04c3fSmrg_mesa_IsTextureHandleResidentARB(GLuint64 handle)
97601e04c3fSmrg{
97701e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
97801e04c3fSmrg
97901e04c3fSmrg   if (!_mesa_has_ARB_bindless_texture(ctx)) {
98001e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
98101e04c3fSmrg                  "glIsTextureHandleResidentARB(unsupported)");
98201e04c3fSmrg      return GL_FALSE;
98301e04c3fSmrg   }
98401e04c3fSmrg
98501e04c3fSmrg   /* The ARB_bindless_texture spec says:
98601e04c3fSmrg    *
98701e04c3fSmrg    * "The error INVALID_OPERATION will be generated by
98801e04c3fSmrg    *  IsTextureHandleResidentARB and IsImageHandleResidentARB if <handle> is
98901e04c3fSmrg    *  not a valid texture or image handle, respectively."
99001e04c3fSmrg    */
99101e04c3fSmrg   if (!lookup_texture_handle(ctx, handle)) {
99201e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
99301e04c3fSmrg                  "glIsTextureHandleResidentARB(handle)");
99401e04c3fSmrg      return GL_FALSE;
99501e04c3fSmrg   }
99601e04c3fSmrg
99701e04c3fSmrg   return is_texture_handle_resident(ctx, handle);
99801e04c3fSmrg}
99901e04c3fSmrg
100001e04c3fSmrgGLboolean GLAPIENTRY
100101e04c3fSmrg_mesa_IsImageHandleResidentARB_no_error(GLuint64 handle)
100201e04c3fSmrg{
100301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
100401e04c3fSmrg   return is_image_handle_resident(ctx, handle);
100501e04c3fSmrg}
100601e04c3fSmrg
100701e04c3fSmrgGLboolean GLAPIENTRY
100801e04c3fSmrg_mesa_IsImageHandleResidentARB(GLuint64 handle)
100901e04c3fSmrg{
101001e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
101101e04c3fSmrg
101201e04c3fSmrg   if (!_mesa_has_ARB_bindless_texture(ctx) ||
101301e04c3fSmrg       !_mesa_has_ARB_shader_image_load_store(ctx)) {
101401e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
101501e04c3fSmrg                  "glIsImageHandleResidentARB(unsupported)");
101601e04c3fSmrg      return GL_FALSE;
101701e04c3fSmrg   }
101801e04c3fSmrg
101901e04c3fSmrg   /* The ARB_bindless_texture spec says:
102001e04c3fSmrg    *
102101e04c3fSmrg    * "The error INVALID_OPERATION will be generated by
102201e04c3fSmrg    *  IsTextureHandleResidentARB and IsImageHandleResidentARB if <handle> is
102301e04c3fSmrg    *  not a valid texture or image handle, respectively."
102401e04c3fSmrg    */
102501e04c3fSmrg   if (!lookup_image_handle(ctx, handle)) {
102601e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
102701e04c3fSmrg                  "glIsImageHandleResidentARB(handle)");
102801e04c3fSmrg      return GL_FALSE;
102901e04c3fSmrg   }
103001e04c3fSmrg
103101e04c3fSmrg   return is_image_handle_resident(ctx, handle);
103201e04c3fSmrg}
1033