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 "externalobjects.h"
29 #include "teximage.h"
30 #include "texobj.h"
31 #include "glformats.h"
32 #include "texstorage.h"
33 #include "util/u_memory.h"
34 
35 /**
36  * Allocate and initialize a new memory object.  But don't put it into the
37  * memory object hash table.
38  *
39  * Called via ctx->Driver.NewMemoryObject, unless overridden by a device
40  * driver.
41  *
42  * \return pointer to new memory object.
43  */
44 static struct gl_memory_object *
_mesa_new_memory_object(struct gl_context * ctx,GLuint name)45 _mesa_new_memory_object(struct gl_context *ctx, GLuint name)
46 {
47    struct gl_memory_object *obj = MALLOC_STRUCT(gl_memory_object);
48    if (!obj)
49       return NULL;
50 
51    _mesa_initialize_memory_object(ctx, obj, name);
52    return obj;
53 }
54 
55 /**
56  * Delete a memory object.  Called via ctx->Driver.DeleteMemory().
57  * Not removed from hash table here.
58  */
59 void
_mesa_delete_memory_object(struct gl_context * ctx,struct gl_memory_object * memObj)60 _mesa_delete_memory_object(struct gl_context *ctx,
61                            struct gl_memory_object *memObj)
62 {
63    free(memObj);
64 }
65 
66 void
_mesa_init_memory_object_functions(struct dd_function_table * driver)67 _mesa_init_memory_object_functions(struct dd_function_table *driver)
68 {
69    driver->NewMemoryObject = _mesa_new_memory_object;
70    driver->DeleteMemoryObject = _mesa_delete_memory_object;
71 }
72 
73 /**
74  * Initialize a buffer object to default values.
75  */
76 void
_mesa_initialize_memory_object(struct gl_context * ctx,struct gl_memory_object * obj,GLuint name)77 _mesa_initialize_memory_object(struct gl_context *ctx,
78                                struct gl_memory_object *obj,
79                                GLuint name)
80 {
81    memset(obj, 0, sizeof(struct gl_memory_object));
82    obj->Name = name;
83    obj->Dedicated = GL_FALSE;
84 }
85 
86 void GLAPIENTRY
_mesa_DeleteMemoryObjectsEXT(GLsizei n,const GLuint * memoryObjects)87 _mesa_DeleteMemoryObjectsEXT(GLsizei n, const GLuint *memoryObjects)
88 {
89    GET_CURRENT_CONTEXT(ctx);
90 
91    if (MESA_VERBOSE & (VERBOSE_API)) {
92       _mesa_debug(ctx, "glDeleteMemoryObjectsEXT(%d, %p)\n", n,
93                   memoryObjects);
94    }
95 
96    if (!ctx->Extensions.EXT_memory_object) {
97       _mesa_error(ctx, GL_INVALID_OPERATION,
98                   "glDeleteMemoryObjectsEXT(unsupported)");
99       return;
100    }
101 
102    if (n < 0) {
103       _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteMemoryObjectsEXT(n < 0)");
104       return;
105    }
106 
107    if (!memoryObjects)
108       return;
109 
110    _mesa_HashLockMutex(ctx->Shared->MemoryObjects);
111    for (GLint i = 0; i < n; i++) {
112       if (memoryObjects[i] > 0) {
113          struct gl_memory_object *delObj
114             = _mesa_lookup_memory_object_locked(ctx, memoryObjects[i]);
115 
116          if (delObj) {
117             _mesa_HashRemoveLocked(ctx->Shared->MemoryObjects,
118                                    memoryObjects[i]);
119             ctx->Driver.DeleteMemoryObject(ctx, delObj);
120          }
121       }
122    }
123    _mesa_HashUnlockMutex(ctx->Shared->MemoryObjects);
124 }
125 
126 GLboolean GLAPIENTRY
_mesa_IsMemoryObjectEXT(GLuint memoryObject)127 _mesa_IsMemoryObjectEXT(GLuint memoryObject)
128 {
129    GET_CURRENT_CONTEXT(ctx);
130 
131    if (!ctx->Extensions.EXT_memory_object) {
132       _mesa_error(ctx, GL_INVALID_OPERATION,
133                   "glIsMemoryObjectEXT(unsupported)");
134       return GL_FALSE;
135    }
136 
137    struct gl_memory_object *obj =
138       _mesa_lookup_memory_object(ctx, memoryObject);
139 
140    return obj ? GL_TRUE : GL_FALSE;
141 }
142 
143 void GLAPIENTRY
_mesa_CreateMemoryObjectsEXT(GLsizei n,GLuint * memoryObjects)144 _mesa_CreateMemoryObjectsEXT(GLsizei n, GLuint *memoryObjects)
145 {
146    GET_CURRENT_CONTEXT(ctx);
147 
148    const char *func = "glCreateMemoryObjectsEXT";
149 
150    if (MESA_VERBOSE & (VERBOSE_API))
151       _mesa_debug(ctx, "%s(%d, %p)", func, n, memoryObjects);
152 
153    if (!ctx->Extensions.EXT_memory_object) {
154       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
155       return;
156    }
157 
158    if (n < 0) {
159       _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
160       return;
161    }
162 
163    if (!memoryObjects)
164       return;
165 
166    _mesa_HashLockMutex(ctx->Shared->MemoryObjects);
167    if (_mesa_HashFindFreeKeys(ctx->Shared->MemoryObjects, memoryObjects, n)) {
168       for (GLsizei i = 0; i < n; i++) {
169          struct gl_memory_object *memObj;
170 
171          /* allocate memory object */
172          memObj = ctx->Driver.NewMemoryObject(ctx, memoryObjects[i]);
173          if (!memObj) {
174             _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s()", func);
175             _mesa_HashUnlockMutex(ctx->Shared->MemoryObjects);
176             return;
177          }
178 
179          /* insert into hash table */
180          _mesa_HashInsertLocked(ctx->Shared->MemoryObjects,
181                                 memoryObjects[i],
182                                 memObj, true);
183       }
184    }
185 
186    _mesa_HashUnlockMutex(ctx->Shared->MemoryObjects);
187 }
188 
189 void GLAPIENTRY
_mesa_MemoryObjectParameterivEXT(GLuint memoryObject,GLenum pname,const GLint * params)190 _mesa_MemoryObjectParameterivEXT(GLuint memoryObject,
191                                  GLenum pname,
192                                  const GLint *params)
193 {
194    GET_CURRENT_CONTEXT(ctx);
195    struct gl_memory_object *memObj;
196 
197    const char *func = "glMemoryObjectParameterivEXT";
198 
199    if (!ctx->Extensions.EXT_memory_object) {
200       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
201       return;
202    }
203 
204    memObj = _mesa_lookup_memory_object(ctx, memoryObject);
205    if (!memObj)
206       return;
207 
208    if (memObj->Immutable) {
209       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(memoryObject is immutable", func);
210       return;
211    }
212 
213    switch (pname) {
214    case GL_DEDICATED_MEMORY_OBJECT_EXT:
215       memObj->Dedicated = (GLboolean) params[0];
216       break;
217    case GL_PROTECTED_MEMORY_OBJECT_EXT:
218       /* EXT_protected_textures not supported */
219       goto invalid_pname;
220    default:
221       goto invalid_pname;
222    }
223    return;
224 
225 invalid_pname:
226    _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
227 }
228 
229 void GLAPIENTRY
_mesa_GetMemoryObjectParameterivEXT(GLuint memoryObject,GLenum pname,GLint * params)230 _mesa_GetMemoryObjectParameterivEXT(GLuint memoryObject,
231                                     GLenum pname,
232                                     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    switch (pname) {
249       case GL_DEDICATED_MEMORY_OBJECT_EXT:
250          *params = (GLint) memObj->Dedicated;
251          break;
252       case GL_PROTECTED_MEMORY_OBJECT_EXT:
253          /* EXT_protected_textures not supported */
254          goto invalid_pname;
255       default:
256          goto invalid_pname;
257    }
258    return;
259 
260 invalid_pname:
261    _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
262 }
263 
264 static struct gl_memory_object *
lookup_memory_object_err(struct gl_context * ctx,unsigned memory,const char * func)265 lookup_memory_object_err(struct gl_context *ctx, unsigned memory,
266                          const char* func)
267 {
268    if (memory == 0) {
269       _mesa_error(ctx, GL_INVALID_VALUE, "%s(memory=0)", func);
270       return NULL;
271    }
272 
273    struct gl_memory_object *memObj = _mesa_lookup_memory_object(ctx, memory);
274    if (!memObj)
275       return NULL;
276 
277    if (!memObj->Immutable) {
278       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no associated memory)",
279                   func);
280       return NULL;
281    }
282 
283    return memObj;
284 }
285 
286 /**
287  * Helper used by _mesa_TexStorageMem1/2/3DEXT().
288  */
289 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)290 texstorage_memory(GLuint dims, GLenum target, GLsizei levels,
291                   GLenum internalFormat, GLsizei width, GLsizei height,
292                   GLsizei depth, GLuint memory, GLuint64 offset,
293                   const char *func)
294 {
295    struct gl_texture_object *texObj;
296    struct gl_memory_object *memObj;
297 
298    GET_CURRENT_CONTEXT(ctx);
299 
300    if (!ctx->Extensions.EXT_memory_object) {
301       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
302       return;
303    }
304 
305    texObj = _mesa_get_current_tex_object(ctx, target);
306    if (!texObj)
307       return;
308 
309    memObj = lookup_memory_object_err(ctx, memory, func);
310    if (!memObj)
311       return;
312 
313    _mesa_texture_storage_memory(ctx, dims, texObj, memObj, target,
314                                 levels, internalFormat,
315                                 width, height, depth, offset, false);
316 }
317 
318 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)319 texstorage_memory_ms(GLuint dims, GLenum target, GLsizei samples,
320                      GLenum internalFormat, GLsizei width, GLsizei height,
321                      GLsizei depth, GLboolean fixedSampleLocations,
322                      GLuint memory, GLuint64 offset, const char* func)
323 {
324    struct gl_texture_object *texObj;
325    struct gl_memory_object *memObj;
326 
327    GET_CURRENT_CONTEXT(ctx);
328 
329    if (!ctx->Extensions.EXT_memory_object) {
330       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
331       return;
332    }
333 
334    texObj = _mesa_get_current_tex_object(ctx, target);
335    if (!texObj)
336       return;
337 
338    memObj = lookup_memory_object_err(ctx, memory, func);
339    if (!memObj)
340       return;
341 
342    _mesa_texture_storage_ms_memory(ctx, dims, texObj, memObj, target, samples,
343                                    internalFormat, width, height, depth,
344                                    fixedSampleLocations, offset, func);
345 }
346 
347 /**
348  * Helper used by _mesa_TextureStorageMem1/2/3DEXT().
349  */
350 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)351 texturestorage_memory(GLuint dims, GLuint texture, GLsizei levels,
352                       GLenum internalFormat, GLsizei width, GLsizei height,
353                       GLsizei depth, GLuint memory, GLuint64 offset,
354                       const char *func)
355 {
356    struct gl_texture_object *texObj;
357    struct gl_memory_object *memObj;
358 
359    GET_CURRENT_CONTEXT(ctx);
360 
361    if (!ctx->Extensions.EXT_memory_object) {
362       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
363       return;
364    }
365 
366    texObj = _mesa_lookup_texture(ctx, texture);
367    if (!texObj)
368       return;
369 
370    memObj = lookup_memory_object_err(ctx, memory, func);
371    if (!memObj)
372       return;
373 
374    _mesa_texture_storage_memory(ctx, dims, texObj, memObj, texObj->Target,
375                                 levels, internalFormat,
376                                 width, height, depth, offset, true);
377 }
378 
379 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)380 texturestorage_memory_ms(GLuint dims, GLuint texture, GLsizei samples,
381                          GLenum internalFormat, GLsizei width, GLsizei height,
382                          GLsizei depth, GLboolean fixedSampleLocations,
383                          GLuint memory, GLuint64 offset, const char* func)
384 {
385    struct gl_texture_object *texObj;
386    struct gl_memory_object *memObj;
387 
388    GET_CURRENT_CONTEXT(ctx);
389 
390    if (!ctx->Extensions.EXT_memory_object) {
391       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
392       return;
393    }
394 
395    texObj = _mesa_lookup_texture(ctx, texture);
396    if (!texObj)
397       return;
398 
399    memObj = lookup_memory_object_err(ctx, memory, func);
400    if (!memObj)
401       return;
402 
403    _mesa_texture_storage_ms_memory(ctx, dims, texObj, memObj, texObj->Target,
404                                    samples, internalFormat, width, height,
405                                    depth, fixedSampleLocations, offset, func);
406 }
407 
408 void GLAPIENTRY
_mesa_TexStorageMem2DEXT(GLenum target,GLsizei levels,GLenum internalFormat,GLsizei width,GLsizei height,GLuint memory,GLuint64 offset)409 _mesa_TexStorageMem2DEXT(GLenum target,
410                          GLsizei levels,
411                          GLenum internalFormat,
412                          GLsizei width,
413                          GLsizei height,
414                          GLuint memory,
415                          GLuint64 offset)
416 {
417    texstorage_memory(2, target, levels, internalFormat, width, height, 1,
418                      memory, offset, "glTexStorageMem2DEXT");
419 }
420 
421 void GLAPIENTRY
_mesa_TexStorageMem2DMultisampleEXT(GLenum target,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height,GLboolean fixedSampleLocations,GLuint memory,GLuint64 offset)422 _mesa_TexStorageMem2DMultisampleEXT(GLenum target,
423                                     GLsizei samples,
424                                     GLenum internalFormat,
425                                     GLsizei width,
426                                     GLsizei height,
427                                     GLboolean fixedSampleLocations,
428                                     GLuint memory,
429                                     GLuint64 offset)
430 {
431    texstorage_memory_ms(2, target, samples, internalFormat, width, height, 1,
432                         fixedSampleLocations, memory, offset,
433                         "glTexStorageMem2DMultisampleEXT");
434 }
435 
436 void GLAPIENTRY
_mesa_TexStorageMem3DEXT(GLenum target,GLsizei levels,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei depth,GLuint memory,GLuint64 offset)437 _mesa_TexStorageMem3DEXT(GLenum target,
438                          GLsizei levels,
439                          GLenum internalFormat,
440                          GLsizei width,
441                          GLsizei height,
442                          GLsizei depth,
443                          GLuint memory,
444                          GLuint64 offset)
445 {
446    texstorage_memory(3, target, levels, internalFormat, width, height, depth,
447                      memory, offset, "glTexStorageMem3DEXT");
448 }
449 
450 void GLAPIENTRY
_mesa_TexStorageMem3DMultisampleEXT(GLenum target,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei depth,GLboolean fixedSampleLocations,GLuint memory,GLuint64 offset)451 _mesa_TexStorageMem3DMultisampleEXT(GLenum target,
452                                     GLsizei samples,
453                                     GLenum internalFormat,
454                                     GLsizei width,
455                                     GLsizei height,
456                                     GLsizei depth,
457                                     GLboolean fixedSampleLocations,
458                                     GLuint memory,
459                                     GLuint64 offset)
460 {
461    texstorage_memory_ms(3, target, samples, internalFormat, width, height,
462                         depth, fixedSampleLocations, memory, offset,
463                         "glTexStorageMem3DMultisampleEXT");
464 }
465 
466 void GLAPIENTRY
_mesa_TextureStorageMem2DEXT(GLuint texture,GLsizei levels,GLenum internalFormat,GLsizei width,GLsizei height,GLuint memory,GLuint64 offset)467 _mesa_TextureStorageMem2DEXT(GLuint texture,
468                              GLsizei levels,
469                              GLenum internalFormat,
470                              GLsizei width,
471                              GLsizei height,
472                              GLuint memory,
473                              GLuint64 offset)
474 {
475    texturestorage_memory(2, texture, levels, internalFormat, width, height, 1,
476                          memory, offset, "glTexureStorageMem2DEXT");
477 }
478 
479 void GLAPIENTRY
_mesa_TextureStorageMem2DMultisampleEXT(GLuint texture,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height,GLboolean fixedSampleLocations,GLuint memory,GLuint64 offset)480 _mesa_TextureStorageMem2DMultisampleEXT(GLuint texture,
481                                         GLsizei samples,
482                                         GLenum internalFormat,
483                                         GLsizei width,
484                                         GLsizei height,
485                                         GLboolean fixedSampleLocations,
486                                         GLuint memory,
487                                         GLuint64 offset)
488 {
489    texturestorage_memory_ms(2, texture, samples, internalFormat, width, height,
490                             1, fixedSampleLocations, memory, offset,
491                             "glTextureStorageMem2DMultisampleEXT");
492 }
493 
494 void GLAPIENTRY
_mesa_TextureStorageMem3DEXT(GLuint texture,GLsizei levels,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei depth,GLuint memory,GLuint64 offset)495 _mesa_TextureStorageMem3DEXT(GLuint texture,
496                              GLsizei levels,
497                              GLenum internalFormat,
498                              GLsizei width,
499                              GLsizei height,
500                              GLsizei depth,
501                              GLuint memory,
502                              GLuint64 offset)
503 {
504    texturestorage_memory(3, texture, levels, internalFormat, width, height,
505                          depth, memory, offset, "glTextureStorageMem3DEXT");
506 }
507 
508 void GLAPIENTRY
_mesa_TextureStorageMem3DMultisampleEXT(GLuint texture,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei depth,GLboolean fixedSampleLocations,GLuint memory,GLuint64 offset)509 _mesa_TextureStorageMem3DMultisampleEXT(GLuint texture,
510                                         GLsizei samples,
511                                         GLenum internalFormat,
512                                         GLsizei width,
513                                         GLsizei height,
514                                         GLsizei depth,
515                                         GLboolean fixedSampleLocations,
516                                         GLuint memory,
517                                         GLuint64 offset)
518 {
519    texturestorage_memory_ms(3, texture, samples, internalFormat, width, height,
520                             depth, fixedSampleLocations, memory, offset,
521                             "glTextureStorageMem3DMultisampleEXT");
522 }
523 
524 void GLAPIENTRY
_mesa_TexStorageMem1DEXT(GLenum target,GLsizei levels,GLenum internalFormat,GLsizei width,GLuint memory,GLuint64 offset)525 _mesa_TexStorageMem1DEXT(GLenum target,
526                          GLsizei levels,
527                          GLenum internalFormat,
528                          GLsizei width,
529                          GLuint memory,
530                          GLuint64 offset)
531 {
532    texstorage_memory(1, target, levels, internalFormat, width, 1, 1, memory,
533                      offset, "glTexStorageMem1DEXT");
534 }
535 
536 void GLAPIENTRY
_mesa_TextureStorageMem1DEXT(GLuint texture,GLsizei levels,GLenum internalFormat,GLsizei width,GLuint memory,GLuint64 offset)537 _mesa_TextureStorageMem1DEXT(GLuint texture,
538                              GLsizei levels,
539                              GLenum internalFormat,
540                              GLsizei width,
541                              GLuint memory,
542                              GLuint64 offset)
543 {
544    texturestorage_memory(1, texture, levels, internalFormat, width, 1, 1,
545                          memory, offset, "glTextureStorageMem1DEXT");
546 }
547 
548 /**
549  * Used as a placeholder for semaphore objects between glGenSemaphoresEXT()
550  * and glImportSemaphoreFdEXT(), so that glIsSemaphoreEXT() can work correctly.
551  */
552 static struct gl_semaphore_object DummySemaphoreObject;
553 
554 /**
555  * Delete a semaphore object.  Called via ctx->Driver.DeleteSemaphore().
556  * Not removed from hash table here.
557  */
558 void
_mesa_delete_semaphore_object(struct gl_context * ctx,struct gl_semaphore_object * semObj)559 _mesa_delete_semaphore_object(struct gl_context *ctx,
560                               struct gl_semaphore_object *semObj)
561 {
562    if (semObj != &DummySemaphoreObject)
563       free(semObj);
564 }
565 
566 /**
567  * Initialize a semaphore object to default values.
568  */
569 void
_mesa_initialize_semaphore_object(struct gl_context * ctx,struct gl_semaphore_object * obj,GLuint name)570 _mesa_initialize_semaphore_object(struct gl_context *ctx,
571                                   struct gl_semaphore_object *obj,
572                                   GLuint name)
573 {
574    memset(obj, 0, sizeof(struct gl_semaphore_object));
575    obj->Name = name;
576 }
577 
578 void GLAPIENTRY
_mesa_GenSemaphoresEXT(GLsizei n,GLuint * semaphores)579 _mesa_GenSemaphoresEXT(GLsizei n, GLuint *semaphores)
580 {
581    GET_CURRENT_CONTEXT(ctx);
582 
583    const char *func = "glGenSemaphoresEXT";
584 
585    if (MESA_VERBOSE & (VERBOSE_API))
586       _mesa_debug(ctx, "%s(%d, %p)", func, n, semaphores);
587 
588    if (!ctx->Extensions.EXT_semaphore) {
589       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
590       return;
591    }
592 
593    if (n < 0) {
594       _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
595       return;
596    }
597 
598    if (!semaphores)
599       return;
600 
601    _mesa_HashLockMutex(ctx->Shared->SemaphoreObjects);
602    if (_mesa_HashFindFreeKeys(ctx->Shared->SemaphoreObjects, semaphores, n)) {
603       for (GLsizei i = 0; i < n; i++) {
604          _mesa_HashInsertLocked(ctx->Shared->SemaphoreObjects,
605                                 semaphores[i], &DummySemaphoreObject, true);
606       }
607    }
608 
609    _mesa_HashUnlockMutex(ctx->Shared->SemaphoreObjects);
610 }
611 
612 void GLAPIENTRY
_mesa_DeleteSemaphoresEXT(GLsizei n,const GLuint * semaphores)613 _mesa_DeleteSemaphoresEXT(GLsizei n, const GLuint *semaphores)
614 {
615    GET_CURRENT_CONTEXT(ctx);
616 
617    const char *func = "glDeleteSemaphoresEXT";
618 
619    if (MESA_VERBOSE & (VERBOSE_API)) {
620       _mesa_debug(ctx, "%s(%d, %p)\n", func, n, semaphores);
621    }
622 
623    if (!ctx->Extensions.EXT_semaphore) {
624       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
625       return;
626    }
627 
628    if (n < 0) {
629       _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
630       return;
631    }
632 
633    if (!semaphores)
634       return;
635 
636    _mesa_HashLockMutex(ctx->Shared->SemaphoreObjects);
637    for (GLint i = 0; i < n; i++) {
638       if (semaphores[i] > 0) {
639          struct gl_semaphore_object *delObj
640             = _mesa_lookup_semaphore_object_locked(ctx, semaphores[i]);
641 
642          if (delObj) {
643             _mesa_HashRemoveLocked(ctx->Shared->SemaphoreObjects,
644                                    semaphores[i]);
645             ctx->Driver.DeleteSemaphoreObject(ctx, delObj);
646          }
647       }
648    }
649    _mesa_HashUnlockMutex(ctx->Shared->SemaphoreObjects);
650 }
651 
652 GLboolean GLAPIENTRY
_mesa_IsSemaphoreEXT(GLuint semaphore)653 _mesa_IsSemaphoreEXT(GLuint semaphore)
654 {
655    GET_CURRENT_CONTEXT(ctx);
656 
657    if (!ctx->Extensions.EXT_semaphore) {
658       _mesa_error(ctx, GL_INVALID_OPERATION, "glIsSemaphoreEXT(unsupported)");
659       return GL_FALSE;
660    }
661 
662    struct gl_semaphore_object *obj =
663       _mesa_lookup_semaphore_object(ctx, semaphore);
664 
665    return obj ? GL_TRUE : GL_FALSE;
666 }
667 
668 /**
669  * Helper that outputs the correct error status for parameter
670  * calls where no pnames are defined
671  */
672 static void
semaphore_parameter_stub(const char * func,GLenum pname)673 semaphore_parameter_stub(const char* func, GLenum pname)
674 {
675    GET_CURRENT_CONTEXT(ctx);
676 
677    if (!ctx->Extensions.EXT_semaphore) {
678       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
679       return;
680    }
681 
682    /* EXT_semaphore and EXT_semaphore_fd define no parameters */
683    _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
684 }
685 
686 void GLAPIENTRY
_mesa_SemaphoreParameterui64vEXT(GLuint semaphore,GLenum pname,const GLuint64 * params)687 _mesa_SemaphoreParameterui64vEXT(GLuint semaphore,
688                                  GLenum pname,
689                                  const GLuint64 *params)
690 {
691    const char *func = "glSemaphoreParameterui64vEXT";
692 
693    semaphore_parameter_stub(func, pname);
694 }
695 
696 void GLAPIENTRY
_mesa_GetSemaphoreParameterui64vEXT(GLuint semaphore,GLenum pname,GLuint64 * params)697 _mesa_GetSemaphoreParameterui64vEXT(GLuint semaphore,
698                                     GLenum pname,
699                                     GLuint64 *params)
700 {
701    const char *func = "glGetSemaphoreParameterui64vEXT";
702 
703    semaphore_parameter_stub(func, pname);
704 }
705 
706 void GLAPIENTRY
_mesa_WaitSemaphoreEXT(GLuint semaphore,GLuint numBufferBarriers,const GLuint * buffers,GLuint numTextureBarriers,const GLuint * textures,const GLenum * srcLayouts)707 _mesa_WaitSemaphoreEXT(GLuint semaphore,
708                        GLuint numBufferBarriers,
709                        const GLuint *buffers,
710                        GLuint numTextureBarriers,
711                        const GLuint *textures,
712                        const GLenum *srcLayouts)
713 {
714    GET_CURRENT_CONTEXT(ctx);
715    struct gl_semaphore_object *semObj = NULL;
716    struct gl_buffer_object **bufObjs = NULL;
717    struct gl_texture_object **texObjs = NULL;
718 
719    const char *func = "glWaitSemaphoreEXT";
720 
721    if (!ctx->Extensions.EXT_semaphore) {
722       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
723       return;
724    }
725 
726    ASSERT_OUTSIDE_BEGIN_END(ctx);
727 
728    semObj = _mesa_lookup_semaphore_object(ctx, semaphore);
729    if (!semObj)
730       return;
731 
732    FLUSH_VERTICES(ctx, 0, 0);
733 
734    bufObjs = malloc(sizeof(struct gl_buffer_object *) * numBufferBarriers);
735    if (!bufObjs) {
736       _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(numBufferBarriers=%u)",
737                   func, numBufferBarriers);
738       goto end;
739    }
740 
741    for (unsigned i = 0; i < numBufferBarriers; i++) {
742       bufObjs[i] = _mesa_lookup_bufferobj(ctx, buffers[i]);
743    }
744 
745    texObjs = malloc(sizeof(struct gl_texture_object *) * numTextureBarriers);
746    if (!texObjs) {
747       _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(numTextureBarriers=%u)",
748                   func, numTextureBarriers);
749       goto end;
750    }
751 
752    for (unsigned i = 0; i < numTextureBarriers; i++) {
753       texObjs[i] = _mesa_lookup_texture(ctx, textures[i]);
754    }
755 
756    ctx->Driver.ServerWaitSemaphoreObject(ctx, semObj,
757                                          numBufferBarriers, bufObjs,
758                                          numTextureBarriers, texObjs,
759                                          srcLayouts);
760 
761 end:
762    free(bufObjs);
763    free(texObjs);
764 }
765 
766 void GLAPIENTRY
_mesa_SignalSemaphoreEXT(GLuint semaphore,GLuint numBufferBarriers,const GLuint * buffers,GLuint numTextureBarriers,const GLuint * textures,const GLenum * dstLayouts)767 _mesa_SignalSemaphoreEXT(GLuint semaphore,
768                          GLuint numBufferBarriers,
769                          const GLuint *buffers,
770                          GLuint numTextureBarriers,
771                          const GLuint *textures,
772                          const GLenum *dstLayouts)
773 {
774    GET_CURRENT_CONTEXT(ctx);
775    struct gl_semaphore_object *semObj = NULL;
776    struct gl_buffer_object **bufObjs = NULL;
777    struct gl_texture_object **texObjs = NULL;
778 
779    const char *func = "glSignalSemaphoreEXT";
780 
781    if (!ctx->Extensions.EXT_semaphore) {
782       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
783       return;
784    }
785 
786    ASSERT_OUTSIDE_BEGIN_END(ctx);
787 
788    semObj = _mesa_lookup_semaphore_object(ctx, semaphore);
789    if (!semObj)
790       return;
791 
792    FLUSH_VERTICES(ctx, 0, 0);
793 
794    bufObjs = malloc(sizeof(struct gl_buffer_object *) * numBufferBarriers);
795    if (!bufObjs) {
796       _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(numBufferBarriers=%u)",
797                   func, numBufferBarriers);
798       goto end;
799    }
800 
801    for (unsigned i = 0; i < numBufferBarriers; i++) {
802       bufObjs[i] = _mesa_lookup_bufferobj(ctx, buffers[i]);
803    }
804 
805    texObjs = malloc(sizeof(struct gl_texture_object *) * numTextureBarriers);
806    if (!texObjs) {
807       _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(numTextureBarriers=%u)",
808                   func, numTextureBarriers);
809       goto end;
810    }
811 
812    for (unsigned i = 0; i < numTextureBarriers; i++) {
813       texObjs[i] = _mesa_lookup_texture(ctx, textures[i]);
814    }
815 
816    ctx->Driver.ServerSignalSemaphoreObject(ctx, semObj,
817                                            numBufferBarriers, bufObjs,
818                                            numTextureBarriers, texObjs,
819                                            dstLayouts);
820 
821 end:
822    free(bufObjs);
823    free(texObjs);
824 }
825 
826 void GLAPIENTRY
_mesa_ImportMemoryFdEXT(GLuint memory,GLuint64 size,GLenum handleType,GLint fd)827 _mesa_ImportMemoryFdEXT(GLuint memory,
828                         GLuint64 size,
829                         GLenum handleType,
830                         GLint fd)
831 {
832    GET_CURRENT_CONTEXT(ctx);
833 
834    const char *func = "glImportMemoryFdEXT";
835 
836    if (!ctx->Extensions.EXT_memory_object_fd) {
837       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
838       return;
839    }
840 
841    if (handleType != GL_HANDLE_TYPE_OPAQUE_FD_EXT) {
842       _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType);
843       return;
844    }
845 
846    struct gl_memory_object *memObj = _mesa_lookup_memory_object(ctx, memory);
847    if (!memObj)
848       return;
849 
850    ctx->Driver.ImportMemoryObjectFd(ctx, memObj, size, fd);
851    memObj->Immutable = GL_TRUE;
852 }
853 
854 void GLAPIENTRY
_mesa_ImportSemaphoreFdEXT(GLuint semaphore,GLenum handleType,GLint fd)855 _mesa_ImportSemaphoreFdEXT(GLuint semaphore,
856                            GLenum handleType,
857                            GLint fd)
858 {
859    GET_CURRENT_CONTEXT(ctx);
860 
861    const char *func = "glImportSemaphoreFdEXT";
862 
863    if (!ctx->Extensions.EXT_semaphore_fd) {
864       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
865       return;
866    }
867 
868    if (handleType != GL_HANDLE_TYPE_OPAQUE_FD_EXT) {
869       _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType);
870       return;
871    }
872 
873    struct gl_semaphore_object *semObj = _mesa_lookup_semaphore_object(ctx,
874                                                                       semaphore);
875    if (!semObj)
876       return;
877 
878    if (semObj == &DummySemaphoreObject) {
879       semObj = ctx->Driver.NewSemaphoreObject(ctx, semaphore);
880       if (!semObj) {
881          _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
882          return;
883       }
884       _mesa_HashInsert(ctx->Shared->SemaphoreObjects, semaphore, semObj, true);
885    }
886 
887    ctx->Driver.ImportSemaphoreFd(ctx, semObj, fd);
888 }
889