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