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