1/* 2 * Copyright © 2016 Red Hat. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24#include "macros.h" 25#include "mtypes.h" 26#include "bufferobj.h" 27#include "context.h" 28#include "enums.h" 29#include "externalobjects.h" 30#include "teximage.h" 31#include "texobj.h" 32#include "glformats.h" 33#include "texstorage.h" 34#include "util/u_memory.h" 35 36#include "pipe/p_context.h" 37#include "pipe/p_screen.h" 38#include "api_exec_decl.h" 39 40#include "state_tracker/st_cb_bitmap.h" 41#include "state_tracker/st_texture.h" 42 43struct st_context; 44 45#include "frontend/drm_driver.h" 46#ifdef HAVE_LIBDRM 47#include "drm-uapi/drm_fourcc.h" 48#endif 49 50static struct gl_memory_object * 51memoryobj_alloc(struct gl_context *ctx, GLuint name) 52{ 53 struct gl_memory_object *obj = CALLOC_STRUCT(gl_memory_object); 54 if (!obj) 55 return NULL; 56 57 obj->Name = name; 58 obj->Dedicated = GL_FALSE; 59 return obj; 60} 61 62static void 63import_memoryobj_fd(struct gl_context *ctx, 64 struct gl_memory_object *obj, 65 GLuint64 size, 66 int fd) 67{ 68#if !defined(_WIN32) 69 struct pipe_screen *screen = ctx->pipe->screen; 70 struct winsys_handle whandle = { 71 .type = WINSYS_HANDLE_TYPE_FD, 72 .handle = fd, 73#ifdef HAVE_LIBDRM 74 .modifier = DRM_FORMAT_MOD_INVALID, 75#endif 76 }; 77 78 obj->memory = screen->memobj_create_from_handle(screen, 79 &whandle, 80 obj->Dedicated); 81 82 /* We own fd, but we no longer need it. So get rid of it */ 83 close(fd); 84#endif 85} 86 87static void 88import_memoryobj_win32(struct gl_context *ctx, 89 struct gl_memory_object *obj, 90 GLuint64 size, 91 void *handle, 92 const void *name) 93{ 94 struct pipe_screen *screen = ctx->pipe->screen; 95 struct winsys_handle whandle = { 96 .type = handle ? WINSYS_HANDLE_TYPE_WIN32_HANDLE : WINSYS_HANDLE_TYPE_WIN32_NAME, 97#ifdef _WIN32 98 .handle = handle, 99#else 100 .handle = 0, 101#endif 102#ifdef HAVE_LIBDRM 103 .modifier = DRM_FORMAT_MOD_INVALID, 104#endif 105 .name = name, 106 }; 107 108 obj->memory = screen->memobj_create_from_handle(screen, 109 &whandle, 110 obj->Dedicated); 111} 112 113/** 114 * Delete a memory object. 115 * Not removed from hash table here. 116 */ 117void 118_mesa_delete_memory_object(struct gl_context *ctx, 119 struct gl_memory_object *memObj) 120{ 121 struct pipe_screen *screen = ctx->pipe->screen; 122 if (memObj->memory) 123 screen->memobj_destroy(screen, memObj->memory); 124 FREE(memObj); 125} 126 127void GLAPIENTRY 128_mesa_DeleteMemoryObjectsEXT(GLsizei n, const GLuint *memoryObjects) 129{ 130 GET_CURRENT_CONTEXT(ctx); 131 132 if (MESA_VERBOSE & (VERBOSE_API)) { 133 _mesa_debug(ctx, "glDeleteMemoryObjectsEXT(%d, %p)\n", n, 134 memoryObjects); 135 } 136 137 if (!ctx->Extensions.EXT_memory_object) { 138 _mesa_error(ctx, GL_INVALID_OPERATION, 139 "glDeleteMemoryObjectsEXT(unsupported)"); 140 return; 141 } 142 143 if (n < 0) { 144 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteMemoryObjectsEXT(n < 0)"); 145 return; 146 } 147 148 if (!memoryObjects) 149 return; 150 151 _mesa_HashLockMutex(ctx->Shared->MemoryObjects); 152 for (GLint i = 0; i < n; i++) { 153 if (memoryObjects[i] > 0) { 154 struct gl_memory_object *delObj 155 = _mesa_lookup_memory_object_locked(ctx, memoryObjects[i]); 156 157 if (delObj) { 158 _mesa_HashRemoveLocked(ctx->Shared->MemoryObjects, 159 memoryObjects[i]); 160 _mesa_delete_memory_object(ctx, delObj); 161 } 162 } 163 } 164 _mesa_HashUnlockMutex(ctx->Shared->MemoryObjects); 165} 166 167GLboolean GLAPIENTRY 168_mesa_IsMemoryObjectEXT(GLuint memoryObject) 169{ 170 GET_CURRENT_CONTEXT(ctx); 171 172 if (!ctx->Extensions.EXT_memory_object) { 173 _mesa_error(ctx, GL_INVALID_OPERATION, 174 "glIsMemoryObjectEXT(unsupported)"); 175 return GL_FALSE; 176 } 177 178 struct gl_memory_object *obj = 179 _mesa_lookup_memory_object(ctx, memoryObject); 180 181 return obj ? GL_TRUE : GL_FALSE; 182} 183 184void GLAPIENTRY 185_mesa_CreateMemoryObjectsEXT(GLsizei n, GLuint *memoryObjects) 186{ 187 GET_CURRENT_CONTEXT(ctx); 188 189 const char *func = "glCreateMemoryObjectsEXT"; 190 191 if (MESA_VERBOSE & (VERBOSE_API)) 192 _mesa_debug(ctx, "%s(%d, %p)", func, n, memoryObjects); 193 194 if (!ctx->Extensions.EXT_memory_object) { 195 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 196 return; 197 } 198 199 if (n < 0) { 200 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); 201 return; 202 } 203 204 if (!memoryObjects) 205 return; 206 207 _mesa_HashLockMutex(ctx->Shared->MemoryObjects); 208 if (_mesa_HashFindFreeKeys(ctx->Shared->MemoryObjects, memoryObjects, n)) { 209 for (GLsizei i = 0; i < n; i++) { 210 struct gl_memory_object *memObj; 211 212 /* allocate memory object */ 213 memObj = memoryobj_alloc(ctx, memoryObjects[i]); 214 if (!memObj) { 215 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s()", func); 216 _mesa_HashUnlockMutex(ctx->Shared->MemoryObjects); 217 return; 218 } 219 220 /* insert into hash table */ 221 _mesa_HashInsertLocked(ctx->Shared->MemoryObjects, 222 memoryObjects[i], 223 memObj, true); 224 } 225 } 226 227 _mesa_HashUnlockMutex(ctx->Shared->MemoryObjects); 228} 229 230void GLAPIENTRY 231_mesa_MemoryObjectParameterivEXT(GLuint memoryObject, 232 GLenum pname, 233 const GLint *params) 234{ 235 GET_CURRENT_CONTEXT(ctx); 236 struct gl_memory_object *memObj; 237 238 const char *func = "glMemoryObjectParameterivEXT"; 239 240 if (!ctx->Extensions.EXT_memory_object) { 241 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 242 return; 243 } 244 245 memObj = _mesa_lookup_memory_object(ctx, memoryObject); 246 if (!memObj) 247 return; 248 249 if (memObj->Immutable) { 250 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(memoryObject is immutable", func); 251 return; 252 } 253 254 switch (pname) { 255 case GL_DEDICATED_MEMORY_OBJECT_EXT: 256 memObj->Dedicated = (GLboolean) params[0]; 257 break; 258 case GL_PROTECTED_MEMORY_OBJECT_EXT: 259 /* EXT_protected_textures not supported */ 260 goto invalid_pname; 261 default: 262 goto invalid_pname; 263 } 264 return; 265 266invalid_pname: 267 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname); 268} 269 270void GLAPIENTRY 271_mesa_GetMemoryObjectParameterivEXT(GLuint memoryObject, 272 GLenum pname, 273 GLint *params) 274{ 275 GET_CURRENT_CONTEXT(ctx); 276 struct gl_memory_object *memObj; 277 278 const char *func = "glMemoryObjectParameterivEXT"; 279 280 if (!ctx->Extensions.EXT_memory_object) { 281 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 282 return; 283 } 284 285 memObj = _mesa_lookup_memory_object(ctx, memoryObject); 286 if (!memObj) 287 return; 288 289 switch (pname) { 290 case GL_DEDICATED_MEMORY_OBJECT_EXT: 291 *params = (GLint) memObj->Dedicated; 292 break; 293 case GL_PROTECTED_MEMORY_OBJECT_EXT: 294 /* EXT_protected_textures not supported */ 295 goto invalid_pname; 296 default: 297 goto invalid_pname; 298 } 299 return; 300 301invalid_pname: 302 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname); 303} 304 305static struct gl_memory_object * 306lookup_memory_object_err(struct gl_context *ctx, unsigned memory, 307 const char* func) 308{ 309 if (memory == 0) { 310 _mesa_error(ctx, GL_INVALID_VALUE, "%s(memory=0)", func); 311 return NULL; 312 } 313 314 struct gl_memory_object *memObj = _mesa_lookup_memory_object(ctx, memory); 315 if (!memObj) 316 return NULL; 317 318 if (!memObj->Immutable) { 319 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no associated memory)", 320 func); 321 return NULL; 322 } 323 324 return memObj; 325} 326 327/** 328 * Helper used by _mesa_TexStorageMem1/2/3DEXT(). 329 */ 330static void 331texstorage_memory(GLuint dims, GLenum target, GLsizei levels, 332 GLenum internalFormat, GLsizei width, GLsizei height, 333 GLsizei depth, GLuint memory, GLuint64 offset, 334 const char *func) 335{ 336 struct gl_texture_object *texObj; 337 struct gl_memory_object *memObj; 338 339 GET_CURRENT_CONTEXT(ctx); 340 341 if (!ctx->Extensions.EXT_memory_object) { 342 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 343 return; 344 } 345 346 if (!_mesa_is_legal_tex_storage_target(ctx, dims, target)) { 347 _mesa_error(ctx, GL_INVALID_ENUM, 348 "%s(illegal target=%s)", 349 func, _mesa_enum_to_string(target)); 350 return; 351 } 352 353 /* Check the format to make sure it is sized. */ 354 if (!_mesa_is_legal_tex_storage_format(ctx, internalFormat)) { 355 _mesa_error(ctx, GL_INVALID_ENUM, 356 "%s(internalformat = %s)", func, 357 _mesa_enum_to_string(internalFormat)); 358 return; 359 } 360 361 texObj = _mesa_get_current_tex_object(ctx, target); 362 if (!texObj) 363 return; 364 365 memObj = lookup_memory_object_err(ctx, memory, func); 366 if (!memObj) 367 return; 368 369 _mesa_texture_storage_memory(ctx, dims, texObj, memObj, target, 370 levels, internalFormat, 371 width, height, depth, offset, false); 372} 373 374static void 375texstorage_memory_ms(GLuint dims, GLenum target, GLsizei samples, 376 GLenum internalFormat, GLsizei width, GLsizei height, 377 GLsizei depth, GLboolean fixedSampleLocations, 378 GLuint memory, GLuint64 offset, const char* func) 379{ 380 struct gl_texture_object *texObj; 381 struct gl_memory_object *memObj; 382 383 GET_CURRENT_CONTEXT(ctx); 384 385 if (!ctx->Extensions.EXT_memory_object) { 386 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 387 return; 388 } 389 390 texObj = _mesa_get_current_tex_object(ctx, target); 391 if (!texObj) 392 return; 393 394 memObj = lookup_memory_object_err(ctx, memory, func); 395 if (!memObj) 396 return; 397 398 _mesa_texture_storage_ms_memory(ctx, dims, texObj, memObj, target, samples, 399 internalFormat, width, height, depth, 400 fixedSampleLocations, offset, func); 401} 402 403/** 404 * Helper used by _mesa_TextureStorageMem1/2/3DEXT(). 405 */ 406static void 407texturestorage_memory(GLuint dims, GLuint texture, GLsizei levels, 408 GLenum internalFormat, GLsizei width, GLsizei height, 409 GLsizei depth, GLuint memory, GLuint64 offset, 410 const char *func) 411{ 412 struct gl_texture_object *texObj; 413 struct gl_memory_object *memObj; 414 415 GET_CURRENT_CONTEXT(ctx); 416 417 if (!ctx->Extensions.EXT_memory_object) { 418 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 419 return; 420 } 421 422 /* Check the format to make sure it is sized. */ 423 if (!_mesa_is_legal_tex_storage_format(ctx, internalFormat)) { 424 _mesa_error(ctx, GL_INVALID_ENUM, 425 "%s(internalformat = %s)", func, 426 _mesa_enum_to_string(internalFormat)); 427 return; 428 } 429 430 texObj = _mesa_lookup_texture(ctx, texture); 431 if (!texObj) 432 return; 433 434 if (!_mesa_is_legal_tex_storage_target(ctx, dims, texObj->Target)) { 435 _mesa_error(ctx, GL_INVALID_OPERATION, 436 "%s(illegal target=%s)", func, 437 _mesa_enum_to_string(texObj->Target)); 438 return; 439 } 440 441 memObj = lookup_memory_object_err(ctx, memory, func); 442 if (!memObj) 443 return; 444 445 _mesa_texture_storage_memory(ctx, dims, texObj, memObj, texObj->Target, 446 levels, internalFormat, 447 width, height, depth, offset, true); 448} 449 450static void 451texturestorage_memory_ms(GLuint dims, GLuint texture, GLsizei samples, 452 GLenum internalFormat, GLsizei width, GLsizei height, 453 GLsizei depth, GLboolean fixedSampleLocations, 454 GLuint memory, GLuint64 offset, const char* func) 455{ 456 struct gl_texture_object *texObj; 457 struct gl_memory_object *memObj; 458 459 GET_CURRENT_CONTEXT(ctx); 460 461 if (!ctx->Extensions.EXT_memory_object) { 462 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 463 return; 464 } 465 466 texObj = _mesa_lookup_texture(ctx, texture); 467 if (!texObj) 468 return; 469 470 memObj = lookup_memory_object_err(ctx, memory, func); 471 if (!memObj) 472 return; 473 474 _mesa_texture_storage_ms_memory(ctx, dims, texObj, memObj, texObj->Target, 475 samples, internalFormat, width, height, 476 depth, fixedSampleLocations, offset, func); 477} 478 479void GLAPIENTRY 480_mesa_TexStorageMem2DEXT(GLenum target, 481 GLsizei levels, 482 GLenum internalFormat, 483 GLsizei width, 484 GLsizei height, 485 GLuint memory, 486 GLuint64 offset) 487{ 488 texstorage_memory(2, target, levels, internalFormat, width, height, 1, 489 memory, offset, "glTexStorageMem2DEXT"); 490} 491 492void GLAPIENTRY 493_mesa_TexStorageMem2DMultisampleEXT(GLenum target, 494 GLsizei samples, 495 GLenum internalFormat, 496 GLsizei width, 497 GLsizei height, 498 GLboolean fixedSampleLocations, 499 GLuint memory, 500 GLuint64 offset) 501{ 502 texstorage_memory_ms(2, target, samples, internalFormat, width, height, 1, 503 fixedSampleLocations, memory, offset, 504 "glTexStorageMem2DMultisampleEXT"); 505} 506 507void GLAPIENTRY 508_mesa_TexStorageMem3DEXT(GLenum target, 509 GLsizei levels, 510 GLenum internalFormat, 511 GLsizei width, 512 GLsizei height, 513 GLsizei depth, 514 GLuint memory, 515 GLuint64 offset) 516{ 517 texstorage_memory(3, target, levels, internalFormat, width, height, depth, 518 memory, offset, "glTexStorageMem3DEXT"); 519} 520 521void GLAPIENTRY 522_mesa_TexStorageMem3DMultisampleEXT(GLenum target, 523 GLsizei samples, 524 GLenum internalFormat, 525 GLsizei width, 526 GLsizei height, 527 GLsizei depth, 528 GLboolean fixedSampleLocations, 529 GLuint memory, 530 GLuint64 offset) 531{ 532 texstorage_memory_ms(3, target, samples, internalFormat, width, height, 533 depth, fixedSampleLocations, memory, offset, 534 "glTexStorageMem3DMultisampleEXT"); 535} 536 537void GLAPIENTRY 538_mesa_TextureStorageMem2DEXT(GLuint texture, 539 GLsizei levels, 540 GLenum internalFormat, 541 GLsizei width, 542 GLsizei height, 543 GLuint memory, 544 GLuint64 offset) 545{ 546 texturestorage_memory(2, texture, levels, internalFormat, width, height, 1, 547 memory, offset, "glTexureStorageMem2DEXT"); 548} 549 550void GLAPIENTRY 551_mesa_TextureStorageMem2DMultisampleEXT(GLuint texture, 552 GLsizei samples, 553 GLenum internalFormat, 554 GLsizei width, 555 GLsizei height, 556 GLboolean fixedSampleLocations, 557 GLuint memory, 558 GLuint64 offset) 559{ 560 texturestorage_memory_ms(2, texture, samples, internalFormat, width, height, 561 1, fixedSampleLocations, memory, offset, 562 "glTextureStorageMem2DMultisampleEXT"); 563} 564 565void GLAPIENTRY 566_mesa_TextureStorageMem3DEXT(GLuint texture, 567 GLsizei levels, 568 GLenum internalFormat, 569 GLsizei width, 570 GLsizei height, 571 GLsizei depth, 572 GLuint memory, 573 GLuint64 offset) 574{ 575 texturestorage_memory(3, texture, levels, internalFormat, width, height, 576 depth, memory, offset, "glTextureStorageMem3DEXT"); 577} 578 579void GLAPIENTRY 580_mesa_TextureStorageMem3DMultisampleEXT(GLuint texture, 581 GLsizei samples, 582 GLenum internalFormat, 583 GLsizei width, 584 GLsizei height, 585 GLsizei depth, 586 GLboolean fixedSampleLocations, 587 GLuint memory, 588 GLuint64 offset) 589{ 590 texturestorage_memory_ms(3, texture, samples, internalFormat, width, height, 591 depth, fixedSampleLocations, memory, offset, 592 "glTextureStorageMem3DMultisampleEXT"); 593} 594 595void GLAPIENTRY 596_mesa_TexStorageMem1DEXT(GLenum target, 597 GLsizei levels, 598 GLenum internalFormat, 599 GLsizei width, 600 GLuint memory, 601 GLuint64 offset) 602{ 603 texstorage_memory(1, target, levels, internalFormat, width, 1, 1, memory, 604 offset, "glTexStorageMem1DEXT"); 605} 606 607void GLAPIENTRY 608_mesa_TextureStorageMem1DEXT(GLuint texture, 609 GLsizei levels, 610 GLenum internalFormat, 611 GLsizei width, 612 GLuint memory, 613 GLuint64 offset) 614{ 615 texturestorage_memory(1, texture, levels, internalFormat, width, 1, 1, 616 memory, offset, "glTextureStorageMem1DEXT"); 617} 618 619static struct gl_semaphore_object * 620semaphoreobj_alloc(struct gl_context *ctx, GLuint name) 621{ 622 struct gl_semaphore_object *obj = CALLOC_STRUCT(gl_semaphore_object); 623 if (!obj) 624 return NULL; 625 626 obj->Name = name; 627 return obj; 628} 629 630static void 631import_semaphoreobj_fd(struct gl_context *ctx, 632 struct gl_semaphore_object *semObj, 633 int fd) 634{ 635 struct pipe_context *pipe = ctx->pipe; 636 637 pipe->create_fence_fd(pipe, &semObj->fence, fd, PIPE_FD_TYPE_SYNCOBJ); 638 639#if !defined(_WIN32) 640 /* We own fd, but we no longer need it. So get rid of it */ 641 close(fd); 642#endif 643} 644 645static void 646import_semaphoreobj_win32(struct gl_context *ctx, 647 struct gl_semaphore_object *semObj, 648 void *handle, 649 const void *name, 650 enum pipe_fd_type type) 651{ 652 struct pipe_context *pipe = ctx->pipe; 653 semObj->type = type; 654 655 pipe->screen->create_fence_win32(pipe->screen, &semObj->fence, handle, name, type); 656} 657 658static void 659server_wait_semaphore(struct gl_context *ctx, 660 struct gl_semaphore_object *semObj, 661 GLuint numBufferBarriers, 662 struct gl_buffer_object **bufObjs, 663 GLuint numTextureBarriers, 664 struct gl_texture_object **texObjs, 665 const GLenum *srcLayouts) 666{ 667 struct st_context *st = ctx->st; 668 struct pipe_context *pipe = ctx->pipe; 669 struct gl_buffer_object *bufObj; 670 struct gl_texture_object *texObj; 671 672 /* The driver is allowed to flush during fence_server_sync, be prepared */ 673 st_flush_bitmap_cache(st); 674 pipe->fence_server_sync(pipe, semObj->fence); 675 676 /** 677 * According to the EXT_external_objects spec, the memory operations must 678 * follow the wait. This is to make sure the flush is executed after the 679 * other party is done modifying the memory. 680 * 681 * Relevant excerpt from section "4.2.3 Waiting for Semaphores": 682 * 683 * Following completion of the semaphore wait operation, memory will also be 684 * made visible in the specified buffer and texture objects. 685 * 686 */ 687 for (unsigned i = 0; i < numBufferBarriers; i++) { 688 if (!bufObjs[i]) 689 continue; 690 691 bufObj = bufObjs[i]; 692 if (bufObj->buffer) 693 pipe->flush_resource(pipe, bufObj->buffer); 694 } 695 696 for (unsigned i = 0; i < numTextureBarriers; i++) { 697 if (!texObjs[i]) 698 continue; 699 700 texObj = texObjs[i]; 701 if (texObj->pt) 702 pipe->flush_resource(pipe, texObj->pt); 703 } 704} 705 706static void 707server_signal_semaphore(struct gl_context *ctx, 708 struct gl_semaphore_object *semObj, 709 GLuint numBufferBarriers, 710 struct gl_buffer_object **bufObjs, 711 GLuint numTextureBarriers, 712 struct gl_texture_object **texObjs, 713 const GLenum *dstLayouts) 714{ 715 struct st_context *st = ctx->st; 716 struct pipe_context *pipe = ctx->pipe; 717 struct gl_buffer_object *bufObj; 718 struct gl_texture_object *texObj; 719 720 for (unsigned i = 0; i < numBufferBarriers; i++) { 721 if (!bufObjs[i]) 722 continue; 723 724 bufObj = bufObjs[i]; 725 if (bufObj->buffer) 726 pipe->flush_resource(pipe, bufObj->buffer); 727 } 728 729 for (unsigned i = 0; i < numTextureBarriers; i++) { 730 if (!texObjs[i]) 731 continue; 732 733 texObj = texObjs[i]; 734 if (texObj->pt) 735 pipe->flush_resource(pipe, texObj->pt); 736 } 737 738 /* The driver must flush during fence_server_signal, be prepared */ 739 st_flush_bitmap_cache(st); 740 pipe->fence_server_signal(pipe, semObj->fence); 741} 742 743/** 744 * Used as a placeholder for semaphore objects between glGenSemaphoresEXT() 745 * and glImportSemaphoreFdEXT(), so that glIsSemaphoreEXT() can work correctly. 746 */ 747static struct gl_semaphore_object DummySemaphoreObject; 748 749/** 750 * Delete a semaphore object. 751 * Not removed from hash table here. 752 */ 753void 754_mesa_delete_semaphore_object(struct gl_context *ctx, 755 struct gl_semaphore_object *semObj) 756{ 757 if (semObj != &DummySemaphoreObject) 758 FREE(semObj); 759} 760 761void GLAPIENTRY 762_mesa_GenSemaphoresEXT(GLsizei n, GLuint *semaphores) 763{ 764 GET_CURRENT_CONTEXT(ctx); 765 766 const char *func = "glGenSemaphoresEXT"; 767 768 if (MESA_VERBOSE & (VERBOSE_API)) 769 _mesa_debug(ctx, "%s(%d, %p)", func, n, semaphores); 770 771 if (!ctx->Extensions.EXT_semaphore) { 772 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 773 return; 774 } 775 776 if (n < 0) { 777 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); 778 return; 779 } 780 781 if (!semaphores) 782 return; 783 784 _mesa_HashLockMutex(ctx->Shared->SemaphoreObjects); 785 if (_mesa_HashFindFreeKeys(ctx->Shared->SemaphoreObjects, semaphores, n)) { 786 for (GLsizei i = 0; i < n; i++) { 787 _mesa_HashInsertLocked(ctx->Shared->SemaphoreObjects, 788 semaphores[i], &DummySemaphoreObject, true); 789 } 790 } 791 792 _mesa_HashUnlockMutex(ctx->Shared->SemaphoreObjects); 793} 794 795void GLAPIENTRY 796_mesa_DeleteSemaphoresEXT(GLsizei n, const GLuint *semaphores) 797{ 798 GET_CURRENT_CONTEXT(ctx); 799 800 const char *func = "glDeleteSemaphoresEXT"; 801 802 if (MESA_VERBOSE & (VERBOSE_API)) { 803 _mesa_debug(ctx, "%s(%d, %p)\n", func, n, semaphores); 804 } 805 806 if (!ctx->Extensions.EXT_semaphore) { 807 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 808 return; 809 } 810 811 if (n < 0) { 812 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); 813 return; 814 } 815 816 if (!semaphores) 817 return; 818 819 _mesa_HashLockMutex(ctx->Shared->SemaphoreObjects); 820 for (GLint i = 0; i < n; i++) { 821 if (semaphores[i] > 0) { 822 struct gl_semaphore_object *delObj 823 = _mesa_lookup_semaphore_object_locked(ctx, semaphores[i]); 824 825 if (delObj) { 826 _mesa_HashRemoveLocked(ctx->Shared->SemaphoreObjects, 827 semaphores[i]); 828 _mesa_delete_semaphore_object(ctx, delObj); 829 } 830 } 831 } 832 _mesa_HashUnlockMutex(ctx->Shared->SemaphoreObjects); 833} 834 835GLboolean GLAPIENTRY 836_mesa_IsSemaphoreEXT(GLuint semaphore) 837{ 838 GET_CURRENT_CONTEXT(ctx); 839 840 if (!ctx->Extensions.EXT_semaphore) { 841 _mesa_error(ctx, GL_INVALID_OPERATION, "glIsSemaphoreEXT(unsupported)"); 842 return GL_FALSE; 843 } 844 845 struct gl_semaphore_object *obj = 846 _mesa_lookup_semaphore_object(ctx, semaphore); 847 848 return obj ? GL_TRUE : GL_FALSE; 849} 850 851/** 852 * Helper that outputs the correct error status for parameter 853 * calls where no pnames are defined 854 */ 855static void 856semaphore_parameter_stub(const char* func, GLenum pname) 857{ 858} 859 860void GLAPIENTRY 861_mesa_SemaphoreParameterui64vEXT(GLuint semaphore, 862 GLenum pname, 863 const GLuint64 *params) 864{ 865 GET_CURRENT_CONTEXT(ctx); 866 const char *func = "glSemaphoreParameterui64vEXT"; 867 868 if (!ctx->Extensions.EXT_semaphore) { 869 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 870 return; 871 } 872 873 if (pname != GL_D3D12_FENCE_VALUE_EXT) { 874 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname); 875 return; 876 } 877 878 struct gl_semaphore_object *semObj = _mesa_lookup_semaphore_object(ctx, 879 semaphore); 880 if (!semObj) 881 return; 882 883 if (semObj->type != PIPE_FD_TYPE_TIMELINE_SEMAPHORE) { 884 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(Not a D3D12 fence)", func); 885 return; 886 } 887 888 semObj->timeline_value = params[0]; 889 ctx->screen->set_fence_timeline_value(ctx->screen, semObj->fence, params[0]); 890} 891 892void GLAPIENTRY 893_mesa_GetSemaphoreParameterui64vEXT(GLuint semaphore, 894 GLenum pname, 895 GLuint64 *params) 896{ 897 GET_CURRENT_CONTEXT(ctx); 898 const char *func = "glGetSemaphoreParameterui64vEXT"; 899 900 if (!ctx->Extensions.EXT_semaphore) { 901 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 902 return; 903 } 904 905 if (pname != GL_D3D12_FENCE_VALUE_EXT) { 906 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname); 907 return; 908 } 909 910 struct gl_semaphore_object *semObj = _mesa_lookup_semaphore_object(ctx, 911 semaphore); 912 if (!semObj) 913 return; 914 915 if (semObj->type != PIPE_FD_TYPE_TIMELINE_SEMAPHORE) { 916 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(Not a D3D12 fence)", func); 917 return; 918 } 919 920 params[0] = semObj->timeline_value; 921} 922 923void GLAPIENTRY 924_mesa_WaitSemaphoreEXT(GLuint semaphore, 925 GLuint numBufferBarriers, 926 const GLuint *buffers, 927 GLuint numTextureBarriers, 928 const GLuint *textures, 929 const GLenum *srcLayouts) 930{ 931 GET_CURRENT_CONTEXT(ctx); 932 struct gl_semaphore_object *semObj = NULL; 933 struct gl_buffer_object **bufObjs = NULL; 934 struct gl_texture_object **texObjs = NULL; 935 936 const char *func = "glWaitSemaphoreEXT"; 937 938 if (!ctx->Extensions.EXT_semaphore) { 939 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 940 return; 941 } 942 943 ASSERT_OUTSIDE_BEGIN_END(ctx); 944 945 semObj = _mesa_lookup_semaphore_object(ctx, semaphore); 946 if (!semObj) 947 return; 948 949 FLUSH_VERTICES(ctx, 0, 0); 950 951 bufObjs = malloc(sizeof(struct gl_buffer_object *) * numBufferBarriers); 952 if (!bufObjs) { 953 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(numBufferBarriers=%u)", 954 func, numBufferBarriers); 955 goto end; 956 } 957 958 for (unsigned i = 0; i < numBufferBarriers; i++) { 959 bufObjs[i] = _mesa_lookup_bufferobj(ctx, buffers[i]); 960 } 961 962 texObjs = malloc(sizeof(struct gl_texture_object *) * numTextureBarriers); 963 if (!texObjs) { 964 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(numTextureBarriers=%u)", 965 func, numTextureBarriers); 966 goto end; 967 } 968 969 for (unsigned i = 0; i < numTextureBarriers; i++) { 970 texObjs[i] = _mesa_lookup_texture(ctx, textures[i]); 971 } 972 973 server_wait_semaphore(ctx, semObj, 974 numBufferBarriers, bufObjs, 975 numTextureBarriers, texObjs, 976 srcLayouts); 977 978end: 979 free(bufObjs); 980 free(texObjs); 981} 982 983void GLAPIENTRY 984_mesa_SignalSemaphoreEXT(GLuint semaphore, 985 GLuint numBufferBarriers, 986 const GLuint *buffers, 987 GLuint numTextureBarriers, 988 const GLuint *textures, 989 const GLenum *dstLayouts) 990{ 991 GET_CURRENT_CONTEXT(ctx); 992 struct gl_semaphore_object *semObj = NULL; 993 struct gl_buffer_object **bufObjs = NULL; 994 struct gl_texture_object **texObjs = NULL; 995 996 const char *func = "glSignalSemaphoreEXT"; 997 998 if (!ctx->Extensions.EXT_semaphore) { 999 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 1000 return; 1001 } 1002 1003 ASSERT_OUTSIDE_BEGIN_END(ctx); 1004 1005 semObj = _mesa_lookup_semaphore_object(ctx, semaphore); 1006 if (!semObj) 1007 return; 1008 1009 FLUSH_VERTICES(ctx, 0, 0); 1010 1011 bufObjs = malloc(sizeof(struct gl_buffer_object *) * numBufferBarriers); 1012 if (!bufObjs) { 1013 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(numBufferBarriers=%u)", 1014 func, numBufferBarriers); 1015 goto end; 1016 } 1017 1018 for (unsigned i = 0; i < numBufferBarriers; i++) { 1019 bufObjs[i] = _mesa_lookup_bufferobj(ctx, buffers[i]); 1020 } 1021 1022 texObjs = malloc(sizeof(struct gl_texture_object *) * numTextureBarriers); 1023 if (!texObjs) { 1024 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(numTextureBarriers=%u)", 1025 func, numTextureBarriers); 1026 goto end; 1027 } 1028 1029 for (unsigned i = 0; i < numTextureBarriers; i++) { 1030 texObjs[i] = _mesa_lookup_texture(ctx, textures[i]); 1031 } 1032 1033 server_signal_semaphore(ctx, semObj, 1034 numBufferBarriers, bufObjs, 1035 numTextureBarriers, texObjs, 1036 dstLayouts); 1037 1038end: 1039 free(bufObjs); 1040 free(texObjs); 1041} 1042 1043void GLAPIENTRY 1044_mesa_ImportMemoryFdEXT(GLuint memory, 1045 GLuint64 size, 1046 GLenum handleType, 1047 GLint fd) 1048{ 1049 GET_CURRENT_CONTEXT(ctx); 1050 1051 const char *func = "glImportMemoryFdEXT"; 1052 1053 if (!ctx->Extensions.EXT_memory_object_fd) { 1054 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 1055 return; 1056 } 1057 1058 if (handleType != GL_HANDLE_TYPE_OPAQUE_FD_EXT) { 1059 _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType); 1060 return; 1061 } 1062 1063 struct gl_memory_object *memObj = _mesa_lookup_memory_object(ctx, memory); 1064 if (!memObj) 1065 return; 1066 1067 import_memoryobj_fd(ctx, memObj, size, fd); 1068 memObj->Immutable = GL_TRUE; 1069} 1070 1071void GLAPIENTRY 1072_mesa_ImportMemoryWin32HandleEXT(GLuint memory, 1073 GLuint64 size, 1074 GLenum handleType, 1075 void *handle) 1076{ 1077 GET_CURRENT_CONTEXT(ctx); 1078 1079 const char *func = "glImportMemoryWin32HandleEXT"; 1080 1081 if (!ctx->Extensions.EXT_memory_object_win32) { 1082 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 1083 return; 1084 } 1085 1086 if (handleType != GL_HANDLE_TYPE_OPAQUE_WIN32_EXT && 1087 handleType != GL_HANDLE_TYPE_D3D11_IMAGE_EXT && 1088 handleType != GL_HANDLE_TYPE_D3D12_RESOURCE_EXT && 1089 handleType != GL_HANDLE_TYPE_D3D12_TILEPOOL_EXT) { 1090 _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType); 1091 return; 1092 } 1093 1094 struct gl_memory_object *memObj = _mesa_lookup_memory_object(ctx, memory); 1095 if (!memObj) 1096 return; 1097 1098 import_memoryobj_win32(ctx, memObj, size, handle, NULL); 1099 memObj->Immutable = GL_TRUE; 1100} 1101 1102void GLAPIENTRY 1103_mesa_ImportMemoryWin32NameEXT(GLuint memory, 1104 GLuint64 size, 1105 GLenum handleType, 1106 const void *name) 1107{ 1108 GET_CURRENT_CONTEXT(ctx); 1109 1110 const char *func = "glImportMemoryWin32NameEXT"; 1111 1112 if (!ctx->Extensions.EXT_memory_object_win32) { 1113 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 1114 return; 1115 } 1116 1117 if (handleType != GL_HANDLE_TYPE_OPAQUE_WIN32_EXT && 1118 handleType != GL_HANDLE_TYPE_D3D11_IMAGE_EXT && 1119 handleType != GL_HANDLE_TYPE_D3D12_RESOURCE_EXT && 1120 handleType != GL_HANDLE_TYPE_D3D12_TILEPOOL_EXT) { 1121 _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType); 1122 return; 1123 } 1124 1125 struct gl_memory_object *memObj = _mesa_lookup_memory_object(ctx, memory); 1126 if (!memObj) 1127 return; 1128 1129 import_memoryobj_win32(ctx, memObj, size, NULL, name); 1130 memObj->Immutable = GL_TRUE; 1131} 1132 1133void GLAPIENTRY 1134_mesa_ImportSemaphoreFdEXT(GLuint semaphore, 1135 GLenum handleType, 1136 GLint fd) 1137{ 1138 GET_CURRENT_CONTEXT(ctx); 1139 1140 const char *func = "glImportSemaphoreFdEXT"; 1141 1142 if (!ctx->Extensions.EXT_semaphore_fd) { 1143 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 1144 return; 1145 } 1146 1147 if (handleType != GL_HANDLE_TYPE_OPAQUE_FD_EXT) { 1148 _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType); 1149 return; 1150 } 1151 1152 struct gl_semaphore_object *semObj = _mesa_lookup_semaphore_object(ctx, 1153 semaphore); 1154 if (!semObj) 1155 return; 1156 1157 if (semObj == &DummySemaphoreObject) { 1158 semObj = semaphoreobj_alloc(ctx, semaphore); 1159 if (!semObj) { 1160 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); 1161 return; 1162 } 1163 _mesa_HashInsert(ctx->Shared->SemaphoreObjects, semaphore, semObj, true); 1164 } 1165 1166 import_semaphoreobj_fd(ctx, semObj, fd); 1167} 1168 1169void GLAPIENTRY 1170_mesa_ImportSemaphoreWin32HandleEXT(GLuint semaphore, 1171 GLenum handleType, 1172 void *handle) 1173{ 1174 GET_CURRENT_CONTEXT(ctx); 1175 1176 const char *func = "glImportSemaphoreWin32HandleEXT"; 1177 1178 if (!ctx->Extensions.EXT_semaphore_win32) { 1179 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 1180 return; 1181 } 1182 1183 if (handleType != GL_HANDLE_TYPE_OPAQUE_WIN32_EXT && 1184 handleType != GL_HANDLE_TYPE_D3D12_FENCE_EXT) { 1185 _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType); 1186 return; 1187 } 1188 1189 if (handleType == GL_HANDLE_TYPE_D3D12_FENCE_EXT && 1190 !ctx->screen->get_param(ctx->screen, PIPE_CAP_TIMELINE_SEMAPHORE_IMPORT)) { 1191 _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType); 1192 } 1193 1194 struct gl_semaphore_object *semObj = _mesa_lookup_semaphore_object(ctx, 1195 semaphore); 1196 if (!semObj) 1197 return; 1198 1199 if (semObj == &DummySemaphoreObject) { 1200 semObj = semaphoreobj_alloc(ctx, semaphore); 1201 if (!semObj) { 1202 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); 1203 return; 1204 } 1205 _mesa_HashInsert(ctx->Shared->SemaphoreObjects, semaphore, semObj, true); 1206 } 1207 1208 enum pipe_fd_type type = handleType == GL_HANDLE_TYPE_D3D12_FENCE_EXT ? 1209 PIPE_FD_TYPE_TIMELINE_SEMAPHORE : PIPE_FD_TYPE_SYNCOBJ; 1210 import_semaphoreobj_win32(ctx, semObj, handle, NULL, type); 1211} 1212 1213void GLAPIENTRY 1214_mesa_ImportSemaphoreWin32NameEXT(GLuint semaphore, 1215 GLenum handleType, 1216 const void *name) 1217{ 1218 GET_CURRENT_CONTEXT(ctx); 1219 1220 const char *func = "glImportSemaphoreWin32HandleEXT"; 1221 1222 if (!ctx->Extensions.EXT_semaphore_win32) { 1223 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 1224 return; 1225 } 1226 1227 if (handleType != GL_HANDLE_TYPE_OPAQUE_WIN32_EXT && 1228 handleType != GL_HANDLE_TYPE_D3D12_FENCE_EXT) { 1229 _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType); 1230 return; 1231 } 1232 1233 if (handleType == GL_HANDLE_TYPE_D3D12_FENCE_EXT && 1234 !ctx->screen->get_param(ctx->screen, PIPE_CAP_TIMELINE_SEMAPHORE_IMPORT)) { 1235 _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType); 1236 } 1237 1238 struct gl_semaphore_object *semObj = _mesa_lookup_semaphore_object(ctx, 1239 semaphore); 1240 if (!semObj) 1241 return; 1242 1243 if (semObj == &DummySemaphoreObject) { 1244 semObj = semaphoreobj_alloc(ctx, semaphore); 1245 if (!semObj) { 1246 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); 1247 return; 1248 } 1249 _mesa_HashInsert(ctx->Shared->SemaphoreObjects, semaphore, semObj, true); 1250 } 1251 1252 enum pipe_fd_type type = handleType == GL_HANDLE_TYPE_D3D12_FENCE_EXT ? 1253 PIPE_FD_TYPE_TIMELINE_SEMAPHORE : PIPE_FD_TYPE_SYNCOBJ; 1254 import_semaphoreobj_win32(ctx, semObj, NULL, name, type); 1255} 1256