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