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