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