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 "externalobjects.h" 27 #include "teximage.h" 28 #include "texobj.h" 29 #include "glformats.h" 30 #include "texstorage.h" 31 32 /** 33 * Allocate and initialize a new memory object. But don't put it into the 34 * memory object hash table. 35 * 36 * Called via ctx->Driver.NewMemoryObject, unless overridden by a device 37 * driver. 38 * 39 * \return pointer to new memory object. 40 */ 41 static struct gl_memory_object * 42 _mesa_new_memory_object(struct gl_context *ctx, GLuint name) 43 { 44 struct gl_memory_object *obj = MALLOC_STRUCT(gl_memory_object); 45 if (!obj) 46 return NULL; 47 48 _mesa_initialize_memory_object(ctx, obj, name); 49 return obj; 50 } 51 52 /** 53 * Delete a memory object. Called via ctx->Driver.DeleteMemory(). 54 * Not removed from hash table here. 55 */ 56 void 57 _mesa_delete_memory_object(struct gl_context *ctx, 58 struct gl_memory_object *memObj) 59 { 60 free(memObj); 61 } 62 63 void 64 _mesa_init_memory_object_functions(struct dd_function_table *driver) 65 { 66 driver->NewMemoryObject = _mesa_new_memory_object; 67 driver->DeleteMemoryObject = _mesa_delete_memory_object; 68 } 69 70 /** 71 * Initialize a buffer object to default values. 72 */ 73 void 74 _mesa_initialize_memory_object(struct gl_context *ctx, 75 struct gl_memory_object *obj, 76 GLuint name) 77 { 78 memset(obj, 0, sizeof(struct gl_memory_object)); 79 obj->Name = name; 80 obj->Dedicated = GL_FALSE; 81 } 82 83 void GLAPIENTRY 84 _mesa_DeleteMemoryObjectsEXT(GLsizei n, const GLuint *memoryObjects) 85 { 86 GET_CURRENT_CONTEXT(ctx); 87 88 if (MESA_VERBOSE & (VERBOSE_API)) { 89 _mesa_debug(ctx, "glDeleteMemoryObjectsEXT(%d, %p)\n", n, 90 memoryObjects); 91 } 92 93 if (!ctx->Extensions.EXT_memory_object) { 94 _mesa_error(ctx, GL_INVALID_OPERATION, 95 "glDeleteMemoryObjectsEXT(unsupported)"); 96 return; 97 } 98 99 if (n < 0) { 100 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteMemoryObjectsEXT(n < 0)"); 101 return; 102 } 103 104 if (!memoryObjects) 105 return; 106 107 _mesa_HashLockMutex(ctx->Shared->MemoryObjects); 108 for (GLint i = 0; i < n; i++) { 109 if (memoryObjects[i] > 0) { 110 struct gl_memory_object *delObj 111 = _mesa_lookup_memory_object_locked(ctx, memoryObjects[i]); 112 113 if (delObj) { 114 _mesa_HashRemoveLocked(ctx->Shared->MemoryObjects, 115 memoryObjects[i]); 116 ctx->Driver.DeleteMemoryObject(ctx, delObj); 117 } 118 } 119 } 120 _mesa_HashUnlockMutex(ctx->Shared->MemoryObjects); 121 } 122 123 GLboolean GLAPIENTRY 124 _mesa_IsMemoryObjectEXT(GLuint memoryObject) 125 { 126 GET_CURRENT_CONTEXT(ctx); 127 128 if (!ctx->Extensions.EXT_memory_object) { 129 _mesa_error(ctx, GL_INVALID_OPERATION, 130 "glIsMemoryObjectEXT(unsupported)"); 131 return GL_FALSE; 132 } 133 134 struct gl_memory_object *obj = 135 _mesa_lookup_memory_object(ctx, memoryObject); 136 137 return obj ? GL_TRUE : GL_FALSE; 138 } 139 140 void GLAPIENTRY 141 _mesa_CreateMemoryObjectsEXT(GLsizei n, GLuint *memoryObjects) 142 { 143 GET_CURRENT_CONTEXT(ctx); 144 145 const char *func = "glCreateMemoryObjectsEXT"; 146 147 if (MESA_VERBOSE & (VERBOSE_API)) 148 _mesa_debug(ctx, "%s(%d, %p)", func, n, memoryObjects); 149 150 if (!ctx->Extensions.EXT_memory_object) { 151 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 152 return; 153 } 154 155 if (n < 0) { 156 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); 157 return; 158 } 159 160 if (!memoryObjects) 161 return; 162 163 _mesa_HashLockMutex(ctx->Shared->MemoryObjects); 164 GLuint first = _mesa_HashFindFreeKeyBlock(ctx->Shared->MemoryObjects, n); 165 if (first) { 166 for (GLsizei i = 0; i < n; i++) { 167 struct gl_memory_object *memObj; 168 169 memoryObjects[i] = first + i; 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); 183 } 184 } 185 186 _mesa_HashUnlockMutex(ctx->Shared->MemoryObjects); 187 } 188 189 void GLAPIENTRY 190 _mesa_MemoryObjectParameterivEXT(GLuint memoryObject, 191 GLenum pname, 192 const GLint *params) 193 { 194 GET_CURRENT_CONTEXT(ctx); 195 struct gl_memory_object *memObj; 196 197 const char *func = "glMemoryObjectParameterivEXT"; 198 199 if (!ctx->Extensions.EXT_memory_object) { 200 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 201 return; 202 } 203 204 memObj = _mesa_lookup_memory_object(ctx, memoryObject); 205 if (!memObj) 206 return; 207 208 if (memObj->Immutable) { 209 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(memoryObject is immutable", func); 210 return; 211 } 212 213 switch (pname) { 214 case GL_DEDICATED_MEMORY_OBJECT_EXT: 215 memObj->Dedicated = (GLboolean) params[0]; 216 break; 217 case GL_PROTECTED_MEMORY_OBJECT_EXT: 218 /* EXT_protected_textures not supported */ 219 goto invalid_pname; 220 default: 221 goto invalid_pname; 222 } 223 return; 224 225 invalid_pname: 226 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname); 227 } 228 229 void GLAPIENTRY 230 _mesa_GetMemoryObjectParameterivEXT(GLuint memoryObject, 231 GLenum pname, 232 GLint *params) 233 { 234 GET_CURRENT_CONTEXT(ctx); 235 struct gl_memory_object *memObj; 236 237 const char *func = "glMemoryObjectParameterivEXT"; 238 239 if (!ctx->Extensions.EXT_memory_object) { 240 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 241 return; 242 } 243 244 memObj = _mesa_lookup_memory_object(ctx, memoryObject); 245 if (!memObj) 246 return; 247 248 switch (pname) { 249 case GL_DEDICATED_MEMORY_OBJECT_EXT: 250 *params = (GLint) memObj->Dedicated; 251 break; 252 case GL_PROTECTED_MEMORY_OBJECT_EXT: 253 /* EXT_protected_textures not supported */ 254 goto invalid_pname; 255 default: 256 goto invalid_pname; 257 } 258 return; 259 260 invalid_pname: 261 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname); 262 } 263 264 static struct gl_memory_object * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 void GLAPIENTRY 549 _mesa_GenSemaphoresEXT(GLsizei n, GLuint *semaphores) 550 { 551 552 } 553 554 void GLAPIENTRY 555 _mesa_DeleteSemaphoresEXT(GLsizei n, const GLuint *semaphores) 556 { 557 558 } 559 560 GLboolean GLAPIENTRY 561 _mesa_IsSemaphoreEXT(GLuint semaphore) 562 { 563 return GL_FALSE; 564 } 565 566 void GLAPIENTRY 567 _mesa_SemaphoreParameterui64vEXT(GLuint semaphore, 568 GLenum pname, 569 const GLuint64 *params) 570 { 571 572 } 573 574 void GLAPIENTRY 575 _mesa_GetSemaphoreParameterui64vEXT(GLuint semaphore, 576 GLenum pname, 577 GLuint64 *params) 578 { 579 580 } 581 582 void GLAPIENTRY 583 _mesa_WaitSemaphoreEXT(GLuint semaphore, 584 GLuint numBufferBarriers, 585 const GLuint *buffers, 586 GLuint numTextureBarriers, 587 const GLuint *textures, 588 const GLenum *srcLayouts) 589 { 590 591 } 592 593 void GLAPIENTRY 594 _mesa_SignalSemaphoreEXT(GLuint semaphore, 595 GLuint numBufferBarriers, 596 const GLuint *buffers, 597 GLuint numTextureBarriers, 598 const GLuint *textures, 599 const GLenum *dstLayouts) 600 { 601 602 } 603 604 void GLAPIENTRY 605 _mesa_ImportMemoryFdEXT(GLuint memory, 606 GLuint64 size, 607 GLenum handleType, 608 GLint fd) 609 { 610 GET_CURRENT_CONTEXT(ctx); 611 612 const char *func = "glImportMemoryFdEXT"; 613 614 if (!ctx->Extensions.EXT_memory_object_fd) { 615 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 616 return; 617 } 618 619 if (handleType != GL_HANDLE_TYPE_OPAQUE_FD_EXT) { 620 _mesa_error(ctx, GL_INVALID_VALUE, "%s(handleType=%u)", func, handleType); 621 return; 622 } 623 624 struct gl_memory_object *memObj = _mesa_lookup_memory_object(ctx, memory); 625 if (!memObj) 626 return; 627 628 ctx->Driver.ImportMemoryObjectFd(ctx, memObj, size, fd); 629 memObj->Immutable = GL_TRUE; 630 } 631 632 void GLAPIENTRY 633 _mesa_ImportSemaphoreFdEXT(GLuint semaphore, 634 GLenum handleType, 635 GLint fd) 636 { 637 638 } 639