1/*
2 * Copyright © 2017 Valve Corporation.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24#include "glheader.h"
25#include "context.h"
26#include "enums.h"
27#include "imports.h"
28#include "hash.h"
29#include "mtypes.h"
30#include "shaderimage.h"
31#include "teximage.h"
32#include "texobj.h"
33#include "texturebindless.h"
34
35#include "util/hash_table.h"
36
37/**
38 * Return the gl_texture_handle_object for a given 64-bit handle.
39 */
40static struct gl_texture_handle_object *
41lookup_texture_handle(struct gl_context *ctx, GLuint64 id)
42{
43   struct gl_texture_handle_object *texHandleObj;
44
45   mtx_lock(&ctx->Shared->HandlesMutex);
46   texHandleObj = (struct gl_texture_handle_object *)
47      _mesa_hash_table_u64_search(ctx->Shared->TextureHandles, id);
48   mtx_unlock(&ctx->Shared->HandlesMutex);
49
50   return texHandleObj;
51}
52
53/**
54 * Return the gl_image_handle_object for a given 64-bit handle.
55 */
56static struct gl_image_handle_object *
57lookup_image_handle(struct gl_context *ctx, GLuint64 id)
58{
59   struct gl_image_handle_object *imgHandleObj;
60
61   mtx_lock(&ctx->Shared->HandlesMutex);
62   imgHandleObj = (struct gl_image_handle_object *)
63      _mesa_hash_table_u64_search(ctx->Shared->ImageHandles, id);
64   mtx_unlock(&ctx->Shared->HandlesMutex);
65
66   return imgHandleObj;
67}
68
69/**
70 * Delete a texture handle in the shared state.
71 */
72static void
73delete_texture_handle(struct gl_context *ctx, GLuint64 id)
74{
75   mtx_lock(&ctx->Shared->HandlesMutex);
76   _mesa_hash_table_u64_remove(ctx->Shared->TextureHandles, id);
77   mtx_unlock(&ctx->Shared->HandlesMutex);
78
79   ctx->Driver.DeleteTextureHandle(ctx, id);
80}
81
82/**
83 * Delete an image handle in the shared state.
84 */
85static void
86delete_image_handle(struct gl_context *ctx, GLuint64 id)
87{
88   mtx_lock(&ctx->Shared->HandlesMutex);
89   _mesa_hash_table_u64_remove(ctx->Shared->ImageHandles, id);
90   mtx_unlock(&ctx->Shared->HandlesMutex);
91
92   ctx->Driver.DeleteImageHandle(ctx, id);
93}
94
95/**
96 * Return TRUE if the texture handle is resident in the current context.
97 */
98static inline bool
99is_texture_handle_resident(struct gl_context *ctx, GLuint64 handle)
100{
101   return _mesa_hash_table_u64_search(ctx->ResidentTextureHandles,
102                                      handle) != NULL;
103}
104
105/**
106 * Return TRUE if the image handle is resident in the current context.
107 */
108static inline bool
109is_image_handle_resident(struct gl_context *ctx, GLuint64 handle)
110{
111   return _mesa_hash_table_u64_search(ctx->ResidentImageHandles,
112                                      handle) != NULL;
113}
114
115/**
116 * Make a texture handle resident/non-resident in the current context.
117 */
118static void
119make_texture_handle_resident(struct gl_context *ctx,
120                             struct gl_texture_handle_object *texHandleObj,
121                             bool resident)
122{
123   struct gl_sampler_object *sampObj = NULL;
124   struct gl_texture_object *texObj = NULL;
125   GLuint64 handle = texHandleObj->handle;
126
127   if (resident) {
128      assert(!is_texture_handle_resident(ctx, handle));
129
130      _mesa_hash_table_u64_insert(ctx->ResidentTextureHandles, handle,
131                                  texHandleObj);
132
133      ctx->Driver.MakeTextureHandleResident(ctx, handle, GL_TRUE);
134
135      /* Reference the texture object (and the separate sampler if needed) to
136       * be sure it won't be deleted until it is not bound anywhere and there
137       * are no handles using the object that are resident in any context.
138       */
139      _mesa_reference_texobj(&texObj, texHandleObj->texObj);
140      if (texHandleObj->sampObj)
141         _mesa_reference_sampler_object(ctx, &sampObj, texHandleObj->sampObj);
142   } else {
143      assert(is_texture_handle_resident(ctx, handle));
144
145      _mesa_hash_table_u64_remove(ctx->ResidentTextureHandles, handle);
146
147      ctx->Driver.MakeTextureHandleResident(ctx, handle, GL_FALSE);
148
149      /* Unreference the texture object but keep the pointer intact, if
150       * refcount hits zero, the texture and all handles will be deleted.
151       */
152      texObj = texHandleObj->texObj;
153      _mesa_reference_texobj(&texObj, NULL);
154
155      /* Unreference the separate sampler object but keep the pointer intact,
156       * if refcount hits zero, the sampler and all handles will be deleted.
157       */
158      if (texHandleObj->sampObj) {
159         sampObj = texHandleObj->sampObj;
160         _mesa_reference_sampler_object(ctx, &sampObj, NULL);
161      }
162   }
163}
164
165/**
166 * Make an image handle resident/non-resident in the current context.
167 */
168static void
169make_image_handle_resident(struct gl_context *ctx,
170                           struct gl_image_handle_object *imgHandleObj,
171                           GLenum access, bool resident)
172{
173   struct gl_texture_object *texObj = NULL;
174   GLuint64 handle = imgHandleObj->handle;
175
176   if (resident) {
177      assert(!is_image_handle_resident(ctx, handle));
178
179      _mesa_hash_table_u64_insert(ctx->ResidentImageHandles, handle,
180                                  imgHandleObj);
181
182      ctx->Driver.MakeImageHandleResident(ctx, handle, access, GL_TRUE);
183
184      /* Reference the texture object to be sure it won't be deleted until it
185       * is not bound anywhere and there are no handles using the object that
186       * are resident in any context.
187       */
188      _mesa_reference_texobj(&texObj, imgHandleObj->imgObj.TexObj);
189   } else {
190      assert(is_image_handle_resident(ctx, handle));
191
192      _mesa_hash_table_u64_remove(ctx->ResidentImageHandles, handle);
193
194      ctx->Driver.MakeImageHandleResident(ctx, handle, access, GL_FALSE);
195
196      /* Unreference the texture object but keep the pointer intact, if
197       * refcount hits zero, the texture and all handles will be deleted.
198       */
199      texObj = imgHandleObj->imgObj.TexObj;
200      _mesa_reference_texobj(&texObj, NULL);
201   }
202}
203
204static struct gl_texture_handle_object *
205find_texhandleobj(struct gl_texture_object *texObj,
206                  struct gl_sampler_object *sampObj)
207{
208   util_dynarray_foreach(&texObj->SamplerHandles,
209                         struct gl_texture_handle_object *, texHandleObj) {
210      if ((*texHandleObj)->sampObj == sampObj)
211         return *texHandleObj;
212   }
213   return NULL;
214}
215
216static GLuint64
217get_texture_handle(struct gl_context *ctx, struct gl_texture_object *texObj,
218                   struct gl_sampler_object *sampObj)
219{
220   bool separate_sampler = &texObj->Sampler != sampObj;
221   struct gl_texture_handle_object *texHandleObj;
222   GLuint64 handle;
223
224   /* The ARB_bindless_texture spec says:
225    *
226    * "The handle for each texture or texture/sampler pair is unique; the same
227    *  handle will be returned if GetTextureHandleARB is called multiple times
228    *  for the same texture or if GetTextureSamplerHandleARB is called multiple
229    *  times for the same texture/sampler pair."
230    */
231   mtx_lock(&ctx->Shared->HandlesMutex);
232   texHandleObj = find_texhandleobj(texObj, separate_sampler ? sampObj : NULL);
233   if (texHandleObj) {
234      mtx_unlock(&ctx->Shared->HandlesMutex);
235      return texHandleObj->handle;
236   }
237
238   /* Request a new texture handle from the driver. */
239   handle = ctx->Driver.NewTextureHandle(ctx, texObj, sampObj);
240   if (!handle) {
241      mtx_unlock(&ctx->Shared->HandlesMutex);
242      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexture*HandleARB()");
243      return 0;
244   }
245
246   texHandleObj = CALLOC_STRUCT(gl_texture_handle_object);
247   if (!texHandleObj) {
248      mtx_unlock(&ctx->Shared->HandlesMutex);
249      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexture*HandleARB()");
250      return 0;
251   }
252
253   /* Store the handle into the texture object. */
254   texHandleObj->texObj = texObj;
255   texHandleObj->sampObj = separate_sampler ? sampObj : NULL;
256   texHandleObj->handle = handle;
257   util_dynarray_append(&texObj->SamplerHandles,
258                        struct gl_texture_handle_object *, texHandleObj);
259
260   if (separate_sampler) {
261      /* Store the handle into the separate sampler if needed. */
262      util_dynarray_append(&sampObj->Handles,
263                           struct gl_texture_handle_object *, texHandleObj);
264   }
265
266   /* When referenced by one or more handles, texture objects are immutable. */
267   texObj->HandleAllocated = true;
268   if (texObj->Target == GL_TEXTURE_BUFFER)
269      texObj->BufferObject->HandleAllocated = true;
270   sampObj->HandleAllocated = true;
271
272   /* Store the handle in the shared state for all contexts. */
273   _mesa_hash_table_u64_insert(ctx->Shared->TextureHandles, handle,
274                               texHandleObj);
275   mtx_unlock(&ctx->Shared->HandlesMutex);
276
277   return handle;
278}
279
280static struct gl_image_handle_object *
281find_imghandleobj(struct gl_texture_object *texObj, GLint level,
282                  GLboolean layered, GLint layer, GLenum format)
283{
284   util_dynarray_foreach(&texObj->ImageHandles,
285                         struct gl_image_handle_object *, imgHandleObj) {
286      struct gl_image_unit *u = &(*imgHandleObj)->imgObj;
287
288      if (u->TexObj == texObj && u->Level == level && u->Layered == layered &&
289          u->Layer == layer && u->Format == format)
290         return *imgHandleObj;
291   }
292   return NULL;
293}
294
295static GLuint64
296get_image_handle(struct gl_context *ctx, struct gl_texture_object *texObj,
297                 GLint level, GLboolean layered, GLint layer, GLenum format)
298{
299   struct gl_image_handle_object *imgHandleObj;
300   struct gl_image_unit imgObj;
301   GLuint64 handle;
302
303   /* The ARB_bindless_texture spec says:
304    *
305    * "The handle returned for each combination of <texture>, <level>,
306    * <layered>, <layer>, and <format> is unique; the same handle will be
307    * returned if GetImageHandleARB is called multiple times with the same
308    * parameters."
309    */
310   mtx_lock(&ctx->Shared->HandlesMutex);
311   imgHandleObj = find_imghandleobj(texObj, level, layered, layer, format);
312   if (imgHandleObj) {
313      mtx_unlock(&ctx->Shared->HandlesMutex);
314      return imgHandleObj->handle;
315   }
316
317   imgObj.TexObj = texObj; /* weak reference */
318   imgObj.Level = level;
319   imgObj.Access = GL_READ_WRITE;
320   imgObj.Format = format;
321   imgObj._ActualFormat = _mesa_get_shader_image_format(format);
322
323   if (_mesa_tex_target_is_layered(texObj->Target)) {
324      imgObj.Layered = layered;
325      imgObj.Layer = layer;
326      imgObj._Layer = (imgObj.Layered ? 0 : imgObj.Layer);
327   } else {
328      imgObj.Layered = GL_FALSE;
329      imgObj.Layer = 0;
330      imgObj._Layer = 0;
331   }
332
333   /* Request a new image handle from the driver. */
334   handle = ctx->Driver.NewImageHandle(ctx, &imgObj);
335   if (!handle) {
336      mtx_unlock(&ctx->Shared->HandlesMutex);
337      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetImageHandleARB()");
338      return 0;
339   }
340
341   imgHandleObj = CALLOC_STRUCT(gl_image_handle_object);
342   if (!imgHandleObj) {
343      mtx_unlock(&ctx->Shared->HandlesMutex);
344      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetImageHandleARB()");
345      return 0;
346   }
347
348   /* Store the handle into the texture object. */
349   memcpy(&imgHandleObj->imgObj, &imgObj, sizeof(struct gl_image_unit));
350   imgHandleObj->handle = handle;
351   util_dynarray_append(&texObj->ImageHandles,
352                        struct gl_image_handle_object *, imgHandleObj);
353
354   /* When referenced by one or more handles, texture objects are immutable. */
355   texObj->HandleAllocated = true;
356   if (texObj->Target == GL_TEXTURE_BUFFER)
357      texObj->BufferObject->HandleAllocated = true;
358   texObj->Sampler.HandleAllocated = true;
359
360   /* Store the handle in the shared state for all contexts. */
361   _mesa_hash_table_u64_insert(ctx->Shared->ImageHandles, handle, imgHandleObj);
362   mtx_unlock(&ctx->Shared->HandlesMutex);
363
364   return handle;
365}
366
367/**
368 * Init/free per-context resident handles.
369 */
370void
371_mesa_init_resident_handles(struct gl_context *ctx)
372{
373   ctx->ResidentTextureHandles = _mesa_hash_table_u64_create(NULL);
374   ctx->ResidentImageHandles = _mesa_hash_table_u64_create(NULL);
375}
376
377void
378_mesa_free_resident_handles(struct gl_context *ctx)
379{
380   _mesa_hash_table_u64_destroy(ctx->ResidentTextureHandles, NULL);
381   _mesa_hash_table_u64_destroy(ctx->ResidentImageHandles, NULL);
382}
383
384/**
385 * Init/free shared allocated handles.
386 */
387void
388_mesa_init_shared_handles(struct gl_shared_state *shared)
389{
390   shared->TextureHandles = _mesa_hash_table_u64_create(NULL);
391   shared->ImageHandles = _mesa_hash_table_u64_create(NULL);
392   mtx_init(&shared->HandlesMutex, mtx_recursive);
393}
394
395void
396_mesa_free_shared_handles(struct gl_shared_state *shared)
397{
398   if (shared->TextureHandles)
399      _mesa_hash_table_u64_destroy(shared->TextureHandles, NULL);
400
401   if (shared->ImageHandles)
402      _mesa_hash_table_u64_destroy(shared->ImageHandles, NULL);
403
404   mtx_destroy(&shared->HandlesMutex);
405}
406
407/**
408 * Init/free texture/image handles per-texture object.
409 */
410void
411_mesa_init_texture_handles(struct gl_texture_object *texObj)
412{
413   util_dynarray_init(&texObj->SamplerHandles, NULL);
414   util_dynarray_init(&texObj->ImageHandles, NULL);
415}
416
417void
418_mesa_make_texture_handles_non_resident(struct gl_context *ctx,
419                                        struct gl_texture_object *texObj)
420{
421   mtx_lock(&ctx->Shared->HandlesMutex);
422
423   /* Texture handles */
424   util_dynarray_foreach(&texObj->SamplerHandles,
425                         struct gl_texture_handle_object *, texHandleObj) {
426      if (is_texture_handle_resident(ctx, (*texHandleObj)->handle))
427         make_texture_handle_resident(ctx, *texHandleObj, false);
428   }
429
430   /* Image handles */
431   util_dynarray_foreach(&texObj->ImageHandles,
432                         struct gl_image_handle_object *, imgHandleObj) {
433      if (is_image_handle_resident(ctx, (*imgHandleObj)->handle))
434         make_image_handle_resident(ctx, *imgHandleObj, GL_READ_ONLY, false);
435   }
436
437   mtx_unlock(&ctx->Shared->HandlesMutex);
438}
439
440void
441_mesa_delete_texture_handles(struct gl_context *ctx,
442                             struct gl_texture_object *texObj)
443{
444   /* Texture handles */
445   util_dynarray_foreach(&texObj->SamplerHandles,
446                         struct gl_texture_handle_object *, texHandleObj) {
447      struct gl_sampler_object *sampObj = (*texHandleObj)->sampObj;
448
449      if (sampObj) {
450         /* Delete the handle in the separate sampler object. */
451         util_dynarray_delete_unordered(&sampObj->Handles,
452                                        struct gl_texture_handle_object *,
453                                        *texHandleObj);
454      }
455      delete_texture_handle(ctx, (*texHandleObj)->handle);
456      free(*texHandleObj);
457   }
458   util_dynarray_fini(&texObj->SamplerHandles);
459
460   /* Image handles */
461   util_dynarray_foreach(&texObj->ImageHandles,
462                         struct gl_image_handle_object *, imgHandleObj) {
463      delete_image_handle(ctx, (*imgHandleObj)->handle);
464      free(*imgHandleObj);
465   }
466   util_dynarray_fini(&texObj->ImageHandles);
467}
468
469/**
470 * Init/free texture handles per-sampler object.
471 */
472void
473_mesa_init_sampler_handles(struct gl_sampler_object *sampObj)
474{
475   util_dynarray_init(&sampObj->Handles, NULL);
476}
477
478void
479_mesa_delete_sampler_handles(struct gl_context *ctx,
480                             struct gl_sampler_object *sampObj)
481{
482   util_dynarray_foreach(&sampObj->Handles,
483                         struct gl_texture_handle_object *, texHandleObj) {
484      struct gl_texture_object *texObj = (*texHandleObj)->texObj;
485
486      /* Delete the handle in the texture object. */
487      util_dynarray_delete_unordered(&texObj->SamplerHandles,
488                                     struct gl_texture_handle_object *,
489                                     *texHandleObj);
490
491      delete_texture_handle(ctx, (*texHandleObj)->handle);
492      free(*texHandleObj);
493   }
494   util_dynarray_fini(&sampObj->Handles);
495}
496
497static GLboolean
498is_sampler_border_color_valid(struct gl_sampler_object *samp)
499{
500   static const GLfloat valid_float_border_colors[4][4] = {
501      { 0.0, 0.0, 0.0, 0.0 },
502      { 0.0, 0.0, 0.0, 1.0 },
503      { 1.0, 1.0, 1.0, 0.0 },
504      { 1.0, 1.0, 1.0, 1.0 },
505   };
506   static const GLint valid_integer_border_colors[4][4] = {
507      { 0, 0, 0, 0 },
508      { 0, 0, 0, 1 },
509      { 1, 1, 1, 0 },
510      { 1, 1, 1, 1 },
511   };
512   size_t size = sizeof(samp->BorderColor.ui);
513
514   /* The ARB_bindless_texture spec says:
515    *
516    * "The error INVALID_OPERATION is generated if the border color (taken from
517    *  the embedded sampler for GetTextureHandleARB or from the <sampler> for
518    *  GetTextureSamplerHandleARB) is not one of the following allowed values.
519    *  If the texture's base internal format is signed or unsigned integer,
520    *  allowed values are (0,0,0,0), (0,0,0,1), (1,1,1,0), and (1,1,1,1). If
521    *  the base internal format is not integer, allowed values are
522    *  (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
523    *  (1.0,1.0,1.0,1.0)."
524    */
525   if (!memcmp(samp->BorderColor.f, valid_float_border_colors[0], size) ||
526       !memcmp(samp->BorderColor.f, valid_float_border_colors[1], size) ||
527       !memcmp(samp->BorderColor.f, valid_float_border_colors[2], size) ||
528       !memcmp(samp->BorderColor.f, valid_float_border_colors[3], size))
529      return GL_TRUE;
530
531   if (!memcmp(samp->BorderColor.ui, valid_integer_border_colors[0], size) ||
532       !memcmp(samp->BorderColor.ui, valid_integer_border_colors[1], size) ||
533       !memcmp(samp->BorderColor.ui, valid_integer_border_colors[2], size) ||
534       !memcmp(samp->BorderColor.ui, valid_integer_border_colors[3], size))
535      return GL_TRUE;
536
537   return GL_FALSE;
538}
539
540GLuint64 GLAPIENTRY
541_mesa_GetTextureHandleARB_no_error(GLuint texture)
542{
543   struct gl_texture_object *texObj;
544
545   GET_CURRENT_CONTEXT(ctx);
546
547   texObj = _mesa_lookup_texture(ctx, texture);
548   if (!_mesa_is_texture_complete(texObj, &texObj->Sampler))
549      _mesa_test_texobj_completeness(ctx, texObj);
550
551   return get_texture_handle(ctx, texObj, &texObj->Sampler);
552}
553
554GLuint64 GLAPIENTRY
555_mesa_GetTextureHandleARB(GLuint texture)
556{
557   struct gl_texture_object *texObj = NULL;
558
559   GET_CURRENT_CONTEXT(ctx);
560
561   if (!_mesa_has_ARB_bindless_texture(ctx)) {
562      _mesa_error(ctx, GL_INVALID_OPERATION,
563                  "glGetTextureHandleARB(unsupported)");
564      return 0;
565   }
566
567   /* The ARB_bindless_texture spec says:
568    *
569    * "The error INVALID_VALUE is generated by GetTextureHandleARB or
570    *  GetTextureSamplerHandleARB if <texture> is zero or not the name of an
571    *  existing texture object."
572    */
573   if (texture > 0)
574      texObj = _mesa_lookup_texture(ctx, texture);
575
576   if (!texObj) {
577      _mesa_error(ctx, GL_INVALID_VALUE, "glGetTextureHandleARB(texture)");
578      return 0;
579   }
580
581   /* The ARB_bindless_texture spec says:
582    *
583    * "The error INVALID_OPERATION is generated by GetTextureHandleARB or
584    *  GetTextureSamplerHandleARB if the texture object specified by <texture>
585    *  is not complete."
586    */
587   if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
588      _mesa_test_texobj_completeness(ctx, texObj);
589      if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
590         _mesa_error(ctx, GL_INVALID_OPERATION,
591                     "glGetTextureHandleARB(incomplete texture)");
592         return 0;
593      }
594   }
595
596   if (!is_sampler_border_color_valid(&texObj->Sampler)) {
597      _mesa_error(ctx, GL_INVALID_OPERATION,
598                  "glGetTextureHandleARB(invalid border color)");
599      return 0;
600   }
601
602   return get_texture_handle(ctx, texObj, &texObj->Sampler);
603}
604
605GLuint64 GLAPIENTRY
606_mesa_GetTextureSamplerHandleARB_no_error(GLuint texture, GLuint sampler)
607{
608   struct gl_texture_object *texObj;
609   struct gl_sampler_object *sampObj;
610
611   GET_CURRENT_CONTEXT(ctx);
612
613   texObj = _mesa_lookup_texture(ctx, texture);
614   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
615
616   if (!_mesa_is_texture_complete(texObj, sampObj))
617      _mesa_test_texobj_completeness(ctx, texObj);
618
619   return get_texture_handle(ctx, texObj, sampObj);
620}
621
622GLuint64 GLAPIENTRY
623_mesa_GetTextureSamplerHandleARB(GLuint texture, GLuint sampler)
624{
625   struct gl_texture_object *texObj = NULL;
626   struct gl_sampler_object *sampObj;
627
628   GET_CURRENT_CONTEXT(ctx);
629
630   if (!_mesa_has_ARB_bindless_texture(ctx)) {
631      _mesa_error(ctx, GL_INVALID_OPERATION,
632                  "glGetTextureSamplerHandleARB(unsupported)");
633      return 0;
634   }
635
636   /* The ARB_bindless_texture spec says:
637    *
638    * "The error INVALID_VALUE is generated by GetTextureHandleARB or
639    *  GetTextureSamplerHandleARB if <texture> is zero or not the name of an
640    *  existing texture object."
641    */
642   if (texture > 0)
643      texObj = _mesa_lookup_texture(ctx, texture);
644
645   if (!texObj) {
646      _mesa_error(ctx, GL_INVALID_VALUE,
647                  "glGetTextureSamplerHandleARB(texture)");
648      return 0;
649   }
650
651   /* The ARB_bindless_texture spec says:
652    *
653    * "The error INVALID_VALUE is generated by GetTextureSamplerHandleARB if
654    *  <sampler> is zero or is not the name of an existing sampler object."
655    */
656   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
657   if (!sampObj) {
658      _mesa_error(ctx, GL_INVALID_VALUE,
659                  "glGetTextureSamplerHandleARB(sampler)");
660      return 0;
661   }
662
663   /* The ARB_bindless_texture spec says:
664    *
665    * "The error INVALID_OPERATION is generated by GetTextureHandleARB or
666    *  GetTextureSamplerHandleARB if the texture object specified by <texture>
667    *  is not complete."
668    */
669   if (!_mesa_is_texture_complete(texObj, sampObj)) {
670      _mesa_test_texobj_completeness(ctx, texObj);
671      if (!_mesa_is_texture_complete(texObj, sampObj)) {
672         _mesa_error(ctx, GL_INVALID_OPERATION,
673                     "glGetTextureSamplerHandleARB(incomplete texture)");
674         return 0;
675      }
676   }
677
678   if (!is_sampler_border_color_valid(sampObj)) {
679      _mesa_error(ctx, GL_INVALID_OPERATION,
680                  "glGetTextureSamplerHandleARB(invalid border color)");
681      return 0;
682   }
683
684   return get_texture_handle(ctx, texObj, sampObj);
685}
686
687void GLAPIENTRY
688_mesa_MakeTextureHandleResidentARB_no_error(GLuint64 handle)
689{
690   struct gl_texture_handle_object *texHandleObj;
691
692   GET_CURRENT_CONTEXT(ctx);
693
694   texHandleObj = lookup_texture_handle(ctx, handle);
695   make_texture_handle_resident(ctx, texHandleObj, true);
696}
697
698void GLAPIENTRY
699_mesa_MakeTextureHandleResidentARB(GLuint64 handle)
700{
701   struct gl_texture_handle_object *texHandleObj;
702
703   GET_CURRENT_CONTEXT(ctx);
704
705   if (!_mesa_has_ARB_bindless_texture(ctx)) {
706      _mesa_error(ctx, GL_INVALID_OPERATION,
707                  "glMakeTextureHandleResidentARB(unsupported)");
708      return;
709   }
710
711   /* The ARB_bindless_texture spec says:
712    *
713    * "The error INVALID_OPERATION is generated by MakeTextureHandleResidentARB
714    *  if <handle> is not a valid texture handle, or if <handle> is already
715    *  resident in the current GL context."
716    */
717   texHandleObj = lookup_texture_handle(ctx, handle);
718   if (!texHandleObj) {
719      _mesa_error(ctx, GL_INVALID_OPERATION,
720                  "glMakeTextureHandleResidentARB(handle)");
721      return;
722   }
723
724   if (is_texture_handle_resident(ctx, handle)) {
725      _mesa_error(ctx, GL_INVALID_OPERATION,
726                  "glMakeTextureHandleResidentARB(already resident)");
727      return;
728   }
729
730   make_texture_handle_resident(ctx, texHandleObj, true);
731}
732
733void GLAPIENTRY
734_mesa_MakeTextureHandleNonResidentARB_no_error(GLuint64 handle)
735{
736   struct gl_texture_handle_object *texHandleObj;
737
738   GET_CURRENT_CONTEXT(ctx);
739
740   texHandleObj = lookup_texture_handle(ctx, handle);
741   make_texture_handle_resident(ctx, texHandleObj, false);
742}
743
744void GLAPIENTRY
745_mesa_MakeTextureHandleNonResidentARB(GLuint64 handle)
746{
747   struct gl_texture_handle_object *texHandleObj;
748
749   GET_CURRENT_CONTEXT(ctx);
750
751   if (!_mesa_has_ARB_bindless_texture(ctx)) {
752      _mesa_error(ctx, GL_INVALID_OPERATION,
753                  "glMakeTextureHandleNonResidentARB(unsupported)");
754      return;
755   }
756
757   /* The ARB_bindless_texture spec says:
758    *
759    * "The error INVALID_OPERATION is generated by
760    *  MakeTextureHandleNonResidentARB if <handle> is not a valid texture
761    *  handle, or if <handle> is not resident in the current GL context."
762    */
763   texHandleObj = lookup_texture_handle(ctx, handle);
764   if (!texHandleObj) {
765      _mesa_error(ctx, GL_INVALID_OPERATION,
766                  "glMakeTextureHandleNonResidentARB(handle)");
767      return;
768   }
769
770   if (!is_texture_handle_resident(ctx, handle)) {
771      _mesa_error(ctx, GL_INVALID_OPERATION,
772                  "glMakeTextureHandleNonResidentARB(not resident)");
773      return;
774   }
775
776   make_texture_handle_resident(ctx, texHandleObj, false);
777}
778
779GLuint64 GLAPIENTRY
780_mesa_GetImageHandleARB_no_error(GLuint texture, GLint level, GLboolean layered,
781                                 GLint layer, GLenum format)
782{
783   struct gl_texture_object *texObj;
784
785   GET_CURRENT_CONTEXT(ctx);
786
787   texObj = _mesa_lookup_texture(ctx, texture);
788   if (!_mesa_is_texture_complete(texObj, &texObj->Sampler))
789      _mesa_test_texobj_completeness(ctx, texObj);
790
791   return get_image_handle(ctx, texObj, level, layered, layer, format);
792}
793
794GLuint64 GLAPIENTRY
795_mesa_GetImageHandleARB(GLuint texture, GLint level, GLboolean layered,
796                        GLint layer, GLenum format)
797{
798   struct gl_texture_object *texObj = NULL;
799
800   GET_CURRENT_CONTEXT(ctx);
801
802   if (!_mesa_has_ARB_bindless_texture(ctx) ||
803       !_mesa_has_ARB_shader_image_load_store(ctx)) {
804      _mesa_error(ctx, GL_INVALID_OPERATION,
805                  "glGetImageHandleARB(unsupported)");
806      return 0;
807   }
808
809   /* The ARB_bindless_texture spec says:
810    *
811    * "The error INVALID_VALUE is generated by GetImageHandleARB if <texture>
812    *  is zero or not the name of an existing texture object, if the image for
813    *  <level> does not existing in <texture>, or if <layered> is FALSE and
814    *  <layer> is greater than or equal to the number of layers in the image at
815    *  <level>."
816    */
817   if (texture > 0)
818      texObj = _mesa_lookup_texture(ctx, texture);
819
820   if (!texObj) {
821      _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(texture)");
822      return 0;
823   }
824
825   if (level < 0 || level >= _mesa_max_texture_levels(ctx, texObj->Target)) {
826      _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(level)");
827      return 0;
828   }
829
830   if (!layered && layer > _mesa_get_texture_layers(texObj, level)) {
831      _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(layer)");
832      return 0;
833   }
834
835   if (!_mesa_is_shader_image_format_supported(ctx, format)) {
836      _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(format)");
837      return 0;
838   }
839
840   /* The ARB_bindless_texture spec says:
841    *
842    * "The error INVALID_OPERATION is generated by GetImageHandleARB if the
843    *  texture object <texture> is not complete or if <layered> is TRUE and
844    *  <texture> is not a three-dimensional, one-dimensional array, two
845    *  dimensional array, cube map, or cube map array texture."
846    */
847   if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
848      _mesa_test_texobj_completeness(ctx, texObj);
849      if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
850         _mesa_error(ctx, GL_INVALID_OPERATION,
851                     "glGetImageHandleARB(incomplete texture)");
852         return 0;
853      }
854   }
855
856   if (layered && !_mesa_tex_target_is_layered(texObj->Target)) {
857      _mesa_error(ctx, GL_INVALID_OPERATION,
858                  "glGetImageHandleARB(not layered)");
859      return 0;
860   }
861
862   return get_image_handle(ctx, texObj, level, layered, layer, format);
863}
864
865void GLAPIENTRY
866_mesa_MakeImageHandleResidentARB_no_error(GLuint64 handle, GLenum access)
867{
868   struct gl_image_handle_object *imgHandleObj;
869
870   GET_CURRENT_CONTEXT(ctx);
871
872   imgHandleObj = lookup_image_handle(ctx, handle);
873   make_image_handle_resident(ctx, imgHandleObj, access, true);
874}
875
876void GLAPIENTRY
877_mesa_MakeImageHandleResidentARB(GLuint64 handle, GLenum access)
878{
879   struct gl_image_handle_object *imgHandleObj;
880
881   GET_CURRENT_CONTEXT(ctx);
882
883   if (!_mesa_has_ARB_bindless_texture(ctx) ||
884       !_mesa_has_ARB_shader_image_load_store(ctx)) {
885      _mesa_error(ctx, GL_INVALID_OPERATION,
886                  "glMakeImageHandleResidentARB(unsupported)");
887      return;
888   }
889
890   if (access != GL_READ_ONLY &&
891       access != GL_WRITE_ONLY &&
892       access != GL_READ_WRITE) {
893      _mesa_error(ctx, GL_INVALID_ENUM,
894                  "glMakeImageHandleResidentARB(access)");
895      return;
896   }
897
898   /* The ARB_bindless_texture spec says:
899    *
900    * "The error INVALID_OPERATION is generated by MakeImageHandleResidentARB
901    *  if <handle> is not a valid image handle, or if <handle> is already
902    *  resident in the current GL context."
903    */
904   imgHandleObj = lookup_image_handle(ctx, handle);
905   if (!imgHandleObj) {
906      _mesa_error(ctx, GL_INVALID_OPERATION,
907                  "glMakeImageHandleResidentARB(handle)");
908      return;
909   }
910
911   if (is_image_handle_resident(ctx, handle)) {
912      _mesa_error(ctx, GL_INVALID_OPERATION,
913                  "glMakeImageHandleResidentARB(already resident)");
914      return;
915   }
916
917   make_image_handle_resident(ctx, imgHandleObj, access, true);
918}
919
920void GLAPIENTRY
921_mesa_MakeImageHandleNonResidentARB_no_error(GLuint64 handle)
922{
923   struct gl_image_handle_object *imgHandleObj;
924
925   GET_CURRENT_CONTEXT(ctx);
926
927   imgHandleObj = lookup_image_handle(ctx, handle);
928   make_image_handle_resident(ctx, imgHandleObj, GL_READ_ONLY, false);
929}
930
931void GLAPIENTRY
932_mesa_MakeImageHandleNonResidentARB(GLuint64 handle)
933{
934   struct gl_image_handle_object *imgHandleObj;
935
936   GET_CURRENT_CONTEXT(ctx);
937
938   if (!_mesa_has_ARB_bindless_texture(ctx) ||
939       !_mesa_has_ARB_shader_image_load_store(ctx)) {
940      _mesa_error(ctx, GL_INVALID_OPERATION,
941                  "glMakeImageHandleNonResidentARB(unsupported)");
942      return;
943   }
944
945   /* The ARB_bindless_texture spec says:
946    *
947    * "The error INVALID_OPERATION is generated by
948    *  MakeImageHandleNonResidentARB if <handle> is not a valid image handle,
949    *  or if <handle> is not resident in the current GL context."
950    */
951   imgHandleObj = lookup_image_handle(ctx, handle);
952   if (!imgHandleObj) {
953      _mesa_error(ctx, GL_INVALID_OPERATION,
954                  "glMakeImageHandleNonResidentARB(handle)");
955      return;
956   }
957
958   if (!is_image_handle_resident(ctx, handle)) {
959      _mesa_error(ctx, GL_INVALID_OPERATION,
960                  "glMakeImageHandleNonResidentARB(not resident)");
961      return;
962   }
963
964   make_image_handle_resident(ctx, imgHandleObj, GL_READ_ONLY, false);
965}
966
967GLboolean GLAPIENTRY
968_mesa_IsTextureHandleResidentARB_no_error(GLuint64 handle)
969{
970   GET_CURRENT_CONTEXT(ctx);
971   return is_texture_handle_resident(ctx, handle);
972}
973
974GLboolean GLAPIENTRY
975_mesa_IsTextureHandleResidentARB(GLuint64 handle)
976{
977   GET_CURRENT_CONTEXT(ctx);
978
979   if (!_mesa_has_ARB_bindless_texture(ctx)) {
980      _mesa_error(ctx, GL_INVALID_OPERATION,
981                  "glIsTextureHandleResidentARB(unsupported)");
982      return GL_FALSE;
983   }
984
985   /* The ARB_bindless_texture spec says:
986    *
987    * "The error INVALID_OPERATION will be generated by
988    *  IsTextureHandleResidentARB and IsImageHandleResidentARB if <handle> is
989    *  not a valid texture or image handle, respectively."
990    */
991   if (!lookup_texture_handle(ctx, handle)) {
992      _mesa_error(ctx, GL_INVALID_OPERATION,
993                  "glIsTextureHandleResidentARB(handle)");
994      return GL_FALSE;
995   }
996
997   return is_texture_handle_resident(ctx, handle);
998}
999
1000GLboolean GLAPIENTRY
1001_mesa_IsImageHandleResidentARB_no_error(GLuint64 handle)
1002{
1003   GET_CURRENT_CONTEXT(ctx);
1004   return is_image_handle_resident(ctx, handle);
1005}
1006
1007GLboolean GLAPIENTRY
1008_mesa_IsImageHandleResidentARB(GLuint64 handle)
1009{
1010   GET_CURRENT_CONTEXT(ctx);
1011
1012   if (!_mesa_has_ARB_bindless_texture(ctx) ||
1013       !_mesa_has_ARB_shader_image_load_store(ctx)) {
1014      _mesa_error(ctx, GL_INVALID_OPERATION,
1015                  "glIsImageHandleResidentARB(unsupported)");
1016      return GL_FALSE;
1017   }
1018
1019   /* The ARB_bindless_texture spec says:
1020    *
1021    * "The error INVALID_OPERATION will be generated by
1022    *  IsTextureHandleResidentARB and IsImageHandleResidentARB if <handle> is
1023    *  not a valid texture or image handle, respectively."
1024    */
1025   if (!lookup_image_handle(ctx, handle)) {
1026      _mesa_error(ctx, GL_INVALID_OPERATION,
1027                  "glIsImageHandleResidentARB(handle)");
1028      return GL_FALSE;
1029   }
1030
1031   return is_image_handle_resident(ctx, handle);
1032}
1033