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