• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2016 Red Hat.
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 "macros.h"
25 #include "mtypes.h"
26 #include "bufferobj.h"
27 #include "context.h"
28 #include "enums.h"
29 #include "externalobjects.h"
30 #include "teximage.h"
31 #include "texobj.h"
32 #include "glformats.h"
33 #include "texstorage.h"
34 #include "util/u_memory.h"
35 
36 #include "pipe/p_context.h"
37 #include "pipe/p_screen.h"
38 #include "api_exec_decl.h"
39 
40 #include "state_tracker/st_cb_bitmap.h"
41 #include "state_tracker/st_texture.h"
42 
43 struct st_context;
44 
45 #include "frontend/drm_driver.h"
46 #ifdef HAVE_LIBDRM
47 #include "drm-uapi/drm_fourcc.h"
48 #endif
49 
50 static struct gl_memory_object *
memoryobj_alloc(struct gl_context * ctx,GLuint name)51 memoryobj_alloc(struct gl_context *ctx, GLuint name)
52 {
53    struct gl_memory_object *obj = CALLOC_STRUCT(gl_memory_object);
54    if (!obj)
55       return NULL;
56 
57    obj->Name = name;
58    obj->Dedicated = GL_FALSE;
59    return obj;
60 }
61 
62 static void
import_memoryobj_fd(struct gl_context * ctx,struct gl_memory_object * obj,GLuint64 size,int fd)63 import_memoryobj_fd(struct gl_context *ctx,
64                     struct gl_memory_object *obj,
65                     GLuint64 size,
66                     int fd)
67 {
68 #if !defined(_WIN32)
69    struct pipe_screen *screen = ctx->pipe->screen;
70    struct winsys_handle whandle = {
71       .type = WINSYS_HANDLE_TYPE_FD,
72       .handle = fd,
73 #ifdef HAVE_LIBDRM
74       .modifier = DRM_FORMAT_MOD_INVALID,
75 #endif
76    };
77 
78    obj->memory = screen->memobj_create_from_handle(screen,
79                                                    &whandle,
80                                                    obj->Dedicated);
81 
82    /* We own fd, but we no longer need it. So get rid of it */
83    close(fd);
84 #endif
85 }
86 
87 static void
import_memoryobj_win32(struct gl_context * ctx,struct gl_memory_object * obj,GLuint64 size,void * handle,const void * name)88 import_memoryobj_win32(struct gl_context *ctx,
89                        struct gl_memory_object *obj,
90                        GLuint64 size,
91                        void *handle,
92                        const void *name)
93 {
94    struct pipe_screen *screen = ctx->pipe->screen;
95    struct winsys_handle whandle = {
96       .type = handle ? WINSYS_HANDLE_TYPE_WIN32_HANDLE : WINSYS_HANDLE_TYPE_WIN32_NAME,
97 #ifdef _WIN32
98       .handle = handle,
99 #else
100       .handle = 0,
101 #endif
102 #ifdef HAVE_LIBDRM
103       .modifier = DRM_FORMAT_MOD_INVALID,
104 #endif
105       .name = name,
106    };
107 
108    obj->memory = screen->memobj_create_from_handle(screen,
109                                                    &whandle,
110                                                    obj->Dedicated);
111 }
112 
113 /**
114  * Delete a memory object.
115  * Not removed from hash table here.
116  */
117 void
_mesa_delete_memory_object(struct gl_context * ctx,struct gl_memory_object * memObj)118 _mesa_delete_memory_object(struct gl_context *ctx,
119                            struct gl_memory_object *memObj)
120 {
121    struct pipe_screen *screen = ctx->pipe->screen;
122    if (memObj->memory)
123       screen->memobj_destroy(screen, memObj->memory);
124    FREE(memObj);
125 }
126 
127 void GLAPIENTRY
_mesa_DeleteMemoryObjectsEXT(GLsizei n,const GLuint * memoryObjects)128 _mesa_DeleteMemoryObjectsEXT(GLsizei n, const GLuint *memoryObjects)
129 {
130    GET_CURRENT_CONTEXT(ctx);
131 
132    if (MESA_VERBOSE & (VERBOSE_API)) {
133       _mesa_debug(ctx, "glDeleteMemoryObjectsEXT(%d, %p)\n", n,
134                   memoryObjects);
135    }
136 
137    if (!ctx->Extensions.EXT_memory_object) {
138       _mesa_error(ctx, GL_INVALID_OPERATION,
139                   "glDeleteMemoryObjectsEXT(unsupported)");
140       return;
141    }
142 
143    if (n < 0) {
144       _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteMemoryObjectsEXT(n < 0)");
145       return;
146    }
147 
148    if (!memoryObjects)
149       return;
150 
151    _mesa_HashLockMutex(ctx->Shared->MemoryObjects);
152    for (GLint i = 0; i < n; i++) {
153       if (memoryObjects[i] > 0) {
154          struct gl_memory_object *delObj
155             = _mesa_lookup_memory_object_locked(ctx, memoryObjects[i]);
156 
157          if (delObj) {
158             _mesa_HashRemoveLocked(ctx->Shared->MemoryObjects,
159                                    memoryObjects[i]);
160             _mesa_delete_memory_object(ctx, delObj);
161          }
162       }
163    }
164    _mesa_HashUnlockMutex(ctx->Shared->MemoryObjects);
165 }
166 
167 GLboolean GLAPIENTRY
_mesa_IsMemoryObjectEXT(GLuint memoryObject)168 _mesa_IsMemoryObjectEXT(GLuint memoryObject)
169 {
170    GET_CURRENT_CONTEXT(ctx);
171 
172    if (!ctx->Extensions.EXT_memory_object) {
173       _mesa_error(ctx, GL_INVALID_OPERATION,
174                   "glIsMemoryObjectEXT(unsupported)");
175       return GL_FALSE;
176    }
177 
178    struct gl_memory_object *obj =
179       _mesa_lookup_memory_object(ctx, memoryObject);
180 
181    return obj ? GL_TRUE : GL_FALSE;
182 }
183 
184 void GLAPIENTRY
_mesa_CreateMemoryObjectsEXT(GLsizei n,GLuint * memoryObjects)185 _mesa_CreateMemoryObjectsEXT(GLsizei n, GLuint *memoryObjects)
186 {
187    GET_CURRENT_CONTEXT(ctx);
188 
189    const char *func = "glCreateMemoryObjectsEXT";
190 
191    if (MESA_VERBOSE & (VERBOSE_API))
192       _mesa_debug(ctx, "%s(%d, %p)", func, n, memoryObjects);
193 
194    if (!ctx->Extensions.EXT_memory_object) {
195       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
196       return;
197    }
198 
199    if (n < 0) {
200       _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
201       return;
202    }
203 
204    if (!memoryObjects)
205       return;
206 
207    _mesa_HashLockMutex(ctx->Shared->MemoryObjects);
208    if (_mesa_HashFindFreeKeys(ctx->Shared->MemoryObjects, memoryObjects, n)) {
209       for (GLsizei i = 0; i < n; i++) {
210          struct gl_memory_object *memObj;
211 
212          /* allocate memory object */
213          memObj = memoryobj_alloc(ctx, memoryObjects[i]);
214          if (!memObj) {
215             _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s()", func);
216             _mesa_HashUnlockMutex(ctx->Shared->MemoryObjects);
217             return;
218          }
219 
220          /* insert into hash table */
221          _mesa_HashInsertLocked(ctx->Shared->MemoryObjects,
222                                 memoryObjects[i],
223                                 memObj, true);
224       }
225    }
226 
227    _mesa_HashUnlockMutex(ctx->Shared->MemoryObjects);
228 }
229 
230 void GLAPIENTRY
_mesa_MemoryObjectParameterivEXT(GLuint memoryObject,GLenum pname,const GLint * params)231 _mesa_MemoryObjectParameterivEXT(GLuint memoryObject,
232                                  GLenum pname,
233                                  const GLint *params)
234 {
235    GET_CURRENT_CONTEXT(ctx);
236    struct gl_memory_object *memObj;
237 
238    const char *func = "glMemoryObjectParameterivEXT";
239 
240    if (!ctx->Extensions.EXT_memory_object) {
241       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
242       return;
243    }
244 
245    memObj = _mesa_lookup_memory_object(ctx, memoryObject);
246    if (!memObj)
247       return;
248 
249    if (memObj->Immutable) {
250       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(memoryObject is immutable", func);
251       return;
252    }
253 
254    switch (pname) {
255    case GL_DEDICATED_MEMORY_OBJECT_EXT:
256       memObj->Dedicated = (GLboolean) params[0];
257       break;
258    case GL_PROTECTED_MEMORY_OBJECT_EXT:
259       /* EXT_protected_textures not supported */
260       goto invalid_pname;
261    default:
262       goto invalid_pname;
263    }
264    return;
265 
266 invalid_pname:
267    _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
268 }
269 
270 void GLAPIENTRY
_mesa_GetMemoryObjectParameterivEXT(GLuint memoryObject,GLenum pname,GLint * params)271 _mesa_GetMemoryObjectParameterivEXT(GLuint memoryObject,
272                                     GLenum pname,
273                                     GLint *params)
274 {
275    GET_CURRENT_CONTEXT(ctx);
276    struct gl_memory_object *memObj;
277 
278    const char *func = "glMemoryObjectParameterivEXT";
279 
280    if (!ctx->Extensions.EXT_memory_object) {
281       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
282       return;
283    }
284 
285    memObj = _mesa_lookup_memory_object(ctx, memoryObject);
286    if (!memObj)
287       return;
288 
289    switch (pname) {
290       case GL_DEDICATED_MEMORY_OBJECT_EXT:
291          *params = (GLint) memObj->Dedicated;
292          break;
293       case GL_PROTECTED_MEMORY_OBJECT_EXT:
294          /* EXT_protected_textures not supported */
295          goto invalid_pname;
296       default:
297          goto invalid_pname;
298    }
299    return;
300 
301 invalid_pname:
302    _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
303 }
304 
305 static struct gl_memory_object *
lookup_memory_object_err(struct gl_context * ctx,unsigned memory,const char * func)306 lookup_memory_object_err(struct gl_context *ctx, unsigned memory,
307                          const char* func)
308 {
309    if (memory == 0) {
310       _mesa_error(ctx, GL_INVALID_VALUE, "%s(memory=0)", func);
311       return NULL;
312    }
313 
314    struct gl_memory_object *memObj = _mesa_lookup_memory_object(ctx, memory);
315    if (!memObj)
316       return NULL;
317 
318    if (!memObj->Immutable) {
319       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no associated memory)",
320                   func);
321       return NULL;
322    }
323 
324    return memObj;
325 }
326 
327 /**
328  * Helper used by _mesa_TexStorageMem1/2/3DEXT().
329  */
330 static void
texstorage_memory(GLuint dims,GLenum target,GLsizei levels,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei depth,GLuint memory,GLuint64 offset,const char * func)331 texstorage_memory(GLuint dims, GLenum target, GLsizei levels,
332                   GLenum internalFormat, GLsizei width, GLsizei height,
333                   GLsizei depth, GLuint memory, GLuint64 offset,
334                   const char *func)
335 {
336    struct gl_texture_object *texObj;
337    struct gl_memory_object *memObj;
338 
339    GET_CURRENT_CONTEXT(ctx);
340 
341    if (!ctx->Extensions.EXT_memory_object) {
342       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
343       return;
344    }
345 
346    if (!_mesa_is_legal_tex_storage_target(ctx, dims, target)) {
347       _mesa_error(ctx, GL_INVALID_ENUM,
348                   "%s(illegal target=%s)",
349                   func, _mesa_enum_to_string(target));
350       return;
351    }
352 
353    /* Check the format to make sure it is sized. */
354    if (!_mesa_is_legal_tex_storage_format(ctx, internalFormat)) {
355       _mesa_error(ctx, GL_INVALID_ENUM,
356                   "%s(internalformat = %s)", func,
357                   _mesa_enum_to_string(internalFormat));
358       return;
359    }
360 
361    texObj = _mesa_get_current_tex_object(ctx, target);
362    if (!texObj)
363       return;
364 
365    memObj = lookup_memory_object_err(ctx, memory, func);
366    if (!memObj)
367       return;
368 
369    _mesa_texture_storage_memory(ctx, dims, texObj, memObj, target,
370                                 levels, internalFormat,
371                                 width, height, depth, offset, false);
372 }
373 
374 static void
texstorage_memory_ms(GLuint dims,GLenum target,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei depth,GLboolean fixedSampleLocations,GLuint memory,GLuint64 offset,const char * func)375 texstorage_memory_ms(GLuint dims, GLenum target, GLsizei samples,
376                      GLenum internalFormat, GLsizei width, GLsizei height,
377                      GLsizei depth, GLboolean fixedSampleLocations,
378                      GLuint memory, GLuint64 offset, const char* func)
379 {
380    struct gl_texture_object *texObj;
381    struct gl_memory_object *memObj;
382 
383    GET_CURRENT_CONTEXT(ctx);
384 
385    if (!ctx->Extensions.EXT_memory_object) {
386       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
387       return;
388    }
389 
390    texObj = _mesa_get_current_tex_object(ctx, target);
391    if (!texObj)
392       return;
393 
394    memObj = lookup_memory_object_err(ctx, memory, func);
395    if (!memObj)
396       return;
397 
398    _mesa_texture_storage_ms_memory(ctx, dims, texObj, memObj, target, samples,
399                                    internalFormat, width, height, depth,
400                                    fixedSampleLocations, offset, func);
401 }
402 
403 /**
404  * Helper used by _mesa_TextureStorageMem1/2/3DEXT().
405  */
406 static void
texturestorage_memory(GLuint dims,GLuint texture,GLsizei levels,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei depth,GLuint memory,GLuint64 offset,const char * func)407 texturestorage_memory(GLuint dims, GLuint texture, GLsizei levels,
408                       GLenum internalFormat, GLsizei width, GLsizei height,
409                       GLsizei depth, GLuint memory, GLuint64 offset,
410                       const char *func)
411 {
412    struct gl_texture_object *texObj;
413    struct gl_memory_object *memObj;
414 
415    GET_CURRENT_CONTEXT(ctx);
416 
417    if (!ctx->Extensions.EXT_memory_object) {
418       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
419       return;
420    }
421 
422    /* Check the format to make sure it is sized. */
423    if (!_mesa_is_legal_tex_storage_format(ctx, internalFormat)) {
424       _mesa_error(ctx, GL_INVALID_ENUM,
425                   "%s(internalformat = %s)", func,
426                   _mesa_enum_to_string(internalFormat));
427       return;
428    }
429 
430    texObj = _mesa_lookup_texture(ctx, texture);
431    if (!texObj)
432       return;
433 
434    if (!_mesa_is_legal_tex_storage_target(ctx, dims, texObj->Target)) {
435       _mesa_error(ctx, GL_INVALID_OPERATION,
436                   "%s(illegal target=%s)", func,
437                   _mesa_enum_to_string(texObj->Target));
438       return;
439    }
440 
441    memObj = lookup_memory_object_err(ctx, memory, func);
442    if (!memObj)
443       return;
444 
445    _mesa_texture_storage_memory(ctx, dims, texObj, memObj, texObj->Target,
446                                 levels, internalFormat,
447                                 width, height, depth, offset, true);
448 }
449 
450 static void
texturestorage_memory_ms(GLuint dims,GLuint texture,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei depth,GLboolean fixedSampleLocations,GLuint memory,GLuint64 offset,const char * func)451 texturestorage_memory_ms(GLuint dims, GLuint texture, GLsizei samples,
452                          GLenum internalFormat, GLsizei width, GLsizei height,
453                          GLsizei depth, GLboolean fixedSampleLocations,
454                          GLuint memory, GLuint64 offset, const char* func)
455 {
456    struct gl_texture_object *texObj;
457    struct gl_memory_object *memObj;
458 
459    GET_CURRENT_CONTEXT(ctx);
460 
461    if (!ctx->Extensions.EXT_memory_object) {
462       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
463       return;
464    }
465 
466    texObj = _mesa_lookup_texture(ctx, texture);
467    if (!texObj)
468       return;
469 
470    memObj = lookup_memory_object_err(ctx, memory, func);
471    if (!memObj)
472       return;
473 
474    _mesa_texture_storage_ms_memory(ctx, dims, texObj, memObj, texObj->Target,
475                                    samples, internalFormat, width, height,
476                                    depth, fixedSampleLocations, offset, func);
477 }
478 
479 void GLAPIENTRY
_mesa_TexStorageMem2DEXT(GLenum target,GLsizei levels,GLenum internalFormat,GLsizei width,GLsizei height,GLuint memory,GLuint64 offset)480 _mesa_TexStorageMem2DEXT(GLenum target,
481                          GLsizei levels,
482                          GLenum internalFormat,
483                          GLsizei width,
484                          GLsizei height,
485                          GLuint memory,
486                          GLuint64 offset)
487 {
488    texstorage_memory(2, target, levels, internalFormat, width, height, 1,
489                      memory, offset, "glTexStorageMem2DEXT");
490 }
491 
492 void GLAPIENTRY
_mesa_TexStorageMem2DMultisampleEXT(GLenum target,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height,GLboolean fixedSampleLocations,GLuint memory,GLuint64 offset)493 _mesa_TexStorageMem2DMultisampleEXT(GLenum target,
494                                     GLsizei samples,
495                                     GLenum internalFormat,
496                                     GLsizei width,
497                                     GLsizei height,
498                                     GLboolean fixedSampleLocations,
499                                     GLuint memory,
500                                     GLuint64 offset)
501 {
502    texstorage_memory_ms(2, target, samples, internalFormat, width, height, 1,
503                         fixedSampleLocations, memory, offset,
504                         "glTexStorageMem2DMultisampleEXT");
505 }
506 
507 void GLAPIENTRY
_mesa_TexStorageMem3DEXT(GLenum target,GLsizei levels,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei depth,GLuint memory,GLuint64 offset)508 _mesa_TexStorageMem3DEXT(GLenum target,
509                          GLsizei levels,
510                          GLenum internalFormat,
511                          GLsizei width,
512                          GLsizei height,
513                          GLsizei depth,
514                          GLuint memory,
515                          GLuint64 offset)
516 {
517    texstorage_memory(3, target, levels, internalFormat, width, height, depth,
518                      memory, offset, "glTexStorageMem3DEXT");
519 }
520 
521 void GLAPIENTRY
_mesa_TexStorageMem3DMultisampleEXT(GLenum target,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei depth,GLboolean fixedSampleLocations,GLuint memory,GLuint64 offset)522 _mesa_TexStorageMem3DMultisampleEXT(GLenum target,
523                                     GLsizei samples,
524                                     GLenum internalFormat,
525                                     GLsizei width,
526                                     GLsizei height,
527                                     GLsizei depth,
528                                     GLboolean fixedSampleLocations,
529                                     GLuint memory,
530                                     GLuint64 offset)
531 {
532    texstorage_memory_ms(3, target, samples, internalFormat, width, height,
533                         depth, fixedSampleLocations, memory, offset,
534                         "glTexStorageMem3DMultisampleEXT");
535 }
536 
537 void GLAPIENTRY
_mesa_TextureStorageMem2DEXT(GLuint texture,GLsizei levels,GLenum internalFormat,GLsizei width,GLsizei height,GLuint memory,GLuint64 offset)538 _mesa_TextureStorageMem2DEXT(GLuint texture,
539                              GLsizei levels,
540                              GLenum internalFormat,
541                              GLsizei width,
542                              GLsizei height,
543                              GLuint memory,
544                              GLuint64 offset)
545 {
546    texturestorage_memory(2, texture, levels, internalFormat, width, height, 1,
547                          memory, offset, "glTexureStorageMem2DEXT");
548 }
549 
550 void GLAPIENTRY
_mesa_TextureStorageMem2DMultisampleEXT(GLuint texture,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height,GLboolean fixedSampleLocations,GLuint memory,GLuint64 offset)551 _mesa_TextureStorageMem2DMultisampleEXT(GLuint texture,
552                                         GLsizei samples,
553                                         GLenum internalFormat,
554                                         GLsizei width,
555                                         GLsizei height,
556                                         GLboolean fixedSampleLocations,
557                                         GLuint memory,
558                                         GLuint64 offset)
559 {
560    texturestorage_memory_ms(2, texture, samples, internalFormat, width, height,
561                             1, fixedSampleLocations, memory, offset,
562                             "glTextureStorageMem2DMultisampleEXT");
563 }
564 
565 void GLAPIENTRY
_mesa_TextureStorageMem3DEXT(GLuint texture,GLsizei levels,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei depth,GLuint memory,GLuint64 offset)566 _mesa_TextureStorageMem3DEXT(GLuint texture,
567                              GLsizei levels,
568                              GLenum internalFormat,
569                              GLsizei width,
570                              GLsizei height,
571                              GLsizei depth,
572                              GLuint memory,
573                              GLuint64 offset)
574 {
575    texturestorage_memory(3, texture, levels, internalFormat, width, height,
576                          depth, memory, offset, "glTextureStorageMem3DEXT");
577 }
578 
579 void GLAPIENTRY
_mesa_TextureStorageMem3DMultisampleEXT(GLuint texture,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei depth,GLboolean fixedSampleLocations,GLuint memory,GLuint64 offset)580 _mesa_TextureStorageMem3DMultisampleEXT(GLuint texture,
581                                         GLsizei samples,
582                                         GLenum internalFormat,
583                                         GLsizei width,
584                                         GLsizei height,
585                                         GLsizei depth,
586                                         GLboolean fixedSampleLocations,
587                                         GLuint memory,
588                                         GLuint64 offset)
589 {
590    texturestorage_memory_ms(3, texture, samples, internalFormat, width, height,
591                             depth, fixedSampleLocations, memory, offset,
592                             "glTextureStorageMem3DMultisampleEXT");
593 }
594 
595 void GLAPIENTRY
_mesa_TexStorageMem1DEXT(GLenum target,GLsizei levels,GLenum internalFormat,GLsizei width,GLuint memory,GLuint64 offset)596 _mesa_TexStorageMem1DEXT(GLenum target,
597                          GLsizei levels,
598                          GLenum internalFormat,
599                          GLsizei width,
600                          GLuint memory,
601                          GLuint64 offset)
602 {
603    texstorage_memory(1, target, levels, internalFormat, width, 1, 1, memory,
604                      offset, "glTexStorageMem1DEXT");
605 }
606 
607 void GLAPIENTRY
_mesa_TextureStorageMem1DEXT(GLuint texture,GLsizei levels,GLenum internalFormat,GLsizei width,GLuint memory,GLuint64 offset)608 _mesa_TextureStorageMem1DEXT(GLuint texture,
609                              GLsizei levels,
610                              GLenum internalFormat,
611                              GLsizei width,
612                              GLuint memory,
613                              GLuint64 offset)
614 {
615    texturestorage_memory(1, texture, levels, internalFormat, width, 1, 1,
616                          memory, offset, "glTextureStorageMem1DEXT");
617 }
618 
619 static struct gl_semaphore_object *
semaphoreobj_alloc(struct gl_context * ctx,GLuint name)620 semaphoreobj_alloc(struct gl_context *ctx, GLuint name)
621 {
622    struct gl_semaphore_object *obj = CALLOC_STRUCT(gl_semaphore_object);
623    if (!obj)
624       return NULL;
625 
626    obj->Name = name;
627    return obj;
628 }
629 
630 static void
import_semaphoreobj_fd(struct gl_context * ctx,struct gl_semaphore_object * semObj,int fd)631 import_semaphoreobj_fd(struct gl_context *ctx,
632                           struct gl_semaphore_object *semObj,
633                           int fd)
634 {
635    struct pipe_context *pipe = ctx->pipe;
636 
637    pipe->create_fence_fd(pipe, &semObj->fence, fd, PIPE_FD_TYPE_SYNCOBJ);
638 
639 #if !defined(_WIN32)
640    /* We own fd, but we no longer need it. So get rid of it */
641    close(fd);
642 #endif
643 }
644 
645 static void
import_semaphoreobj_win32(struct gl_context * ctx,struct gl_semaphore_object * semObj,void * handle,const void * name,enum pipe_fd_type type)646 import_semaphoreobj_win32(struct gl_context *ctx,
647                           struct gl_semaphore_object *semObj,
648                           void *handle,
649                           const void *name,
650                           enum pipe_fd_type type)
651 {
652    struct pipe_context *pipe = ctx->pipe;
653    semObj->type = type;
654 
655    pipe->screen->create_fence_win32(pipe->screen, &semObj->fence, handle, name, type);
656 }
657 
658 static void
server_wait_semaphore(struct gl_context * ctx,struct gl_semaphore_object * semObj,GLuint numBufferBarriers,struct gl_buffer_object ** bufObjs,GLuint numTextureBarriers,struct gl_texture_object ** texObjs,const GLenum * srcLayouts)659 server_wait_semaphore(struct gl_context *ctx,
660                       struct gl_semaphore_object *semObj,
661                       GLuint numBufferBarriers,
662                       struct gl_buffer_object **bufObjs,
663                       GLuint numTextureBarriers,
664                       struct gl_texture_object **texObjs,
665                       const GLenum *srcLayouts)
666 {
667    struct st_context *st = ctx->st;
668    struct pipe_context *pipe = ctx->pipe;
669    struct gl_buffer_object *bufObj;
670    struct gl_texture_object *texObj;
671 
672    /* The driver is allowed to flush during fence_server_sync, be prepared */
673    st_flush_bitmap_cache(st);
674    pipe->fence_server_sync(pipe, semObj->fence);
675 
676    /**
677     * According to the EXT_external_objects spec, the memory operations must
678     * follow the wait. This is to make sure the flush is executed after the
679     * other party is done modifying the memory.
680     *
681     * Relevant excerpt from section "4.2.3 Waiting for Semaphores":
682     *
683     * Following completion of the semaphore wait operation, memory will also be
684     * made visible in the specified buffer and texture objects.
685     *
686     */
687    for (unsigned i = 0; i < numBufferBarriers; i++) {
688       if (!bufObjs[i])
689          continue;
690 
691       bufObj = bufObjs[i];
692       if (bufObj->buffer)
693          pipe->flush_resource(pipe, bufObj->buffer);
694    }
695 
696    for (unsigned i = 0; i < numTextureBarriers; i++) {
697       if (!texObjs[i])
698          continue;
699 
700       texObj = texObjs[i];
701       if (texObj->pt)
702          pipe->flush_resource(pipe, texObj->pt);
703    }
704 }
705 
706 static void
server_signal_semaphore(struct gl_context * ctx,struct gl_semaphore_object * semObj,GLuint numBufferBarriers,struct gl_buffer_object ** bufObjs,GLuint numTextureBarriers,struct gl_texture_object ** texObjs,const GLenum * dstLayouts)707 server_signal_semaphore(struct gl_context *ctx,
708                         struct gl_semaphore_object *semObj,
709                         GLuint numBufferBarriers,
710                         struct gl_buffer_object **bufObjs,
711                         GLuint numTextureBarriers,
712                         struct gl_texture_object **texObjs,
713                         const GLenum *dstLayouts)
714 {
715    struct st_context *st = ctx->st;
716    struct pipe_context *pipe = ctx->pipe;
717    struct gl_buffer_object *bufObj;
718    struct gl_texture_object *texObj;
719 
720    for (unsigned i = 0; i < numBufferBarriers; i++) {
721       if (!bufObjs[i])
722          continue;
723 
724       bufObj = bufObjs[i];
725       if (bufObj->buffer)
726          pipe->flush_resource(pipe, bufObj->buffer);
727    }
728 
729    for (unsigned i = 0; i < numTextureBarriers; i++) {
730       if (!texObjs[i])
731          continue;
732 
733       texObj = texObjs[i];
734       if (texObj->pt)
735          pipe->flush_resource(pipe, texObj->pt);
736    }
737 
738    /* The driver must flush during fence_server_signal, be prepared */
739    st_flush_bitmap_cache(st);
740    pipe->fence_server_signal(pipe, semObj->fence);
741 }
742 
743 /**
744  * Used as a placeholder for semaphore objects between glGenSemaphoresEXT()
745  * and glImportSemaphoreFdEXT(), so that glIsSemaphoreEXT() can work correctly.
746  */
747 static struct gl_semaphore_object DummySemaphoreObject;
748 
749 /**
750  * Delete a semaphore object.
751  * Not removed from hash table here.
752  */
753 void
_mesa_delete_semaphore_object(struct gl_context * ctx,struct gl_semaphore_object * semObj)754 _mesa_delete_semaphore_object(struct gl_context *ctx,
755                               struct gl_semaphore_object *semObj)
756 {
757    if (semObj != &DummySemaphoreObject)
758       FREE(semObj);
759 }
760 
761 void GLAPIENTRY
_mesa_GenSemaphoresEXT(GLsizei n,GLuint * semaphores)762 _mesa_GenSemaphoresEXT(GLsizei n, GLuint *semaphores)
763 {
764    GET_CURRENT_CONTEXT(ctx);
765 
766    const char *func = "glGenSemaphoresEXT";
767 
768    if (MESA_VERBOSE & (VERBOSE_API))
769       _mesa_debug(ctx, "%s(%d, %p)", func, n, semaphores);
770 
771    if (!ctx->Extensions.EXT_semaphore) {
772       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
773       return;
774    }
775 
776    if (n < 0) {
777       _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
778       return;
779    }
780 
781    if (!semaphores)
782       return;
783 
784    _mesa_HashLockMutex(ctx->Shared->SemaphoreObjects);
785    if (_mesa_HashFindFreeKeys(ctx->Shared->SemaphoreObjects, semaphores, n)) {
786       for (GLsizei i = 0; i < n; i++) {
787          _mesa_HashInsertLocked(ctx->Shared->SemaphoreObjects,
788                                 semaphores[i], &DummySemaphoreObject, true);
789       }
790    }
791 
792    _mesa_HashUnlockMutex(ctx->Shared->SemaphoreObjects);
793 }
794 
795 void GLAPIENTRY
_mesa_DeleteSemaphoresEXT(GLsizei n,const GLuint * semaphores)796 _mesa_DeleteSemaphoresEXT(GLsizei n, const GLuint *semaphores)
797 {
798    GET_CURRENT_CONTEXT(ctx);
799 
800    const char *func = "glDeleteSemaphoresEXT";
801 
802    if (MESA_VERBOSE & (VERBOSE_API)) {
803       _mesa_debug(ctx, "%s(%d, %p)\n", func, n, semaphores);
804    }
805 
806    if (!ctx->Extensions.EXT_semaphore) {
807       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
808       return;
809    }
810 
811    if (n < 0) {
812       _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
813       return;
814    }
815 
816    if (!semaphores)
817       return;
818 
819    _mesa_HashLockMutex(ctx->Shared->SemaphoreObjects);
820    for (GLint i = 0; i < n; i++) {
821       if (semaphores[i] > 0) {
822          struct gl_semaphore_object *delObj
823             = _mesa_lookup_semaphore_object_locked(ctx, semaphores[i]);
824 
825          if (delObj) {
826             _mesa_HashRemoveLocked(ctx->Shared->SemaphoreObjects,
827                                    semaphores[i]);
828             _mesa_delete_semaphore_object(ctx, delObj);
829          }
830       }
831    }
832    _mesa_HashUnlockMutex(ctx->Shared->SemaphoreObjects);
833 }
834 
835 GLboolean GLAPIENTRY
_mesa_IsSemaphoreEXT(GLuint semaphore)836 _mesa_IsSemaphoreEXT(GLuint semaphore)
837 {
838    GET_CURRENT_CONTEXT(ctx);
839 
840    if (!ctx->Extensions.EXT_semaphore) {
841       _mesa_error(ctx, GL_INVALID_OPERATION, "glIsSemaphoreEXT(unsupported)");
842       return GL_FALSE;
843    }
844 
845    struct gl_semaphore_object *obj =
846       _mesa_lookup_semaphore_object(ctx, semaphore);
847 
848    return obj ? GL_TRUE : GL_FALSE;
849 }
850 
851 /**
852  * Helper that outputs the correct error status for parameter
853  * calls where no pnames are defined
854  */
855 static void
semaphore_parameter_stub(const char * func,GLenum pname)856 semaphore_parameter_stub(const char* func, GLenum pname)
857 {
858 }
859 
860 void GLAPIENTRY
_mesa_SemaphoreParameterui64vEXT(GLuint semaphore,GLenum pname,const GLuint64 * params)861 _mesa_SemaphoreParameterui64vEXT(GLuint semaphore,
862                                  GLenum pname,
863                                  const GLuint64 *params)
864 {
865    GET_CURRENT_CONTEXT(ctx);
866    const char *func = "glSemaphoreParameterui64vEXT";
867 
868    if (!ctx->Extensions.EXT_semaphore) {
869       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
870       return;
871    }
872 
873    if (pname != GL_D3D12_FENCE_VALUE_EXT) {
874       _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
875       return;
876    }
877 
878    struct gl_semaphore_object *semObj = _mesa_lookup_semaphore_object(ctx,
879                                                                       semaphore);
880    if (!semObj)
881       return;
882 
883    if (semObj->type != PIPE_FD_TYPE_TIMELINE_SEMAPHORE) {
884       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(Not a D3D12 fence)", func);
885       return;
886    }
887 
888    semObj->timeline_value = params[0];
889    ctx->screen->set_fence_timeline_value(ctx->screen, semObj->fence, params[0]);
890 }
891 
892 void GLAPIENTRY
_mesa_GetSemaphoreParameterui64vEXT(GLuint semaphore,GLenum pname,GLuint64 * params)893 _mesa_GetSemaphoreParameterui64vEXT(GLuint semaphore,
894                                     GLenum pname,
895                                     GLuint64 *params)
896 {
897    GET_CURRENT_CONTEXT(ctx);
898    const char *func = "glGetSemaphoreParameterui64vEXT";
899 
900    if (!ctx->Extensions.EXT_semaphore) {
901       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
902       return;
903    }
904 
905    if (pname != GL_D3D12_FENCE_VALUE_EXT) {
906       _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
907       return;
908    }
909 
910    struct gl_semaphore_object *semObj = _mesa_lookup_semaphore_object(ctx,
911                                                                       semaphore);
912    if (!semObj)
913       return;
914 
915    if (semObj->type != PIPE_FD_TYPE_TIMELINE_SEMAPHORE) {
916       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(Not a D3D12 fence)", func);
917       return;
918    }
919 
920    params[0] = semObj->timeline_value;
921 }
922 
923 void GLAPIENTRY
_mesa_WaitSemaphoreEXT(GLuint semaphore,GLuint numBufferBarriers,const GLuint * buffers,GLuint numTextureBarriers,const GLuint * textures,const GLenum * srcLayouts)924 _mesa_WaitSemaphoreEXT(GLuint semaphore,
925                        GLuint numBufferBarriers,
926                        const GLuint *buffers,
927                        GLuint numTextureBarriers,
928                        const GLuint *textures,
929                        const GLenum *srcLayouts)
930 {
931    GET_CURRENT_CONTEXT(ctx);
932    struct gl_semaphore_object *semObj = NULL;
933    struct gl_buffer_object **bufObjs = NULL;
934    struct gl_texture_object **texObjs = NULL;
935 
936    const char *func = "glWaitSemaphoreEXT";
937 
938    if (!ctx->Extensions.EXT_semaphore) {
939       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
940       return;
941    }
942 
943    ASSERT_OUTSIDE_BEGIN_END(ctx);
944 
945    semObj = _mesa_lookup_semaphore_object(ctx, semaphore);
946    if (!semObj)
947       return;
948 
949    FLUSH_VERTICES(ctx, 0, 0);
950 
951    bufObjs = malloc(sizeof(struct gl_buffer_object *) * numBufferBarriers);
952    if (!bufObjs) {
953       _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(numBufferBarriers=%u)",
954                   func, numBufferBarriers);
955       goto end;
956    }
957 
958    for (unsigned i = 0; i < numBufferBarriers; i++) {
959       bufObjs[i] = _mesa_lookup_bufferobj(ctx, buffers[i]);
960    }
961 
962    texObjs = malloc(sizeof(struct gl_texture_object *) * numTextureBarriers);
963    if (!texObjs) {
964       _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(numTextureBarriers=%u)",
965                   func, numTextureBarriers);
966       goto end;
967    }
968 
969    for (unsigned i = 0; i < numTextureBarriers; i++) {
970       texObjs[i] = _mesa_lookup_texture(ctx, textures[i]);
971    }
972 
973    server_wait_semaphore(ctx, semObj,
974                          numBufferBarriers, bufObjs,
975                          numTextureBarriers, texObjs,
976                          srcLayouts);
977 
978 end:
979    free(bufObjs);
980    free(texObjs);
981 }
982 
983 void GLAPIENTRY
_mesa_SignalSemaphoreEXT(GLuint semaphore,GLuint numBufferBarriers,const GLuint * buffers,GLuint numTextureBarriers,const GLuint * textures,const GLenum * dstLayouts)984 _mesa_SignalSemaphoreEXT(GLuint semaphore,
985                          GLuint numBufferBarriers,
986                          const GLuint *buffers,
987                          GLuint numTextureBarriers,
988                          const GLuint *textures,
989                          const GLenum *dstLayouts)
990 {
991    GET_CURRENT_CONTEXT(ctx);
992    struct gl_semaphore_object *semObj = NULL;
993    struct gl_buffer_object **bufObjs = NULL;
994    struct gl_texture_object **texObjs = NULL;
995 
996    const char *func = "glSignalSemaphoreEXT";
997 
998    if (!ctx->Extensions.EXT_semaphore) {
999       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
1000       return;
1001    }
1002 
1003    ASSERT_OUTSIDE_BEGIN_END(ctx);
1004 
1005    semObj = _mesa_lookup_semaphore_object(ctx, semaphore);
1006    if (!semObj)
1007       return;
1008 
1009    FLUSH_VERTICES(ctx, 0, 0);
1010 
1011    bufObjs = malloc(sizeof(struct gl_buffer_object *) * numBufferBarriers);
1012    if (!bufObjs) {
1013       _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(numBufferBarriers=%u)",
1014                   func, numBufferBarriers);
1015       goto end;
1016    }
1017 
1018    for (unsigned i = 0; i < numBufferBarriers; i++) {
1019       bufObjs[i] = _mesa_lookup_bufferobj(ctx, buffers[i]);
1020    }
1021 
1022    texObjs = malloc(sizeof(struct gl_texture_object *) * numTextureBarriers);
1023    if (!texObjs) {
1024       _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(numTextureBarriers=%u)",
1025                   func, numTextureBarriers);
1026       goto end;
1027    }
1028 
1029    for (unsigned i = 0; i < numTextureBarriers; i++) {
1030       texObjs[i] = _mesa_lookup_texture(ctx, textures[i]);
1031    }
1032 
1033    server_signal_semaphore(ctx, semObj,
1034                            numBufferBarriers, bufObjs,
1035                            numTextureBarriers, texObjs,
1036                            dstLayouts);
1037 
1038 end:
1039    free(bufObjs);
1040    free(texObjs);
1041 }
1042 
1043 void GLAPIENTRY
_mesa_ImportMemoryFdEXT(GLuint memory,GLuint64 size,GLenum handleType,GLint fd)1044 _mesa_ImportMemoryFdEXT(GLuint memory,
1045                         GLuint64 size,
1046                         GLenum handleType,
1047                         GLint fd)
1048 {
1049    GET_CURRENT_CONTEXT(ctx);
1050 
1051    const char *func = "glImportMemoryFdEXT";
1052 
1053    if (!ctx->Extensions.EXT_memory_object_fd) {
1054       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
1055       return;
1056    }
1057 
1058    if (handleType != GL_HANDLE_TYPE_OPAQUE_FD_EXT) {
1059       _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType);
1060       return;
1061    }
1062 
1063    struct gl_memory_object *memObj = _mesa_lookup_memory_object(ctx, memory);
1064    if (!memObj)
1065       return;
1066 
1067    import_memoryobj_fd(ctx, memObj, size, fd);
1068    memObj->Immutable = GL_TRUE;
1069 }
1070 
1071 void GLAPIENTRY
_mesa_ImportMemoryWin32HandleEXT(GLuint memory,GLuint64 size,GLenum handleType,void * handle)1072 _mesa_ImportMemoryWin32HandleEXT(GLuint memory,
1073                                  GLuint64 size,
1074                                  GLenum handleType,
1075                                  void *handle)
1076 {
1077    GET_CURRENT_CONTEXT(ctx);
1078 
1079    const char *func = "glImportMemoryWin32HandleEXT";
1080 
1081    if (!ctx->Extensions.EXT_memory_object_win32) {
1082       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
1083       return;
1084    }
1085 
1086    if (handleType != GL_HANDLE_TYPE_OPAQUE_WIN32_EXT &&
1087        handleType != GL_HANDLE_TYPE_D3D11_IMAGE_EXT &&
1088        handleType != GL_HANDLE_TYPE_D3D12_RESOURCE_EXT &&
1089        handleType != GL_HANDLE_TYPE_D3D12_TILEPOOL_EXT) {
1090       _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType);
1091       return;
1092    }
1093 
1094    struct gl_memory_object *memObj = _mesa_lookup_memory_object(ctx, memory);
1095    if (!memObj)
1096       return;
1097 
1098    import_memoryobj_win32(ctx, memObj, size, handle, NULL);
1099    memObj->Immutable = GL_TRUE;
1100 }
1101 
1102 void GLAPIENTRY
_mesa_ImportMemoryWin32NameEXT(GLuint memory,GLuint64 size,GLenum handleType,const void * name)1103 _mesa_ImportMemoryWin32NameEXT(GLuint memory,
1104                                  GLuint64 size,
1105                                  GLenum handleType,
1106                                  const void *name)
1107 {
1108    GET_CURRENT_CONTEXT(ctx);
1109 
1110    const char *func = "glImportMemoryWin32NameEXT";
1111 
1112    if (!ctx->Extensions.EXT_memory_object_win32) {
1113       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
1114       return;
1115    }
1116 
1117    if (handleType != GL_HANDLE_TYPE_OPAQUE_WIN32_EXT &&
1118        handleType != GL_HANDLE_TYPE_D3D11_IMAGE_EXT &&
1119        handleType != GL_HANDLE_TYPE_D3D12_RESOURCE_EXT &&
1120        handleType != GL_HANDLE_TYPE_D3D12_TILEPOOL_EXT) {
1121       _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType);
1122       return;
1123    }
1124 
1125    struct gl_memory_object *memObj = _mesa_lookup_memory_object(ctx, memory);
1126    if (!memObj)
1127       return;
1128 
1129    import_memoryobj_win32(ctx, memObj, size, NULL, name);
1130    memObj->Immutable = GL_TRUE;
1131 }
1132 
1133 void GLAPIENTRY
_mesa_ImportSemaphoreFdEXT(GLuint semaphore,GLenum handleType,GLint fd)1134 _mesa_ImportSemaphoreFdEXT(GLuint semaphore,
1135                            GLenum handleType,
1136                            GLint fd)
1137 {
1138    GET_CURRENT_CONTEXT(ctx);
1139 
1140    const char *func = "glImportSemaphoreFdEXT";
1141 
1142    if (!ctx->Extensions.EXT_semaphore_fd) {
1143       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
1144       return;
1145    }
1146 
1147    if (handleType != GL_HANDLE_TYPE_OPAQUE_FD_EXT) {
1148       _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType);
1149       return;
1150    }
1151 
1152    struct gl_semaphore_object *semObj = _mesa_lookup_semaphore_object(ctx,
1153                                                                       semaphore);
1154    if (!semObj)
1155       return;
1156 
1157    if (semObj == &DummySemaphoreObject) {
1158       semObj = semaphoreobj_alloc(ctx, semaphore);
1159       if (!semObj) {
1160          _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
1161          return;
1162       }
1163       _mesa_HashInsert(ctx->Shared->SemaphoreObjects, semaphore, semObj, true);
1164    }
1165 
1166    import_semaphoreobj_fd(ctx, semObj, fd);
1167 }
1168 
1169 void GLAPIENTRY
_mesa_ImportSemaphoreWin32HandleEXT(GLuint semaphore,GLenum handleType,void * handle)1170 _mesa_ImportSemaphoreWin32HandleEXT(GLuint semaphore,
1171                            GLenum handleType,
1172                            void *handle)
1173 {
1174    GET_CURRENT_CONTEXT(ctx);
1175 
1176    const char *func = "glImportSemaphoreWin32HandleEXT";
1177 
1178    if (!ctx->Extensions.EXT_semaphore_win32) {
1179       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
1180       return;
1181    }
1182 
1183    if (handleType != GL_HANDLE_TYPE_OPAQUE_WIN32_EXT &&
1184        handleType != GL_HANDLE_TYPE_D3D12_FENCE_EXT) {
1185       _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType);
1186       return;
1187    }
1188 
1189    if (handleType == GL_HANDLE_TYPE_D3D12_FENCE_EXT &&
1190        !ctx->screen->get_param(ctx->screen, PIPE_CAP_TIMELINE_SEMAPHORE_IMPORT)) {
1191       _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType);
1192    }
1193 
1194    struct gl_semaphore_object *semObj = _mesa_lookup_semaphore_object(ctx,
1195                                                                       semaphore);
1196    if (!semObj)
1197       return;
1198 
1199    if (semObj == &DummySemaphoreObject) {
1200       semObj = semaphoreobj_alloc(ctx, semaphore);
1201       if (!semObj) {
1202          _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
1203          return;
1204       }
1205       _mesa_HashInsert(ctx->Shared->SemaphoreObjects, semaphore, semObj, true);
1206    }
1207 
1208    enum pipe_fd_type type = handleType == GL_HANDLE_TYPE_D3D12_FENCE_EXT ?
1209       PIPE_FD_TYPE_TIMELINE_SEMAPHORE : PIPE_FD_TYPE_SYNCOBJ;
1210    import_semaphoreobj_win32(ctx, semObj, handle, NULL, type);
1211 }
1212 
1213 void GLAPIENTRY
_mesa_ImportSemaphoreWin32NameEXT(GLuint semaphore,GLenum handleType,const void * name)1214 _mesa_ImportSemaphoreWin32NameEXT(GLuint semaphore,
1215                                   GLenum handleType,
1216                                   const void *name)
1217 {
1218    GET_CURRENT_CONTEXT(ctx);
1219 
1220    const char *func = "glImportSemaphoreWin32HandleEXT";
1221 
1222    if (!ctx->Extensions.EXT_semaphore_win32) {
1223       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
1224       return;
1225    }
1226 
1227    if (handleType != GL_HANDLE_TYPE_OPAQUE_WIN32_EXT &&
1228        handleType != GL_HANDLE_TYPE_D3D12_FENCE_EXT) {
1229       _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType);
1230       return;
1231    }
1232 
1233    if (handleType == GL_HANDLE_TYPE_D3D12_FENCE_EXT &&
1234        !ctx->screen->get_param(ctx->screen, PIPE_CAP_TIMELINE_SEMAPHORE_IMPORT)) {
1235       _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType);
1236    }
1237 
1238    struct gl_semaphore_object *semObj = _mesa_lookup_semaphore_object(ctx,
1239                                                                       semaphore);
1240    if (!semObj)
1241       return;
1242 
1243    if (semObj == &DummySemaphoreObject) {
1244       semObj = semaphoreobj_alloc(ctx, semaphore);
1245       if (!semObj) {
1246          _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
1247          return;
1248       }
1249       _mesa_HashInsert(ctx->Shared->SemaphoreObjects, semaphore, semObj, true);
1250    }
1251 
1252    enum pipe_fd_type type = handleType == GL_HANDLE_TYPE_D3D12_FENCE_EXT ?
1253       PIPE_FD_TYPE_TIMELINE_SEMAPHORE : PIPE_FD_TYPE_SYNCOBJ;
1254    import_semaphoreobj_win32(ctx, semObj, NULL, name, type);
1255 }
1256