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