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 */
44static struct gl_memory_object *
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 */
59void
60_mesa_delete_memory_object(struct gl_context *ctx,
61                           struct gl_memory_object *memObj)
62{
63   free(memObj);
64}
65
66void
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 */
76void
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
86void GLAPIENTRY
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
126GLboolean GLAPIENTRY
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
143void GLAPIENTRY
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
189void GLAPIENTRY
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
225invalid_pname:
226   _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
227}
228
229void GLAPIENTRY
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
260invalid_pname:
261   _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
262}
263
264static struct gl_memory_object *
265lookup_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 */
289static void
290texstorage_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
318static void
319texstorage_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 */
350static void
351texturestorage_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
379static void
380texturestorage_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
408void GLAPIENTRY
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
421void GLAPIENTRY
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
436void GLAPIENTRY
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
450void GLAPIENTRY
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
466void GLAPIENTRY
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
479void GLAPIENTRY
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
494void GLAPIENTRY
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
508void GLAPIENTRY
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
524void GLAPIENTRY
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
536void GLAPIENTRY
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 */
552static 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 */
558void
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 */
569void
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
578void GLAPIENTRY
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
612void GLAPIENTRY
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
652GLboolean GLAPIENTRY
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 */
672static void
673semaphore_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
686void GLAPIENTRY
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
696void GLAPIENTRY
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
706void GLAPIENTRY
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
761end:
762   free(bufObjs);
763   free(texObjs);
764}
765
766void GLAPIENTRY
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
821end:
822   free(bufObjs);
823   free(texObjs);
824}
825
826void GLAPIENTRY
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
854void GLAPIENTRY
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