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