1 /* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5 * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 * OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26 27 /** 28 * \file bufferobj.c 29 * \brief Functions for the GL_ARB_vertex/pixel_buffer_object extensions. 30 * \author Brian Paul, Ian Romanick 31 */ 32 33 #include <stdbool.h> 34 #include <inttypes.h> /* for PRId64 macro */ 35 #include "util/debug.h" 36 #include "glheader.h" 37 #include "enums.h" 38 #include "hash.h" 39 #include "imports.h" 40 #include "context.h" 41 #include "bufferobj.h" 42 #include "externalobjects.h" 43 #include "mtypes.h" 44 #include "teximage.h" 45 #include "glformats.h" 46 #include "texstore.h" 47 #include "transformfeedback.h" 48 #include "varray.h" 49 50 51 /* Debug flags */ 52 /*#define VBO_DEBUG*/ 53 /*#define BOUNDS_CHECK*/ 54 55 56 /** 57 * We count the number of buffer modification calls to check for 58 * inefficient buffer use. This is the number of such calls before we 59 * issue a warning. 60 */ 61 #define BUFFER_WARNING_CALL_COUNT 4 62 63 64 /** 65 * Helper to warn of possible performance issues, such as frequently 66 * updating a buffer created with GL_STATIC_DRAW. Called via the macro 67 * below. 68 */ 69 static void 70 buffer_usage_warning(struct gl_context *ctx, GLuint *id, const char *fmt, ...) 71 { 72 va_list args; 73 74 va_start(args, fmt); 75 _mesa_gl_vdebug(ctx, id, 76 MESA_DEBUG_SOURCE_API, 77 MESA_DEBUG_TYPE_PERFORMANCE, 78 MESA_DEBUG_SEVERITY_MEDIUM, 79 fmt, args); 80 va_end(args); 81 } 82 83 #define BUFFER_USAGE_WARNING(CTX, FMT, ...) \ 84 do { \ 85 static GLuint id = 0; \ 86 buffer_usage_warning(CTX, &id, FMT, ##__VA_ARGS__); \ 87 } while (0) 88 89 90 /** 91 * Used as a placeholder for buffer objects between glGenBuffers() and 92 * glBindBuffer() so that glIsBuffer() can work correctly. 93 */ 94 static struct gl_buffer_object DummyBufferObject; 95 96 97 /** 98 * Return pointer to address of a buffer object target. 99 * \param ctx the GL context 100 * \param target the buffer object target to be retrieved. 101 * \return pointer to pointer to the buffer object bound to \c target in the 102 * specified context or \c NULL if \c target is invalid. 103 */ 104 static inline struct gl_buffer_object ** 105 get_buffer_target(struct gl_context *ctx, GLenum target) 106 { 107 /* Other targets are only supported in desktop OpenGL and OpenGL ES 3.0. 108 */ 109 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx) 110 && target != GL_ARRAY_BUFFER && target != GL_ELEMENT_ARRAY_BUFFER) 111 return NULL; 112 113 switch (target) { 114 case GL_ARRAY_BUFFER_ARB: 115 return &ctx->Array.ArrayBufferObj; 116 case GL_ELEMENT_ARRAY_BUFFER_ARB: 117 return &ctx->Array.VAO->IndexBufferObj; 118 case GL_PIXEL_PACK_BUFFER_EXT: 119 return &ctx->Pack.BufferObj; 120 case GL_PIXEL_UNPACK_BUFFER_EXT: 121 return &ctx->Unpack.BufferObj; 122 case GL_COPY_READ_BUFFER: 123 return &ctx->CopyReadBuffer; 124 case GL_COPY_WRITE_BUFFER: 125 return &ctx->CopyWriteBuffer; 126 case GL_QUERY_BUFFER: 127 if (_mesa_has_ARB_query_buffer_object(ctx)) 128 return &ctx->QueryBuffer; 129 break; 130 case GL_DRAW_INDIRECT_BUFFER: 131 if ((ctx->API == API_OPENGL_CORE && 132 ctx->Extensions.ARB_draw_indirect) || 133 _mesa_is_gles31(ctx)) { 134 return &ctx->DrawIndirectBuffer; 135 } 136 break; 137 case GL_PARAMETER_BUFFER_ARB: 138 if (_mesa_has_ARB_indirect_parameters(ctx)) { 139 return &ctx->ParameterBuffer; 140 } 141 break; 142 case GL_DISPATCH_INDIRECT_BUFFER: 143 if (_mesa_has_compute_shaders(ctx)) { 144 return &ctx->DispatchIndirectBuffer; 145 } 146 break; 147 case GL_TRANSFORM_FEEDBACK_BUFFER: 148 if (ctx->Extensions.EXT_transform_feedback) { 149 return &ctx->TransformFeedback.CurrentBuffer; 150 } 151 break; 152 case GL_TEXTURE_BUFFER: 153 if (_mesa_has_ARB_texture_buffer_object(ctx) || 154 _mesa_has_OES_texture_buffer(ctx)) { 155 return &ctx->Texture.BufferObject; 156 } 157 break; 158 case GL_UNIFORM_BUFFER: 159 if (ctx->Extensions.ARB_uniform_buffer_object) { 160 return &ctx->UniformBuffer; 161 } 162 break; 163 case GL_SHADER_STORAGE_BUFFER: 164 if (ctx->Extensions.ARB_shader_storage_buffer_object) { 165 return &ctx->ShaderStorageBuffer; 166 } 167 break; 168 case GL_ATOMIC_COUNTER_BUFFER: 169 if (ctx->Extensions.ARB_shader_atomic_counters) { 170 return &ctx->AtomicBuffer; 171 } 172 break; 173 case GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD: 174 if (ctx->Extensions.AMD_pinned_memory) { 175 return &ctx->ExternalVirtualMemoryBuffer; 176 } 177 break; 178 default: 179 return NULL; 180 } 181 return NULL; 182 } 183 184 185 /** 186 * Get the buffer object bound to the specified target in a GL context. 187 * \param ctx the GL context 188 * \param target the buffer object target to be retrieved. 189 * \param error the GL error to record if target is illegal. 190 * \return pointer to the buffer object bound to \c target in the 191 * specified context or \c NULL if \c target is invalid. 192 */ 193 static inline struct gl_buffer_object * 194 get_buffer(struct gl_context *ctx, const char *func, GLenum target, 195 GLenum error) 196 { 197 struct gl_buffer_object **bufObj = get_buffer_target(ctx, target); 198 199 if (!bufObj) { 200 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func); 201 return NULL; 202 } 203 204 if (!_mesa_is_bufferobj(*bufObj)) { 205 _mesa_error(ctx, error, "%s(no buffer bound)", func); 206 return NULL; 207 } 208 209 return *bufObj; 210 } 211 212 213 /** 214 * Convert a GLbitfield describing the mapped buffer access flags 215 * into one of GL_READ_WRITE, GL_READ_ONLY, or GL_WRITE_ONLY. 216 */ 217 static GLenum 218 simplified_access_mode(struct gl_context *ctx, GLbitfield access) 219 { 220 const GLbitfield rwFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT; 221 if ((access & rwFlags) == rwFlags) 222 return GL_READ_WRITE; 223 if ((access & GL_MAP_READ_BIT) == GL_MAP_READ_BIT) 224 return GL_READ_ONLY; 225 if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT) 226 return GL_WRITE_ONLY; 227 228 /* Otherwise, AccessFlags is zero (the default state). 229 * 230 * Table 2.6 on page 31 (page 44 of the PDF) of the OpenGL 1.5 spec says: 231 * 232 * Name Type Initial Value Legal Values 233 * ... ... ... ... 234 * BUFFER_ACCESS enum READ_WRITE READ_ONLY, WRITE_ONLY 235 * READ_WRITE 236 * 237 * However, table 6.8 in the GL_OES_mapbuffer extension says: 238 * 239 * Get Value Type Get Command Value Description 240 * --------- ---- ----------- ----- ----------- 241 * BUFFER_ACCESS_OES Z1 GetBufferParameteriv WRITE_ONLY_OES buffer map flag 242 * 243 * The difference is because GL_OES_mapbuffer only supports mapping buffers 244 * write-only. 245 */ 246 assert(access == 0); 247 248 return _mesa_is_gles(ctx) ? GL_WRITE_ONLY : GL_READ_WRITE; 249 } 250 251 252 /** 253 * Test if the buffer is mapped, and if so, if the mapped range overlaps the 254 * given range. 255 * The regions do not overlap if and only if the end of the given 256 * region is before the mapped region or the start of the given region 257 * is after the mapped region. 258 * 259 * \param obj Buffer object target on which to operate. 260 * \param offset Offset of the first byte of the subdata range. 261 * \param size Size, in bytes, of the subdata range. 262 * \return true if ranges overlap, false otherwise 263 * 264 */ 265 static bool 266 bufferobj_range_mapped(const struct gl_buffer_object *obj, 267 GLintptr offset, GLsizeiptr size) 268 { 269 if (_mesa_bufferobj_mapped(obj, MAP_USER)) { 270 const GLintptr end = offset + size; 271 const GLintptr mapEnd = obj->Mappings[MAP_USER].Offset + 272 obj->Mappings[MAP_USER].Length; 273 274 if (!(end <= obj->Mappings[MAP_USER].Offset || offset >= mapEnd)) { 275 return true; 276 } 277 } 278 return false; 279 } 280 281 282 /** 283 * Tests the subdata range parameters and sets the GL error code for 284 * \c glBufferSubDataARB, \c glGetBufferSubDataARB and 285 * \c glClearBufferSubData. 286 * 287 * \param ctx GL context. 288 * \param bufObj The buffer object. 289 * \param offset Offset of the first byte of the subdata range. 290 * \param size Size, in bytes, of the subdata range. 291 * \param mappedRange If true, checks if an overlapping range is mapped. 292 * If false, checks if buffer is mapped. 293 * \param caller Name of calling function for recording errors. 294 * \return false if error, true otherwise 295 * 296 * \sa glBufferSubDataARB, glGetBufferSubDataARB, glClearBufferSubData 297 */ 298 static bool 299 buffer_object_subdata_range_good(struct gl_context *ctx, 300 const struct gl_buffer_object *bufObj, 301 GLintptr offset, GLsizeiptr size, 302 bool mappedRange, const char *caller) 303 { 304 if (size < 0) { 305 _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", caller); 306 return false; 307 } 308 309 if (offset < 0) { 310 _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset < 0)", caller); 311 return false; 312 } 313 314 if (offset + size > bufObj->Size) { 315 _mesa_error(ctx, GL_INVALID_VALUE, 316 "%s(offset %lu + size %lu > buffer size %lu)", caller, 317 (unsigned long) offset, 318 (unsigned long) size, 319 (unsigned long) bufObj->Size); 320 return false; 321 } 322 323 if (bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_PERSISTENT_BIT) 324 return true; 325 326 if (mappedRange) { 327 if (bufferobj_range_mapped(bufObj, offset, size)) { 328 _mesa_error(ctx, GL_INVALID_OPERATION, 329 "%s(range is mapped without persistent bit)", 330 caller); 331 return false; 332 } 333 } 334 else { 335 if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) { 336 _mesa_error(ctx, GL_INVALID_OPERATION, 337 "%s(buffer is mapped without persistent bit)", 338 caller); 339 return false; 340 } 341 } 342 343 return true; 344 } 345 346 347 /** 348 * Test the format and type parameters and set the GL error code for 349 * \c glClearBufferData and \c glClearBufferSubData. 350 * 351 * \param ctx GL context. 352 * \param internalformat Format to which the data is to be converted. 353 * \param format Format of the supplied data. 354 * \param type Type of the supplied data. 355 * \param caller Name of calling function for recording errors. 356 * \return If internalformat, format and type are legal the mesa_format 357 * corresponding to internalformat, otherwise MESA_FORMAT_NONE. 358 * 359 * \sa glClearBufferData and glClearBufferSubData 360 */ 361 static mesa_format 362 validate_clear_buffer_format(struct gl_context *ctx, 363 GLenum internalformat, 364 GLenum format, GLenum type, 365 const char *caller) 366 { 367 mesa_format mesaFormat; 368 GLenum errorFormatType; 369 370 mesaFormat = _mesa_validate_texbuffer_format(ctx, internalformat); 371 if (mesaFormat == MESA_FORMAT_NONE) { 372 _mesa_error(ctx, GL_INVALID_ENUM, 373 "%s(invalid internalformat)", caller); 374 return MESA_FORMAT_NONE; 375 } 376 377 /* NOTE: not mentioned in ARB_clear_buffer_object but according to 378 * EXT_texture_integer there is no conversion between integer and 379 * non-integer formats 380 */ 381 if (_mesa_is_enum_format_signed_int(format) != 382 _mesa_is_format_integer_color(mesaFormat)) { 383 _mesa_error(ctx, GL_INVALID_OPERATION, 384 "%s(integer vs non-integer)", caller); 385 return MESA_FORMAT_NONE; 386 } 387 388 if (!_mesa_is_color_format(format)) { 389 _mesa_error(ctx, GL_INVALID_ENUM, 390 "%s(format is not a color format)", caller); 391 return MESA_FORMAT_NONE; 392 } 393 394 errorFormatType = _mesa_error_check_format_and_type(ctx, format, type); 395 if (errorFormatType != GL_NO_ERROR) { 396 _mesa_error(ctx, GL_INVALID_ENUM, 397 "%s(invalid format or type)", caller); 398 return MESA_FORMAT_NONE; 399 } 400 401 return mesaFormat; 402 } 403 404 405 /** 406 * Convert user-specified clear value to the specified internal format. 407 * 408 * \param ctx GL context. 409 * \param internalformat Format to which the data is converted. 410 * \param clearValue Points to the converted clear value. 411 * \param format Format of the supplied data. 412 * \param type Type of the supplied data. 413 * \param data Data which is to be converted to internalformat. 414 * \param caller Name of calling function for recording errors. 415 * \return true if data could be converted, false otherwise. 416 * 417 * \sa glClearBufferData, glClearBufferSubData 418 */ 419 static bool 420 convert_clear_buffer_data(struct gl_context *ctx, 421 mesa_format internalformat, 422 GLubyte *clearValue, GLenum format, GLenum type, 423 const GLvoid *data, const char *caller) 424 { 425 GLenum internalformatBase = _mesa_get_format_base_format(internalformat); 426 427 if (_mesa_texstore(ctx, 1, internalformatBase, internalformat, 428 0, &clearValue, 1, 1, 1, 429 format, type, data, &ctx->Unpack)) { 430 return true; 431 } 432 else { 433 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); 434 return false; 435 } 436 } 437 438 439 /** 440 * Allocate and initialize a new buffer object. 441 * 442 * Default callback for the \c dd_function_table::NewBufferObject() hook. 443 */ 444 static struct gl_buffer_object * 445 _mesa_new_buffer_object(struct gl_context *ctx, GLuint name) 446 { 447 struct gl_buffer_object *obj = MALLOC_STRUCT(gl_buffer_object); 448 if (!obj) 449 return NULL; 450 451 _mesa_initialize_buffer_object(ctx, obj, name); 452 return obj; 453 } 454 455 456 /** 457 * Delete a buffer object. 458 * 459 * Default callback for the \c dd_function_table::DeleteBuffer() hook. 460 */ 461 void 462 _mesa_delete_buffer_object(struct gl_context *ctx, 463 struct gl_buffer_object *bufObj) 464 { 465 (void) ctx; 466 467 vbo_delete_minmax_cache(bufObj); 468 _mesa_align_free(bufObj->Data); 469 470 /* assign strange values here to help w/ debugging */ 471 bufObj->RefCount = -1000; 472 bufObj->Name = ~0; 473 474 simple_mtx_destroy(&bufObj->Mutex); 475 free(bufObj->Label); 476 free(bufObj); 477 } 478 479 480 481 /** 482 * Set ptr to bufObj w/ reference counting. 483 * This is normally only called from the _mesa_reference_buffer_object() macro 484 * when there's a real pointer change. 485 */ 486 void 487 _mesa_reference_buffer_object_(struct gl_context *ctx, 488 struct gl_buffer_object **ptr, 489 struct gl_buffer_object *bufObj) 490 { 491 if (*ptr) { 492 /* Unreference the old buffer */ 493 GLboolean deleteFlag = GL_FALSE; 494 struct gl_buffer_object *oldObj = *ptr; 495 496 simple_mtx_lock(&oldObj->Mutex); 497 assert(oldObj->RefCount > 0); 498 oldObj->RefCount--; 499 deleteFlag = (oldObj->RefCount == 0); 500 simple_mtx_unlock(&oldObj->Mutex); 501 502 if (deleteFlag) { 503 assert(ctx->Driver.DeleteBuffer); 504 ctx->Driver.DeleteBuffer(ctx, oldObj); 505 } 506 507 *ptr = NULL; 508 } 509 assert(!*ptr); 510 511 if (bufObj) { 512 /* reference new buffer */ 513 simple_mtx_lock(&bufObj->Mutex); 514 assert(bufObj->RefCount > 0); 515 516 bufObj->RefCount++; 517 *ptr = bufObj; 518 simple_mtx_unlock(&bufObj->Mutex); 519 } 520 } 521 522 523 /** 524 * Get the value of MESA_NO_MINMAX_CACHE. 525 */ 526 static bool 527 get_no_minmax_cache() 528 { 529 static bool read = false; 530 static bool disable = false; 531 532 if (!read) { 533 disable = env_var_as_boolean("MESA_NO_MINMAX_CACHE", false); 534 read = true; 535 } 536 537 return disable; 538 } 539 540 541 /** 542 * Initialize a buffer object to default values. 543 */ 544 void 545 _mesa_initialize_buffer_object(struct gl_context *ctx, 546 struct gl_buffer_object *obj, 547 GLuint name) 548 { 549 memset(obj, 0, sizeof(struct gl_buffer_object)); 550 simple_mtx_init(&obj->Mutex, mtx_plain); 551 obj->RefCount = 1; 552 obj->Name = name; 553 obj->Usage = GL_STATIC_DRAW_ARB; 554 555 if (get_no_minmax_cache()) 556 obj->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE; 557 } 558 559 560 561 /** 562 * Callback called from _mesa_HashWalk() 563 */ 564 static void 565 count_buffer_size(GLuint key, void *data, void *userData) 566 { 567 const struct gl_buffer_object *bufObj = 568 (const struct gl_buffer_object *) data; 569 GLuint *total = (GLuint *) userData; 570 571 (void) key; 572 *total = *total + bufObj->Size; 573 } 574 575 576 /** 577 * Compute total size (in bytes) of all buffer objects for the given context. 578 * For debugging purposes. 579 */ 580 GLuint 581 _mesa_total_buffer_object_memory(struct gl_context *ctx) 582 { 583 GLuint total = 0; 584 585 _mesa_HashWalk(ctx->Shared->BufferObjects, count_buffer_size, &total); 586 587 return total; 588 } 589 590 591 /** 592 * Allocate space for and store data in a buffer object. Any data that was 593 * previously stored in the buffer object is lost. If \c data is \c NULL, 594 * memory will be allocated, but no copy will occur. 595 * 596 * This is the default callback for \c dd_function_table::BufferData() 597 * Note that all GL error checking will have been done already. 598 * 599 * \param ctx GL context. 600 * \param target Buffer object target on which to operate. 601 * \param size Size, in bytes, of the new data store. 602 * \param data Pointer to the data to store in the buffer object. This 603 * pointer may be \c NULL. 604 * \param usage Hints about how the data will be used. 605 * \param bufObj Object to be used. 606 * 607 * \return GL_TRUE for success, GL_FALSE for failure 608 * \sa glBufferDataARB, dd_function_table::BufferData. 609 */ 610 static GLboolean 611 buffer_data_fallback(struct gl_context *ctx, GLenum target, GLsizeiptr size, 612 const GLvoid *data, GLenum usage, GLenum storageFlags, 613 struct gl_buffer_object *bufObj) 614 { 615 void * new_data; 616 617 (void) target; 618 619 _mesa_align_free( bufObj->Data ); 620 621 new_data = _mesa_align_malloc( size, ctx->Const.MinMapBufferAlignment ); 622 if (new_data) { 623 bufObj->Data = (GLubyte *) new_data; 624 bufObj->Size = size; 625 bufObj->Usage = usage; 626 bufObj->StorageFlags = storageFlags; 627 628 if (data) { 629 memcpy( bufObj->Data, data, size ); 630 } 631 632 return GL_TRUE; 633 } 634 else { 635 return GL_FALSE; 636 } 637 } 638 639 640 /** 641 * Replace data in a subrange of buffer object. If the data range 642 * specified by \c size + \c offset extends beyond the end of the buffer or 643 * if \c data is \c NULL, no copy is performed. 644 * 645 * This is the default callback for \c dd_function_table::BufferSubData() 646 * Note that all GL error checking will have been done already. 647 * 648 * \param ctx GL context. 649 * \param offset Offset of the first byte to be modified. 650 * \param size Size, in bytes, of the data range. 651 * \param data Pointer to the data to store in the buffer object. 652 * \param bufObj Object to be used. 653 * 654 * \sa glBufferSubDataARB, dd_function_table::BufferSubData. 655 */ 656 static void 657 buffer_sub_data_fallback(struct gl_context *ctx, GLintptr offset, 658 GLsizeiptr size, const GLvoid *data, 659 struct gl_buffer_object *bufObj) 660 { 661 (void) ctx; 662 663 /* this should have been caught in _mesa_BufferSubData() */ 664 assert(size + offset <= bufObj->Size); 665 666 if (bufObj->Data) { 667 memcpy( (GLubyte *) bufObj->Data + offset, data, size ); 668 } 669 } 670 671 672 /** 673 * Retrieve data from a subrange of buffer object. If the data range 674 * specified by \c size + \c offset extends beyond the end of the buffer or 675 * if \c data is \c NULL, no copy is performed. 676 * 677 * This is the default callback for \c dd_function_table::GetBufferSubData() 678 * Note that all GL error checking will have been done already. 679 * 680 * \param ctx GL context. 681 * \param target Buffer object target on which to operate. 682 * \param offset Offset of the first byte to be fetched. 683 * \param size Size, in bytes, of the data range. 684 * \param data Destination for data 685 * \param bufObj Object to be used. 686 * 687 * \sa glBufferGetSubDataARB, dd_function_table::GetBufferSubData. 688 */ 689 static void 690 buffer_get_subdata(struct gl_context *ctx, GLintptrARB offset, 691 GLsizeiptrARB size, GLvoid *data, 692 struct gl_buffer_object *bufObj ) 693 { 694 (void) ctx; 695 696 if (bufObj->Data && ((GLsizeiptrARB) (size + offset) <= bufObj->Size)) { 697 memcpy( data, (GLubyte *) bufObj->Data + offset, size ); 698 } 699 } 700 701 702 /** 703 * Clear a subrange of the buffer object with copies of the supplied data. 704 * If data is NULL the buffer is filled with zeros. 705 * 706 * This is the default callback for \c dd_function_table::ClearBufferSubData() 707 * Note that all GL error checking will have been done already. 708 * 709 * \param ctx GL context. 710 * \param offset Offset of the first byte to be cleared. 711 * \param size Size, in bytes, of the to be cleared range. 712 * \param clearValue Source of the data. 713 * \param clearValueSize Size, in bytes, of the supplied data. 714 * \param bufObj Object to be cleared. 715 * 716 * \sa glClearBufferSubData, glClearBufferData and 717 * dd_function_table::ClearBufferSubData. 718 */ 719 void 720 _mesa_ClearBufferSubData_sw(struct gl_context *ctx, 721 GLintptr offset, GLsizeiptr size, 722 const GLvoid *clearValue, 723 GLsizeiptr clearValueSize, 724 struct gl_buffer_object *bufObj) 725 { 726 GLsizeiptr i; 727 GLubyte *dest; 728 729 assert(ctx->Driver.MapBufferRange); 730 dest = ctx->Driver.MapBufferRange(ctx, offset, size, 731 GL_MAP_WRITE_BIT | 732 GL_MAP_INVALIDATE_RANGE_BIT, 733 bufObj, MAP_INTERNAL); 734 735 if (!dest) { 736 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClearBuffer[Sub]Data"); 737 return; 738 } 739 740 if (clearValue == NULL) { 741 /* Clear with zeros, per the spec */ 742 memset(dest, 0, size); 743 ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_INTERNAL); 744 return; 745 } 746 747 for (i = 0; i < size/clearValueSize; ++i) { 748 memcpy(dest, clearValue, clearValueSize); 749 dest += clearValueSize; 750 } 751 752 ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_INTERNAL); 753 } 754 755 756 /** 757 * Default fallback for \c dd_function_table::MapBufferRange(). 758 * Called via glMapBufferRange(). 759 */ 760 static void * 761 map_buffer_range_fallback(struct gl_context *ctx, GLintptr offset, 762 GLsizeiptr length, GLbitfield access, 763 struct gl_buffer_object *bufObj, 764 gl_map_buffer_index index) 765 { 766 (void) ctx; 767 assert(!_mesa_bufferobj_mapped(bufObj, index)); 768 /* Just return a direct pointer to the data */ 769 bufObj->Mappings[index].Pointer = bufObj->Data + offset; 770 bufObj->Mappings[index].Length = length; 771 bufObj->Mappings[index].Offset = offset; 772 bufObj->Mappings[index].AccessFlags = access; 773 return bufObj->Mappings[index].Pointer; 774 } 775 776 777 /** 778 * Default fallback for \c dd_function_table::FlushMappedBufferRange(). 779 * Called via glFlushMappedBufferRange(). 780 */ 781 static void 782 flush_mapped_buffer_range_fallback(struct gl_context *ctx, 783 GLintptr offset, GLsizeiptr length, 784 struct gl_buffer_object *obj, 785 gl_map_buffer_index index) 786 { 787 (void) ctx; 788 (void) offset; 789 (void) length; 790 (void) obj; 791 (void) index; 792 /* no-op */ 793 } 794 795 796 /** 797 * Default callback for \c dd_function_table::UnmapBuffer(). 798 * 799 * The input parameters will have been already tested for errors. 800 * 801 * \sa glUnmapBufferARB, dd_function_table::UnmapBuffer 802 */ 803 static GLboolean 804 unmap_buffer_fallback(struct gl_context *ctx, struct gl_buffer_object *bufObj, 805 gl_map_buffer_index index) 806 { 807 (void) ctx; 808 /* XXX we might assert here that bufObj->Pointer is non-null */ 809 bufObj->Mappings[index].Pointer = NULL; 810 bufObj->Mappings[index].Length = 0; 811 bufObj->Mappings[index].Offset = 0; 812 bufObj->Mappings[index].AccessFlags = 0x0; 813 return GL_TRUE; 814 } 815 816 817 /** 818 * Default fallback for \c dd_function_table::CopyBufferSubData(). 819 * Called via glCopyBufferSubData(). 820 */ 821 static void 822 copy_buffer_sub_data_fallback(struct gl_context *ctx, 823 struct gl_buffer_object *src, 824 struct gl_buffer_object *dst, 825 GLintptr readOffset, GLintptr writeOffset, 826 GLsizeiptr size) 827 { 828 GLubyte *srcPtr, *dstPtr; 829 830 if (src == dst) { 831 srcPtr = dstPtr = ctx->Driver.MapBufferRange(ctx, 0, src->Size, 832 GL_MAP_READ_BIT | 833 GL_MAP_WRITE_BIT, src, 834 MAP_INTERNAL); 835 836 if (!srcPtr) 837 return; 838 839 srcPtr += readOffset; 840 dstPtr += writeOffset; 841 } else { 842 srcPtr = ctx->Driver.MapBufferRange(ctx, readOffset, size, 843 GL_MAP_READ_BIT, src, 844 MAP_INTERNAL); 845 dstPtr = ctx->Driver.MapBufferRange(ctx, writeOffset, size, 846 (GL_MAP_WRITE_BIT | 847 GL_MAP_INVALIDATE_RANGE_BIT), dst, 848 MAP_INTERNAL); 849 } 850 851 /* Note: the src and dst regions will never overlap. Trying to do so 852 * would generate GL_INVALID_VALUE earlier. 853 */ 854 if (srcPtr && dstPtr) 855 memcpy(dstPtr, srcPtr, size); 856 857 ctx->Driver.UnmapBuffer(ctx, src, MAP_INTERNAL); 858 if (dst != src) 859 ctx->Driver.UnmapBuffer(ctx, dst, MAP_INTERNAL); 860 } 861 862 863 864 /** 865 * Initialize the state associated with buffer objects 866 */ 867 void 868 _mesa_init_buffer_objects( struct gl_context *ctx ) 869 { 870 GLuint i; 871 872 memset(&DummyBufferObject, 0, sizeof(DummyBufferObject)); 873 simple_mtx_init(&DummyBufferObject.Mutex, mtx_plain); 874 DummyBufferObject.RefCount = 1000*1000*1000; /* never delete */ 875 876 _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, 877 ctx->Shared->NullBufferObj); 878 879 _mesa_reference_buffer_object(ctx, &ctx->CopyReadBuffer, 880 ctx->Shared->NullBufferObj); 881 _mesa_reference_buffer_object(ctx, &ctx->CopyWriteBuffer, 882 ctx->Shared->NullBufferObj); 883 884 _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, 885 ctx->Shared->NullBufferObj); 886 887 _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer, 888 ctx->Shared->NullBufferObj); 889 890 _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, 891 ctx->Shared->NullBufferObj); 892 893 _mesa_reference_buffer_object(ctx, &ctx->DrawIndirectBuffer, 894 ctx->Shared->NullBufferObj); 895 896 _mesa_reference_buffer_object(ctx, &ctx->ParameterBuffer, 897 ctx->Shared->NullBufferObj); 898 899 _mesa_reference_buffer_object(ctx, &ctx->DispatchIndirectBuffer, 900 ctx->Shared->NullBufferObj); 901 902 _mesa_reference_buffer_object(ctx, &ctx->QueryBuffer, 903 ctx->Shared->NullBufferObj); 904 905 for (i = 0; i < MAX_COMBINED_UNIFORM_BUFFERS; i++) { 906 _mesa_reference_buffer_object(ctx, 907 &ctx->UniformBufferBindings[i].BufferObject, 908 ctx->Shared->NullBufferObj); 909 ctx->UniformBufferBindings[i].Offset = -1; 910 ctx->UniformBufferBindings[i].Size = -1; 911 } 912 913 for (i = 0; i < MAX_COMBINED_SHADER_STORAGE_BUFFERS; i++) { 914 _mesa_reference_buffer_object(ctx, 915 &ctx->ShaderStorageBufferBindings[i].BufferObject, 916 ctx->Shared->NullBufferObj); 917 ctx->ShaderStorageBufferBindings[i].Offset = -1; 918 ctx->ShaderStorageBufferBindings[i].Size = -1; 919 } 920 921 for (i = 0; i < MAX_COMBINED_ATOMIC_BUFFERS; i++) { 922 _mesa_reference_buffer_object(ctx, 923 &ctx->AtomicBufferBindings[i].BufferObject, 924 ctx->Shared->NullBufferObj); 925 ctx->AtomicBufferBindings[i].Offset = 0; 926 ctx->AtomicBufferBindings[i].Size = 0; 927 } 928 } 929 930 931 void 932 _mesa_free_buffer_objects( struct gl_context *ctx ) 933 { 934 GLuint i; 935 936 _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, NULL); 937 938 _mesa_reference_buffer_object(ctx, &ctx->CopyReadBuffer, NULL); 939 _mesa_reference_buffer_object(ctx, &ctx->CopyWriteBuffer, NULL); 940 941 _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, NULL); 942 943 _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer, NULL); 944 945 _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, NULL); 946 947 _mesa_reference_buffer_object(ctx, &ctx->DrawIndirectBuffer, NULL); 948 949 _mesa_reference_buffer_object(ctx, &ctx->ParameterBuffer, NULL); 950 951 _mesa_reference_buffer_object(ctx, &ctx->DispatchIndirectBuffer, NULL); 952 953 _mesa_reference_buffer_object(ctx, &ctx->QueryBuffer, NULL); 954 955 for (i = 0; i < MAX_COMBINED_UNIFORM_BUFFERS; i++) { 956 _mesa_reference_buffer_object(ctx, 957 &ctx->UniformBufferBindings[i].BufferObject, 958 NULL); 959 } 960 961 for (i = 0; i < MAX_COMBINED_SHADER_STORAGE_BUFFERS; i++) { 962 _mesa_reference_buffer_object(ctx, 963 &ctx->ShaderStorageBufferBindings[i].BufferObject, 964 NULL); 965 } 966 967 for (i = 0; i < MAX_COMBINED_ATOMIC_BUFFERS; i++) { 968 _mesa_reference_buffer_object(ctx, 969 &ctx->AtomicBufferBindings[i].BufferObject, 970 NULL); 971 } 972 973 } 974 975 bool 976 _mesa_handle_bind_buffer_gen(struct gl_context *ctx, 977 GLuint buffer, 978 struct gl_buffer_object **buf_handle, 979 const char *caller) 980 { 981 struct gl_buffer_object *buf = *buf_handle; 982 983 if (!buf && (ctx->API == API_OPENGL_CORE)) { 984 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-gen name)", caller); 985 return false; 986 } 987 988 if (!buf || buf == &DummyBufferObject) { 989 /* If this is a new buffer object id, or one which was generated but 990 * never used before, allocate a buffer object now. 991 */ 992 buf = ctx->Driver.NewBufferObject(ctx, buffer); 993 if (!buf) { 994 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); 995 return false; 996 } 997 _mesa_HashInsert(ctx->Shared->BufferObjects, buffer, buf); 998 *buf_handle = buf; 999 } 1000 1001 return true; 1002 } 1003 1004 /** 1005 * Bind the specified target to buffer for the specified context. 1006 * Called by glBindBuffer() and other functions. 1007 */ 1008 static void 1009 bind_buffer_object(struct gl_context *ctx, 1010 struct gl_buffer_object **bindTarget, GLuint buffer) 1011 { 1012 struct gl_buffer_object *oldBufObj; 1013 struct gl_buffer_object *newBufObj = NULL; 1014 1015 assert(bindTarget); 1016 1017 /* Get pointer to old buffer object (to be unbound) */ 1018 oldBufObj = *bindTarget; 1019 if (oldBufObj && oldBufObj->Name == buffer && !oldBufObj->DeletePending) 1020 return; /* rebinding the same buffer object- no change */ 1021 1022 /* 1023 * Get pointer to new buffer object (newBufObj) 1024 */ 1025 if (buffer == 0) { 1026 /* The spec says there's not a buffer object named 0, but we use 1027 * one internally because it simplifies things. 1028 */ 1029 newBufObj = ctx->Shared->NullBufferObj; 1030 } 1031 else { 1032 /* non-default buffer object */ 1033 newBufObj = _mesa_lookup_bufferobj(ctx, buffer); 1034 if (!_mesa_handle_bind_buffer_gen(ctx, buffer, 1035 &newBufObj, "glBindBuffer")) 1036 return; 1037 } 1038 1039 /* record usage history */ 1040 if (bindTarget == &ctx->Pack.BufferObj) { 1041 newBufObj->UsageHistory |= USAGE_PIXEL_PACK_BUFFER; 1042 } 1043 1044 /* bind new buffer */ 1045 _mesa_reference_buffer_object(ctx, bindTarget, newBufObj); 1046 } 1047 1048 1049 /** 1050 * Update the default buffer objects in the given context to reference those 1051 * specified in the shared state and release those referencing the old 1052 * shared state. 1053 */ 1054 void 1055 _mesa_update_default_objects_buffer_objects(struct gl_context *ctx) 1056 { 1057 /* Bind the NullBufferObj to remove references to those 1058 * in the shared context hash table. 1059 */ 1060 bind_buffer_object(ctx, &ctx->Array.ArrayBufferObj, 0); 1061 bind_buffer_object(ctx, &ctx->Array.VAO->IndexBufferObj, 0); 1062 bind_buffer_object(ctx, &ctx->Pack.BufferObj, 0); 1063 bind_buffer_object(ctx, &ctx->Unpack.BufferObj, 0); 1064 } 1065 1066 1067 1068 /** 1069 * Return the gl_buffer_object for the given ID. 1070 * Always return NULL for ID 0. 1071 */ 1072 struct gl_buffer_object * 1073 _mesa_lookup_bufferobj(struct gl_context *ctx, GLuint buffer) 1074 { 1075 if (buffer == 0) 1076 return NULL; 1077 else 1078 return (struct gl_buffer_object *) 1079 _mesa_HashLookup(ctx->Shared->BufferObjects, buffer); 1080 } 1081 1082 1083 struct gl_buffer_object * 1084 _mesa_lookup_bufferobj_locked(struct gl_context *ctx, GLuint buffer) 1085 { 1086 if (buffer == 0) 1087 return NULL; 1088 else 1089 return (struct gl_buffer_object *) 1090 _mesa_HashLookupLocked(ctx->Shared->BufferObjects, buffer); 1091 } 1092 1093 /** 1094 * A convenience function for direct state access functions that throws 1095 * GL_INVALID_OPERATION if buffer is not the name of an existing 1096 * buffer object. 1097 */ 1098 struct gl_buffer_object * 1099 _mesa_lookup_bufferobj_err(struct gl_context *ctx, GLuint buffer, 1100 const char *caller) 1101 { 1102 struct gl_buffer_object *bufObj; 1103 1104 bufObj = _mesa_lookup_bufferobj(ctx, buffer); 1105 if (!bufObj || bufObj == &DummyBufferObject) { 1106 _mesa_error(ctx, GL_INVALID_OPERATION, 1107 "%s(non-existent buffer object %u)", caller, buffer); 1108 return NULL; 1109 } 1110 1111 return bufObj; 1112 } 1113 1114 1115 /** 1116 * Look up a buffer object for a multi-bind function. 1117 * 1118 * Unlike _mesa_lookup_bufferobj(), this function also takes care 1119 * of generating an error if the buffer ID is not zero or the name 1120 * of an existing buffer object. 1121 * 1122 * If the buffer ID refers to an existing buffer object, a pointer 1123 * to the buffer object is returned. If the ID is zero, a pointer 1124 * to the shared NullBufferObj is returned. If the ID is not zero 1125 * and does not refer to a valid buffer object, this function 1126 * returns NULL. 1127 * 1128 * This function assumes that the caller has already locked the 1129 * hash table mutex by calling 1130 * _mesa_HashLockMutex(ctx->Shared->BufferObjects). 1131 */ 1132 struct gl_buffer_object * 1133 _mesa_multi_bind_lookup_bufferobj(struct gl_context *ctx, 1134 const GLuint *buffers, 1135 GLuint index, const char *caller) 1136 { 1137 struct gl_buffer_object *bufObj; 1138 1139 if (buffers[index] != 0) { 1140 bufObj = _mesa_lookup_bufferobj_locked(ctx, buffers[index]); 1141 1142 /* The multi-bind functions don't create the buffer objects 1143 when they don't exist. */ 1144 if (bufObj == &DummyBufferObject) 1145 bufObj = NULL; 1146 } else 1147 bufObj = ctx->Shared->NullBufferObj; 1148 1149 if (!bufObj) { 1150 /* The ARB_multi_bind spec says: 1151 * 1152 * "An INVALID_OPERATION error is generated if any value 1153 * in <buffers> is not zero or the name of an existing 1154 * buffer object (per binding)." 1155 */ 1156 _mesa_error(ctx, GL_INVALID_OPERATION, 1157 "%s(buffers[%u]=%u is not zero or the name " 1158 "of an existing buffer object)", 1159 caller, index, buffers[index]); 1160 } 1161 1162 return bufObj; 1163 } 1164 1165 1166 /** 1167 * If *ptr points to obj, set ptr = the Null/default buffer object. 1168 * This is a helper for buffer object deletion. 1169 * The GL spec says that deleting a buffer object causes it to get 1170 * unbound from all arrays in the current context. 1171 */ 1172 static void 1173 unbind(struct gl_context *ctx, 1174 struct gl_vertex_array_object *vao, unsigned index, 1175 struct gl_buffer_object *obj) 1176 { 1177 if (vao->BufferBinding[index].BufferObj == obj) { 1178 _mesa_bind_vertex_buffer(ctx, vao, index, ctx->Shared->NullBufferObj, 1179 vao->BufferBinding[index].Offset, 1180 vao->BufferBinding[index].Stride); 1181 } 1182 } 1183 1184 1185 /** 1186 * Plug default/fallback buffer object functions into the device 1187 * driver hooks. 1188 */ 1189 void 1190 _mesa_init_buffer_object_functions(struct dd_function_table *driver) 1191 { 1192 /* GL_ARB_vertex/pixel_buffer_object */ 1193 driver->NewBufferObject = _mesa_new_buffer_object; 1194 driver->DeleteBuffer = _mesa_delete_buffer_object; 1195 driver->BufferData = buffer_data_fallback; 1196 driver->BufferSubData = buffer_sub_data_fallback; 1197 driver->GetBufferSubData = buffer_get_subdata; 1198 driver->UnmapBuffer = unmap_buffer_fallback; 1199 1200 /* GL_ARB_clear_buffer_object */ 1201 driver->ClearBufferSubData = _mesa_ClearBufferSubData_sw; 1202 1203 /* GL_ARB_map_buffer_range */ 1204 driver->MapBufferRange = map_buffer_range_fallback; 1205 driver->FlushMappedBufferRange = flush_mapped_buffer_range_fallback; 1206 1207 /* GL_ARB_copy_buffer */ 1208 driver->CopyBufferSubData = copy_buffer_sub_data_fallback; 1209 } 1210 1211 1212 void 1213 _mesa_buffer_unmap_all_mappings(struct gl_context *ctx, 1214 struct gl_buffer_object *bufObj) 1215 { 1216 for (int i = 0; i < MAP_COUNT; i++) { 1217 if (_mesa_bufferobj_mapped(bufObj, i)) { 1218 ctx->Driver.UnmapBuffer(ctx, bufObj, i); 1219 assert(bufObj->Mappings[i].Pointer == NULL); 1220 bufObj->Mappings[i].AccessFlags = 0; 1221 } 1222 } 1223 } 1224 1225 1226 /**********************************************************************/ 1227 /* API Functions */ 1228 /**********************************************************************/ 1229 1230 void GLAPIENTRY 1231 _mesa_BindBuffer_no_error(GLenum target, GLuint buffer) 1232 { 1233 GET_CURRENT_CONTEXT(ctx); 1234 1235 struct gl_buffer_object **bindTarget = get_buffer_target(ctx, target); 1236 bind_buffer_object(ctx, bindTarget, buffer); 1237 } 1238 1239 1240 void GLAPIENTRY 1241 _mesa_BindBuffer(GLenum target, GLuint buffer) 1242 { 1243 GET_CURRENT_CONTEXT(ctx); 1244 1245 if (MESA_VERBOSE & VERBOSE_API) { 1246 _mesa_debug(ctx, "glBindBuffer(%s, %u)\n", 1247 _mesa_enum_to_string(target), buffer); 1248 } 1249 1250 struct gl_buffer_object **bindTarget = get_buffer_target(ctx, target); 1251 if (!bindTarget) { 1252 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target %s)", 1253 _mesa_enum_to_string(target)); 1254 return; 1255 } 1256 1257 bind_buffer_object(ctx, bindTarget, buffer); 1258 } 1259 1260 /** 1261 * Binds a buffer object to a binding point. 1262 * 1263 * The caller is responsible for validating the offset, 1264 * flushing the vertices and updating NewDriverState. 1265 */ 1266 static void 1267 set_buffer_binding(struct gl_context *ctx, 1268 struct gl_buffer_binding *binding, 1269 struct gl_buffer_object *bufObj, 1270 GLintptr offset, 1271 GLsizeiptr size, 1272 bool autoSize, gl_buffer_usage usage) 1273 { 1274 _mesa_reference_buffer_object(ctx, &binding->BufferObject, bufObj); 1275 1276 binding->Offset = offset; 1277 binding->Size = size; 1278 binding->AutomaticSize = autoSize; 1279 1280 /* If this is a real buffer object, mark it has having been used 1281 * at some point as an atomic counter buffer. 1282 */ 1283 if (size >= 0) 1284 bufObj->UsageHistory |= usage; 1285 } 1286 1287 static void 1288 set_buffer_multi_binding(struct gl_context *ctx, 1289 const GLuint *buffers, 1290 int idx, 1291 const char *caller, 1292 struct gl_buffer_binding *binding, 1293 GLintptr offset, 1294 GLsizeiptr size, 1295 bool range, 1296 gl_buffer_usage usage) 1297 { 1298 struct gl_buffer_object *bufObj; 1299 if (binding->BufferObject && binding->BufferObject->Name == buffers[idx]) 1300 bufObj = binding->BufferObject; 1301 else 1302 bufObj = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, idx, caller); 1303 1304 if (bufObj) { 1305 if (bufObj == ctx->Shared->NullBufferObj) 1306 set_buffer_binding(ctx, binding, bufObj, -1, -1, !range, usage); 1307 else 1308 set_buffer_binding(ctx, binding, bufObj, offset, size, !range, usage); 1309 } 1310 } 1311 1312 static void 1313 bind_buffer(struct gl_context *ctx, 1314 struct gl_buffer_binding *binding, 1315 struct gl_buffer_object *bufObj, 1316 GLintptr offset, 1317 GLsizeiptr size, 1318 GLboolean autoSize, 1319 uint64_t driver_state, 1320 gl_buffer_usage usage) 1321 { 1322 if (binding->BufferObject == bufObj && 1323 binding->Offset == offset && 1324 binding->Size == size && 1325 binding->AutomaticSize == autoSize) { 1326 return; 1327 } 1328 1329 FLUSH_VERTICES(ctx, 0); 1330 ctx->NewDriverState |= driver_state; 1331 1332 set_buffer_binding(ctx, binding, bufObj, offset, size, autoSize, usage); 1333 } 1334 1335 /** 1336 * Binds a buffer object to a uniform buffer binding point. 1337 * 1338 * Unlike set_buffer_binding(), this function also flushes vertices 1339 * and updates NewDriverState. It also checks if the binding 1340 * has actually changed before updating it. 1341 */ 1342 static void 1343 bind_uniform_buffer(struct gl_context *ctx, 1344 GLuint index, 1345 struct gl_buffer_object *bufObj, 1346 GLintptr offset, 1347 GLsizeiptr size, 1348 GLboolean autoSize) 1349 { 1350 bind_buffer(ctx, &ctx->UniformBufferBindings[index], 1351 bufObj, offset, size, autoSize, 1352 ctx->DriverFlags.NewUniformBuffer, 1353 USAGE_UNIFORM_BUFFER); 1354 } 1355 1356 /** 1357 * Binds a buffer object to a shader storage buffer binding point. 1358 * 1359 * Unlike set_ssbo_binding(), this function also flushes vertices 1360 * and updates NewDriverState. It also checks if the binding 1361 * has actually changed before updating it. 1362 */ 1363 static void 1364 bind_shader_storage_buffer(struct gl_context *ctx, 1365 GLuint index, 1366 struct gl_buffer_object *bufObj, 1367 GLintptr offset, 1368 GLsizeiptr size, 1369 GLboolean autoSize) 1370 { 1371 bind_buffer(ctx, &ctx->ShaderStorageBufferBindings[index], 1372 bufObj, offset, size, autoSize, 1373 ctx->DriverFlags.NewShaderStorageBuffer, 1374 USAGE_SHADER_STORAGE_BUFFER); 1375 } 1376 1377 /** 1378 * Binds a buffer object to an atomic buffer binding point. 1379 * 1380 * Unlike set_atomic_binding(), this function also flushes vertices 1381 * and updates NewDriverState. It also checks if the binding 1382 * has actually changed before updating it. 1383 */ 1384 static void 1385 bind_atomic_buffer(struct gl_context *ctx, unsigned index, 1386 struct gl_buffer_object *bufObj, GLintptr offset, 1387 GLsizeiptr size, GLboolean autoSize) 1388 { 1389 bind_buffer(ctx, &ctx->AtomicBufferBindings[index], 1390 bufObj, offset, size, autoSize, 1391 ctx->DriverFlags.NewAtomicBuffer, 1392 USAGE_ATOMIC_COUNTER_BUFFER); 1393 } 1394 1395 /** 1396 * Bind a buffer object to a uniform block binding point. 1397 * As above, but offset = 0. 1398 */ 1399 static void 1400 bind_buffer_base_uniform_buffer(struct gl_context *ctx, 1401 GLuint index, 1402 struct gl_buffer_object *bufObj) 1403 { 1404 if (index >= ctx->Const.MaxUniformBufferBindings) { 1405 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index); 1406 return; 1407 } 1408 1409 _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, bufObj); 1410 1411 if (bufObj == ctx->Shared->NullBufferObj) 1412 bind_uniform_buffer(ctx, index, bufObj, -1, -1, GL_TRUE); 1413 else 1414 bind_uniform_buffer(ctx, index, bufObj, 0, 0, GL_TRUE); 1415 } 1416 1417 /** 1418 * Bind a buffer object to a shader storage block binding point. 1419 * As above, but offset = 0. 1420 */ 1421 static void 1422 bind_buffer_base_shader_storage_buffer(struct gl_context *ctx, 1423 GLuint index, 1424 struct gl_buffer_object *bufObj) 1425 { 1426 if (index >= ctx->Const.MaxShaderStorageBufferBindings) { 1427 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index); 1428 return; 1429 } 1430 1431 _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer, bufObj); 1432 1433 if (bufObj == ctx->Shared->NullBufferObj) 1434 bind_shader_storage_buffer(ctx, index, bufObj, -1, -1, GL_TRUE); 1435 else 1436 bind_shader_storage_buffer(ctx, index, bufObj, 0, 0, GL_TRUE); 1437 } 1438 1439 /** 1440 * Bind a buffer object to a shader storage block binding point. 1441 * As above, but offset = 0. 1442 */ 1443 static void 1444 bind_buffer_base_atomic_buffer(struct gl_context *ctx, 1445 GLuint index, 1446 struct gl_buffer_object *bufObj) 1447 { 1448 if (index >= ctx->Const.MaxAtomicBufferBindings) { 1449 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index); 1450 return; 1451 } 1452 1453 _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, bufObj); 1454 1455 if (bufObj == ctx->Shared->NullBufferObj) 1456 bind_atomic_buffer(ctx, index, bufObj, -1, -1, GL_TRUE); 1457 else 1458 bind_atomic_buffer(ctx, index, bufObj, 0, 0, GL_TRUE); 1459 } 1460 1461 /** 1462 * Delete a set of buffer objects. 1463 * 1464 * \param n Number of buffer objects to delete. 1465 * \param ids Array of \c n buffer object IDs. 1466 */ 1467 static void 1468 delete_buffers(struct gl_context *ctx, GLsizei n, const GLuint *ids) 1469 { 1470 FLUSH_VERTICES(ctx, 0); 1471 1472 _mesa_HashLockMutex(ctx->Shared->BufferObjects); 1473 1474 for (GLsizei i = 0; i < n; i++) { 1475 struct gl_buffer_object *bufObj = 1476 _mesa_lookup_bufferobj_locked(ctx, ids[i]); 1477 if (bufObj) { 1478 struct gl_vertex_array_object *vao = ctx->Array.VAO; 1479 GLuint j; 1480 1481 assert(bufObj->Name == ids[i] || bufObj == &DummyBufferObject); 1482 1483 _mesa_buffer_unmap_all_mappings(ctx, bufObj); 1484 1485 /* unbind any vertex pointers bound to this buffer */ 1486 for (j = 0; j < ARRAY_SIZE(vao->BufferBinding); j++) { 1487 unbind(ctx, vao, j, bufObj); 1488 } 1489 1490 if (ctx->Array.ArrayBufferObj == bufObj) { 1491 bind_buffer_object(ctx, &ctx->Array.ArrayBufferObj, 0); 1492 } 1493 if (vao->IndexBufferObj == bufObj) { 1494 bind_buffer_object(ctx, &vao->IndexBufferObj, 0); 1495 } 1496 1497 /* unbind ARB_draw_indirect binding point */ 1498 if (ctx->DrawIndirectBuffer == bufObj) { 1499 bind_buffer_object(ctx, &ctx->DrawIndirectBuffer, 0); 1500 } 1501 1502 /* unbind ARB_indirect_parameters binding point */ 1503 if (ctx->ParameterBuffer == bufObj) { 1504 bind_buffer_object(ctx, &ctx->ParameterBuffer, 0); 1505 } 1506 1507 /* unbind ARB_compute_shader binding point */ 1508 if (ctx->DispatchIndirectBuffer == bufObj) { 1509 bind_buffer_object(ctx, &ctx->DispatchIndirectBuffer, 0); 1510 } 1511 1512 /* unbind ARB_copy_buffer binding points */ 1513 if (ctx->CopyReadBuffer == bufObj) { 1514 bind_buffer_object(ctx, &ctx->CopyReadBuffer, 0); 1515 } 1516 if (ctx->CopyWriteBuffer == bufObj) { 1517 bind_buffer_object(ctx, &ctx->CopyWriteBuffer, 0); 1518 } 1519 1520 /* unbind transform feedback binding points */ 1521 if (ctx->TransformFeedback.CurrentBuffer == bufObj) { 1522 bind_buffer_object(ctx, &ctx->TransformFeedback.CurrentBuffer, 0); 1523 } 1524 for (j = 0; j < MAX_FEEDBACK_BUFFERS; j++) { 1525 if (ctx->TransformFeedback.CurrentObject->Buffers[j] == bufObj) { 1526 _mesa_bind_buffer_base_transform_feedback(ctx, 1527 ctx->TransformFeedback.CurrentObject, 1528 j, ctx->Shared->NullBufferObj, 1529 false); 1530 } 1531 } 1532 1533 /* unbind UBO binding points */ 1534 for (j = 0; j < ctx->Const.MaxUniformBufferBindings; j++) { 1535 if (ctx->UniformBufferBindings[j].BufferObject == bufObj) { 1536 bind_buffer_base_uniform_buffer(ctx, j, 1537 ctx->Shared->NullBufferObj); 1538 } 1539 } 1540 1541 if (ctx->UniformBuffer == bufObj) { 1542 bind_buffer_object(ctx, &ctx->UniformBuffer, 0); 1543 } 1544 1545 /* unbind SSBO binding points */ 1546 for (j = 0; j < ctx->Const.MaxShaderStorageBufferBindings; j++) { 1547 if (ctx->ShaderStorageBufferBindings[j].BufferObject == bufObj) { 1548 bind_buffer_base_shader_storage_buffer(ctx, j, 1549 ctx->Shared->NullBufferObj); 1550 } 1551 } 1552 1553 if (ctx->ShaderStorageBuffer == bufObj) { 1554 bind_buffer_object(ctx, &ctx->ShaderStorageBuffer, 0); 1555 } 1556 1557 /* unbind Atomci Buffer binding points */ 1558 for (j = 0; j < ctx->Const.MaxAtomicBufferBindings; j++) { 1559 if (ctx->AtomicBufferBindings[j].BufferObject == bufObj) { 1560 bind_buffer_base_atomic_buffer(ctx, j, 1561 ctx->Shared->NullBufferObj); 1562 } 1563 } 1564 1565 if (ctx->AtomicBuffer == bufObj) { 1566 bind_buffer_object(ctx, &ctx->AtomicBuffer, 0); 1567 } 1568 1569 /* unbind any pixel pack/unpack pointers bound to this buffer */ 1570 if (ctx->Pack.BufferObj == bufObj) { 1571 bind_buffer_object(ctx, &ctx->Pack.BufferObj, 0); 1572 } 1573 if (ctx->Unpack.BufferObj == bufObj) { 1574 bind_buffer_object(ctx, &ctx->Unpack.BufferObj, 0); 1575 } 1576 1577 if (ctx->Texture.BufferObject == bufObj) { 1578 bind_buffer_object(ctx, &ctx->Texture.BufferObject, 0); 1579 } 1580 1581 if (ctx->ExternalVirtualMemoryBuffer == bufObj) { 1582 bind_buffer_object(ctx, &ctx->ExternalVirtualMemoryBuffer, 0); 1583 } 1584 1585 /* unbind query buffer binding point */ 1586 if (ctx->QueryBuffer == bufObj) { 1587 bind_buffer_object(ctx, &ctx->QueryBuffer, 0); 1588 } 1589 1590 /* The ID is immediately freed for re-use */ 1591 _mesa_HashRemoveLocked(ctx->Shared->BufferObjects, ids[i]); 1592 /* Make sure we do not run into the classic ABA problem on bind. 1593 * We don't want to allow re-binding a buffer object that's been 1594 * "deleted" by glDeleteBuffers(). 1595 * 1596 * The explicit rebinding to the default object in the current context 1597 * prevents the above in the current context, but another context 1598 * sharing the same objects might suffer from this problem. 1599 * The alternative would be to do the hash lookup in any case on bind 1600 * which would introduce more runtime overhead than this. 1601 */ 1602 bufObj->DeletePending = GL_TRUE; 1603 _mesa_reference_buffer_object(ctx, &bufObj, NULL); 1604 } 1605 } 1606 1607 _mesa_HashUnlockMutex(ctx->Shared->BufferObjects); 1608 } 1609 1610 1611 void GLAPIENTRY 1612 _mesa_DeleteBuffers_no_error(GLsizei n, const GLuint *ids) 1613 { 1614 GET_CURRENT_CONTEXT(ctx); 1615 delete_buffers(ctx, n, ids); 1616 } 1617 1618 1619 void GLAPIENTRY 1620 _mesa_DeleteBuffers(GLsizei n, const GLuint *ids) 1621 { 1622 GET_CURRENT_CONTEXT(ctx); 1623 1624 if (n < 0) { 1625 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteBuffersARB(n)"); 1626 return; 1627 } 1628 1629 delete_buffers(ctx, n, ids); 1630 } 1631 1632 1633 /** 1634 * This is the implementation for glGenBuffers and glCreateBuffers. It is not 1635 * exposed to the rest of Mesa to encourage the use of nameless buffers in 1636 * driver internals. 1637 */ 1638 static void 1639 create_buffers(struct gl_context *ctx, GLsizei n, GLuint *buffers, bool dsa) 1640 { 1641 GLuint first; 1642 struct gl_buffer_object *buf; 1643 1644 if (!buffers) 1645 return; 1646 1647 /* 1648 * This must be atomic (generation and allocation of buffer object IDs) 1649 */ 1650 _mesa_HashLockMutex(ctx->Shared->BufferObjects); 1651 1652 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n); 1653 1654 /* Insert the ID and pointer into the hash table. If non-DSA, insert a 1655 * DummyBufferObject. Otherwise, create a new buffer object and insert 1656 * it. 1657 */ 1658 for (int i = 0; i < n; i++) { 1659 buffers[i] = first + i; 1660 if (dsa) { 1661 assert(ctx->Driver.NewBufferObject); 1662 buf = ctx->Driver.NewBufferObject(ctx, buffers[i]); 1663 if (!buf) { 1664 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCreateBuffers"); 1665 _mesa_HashUnlockMutex(ctx->Shared->BufferObjects); 1666 return; 1667 } 1668 } 1669 else 1670 buf = &DummyBufferObject; 1671 1672 _mesa_HashInsertLocked(ctx->Shared->BufferObjects, buffers[i], buf); 1673 } 1674 1675 _mesa_HashUnlockMutex(ctx->Shared->BufferObjects); 1676 } 1677 1678 1679 static void 1680 create_buffers_err(struct gl_context *ctx, GLsizei n, GLuint *buffers, bool dsa) 1681 { 1682 const char *func = dsa ? "glCreateBuffers" : "glGenBuffers"; 1683 1684 if (MESA_VERBOSE & VERBOSE_API) 1685 _mesa_debug(ctx, "%s(%d)\n", func, n); 1686 1687 if (n < 0) { 1688 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n %d < 0)", func, n); 1689 return; 1690 } 1691 1692 create_buffers(ctx, n, buffers, dsa); 1693 } 1694 1695 /** 1696 * Generate a set of unique buffer object IDs and store them in \c buffers. 1697 * 1698 * \param n Number of IDs to generate. 1699 * \param buffers Array of \c n locations to store the IDs. 1700 */ 1701 void GLAPIENTRY 1702 _mesa_GenBuffers_no_error(GLsizei n, GLuint *buffers) 1703 { 1704 GET_CURRENT_CONTEXT(ctx); 1705 create_buffers(ctx, n, buffers, false); 1706 } 1707 1708 1709 void GLAPIENTRY 1710 _mesa_GenBuffers(GLsizei n, GLuint *buffers) 1711 { 1712 GET_CURRENT_CONTEXT(ctx); 1713 create_buffers_err(ctx, n, buffers, false); 1714 } 1715 1716 /** 1717 * Create a set of buffer objects and store their unique IDs in \c buffers. 1718 * 1719 * \param n Number of IDs to generate. 1720 * \param buffers Array of \c n locations to store the IDs. 1721 */ 1722 void GLAPIENTRY 1723 _mesa_CreateBuffers_no_error(GLsizei n, GLuint *buffers) 1724 { 1725 GET_CURRENT_CONTEXT(ctx); 1726 create_buffers(ctx, n, buffers, true); 1727 } 1728 1729 1730 void GLAPIENTRY 1731 _mesa_CreateBuffers(GLsizei n, GLuint *buffers) 1732 { 1733 GET_CURRENT_CONTEXT(ctx); 1734 create_buffers_err(ctx, n, buffers, true); 1735 } 1736 1737 1738 /** 1739 * Determine if ID is the name of a buffer object. 1740 * 1741 * \param id ID of the potential buffer object. 1742 * \return \c GL_TRUE if \c id is the name of a buffer object, 1743 * \c GL_FALSE otherwise. 1744 */ 1745 GLboolean GLAPIENTRY 1746 _mesa_IsBuffer(GLuint id) 1747 { 1748 struct gl_buffer_object *bufObj; 1749 GET_CURRENT_CONTEXT(ctx); 1750 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 1751 1752 bufObj = _mesa_lookup_bufferobj(ctx, id); 1753 1754 return bufObj && bufObj != &DummyBufferObject; 1755 } 1756 1757 1758 static bool 1759 validate_buffer_storage(struct gl_context *ctx, 1760 struct gl_buffer_object *bufObj, GLsizeiptr size, 1761 GLbitfield flags, const char *func) 1762 { 1763 if (size <= 0) { 1764 _mesa_error(ctx, GL_INVALID_VALUE, "%s(size <= 0)", func); 1765 return false; 1766 } 1767 1768 GLbitfield valid_flags = GL_MAP_READ_BIT | 1769 GL_MAP_WRITE_BIT | 1770 GL_MAP_PERSISTENT_BIT | 1771 GL_MAP_COHERENT_BIT | 1772 GL_DYNAMIC_STORAGE_BIT | 1773 GL_CLIENT_STORAGE_BIT; 1774 1775 if (ctx->Extensions.ARB_sparse_buffer) 1776 valid_flags |= GL_SPARSE_STORAGE_BIT_ARB; 1777 1778 if (flags & ~valid_flags) { 1779 _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid flag bits set)", func); 1780 return false; 1781 } 1782 1783 /* The Errors section of the GL_ARB_sparse_buffer spec says: 1784 * 1785 * "INVALID_VALUE is generated by BufferStorage if <flags> contains 1786 * SPARSE_STORAGE_BIT_ARB and <flags> also contains any combination of 1787 * MAP_READ_BIT or MAP_WRITE_BIT." 1788 */ 1789 if (flags & GL_SPARSE_STORAGE_BIT_ARB && 1790 flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) { 1791 _mesa_error(ctx, GL_INVALID_VALUE, "%s(SPARSE_STORAGE and READ/WRITE)", func); 1792 return false; 1793 } 1794 1795 if (flags & GL_MAP_PERSISTENT_BIT && 1796 !(flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT))) { 1797 _mesa_error(ctx, GL_INVALID_VALUE, 1798 "%s(PERSISTENT and flags!=READ/WRITE)", func); 1799 return false; 1800 } 1801 1802 if (flags & GL_MAP_COHERENT_BIT && !(flags & GL_MAP_PERSISTENT_BIT)) { 1803 _mesa_error(ctx, GL_INVALID_VALUE, 1804 "%s(COHERENT and flags!=PERSISTENT)", func); 1805 return false; 1806 } 1807 1808 if (bufObj->Immutable || bufObj->HandleAllocated) { 1809 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func); 1810 return false; 1811 } 1812 1813 return true; 1814 } 1815 1816 1817 static void 1818 buffer_storage(struct gl_context *ctx, struct gl_buffer_object *bufObj, 1819 struct gl_memory_object *memObj, GLenum target, 1820 GLsizeiptr size, const GLvoid *data, GLbitfield flags, 1821 GLuint64 offset, const char *func) 1822 { 1823 GLboolean res; 1824 1825 /* Unmap the existing buffer. We'll replace it now. Not an error. */ 1826 _mesa_buffer_unmap_all_mappings(ctx, bufObj); 1827 1828 FLUSH_VERTICES(ctx, 0); 1829 1830 bufObj->Written = GL_TRUE; 1831 bufObj->Immutable = GL_TRUE; 1832 bufObj->MinMaxCacheDirty = true; 1833 1834 if (memObj) { 1835 assert(ctx->Driver.BufferDataMem); 1836 res = ctx->Driver.BufferDataMem(ctx, target, size, memObj, offset, 1837 GL_DYNAMIC_DRAW, bufObj); 1838 } 1839 else { 1840 assert(ctx->Driver.BufferData); 1841 res = ctx->Driver.BufferData(ctx, target, size, data, GL_DYNAMIC_DRAW, 1842 flags, bufObj); 1843 } 1844 1845 if (!res) { 1846 if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) { 1847 /* Even though the interaction between AMD_pinned_memory and 1848 * glBufferStorage is not described in the spec, Graham Sellers 1849 * said that it should behave the same as glBufferData. 1850 */ 1851 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func); 1852 } 1853 else { 1854 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); 1855 } 1856 } 1857 } 1858 1859 1860 static ALWAYS_INLINE void 1861 inlined_buffer_storage(GLenum target, GLuint buffer, GLsizeiptr size, 1862 const GLvoid *data, GLbitfield flags, 1863 GLuint memory, GLuint64 offset, 1864 bool dsa, bool mem, bool no_error, const char *func) 1865 { 1866 GET_CURRENT_CONTEXT(ctx); 1867 struct gl_buffer_object *bufObj; 1868 struct gl_memory_object *memObj = NULL; 1869 1870 if (mem) { 1871 if (!no_error) { 1872 if (!ctx->Extensions.EXT_memory_object) { 1873 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 1874 return; 1875 } 1876 1877 /* From the EXT_external_objects spec: 1878 * 1879 * "An INVALID_VALUE error is generated by BufferStorageMemEXT and 1880 * NamedBufferStorageMemEXT if <memory> is 0, or ..." 1881 */ 1882 if (memory == 0) { 1883 _mesa_error(ctx, GL_INVALID_VALUE, "%s(memory == 0)", func); 1884 } 1885 } 1886 1887 memObj = _mesa_lookup_memory_object(ctx, memory); 1888 if (!memObj) 1889 return; 1890 1891 /* From the EXT_external_objects spec: 1892 * 1893 * "An INVALID_OPERATION error is generated if <memory> names a 1894 * valid memory object which has no associated memory." 1895 */ 1896 if (!no_error && !memObj->Immutable) { 1897 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no associated memory)", 1898 func); 1899 return; 1900 } 1901 } 1902 1903 if (dsa) { 1904 if (no_error) { 1905 bufObj = _mesa_lookup_bufferobj(ctx, buffer); 1906 } else { 1907 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, func); 1908 if (!bufObj) 1909 return; 1910 } 1911 } else { 1912 if (no_error) { 1913 struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target); 1914 bufObj = *bufObjPtr; 1915 } else { 1916 bufObj = get_buffer(ctx, func, target, GL_INVALID_OPERATION); 1917 if (!bufObj) 1918 return; 1919 } 1920 } 1921 1922 if (no_error || validate_buffer_storage(ctx, bufObj, size, flags, func)) 1923 buffer_storage(ctx, bufObj, memObj, target, size, data, flags, offset, func); 1924 } 1925 1926 1927 void GLAPIENTRY 1928 _mesa_BufferStorage_no_error(GLenum target, GLsizeiptr size, 1929 const GLvoid *data, GLbitfield flags) 1930 { 1931 inlined_buffer_storage(target, 0, size, data, flags, GL_NONE, 0, 1932 false, false, true, "glBufferStorage"); 1933 } 1934 1935 1936 void GLAPIENTRY 1937 _mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data, 1938 GLbitfield flags) 1939 { 1940 inlined_buffer_storage(target, 0, size, data, flags, GL_NONE, 0, 1941 false, false, false, "glBufferStorage"); 1942 } 1943 1944 1945 void GLAPIENTRY 1946 _mesa_BufferStorageMemEXT(GLenum target, GLsizeiptr size, 1947 GLuint memory, GLuint64 offset) 1948 { 1949 inlined_buffer_storage(target, 0, size, NULL, 0, memory, offset, 1950 false, true, false, "glBufferStorageMemEXT"); 1951 } 1952 1953 1954 void GLAPIENTRY 1955 _mesa_BufferStorageMemEXT_no_error(GLenum target, GLsizeiptr size, 1956 GLuint memory, GLuint64 offset) 1957 { 1958 inlined_buffer_storage(target, 0, size, NULL, 0, memory, offset, 1959 false, true, true, "glBufferStorageMemEXT"); 1960 } 1961 1962 1963 void GLAPIENTRY 1964 _mesa_NamedBufferStorage_no_error(GLuint buffer, GLsizeiptr size, 1965 const GLvoid *data, GLbitfield flags) 1966 { 1967 /* In direct state access, buffer objects have an unspecified target 1968 * since they are not required to be bound. 1969 */ 1970 inlined_buffer_storage(GL_NONE, buffer, size, data, flags, GL_NONE, 0, 1971 true, false, true, "glNamedBufferStorage"); 1972 } 1973 1974 1975 void GLAPIENTRY 1976 _mesa_NamedBufferStorage(GLuint buffer, GLsizeiptr size, const GLvoid *data, 1977 GLbitfield flags) 1978 { 1979 /* In direct state access, buffer objects have an unspecified target 1980 * since they are not required to be bound. 1981 */ 1982 inlined_buffer_storage(GL_NONE, buffer, size, data, flags, GL_NONE, 0, 1983 true, false, false, "glNamedBufferStorage"); 1984 } 1985 1986 void GLAPIENTRY 1987 _mesa_NamedBufferStorageMemEXT(GLuint buffer, GLsizeiptr size, 1988 GLuint memory, GLuint64 offset) 1989 { 1990 inlined_buffer_storage(GL_NONE, buffer, size, GL_NONE, 0, memory, offset, 1991 true, true, false, "glNamedBufferStorageMemEXT"); 1992 } 1993 1994 1995 void GLAPIENTRY 1996 _mesa_NamedBufferStorageMemEXT_no_error(GLuint buffer, GLsizeiptr size, 1997 GLuint memory, GLuint64 offset) 1998 { 1999 inlined_buffer_storage(GL_NONE, buffer, size, GL_NONE, 0, memory, offset, 2000 true, true, true, "glNamedBufferStorageMemEXT"); 2001 } 2002 2003 2004 static ALWAYS_INLINE void 2005 buffer_data(struct gl_context *ctx, struct gl_buffer_object *bufObj, 2006 GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage, 2007 const char *func, bool no_error) 2008 { 2009 bool valid_usage; 2010 2011 if (MESA_VERBOSE & VERBOSE_API) { 2012 _mesa_debug(ctx, "%s(%s, %ld, %p, %s)\n", 2013 func, 2014 _mesa_enum_to_string(target), 2015 (long int) size, data, 2016 _mesa_enum_to_string(usage)); 2017 } 2018 2019 if (!no_error) { 2020 if (size < 0) { 2021 _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", func); 2022 return; 2023 } 2024 2025 switch (usage) { 2026 case GL_STREAM_DRAW_ARB: 2027 valid_usage = (ctx->API != API_OPENGLES); 2028 break; 2029 case GL_STATIC_DRAW_ARB: 2030 case GL_DYNAMIC_DRAW_ARB: 2031 valid_usage = true; 2032 break; 2033 case GL_STREAM_READ_ARB: 2034 case GL_STREAM_COPY_ARB: 2035 case GL_STATIC_READ_ARB: 2036 case GL_STATIC_COPY_ARB: 2037 case GL_DYNAMIC_READ_ARB: 2038 case GL_DYNAMIC_COPY_ARB: 2039 valid_usage = _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx); 2040 break; 2041 default: 2042 valid_usage = false; 2043 break; 2044 } 2045 2046 if (!valid_usage) { 2047 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid usage: %s)", func, 2048 _mesa_enum_to_string(usage)); 2049 return; 2050 } 2051 2052 if (bufObj->Immutable || bufObj->HandleAllocated) { 2053 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func); 2054 return; 2055 } 2056 } 2057 2058 /* Unmap the existing buffer. We'll replace it now. Not an error. */ 2059 _mesa_buffer_unmap_all_mappings(ctx, bufObj); 2060 2061 FLUSH_VERTICES(ctx, 0); 2062 2063 bufObj->Written = GL_TRUE; 2064 bufObj->MinMaxCacheDirty = true; 2065 2066 #ifdef VBO_DEBUG 2067 printf("glBufferDataARB(%u, sz %ld, from %p, usage 0x%x)\n", 2068 bufObj->Name, size, data, usage); 2069 #endif 2070 2071 #ifdef BOUNDS_CHECK 2072 size += 100; 2073 #endif 2074 2075 assert(ctx->Driver.BufferData); 2076 if (!ctx->Driver.BufferData(ctx, target, size, data, usage, 2077 GL_MAP_READ_BIT | 2078 GL_MAP_WRITE_BIT | 2079 GL_DYNAMIC_STORAGE_BIT, 2080 bufObj)) { 2081 if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) { 2082 if (!no_error) { 2083 /* From GL_AMD_pinned_memory: 2084 * 2085 * INVALID_OPERATION is generated by BufferData if <target> is 2086 * EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, and the store cannot be 2087 * mapped to the GPU address space. 2088 */ 2089 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func); 2090 } 2091 } else { 2092 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); 2093 } 2094 } 2095 } 2096 2097 static void 2098 buffer_data_error(struct gl_context *ctx, struct gl_buffer_object *bufObj, 2099 GLenum target, GLsizeiptr size, const GLvoid *data, 2100 GLenum usage, const char *func) 2101 { 2102 buffer_data(ctx, bufObj, target, size, data, usage, func, false); 2103 } 2104 2105 static void 2106 buffer_data_no_error(struct gl_context *ctx, struct gl_buffer_object *bufObj, 2107 GLenum target, GLsizeiptr size, const GLvoid *data, 2108 GLenum usage, const char *func) 2109 { 2110 buffer_data(ctx, bufObj, target, size, data, usage, func, true); 2111 } 2112 2113 void 2114 _mesa_buffer_data(struct gl_context *ctx, struct gl_buffer_object *bufObj, 2115 GLenum target, GLsizeiptr size, const GLvoid *data, 2116 GLenum usage, const char *func) 2117 { 2118 buffer_data_error(ctx, bufObj, target, size, data, usage, func); 2119 } 2120 2121 void GLAPIENTRY 2122 _mesa_BufferData_no_error(GLenum target, GLsizeiptr size, const GLvoid *data, 2123 GLenum usage) 2124 { 2125 GET_CURRENT_CONTEXT(ctx); 2126 2127 struct gl_buffer_object **bufObj = get_buffer_target(ctx, target); 2128 buffer_data_no_error(ctx, *bufObj, target, size, data, usage, 2129 "glBufferData"); 2130 } 2131 2132 void GLAPIENTRY 2133 _mesa_BufferData(GLenum target, GLsizeiptr size, 2134 const GLvoid *data, GLenum usage) 2135 { 2136 GET_CURRENT_CONTEXT(ctx); 2137 struct gl_buffer_object *bufObj; 2138 2139 bufObj = get_buffer(ctx, "glBufferData", target, GL_INVALID_OPERATION); 2140 if (!bufObj) 2141 return; 2142 2143 _mesa_buffer_data(ctx, bufObj, target, size, data, usage, 2144 "glBufferData"); 2145 } 2146 2147 void GLAPIENTRY 2148 _mesa_NamedBufferData_no_error(GLuint buffer, GLsizeiptr size, 2149 const GLvoid *data, GLenum usage) 2150 { 2151 GET_CURRENT_CONTEXT(ctx); 2152 2153 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer); 2154 buffer_data_no_error(ctx, bufObj, GL_NONE, size, data, usage, 2155 "glNamedBufferData"); 2156 } 2157 2158 void GLAPIENTRY 2159 _mesa_NamedBufferData(GLuint buffer, GLsizeiptr size, const GLvoid *data, 2160 GLenum usage) 2161 { 2162 GET_CURRENT_CONTEXT(ctx); 2163 struct gl_buffer_object *bufObj; 2164 2165 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferData"); 2166 if (!bufObj) 2167 return; 2168 2169 /* In direct state access, buffer objects have an unspecified target since 2170 * they are not required to be bound. 2171 */ 2172 _mesa_buffer_data(ctx, bufObj, GL_NONE, size, data, usage, 2173 "glNamedBufferData"); 2174 } 2175 2176 2177 static bool 2178 validate_buffer_sub_data(struct gl_context *ctx, 2179 struct gl_buffer_object *bufObj, 2180 GLintptr offset, GLsizeiptr size, 2181 const char *func) 2182 { 2183 if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size, 2184 true, func)) { 2185 /* error already recorded */ 2186 return false; 2187 } 2188 2189 if (bufObj->Immutable && 2190 !(bufObj->StorageFlags & GL_DYNAMIC_STORAGE_BIT)) { 2191 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func); 2192 return false; 2193 } 2194 2195 if ((bufObj->Usage == GL_STATIC_DRAW || 2196 bufObj->Usage == GL_STATIC_COPY) && 2197 bufObj->NumSubDataCalls >= BUFFER_WARNING_CALL_COUNT - 1) { 2198 /* If the application declared the buffer as static draw/copy or stream 2199 * draw, it should not be frequently modified with glBufferSubData. 2200 */ 2201 BUFFER_USAGE_WARNING(ctx, 2202 "using %s(buffer %u, offset %u, size %u) to " 2203 "update a %s buffer", 2204 func, bufObj->Name, offset, size, 2205 _mesa_enum_to_string(bufObj->Usage)); 2206 } 2207 2208 return true; 2209 } 2210 2211 2212 /** 2213 * Implementation for glBufferSubData and glNamedBufferSubData. 2214 * 2215 * \param ctx GL context. 2216 * \param bufObj The buffer object. 2217 * \param offset Offset of the first byte of the subdata range. 2218 * \param size Size, in bytes, of the subdata range. 2219 * \param data The data store. 2220 * \param func Name of calling function for recording errors. 2221 * 2222 */ 2223 void 2224 _mesa_buffer_sub_data(struct gl_context *ctx, struct gl_buffer_object *bufObj, 2225 GLintptr offset, GLsizeiptr size, const GLvoid *data) 2226 { 2227 if (size == 0) 2228 return; 2229 2230 bufObj->NumSubDataCalls++; 2231 bufObj->Written = GL_TRUE; 2232 bufObj->MinMaxCacheDirty = true; 2233 2234 assert(ctx->Driver.BufferSubData); 2235 ctx->Driver.BufferSubData(ctx, offset, size, data, bufObj); 2236 } 2237 2238 2239 static ALWAYS_INLINE void 2240 buffer_sub_data(GLenum target, GLuint buffer, GLintptr offset, 2241 GLsizeiptr size, const GLvoid *data, 2242 bool dsa, bool no_error, const char *func) 2243 { 2244 GET_CURRENT_CONTEXT(ctx); 2245 struct gl_buffer_object *bufObj; 2246 2247 if (dsa) { 2248 if (no_error) { 2249 bufObj = _mesa_lookup_bufferobj(ctx, buffer); 2250 } else { 2251 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, func); 2252 if (!bufObj) 2253 return; 2254 } 2255 } else { 2256 if (no_error) { 2257 struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target); 2258 bufObj = *bufObjPtr; 2259 } else { 2260 bufObj = get_buffer(ctx, func, target, GL_INVALID_OPERATION); 2261 if (!bufObj) 2262 return; 2263 } 2264 } 2265 2266 if (no_error || validate_buffer_sub_data(ctx, bufObj, offset, size, func)) 2267 _mesa_buffer_sub_data(ctx, bufObj, offset, size, data); 2268 } 2269 2270 2271 void GLAPIENTRY 2272 _mesa_BufferSubData_no_error(GLenum target, GLintptr offset, 2273 GLsizeiptr size, const GLvoid *data) 2274 { 2275 buffer_sub_data(target, 0, offset, size, data, false, true, 2276 "glBufferSubData"); 2277 } 2278 2279 2280 void GLAPIENTRY 2281 _mesa_BufferSubData(GLenum target, GLintptr offset, 2282 GLsizeiptr size, const GLvoid *data) 2283 { 2284 buffer_sub_data(target, 0, offset, size, data, false, false, 2285 "glBufferSubData"); 2286 } 2287 2288 void GLAPIENTRY 2289 _mesa_NamedBufferSubData_no_error(GLuint buffer, GLintptr offset, 2290 GLsizeiptr size, const GLvoid *data) 2291 { 2292 buffer_sub_data(0, buffer, offset, size, data, true, true, 2293 "glNamedBufferSubData"); 2294 } 2295 2296 void GLAPIENTRY 2297 _mesa_NamedBufferSubData(GLuint buffer, GLintptr offset, 2298 GLsizeiptr size, const GLvoid *data) 2299 { 2300 buffer_sub_data(0, buffer, offset, size, data, true, false, 2301 "glNamedBufferSubData"); 2302 } 2303 2304 2305 void GLAPIENTRY 2306 _mesa_GetBufferSubData(GLenum target, GLintptr offset, 2307 GLsizeiptr size, GLvoid *data) 2308 { 2309 GET_CURRENT_CONTEXT(ctx); 2310 struct gl_buffer_object *bufObj; 2311 2312 bufObj = get_buffer(ctx, "glGetBufferSubData", target, 2313 GL_INVALID_OPERATION); 2314 if (!bufObj) 2315 return; 2316 2317 if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size, false, 2318 "glGetBufferSubData")) { 2319 return; 2320 } 2321 2322 assert(ctx->Driver.GetBufferSubData); 2323 ctx->Driver.GetBufferSubData(ctx, offset, size, data, bufObj); 2324 } 2325 2326 void GLAPIENTRY 2327 _mesa_GetNamedBufferSubData(GLuint buffer, GLintptr offset, 2328 GLsizeiptr size, GLvoid *data) 2329 { 2330 GET_CURRENT_CONTEXT(ctx); 2331 struct gl_buffer_object *bufObj; 2332 2333 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, 2334 "glGetNamedBufferSubData"); 2335 if (!bufObj) 2336 return; 2337 2338 if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size, false, 2339 "glGetNamedBufferSubData")) { 2340 return; 2341 } 2342 2343 assert(ctx->Driver.GetBufferSubData); 2344 ctx->Driver.GetBufferSubData(ctx, offset, size, data, bufObj); 2345 } 2346 2347 2348 /** 2349 * \param subdata true if caller is *SubData, false if *Data 2350 */ 2351 static ALWAYS_INLINE void 2352 clear_buffer_sub_data(struct gl_context *ctx, struct gl_buffer_object *bufObj, 2353 GLenum internalformat, GLintptr offset, GLsizeiptr size, 2354 GLenum format, GLenum type, const GLvoid *data, 2355 const char *func, bool subdata, bool no_error) 2356 { 2357 mesa_format mesaFormat; 2358 GLubyte clearValue[MAX_PIXEL_BYTES]; 2359 GLsizeiptr clearValueSize; 2360 2361 /* This checks for disallowed mappings. */ 2362 if (!no_error && !buffer_object_subdata_range_good(ctx, bufObj, offset, size, 2363 subdata, func)) { 2364 return; 2365 } 2366 2367 if (no_error) { 2368 mesaFormat = _mesa_get_texbuffer_format(ctx, internalformat); 2369 } else { 2370 mesaFormat = validate_clear_buffer_format(ctx, internalformat, 2371 format, type, func); 2372 } 2373 2374 if (mesaFormat == MESA_FORMAT_NONE) 2375 return; 2376 2377 clearValueSize = _mesa_get_format_bytes(mesaFormat); 2378 if (!no_error && 2379 (offset % clearValueSize != 0 || size % clearValueSize != 0)) { 2380 _mesa_error(ctx, GL_INVALID_VALUE, 2381 "%s(offset or size is not a multiple of " 2382 "internalformat size)", func); 2383 return; 2384 } 2385 2386 /* Bail early. Negative size has already been checked. */ 2387 if (size == 0) 2388 return; 2389 2390 bufObj->MinMaxCacheDirty = true; 2391 2392 if (data == NULL) { 2393 /* clear to zeros, per the spec */ 2394 ctx->Driver.ClearBufferSubData(ctx, offset, size, 2395 NULL, clearValueSize, bufObj); 2396 return; 2397 } 2398 2399 if (!convert_clear_buffer_data(ctx, mesaFormat, clearValue, 2400 format, type, data, func)) { 2401 return; 2402 } 2403 2404 ctx->Driver.ClearBufferSubData(ctx, offset, size, 2405 clearValue, clearValueSize, bufObj); 2406 } 2407 2408 static void 2409 clear_buffer_sub_data_error(struct gl_context *ctx, 2410 struct gl_buffer_object *bufObj, 2411 GLenum internalformat, GLintptr offset, 2412 GLsizeiptr size, GLenum format, GLenum type, 2413 const GLvoid *data, const char *func, bool subdata) 2414 { 2415 clear_buffer_sub_data(ctx, bufObj, internalformat, offset, size, format, 2416 type, data, func, subdata, false); 2417 } 2418 2419 2420 static void 2421 clear_buffer_sub_data_no_error(struct gl_context *ctx, 2422 struct gl_buffer_object *bufObj, 2423 GLenum internalformat, GLintptr offset, 2424 GLsizeiptr size, GLenum format, GLenum type, 2425 const GLvoid *data, const char *func, 2426 bool subdata) 2427 { 2428 clear_buffer_sub_data(ctx, bufObj, internalformat, offset, size, format, 2429 type, data, func, subdata, true); 2430 } 2431 2432 2433 void GLAPIENTRY 2434 _mesa_ClearBufferData_no_error(GLenum target, GLenum internalformat, 2435 GLenum format, GLenum type, const GLvoid *data) 2436 { 2437 GET_CURRENT_CONTEXT(ctx); 2438 2439 struct gl_buffer_object **bufObj = get_buffer_target(ctx, target); 2440 clear_buffer_sub_data_no_error(ctx, *bufObj, internalformat, 0, 2441 (*bufObj)->Size, format, type, data, 2442 "glClearBufferData", false); 2443 } 2444 2445 2446 void GLAPIENTRY 2447 _mesa_ClearBufferData(GLenum target, GLenum internalformat, GLenum format, 2448 GLenum type, const GLvoid *data) 2449 { 2450 GET_CURRENT_CONTEXT(ctx); 2451 struct gl_buffer_object *bufObj; 2452 2453 bufObj = get_buffer(ctx, "glClearBufferData", target, GL_INVALID_VALUE); 2454 if (!bufObj) 2455 return; 2456 2457 clear_buffer_sub_data_error(ctx, bufObj, internalformat, 0, bufObj->Size, 2458 format, type, data, "glClearBufferData", false); 2459 } 2460 2461 2462 void GLAPIENTRY 2463 _mesa_ClearNamedBufferData_no_error(GLuint buffer, GLenum internalformat, 2464 GLenum format, GLenum type, 2465 const GLvoid *data) 2466 { 2467 GET_CURRENT_CONTEXT(ctx); 2468 2469 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer); 2470 clear_buffer_sub_data_no_error(ctx, bufObj, internalformat, 0, bufObj->Size, 2471 format, type, data, "glClearNamedBufferData", 2472 false); 2473 } 2474 2475 2476 void GLAPIENTRY 2477 _mesa_ClearNamedBufferData(GLuint buffer, GLenum internalformat, 2478 GLenum format, GLenum type, const GLvoid *data) 2479 { 2480 GET_CURRENT_CONTEXT(ctx); 2481 struct gl_buffer_object *bufObj; 2482 2483 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glClearNamedBufferData"); 2484 if (!bufObj) 2485 return; 2486 2487 clear_buffer_sub_data_error(ctx, bufObj, internalformat, 0, bufObj->Size, 2488 format, type, data, "glClearNamedBufferData", 2489 false); 2490 } 2491 2492 2493 void GLAPIENTRY 2494 _mesa_ClearBufferSubData_no_error(GLenum target, GLenum internalformat, 2495 GLintptr offset, GLsizeiptr size, 2496 GLenum format, GLenum type, 2497 const GLvoid *data) 2498 { 2499 GET_CURRENT_CONTEXT(ctx); 2500 2501 struct gl_buffer_object **bufObj = get_buffer_target(ctx, target); 2502 clear_buffer_sub_data_no_error(ctx, *bufObj, internalformat, offset, size, 2503 format, type, data, "glClearBufferSubData", 2504 true); 2505 } 2506 2507 2508 void GLAPIENTRY 2509 _mesa_ClearBufferSubData(GLenum target, GLenum internalformat, 2510 GLintptr offset, GLsizeiptr size, 2511 GLenum format, GLenum type, 2512 const GLvoid *data) 2513 { 2514 GET_CURRENT_CONTEXT(ctx); 2515 struct gl_buffer_object *bufObj; 2516 2517 bufObj = get_buffer(ctx, "glClearBufferSubData", target, GL_INVALID_VALUE); 2518 if (!bufObj) 2519 return; 2520 2521 clear_buffer_sub_data_error(ctx, bufObj, internalformat, offset, size, 2522 format, type, data, "glClearBufferSubData", 2523 true); 2524 } 2525 2526 2527 void GLAPIENTRY 2528 _mesa_ClearNamedBufferSubData_no_error(GLuint buffer, GLenum internalformat, 2529 GLintptr offset, GLsizeiptr size, 2530 GLenum format, GLenum type, 2531 const GLvoid *data) 2532 { 2533 GET_CURRENT_CONTEXT(ctx); 2534 2535 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer); 2536 clear_buffer_sub_data_no_error(ctx, bufObj, internalformat, offset, size, 2537 format, type, data, 2538 "glClearNamedBufferSubData", true); 2539 } 2540 2541 2542 void GLAPIENTRY 2543 _mesa_ClearNamedBufferSubData(GLuint buffer, GLenum internalformat, 2544 GLintptr offset, GLsizeiptr size, 2545 GLenum format, GLenum type, 2546 const GLvoid *data) 2547 { 2548 GET_CURRENT_CONTEXT(ctx); 2549 struct gl_buffer_object *bufObj; 2550 2551 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, 2552 "glClearNamedBufferSubData"); 2553 if (!bufObj) 2554 return; 2555 2556 clear_buffer_sub_data_error(ctx, bufObj, internalformat, offset, size, 2557 format, type, data, "glClearNamedBufferSubData", 2558 true); 2559 } 2560 2561 static GLboolean 2562 unmap_buffer(struct gl_context *ctx, struct gl_buffer_object *bufObj) 2563 { 2564 GLboolean status = ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_USER); 2565 bufObj->Mappings[MAP_USER].AccessFlags = 0; 2566 assert(bufObj->Mappings[MAP_USER].Pointer == NULL); 2567 assert(bufObj->Mappings[MAP_USER].Offset == 0); 2568 assert(bufObj->Mappings[MAP_USER].Length == 0); 2569 2570 return status; 2571 } 2572 2573 static GLboolean 2574 validate_and_unmap_buffer(struct gl_context *ctx, 2575 struct gl_buffer_object *bufObj, 2576 const char *func) 2577 { 2578 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 2579 2580 if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) { 2581 _mesa_error(ctx, GL_INVALID_OPERATION, 2582 "%s(buffer is not mapped)", func); 2583 return GL_FALSE; 2584 } 2585 2586 #ifdef BOUNDS_CHECK 2587 if (bufObj->Access != GL_READ_ONLY_ARB) { 2588 GLubyte *buf = (GLubyte *) bufObj->Pointer; 2589 GLuint i; 2590 /* check that last 100 bytes are still = magic value */ 2591 for (i = 0; i < 100; i++) { 2592 GLuint pos = bufObj->Size - i - 1; 2593 if (buf[pos] != 123) { 2594 _mesa_warning(ctx, "Out of bounds buffer object write detected" 2595 " at position %d (value = %u)\n", 2596 pos, buf[pos]); 2597 } 2598 } 2599 } 2600 #endif 2601 2602 #ifdef VBO_DEBUG 2603 if (bufObj->AccessFlags & GL_MAP_WRITE_BIT) { 2604 GLuint i, unchanged = 0; 2605 GLubyte *b = (GLubyte *) bufObj->Pointer; 2606 GLint pos = -1; 2607 /* check which bytes changed */ 2608 for (i = 0; i < bufObj->Size - 1; i++) { 2609 if (b[i] == (i & 0xff) && b[i+1] == ((i+1) & 0xff)) { 2610 unchanged++; 2611 if (pos == -1) 2612 pos = i; 2613 } 2614 } 2615 if (unchanged) { 2616 printf("glUnmapBufferARB(%u): %u of %ld unchanged, starting at %d\n", 2617 bufObj->Name, unchanged, bufObj->Size, pos); 2618 } 2619 } 2620 #endif 2621 2622 return unmap_buffer(ctx, bufObj); 2623 } 2624 2625 GLboolean GLAPIENTRY 2626 _mesa_UnmapBuffer_no_error(GLenum target) 2627 { 2628 GET_CURRENT_CONTEXT(ctx); 2629 struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target); 2630 struct gl_buffer_object *bufObj = *bufObjPtr; 2631 2632 return unmap_buffer(ctx, bufObj); 2633 } 2634 2635 GLboolean GLAPIENTRY 2636 _mesa_UnmapBuffer(GLenum target) 2637 { 2638 GET_CURRENT_CONTEXT(ctx); 2639 struct gl_buffer_object *bufObj; 2640 2641 bufObj = get_buffer(ctx, "glUnmapBuffer", target, GL_INVALID_OPERATION); 2642 if (!bufObj) 2643 return GL_FALSE; 2644 2645 return validate_and_unmap_buffer(ctx, bufObj, "glUnmapBuffer"); 2646 } 2647 2648 GLboolean GLAPIENTRY 2649 _mesa_UnmapNamedBuffer_no_error(GLuint buffer) 2650 { 2651 GET_CURRENT_CONTEXT(ctx); 2652 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer); 2653 2654 return unmap_buffer(ctx, bufObj); 2655 } 2656 2657 GLboolean GLAPIENTRY 2658 _mesa_UnmapNamedBuffer(GLuint buffer) 2659 { 2660 GET_CURRENT_CONTEXT(ctx); 2661 struct gl_buffer_object *bufObj; 2662 2663 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glUnmapNamedBuffer"); 2664 if (!bufObj) 2665 return GL_FALSE; 2666 2667 return validate_and_unmap_buffer(ctx, bufObj, "glUnmapNamedBuffer"); 2668 } 2669 2670 2671 static bool 2672 get_buffer_parameter(struct gl_context *ctx, 2673 struct gl_buffer_object *bufObj, GLenum pname, 2674 GLint64 *params, const char *func) 2675 { 2676 switch (pname) { 2677 case GL_BUFFER_SIZE_ARB: 2678 *params = bufObj->Size; 2679 break; 2680 case GL_BUFFER_USAGE_ARB: 2681 *params = bufObj->Usage; 2682 break; 2683 case GL_BUFFER_ACCESS_ARB: 2684 *params = simplified_access_mode(ctx, 2685 bufObj->Mappings[MAP_USER].AccessFlags); 2686 break; 2687 case GL_BUFFER_MAPPED_ARB: 2688 *params = _mesa_bufferobj_mapped(bufObj, MAP_USER); 2689 break; 2690 case GL_BUFFER_ACCESS_FLAGS: 2691 if (!ctx->Extensions.ARB_map_buffer_range) 2692 goto invalid_pname; 2693 *params = bufObj->Mappings[MAP_USER].AccessFlags; 2694 break; 2695 case GL_BUFFER_MAP_OFFSET: 2696 if (!ctx->Extensions.ARB_map_buffer_range) 2697 goto invalid_pname; 2698 *params = bufObj->Mappings[MAP_USER].Offset; 2699 break; 2700 case GL_BUFFER_MAP_LENGTH: 2701 if (!ctx->Extensions.ARB_map_buffer_range) 2702 goto invalid_pname; 2703 *params = bufObj->Mappings[MAP_USER].Length; 2704 break; 2705 case GL_BUFFER_IMMUTABLE_STORAGE: 2706 if (!ctx->Extensions.ARB_buffer_storage) 2707 goto invalid_pname; 2708 *params = bufObj->Immutable; 2709 break; 2710 case GL_BUFFER_STORAGE_FLAGS: 2711 if (!ctx->Extensions.ARB_buffer_storage) 2712 goto invalid_pname; 2713 *params = bufObj->StorageFlags; 2714 break; 2715 default: 2716 goto invalid_pname; 2717 } 2718 2719 return true; 2720 2721 invalid_pname: 2722 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname: %s)", func, 2723 _mesa_enum_to_string(pname)); 2724 return false; 2725 } 2726 2727 void GLAPIENTRY 2728 _mesa_GetBufferParameteriv(GLenum target, GLenum pname, GLint *params) 2729 { 2730 GET_CURRENT_CONTEXT(ctx); 2731 struct gl_buffer_object *bufObj; 2732 GLint64 parameter; 2733 2734 bufObj = get_buffer(ctx, "glGetBufferParameteriv", target, 2735 GL_INVALID_OPERATION); 2736 if (!bufObj) 2737 return; 2738 2739 if (!get_buffer_parameter(ctx, bufObj, pname, ¶meter, 2740 "glGetBufferParameteriv")) 2741 return; /* Error already recorded. */ 2742 2743 *params = (GLint) parameter; 2744 } 2745 2746 void GLAPIENTRY 2747 _mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params) 2748 { 2749 GET_CURRENT_CONTEXT(ctx); 2750 struct gl_buffer_object *bufObj; 2751 GLint64 parameter; 2752 2753 bufObj = get_buffer(ctx, "glGetBufferParameteri64v", target, 2754 GL_INVALID_OPERATION); 2755 if (!bufObj) 2756 return; 2757 2758 if (!get_buffer_parameter(ctx, bufObj, pname, ¶meter, 2759 "glGetBufferParameteri64v")) 2760 return; /* Error already recorded. */ 2761 2762 *params = parameter; 2763 } 2764 2765 void GLAPIENTRY 2766 _mesa_GetNamedBufferParameteriv(GLuint buffer, GLenum pname, GLint *params) 2767 { 2768 GET_CURRENT_CONTEXT(ctx); 2769 struct gl_buffer_object *bufObj; 2770 GLint64 parameter; 2771 2772 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, 2773 "glGetNamedBufferParameteriv"); 2774 if (!bufObj) 2775 return; 2776 2777 if (!get_buffer_parameter(ctx, bufObj, pname, ¶meter, 2778 "glGetNamedBufferParameteriv")) 2779 return; /* Error already recorded. */ 2780 2781 *params = (GLint) parameter; 2782 } 2783 2784 void GLAPIENTRY 2785 _mesa_GetNamedBufferParameteri64v(GLuint buffer, GLenum pname, 2786 GLint64 *params) 2787 { 2788 GET_CURRENT_CONTEXT(ctx); 2789 struct gl_buffer_object *bufObj; 2790 GLint64 parameter; 2791 2792 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, 2793 "glGetNamedBufferParameteri64v"); 2794 if (!bufObj) 2795 return; 2796 2797 if (!get_buffer_parameter(ctx, bufObj, pname, ¶meter, 2798 "glGetNamedBufferParameteri64v")) 2799 return; /* Error already recorded. */ 2800 2801 *params = parameter; 2802 } 2803 2804 2805 void GLAPIENTRY 2806 _mesa_GetBufferPointerv(GLenum target, GLenum pname, GLvoid **params) 2807 { 2808 GET_CURRENT_CONTEXT(ctx); 2809 struct gl_buffer_object *bufObj; 2810 2811 if (pname != GL_BUFFER_MAP_POINTER) { 2812 _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointerv(pname != " 2813 "GL_BUFFER_MAP_POINTER)"); 2814 return; 2815 } 2816 2817 bufObj = get_buffer(ctx, "glGetBufferPointerv", target, 2818 GL_INVALID_OPERATION); 2819 if (!bufObj) 2820 return; 2821 2822 *params = bufObj->Mappings[MAP_USER].Pointer; 2823 } 2824 2825 void GLAPIENTRY 2826 _mesa_GetNamedBufferPointerv(GLuint buffer, GLenum pname, GLvoid **params) 2827 { 2828 GET_CURRENT_CONTEXT(ctx); 2829 struct gl_buffer_object *bufObj; 2830 2831 if (pname != GL_BUFFER_MAP_POINTER) { 2832 _mesa_error(ctx, GL_INVALID_ENUM, "glGetNamedBufferPointerv(pname != " 2833 "GL_BUFFER_MAP_POINTER)"); 2834 return; 2835 } 2836 2837 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, 2838 "glGetNamedBufferPointerv"); 2839 if (!bufObj) 2840 return; 2841 2842 *params = bufObj->Mappings[MAP_USER].Pointer; 2843 } 2844 2845 2846 static void 2847 copy_buffer_sub_data(struct gl_context *ctx, struct gl_buffer_object *src, 2848 struct gl_buffer_object *dst, GLintptr readOffset, 2849 GLintptr writeOffset, GLsizeiptr size, const char *func) 2850 { 2851 if (_mesa_check_disallowed_mapping(src)) { 2852 _mesa_error(ctx, GL_INVALID_OPERATION, 2853 "%s(readBuffer is mapped)", func); 2854 return; 2855 } 2856 2857 if (_mesa_check_disallowed_mapping(dst)) { 2858 _mesa_error(ctx, GL_INVALID_OPERATION, 2859 "%s(writeBuffer is mapped)", func); 2860 return; 2861 } 2862 2863 if (readOffset < 0) { 2864 _mesa_error(ctx, GL_INVALID_VALUE, 2865 "%s(readOffset %d < 0)", func, (int) readOffset); 2866 return; 2867 } 2868 2869 if (writeOffset < 0) { 2870 _mesa_error(ctx, GL_INVALID_VALUE, 2871 "%s(writeOffset %d < 0)", func, (int) writeOffset); 2872 return; 2873 } 2874 2875 if (size < 0) { 2876 _mesa_error(ctx, GL_INVALID_VALUE, 2877 "%s(size %d < 0)", func, (int) size); 2878 return; 2879 } 2880 2881 if (readOffset + size > src->Size) { 2882 _mesa_error(ctx, GL_INVALID_VALUE, 2883 "%s(readOffset %d + size %d > src_buffer_size %d)", func, 2884 (int) readOffset, (int) size, (int) src->Size); 2885 return; 2886 } 2887 2888 if (writeOffset + size > dst->Size) { 2889 _mesa_error(ctx, GL_INVALID_VALUE, 2890 "%s(writeOffset %d + size %d > dst_buffer_size %d)", func, 2891 (int) writeOffset, (int) size, (int) dst->Size); 2892 return; 2893 } 2894 2895 if (src == dst) { 2896 if (readOffset + size <= writeOffset) { 2897 /* OK */ 2898 } 2899 else if (writeOffset + size <= readOffset) { 2900 /* OK */ 2901 } 2902 else { 2903 /* overlapping src/dst is illegal */ 2904 _mesa_error(ctx, GL_INVALID_VALUE, 2905 "%s(overlapping src/dst)", func); 2906 return; 2907 } 2908 } 2909 2910 dst->MinMaxCacheDirty = true; 2911 2912 ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset, size); 2913 } 2914 2915 void GLAPIENTRY 2916 _mesa_CopyBufferSubData_no_error(GLenum readTarget, GLenum writeTarget, 2917 GLintptr readOffset, GLintptr writeOffset, 2918 GLsizeiptr size) 2919 { 2920 GET_CURRENT_CONTEXT(ctx); 2921 2922 struct gl_buffer_object **src_ptr = get_buffer_target(ctx, readTarget); 2923 struct gl_buffer_object *src = *src_ptr; 2924 2925 struct gl_buffer_object **dst_ptr = get_buffer_target(ctx, writeTarget); 2926 struct gl_buffer_object *dst = *dst_ptr; 2927 2928 dst->MinMaxCacheDirty = true; 2929 ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset, 2930 size); 2931 } 2932 2933 void GLAPIENTRY 2934 _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget, 2935 GLintptr readOffset, GLintptr writeOffset, 2936 GLsizeiptr size) 2937 { 2938 GET_CURRENT_CONTEXT(ctx); 2939 struct gl_buffer_object *src, *dst; 2940 2941 src = get_buffer(ctx, "glCopyBufferSubData", readTarget, 2942 GL_INVALID_OPERATION); 2943 if (!src) 2944 return; 2945 2946 dst = get_buffer(ctx, "glCopyBufferSubData", writeTarget, 2947 GL_INVALID_OPERATION); 2948 if (!dst) 2949 return; 2950 2951 copy_buffer_sub_data(ctx, src, dst, readOffset, writeOffset, size, 2952 "glCopyBufferSubData"); 2953 } 2954 2955 void GLAPIENTRY 2956 _mesa_CopyNamedBufferSubData_no_error(GLuint readBuffer, GLuint writeBuffer, 2957 GLintptr readOffset, 2958 GLintptr writeOffset, GLsizeiptr size) 2959 { 2960 GET_CURRENT_CONTEXT(ctx); 2961 2962 struct gl_buffer_object *src = _mesa_lookup_bufferobj(ctx, readBuffer); 2963 struct gl_buffer_object *dst = _mesa_lookup_bufferobj(ctx, writeBuffer); 2964 2965 dst->MinMaxCacheDirty = true; 2966 ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset, 2967 size); 2968 } 2969 2970 void GLAPIENTRY 2971 _mesa_CopyNamedBufferSubData(GLuint readBuffer, GLuint writeBuffer, 2972 GLintptr readOffset, GLintptr writeOffset, 2973 GLsizeiptr size) 2974 { 2975 GET_CURRENT_CONTEXT(ctx); 2976 struct gl_buffer_object *src, *dst; 2977 2978 src = _mesa_lookup_bufferobj_err(ctx, readBuffer, 2979 "glCopyNamedBufferSubData"); 2980 if (!src) 2981 return; 2982 2983 dst = _mesa_lookup_bufferobj_err(ctx, writeBuffer, 2984 "glCopyNamedBufferSubData"); 2985 if (!dst) 2986 return; 2987 2988 copy_buffer_sub_data(ctx, src, dst, readOffset, writeOffset, size, 2989 "glCopyNamedBufferSubData"); 2990 } 2991 2992 static bool 2993 validate_map_buffer_range(struct gl_context *ctx, 2994 struct gl_buffer_object *bufObj, GLintptr offset, 2995 GLsizeiptr length, GLbitfield access, 2996 const char *func) 2997 { 2998 GLbitfield allowed_access; 2999 3000 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, false); 3001 3002 if (offset < 0) { 3003 _mesa_error(ctx, GL_INVALID_VALUE, 3004 "%s(offset %ld < 0)", func, (long) offset); 3005 return false; 3006 } 3007 3008 if (length < 0) { 3009 _mesa_error(ctx, GL_INVALID_VALUE, 3010 "%s(length %ld < 0)", func, (long) length); 3011 return false; 3012 } 3013 3014 /* Page 38 of the PDF of the OpenGL ES 3.0 spec says: 3015 * 3016 * "An INVALID_OPERATION error is generated for any of the following 3017 * conditions: 3018 * 3019 * * <length> is zero." 3020 * 3021 * Additionally, page 94 of the PDF of the OpenGL 4.5 core spec 3022 * (30.10.2014) also says this, so it's no longer allowed for desktop GL, 3023 * either. 3024 */ 3025 if (length == 0) { 3026 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(length = 0)", func); 3027 return false; 3028 } 3029 3030 allowed_access = GL_MAP_READ_BIT | 3031 GL_MAP_WRITE_BIT | 3032 GL_MAP_INVALIDATE_RANGE_BIT | 3033 GL_MAP_INVALIDATE_BUFFER_BIT | 3034 GL_MAP_FLUSH_EXPLICIT_BIT | 3035 GL_MAP_UNSYNCHRONIZED_BIT; 3036 3037 if (ctx->Extensions.ARB_buffer_storage) { 3038 allowed_access |= GL_MAP_PERSISTENT_BIT | 3039 GL_MAP_COHERENT_BIT; 3040 } 3041 3042 if (access & ~allowed_access) { 3043 /* generate an error if any bits other than those allowed are set */ 3044 _mesa_error(ctx, GL_INVALID_VALUE, 3045 "%s(access has undefined bits set)", func); 3046 return false; 3047 } 3048 3049 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) { 3050 _mesa_error(ctx, GL_INVALID_OPERATION, 3051 "%s(access indicates neither read or write)", func); 3052 return false; 3053 } 3054 3055 if ((access & GL_MAP_READ_BIT) && 3056 (access & (GL_MAP_INVALIDATE_RANGE_BIT | 3057 GL_MAP_INVALIDATE_BUFFER_BIT | 3058 GL_MAP_UNSYNCHRONIZED_BIT))) { 3059 _mesa_error(ctx, GL_INVALID_OPERATION, 3060 "%s(read access with disallowed bits)", func); 3061 return false; 3062 } 3063 3064 if ((access & GL_MAP_FLUSH_EXPLICIT_BIT) && 3065 ((access & GL_MAP_WRITE_BIT) == 0)) { 3066 _mesa_error(ctx, GL_INVALID_OPERATION, 3067 "%s(access has flush explicit without write)", func); 3068 return false; 3069 } 3070 3071 if (access & GL_MAP_READ_BIT && 3072 !(bufObj->StorageFlags & GL_MAP_READ_BIT)) { 3073 _mesa_error(ctx, GL_INVALID_OPERATION, 3074 "%s(buffer does not allow read access)", func); 3075 return false; 3076 } 3077 3078 if (access & GL_MAP_WRITE_BIT && 3079 !(bufObj->StorageFlags & GL_MAP_WRITE_BIT)) { 3080 _mesa_error(ctx, GL_INVALID_OPERATION, 3081 "%s(buffer does not allow write access)", func); 3082 return false; 3083 } 3084 3085 if (access & GL_MAP_COHERENT_BIT && 3086 !(bufObj->StorageFlags & GL_MAP_COHERENT_BIT)) { 3087 _mesa_error(ctx, GL_INVALID_OPERATION, 3088 "%s(buffer does not allow coherent access)", func); 3089 return false; 3090 } 3091 3092 if (access & GL_MAP_PERSISTENT_BIT && 3093 !(bufObj->StorageFlags & GL_MAP_PERSISTENT_BIT)) { 3094 _mesa_error(ctx, GL_INVALID_OPERATION, 3095 "%s(buffer does not allow persistent access)", func); 3096 return false; 3097 } 3098 3099 if (offset + length > bufObj->Size) { 3100 _mesa_error(ctx, GL_INVALID_VALUE, 3101 "%s(offset %lu + length %lu > buffer_size %lu)", func, 3102 (unsigned long) offset, (unsigned long) length, 3103 (unsigned long) bufObj->Size); 3104 return false; 3105 } 3106 3107 if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) { 3108 _mesa_error(ctx, GL_INVALID_OPERATION, 3109 "%s(buffer already mapped)", func); 3110 return false; 3111 } 3112 3113 if (access & GL_MAP_WRITE_BIT) { 3114 bufObj->NumMapBufferWriteCalls++; 3115 if ((bufObj->Usage == GL_STATIC_DRAW || 3116 bufObj->Usage == GL_STATIC_COPY) && 3117 bufObj->NumMapBufferWriteCalls >= BUFFER_WARNING_CALL_COUNT) { 3118 BUFFER_USAGE_WARNING(ctx, 3119 "using %s(buffer %u, offset %u, length %u) to " 3120 "update a %s buffer", 3121 func, bufObj->Name, offset, length, 3122 _mesa_enum_to_string(bufObj->Usage)); 3123 } 3124 } 3125 3126 return true; 3127 } 3128 3129 static void * 3130 map_buffer_range(struct gl_context *ctx, struct gl_buffer_object *bufObj, 3131 GLintptr offset, GLsizeiptr length, GLbitfield access, 3132 const char *func) 3133 { 3134 if (!bufObj->Size) { 3135 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(buffer size = 0)", func); 3136 return NULL; 3137 } 3138 3139 assert(ctx->Driver.MapBufferRange); 3140 void *map = ctx->Driver.MapBufferRange(ctx, offset, length, access, bufObj, 3141 MAP_USER); 3142 if (!map) { 3143 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(map failed)", func); 3144 } 3145 else { 3146 /* The driver callback should have set all these fields. 3147 * This is important because other modules (like VBO) might call 3148 * the driver function directly. 3149 */ 3150 assert(bufObj->Mappings[MAP_USER].Pointer == map); 3151 assert(bufObj->Mappings[MAP_USER].Length == length); 3152 assert(bufObj->Mappings[MAP_USER].Offset == offset); 3153 assert(bufObj->Mappings[MAP_USER].AccessFlags == access); 3154 } 3155 3156 if (access & GL_MAP_WRITE_BIT) { 3157 bufObj->Written = GL_TRUE; 3158 bufObj->MinMaxCacheDirty = true; 3159 } 3160 3161 #ifdef VBO_DEBUG 3162 if (strstr(func, "Range") == NULL) { /* If not MapRange */ 3163 printf("glMapBuffer(%u, sz %ld, access 0x%x)\n", 3164 bufObj->Name, bufObj->Size, access); 3165 /* Access must be write only */ 3166 if ((access & GL_MAP_WRITE_BIT) && (!(access & ~GL_MAP_WRITE_BIT))) { 3167 GLuint i; 3168 GLubyte *b = (GLubyte *) bufObj->Pointer; 3169 for (i = 0; i < bufObj->Size; i++) 3170 b[i] = i & 0xff; 3171 } 3172 } 3173 #endif 3174 3175 #ifdef BOUNDS_CHECK 3176 if (strstr(func, "Range") == NULL) { /* If not MapRange */ 3177 GLubyte *buf = (GLubyte *) bufObj->Pointer; 3178 GLuint i; 3179 /* buffer is 100 bytes larger than requested, fill with magic value */ 3180 for (i = 0; i < 100; i++) { 3181 buf[bufObj->Size - i - 1] = 123; 3182 } 3183 } 3184 #endif 3185 3186 return map; 3187 } 3188 3189 void * GLAPIENTRY 3190 _mesa_MapBufferRange_no_error(GLenum target, GLintptr offset, 3191 GLsizeiptr length, GLbitfield access) 3192 { 3193 GET_CURRENT_CONTEXT(ctx); 3194 3195 struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target); 3196 struct gl_buffer_object *bufObj = *bufObjPtr; 3197 3198 return map_buffer_range(ctx, bufObj, offset, length, access, 3199 "glMapBufferRange"); 3200 } 3201 3202 void * GLAPIENTRY 3203 _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, 3204 GLbitfield access) 3205 { 3206 GET_CURRENT_CONTEXT(ctx); 3207 struct gl_buffer_object *bufObj; 3208 3209 if (!ctx->Extensions.ARB_map_buffer_range) { 3210 _mesa_error(ctx, GL_INVALID_OPERATION, 3211 "glMapBufferRange(ARB_map_buffer_range not supported)"); 3212 return NULL; 3213 } 3214 3215 bufObj = get_buffer(ctx, "glMapBufferRange", target, GL_INVALID_OPERATION); 3216 if (!bufObj) 3217 return NULL; 3218 3219 if (!validate_map_buffer_range(ctx, bufObj, offset, length, access, 3220 "glMapBufferRange")) 3221 return NULL; 3222 3223 return map_buffer_range(ctx, bufObj, offset, length, access, 3224 "glMapBufferRange"); 3225 } 3226 3227 void * GLAPIENTRY 3228 _mesa_MapNamedBufferRange_no_error(GLuint buffer, GLintptr offset, 3229 GLsizeiptr length, GLbitfield access) 3230 { 3231 GET_CURRENT_CONTEXT(ctx); 3232 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer); 3233 3234 return map_buffer_range(ctx, bufObj, offset, length, access, 3235 "glMapNamedBufferRange"); 3236 } 3237 3238 void * GLAPIENTRY 3239 _mesa_MapNamedBufferRange(GLuint buffer, GLintptr offset, GLsizeiptr length, 3240 GLbitfield access) 3241 { 3242 GET_CURRENT_CONTEXT(ctx); 3243 struct gl_buffer_object *bufObj; 3244 3245 if (!ctx->Extensions.ARB_map_buffer_range) { 3246 _mesa_error(ctx, GL_INVALID_OPERATION, 3247 "glMapNamedBufferRange(" 3248 "ARB_map_buffer_range not supported)"); 3249 return NULL; 3250 } 3251 3252 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glMapNamedBufferRange"); 3253 if (!bufObj) 3254 return NULL; 3255 3256 if (!validate_map_buffer_range(ctx, bufObj, offset, length, access, 3257 "glMapNamedBufferRange")) 3258 return NULL; 3259 3260 return map_buffer_range(ctx, bufObj, offset, length, access, 3261 "glMapNamedBufferRange"); 3262 } 3263 3264 /** 3265 * Converts GLenum access from MapBuffer and MapNamedBuffer into 3266 * flags for input to map_buffer_range. 3267 * 3268 * \return true if the type of requested access is permissible. 3269 */ 3270 static bool 3271 get_map_buffer_access_flags(struct gl_context *ctx, GLenum access, 3272 GLbitfield *flags) 3273 { 3274 switch (access) { 3275 case GL_READ_ONLY_ARB: 3276 *flags = GL_MAP_READ_BIT; 3277 return _mesa_is_desktop_gl(ctx); 3278 case GL_WRITE_ONLY_ARB: 3279 *flags = GL_MAP_WRITE_BIT; 3280 return true; 3281 case GL_READ_WRITE_ARB: 3282 *flags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT; 3283 return _mesa_is_desktop_gl(ctx); 3284 default: 3285 *flags = 0; 3286 return false; 3287 } 3288 } 3289 3290 void * GLAPIENTRY 3291 _mesa_MapBuffer_no_error(GLenum target, GLenum access) 3292 { 3293 GET_CURRENT_CONTEXT(ctx); 3294 3295 GLbitfield accessFlags; 3296 get_map_buffer_access_flags(ctx, access, &accessFlags); 3297 3298 struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target); 3299 struct gl_buffer_object *bufObj = *bufObjPtr; 3300 3301 return map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags, 3302 "glMapBuffer"); 3303 } 3304 3305 void * GLAPIENTRY 3306 _mesa_MapBuffer(GLenum target, GLenum access) 3307 { 3308 GET_CURRENT_CONTEXT(ctx); 3309 struct gl_buffer_object *bufObj; 3310 GLbitfield accessFlags; 3311 3312 if (!get_map_buffer_access_flags(ctx, access, &accessFlags)) { 3313 _mesa_error(ctx, GL_INVALID_ENUM, "glMapBuffer(invalid access)"); 3314 return NULL; 3315 } 3316 3317 bufObj = get_buffer(ctx, "glMapBuffer", target, GL_INVALID_OPERATION); 3318 if (!bufObj) 3319 return NULL; 3320 3321 if (!validate_map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags, 3322 "glMapBuffer")) 3323 return NULL; 3324 3325 return map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags, 3326 "glMapBuffer"); 3327 } 3328 3329 void * GLAPIENTRY 3330 _mesa_MapNamedBuffer_no_error(GLuint buffer, GLenum access) 3331 { 3332 GET_CURRENT_CONTEXT(ctx); 3333 3334 GLbitfield accessFlags; 3335 get_map_buffer_access_flags(ctx, access, &accessFlags); 3336 3337 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer); 3338 3339 return map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags, 3340 "glMapNamedBuffer"); 3341 } 3342 3343 void * GLAPIENTRY 3344 _mesa_MapNamedBuffer(GLuint buffer, GLenum access) 3345 { 3346 GET_CURRENT_CONTEXT(ctx); 3347 struct gl_buffer_object *bufObj; 3348 GLbitfield accessFlags; 3349 3350 if (!get_map_buffer_access_flags(ctx, access, &accessFlags)) { 3351 _mesa_error(ctx, GL_INVALID_ENUM, "glMapNamedBuffer(invalid access)"); 3352 return NULL; 3353 } 3354 3355 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glMapNamedBuffer"); 3356 if (!bufObj) 3357 return NULL; 3358 3359 if (!validate_map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags, 3360 "glMapNamedBuffer")) 3361 return NULL; 3362 3363 return map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags, 3364 "glMapNamedBuffer"); 3365 } 3366 3367 3368 static void 3369 flush_mapped_buffer_range(struct gl_context *ctx, 3370 struct gl_buffer_object *bufObj, 3371 GLintptr offset, GLsizeiptr length, 3372 const char *func) 3373 { 3374 if (!ctx->Extensions.ARB_map_buffer_range) { 3375 _mesa_error(ctx, GL_INVALID_OPERATION, 3376 "%s(ARB_map_buffer_range not supported)", func); 3377 return; 3378 } 3379 3380 if (offset < 0) { 3381 _mesa_error(ctx, GL_INVALID_VALUE, 3382 "%s(offset %ld < 0)", func, (long) offset); 3383 return; 3384 } 3385 3386 if (length < 0) { 3387 _mesa_error(ctx, GL_INVALID_VALUE, 3388 "%s(length %ld < 0)", func, (long) length); 3389 return; 3390 } 3391 3392 if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) { 3393 /* buffer is not mapped */ 3394 _mesa_error(ctx, GL_INVALID_OPERATION, 3395 "%s(buffer is not mapped)", func); 3396 return; 3397 } 3398 3399 if ((bufObj->Mappings[MAP_USER].AccessFlags & 3400 GL_MAP_FLUSH_EXPLICIT_BIT) == 0) { 3401 _mesa_error(ctx, GL_INVALID_OPERATION, 3402 "%s(GL_MAP_FLUSH_EXPLICIT_BIT not set)", func); 3403 return; 3404 } 3405 3406 if (offset + length > bufObj->Mappings[MAP_USER].Length) { 3407 _mesa_error(ctx, GL_INVALID_VALUE, 3408 "%s(offset %ld + length %ld > mapped length %ld)", func, 3409 (long) offset, (long) length, 3410 (long) bufObj->Mappings[MAP_USER].Length); 3411 return; 3412 } 3413 3414 assert(bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_WRITE_BIT); 3415 3416 if (ctx->Driver.FlushMappedBufferRange) 3417 ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj, 3418 MAP_USER); 3419 } 3420 3421 void GLAPIENTRY 3422 _mesa_FlushMappedBufferRange_no_error(GLenum target, GLintptr offset, 3423 GLsizeiptr length) 3424 { 3425 GET_CURRENT_CONTEXT(ctx); 3426 struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target); 3427 struct gl_buffer_object *bufObj = *bufObjPtr; 3428 3429 if (ctx->Driver.FlushMappedBufferRange) 3430 ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj, 3431 MAP_USER); 3432 } 3433 3434 void GLAPIENTRY 3435 _mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, 3436 GLsizeiptr length) 3437 { 3438 GET_CURRENT_CONTEXT(ctx); 3439 struct gl_buffer_object *bufObj; 3440 3441 bufObj = get_buffer(ctx, "glFlushMappedBufferRange", target, 3442 GL_INVALID_OPERATION); 3443 if (!bufObj) 3444 return; 3445 3446 flush_mapped_buffer_range(ctx, bufObj, offset, length, 3447 "glFlushMappedBufferRange"); 3448 } 3449 3450 void GLAPIENTRY 3451 _mesa_FlushMappedNamedBufferRange_no_error(GLuint buffer, GLintptr offset, 3452 GLsizeiptr length) 3453 { 3454 GET_CURRENT_CONTEXT(ctx); 3455 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer); 3456 3457 if (ctx->Driver.FlushMappedBufferRange) 3458 ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj, 3459 MAP_USER); 3460 } 3461 3462 void GLAPIENTRY 3463 _mesa_FlushMappedNamedBufferRange(GLuint buffer, GLintptr offset, 3464 GLsizeiptr length) 3465 { 3466 GET_CURRENT_CONTEXT(ctx); 3467 struct gl_buffer_object *bufObj; 3468 3469 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, 3470 "glFlushMappedNamedBufferRange"); 3471 if (!bufObj) 3472 return; 3473 3474 flush_mapped_buffer_range(ctx, bufObj, offset, length, 3475 "glFlushMappedNamedBufferRange"); 3476 } 3477 3478 static void 3479 bind_buffer_range_uniform_buffer(struct gl_context *ctx, GLuint index, 3480 struct gl_buffer_object *bufObj, 3481 GLintptr offset, GLsizeiptr size) 3482 { 3483 if (bufObj == ctx->Shared->NullBufferObj) { 3484 offset = -1; 3485 size = -1; 3486 } 3487 3488 _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, bufObj); 3489 bind_uniform_buffer(ctx, index, bufObj, offset, size, GL_FALSE); 3490 } 3491 3492 /** 3493 * Bind a region of a buffer object to a uniform block binding point. 3494 * \param index the uniform buffer binding point index 3495 * \param bufObj the buffer object 3496 * \param offset offset to the start of buffer object region 3497 * \param size size of the buffer object region 3498 */ 3499 static void 3500 bind_buffer_range_uniform_buffer_err(struct gl_context *ctx, GLuint index, 3501 struct gl_buffer_object *bufObj, 3502 GLintptr offset, GLsizeiptr size) 3503 { 3504 if (index >= ctx->Const.MaxUniformBufferBindings) { 3505 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index); 3506 return; 3507 } 3508 3509 if (offset & (ctx->Const.UniformBufferOffsetAlignment - 1)) { 3510 _mesa_error(ctx, GL_INVALID_VALUE, 3511 "glBindBufferRange(offset misaligned %d/%d)", (int) offset, 3512 ctx->Const.UniformBufferOffsetAlignment); 3513 return; 3514 } 3515 3516 bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size); 3517 } 3518 3519 static void 3520 bind_buffer_range_shader_storage_buffer(struct gl_context *ctx, 3521 GLuint index, 3522 struct gl_buffer_object *bufObj, 3523 GLintptr offset, 3524 GLsizeiptr size) 3525 { 3526 if (bufObj == ctx->Shared->NullBufferObj) { 3527 offset = -1; 3528 size = -1; 3529 } 3530 3531 _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer, bufObj); 3532 bind_shader_storage_buffer(ctx, index, bufObj, offset, size, GL_FALSE); 3533 } 3534 3535 /** 3536 * Bind a region of a buffer object to a shader storage block binding point. 3537 * \param index the shader storage buffer binding point index 3538 * \param bufObj the buffer object 3539 * \param offset offset to the start of buffer object region 3540 * \param size size of the buffer object region 3541 */ 3542 static void 3543 bind_buffer_range_shader_storage_buffer_err(struct gl_context *ctx, 3544 GLuint index, 3545 struct gl_buffer_object *bufObj, 3546 GLintptr offset, GLsizeiptr size) 3547 { 3548 if (index >= ctx->Const.MaxShaderStorageBufferBindings) { 3549 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index); 3550 return; 3551 } 3552 3553 if (offset & (ctx->Const.ShaderStorageBufferOffsetAlignment - 1)) { 3554 _mesa_error(ctx, GL_INVALID_VALUE, 3555 "glBindBufferRange(offset misaligned %d/%d)", (int) offset, 3556 ctx->Const.ShaderStorageBufferOffsetAlignment); 3557 return; 3558 } 3559 3560 bind_buffer_range_shader_storage_buffer(ctx, index, bufObj, offset, size); 3561 } 3562 3563 static void 3564 bind_buffer_range_atomic_buffer(struct gl_context *ctx, GLuint index, 3565 struct gl_buffer_object *bufObj, 3566 GLintptr offset, GLsizeiptr size) 3567 { 3568 if (bufObj == ctx->Shared->NullBufferObj) { 3569 offset = -1; 3570 size = -1; 3571 } 3572 3573 _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, bufObj); 3574 bind_atomic_buffer(ctx, index, bufObj, offset, size, GL_FALSE); 3575 } 3576 3577 /** 3578 * Bind a region of a buffer object to an atomic storage block binding point. 3579 * \param index the shader storage buffer binding point index 3580 * \param bufObj the buffer object 3581 * \param offset offset to the start of buffer object region 3582 * \param size size of the buffer object region 3583 */ 3584 static void 3585 bind_buffer_range_atomic_buffer_err(struct gl_context *ctx, 3586 GLuint index, 3587 struct gl_buffer_object *bufObj, 3588 GLintptr offset, GLsizeiptr size) 3589 { 3590 if (index >= ctx->Const.MaxAtomicBufferBindings) { 3591 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index); 3592 return; 3593 } 3594 3595 if (offset & (ATOMIC_COUNTER_SIZE - 1)) { 3596 _mesa_error(ctx, GL_INVALID_VALUE, 3597 "glBindBufferRange(offset misaligned %d/%d)", (int) offset, 3598 ATOMIC_COUNTER_SIZE); 3599 return; 3600 } 3601 3602 bind_buffer_range_atomic_buffer(ctx, index, bufObj, offset, size); 3603 } 3604 3605 static inline bool 3606 bind_buffers_check_offset_and_size(struct gl_context *ctx, 3607 GLuint index, 3608 const GLintptr *offsets, 3609 const GLsizeiptr *sizes) 3610 { 3611 if (offsets[index] < 0) { 3612 /* The ARB_multi_bind spec says: 3613 * 3614 * "An INVALID_VALUE error is generated by BindBuffersRange if any 3615 * value in <offsets> is less than zero (per binding)." 3616 */ 3617 _mesa_error(ctx, GL_INVALID_VALUE, 3618 "glBindBuffersRange(offsets[%u]=%" PRId64 " < 0)", 3619 index, (int64_t) offsets[index]); 3620 return false; 3621 } 3622 3623 if (sizes[index] <= 0) { 3624 /* The ARB_multi_bind spec says: 3625 * 3626 * "An INVALID_VALUE error is generated by BindBuffersRange if any 3627 * value in <sizes> is less than or equal to zero (per binding)." 3628 */ 3629 _mesa_error(ctx, GL_INVALID_VALUE, 3630 "glBindBuffersRange(sizes[%u]=%" PRId64 " <= 0)", 3631 index, (int64_t) sizes[index]); 3632 return false; 3633 } 3634 3635 return true; 3636 } 3637 3638 static bool 3639 error_check_bind_uniform_buffers(struct gl_context *ctx, 3640 GLuint first, GLsizei count, 3641 const char *caller) 3642 { 3643 if (!ctx->Extensions.ARB_uniform_buffer_object) { 3644 _mesa_error(ctx, GL_INVALID_ENUM, 3645 "%s(target=GL_UNIFORM_BUFFER)", caller); 3646 return false; 3647 } 3648 3649 /* The ARB_multi_bind_spec says: 3650 * 3651 * "An INVALID_OPERATION error is generated if <first> + <count> is 3652 * greater than the number of target-specific indexed binding points, 3653 * as described in section 6.7.1." 3654 */ 3655 if (first + count > ctx->Const.MaxUniformBufferBindings) { 3656 _mesa_error(ctx, GL_INVALID_OPERATION, 3657 "%s(first=%u + count=%d > the value of " 3658 "GL_MAX_UNIFORM_BUFFER_BINDINGS=%u)", 3659 caller, first, count, 3660 ctx->Const.MaxUniformBufferBindings); 3661 return false; 3662 } 3663 3664 return true; 3665 } 3666 3667 static bool 3668 error_check_bind_shader_storage_buffers(struct gl_context *ctx, 3669 GLuint first, GLsizei count, 3670 const char *caller) 3671 { 3672 if (!ctx->Extensions.ARB_shader_storage_buffer_object) { 3673 _mesa_error(ctx, GL_INVALID_ENUM, 3674 "%s(target=GL_SHADER_STORAGE_BUFFER)", caller); 3675 return false; 3676 } 3677 3678 /* The ARB_multi_bind_spec says: 3679 * 3680 * "An INVALID_OPERATION error is generated if <first> + <count> is 3681 * greater than the number of target-specific indexed binding points, 3682 * as described in section 6.7.1." 3683 */ 3684 if (first + count > ctx->Const.MaxShaderStorageBufferBindings) { 3685 _mesa_error(ctx, GL_INVALID_OPERATION, 3686 "%s(first=%u + count=%d > the value of " 3687 "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS=%u)", 3688 caller, first, count, 3689 ctx->Const.MaxShaderStorageBufferBindings); 3690 return false; 3691 } 3692 3693 return true; 3694 } 3695 3696 /** 3697 * Unbind all uniform buffers in the range 3698 * <first> through <first>+<count>-1 3699 */ 3700 static void 3701 unbind_uniform_buffers(struct gl_context *ctx, GLuint first, GLsizei count) 3702 { 3703 struct gl_buffer_object *bufObj = ctx->Shared->NullBufferObj; 3704 3705 for (int i = 0; i < count; i++) 3706 set_buffer_binding(ctx, &ctx->UniformBufferBindings[first + i], 3707 bufObj, -1, -1, GL_TRUE, 0); 3708 } 3709 3710 /** 3711 * Unbind all shader storage buffers in the range 3712 * <first> through <first>+<count>-1 3713 */ 3714 static void 3715 unbind_shader_storage_buffers(struct gl_context *ctx, GLuint first, 3716 GLsizei count) 3717 { 3718 struct gl_buffer_object *bufObj = ctx->Shared->NullBufferObj; 3719 3720 for (int i = 0; i < count; i++) 3721 set_buffer_binding(ctx, &ctx->ShaderStorageBufferBindings[first + i], 3722 bufObj, -1, -1, GL_TRUE, 0); 3723 } 3724 3725 static void 3726 bind_uniform_buffers(struct gl_context *ctx, GLuint first, GLsizei count, 3727 const GLuint *buffers, 3728 bool range, 3729 const GLintptr *offsets, const GLsizeiptr *sizes, 3730 const char *caller) 3731 { 3732 if (!error_check_bind_uniform_buffers(ctx, first, count, caller)) 3733 return; 3734 3735 /* Assume that at least one binding will be changed */ 3736 FLUSH_VERTICES(ctx, 0); 3737 ctx->NewDriverState |= ctx->DriverFlags.NewUniformBuffer; 3738 3739 if (!buffers) { 3740 /* The ARB_multi_bind spec says: 3741 * 3742 * "If <buffers> is NULL, all bindings from <first> through 3743 * <first>+<count>-1 are reset to their unbound (zero) state. 3744 * In this case, the offsets and sizes associated with the 3745 * binding points are set to default values, ignoring 3746 * <offsets> and <sizes>." 3747 */ 3748 unbind_uniform_buffers(ctx, first, count); 3749 return; 3750 } 3751 3752 /* Note that the error semantics for multi-bind commands differ from 3753 * those of other GL commands. 3754 * 3755 * The Issues section in the ARB_multi_bind spec says: 3756 * 3757 * "(11) Typically, OpenGL specifies that if an error is generated by a 3758 * command, that command has no effect. This is somewhat 3759 * unfortunate for multi-bind commands, because it would require a 3760 * first pass to scan the entire list of bound objects for errors 3761 * and then a second pass to actually perform the bindings. 3762 * Should we have different error semantics? 3763 * 3764 * RESOLVED: Yes. In this specification, when the parameters for 3765 * one of the <count> binding points are invalid, that binding point 3766 * is not updated and an error will be generated. However, other 3767 * binding points in the same command will be updated if their 3768 * parameters are valid and no other error occurs." 3769 */ 3770 3771 _mesa_HashLockMutex(ctx->Shared->BufferObjects); 3772 3773 for (int i = 0; i < count; i++) { 3774 struct gl_buffer_binding *binding = 3775 &ctx->UniformBufferBindings[first + i]; 3776 GLintptr offset = 0; 3777 GLsizeiptr size = 0; 3778 3779 if (range) { 3780 if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes)) 3781 continue; 3782 3783 /* The ARB_multi_bind spec says: 3784 * 3785 * "An INVALID_VALUE error is generated by BindBuffersRange if any 3786 * pair of values in <offsets> and <sizes> does not respectively 3787 * satisfy the constraints described for those parameters for the 3788 * specified target, as described in section 6.7.1 (per binding)." 3789 * 3790 * Section 6.7.1 refers to table 6.5, which says: 3791 * 3792 * " 3793 * Uniform buffer array bindings (see sec. 7.6) 3794 * 3795 * ... ... 3796 * offset restriction multiple of value of UNIFORM_BUFFER_- 3797 * OFFSET_ALIGNMENT 3798 * ... ... 3799 * size restriction none 3800 * " 3801 */ 3802 if (offsets[i] & (ctx->Const.UniformBufferOffsetAlignment - 1)) { 3803 _mesa_error(ctx, GL_INVALID_VALUE, 3804 "glBindBuffersRange(offsets[%u]=%" PRId64 3805 " is misaligned; it must be a multiple of the value of " 3806 "GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT=%u when " 3807 "target=GL_UNIFORM_BUFFER)", 3808 i, (int64_t) offsets[i], 3809 ctx->Const.UniformBufferOffsetAlignment); 3810 continue; 3811 } 3812 3813 offset = offsets[i]; 3814 size = sizes[i]; 3815 } 3816 3817 set_buffer_multi_binding(ctx, buffers, i, caller, 3818 binding, offset, size, range, 3819 USAGE_UNIFORM_BUFFER); 3820 } 3821 3822 _mesa_HashUnlockMutex(ctx->Shared->BufferObjects); 3823 } 3824 3825 static void 3826 bind_shader_storage_buffers(struct gl_context *ctx, GLuint first, 3827 GLsizei count, const GLuint *buffers, 3828 bool range, 3829 const GLintptr *offsets, 3830 const GLsizeiptr *sizes, 3831 const char *caller) 3832 { 3833 if (!error_check_bind_shader_storage_buffers(ctx, first, count, caller)) 3834 return; 3835 3836 /* Assume that at least one binding will be changed */ 3837 FLUSH_VERTICES(ctx, 0); 3838 ctx->NewDriverState |= ctx->DriverFlags.NewShaderStorageBuffer; 3839 3840 if (!buffers) { 3841 /* The ARB_multi_bind spec says: 3842 * 3843 * "If <buffers> is NULL, all bindings from <first> through 3844 * <first>+<count>-1 are reset to their unbound (zero) state. 3845 * In this case, the offsets and sizes associated with the 3846 * binding points are set to default values, ignoring 3847 * <offsets> and <sizes>." 3848 */ 3849 unbind_shader_storage_buffers(ctx, first, count); 3850 return; 3851 } 3852 3853 /* Note that the error semantics for multi-bind commands differ from 3854 * those of other GL commands. 3855 * 3856 * The Issues section in the ARB_multi_bind spec says: 3857 * 3858 * "(11) Typically, OpenGL specifies that if an error is generated by a 3859 * command, that command has no effect. This is somewhat 3860 * unfortunate for multi-bind commands, because it would require a 3861 * first pass to scan the entire list of bound objects for errors 3862 * and then a second pass to actually perform the bindings. 3863 * Should we have different error semantics? 3864 * 3865 * RESOLVED: Yes. In this specification, when the parameters for 3866 * one of the <count> binding points are invalid, that binding point 3867 * is not updated and an error will be generated. However, other 3868 * binding points in the same command will be updated if their 3869 * parameters are valid and no other error occurs." 3870 */ 3871 3872 _mesa_HashLockMutex(ctx->Shared->BufferObjects); 3873 3874 for (int i = 0; i < count; i++) { 3875 struct gl_buffer_binding *binding = 3876 &ctx->ShaderStorageBufferBindings[first + i]; 3877 GLintptr offset = 0; 3878 GLsizeiptr size = 0; 3879 3880 if (range) { 3881 if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes)) 3882 continue; 3883 3884 /* The ARB_multi_bind spec says: 3885 * 3886 * "An INVALID_VALUE error is generated by BindBuffersRange if any 3887 * pair of values in <offsets> and <sizes> does not respectively 3888 * satisfy the constraints described for those parameters for the 3889 * specified target, as described in section 6.7.1 (per binding)." 3890 * 3891 * Section 6.7.1 refers to table 6.5, which says: 3892 * 3893 * " 3894 * Shader storage buffer array bindings (see sec. 7.8) 3895 * 3896 * ... ... 3897 * offset restriction multiple of value of SHADER_STORAGE_- 3898 * BUFFER_OFFSET_ALIGNMENT 3899 * ... ... 3900 * size restriction none 3901 * " 3902 */ 3903 if (offsets[i] & (ctx->Const.ShaderStorageBufferOffsetAlignment - 1)) { 3904 _mesa_error(ctx, GL_INVALID_VALUE, 3905 "glBindBuffersRange(offsets[%u]=%" PRId64 3906 " is misaligned; it must be a multiple of the value of " 3907 "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT=%u when " 3908 "target=GL_SHADER_STORAGE_BUFFER)", 3909 i, (int64_t) offsets[i], 3910 ctx->Const.ShaderStorageBufferOffsetAlignment); 3911 continue; 3912 } 3913 3914 offset = offsets[i]; 3915 size = sizes[i]; 3916 } 3917 3918 set_buffer_multi_binding(ctx, buffers, i, caller, 3919 binding, offset, size, range, 3920 USAGE_SHADER_STORAGE_BUFFER); 3921 } 3922 3923 _mesa_HashUnlockMutex(ctx->Shared->BufferObjects); 3924 } 3925 3926 static bool 3927 error_check_bind_xfb_buffers(struct gl_context *ctx, 3928 struct gl_transform_feedback_object *tfObj, 3929 GLuint first, GLsizei count, const char *caller) 3930 { 3931 if (!ctx->Extensions.EXT_transform_feedback) { 3932 _mesa_error(ctx, GL_INVALID_ENUM, 3933 "%s(target=GL_TRANSFORM_FEEDBACK_BUFFER)", caller); 3934 return false; 3935 } 3936 3937 /* Page 398 of the PDF of the OpenGL 4.4 (Core Profile) spec says: 3938 * 3939 * "An INVALID_OPERATION error is generated : 3940 * 3941 * ... 3942 * by BindBufferRange or BindBufferBase if target is TRANSFORM_- 3943 * FEEDBACK_BUFFER and transform feedback is currently active." 3944 * 3945 * We assume that this is also meant to apply to BindBuffersRange 3946 * and BindBuffersBase. 3947 */ 3948 if (tfObj->Active) { 3949 _mesa_error(ctx, GL_INVALID_OPERATION, 3950 "%s(Changing transform feedback buffers while " 3951 "transform feedback is active)", caller); 3952 return false; 3953 } 3954 3955 /* The ARB_multi_bind_spec says: 3956 * 3957 * "An INVALID_OPERATION error is generated if <first> + <count> is 3958 * greater than the number of target-specific indexed binding points, 3959 * as described in section 6.7.1." 3960 */ 3961 if (first + count > ctx->Const.MaxTransformFeedbackBuffers) { 3962 _mesa_error(ctx, GL_INVALID_OPERATION, 3963 "%s(first=%u + count=%d > the value of " 3964 "GL_MAX_TRANSFORM_FEEDBACK_BUFFERS=%u)", 3965 caller, first, count, 3966 ctx->Const.MaxTransformFeedbackBuffers); 3967 return false; 3968 } 3969 3970 return true; 3971 } 3972 3973 /** 3974 * Unbind all transform feedback buffers in the range 3975 * <first> through <first>+<count>-1 3976 */ 3977 static void 3978 unbind_xfb_buffers(struct gl_context *ctx, 3979 struct gl_transform_feedback_object *tfObj, 3980 GLuint first, GLsizei count) 3981 { 3982 struct gl_buffer_object * const bufObj = ctx->Shared->NullBufferObj; 3983 3984 for (int i = 0; i < count; i++) 3985 _mesa_set_transform_feedback_binding(ctx, tfObj, first + i, 3986 bufObj, 0, 0); 3987 } 3988 3989 static void 3990 bind_xfb_buffers(struct gl_context *ctx, 3991 GLuint first, GLsizei count, 3992 const GLuint *buffers, 3993 bool range, 3994 const GLintptr *offsets, 3995 const GLsizeiptr *sizes, 3996 const char *caller) 3997 { 3998 struct gl_transform_feedback_object *tfObj = 3999 ctx->TransformFeedback.CurrentObject; 4000 4001 if (!error_check_bind_xfb_buffers(ctx, tfObj, first, count, caller)) 4002 return; 4003 4004 /* Assume that at least one binding will be changed */ 4005 FLUSH_VERTICES(ctx, 0); 4006 ctx->NewDriverState |= ctx->DriverFlags.NewTransformFeedback; 4007 4008 if (!buffers) { 4009 /* The ARB_multi_bind spec says: 4010 * 4011 * "If <buffers> is NULL, all bindings from <first> through 4012 * <first>+<count>-1 are reset to their unbound (zero) state. 4013 * In this case, the offsets and sizes associated with the 4014 * binding points are set to default values, ignoring 4015 * <offsets> and <sizes>." 4016 */ 4017 unbind_xfb_buffers(ctx, tfObj, first, count); 4018 return; 4019 } 4020 4021 /* Note that the error semantics for multi-bind commands differ from 4022 * those of other GL commands. 4023 * 4024 * The Issues section in the ARB_multi_bind spec says: 4025 * 4026 * "(11) Typically, OpenGL specifies that if an error is generated by a 4027 * command, that command has no effect. This is somewhat 4028 * unfortunate for multi-bind commands, because it would require a 4029 * first pass to scan the entire list of bound objects for errors 4030 * and then a second pass to actually perform the bindings. 4031 * Should we have different error semantics? 4032 * 4033 * RESOLVED: Yes. In this specification, when the parameters for 4034 * one of the <count> binding points are invalid, that binding point 4035 * is not updated and an error will be generated. However, other 4036 * binding points in the same command will be updated if their 4037 * parameters are valid and no other error occurs." 4038 */ 4039 4040 _mesa_HashLockMutex(ctx->Shared->BufferObjects); 4041 4042 for (int i = 0; i < count; i++) { 4043 const GLuint index = first + i; 4044 struct gl_buffer_object * const boundBufObj = tfObj->Buffers[index]; 4045 struct gl_buffer_object *bufObj; 4046 GLintptr offset = 0; 4047 GLsizeiptr size = 0; 4048 4049 if (range) { 4050 if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes)) 4051 continue; 4052 4053 /* The ARB_multi_bind spec says: 4054 * 4055 * "An INVALID_VALUE error is generated by BindBuffersRange if any 4056 * pair of values in <offsets> and <sizes> does not respectively 4057 * satisfy the constraints described for those parameters for the 4058 * specified target, as described in section 6.7.1 (per binding)." 4059 * 4060 * Section 6.7.1 refers to table 6.5, which says: 4061 * 4062 * " 4063 * Transform feedback array bindings (see sec. 13.2.2) 4064 * 4065 * ... ... 4066 * offset restriction multiple of 4 4067 * ... ... 4068 * size restriction multiple of 4 4069 * " 4070 */ 4071 if (offsets[i] & 0x3) { 4072 _mesa_error(ctx, GL_INVALID_VALUE, 4073 "glBindBuffersRange(offsets[%u]=%" PRId64 4074 " is misaligned; it must be a multiple of 4 when " 4075 "target=GL_TRANSFORM_FEEDBACK_BUFFER)", 4076 i, (int64_t) offsets[i]); 4077 continue; 4078 } 4079 4080 if (sizes[i] & 0x3) { 4081 _mesa_error(ctx, GL_INVALID_VALUE, 4082 "glBindBuffersRange(sizes[%u]=%" PRId64 4083 " is misaligned; it must be a multiple of 4 when " 4084 "target=GL_TRANSFORM_FEEDBACK_BUFFER)", 4085 i, (int64_t) sizes[i]); 4086 continue; 4087 } 4088 4089 offset = offsets[i]; 4090 size = sizes[i]; 4091 } 4092 4093 if (boundBufObj && boundBufObj->Name == buffers[i]) 4094 bufObj = boundBufObj; 4095 else 4096 bufObj = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, caller); 4097 4098 if (bufObj) 4099 _mesa_set_transform_feedback_binding(ctx, tfObj, index, bufObj, 4100 offset, size); 4101 } 4102 4103 _mesa_HashUnlockMutex(ctx->Shared->BufferObjects); 4104 } 4105 4106 static bool 4107 error_check_bind_atomic_buffers(struct gl_context *ctx, 4108 GLuint first, GLsizei count, 4109 const char *caller) 4110 { 4111 if (!ctx->Extensions.ARB_shader_atomic_counters) { 4112 _mesa_error(ctx, GL_INVALID_ENUM, 4113 "%s(target=GL_ATOMIC_COUNTER_BUFFER)", caller); 4114 return false; 4115 } 4116 4117 /* The ARB_multi_bind_spec says: 4118 * 4119 * "An INVALID_OPERATION error is generated if <first> + <count> is 4120 * greater than the number of target-specific indexed binding points, 4121 * as described in section 6.7.1." 4122 */ 4123 if (first + count > ctx->Const.MaxAtomicBufferBindings) { 4124 _mesa_error(ctx, GL_INVALID_OPERATION, 4125 "%s(first=%u + count=%d > the value of " 4126 "GL_MAX_ATOMIC_BUFFER_BINDINGS=%u)", 4127 caller, first, count, ctx->Const.MaxAtomicBufferBindings); 4128 return false; 4129 } 4130 4131 return true; 4132 } 4133 4134 /** 4135 * Unbind all atomic counter buffers in the range 4136 * <first> through <first>+<count>-1 4137 */ 4138 static void 4139 unbind_atomic_buffers(struct gl_context *ctx, GLuint first, GLsizei count) 4140 { 4141 struct gl_buffer_object * const bufObj = ctx->Shared->NullBufferObj; 4142 4143 for (int i = 0; i < count; i++) 4144 set_buffer_binding(ctx, &ctx->AtomicBufferBindings[first + i], 4145 bufObj, -1, -1, GL_TRUE, 0); 4146 } 4147 4148 static void 4149 bind_atomic_buffers(struct gl_context *ctx, 4150 GLuint first, 4151 GLsizei count, 4152 const GLuint *buffers, 4153 bool range, 4154 const GLintptr *offsets, 4155 const GLsizeiptr *sizes, 4156 const char *caller) 4157 { 4158 if (!error_check_bind_atomic_buffers(ctx, first, count, caller)) 4159 return; 4160 4161 /* Assume that at least one binding will be changed */ 4162 FLUSH_VERTICES(ctx, 0); 4163 ctx->NewDriverState |= ctx->DriverFlags.NewAtomicBuffer; 4164 4165 if (!buffers) { 4166 /* The ARB_multi_bind spec says: 4167 * 4168 * "If <buffers> is NULL, all bindings from <first> through 4169 * <first>+<count>-1 are reset to their unbound (zero) state. 4170 * In this case, the offsets and sizes associated with the 4171 * binding points are set to default values, ignoring 4172 * <offsets> and <sizes>." 4173 */ 4174 unbind_atomic_buffers(ctx, first, count); 4175 return; 4176 } 4177 4178 /* Note that the error semantics for multi-bind commands differ from 4179 * those of other GL commands. 4180 * 4181 * The Issues section in the ARB_multi_bind spec says: 4182 * 4183 * "(11) Typically, OpenGL specifies that if an error is generated by a 4184 * command, that command has no effect. This is somewhat 4185 * unfortunate for multi-bind commands, because it would require a 4186 * first pass to scan the entire list of bound objects for errors 4187 * and then a second pass to actually perform the bindings. 4188 * Should we have different error semantics? 4189 * 4190 * RESOLVED: Yes. In this specification, when the parameters for 4191 * one of the <count> binding points are invalid, that binding point 4192 * is not updated and an error will be generated. However, other 4193 * binding points in the same command will be updated if their 4194 * parameters are valid and no other error occurs." 4195 */ 4196 4197 _mesa_HashLockMutex(ctx->Shared->BufferObjects); 4198 4199 for (int i = 0; i < count; i++) { 4200 struct gl_buffer_binding *binding = 4201 &ctx->AtomicBufferBindings[first + i]; 4202 GLintptr offset = 0; 4203 GLsizeiptr size = 0; 4204 4205 if (range) { 4206 if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes)) 4207 continue; 4208 4209 /* The ARB_multi_bind spec says: 4210 * 4211 * "An INVALID_VALUE error is generated by BindBuffersRange if any 4212 * pair of values in <offsets> and <sizes> does not respectively 4213 * satisfy the constraints described for those parameters for the 4214 * specified target, as described in section 6.7.1 (per binding)." 4215 * 4216 * Section 6.7.1 refers to table 6.5, which says: 4217 * 4218 * " 4219 * Atomic counter array bindings (see sec. 7.7.2) 4220 * 4221 * ... ... 4222 * offset restriction multiple of 4 4223 * ... ... 4224 * size restriction none 4225 * " 4226 */ 4227 if (offsets[i] & (ATOMIC_COUNTER_SIZE - 1)) { 4228 _mesa_error(ctx, GL_INVALID_VALUE, 4229 "glBindBuffersRange(offsets[%u]=%" PRId64 4230 " is misaligned; it must be a multiple of %d when " 4231 "target=GL_ATOMIC_COUNTER_BUFFER)", 4232 i, (int64_t) offsets[i], ATOMIC_COUNTER_SIZE); 4233 continue; 4234 } 4235 4236 offset = offsets[i]; 4237 size = sizes[i]; 4238 } 4239 4240 set_buffer_multi_binding(ctx, buffers, i, caller, 4241 binding, offset, size, range, 4242 USAGE_ATOMIC_COUNTER_BUFFER); 4243 } 4244 4245 _mesa_HashUnlockMutex(ctx->Shared->BufferObjects); 4246 } 4247 4248 static ALWAYS_INLINE void 4249 bind_buffer_range(GLenum target, GLuint index, GLuint buffer, GLintptr offset, 4250 GLsizeiptr size, bool no_error) 4251 { 4252 GET_CURRENT_CONTEXT(ctx); 4253 struct gl_buffer_object *bufObj; 4254 4255 if (MESA_VERBOSE & VERBOSE_API) { 4256 _mesa_debug(ctx, "glBindBufferRange(%s, %u, %u, %lu, %lu)\n", 4257 _mesa_enum_to_string(target), index, buffer, 4258 (unsigned long) offset, (unsigned long) size); 4259 } 4260 4261 if (buffer == 0) { 4262 bufObj = ctx->Shared->NullBufferObj; 4263 } else { 4264 bufObj = _mesa_lookup_bufferobj(ctx, buffer); 4265 if (!_mesa_handle_bind_buffer_gen(ctx, buffer, 4266 &bufObj, "glBindBufferRange")) 4267 return; 4268 4269 if (!no_error && !bufObj) { 4270 _mesa_error(ctx, GL_INVALID_OPERATION, 4271 "glBindBufferRange(invalid buffer=%u)", buffer); 4272 return; 4273 } 4274 } 4275 4276 if (no_error) { 4277 switch (target) { 4278 case GL_TRANSFORM_FEEDBACK_BUFFER: 4279 _mesa_bind_buffer_range_xfb(ctx, ctx->TransformFeedback.CurrentObject, 4280 index, bufObj, offset, size); 4281 return; 4282 case GL_UNIFORM_BUFFER: 4283 bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size); 4284 return; 4285 case GL_SHADER_STORAGE_BUFFER: 4286 bind_buffer_range_shader_storage_buffer(ctx, index, bufObj, offset, 4287 size); 4288 return; 4289 case GL_ATOMIC_COUNTER_BUFFER: 4290 bind_buffer_range_atomic_buffer(ctx, index, bufObj, offset, size); 4291 return; 4292 default: 4293 unreachable("invalid BindBufferRange target with KHR_no_error"); 4294 } 4295 } else { 4296 if (buffer != 0) { 4297 if (size <= 0) { 4298 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size=%d)", 4299 (int) size); 4300 return; 4301 } 4302 } 4303 4304 switch (target) { 4305 case GL_TRANSFORM_FEEDBACK_BUFFER: 4306 if (!_mesa_validate_buffer_range_xfb(ctx, 4307 ctx->TransformFeedback.CurrentObject, 4308 index, bufObj, offset, size, 4309 false)) 4310 return; 4311 4312 _mesa_bind_buffer_range_xfb(ctx, ctx->TransformFeedback.CurrentObject, 4313 index, bufObj, offset, size); 4314 return; 4315 case GL_UNIFORM_BUFFER: 4316 bind_buffer_range_uniform_buffer_err(ctx, index, bufObj, offset, 4317 size); 4318 return; 4319 case GL_SHADER_STORAGE_BUFFER: 4320 bind_buffer_range_shader_storage_buffer_err(ctx, index, bufObj, 4321 offset, size); 4322 return; 4323 case GL_ATOMIC_COUNTER_BUFFER: 4324 bind_buffer_range_atomic_buffer_err(ctx, index, bufObj, 4325 offset, size); 4326 return; 4327 default: 4328 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferRange(target)"); 4329 return; 4330 } 4331 } 4332 } 4333 4334 void GLAPIENTRY 4335 _mesa_BindBufferRange_no_error(GLenum target, GLuint index, GLuint buffer, 4336 GLintptr offset, GLsizeiptr size) 4337 { 4338 bind_buffer_range(target, index, buffer, offset, size, true); 4339 } 4340 4341 void GLAPIENTRY 4342 _mesa_BindBufferRange(GLenum target, GLuint index, 4343 GLuint buffer, GLintptr offset, GLsizeiptr size) 4344 { 4345 bind_buffer_range(target, index, buffer, offset, size, false); 4346 } 4347 4348 void GLAPIENTRY 4349 _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer) 4350 { 4351 GET_CURRENT_CONTEXT(ctx); 4352 struct gl_buffer_object *bufObj; 4353 4354 if (MESA_VERBOSE & VERBOSE_API) { 4355 _mesa_debug(ctx, "glBindBufferBase(%s, %u, %u)\n", 4356 _mesa_enum_to_string(target), index, buffer); 4357 } 4358 4359 if (buffer == 0) { 4360 bufObj = ctx->Shared->NullBufferObj; 4361 } else { 4362 bufObj = _mesa_lookup_bufferobj(ctx, buffer); 4363 if (!_mesa_handle_bind_buffer_gen(ctx, buffer, 4364 &bufObj, "glBindBufferBase")) 4365 return; 4366 4367 if (!bufObj) { 4368 _mesa_error(ctx, GL_INVALID_OPERATION, 4369 "glBindBufferBase(invalid buffer=%u)", buffer); 4370 return; 4371 } 4372 } 4373 4374 /* Note that there's some oddness in the GL 3.1-GL 3.3 specifications with 4375 * regards to BindBufferBase. It says (GL 3.1 core spec, page 63): 4376 * 4377 * "BindBufferBase is equivalent to calling BindBufferRange with offset 4378 * zero and size equal to the size of buffer." 4379 * 4380 * but it says for glGetIntegeri_v (GL 3.1 core spec, page 230): 4381 * 4382 * "If the parameter (starting offset or size) was not specified when the 4383 * buffer object was bound, zero is returned." 4384 * 4385 * What happens if the size of the buffer changes? Does the size of the 4386 * buffer at the moment glBindBufferBase was called still play a role, like 4387 * the first quote would imply, or is the size meaningless in the 4388 * glBindBufferBase case like the second quote would suggest? The GL 4.1 4389 * core spec page 45 says: 4390 * 4391 * "It is equivalent to calling BindBufferRange with offset zero, while 4392 * size is determined by the size of the bound buffer at the time the 4393 * binding is used." 4394 * 4395 * My interpretation is that the GL 4.1 spec was a clarification of the 4396 * behavior, not a change. In particular, this choice will only make 4397 * rendering work in cases where it would have had undefined results. 4398 */ 4399 4400 switch (target) { 4401 case GL_TRANSFORM_FEEDBACK_BUFFER: 4402 _mesa_bind_buffer_base_transform_feedback(ctx, 4403 ctx->TransformFeedback.CurrentObject, 4404 index, bufObj, false); 4405 return; 4406 case GL_UNIFORM_BUFFER: 4407 bind_buffer_base_uniform_buffer(ctx, index, bufObj); 4408 return; 4409 case GL_SHADER_STORAGE_BUFFER: 4410 bind_buffer_base_shader_storage_buffer(ctx, index, bufObj); 4411 return; 4412 case GL_ATOMIC_COUNTER_BUFFER: 4413 bind_buffer_base_atomic_buffer(ctx, index, bufObj); 4414 return; 4415 default: 4416 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferBase(target)"); 4417 return; 4418 } 4419 } 4420 4421 void GLAPIENTRY 4422 _mesa_BindBuffersRange(GLenum target, GLuint first, GLsizei count, 4423 const GLuint *buffers, 4424 const GLintptr *offsets, const GLsizeiptr *sizes) 4425 { 4426 GET_CURRENT_CONTEXT(ctx); 4427 4428 if (MESA_VERBOSE & VERBOSE_API) { 4429 _mesa_debug(ctx, "glBindBuffersRange(%s, %u, %d, %p, %p, %p)\n", 4430 _mesa_enum_to_string(target), first, count, 4431 buffers, offsets, sizes); 4432 } 4433 4434 switch (target) { 4435 case GL_TRANSFORM_FEEDBACK_BUFFER: 4436 bind_xfb_buffers(ctx, first, count, buffers, true, offsets, sizes, 4437 "glBindBuffersRange"); 4438 return; 4439 case GL_UNIFORM_BUFFER: 4440 bind_uniform_buffers(ctx, first, count, buffers, true, offsets, sizes, 4441 "glBindBuffersRange"); 4442 return; 4443 case GL_SHADER_STORAGE_BUFFER: 4444 bind_shader_storage_buffers(ctx, first, count, buffers, true, offsets, sizes, 4445 "glBindBuffersRange"); 4446 return; 4447 case GL_ATOMIC_COUNTER_BUFFER: 4448 bind_atomic_buffers(ctx, first, count, buffers, true, offsets, sizes, 4449 "glBindBuffersRange"); 4450 return; 4451 default: 4452 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBuffersRange(target=%s)", 4453 _mesa_enum_to_string(target)); 4454 break; 4455 } 4456 } 4457 4458 void GLAPIENTRY 4459 _mesa_BindBuffersBase(GLenum target, GLuint first, GLsizei count, 4460 const GLuint *buffers) 4461 { 4462 GET_CURRENT_CONTEXT(ctx); 4463 4464 if (MESA_VERBOSE & VERBOSE_API) { 4465 _mesa_debug(ctx, "glBindBuffersBase(%s, %u, %d, %p)\n", 4466 _mesa_enum_to_string(target), first, count, buffers); 4467 } 4468 4469 switch (target) { 4470 case GL_TRANSFORM_FEEDBACK_BUFFER: 4471 bind_xfb_buffers(ctx, first, count, buffers, false, NULL, NULL, 4472 "glBindBuffersBase"); 4473 return; 4474 case GL_UNIFORM_BUFFER: 4475 bind_uniform_buffers(ctx, first, count, buffers, false, NULL, NULL, 4476 "glBindBuffersBase"); 4477 return; 4478 case GL_SHADER_STORAGE_BUFFER: 4479 bind_shader_storage_buffers(ctx, first, count, buffers, false, NULL, NULL, 4480 "glBindBuffersBase"); 4481 return; 4482 case GL_ATOMIC_COUNTER_BUFFER: 4483 bind_atomic_buffers(ctx, first, count, buffers, false, NULL, NULL, 4484 "glBindBuffersBase"); 4485 return; 4486 default: 4487 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBuffersBase(target=%s)", 4488 _mesa_enum_to_string(target)); 4489 break; 4490 } 4491 } 4492 4493 static ALWAYS_INLINE void 4494 invalidate_buffer_subdata(struct gl_context *ctx, 4495 struct gl_buffer_object *bufObj, GLintptr offset, 4496 GLsizeiptr length) 4497 { 4498 if (ctx->Driver.InvalidateBufferSubData) 4499 ctx->Driver.InvalidateBufferSubData(ctx, bufObj, offset, length); 4500 } 4501 4502 void GLAPIENTRY 4503 _mesa_InvalidateBufferSubData_no_error(GLuint buffer, GLintptr offset, 4504 GLsizeiptr length) 4505 { 4506 GET_CURRENT_CONTEXT(ctx); 4507 4508 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer); 4509 invalidate_buffer_subdata(ctx, bufObj, offset, length); 4510 } 4511 4512 void GLAPIENTRY 4513 _mesa_InvalidateBufferSubData(GLuint buffer, GLintptr offset, 4514 GLsizeiptr length) 4515 { 4516 GET_CURRENT_CONTEXT(ctx); 4517 struct gl_buffer_object *bufObj; 4518 const GLintptr end = offset + length; 4519 4520 /* Section 6.5 (Invalidating Buffer Data) of the OpenGL 4.5 (Compatibility 4521 * Profile) spec says: 4522 * 4523 * "An INVALID_VALUE error is generated if buffer is zero or is not the 4524 * name of an existing buffer object." 4525 */ 4526 bufObj = _mesa_lookup_bufferobj(ctx, buffer); 4527 if (!bufObj || bufObj == &DummyBufferObject) { 4528 _mesa_error(ctx, GL_INVALID_VALUE, 4529 "glInvalidateBufferSubData(name = %u) invalid object", 4530 buffer); 4531 return; 4532 } 4533 4534 /* The GL_ARB_invalidate_subdata spec says: 4535 * 4536 * "An INVALID_VALUE error is generated if <offset> or <length> is 4537 * negative, or if <offset> + <length> is greater than the value of 4538 * BUFFER_SIZE." 4539 */ 4540 if (offset < 0 || length < 0 || end > bufObj->Size) { 4541 _mesa_error(ctx, GL_INVALID_VALUE, 4542 "glInvalidateBufferSubData(invalid offset or length)"); 4543 return; 4544 } 4545 4546 /* The OpenGL 4.4 (Core Profile) spec says: 4547 * 4548 * "An INVALID_OPERATION error is generated if buffer is currently 4549 * mapped by MapBuffer or if the invalidate range intersects the range 4550 * currently mapped by MapBufferRange, unless it was mapped 4551 * with MAP_PERSISTENT_BIT set in the MapBufferRange access flags." 4552 */ 4553 if (!(bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_PERSISTENT_BIT) && 4554 bufferobj_range_mapped(bufObj, offset, length)) { 4555 _mesa_error(ctx, GL_INVALID_OPERATION, 4556 "glInvalidateBufferSubData(intersection with mapped " 4557 "range)"); 4558 return; 4559 } 4560 4561 invalidate_buffer_subdata(ctx, bufObj, offset, length); 4562 } 4563 4564 void GLAPIENTRY 4565 _mesa_InvalidateBufferData_no_error(GLuint buffer) 4566 { 4567 GET_CURRENT_CONTEXT(ctx); 4568 4569 struct gl_buffer_object *bufObj =_mesa_lookup_bufferobj(ctx, buffer); 4570 invalidate_buffer_subdata(ctx, bufObj, 0, bufObj->Size); 4571 } 4572 4573 void GLAPIENTRY 4574 _mesa_InvalidateBufferData(GLuint buffer) 4575 { 4576 GET_CURRENT_CONTEXT(ctx); 4577 struct gl_buffer_object *bufObj; 4578 4579 /* Section 6.5 (Invalidating Buffer Data) of the OpenGL 4.5 (Compatibility 4580 * Profile) spec says: 4581 * 4582 * "An INVALID_VALUE error is generated if buffer is zero or is not the 4583 * name of an existing buffer object." 4584 */ 4585 bufObj = _mesa_lookup_bufferobj(ctx, buffer); 4586 if (!bufObj || bufObj == &DummyBufferObject) { 4587 _mesa_error(ctx, GL_INVALID_VALUE, 4588 "glInvalidateBufferData(name = %u) invalid object", 4589 buffer); 4590 return; 4591 } 4592 4593 /* The OpenGL 4.4 (Core Profile) spec says: 4594 * 4595 * "An INVALID_OPERATION error is generated if buffer is currently 4596 * mapped by MapBuffer or if the invalidate range intersects the range 4597 * currently mapped by MapBufferRange, unless it was mapped 4598 * with MAP_PERSISTENT_BIT set in the MapBufferRange access flags." 4599 */ 4600 if (_mesa_check_disallowed_mapping(bufObj)) { 4601 _mesa_error(ctx, GL_INVALID_OPERATION, 4602 "glInvalidateBufferData(intersection with mapped " 4603 "range)"); 4604 return; 4605 } 4606 4607 invalidate_buffer_subdata(ctx, bufObj, 0, bufObj->Size); 4608 } 4609 4610 static void 4611 buffer_page_commitment(struct gl_context *ctx, 4612 struct gl_buffer_object *bufferObj, 4613 GLintptr offset, GLsizeiptr size, 4614 GLboolean commit, const char *func) 4615 { 4616 if (!(bufferObj->StorageFlags & GL_SPARSE_STORAGE_BIT_ARB)) { 4617 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(not a sparse buffer object)", 4618 func); 4619 return; 4620 } 4621 4622 if (size < 0 || size > bufferObj->Size || 4623 offset < 0 || offset > bufferObj->Size - size) { 4624 _mesa_error(ctx, GL_INVALID_VALUE, "%s(out of bounds)", 4625 func); 4626 return; 4627 } 4628 4629 /* The GL_ARB_sparse_buffer extension specification says: 4630 * 4631 * "INVALID_VALUE is generated by BufferPageCommitmentARB if <offset> is 4632 * not an integer multiple of SPARSE_BUFFER_PAGE_SIZE_ARB, or if <size> 4633 * is not an integer multiple of SPARSE_BUFFER_PAGE_SIZE_ARB and does 4634 * not extend to the end of the buffer's data store." 4635 */ 4636 if (offset % ctx->Const.SparseBufferPageSize != 0) { 4637 _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset not aligned to page size)", 4638 func); 4639 return; 4640 } 4641 4642 if (size % ctx->Const.SparseBufferPageSize != 0 && 4643 offset + size != bufferObj->Size) { 4644 _mesa_error(ctx, GL_INVALID_VALUE, "%s(size not aligned to page size)", 4645 func); 4646 return; 4647 } 4648 4649 ctx->Driver.BufferPageCommitment(ctx, bufferObj, offset, size, commit); 4650 } 4651 4652 void GLAPIENTRY 4653 _mesa_BufferPageCommitmentARB(GLenum target, GLintptr offset, GLsizeiptr size, 4654 GLboolean commit) 4655 { 4656 GET_CURRENT_CONTEXT(ctx); 4657 struct gl_buffer_object *bufferObj; 4658 4659 bufferObj = get_buffer(ctx, "glBufferPageCommitmentARB", target, 4660 GL_INVALID_ENUM); 4661 if (!bufferObj) 4662 return; 4663 4664 buffer_page_commitment(ctx, bufferObj, offset, size, commit, 4665 "glBufferPageCommitmentARB"); 4666 } 4667 4668 void GLAPIENTRY 4669 _mesa_NamedBufferPageCommitmentARB(GLuint buffer, GLintptr offset, 4670 GLsizeiptr size, GLboolean commit) 4671 { 4672 GET_CURRENT_CONTEXT(ctx); 4673 struct gl_buffer_object *bufferObj; 4674 4675 bufferObj = _mesa_lookup_bufferobj(ctx, buffer); 4676 if (!bufferObj || bufferObj == &DummyBufferObject) { 4677 /* Note: the extension spec is not clear about the excpected error value. */ 4678 _mesa_error(ctx, GL_INVALID_VALUE, 4679 "glNamedBufferPageCommitmentARB(name = %u) invalid object", 4680 buffer); 4681 return; 4682 } 4683 4684 buffer_page_commitment(ctx, bufferObj, offset, size, commit, 4685 "glNamedBufferPageCommitmentARB"); 4686 } 4687