bufferobj.c revision 848b8605
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 "glheader.h" 36#include "enums.h" 37#include "hash.h" 38#include "imports.h" 39#include "image.h" 40#include "context.h" 41#include "bufferobj.h" 42#include "fbobject.h" 43#include "mtypes.h" 44#include "texobj.h" 45#include "teximage.h" 46#include "glformats.h" 47#include "texstore.h" 48#include "transformfeedback.h" 49#include "dispatch.h" 50 51 52/* Debug flags */ 53/*#define VBO_DEBUG*/ 54/*#define BOUNDS_CHECK*/ 55 56 57/** 58 * Used as a placeholder for buffer objects between glGenBuffers() and 59 * glBindBuffer() so that glIsBuffer() can work correctly. 60 */ 61static struct gl_buffer_object DummyBufferObject; 62 63 64/** 65 * Return pointer to address of a buffer object target. 66 * \param ctx the GL context 67 * \param target the buffer object target to be retrieved. 68 * \return pointer to pointer to the buffer object bound to \c target in the 69 * specified context or \c NULL if \c target is invalid. 70 */ 71static inline struct gl_buffer_object ** 72get_buffer_target(struct gl_context *ctx, GLenum target) 73{ 74 /* Other targets are only supported in desktop OpenGL and OpenGL ES 3.0. 75 */ 76 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx) 77 && target != GL_ARRAY_BUFFER && target != GL_ELEMENT_ARRAY_BUFFER) 78 return NULL; 79 80 switch (target) { 81 case GL_ARRAY_BUFFER_ARB: 82 return &ctx->Array.ArrayBufferObj; 83 case GL_ELEMENT_ARRAY_BUFFER_ARB: 84 return &ctx->Array.VAO->IndexBufferObj; 85 case GL_PIXEL_PACK_BUFFER_EXT: 86 return &ctx->Pack.BufferObj; 87 case GL_PIXEL_UNPACK_BUFFER_EXT: 88 return &ctx->Unpack.BufferObj; 89 case GL_COPY_READ_BUFFER: 90 return &ctx->CopyReadBuffer; 91 case GL_COPY_WRITE_BUFFER: 92 return &ctx->CopyWriteBuffer; 93 case GL_DRAW_INDIRECT_BUFFER: 94 if (ctx->API == API_OPENGL_CORE && 95 ctx->Extensions.ARB_draw_indirect) { 96 return &ctx->DrawIndirectBuffer; 97 } 98 break; 99 case GL_TRANSFORM_FEEDBACK_BUFFER: 100 if (ctx->Extensions.EXT_transform_feedback) { 101 return &ctx->TransformFeedback.CurrentBuffer; 102 } 103 break; 104 case GL_TEXTURE_BUFFER: 105 if (ctx->API == API_OPENGL_CORE && 106 ctx->Extensions.ARB_texture_buffer_object) { 107 return &ctx->Texture.BufferObject; 108 } 109 break; 110 case GL_UNIFORM_BUFFER: 111 if (ctx->Extensions.ARB_uniform_buffer_object) { 112 return &ctx->UniformBuffer; 113 } 114 break; 115 case GL_ATOMIC_COUNTER_BUFFER: 116 if (ctx->Extensions.ARB_shader_atomic_counters) { 117 return &ctx->AtomicBuffer; 118 } 119 break; 120 default: 121 return NULL; 122 } 123 return NULL; 124} 125 126 127/** 128 * Get the buffer object bound to the specified target in a GL context. 129 * \param ctx the GL context 130 * \param target the buffer object target to be retrieved. 131 * \param error the GL error to record if target is illegal. 132 * \return pointer to the buffer object bound to \c target in the 133 * specified context or \c NULL if \c target is invalid. 134 */ 135static inline struct gl_buffer_object * 136get_buffer(struct gl_context *ctx, const char *func, GLenum target, 137 GLenum error) 138{ 139 struct gl_buffer_object **bufObj = get_buffer_target(ctx, target); 140 141 if (!bufObj) { 142 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func); 143 return NULL; 144 } 145 146 if (!_mesa_is_bufferobj(*bufObj)) { 147 _mesa_error(ctx, error, "%s(no buffer bound)", func); 148 return NULL; 149 } 150 151 return *bufObj; 152} 153 154 155/** 156 * Convert a GLbitfield describing the mapped buffer access flags 157 * into one of GL_READ_WRITE, GL_READ_ONLY, or GL_WRITE_ONLY. 158 */ 159static GLenum 160simplified_access_mode(struct gl_context *ctx, GLbitfield access) 161{ 162 const GLbitfield rwFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT; 163 if ((access & rwFlags) == rwFlags) 164 return GL_READ_WRITE; 165 if ((access & GL_MAP_READ_BIT) == GL_MAP_READ_BIT) 166 return GL_READ_ONLY; 167 if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT) 168 return GL_WRITE_ONLY; 169 170 /* Otherwise, AccessFlags is zero (the default state). 171 * 172 * Table 2.6 on page 31 (page 44 of the PDF) of the OpenGL 1.5 spec says: 173 * 174 * Name Type Initial Value Legal Values 175 * ... ... ... ... 176 * BUFFER_ACCESS enum READ_WRITE READ_ONLY, WRITE_ONLY 177 * READ_WRITE 178 * 179 * However, table 6.8 in the GL_OES_mapbuffer extension says: 180 * 181 * Get Value Type Get Command Value Description 182 * --------- ---- ----------- ----- ----------- 183 * BUFFER_ACCESS_OES Z1 GetBufferParameteriv WRITE_ONLY_OES buffer map flag 184 * 185 * The difference is because GL_OES_mapbuffer only supports mapping buffers 186 * write-only. 187 */ 188 assert(access == 0); 189 190 return _mesa_is_gles(ctx) ? GL_WRITE_ONLY : GL_READ_WRITE; 191} 192 193 194/** 195 * Test if the buffer is mapped, and if so, if the mapped range overlaps the 196 * given range. 197 * The regions do not overlap if and only if the end of the given 198 * region is before the mapped region or the start of the given region 199 * is after the mapped region. 200 * 201 * \param obj Buffer object target on which to operate. 202 * \param offset Offset of the first byte of the subdata range. 203 * \param size Size, in bytes, of the subdata range. 204 * \return true if ranges overlap, false otherwise 205 * 206 */ 207static bool 208bufferobj_range_mapped(const struct gl_buffer_object *obj, 209 GLintptr offset, GLsizeiptr size) 210{ 211 if (_mesa_bufferobj_mapped(obj, MAP_USER)) { 212 const GLintptr end = offset + size; 213 const GLintptr mapEnd = obj->Mappings[MAP_USER].Offset + 214 obj->Mappings[MAP_USER].Length; 215 216 if (!(end <= obj->Mappings[MAP_USER].Offset || offset >= mapEnd)) { 217 return true; 218 } 219 } 220 return false; 221} 222 223 224/** 225 * Tests the subdata range parameters and sets the GL error code for 226 * \c glBufferSubDataARB, \c glGetBufferSubDataARB and 227 * \c glClearBufferSubData. 228 * 229 * \param ctx GL context. 230 * \param target Buffer object target on which to operate. 231 * \param offset Offset of the first byte of the subdata range. 232 * \param size Size, in bytes, of the subdata range. 233 * \param mappedRange If true, checks if an overlapping range is mapped. 234 * If false, checks if buffer is mapped. 235 * \param errorNoBuffer Error code if no buffer is bound to target. 236 * \param caller Name of calling function for recording errors. 237 * \return A pointer to the buffer object bound to \c target in the 238 * specified context or \c NULL if any of the parameter or state 239 * conditions are invalid. 240 * 241 * \sa glBufferSubDataARB, glGetBufferSubDataARB, glClearBufferSubData 242 */ 243static struct gl_buffer_object * 244buffer_object_subdata_range_good(struct gl_context * ctx, GLenum target, 245 GLintptrARB offset, GLsizeiptrARB size, 246 bool mappedRange, GLenum errorNoBuffer, 247 const char *caller) 248{ 249 struct gl_buffer_object *bufObj; 250 251 if (size < 0) { 252 _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", caller); 253 return NULL; 254 } 255 256 if (offset < 0) { 257 _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset < 0)", caller); 258 return NULL; 259 } 260 261 bufObj = get_buffer(ctx, caller, target, errorNoBuffer); 262 if (!bufObj) 263 return NULL; 264 265 if (offset + size > bufObj->Size) { 266 _mesa_error(ctx, GL_INVALID_VALUE, 267 "%s(offset %lu + size %lu > buffer size %lu)", caller, 268 (unsigned long) offset, 269 (unsigned long) size, 270 (unsigned long) bufObj->Size); 271 return NULL; 272 } 273 274 if (bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_PERSISTENT_BIT) 275 return bufObj; 276 277 if (mappedRange) { 278 if (bufferobj_range_mapped(bufObj, offset, size)) { 279 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); 280 return NULL; 281 } 282 } 283 else { 284 if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) { 285 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); 286 return NULL; 287 } 288 } 289 290 return bufObj; 291} 292 293 294/** 295 * Test the format and type parameters and set the GL error code for 296 * \c glClearBufferData and \c glClearBufferSubData. 297 * 298 * \param ctx GL context. 299 * \param internalformat Format to which the data is to be converted. 300 * \param format Format of the supplied data. 301 * \param type Type of the supplied data. 302 * \param caller Name of calling function for recording errors. 303 * \return If internalformat, format and type are legal the mesa_format 304 * corresponding to internalformat, otherwise MESA_FORMAT_NONE. 305 * 306 * \sa glClearBufferData and glClearBufferSubData 307 */ 308static mesa_format 309validate_clear_buffer_format(struct gl_context *ctx, 310 GLenum internalformat, 311 GLenum format, GLenum type, 312 const char *caller) 313{ 314 mesa_format mesaFormat; 315 GLenum errorFormatType; 316 317 mesaFormat = _mesa_validate_texbuffer_format(ctx, internalformat); 318 if (mesaFormat == MESA_FORMAT_NONE) { 319 _mesa_error(ctx, GL_INVALID_ENUM, 320 "%s(invalid internalformat)", caller); 321 return MESA_FORMAT_NONE; 322 } 323 324 /* NOTE: not mentioned in ARB_clear_buffer_object but according to 325 * EXT_texture_integer there is no conversion between integer and 326 * non-integer formats 327 */ 328 if (_mesa_is_enum_format_signed_int(format) != 329 _mesa_is_format_integer_color(mesaFormat)) { 330 _mesa_error(ctx, GL_INVALID_OPERATION, 331 "%s(integer vs non-integer)", caller); 332 return MESA_FORMAT_NONE; 333 } 334 335 if (!_mesa_is_color_format(format)) { 336 _mesa_error(ctx, GL_INVALID_ENUM, 337 "%s(format is not a color format)", caller); 338 return MESA_FORMAT_NONE; 339 } 340 341 errorFormatType = _mesa_error_check_format_and_type(ctx, format, type); 342 if (errorFormatType != GL_NO_ERROR) { 343 _mesa_error(ctx, GL_INVALID_ENUM, 344 "%s(invalid format or type)", caller); 345 return MESA_FORMAT_NONE; 346 } 347 348 return mesaFormat; 349} 350 351 352/** 353 * Convert user-specified clear value to the specified internal format. 354 * 355 * \param ctx GL context. 356 * \param internalformat Format to which the data is converted. 357 * \param clearValue Points to the converted clear value. 358 * \param format Format of the supplied data. 359 * \param type Type of the supplied data. 360 * \param data Data which is to be converted to internalformat. 361 * \param caller Name of calling function for recording errors. 362 * \return true if data could be converted, false otherwise. 363 * 364 * \sa glClearBufferData, glClearBufferSubData 365 */ 366static bool 367convert_clear_buffer_data(struct gl_context *ctx, 368 mesa_format internalformat, 369 GLubyte *clearValue, GLenum format, GLenum type, 370 const GLvoid *data, const char *caller) 371{ 372 GLenum internalformatBase = _mesa_get_format_base_format(internalformat); 373 374 if (_mesa_texstore(ctx, 1, internalformatBase, internalformat, 375 0, &clearValue, 1, 1, 1, 376 format, type, data, &ctx->Unpack)) { 377 return true; 378 } 379 else { 380 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); 381 return false; 382 } 383} 384 385 386/** 387 * Allocate and initialize a new buffer object. 388 * 389 * Default callback for the \c dd_function_table::NewBufferObject() hook. 390 */ 391static struct gl_buffer_object * 392_mesa_new_buffer_object( struct gl_context *ctx, GLuint name, GLenum target ) 393{ 394 struct gl_buffer_object *obj; 395 396 (void) ctx; 397 398 obj = MALLOC_STRUCT(gl_buffer_object); 399 _mesa_initialize_buffer_object(ctx, obj, name, target); 400 return obj; 401} 402 403 404/** 405 * Delete a buffer object. 406 * 407 * Default callback for the \c dd_function_table::DeleteBuffer() hook. 408 */ 409static void 410_mesa_delete_buffer_object(struct gl_context *ctx, 411 struct gl_buffer_object *bufObj) 412{ 413 (void) ctx; 414 415 _mesa_align_free(bufObj->Data); 416 417 /* assign strange values here to help w/ debugging */ 418 bufObj->RefCount = -1000; 419 bufObj->Name = ~0; 420 421 mtx_destroy(&bufObj->Mutex); 422 free(bufObj->Label); 423 free(bufObj); 424} 425 426 427 428/** 429 * Set ptr to bufObj w/ reference counting. 430 * This is normally only called from the _mesa_reference_buffer_object() macro 431 * when there's a real pointer change. 432 */ 433void 434_mesa_reference_buffer_object_(struct gl_context *ctx, 435 struct gl_buffer_object **ptr, 436 struct gl_buffer_object *bufObj) 437{ 438 if (*ptr) { 439 /* Unreference the old buffer */ 440 GLboolean deleteFlag = GL_FALSE; 441 struct gl_buffer_object *oldObj = *ptr; 442 443 mtx_lock(&oldObj->Mutex); 444 ASSERT(oldObj->RefCount > 0); 445 oldObj->RefCount--; 446#if 0 447 printf("BufferObj %p %d DECR to %d\n", 448 (void *) oldObj, oldObj->Name, oldObj->RefCount); 449#endif 450 deleteFlag = (oldObj->RefCount == 0); 451 mtx_unlock(&oldObj->Mutex); 452 453 if (deleteFlag) { 454 455 /* some sanity checking: don't delete a buffer still in use */ 456#if 0 457 /* unfortunately, these tests are invalid during context tear-down */ 458 ASSERT(ctx->Array.ArrayBufferObj != bufObj); 459 ASSERT(ctx->Array.VAO->IndexBufferObj != bufObj); 460 ASSERT(ctx->Array.VAO->Vertex.BufferObj != bufObj); 461#endif 462 463 ASSERT(ctx->Driver.DeleteBuffer); 464 ctx->Driver.DeleteBuffer(ctx, oldObj); 465 } 466 467 *ptr = NULL; 468 } 469 ASSERT(!*ptr); 470 471 if (bufObj) { 472 /* reference new buffer */ 473 mtx_lock(&bufObj->Mutex); 474 if (bufObj->RefCount == 0) { 475 /* this buffer's being deleted (look just above) */ 476 /* Not sure this can every really happen. Warn if it does. */ 477 _mesa_problem(NULL, "referencing deleted buffer object"); 478 *ptr = NULL; 479 } 480 else { 481 bufObj->RefCount++; 482#if 0 483 printf("BufferObj %p %d INCR to %d\n", 484 (void *) bufObj, bufObj->Name, bufObj->RefCount); 485#endif 486 *ptr = bufObj; 487 } 488 mtx_unlock(&bufObj->Mutex); 489 } 490} 491 492 493/** 494 * Initialize a buffer object to default values. 495 */ 496void 497_mesa_initialize_buffer_object( struct gl_context *ctx, 498 struct gl_buffer_object *obj, 499 GLuint name, GLenum target ) 500{ 501 (void) target; 502 503 memset(obj, 0, sizeof(struct gl_buffer_object)); 504 mtx_init(&obj->Mutex, mtx_plain); 505 obj->RefCount = 1; 506 obj->Name = name; 507 obj->Usage = GL_STATIC_DRAW_ARB; 508} 509 510 511 512/** 513 * Callback called from _mesa_HashWalk() 514 */ 515static void 516count_buffer_size(GLuint key, void *data, void *userData) 517{ 518 const struct gl_buffer_object *bufObj = 519 (const struct gl_buffer_object *) data; 520 GLuint *total = (GLuint *) userData; 521 522 *total = *total + bufObj->Size; 523} 524 525 526/** 527 * Compute total size (in bytes) of all buffer objects for the given context. 528 * For debugging purposes. 529 */ 530GLuint 531_mesa_total_buffer_object_memory(struct gl_context *ctx) 532{ 533 GLuint total = 0; 534 535 _mesa_HashWalk(ctx->Shared->BufferObjects, count_buffer_size, &total); 536 537 return total; 538} 539 540 541/** 542 * Allocate space for and store data in a buffer object. Any data that was 543 * previously stored in the buffer object is lost. If \c data is \c NULL, 544 * memory will be allocated, but no copy will occur. 545 * 546 * This is the default callback for \c dd_function_table::BufferData() 547 * Note that all GL error checking will have been done already. 548 * 549 * \param ctx GL context. 550 * \param target Buffer object target on which to operate. 551 * \param size Size, in bytes, of the new data store. 552 * \param data Pointer to the data to store in the buffer object. This 553 * pointer may be \c NULL. 554 * \param usage Hints about how the data will be used. 555 * \param bufObj Object to be used. 556 * 557 * \return GL_TRUE for success, GL_FALSE for failure 558 * \sa glBufferDataARB, dd_function_table::BufferData. 559 */ 560static GLboolean 561_mesa_buffer_data( struct gl_context *ctx, GLenum target, GLsizeiptrARB size, 562 const GLvoid * data, GLenum usage, GLenum storageFlags, 563 struct gl_buffer_object * bufObj ) 564{ 565 void * new_data; 566 567 (void) target; 568 569 _mesa_align_free( bufObj->Data ); 570 571 new_data = _mesa_align_malloc( size, ctx->Const.MinMapBufferAlignment ); 572 if (new_data) { 573 bufObj->Data = (GLubyte *) new_data; 574 bufObj->Size = size; 575 bufObj->Usage = usage; 576 bufObj->StorageFlags = storageFlags; 577 578 if (data) { 579 memcpy( bufObj->Data, data, size ); 580 } 581 582 return GL_TRUE; 583 } 584 else { 585 return GL_FALSE; 586 } 587} 588 589 590/** 591 * Replace data in a subrange of buffer object. If the data range 592 * specified by \c size + \c offset extends beyond the end of the buffer or 593 * if \c data is \c NULL, no copy is performed. 594 * 595 * This is the default callback for \c dd_function_table::BufferSubData() 596 * Note that all GL error checking will have been done already. 597 * 598 * \param ctx GL context. 599 * \param offset Offset of the first byte to be modified. 600 * \param size Size, in bytes, of the data range. 601 * \param data Pointer to the data to store in the buffer object. 602 * \param bufObj Object to be used. 603 * 604 * \sa glBufferSubDataARB, dd_function_table::BufferSubData. 605 */ 606static void 607_mesa_buffer_subdata( struct gl_context *ctx, GLintptrARB offset, 608 GLsizeiptrARB size, const GLvoid * data, 609 struct gl_buffer_object * bufObj ) 610{ 611 (void) ctx; 612 613 /* this should have been caught in _mesa_BufferSubData() */ 614 ASSERT(size + offset <= bufObj->Size); 615 616 if (bufObj->Data) { 617 memcpy( (GLubyte *) bufObj->Data + offset, data, size ); 618 } 619} 620 621 622/** 623 * Retrieve data from a subrange of buffer object. If the data range 624 * specified by \c size + \c offset extends beyond the end of the buffer or 625 * if \c data is \c NULL, no copy is performed. 626 * 627 * This is the default callback for \c dd_function_table::GetBufferSubData() 628 * Note that all GL error checking will have been done already. 629 * 630 * \param ctx GL context. 631 * \param target Buffer object target on which to operate. 632 * \param offset Offset of the first byte to be fetched. 633 * \param size Size, in bytes, of the data range. 634 * \param data Destination for data 635 * \param bufObj Object to be used. 636 * 637 * \sa glBufferGetSubDataARB, dd_function_table::GetBufferSubData. 638 */ 639static void 640_mesa_buffer_get_subdata( struct gl_context *ctx, GLintptrARB offset, 641 GLsizeiptrARB size, GLvoid * data, 642 struct gl_buffer_object * bufObj ) 643{ 644 (void) ctx; 645 646 if (bufObj->Data && ((GLsizeiptrARB) (size + offset) <= bufObj->Size)) { 647 memcpy( data, (GLubyte *) bufObj->Data + offset, size ); 648 } 649} 650 651 652/** 653 * Clear a subrange of the buffer object with copies of the supplied data. 654 * If data is NULL the buffer is filled with zeros. 655 * 656 * This is the default callback for \c dd_function_table::ClearBufferSubData() 657 * Note that all GL error checking will have been done already. 658 * 659 * \param ctx GL context. 660 * \param offset Offset of the first byte to be cleared. 661 * \param size Size, in bytes, of the to be cleared range. 662 * \param clearValue Source of the data. 663 * \param clearValueSize Size, in bytes, of the supplied data. 664 * \param bufObj Object to be cleared. 665 * 666 * \sa glClearBufferSubData, glClearBufferData and 667 * dd_function_table::ClearBufferSubData. 668 */ 669void 670_mesa_buffer_clear_subdata(struct gl_context *ctx, 671 GLintptr offset, GLsizeiptr size, 672 const GLvoid *clearValue, 673 GLsizeiptr clearValueSize, 674 struct gl_buffer_object *bufObj) 675{ 676 GLsizeiptr i; 677 GLubyte *dest; 678 679 ASSERT(ctx->Driver.MapBufferRange); 680 dest = ctx->Driver.MapBufferRange(ctx, offset, size, 681 GL_MAP_WRITE_BIT | 682 GL_MAP_INVALIDATE_RANGE_BIT, 683 bufObj, MAP_INTERNAL); 684 685 if (!dest) { 686 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClearBuffer[Sub]Data"); 687 return; 688 } 689 690 if (clearValue == NULL) { 691 /* Clear with zeros, per the spec */ 692 memset(dest, 0, size); 693 ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_INTERNAL); 694 return; 695 } 696 697 for (i = 0; i < size/clearValueSize; ++i) { 698 memcpy(dest, clearValue, clearValueSize); 699 dest += clearValueSize; 700 } 701 702 ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_INTERNAL); 703} 704 705 706/** 707 * Default fallback for \c dd_function_table::MapBufferRange(). 708 * Called via glMapBufferRange(). 709 */ 710static void * 711_mesa_buffer_map_range( struct gl_context *ctx, GLintptr offset, 712 GLsizeiptr length, GLbitfield access, 713 struct gl_buffer_object *bufObj, 714 gl_map_buffer_index index) 715{ 716 (void) ctx; 717 assert(!_mesa_bufferobj_mapped(bufObj, index)); 718 /* Just return a direct pointer to the data */ 719 bufObj->Mappings[index].Pointer = bufObj->Data + offset; 720 bufObj->Mappings[index].Length = length; 721 bufObj->Mappings[index].Offset = offset; 722 bufObj->Mappings[index].AccessFlags = access; 723 return bufObj->Mappings[index].Pointer; 724} 725 726 727/** 728 * Default fallback for \c dd_function_table::FlushMappedBufferRange(). 729 * Called via glFlushMappedBufferRange(). 730 */ 731static void 732_mesa_buffer_flush_mapped_range( struct gl_context *ctx, 733 GLintptr offset, GLsizeiptr length, 734 struct gl_buffer_object *obj, 735 gl_map_buffer_index index) 736{ 737 (void) ctx; 738 (void) offset; 739 (void) length; 740 (void) obj; 741 /* no-op */ 742} 743 744 745/** 746 * Default callback for \c dd_function_table::MapBuffer(). 747 * 748 * The input parameters will have been already tested for errors. 749 * 750 * \sa glUnmapBufferARB, dd_function_table::UnmapBuffer 751 */ 752static GLboolean 753_mesa_buffer_unmap(struct gl_context *ctx, struct gl_buffer_object *bufObj, 754 gl_map_buffer_index index) 755{ 756 (void) ctx; 757 /* XXX we might assert here that bufObj->Pointer is non-null */ 758 bufObj->Mappings[index].Pointer = NULL; 759 bufObj->Mappings[index].Length = 0; 760 bufObj->Mappings[index].Offset = 0; 761 bufObj->Mappings[index].AccessFlags = 0x0; 762 return GL_TRUE; 763} 764 765 766/** 767 * Default fallback for \c dd_function_table::CopyBufferSubData(). 768 * Called via glCopyBufferSubData(). 769 */ 770static void 771_mesa_copy_buffer_subdata(struct gl_context *ctx, 772 struct gl_buffer_object *src, 773 struct gl_buffer_object *dst, 774 GLintptr readOffset, GLintptr writeOffset, 775 GLsizeiptr size) 776{ 777 GLubyte *srcPtr, *dstPtr; 778 779 if (src == dst) { 780 srcPtr = dstPtr = ctx->Driver.MapBufferRange(ctx, 0, src->Size, 781 GL_MAP_READ_BIT | 782 GL_MAP_WRITE_BIT, src, 783 MAP_INTERNAL); 784 785 if (!srcPtr) 786 return; 787 788 srcPtr += readOffset; 789 dstPtr += writeOffset; 790 } else { 791 srcPtr = ctx->Driver.MapBufferRange(ctx, readOffset, size, 792 GL_MAP_READ_BIT, src, 793 MAP_INTERNAL); 794 dstPtr = ctx->Driver.MapBufferRange(ctx, writeOffset, size, 795 (GL_MAP_WRITE_BIT | 796 GL_MAP_INVALIDATE_RANGE_BIT), dst, 797 MAP_INTERNAL); 798 } 799 800 /* Note: the src and dst regions will never overlap. Trying to do so 801 * would generate GL_INVALID_VALUE earlier. 802 */ 803 if (srcPtr && dstPtr) 804 memcpy(dstPtr, srcPtr, size); 805 806 ctx->Driver.UnmapBuffer(ctx, src, MAP_INTERNAL); 807 if (dst != src) 808 ctx->Driver.UnmapBuffer(ctx, dst, MAP_INTERNAL); 809} 810 811 812 813/** 814 * Initialize the state associated with buffer objects 815 */ 816void 817_mesa_init_buffer_objects( struct gl_context *ctx ) 818{ 819 GLuint i; 820 821 memset(&DummyBufferObject, 0, sizeof(DummyBufferObject)); 822 mtx_init(&DummyBufferObject.Mutex, mtx_plain); 823 DummyBufferObject.RefCount = 1000*1000*1000; /* never delete */ 824 825 _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, 826 ctx->Shared->NullBufferObj); 827 828 _mesa_reference_buffer_object(ctx, &ctx->CopyReadBuffer, 829 ctx->Shared->NullBufferObj); 830 _mesa_reference_buffer_object(ctx, &ctx->CopyWriteBuffer, 831 ctx->Shared->NullBufferObj); 832 833 _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, 834 ctx->Shared->NullBufferObj); 835 836 _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, 837 ctx->Shared->NullBufferObj); 838 839 _mesa_reference_buffer_object(ctx, &ctx->DrawIndirectBuffer, 840 ctx->Shared->NullBufferObj); 841 842 for (i = 0; i < MAX_COMBINED_UNIFORM_BUFFERS; i++) { 843 _mesa_reference_buffer_object(ctx, 844 &ctx->UniformBufferBindings[i].BufferObject, 845 ctx->Shared->NullBufferObj); 846 ctx->UniformBufferBindings[i].Offset = -1; 847 ctx->UniformBufferBindings[i].Size = -1; 848 } 849 850 for (i = 0; i < MAX_COMBINED_ATOMIC_BUFFERS; i++) { 851 _mesa_reference_buffer_object(ctx, 852 &ctx->AtomicBufferBindings[i].BufferObject, 853 ctx->Shared->NullBufferObj); 854 ctx->AtomicBufferBindings[i].Offset = -1; 855 ctx->AtomicBufferBindings[i].Size = -1; 856 } 857} 858 859 860void 861_mesa_free_buffer_objects( struct gl_context *ctx ) 862{ 863 GLuint i; 864 865 _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, NULL); 866 867 _mesa_reference_buffer_object(ctx, &ctx->CopyReadBuffer, NULL); 868 _mesa_reference_buffer_object(ctx, &ctx->CopyWriteBuffer, NULL); 869 870 _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, NULL); 871 872 _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, NULL); 873 874 _mesa_reference_buffer_object(ctx, &ctx->DrawIndirectBuffer, NULL); 875 876 for (i = 0; i < MAX_COMBINED_UNIFORM_BUFFERS; i++) { 877 _mesa_reference_buffer_object(ctx, 878 &ctx->UniformBufferBindings[i].BufferObject, 879 NULL); 880 } 881 882 for (i = 0; i < MAX_COMBINED_ATOMIC_BUFFERS; i++) { 883 _mesa_reference_buffer_object(ctx, 884 &ctx->AtomicBufferBindings[i].BufferObject, 885 NULL); 886 } 887 888} 889 890bool 891_mesa_handle_bind_buffer_gen(struct gl_context *ctx, 892 GLenum target, 893 GLuint buffer, 894 struct gl_buffer_object **buf_handle, 895 const char *caller) 896{ 897 struct gl_buffer_object *buf = *buf_handle; 898 899 if (!buf && ctx->API == API_OPENGL_CORE) { 900 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-gen name)", caller); 901 return false; 902 } 903 904 if (!buf || buf == &DummyBufferObject) { 905 /* If this is a new buffer object id, or one which was generated but 906 * never used before, allocate a buffer object now. 907 */ 908 ASSERT(ctx->Driver.NewBufferObject); 909 buf = ctx->Driver.NewBufferObject(ctx, buffer, target); 910 if (!buf) { 911 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); 912 return false; 913 } 914 _mesa_HashInsert(ctx->Shared->BufferObjects, buffer, buf); 915 *buf_handle = buf; 916 } 917 918 return true; 919} 920 921/** 922 * Bind the specified target to buffer for the specified context. 923 * Called by glBindBuffer() and other functions. 924 */ 925static void 926bind_buffer_object(struct gl_context *ctx, GLenum target, GLuint buffer) 927{ 928 struct gl_buffer_object *oldBufObj; 929 struct gl_buffer_object *newBufObj = NULL; 930 struct gl_buffer_object **bindTarget = NULL; 931 932 bindTarget = get_buffer_target(ctx, target); 933 if (!bindTarget) { 934 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target 0x%x)", target); 935 return; 936 } 937 938 /* Get pointer to old buffer object (to be unbound) */ 939 oldBufObj = *bindTarget; 940 if (oldBufObj && oldBufObj->Name == buffer && !oldBufObj->DeletePending) 941 return; /* rebinding the same buffer object- no change */ 942 943 /* 944 * Get pointer to new buffer object (newBufObj) 945 */ 946 if (buffer == 0) { 947 /* The spec says there's not a buffer object named 0, but we use 948 * one internally because it simplifies things. 949 */ 950 newBufObj = ctx->Shared->NullBufferObj; 951 } 952 else { 953 /* non-default buffer object */ 954 newBufObj = _mesa_lookup_bufferobj(ctx, buffer); 955 if (!_mesa_handle_bind_buffer_gen(ctx, target, buffer, 956 &newBufObj, "glBindBuffer")) 957 return; 958 } 959 960 /* bind new buffer */ 961 _mesa_reference_buffer_object(ctx, bindTarget, newBufObj); 962} 963 964 965/** 966 * Update the default buffer objects in the given context to reference those 967 * specified in the shared state and release those referencing the old 968 * shared state. 969 */ 970void 971_mesa_update_default_objects_buffer_objects(struct gl_context *ctx) 972{ 973 /* Bind the NullBufferObj to remove references to those 974 * in the shared context hash table. 975 */ 976 bind_buffer_object( ctx, GL_ARRAY_BUFFER_ARB, 0); 977 bind_buffer_object( ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, 0); 978 bind_buffer_object( ctx, GL_PIXEL_PACK_BUFFER_ARB, 0); 979 bind_buffer_object( ctx, GL_PIXEL_UNPACK_BUFFER_ARB, 0); 980} 981 982 983 984/** 985 * Return the gl_buffer_object for the given ID. 986 * Always return NULL for ID 0. 987 */ 988struct gl_buffer_object * 989_mesa_lookup_bufferobj(struct gl_context *ctx, GLuint buffer) 990{ 991 if (buffer == 0) 992 return NULL; 993 else 994 return (struct gl_buffer_object *) 995 _mesa_HashLookup(ctx->Shared->BufferObjects, buffer); 996} 997 998 999struct gl_buffer_object * 1000_mesa_lookup_bufferobj_locked(struct gl_context *ctx, GLuint buffer) 1001{ 1002 return (struct gl_buffer_object *) 1003 _mesa_HashLookupLocked(ctx->Shared->BufferObjects, buffer); 1004} 1005 1006 1007void 1008_mesa_begin_bufferobj_lookups(struct gl_context *ctx) 1009{ 1010 _mesa_HashLockMutex(ctx->Shared->BufferObjects); 1011} 1012 1013 1014void 1015_mesa_end_bufferobj_lookups(struct gl_context *ctx) 1016{ 1017 _mesa_HashUnlockMutex(ctx->Shared->BufferObjects); 1018} 1019 1020 1021/** 1022 * Look up a buffer object for a multi-bind function. 1023 * 1024 * Unlike _mesa_lookup_bufferobj(), this function also takes care 1025 * of generating an error if the buffer ID is not zero or the name 1026 * of an existing buffer object. 1027 * 1028 * If the buffer ID refers to an existing buffer object, a pointer 1029 * to the buffer object is returned. If the ID is zero, a pointer 1030 * to the shared NullBufferObj is returned. If the ID is not zero 1031 * and does not refer to a valid buffer object, this function 1032 * returns NULL. 1033 * 1034 * This function assumes that the caller has already locked the 1035 * hash table mutex by calling _mesa_begin_bufferobj_lookups(). 1036 */ 1037struct gl_buffer_object * 1038_mesa_multi_bind_lookup_bufferobj(struct gl_context *ctx, 1039 const GLuint *buffers, 1040 GLuint index, const char *caller) 1041{ 1042 struct gl_buffer_object *bufObj; 1043 1044 if (buffers[index] != 0) { 1045 bufObj = _mesa_lookup_bufferobj_locked(ctx, buffers[index]); 1046 1047 /* The multi-bind functions don't create the buffer objects 1048 when they don't exist. */ 1049 if (bufObj == &DummyBufferObject) 1050 bufObj = NULL; 1051 } else 1052 bufObj = ctx->Shared->NullBufferObj; 1053 1054 if (!bufObj) { 1055 /* The ARB_multi_bind spec says: 1056 * 1057 * "An INVALID_OPERATION error is generated if any value 1058 * in <buffers> is not zero or the name of an existing 1059 * buffer object (per binding)." 1060 */ 1061 _mesa_error(ctx, GL_INVALID_OPERATION, 1062 "%s(buffers[%u]=%u is not zero or the name " 1063 "of an existing buffer object)", 1064 caller, index, buffers[index]); 1065 } 1066 1067 return bufObj; 1068} 1069 1070 1071/** 1072 * If *ptr points to obj, set ptr = the Null/default buffer object. 1073 * This is a helper for buffer object deletion. 1074 * The GL spec says that deleting a buffer object causes it to get 1075 * unbound from all arrays in the current context. 1076 */ 1077static void 1078unbind(struct gl_context *ctx, 1079 struct gl_buffer_object **ptr, 1080 struct gl_buffer_object *obj) 1081{ 1082 if (*ptr == obj) { 1083 _mesa_reference_buffer_object(ctx, ptr, ctx->Shared->NullBufferObj); 1084 } 1085} 1086 1087 1088/** 1089 * Plug default/fallback buffer object functions into the device 1090 * driver hooks. 1091 */ 1092void 1093_mesa_init_buffer_object_functions(struct dd_function_table *driver) 1094{ 1095 /* GL_ARB_vertex/pixel_buffer_object */ 1096 driver->NewBufferObject = _mesa_new_buffer_object; 1097 driver->DeleteBuffer = _mesa_delete_buffer_object; 1098 driver->BufferData = _mesa_buffer_data; 1099 driver->BufferSubData = _mesa_buffer_subdata; 1100 driver->GetBufferSubData = _mesa_buffer_get_subdata; 1101 driver->UnmapBuffer = _mesa_buffer_unmap; 1102 1103 /* GL_ARB_clear_buffer_object */ 1104 driver->ClearBufferSubData = _mesa_buffer_clear_subdata; 1105 1106 /* GL_ARB_map_buffer_range */ 1107 driver->MapBufferRange = _mesa_buffer_map_range; 1108 driver->FlushMappedBufferRange = _mesa_buffer_flush_mapped_range; 1109 1110 /* GL_ARB_copy_buffer */ 1111 driver->CopyBufferSubData = _mesa_copy_buffer_subdata; 1112} 1113 1114 1115void 1116_mesa_buffer_unmap_all_mappings(struct gl_context *ctx, 1117 struct gl_buffer_object *bufObj) 1118{ 1119 int i; 1120 1121 for (i = 0; i < MAP_COUNT; i++) { 1122 if (_mesa_bufferobj_mapped(bufObj, i)) { 1123 ctx->Driver.UnmapBuffer(ctx, bufObj, i); 1124 ASSERT(bufObj->Mappings[i].Pointer == NULL); 1125 bufObj->Mappings[i].AccessFlags = 0; 1126 } 1127 } 1128} 1129 1130 1131/**********************************************************************/ 1132/* API Functions */ 1133/**********************************************************************/ 1134 1135void GLAPIENTRY 1136_mesa_BindBuffer(GLenum target, GLuint buffer) 1137{ 1138 GET_CURRENT_CONTEXT(ctx); 1139 1140 if (MESA_VERBOSE & VERBOSE_API) 1141 _mesa_debug(ctx, "glBindBuffer(%s, %u)\n", 1142 _mesa_lookup_enum_by_nr(target), buffer); 1143 1144 bind_buffer_object(ctx, target, buffer); 1145} 1146 1147 1148/** 1149 * Delete a set of buffer objects. 1150 * 1151 * \param n Number of buffer objects to delete. 1152 * \param ids Array of \c n buffer object IDs. 1153 */ 1154void GLAPIENTRY 1155_mesa_DeleteBuffers(GLsizei n, const GLuint *ids) 1156{ 1157 GET_CURRENT_CONTEXT(ctx); 1158 GLsizei i; 1159 FLUSH_VERTICES(ctx, 0); 1160 1161 if (n < 0) { 1162 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteBuffersARB(n)"); 1163 return; 1164 } 1165 1166 mtx_lock(&ctx->Shared->Mutex); 1167 1168 for (i = 0; i < n; i++) { 1169 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, ids[i]); 1170 if (bufObj) { 1171 struct gl_vertex_array_object *vao = ctx->Array.VAO; 1172 GLuint j; 1173 1174 ASSERT(bufObj->Name == ids[i] || bufObj == &DummyBufferObject); 1175 1176 _mesa_buffer_unmap_all_mappings(ctx, bufObj); 1177 1178 /* unbind any vertex pointers bound to this buffer */ 1179 for (j = 0; j < Elements(vao->VertexBinding); j++) { 1180 unbind(ctx, &vao->VertexBinding[j].BufferObj, bufObj); 1181 } 1182 1183 if (ctx->Array.ArrayBufferObj == bufObj) { 1184 _mesa_BindBuffer( GL_ARRAY_BUFFER_ARB, 0 ); 1185 } 1186 if (vao->IndexBufferObj == bufObj) { 1187 _mesa_BindBuffer( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 ); 1188 } 1189 1190 /* unbind ARB_draw_indirect binding point */ 1191 if (ctx->DrawIndirectBuffer == bufObj) { 1192 _mesa_BindBuffer( GL_DRAW_INDIRECT_BUFFER, 0 ); 1193 } 1194 1195 /* unbind ARB_copy_buffer binding points */ 1196 if (ctx->CopyReadBuffer == bufObj) { 1197 _mesa_BindBuffer( GL_COPY_READ_BUFFER, 0 ); 1198 } 1199 if (ctx->CopyWriteBuffer == bufObj) { 1200 _mesa_BindBuffer( GL_COPY_WRITE_BUFFER, 0 ); 1201 } 1202 1203 /* unbind transform feedback binding points */ 1204 if (ctx->TransformFeedback.CurrentBuffer == bufObj) { 1205 _mesa_BindBuffer( GL_TRANSFORM_FEEDBACK_BUFFER, 0 ); 1206 } 1207 for (j = 0; j < MAX_FEEDBACK_BUFFERS; j++) { 1208 if (ctx->TransformFeedback.CurrentObject->Buffers[j] == bufObj) { 1209 _mesa_BindBufferBase( GL_TRANSFORM_FEEDBACK_BUFFER, j, 0 ); 1210 } 1211 } 1212 1213 /* unbind UBO binding points */ 1214 for (j = 0; j < ctx->Const.MaxUniformBufferBindings; j++) { 1215 if (ctx->UniformBufferBindings[j].BufferObject == bufObj) { 1216 _mesa_BindBufferBase( GL_UNIFORM_BUFFER, j, 0 ); 1217 } 1218 } 1219 1220 if (ctx->UniformBuffer == bufObj) { 1221 _mesa_BindBuffer( GL_UNIFORM_BUFFER, 0 ); 1222 } 1223 1224 /* unbind Atomci Buffer binding points */ 1225 for (j = 0; j < ctx->Const.MaxAtomicBufferBindings; j++) { 1226 if (ctx->AtomicBufferBindings[j].BufferObject == bufObj) { 1227 _mesa_BindBufferBase( GL_ATOMIC_COUNTER_BUFFER, j, 0 ); 1228 } 1229 } 1230 1231 if (ctx->UniformBuffer == bufObj) { 1232 _mesa_BindBuffer( GL_ATOMIC_COUNTER_BUFFER, 0 ); 1233 } 1234 1235 /* unbind any pixel pack/unpack pointers bound to this buffer */ 1236 if (ctx->Pack.BufferObj == bufObj) { 1237 _mesa_BindBuffer( GL_PIXEL_PACK_BUFFER_EXT, 0 ); 1238 } 1239 if (ctx->Unpack.BufferObj == bufObj) { 1240 _mesa_BindBuffer( GL_PIXEL_UNPACK_BUFFER_EXT, 0 ); 1241 } 1242 1243 if (ctx->Texture.BufferObject == bufObj) { 1244 _mesa_BindBuffer( GL_TEXTURE_BUFFER, 0 ); 1245 } 1246 1247 /* The ID is immediately freed for re-use */ 1248 _mesa_HashRemove(ctx->Shared->BufferObjects, ids[i]); 1249 /* Make sure we do not run into the classic ABA problem on bind. 1250 * We don't want to allow re-binding a buffer object that's been 1251 * "deleted" by glDeleteBuffers(). 1252 * 1253 * The explicit rebinding to the default object in the current context 1254 * prevents the above in the current context, but another context 1255 * sharing the same objects might suffer from this problem. 1256 * The alternative would be to do the hash lookup in any case on bind 1257 * which would introduce more runtime overhead than this. 1258 */ 1259 bufObj->DeletePending = GL_TRUE; 1260 _mesa_reference_buffer_object(ctx, &bufObj, NULL); 1261 } 1262 } 1263 1264 mtx_unlock(&ctx->Shared->Mutex); 1265} 1266 1267 1268/** 1269 * Generate a set of unique buffer object IDs and store them in \c buffer. 1270 * 1271 * \param n Number of IDs to generate. 1272 * \param buffer Array of \c n locations to store the IDs. 1273 */ 1274void GLAPIENTRY 1275_mesa_GenBuffers(GLsizei n, GLuint *buffer) 1276{ 1277 GET_CURRENT_CONTEXT(ctx); 1278 GLuint first; 1279 GLint i; 1280 1281 if (MESA_VERBOSE & VERBOSE_API) 1282 _mesa_debug(ctx, "glGenBuffers(%d)\n", n); 1283 1284 if (n < 0) { 1285 _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB"); 1286 return; 1287 } 1288 1289 if (!buffer) { 1290 return; 1291 } 1292 1293 /* 1294 * This must be atomic (generation and allocation of buffer object IDs) 1295 */ 1296 mtx_lock(&ctx->Shared->Mutex); 1297 1298 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n); 1299 1300 /* Insert the ID and pointer to dummy buffer object into hash table */ 1301 for (i = 0; i < n; i++) { 1302 _mesa_HashInsert(ctx->Shared->BufferObjects, first + i, 1303 &DummyBufferObject); 1304 buffer[i] = first + i; 1305 } 1306 1307 mtx_unlock(&ctx->Shared->Mutex); 1308} 1309 1310 1311/** 1312 * Determine if ID is the name of a buffer object. 1313 * 1314 * \param id ID of the potential buffer object. 1315 * \return \c GL_TRUE if \c id is the name of a buffer object, 1316 * \c GL_FALSE otherwise. 1317 */ 1318GLboolean GLAPIENTRY 1319_mesa_IsBuffer(GLuint id) 1320{ 1321 struct gl_buffer_object *bufObj; 1322 GET_CURRENT_CONTEXT(ctx); 1323 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 1324 1325 mtx_lock(&ctx->Shared->Mutex); 1326 bufObj = _mesa_lookup_bufferobj(ctx, id); 1327 mtx_unlock(&ctx->Shared->Mutex); 1328 1329 return bufObj && bufObj != &DummyBufferObject; 1330} 1331 1332 1333void GLAPIENTRY 1334_mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data, 1335 GLbitfield flags) 1336{ 1337 GET_CURRENT_CONTEXT(ctx); 1338 struct gl_buffer_object *bufObj; 1339 1340 if (size <= 0) { 1341 _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(size <= 0)"); 1342 return; 1343 } 1344 1345 if (flags & ~(GL_MAP_READ_BIT | 1346 GL_MAP_WRITE_BIT | 1347 GL_MAP_PERSISTENT_BIT | 1348 GL_MAP_COHERENT_BIT | 1349 GL_DYNAMIC_STORAGE_BIT | 1350 GL_CLIENT_STORAGE_BIT)) { 1351 _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(flags)"); 1352 return; 1353 } 1354 1355 if (flags & GL_MAP_PERSISTENT_BIT && 1356 !(flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT))) { 1357 _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(flags!=READ/WRITE)"); 1358 return; 1359 } 1360 1361 if (flags & GL_MAP_COHERENT_BIT && !(flags & GL_MAP_PERSISTENT_BIT)) { 1362 _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(flags!=PERSISTENT)"); 1363 return; 1364 } 1365 1366 bufObj = get_buffer(ctx, "glBufferStorage", target, GL_INVALID_OPERATION); 1367 if (!bufObj) 1368 return; 1369 1370 if (bufObj->Immutable) { 1371 _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferStorage(immutable)"); 1372 return; 1373 } 1374 1375 /* Unmap the existing buffer. We'll replace it now. Not an error. */ 1376 _mesa_buffer_unmap_all_mappings(ctx, bufObj); 1377 1378 FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT); 1379 1380 bufObj->Written = GL_TRUE; 1381 bufObj->Immutable = GL_TRUE; 1382 1383 ASSERT(ctx->Driver.BufferData); 1384 if (!ctx->Driver.BufferData(ctx, target, size, data, GL_DYNAMIC_DRAW, 1385 flags, bufObj)) { 1386 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferStorage()"); 1387 } 1388} 1389 1390 1391void GLAPIENTRY 1392_mesa_BufferData(GLenum target, GLsizeiptrARB size, 1393 const GLvoid * data, GLenum usage) 1394{ 1395 GET_CURRENT_CONTEXT(ctx); 1396 struct gl_buffer_object *bufObj; 1397 bool valid_usage; 1398 1399 if (MESA_VERBOSE & VERBOSE_API) 1400 _mesa_debug(ctx, "glBufferData(%s, %ld, %p, %s)\n", 1401 _mesa_lookup_enum_by_nr(target), 1402 (long int) size, data, 1403 _mesa_lookup_enum_by_nr(usage)); 1404 1405 if (size < 0) { 1406 _mesa_error(ctx, GL_INVALID_VALUE, "glBufferDataARB(size < 0)"); 1407 return; 1408 } 1409 1410 switch (usage) { 1411 case GL_STREAM_DRAW_ARB: 1412 valid_usage = (ctx->API != API_OPENGLES); 1413 break; 1414 1415 case GL_STATIC_DRAW_ARB: 1416 case GL_DYNAMIC_DRAW_ARB: 1417 valid_usage = true; 1418 break; 1419 1420 case GL_STREAM_READ_ARB: 1421 case GL_STREAM_COPY_ARB: 1422 case GL_STATIC_READ_ARB: 1423 case GL_STATIC_COPY_ARB: 1424 case GL_DYNAMIC_READ_ARB: 1425 case GL_DYNAMIC_COPY_ARB: 1426 valid_usage = _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx); 1427 break; 1428 1429 default: 1430 valid_usage = false; 1431 break; 1432 } 1433 1434 if (!valid_usage) { 1435 _mesa_error(ctx, GL_INVALID_ENUM, "glBufferData(usage)"); 1436 return; 1437 } 1438 1439 bufObj = get_buffer(ctx, "glBufferDataARB", target, GL_INVALID_OPERATION); 1440 if (!bufObj) 1441 return; 1442 1443 if (bufObj->Immutable) { 1444 _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferData(immutable)"); 1445 return; 1446 } 1447 1448 /* Unmap the existing buffer. We'll replace it now. Not an error. */ 1449 _mesa_buffer_unmap_all_mappings(ctx, bufObj); 1450 1451 FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT); 1452 1453 bufObj->Written = GL_TRUE; 1454 1455#ifdef VBO_DEBUG 1456 printf("glBufferDataARB(%u, sz %ld, from %p, usage 0x%x)\n", 1457 bufObj->Name, size, data, usage); 1458#endif 1459 1460#ifdef BOUNDS_CHECK 1461 size += 100; 1462#endif 1463 1464 ASSERT(ctx->Driver.BufferData); 1465 if (!ctx->Driver.BufferData(ctx, target, size, data, usage, 1466 GL_MAP_READ_BIT | 1467 GL_MAP_WRITE_BIT | 1468 GL_DYNAMIC_STORAGE_BIT, 1469 bufObj)) { 1470 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferDataARB()"); 1471 } 1472} 1473 1474 1475void GLAPIENTRY 1476_mesa_BufferSubData(GLenum target, GLintptrARB offset, 1477 GLsizeiptrARB size, const GLvoid * data) 1478{ 1479 GET_CURRENT_CONTEXT(ctx); 1480 struct gl_buffer_object *bufObj; 1481 1482 bufObj = buffer_object_subdata_range_good( ctx, target, offset, size, 1483 false, GL_INVALID_OPERATION, 1484 "glBufferSubDataARB" ); 1485 if (!bufObj) { 1486 /* error already recorded */ 1487 return; 1488 } 1489 1490 if (bufObj->Immutable && 1491 !(bufObj->StorageFlags & GL_DYNAMIC_STORAGE_BIT)) { 1492 _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferSubData"); 1493 return; 1494 } 1495 1496 if (size == 0) 1497 return; 1498 1499 bufObj->Written = GL_TRUE; 1500 1501 ASSERT(ctx->Driver.BufferSubData); 1502 ctx->Driver.BufferSubData( ctx, offset, size, data, bufObj ); 1503} 1504 1505 1506void GLAPIENTRY 1507_mesa_GetBufferSubData(GLenum target, GLintptrARB offset, 1508 GLsizeiptrARB size, void * data) 1509{ 1510 GET_CURRENT_CONTEXT(ctx); 1511 struct gl_buffer_object *bufObj; 1512 1513 bufObj = buffer_object_subdata_range_good(ctx, target, offset, size, 1514 false, GL_INVALID_OPERATION, 1515 "glGetBufferSubDataARB"); 1516 if (!bufObj) { 1517 /* error already recorded */ 1518 return; 1519 } 1520 1521 ASSERT(ctx->Driver.GetBufferSubData); 1522 ctx->Driver.GetBufferSubData( ctx, offset, size, data, bufObj ); 1523} 1524 1525 1526void GLAPIENTRY 1527_mesa_ClearBufferData(GLenum target, GLenum internalformat, GLenum format, 1528 GLenum type, const GLvoid* data) 1529{ 1530 GET_CURRENT_CONTEXT(ctx); 1531 struct gl_buffer_object* bufObj; 1532 mesa_format mesaFormat; 1533 GLubyte clearValue[MAX_PIXEL_BYTES]; 1534 GLsizeiptr clearValueSize; 1535 1536 bufObj = get_buffer(ctx, "glClearBufferData", target, GL_INVALID_VALUE); 1537 if (!bufObj) { 1538 return; 1539 } 1540 1541 if (_mesa_check_disallowed_mapping(bufObj)) { 1542 _mesa_error(ctx, GL_INVALID_OPERATION, 1543 "glClearBufferData(buffer currently mapped)"); 1544 return; 1545 } 1546 1547 mesaFormat = validate_clear_buffer_format(ctx, internalformat, 1548 format, type, 1549 "glClearBufferData"); 1550 if (mesaFormat == MESA_FORMAT_NONE) { 1551 return; 1552 } 1553 1554 clearValueSize = _mesa_get_format_bytes(mesaFormat); 1555 if (bufObj->Size % clearValueSize != 0) { 1556 _mesa_error(ctx, GL_INVALID_VALUE, 1557 "glClearBufferData(size is not a multiple of " 1558 "internalformat size)"); 1559 return; 1560 } 1561 1562 if (data == NULL) { 1563 /* clear to zeros, per the spec */ 1564 ctx->Driver.ClearBufferSubData(ctx, 0, bufObj->Size, 1565 NULL, clearValueSize, bufObj); 1566 return; 1567 } 1568 1569 if (!convert_clear_buffer_data(ctx, mesaFormat, clearValue, 1570 format, type, data, "glClearBufferData")) { 1571 return; 1572 } 1573 1574 ctx->Driver.ClearBufferSubData(ctx, 0, bufObj->Size, 1575 clearValue, clearValueSize, bufObj); 1576} 1577 1578 1579void GLAPIENTRY 1580_mesa_ClearBufferSubData(GLenum target, GLenum internalformat, 1581 GLintptr offset, GLsizeiptr size, 1582 GLenum format, GLenum type, 1583 const GLvoid* data) 1584{ 1585 GET_CURRENT_CONTEXT(ctx); 1586 struct gl_buffer_object* bufObj; 1587 mesa_format mesaFormat; 1588 GLubyte clearValue[MAX_PIXEL_BYTES]; 1589 GLsizeiptr clearValueSize; 1590 1591 bufObj = buffer_object_subdata_range_good(ctx, target, offset, size, 1592 true, GL_INVALID_VALUE, 1593 "glClearBufferSubData"); 1594 if (!bufObj) { 1595 return; 1596 } 1597 1598 mesaFormat = validate_clear_buffer_format(ctx, internalformat, 1599 format, type, 1600 "glClearBufferSubData"); 1601 if (mesaFormat == MESA_FORMAT_NONE) { 1602 return; 1603 } 1604 1605 clearValueSize = _mesa_get_format_bytes(mesaFormat); 1606 if (offset % clearValueSize != 0 || size % clearValueSize != 0) { 1607 _mesa_error(ctx, GL_INVALID_VALUE, 1608 "glClearBufferSubData(offset or size is not a multiple of " 1609 "internalformat size)"); 1610 return; 1611 } 1612 1613 if (data == NULL) { 1614 /* clear to zeros, per the spec */ 1615 if (size > 0) { 1616 ctx->Driver.ClearBufferSubData(ctx, offset, size, 1617 NULL, clearValueSize, bufObj); 1618 } 1619 return; 1620 } 1621 1622 if (!convert_clear_buffer_data(ctx, mesaFormat, clearValue, 1623 format, type, data, 1624 "glClearBufferSubData")) { 1625 return; 1626 } 1627 1628 if (size > 0) { 1629 ctx->Driver.ClearBufferSubData(ctx, offset, size, 1630 clearValue, clearValueSize, bufObj); 1631 } 1632} 1633 1634 1635void * GLAPIENTRY 1636_mesa_MapBuffer(GLenum target, GLenum access) 1637{ 1638 GET_CURRENT_CONTEXT(ctx); 1639 struct gl_buffer_object * bufObj; 1640 GLbitfield accessFlags; 1641 void *map; 1642 bool valid_access; 1643 1644 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL); 1645 1646 switch (access) { 1647 case GL_READ_ONLY_ARB: 1648 accessFlags = GL_MAP_READ_BIT; 1649 valid_access = _mesa_is_desktop_gl(ctx); 1650 break; 1651 case GL_WRITE_ONLY_ARB: 1652 accessFlags = GL_MAP_WRITE_BIT; 1653 valid_access = true; 1654 break; 1655 case GL_READ_WRITE_ARB: 1656 accessFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT; 1657 valid_access = _mesa_is_desktop_gl(ctx); 1658 break; 1659 default: 1660 valid_access = false; 1661 break; 1662 } 1663 1664 if (!valid_access) { 1665 _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(access)"); 1666 return NULL; 1667 } 1668 1669 bufObj = get_buffer(ctx, "glMapBufferARB", target, GL_INVALID_OPERATION); 1670 if (!bufObj) 1671 return NULL; 1672 1673 if (accessFlags & GL_MAP_READ_BIT && 1674 !(bufObj->StorageFlags & GL_MAP_READ_BIT)) { 1675 _mesa_error(ctx, GL_INVALID_OPERATION, 1676 "glMapBuffer(invalid read flag)"); 1677 return NULL; 1678 } 1679 1680 if (accessFlags & GL_MAP_WRITE_BIT && 1681 !(bufObj->StorageFlags & GL_MAP_WRITE_BIT)) { 1682 _mesa_error(ctx, GL_INVALID_OPERATION, 1683 "glMapBuffer(invalid write flag)"); 1684 return NULL; 1685 } 1686 1687 if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) { 1688 _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(already mapped)"); 1689 return NULL; 1690 } 1691 1692 if (!bufObj->Size) { 1693 _mesa_error(ctx, GL_OUT_OF_MEMORY, 1694 "glMapBuffer(buffer size = 0)"); 1695 return NULL; 1696 } 1697 1698 ASSERT(ctx->Driver.MapBufferRange); 1699 map = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size, accessFlags, bufObj, 1700 MAP_USER); 1701 if (!map) { 1702 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)"); 1703 return NULL; 1704 } 1705 else { 1706 /* The driver callback should have set these fields. 1707 * This is important because other modules (like VBO) might call 1708 * the driver function directly. 1709 */ 1710 ASSERT(bufObj->Mappings[MAP_USER].Pointer == map); 1711 ASSERT(bufObj->Mappings[MAP_USER].Length == bufObj->Size); 1712 ASSERT(bufObj->Mappings[MAP_USER].Offset == 0); 1713 bufObj->Mappings[MAP_USER].AccessFlags = accessFlags; 1714 } 1715 1716 if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB) 1717 bufObj->Written = GL_TRUE; 1718 1719#ifdef VBO_DEBUG 1720 printf("glMapBufferARB(%u, sz %ld, access 0x%x)\n", 1721 bufObj->Name, bufObj->Size, access); 1722 if (access == GL_WRITE_ONLY_ARB) { 1723 GLuint i; 1724 GLubyte *b = (GLubyte *) bufObj->Pointer; 1725 for (i = 0; i < bufObj->Size; i++) 1726 b[i] = i & 0xff; 1727 } 1728#endif 1729 1730#ifdef BOUNDS_CHECK 1731 { 1732 GLubyte *buf = (GLubyte *) bufObj->Pointer; 1733 GLuint i; 1734 /* buffer is 100 bytes larger than requested, fill with magic value */ 1735 for (i = 0; i < 100; i++) { 1736 buf[bufObj->Size - i - 1] = 123; 1737 } 1738 } 1739#endif 1740 1741 return bufObj->Mappings[MAP_USER].Pointer; 1742} 1743 1744 1745GLboolean GLAPIENTRY 1746_mesa_UnmapBuffer(GLenum target) 1747{ 1748 GET_CURRENT_CONTEXT(ctx); 1749 struct gl_buffer_object *bufObj; 1750 GLboolean status = GL_TRUE; 1751 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 1752 1753 bufObj = get_buffer(ctx, "glUnmapBufferARB", target, GL_INVALID_OPERATION); 1754 if (!bufObj) 1755 return GL_FALSE; 1756 1757 if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) { 1758 _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB"); 1759 return GL_FALSE; 1760 } 1761 1762#ifdef BOUNDS_CHECK 1763 if (bufObj->Access != GL_READ_ONLY_ARB) { 1764 GLubyte *buf = (GLubyte *) bufObj->Pointer; 1765 GLuint i; 1766 /* check that last 100 bytes are still = magic value */ 1767 for (i = 0; i < 100; i++) { 1768 GLuint pos = bufObj->Size - i - 1; 1769 if (buf[pos] != 123) { 1770 _mesa_warning(ctx, "Out of bounds buffer object write detected" 1771 " at position %d (value = %u)\n", 1772 pos, buf[pos]); 1773 } 1774 } 1775 } 1776#endif 1777 1778#ifdef VBO_DEBUG 1779 if (bufObj->AccessFlags & GL_MAP_WRITE_BIT) { 1780 GLuint i, unchanged = 0; 1781 GLubyte *b = (GLubyte *) bufObj->Pointer; 1782 GLint pos = -1; 1783 /* check which bytes changed */ 1784 for (i = 0; i < bufObj->Size - 1; i++) { 1785 if (b[i] == (i & 0xff) && b[i+1] == ((i+1) & 0xff)) { 1786 unchanged++; 1787 if (pos == -1) 1788 pos = i; 1789 } 1790 } 1791 if (unchanged) { 1792 printf("glUnmapBufferARB(%u): %u of %ld unchanged, starting at %d\n", 1793 bufObj->Name, unchanged, bufObj->Size, pos); 1794 } 1795 } 1796#endif 1797 1798 status = ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_USER); 1799 bufObj->Mappings[MAP_USER].AccessFlags = 0; 1800 ASSERT(bufObj->Mappings[MAP_USER].Pointer == NULL); 1801 ASSERT(bufObj->Mappings[MAP_USER].Offset == 0); 1802 ASSERT(bufObj->Mappings[MAP_USER].Length == 0); 1803 1804 return status; 1805} 1806 1807 1808void GLAPIENTRY 1809_mesa_GetBufferParameteriv(GLenum target, GLenum pname, GLint *params) 1810{ 1811 GET_CURRENT_CONTEXT(ctx); 1812 struct gl_buffer_object *bufObj; 1813 1814 bufObj = get_buffer(ctx, "glGetBufferParameterivARB", target, 1815 GL_INVALID_OPERATION); 1816 if (!bufObj) 1817 return; 1818 1819 switch (pname) { 1820 case GL_BUFFER_SIZE_ARB: 1821 *params = (GLint) bufObj->Size; 1822 return; 1823 case GL_BUFFER_USAGE_ARB: 1824 *params = bufObj->Usage; 1825 return; 1826 case GL_BUFFER_ACCESS_ARB: 1827 *params = simplified_access_mode(ctx, 1828 bufObj->Mappings[MAP_USER].AccessFlags); 1829 return; 1830 case GL_BUFFER_MAPPED_ARB: 1831 *params = _mesa_bufferobj_mapped(bufObj, MAP_USER); 1832 return; 1833 case GL_BUFFER_ACCESS_FLAGS: 1834 if (!ctx->Extensions.ARB_map_buffer_range) 1835 goto invalid_pname; 1836 *params = bufObj->Mappings[MAP_USER].AccessFlags; 1837 return; 1838 case GL_BUFFER_MAP_OFFSET: 1839 if (!ctx->Extensions.ARB_map_buffer_range) 1840 goto invalid_pname; 1841 *params = (GLint) bufObj->Mappings[MAP_USER].Offset; 1842 return; 1843 case GL_BUFFER_MAP_LENGTH: 1844 if (!ctx->Extensions.ARB_map_buffer_range) 1845 goto invalid_pname; 1846 *params = (GLint) bufObj->Mappings[MAP_USER].Length; 1847 return; 1848 case GL_BUFFER_IMMUTABLE_STORAGE: 1849 if (!ctx->Extensions.ARB_buffer_storage) 1850 goto invalid_pname; 1851 *params = bufObj->Immutable; 1852 return; 1853 case GL_BUFFER_STORAGE_FLAGS: 1854 if (!ctx->Extensions.ARB_buffer_storage) 1855 goto invalid_pname; 1856 *params = bufObj->StorageFlags; 1857 return; 1858 default: 1859 ; /* fall-through */ 1860 } 1861 1862invalid_pname: 1863 _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname=%s)", 1864 _mesa_lookup_enum_by_nr(pname)); 1865} 1866 1867 1868/** 1869 * New in GL 3.2 1870 * This is pretty much a duplicate of GetBufferParameteriv() but the 1871 * GL_BUFFER_SIZE_ARB attribute will be 64-bits on a 64-bit system. 1872 */ 1873void GLAPIENTRY 1874_mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params) 1875{ 1876 GET_CURRENT_CONTEXT(ctx); 1877 struct gl_buffer_object *bufObj; 1878 1879 bufObj = get_buffer(ctx, "glGetBufferParameteri64v", target, 1880 GL_INVALID_OPERATION); 1881 if (!bufObj) 1882 return; 1883 1884 switch (pname) { 1885 case GL_BUFFER_SIZE_ARB: 1886 *params = bufObj->Size; 1887 return; 1888 case GL_BUFFER_USAGE_ARB: 1889 *params = bufObj->Usage; 1890 return; 1891 case GL_BUFFER_ACCESS_ARB: 1892 *params = simplified_access_mode(ctx, 1893 bufObj->Mappings[MAP_USER].AccessFlags); 1894 return; 1895 case GL_BUFFER_ACCESS_FLAGS: 1896 if (!ctx->Extensions.ARB_map_buffer_range) 1897 goto invalid_pname; 1898 *params = bufObj->Mappings[MAP_USER].AccessFlags; 1899 return; 1900 case GL_BUFFER_MAPPED_ARB: 1901 *params = _mesa_bufferobj_mapped(bufObj, MAP_USER); 1902 return; 1903 case GL_BUFFER_MAP_OFFSET: 1904 if (!ctx->Extensions.ARB_map_buffer_range) 1905 goto invalid_pname; 1906 *params = bufObj->Mappings[MAP_USER].Offset; 1907 return; 1908 case GL_BUFFER_MAP_LENGTH: 1909 if (!ctx->Extensions.ARB_map_buffer_range) 1910 goto invalid_pname; 1911 *params = bufObj->Mappings[MAP_USER].Length; 1912 return; 1913 case GL_BUFFER_IMMUTABLE_STORAGE: 1914 if (!ctx->Extensions.ARB_buffer_storage) 1915 goto invalid_pname; 1916 *params = bufObj->Immutable; 1917 return; 1918 case GL_BUFFER_STORAGE_FLAGS: 1919 if (!ctx->Extensions.ARB_buffer_storage) 1920 goto invalid_pname; 1921 *params = bufObj->StorageFlags; 1922 return; 1923 default: 1924 ; /* fall-through */ 1925 } 1926 1927invalid_pname: 1928 _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameteri64v(pname=%s)", 1929 _mesa_lookup_enum_by_nr(pname)); 1930} 1931 1932 1933void GLAPIENTRY 1934_mesa_GetBufferPointerv(GLenum target, GLenum pname, GLvoid **params) 1935{ 1936 GET_CURRENT_CONTEXT(ctx); 1937 struct gl_buffer_object * bufObj; 1938 1939 if (pname != GL_BUFFER_MAP_POINTER_ARB) { 1940 _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(pname)"); 1941 return; 1942 } 1943 1944 bufObj = get_buffer(ctx, "glGetBufferPointervARB", target, 1945 GL_INVALID_OPERATION); 1946 if (!bufObj) 1947 return; 1948 1949 *params = bufObj->Mappings[MAP_USER].Pointer; 1950} 1951 1952 1953void GLAPIENTRY 1954_mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget, 1955 GLintptr readOffset, GLintptr writeOffset, 1956 GLsizeiptr size) 1957{ 1958 GET_CURRENT_CONTEXT(ctx); 1959 struct gl_buffer_object *src, *dst; 1960 1961 src = get_buffer(ctx, "glCopyBufferSubData", readTarget, 1962 GL_INVALID_OPERATION); 1963 if (!src) 1964 return; 1965 1966 dst = get_buffer(ctx, "glCopyBufferSubData", writeTarget, 1967 GL_INVALID_OPERATION); 1968 if (!dst) 1969 return; 1970 1971 if (_mesa_check_disallowed_mapping(src)) { 1972 _mesa_error(ctx, GL_INVALID_OPERATION, 1973 "glCopyBufferSubData(readBuffer is mapped)"); 1974 return; 1975 } 1976 1977 if (_mesa_check_disallowed_mapping(dst)) { 1978 _mesa_error(ctx, GL_INVALID_OPERATION, 1979 "glCopyBufferSubData(writeBuffer is mapped)"); 1980 return; 1981 } 1982 1983 if (readOffset < 0) { 1984 _mesa_error(ctx, GL_INVALID_VALUE, 1985 "glCopyBufferSubData(readOffset = %d)", (int) readOffset); 1986 return; 1987 } 1988 1989 if (writeOffset < 0) { 1990 _mesa_error(ctx, GL_INVALID_VALUE, 1991 "glCopyBufferSubData(writeOffset = %d)", (int) writeOffset); 1992 return; 1993 } 1994 1995 if (size < 0) { 1996 _mesa_error(ctx, GL_INVALID_VALUE, 1997 "glCopyBufferSubData(writeOffset = %d)", (int) size); 1998 return; 1999 } 2000 2001 if (readOffset + size > src->Size) { 2002 _mesa_error(ctx, GL_INVALID_VALUE, 2003 "glCopyBufferSubData(readOffset + size = %d)", 2004 (int) (readOffset + size)); 2005 return; 2006 } 2007 2008 if (writeOffset + size > dst->Size) { 2009 _mesa_error(ctx, GL_INVALID_VALUE, 2010 "glCopyBufferSubData(writeOffset + size = %d)", 2011 (int) (writeOffset + size)); 2012 return; 2013 } 2014 2015 if (src == dst) { 2016 if (readOffset + size <= writeOffset) { 2017 /* OK */ 2018 } 2019 else if (writeOffset + size <= readOffset) { 2020 /* OK */ 2021 } 2022 else { 2023 /* overlapping src/dst is illegal */ 2024 _mesa_error(ctx, GL_INVALID_VALUE, 2025 "glCopyBufferSubData(overlapping src/dst)"); 2026 return; 2027 } 2028 } 2029 2030 ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset, size); 2031} 2032 2033 2034/** 2035 * See GL_ARB_map_buffer_range spec 2036 */ 2037void * GLAPIENTRY 2038_mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, 2039 GLbitfield access) 2040{ 2041 GET_CURRENT_CONTEXT(ctx); 2042 struct gl_buffer_object *bufObj; 2043 void *map; 2044 GLbitfield allowed_access; 2045 2046 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL); 2047 2048 if (!ctx->Extensions.ARB_map_buffer_range) { 2049 _mesa_error(ctx, GL_INVALID_OPERATION, 2050 "glMapBufferRange(extension not supported)"); 2051 return NULL; 2052 } 2053 2054 if (offset < 0) { 2055 _mesa_error(ctx, GL_INVALID_VALUE, 2056 "glMapBufferRange(offset = %ld)", (long)offset); 2057 return NULL; 2058 } 2059 2060 if (length < 0) { 2061 _mesa_error(ctx, GL_INVALID_VALUE, 2062 "glMapBufferRange(length = %ld)", (long)length); 2063 return NULL; 2064 } 2065 2066 /* Page 38 of the PDF of the OpenGL ES 3.0 spec says: 2067 * 2068 * "An INVALID_OPERATION error is generated for any of the following 2069 * conditions: 2070 * 2071 * * <length> is zero." 2072 */ 2073 if (_mesa_is_gles(ctx) && length == 0) { 2074 _mesa_error(ctx, GL_INVALID_OPERATION, 2075 "glMapBufferRange(length = 0)"); 2076 return NULL; 2077 } 2078 2079 allowed_access = GL_MAP_READ_BIT | 2080 GL_MAP_WRITE_BIT | 2081 GL_MAP_INVALIDATE_RANGE_BIT | 2082 GL_MAP_INVALIDATE_BUFFER_BIT | 2083 GL_MAP_FLUSH_EXPLICIT_BIT | 2084 GL_MAP_UNSYNCHRONIZED_BIT; 2085 2086 if (ctx->Extensions.ARB_buffer_storage) { 2087 allowed_access |= GL_MAP_PERSISTENT_BIT | 2088 GL_MAP_COHERENT_BIT; 2089 } 2090 2091 if (access & ~allowed_access) { 2092 /* generate an error if any other than allowed bit is set */ 2093 _mesa_error(ctx, GL_INVALID_VALUE, "glMapBufferRange(access)"); 2094 return NULL; 2095 } 2096 2097 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) { 2098 _mesa_error(ctx, GL_INVALID_OPERATION, 2099 "glMapBufferRange(access indicates neither read or write)"); 2100 return NULL; 2101 } 2102 2103 if ((access & GL_MAP_READ_BIT) && 2104 (access & (GL_MAP_INVALIDATE_RANGE_BIT | 2105 GL_MAP_INVALIDATE_BUFFER_BIT | 2106 GL_MAP_UNSYNCHRONIZED_BIT))) { 2107 _mesa_error(ctx, GL_INVALID_OPERATION, 2108 "glMapBufferRange(invalid access flags)"); 2109 return NULL; 2110 } 2111 2112 if ((access & GL_MAP_FLUSH_EXPLICIT_BIT) && 2113 ((access & GL_MAP_WRITE_BIT) == 0)) { 2114 _mesa_error(ctx, GL_INVALID_OPERATION, 2115 "glMapBufferRange(invalid access flags)"); 2116 return NULL; 2117 } 2118 2119 bufObj = get_buffer(ctx, "glMapBufferRange", target, GL_INVALID_OPERATION); 2120 if (!bufObj) 2121 return NULL; 2122 2123 if (access & GL_MAP_READ_BIT && 2124 !(bufObj->StorageFlags & GL_MAP_READ_BIT)) { 2125 _mesa_error(ctx, GL_INVALID_OPERATION, 2126 "glMapBufferRange(invalid read flag)"); 2127 return NULL; 2128 } 2129 2130 if (access & GL_MAP_WRITE_BIT && 2131 !(bufObj->StorageFlags & GL_MAP_WRITE_BIT)) { 2132 _mesa_error(ctx, GL_INVALID_OPERATION, 2133 "glMapBufferRange(invalid write flag)"); 2134 return NULL; 2135 } 2136 2137 if (access & GL_MAP_COHERENT_BIT && 2138 !(bufObj->StorageFlags & GL_MAP_COHERENT_BIT)) { 2139 _mesa_error(ctx, GL_INVALID_OPERATION, 2140 "glMapBufferRange(invalid coherent flag)"); 2141 return NULL; 2142 } 2143 2144 if (access & GL_MAP_PERSISTENT_BIT && 2145 !(bufObj->StorageFlags & GL_MAP_PERSISTENT_BIT)) { 2146 _mesa_error(ctx, GL_INVALID_OPERATION, 2147 "glMapBufferRange(invalid persistent flag)"); 2148 return NULL; 2149 } 2150 2151 if (offset + length > bufObj->Size) { 2152 _mesa_error(ctx, GL_INVALID_VALUE, 2153 "glMapBufferRange(offset + length > size)"); 2154 return NULL; 2155 } 2156 2157 if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) { 2158 _mesa_error(ctx, GL_INVALID_OPERATION, 2159 "glMapBufferRange(buffer already mapped)"); 2160 return NULL; 2161 } 2162 2163 if (!bufObj->Size) { 2164 _mesa_error(ctx, GL_OUT_OF_MEMORY, 2165 "glMapBufferRange(buffer size = 0)"); 2166 return NULL; 2167 } 2168 2169 /* Mapping zero bytes should return a non-null pointer. */ 2170 if (!length) { 2171 static long dummy = 0; 2172 bufObj->Mappings[MAP_USER].Pointer = &dummy; 2173 bufObj->Mappings[MAP_USER].Length = length; 2174 bufObj->Mappings[MAP_USER].Offset = offset; 2175 bufObj->Mappings[MAP_USER].AccessFlags = access; 2176 return bufObj->Mappings[MAP_USER].Pointer; 2177 } 2178 2179 ASSERT(ctx->Driver.MapBufferRange); 2180 map = ctx->Driver.MapBufferRange(ctx, offset, length, access, bufObj, 2181 MAP_USER); 2182 if (!map) { 2183 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)"); 2184 } 2185 else { 2186 /* The driver callback should have set all these fields. 2187 * This is important because other modules (like VBO) might call 2188 * the driver function directly. 2189 */ 2190 ASSERT(bufObj->Mappings[MAP_USER].Pointer == map); 2191 ASSERT(bufObj->Mappings[MAP_USER].Length == length); 2192 ASSERT(bufObj->Mappings[MAP_USER].Offset == offset); 2193 ASSERT(bufObj->Mappings[MAP_USER].AccessFlags == access); 2194 } 2195 2196 return map; 2197} 2198 2199 2200/** 2201 * See GL_ARB_map_buffer_range spec 2202 */ 2203void GLAPIENTRY 2204_mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) 2205{ 2206 GET_CURRENT_CONTEXT(ctx); 2207 struct gl_buffer_object *bufObj; 2208 2209 if (!ctx->Extensions.ARB_map_buffer_range) { 2210 _mesa_error(ctx, GL_INVALID_OPERATION, 2211 "glFlushMappedBufferRange(extension not supported)"); 2212 return; 2213 } 2214 2215 if (offset < 0) { 2216 _mesa_error(ctx, GL_INVALID_VALUE, 2217 "glFlushMappedBufferRange(offset = %ld)", (long)offset); 2218 return; 2219 } 2220 2221 if (length < 0) { 2222 _mesa_error(ctx, GL_INVALID_VALUE, 2223 "glFlushMappedBufferRange(length = %ld)", (long)length); 2224 return; 2225 } 2226 2227 bufObj = get_buffer(ctx, "glFlushMappedBufferRange", target, 2228 GL_INVALID_OPERATION); 2229 if (!bufObj) 2230 return; 2231 2232 if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) { 2233 /* buffer is not mapped */ 2234 _mesa_error(ctx, GL_INVALID_OPERATION, 2235 "glFlushMappedBufferRange(buffer is not mapped)"); 2236 return; 2237 } 2238 2239 if ((bufObj->Mappings[MAP_USER].AccessFlags & 2240 GL_MAP_FLUSH_EXPLICIT_BIT) == 0) { 2241 _mesa_error(ctx, GL_INVALID_OPERATION, 2242 "glFlushMappedBufferRange(GL_MAP_FLUSH_EXPLICIT_BIT not set)"); 2243 return; 2244 } 2245 2246 if (offset + length > bufObj->Mappings[MAP_USER].Length) { 2247 _mesa_error(ctx, GL_INVALID_VALUE, 2248 "glFlushMappedBufferRange(offset %ld + length %ld > mapped length %ld)", 2249 (long)offset, (long)length, 2250 (long)bufObj->Mappings[MAP_USER].Length); 2251 return; 2252 } 2253 2254 ASSERT(bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_WRITE_BIT); 2255 2256 if (ctx->Driver.FlushMappedBufferRange) 2257 ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj, 2258 MAP_USER); 2259} 2260 2261 2262static GLenum 2263buffer_object_purgeable(struct gl_context *ctx, GLuint name, GLenum option) 2264{ 2265 struct gl_buffer_object *bufObj; 2266 GLenum retval; 2267 2268 bufObj = _mesa_lookup_bufferobj(ctx, name); 2269 if (!bufObj) { 2270 _mesa_error(ctx, GL_INVALID_VALUE, 2271 "glObjectPurgeable(name = 0x%x)", name); 2272 return 0; 2273 } 2274 if (!_mesa_is_bufferobj(bufObj)) { 2275 _mesa_error(ctx, GL_INVALID_OPERATION, "glObjectPurgeable(buffer 0)" ); 2276 return 0; 2277 } 2278 2279 if (bufObj->Purgeable) { 2280 _mesa_error(ctx, GL_INVALID_OPERATION, 2281 "glObjectPurgeable(name = 0x%x) is already purgeable", name); 2282 return GL_VOLATILE_APPLE; 2283 } 2284 2285 bufObj->Purgeable = GL_TRUE; 2286 2287 retval = GL_VOLATILE_APPLE; 2288 if (ctx->Driver.BufferObjectPurgeable) 2289 retval = ctx->Driver.BufferObjectPurgeable(ctx, bufObj, option); 2290 2291 return retval; 2292} 2293 2294 2295static GLenum 2296renderbuffer_purgeable(struct gl_context *ctx, GLuint name, GLenum option) 2297{ 2298 struct gl_renderbuffer *bufObj; 2299 GLenum retval; 2300 2301 bufObj = _mesa_lookup_renderbuffer(ctx, name); 2302 if (!bufObj) { 2303 _mesa_error(ctx, GL_INVALID_VALUE, 2304 "glObjectUnpurgeable(name = 0x%x)", name); 2305 return 0; 2306 } 2307 2308 if (bufObj->Purgeable) { 2309 _mesa_error(ctx, GL_INVALID_OPERATION, 2310 "glObjectPurgeable(name = 0x%x) is already purgeable", name); 2311 return GL_VOLATILE_APPLE; 2312 } 2313 2314 bufObj->Purgeable = GL_TRUE; 2315 2316 retval = GL_VOLATILE_APPLE; 2317 if (ctx->Driver.RenderObjectPurgeable) 2318 retval = ctx->Driver.RenderObjectPurgeable(ctx, bufObj, option); 2319 2320 return retval; 2321} 2322 2323 2324static GLenum 2325texture_object_purgeable(struct gl_context *ctx, GLuint name, GLenum option) 2326{ 2327 struct gl_texture_object *bufObj; 2328 GLenum retval; 2329 2330 bufObj = _mesa_lookup_texture(ctx, name); 2331 if (!bufObj) { 2332 _mesa_error(ctx, GL_INVALID_VALUE, 2333 "glObjectPurgeable(name = 0x%x)", name); 2334 return 0; 2335 } 2336 2337 if (bufObj->Purgeable) { 2338 _mesa_error(ctx, GL_INVALID_OPERATION, 2339 "glObjectPurgeable(name = 0x%x) is already purgeable", name); 2340 return GL_VOLATILE_APPLE; 2341 } 2342 2343 bufObj->Purgeable = GL_TRUE; 2344 2345 retval = GL_VOLATILE_APPLE; 2346 if (ctx->Driver.TextureObjectPurgeable) 2347 retval = ctx->Driver.TextureObjectPurgeable(ctx, bufObj, option); 2348 2349 return retval; 2350} 2351 2352 2353GLenum GLAPIENTRY 2354_mesa_ObjectPurgeableAPPLE(GLenum objectType, GLuint name, GLenum option) 2355{ 2356 GLenum retval; 2357 2358 GET_CURRENT_CONTEXT(ctx); 2359 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); 2360 2361 if (name == 0) { 2362 _mesa_error(ctx, GL_INVALID_VALUE, 2363 "glObjectPurgeable(name = 0x%x)", name); 2364 return 0; 2365 } 2366 2367 switch (option) { 2368 case GL_VOLATILE_APPLE: 2369 case GL_RELEASED_APPLE: 2370 /* legal */ 2371 break; 2372 default: 2373 _mesa_error(ctx, GL_INVALID_ENUM, 2374 "glObjectPurgeable(name = 0x%x) invalid option: %d", 2375 name, option); 2376 return 0; 2377 } 2378 2379 switch (objectType) { 2380 case GL_TEXTURE: 2381 retval = texture_object_purgeable(ctx, name, option); 2382 break; 2383 case GL_RENDERBUFFER_EXT: 2384 retval = renderbuffer_purgeable(ctx, name, option); 2385 break; 2386 case GL_BUFFER_OBJECT_APPLE: 2387 retval = buffer_object_purgeable(ctx, name, option); 2388 break; 2389 default: 2390 _mesa_error(ctx, GL_INVALID_ENUM, 2391 "glObjectPurgeable(name = 0x%x) invalid type: %d", 2392 name, objectType); 2393 return 0; 2394 } 2395 2396 /* In strict conformance to the spec, we must only return VOLATILE when 2397 * when passed the VOLATILE option. Madness. 2398 * 2399 * XXX First fix the spec, then fix me. 2400 */ 2401 return option == GL_VOLATILE_APPLE ? GL_VOLATILE_APPLE : retval; 2402} 2403 2404 2405static GLenum 2406buffer_object_unpurgeable(struct gl_context *ctx, GLuint name, GLenum option) 2407{ 2408 struct gl_buffer_object *bufObj; 2409 GLenum retval; 2410 2411 bufObj = _mesa_lookup_bufferobj(ctx, name); 2412 if (!bufObj) { 2413 _mesa_error(ctx, GL_INVALID_VALUE, 2414 "glObjectUnpurgeable(name = 0x%x)", name); 2415 return 0; 2416 } 2417 2418 if (! bufObj->Purgeable) { 2419 _mesa_error(ctx, GL_INVALID_OPERATION, 2420 "glObjectUnpurgeable(name = 0x%x) object is " 2421 " already \"unpurged\"", name); 2422 return 0; 2423 } 2424 2425 bufObj->Purgeable = GL_FALSE; 2426 2427 retval = option; 2428 if (ctx->Driver.BufferObjectUnpurgeable) 2429 retval = ctx->Driver.BufferObjectUnpurgeable(ctx, bufObj, option); 2430 2431 return retval; 2432} 2433 2434 2435static GLenum 2436renderbuffer_unpurgeable(struct gl_context *ctx, GLuint name, GLenum option) 2437{ 2438 struct gl_renderbuffer *bufObj; 2439 GLenum retval; 2440 2441 bufObj = _mesa_lookup_renderbuffer(ctx, name); 2442 if (!bufObj) { 2443 _mesa_error(ctx, GL_INVALID_VALUE, 2444 "glObjectUnpurgeable(name = 0x%x)", name); 2445 return 0; 2446 } 2447 2448 if (! bufObj->Purgeable) { 2449 _mesa_error(ctx, GL_INVALID_OPERATION, 2450 "glObjectUnpurgeable(name = 0x%x) object is " 2451 " already \"unpurged\"", name); 2452 return 0; 2453 } 2454 2455 bufObj->Purgeable = GL_FALSE; 2456 2457 retval = option; 2458 if (ctx->Driver.RenderObjectUnpurgeable) 2459 retval = ctx->Driver.RenderObjectUnpurgeable(ctx, bufObj, option); 2460 2461 return retval; 2462} 2463 2464 2465static GLenum 2466texture_object_unpurgeable(struct gl_context *ctx, GLuint name, GLenum option) 2467{ 2468 struct gl_texture_object *bufObj; 2469 GLenum retval; 2470 2471 bufObj = _mesa_lookup_texture(ctx, name); 2472 if (!bufObj) { 2473 _mesa_error(ctx, GL_INVALID_VALUE, 2474 "glObjectUnpurgeable(name = 0x%x)", name); 2475 return 0; 2476 } 2477 2478 if (! bufObj->Purgeable) { 2479 _mesa_error(ctx, GL_INVALID_OPERATION, 2480 "glObjectUnpurgeable(name = 0x%x) object is" 2481 " already \"unpurged\"", name); 2482 return 0; 2483 } 2484 2485 bufObj->Purgeable = GL_FALSE; 2486 2487 retval = option; 2488 if (ctx->Driver.TextureObjectUnpurgeable) 2489 retval = ctx->Driver.TextureObjectUnpurgeable(ctx, bufObj, option); 2490 2491 return retval; 2492} 2493 2494 2495GLenum GLAPIENTRY 2496_mesa_ObjectUnpurgeableAPPLE(GLenum objectType, GLuint name, GLenum option) 2497{ 2498 GET_CURRENT_CONTEXT(ctx); 2499 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); 2500 2501 if (name == 0) { 2502 _mesa_error(ctx, GL_INVALID_VALUE, 2503 "glObjectUnpurgeable(name = 0x%x)", name); 2504 return 0; 2505 } 2506 2507 switch (option) { 2508 case GL_RETAINED_APPLE: 2509 case GL_UNDEFINED_APPLE: 2510 /* legal */ 2511 break; 2512 default: 2513 _mesa_error(ctx, GL_INVALID_ENUM, 2514 "glObjectUnpurgeable(name = 0x%x) invalid option: %d", 2515 name, option); 2516 return 0; 2517 } 2518 2519 switch (objectType) { 2520 case GL_BUFFER_OBJECT_APPLE: 2521 return buffer_object_unpurgeable(ctx, name, option); 2522 case GL_TEXTURE: 2523 return texture_object_unpurgeable(ctx, name, option); 2524 case GL_RENDERBUFFER_EXT: 2525 return renderbuffer_unpurgeable(ctx, name, option); 2526 default: 2527 _mesa_error(ctx, GL_INVALID_ENUM, 2528 "glObjectUnpurgeable(name = 0x%x) invalid type: %d", 2529 name, objectType); 2530 return 0; 2531 } 2532} 2533 2534 2535static void 2536get_buffer_object_parameteriv(struct gl_context *ctx, GLuint name, 2537 GLenum pname, GLint *params) 2538{ 2539 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, name); 2540 if (!bufObj) { 2541 _mesa_error(ctx, GL_INVALID_VALUE, 2542 "glGetObjectParameteriv(name = 0x%x) invalid object", name); 2543 return; 2544 } 2545 2546 switch (pname) { 2547 case GL_PURGEABLE_APPLE: 2548 *params = bufObj->Purgeable; 2549 break; 2550 default: 2551 _mesa_error(ctx, GL_INVALID_ENUM, 2552 "glGetObjectParameteriv(name = 0x%x) invalid enum: %d", 2553 name, pname); 2554 break; 2555 } 2556} 2557 2558 2559static void 2560get_renderbuffer_parameteriv(struct gl_context *ctx, GLuint name, 2561 GLenum pname, GLint *params) 2562{ 2563 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, name); 2564 if (!rb) { 2565 _mesa_error(ctx, GL_INVALID_VALUE, 2566 "glObjectUnpurgeable(name = 0x%x)", name); 2567 return; 2568 } 2569 2570 switch (pname) { 2571 case GL_PURGEABLE_APPLE: 2572 *params = rb->Purgeable; 2573 break; 2574 default: 2575 _mesa_error(ctx, GL_INVALID_ENUM, 2576 "glGetObjectParameteriv(name = 0x%x) invalid enum: %d", 2577 name, pname); 2578 break; 2579 } 2580} 2581 2582 2583static void 2584get_texture_object_parameteriv(struct gl_context *ctx, GLuint name, 2585 GLenum pname, GLint *params) 2586{ 2587 struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, name); 2588 if (!texObj) { 2589 _mesa_error(ctx, GL_INVALID_VALUE, 2590 "glObjectUnpurgeable(name = 0x%x)", name); 2591 return; 2592 } 2593 2594 switch (pname) { 2595 case GL_PURGEABLE_APPLE: 2596 *params = texObj->Purgeable; 2597 break; 2598 default: 2599 _mesa_error(ctx, GL_INVALID_ENUM, 2600 "glGetObjectParameteriv(name = 0x%x) invalid enum: %d", 2601 name, pname); 2602 break; 2603 } 2604} 2605 2606 2607void GLAPIENTRY 2608_mesa_GetObjectParameterivAPPLE(GLenum objectType, GLuint name, GLenum pname, 2609 GLint *params) 2610{ 2611 GET_CURRENT_CONTEXT(ctx); 2612 2613 if (name == 0) { 2614 _mesa_error(ctx, GL_INVALID_VALUE, 2615 "glGetObjectParameteriv(name = 0x%x)", name); 2616 return; 2617 } 2618 2619 switch (objectType) { 2620 case GL_TEXTURE: 2621 get_texture_object_parameteriv(ctx, name, pname, params); 2622 break; 2623 case GL_BUFFER_OBJECT_APPLE: 2624 get_buffer_object_parameteriv(ctx, name, pname, params); 2625 break; 2626 case GL_RENDERBUFFER_EXT: 2627 get_renderbuffer_parameteriv(ctx, name, pname, params); 2628 break; 2629 default: 2630 _mesa_error(ctx, GL_INVALID_ENUM, 2631 "glGetObjectParameteriv(name = 0x%x) invalid type: %d", 2632 name, objectType); 2633 } 2634} 2635 2636/** 2637 * Binds a buffer object to a uniform buffer binding point. 2638 * 2639 * The caller is responsible for flushing vertices and updating 2640 * NewDriverState. 2641 */ 2642static void 2643set_ubo_binding(struct gl_context *ctx, 2644 struct gl_uniform_buffer_binding *binding, 2645 struct gl_buffer_object *bufObj, 2646 GLintptr offset, 2647 GLsizeiptr size, 2648 GLboolean autoSize) 2649{ 2650 _mesa_reference_buffer_object(ctx, &binding->BufferObject, bufObj); 2651 2652 binding->Offset = offset; 2653 binding->Size = size; 2654 binding->AutomaticSize = autoSize; 2655} 2656 2657/** 2658 * Binds a buffer object to a uniform buffer binding point. 2659 * 2660 * Unlike set_ubo_binding(), this function also flushes vertices 2661 * and updates NewDriverState. It also checks if the binding 2662 * has actually changed before updating it. 2663 */ 2664static void 2665bind_uniform_buffer(struct gl_context *ctx, 2666 GLuint index, 2667 struct gl_buffer_object *bufObj, 2668 GLintptr offset, 2669 GLsizeiptr size, 2670 GLboolean autoSize) 2671{ 2672 struct gl_uniform_buffer_binding *binding = 2673 &ctx->UniformBufferBindings[index]; 2674 2675 if (binding->BufferObject == bufObj && 2676 binding->Offset == offset && 2677 binding->Size == size && 2678 binding->AutomaticSize == autoSize) { 2679 return; 2680 } 2681 2682 FLUSH_VERTICES(ctx, 0); 2683 ctx->NewDriverState |= ctx->DriverFlags.NewUniformBuffer; 2684 2685 set_ubo_binding(ctx, binding, bufObj, offset, size, autoSize); 2686} 2687 2688/** 2689 * Bind a region of a buffer object to a uniform block binding point. 2690 * \param index the uniform buffer binding point index 2691 * \param bufObj the buffer object 2692 * \param offset offset to the start of buffer object region 2693 * \param size size of the buffer object region 2694 */ 2695static void 2696bind_buffer_range_uniform_buffer(struct gl_context *ctx, 2697 GLuint index, 2698 struct gl_buffer_object *bufObj, 2699 GLintptr offset, 2700 GLsizeiptr size) 2701{ 2702 if (index >= ctx->Const.MaxUniformBufferBindings) { 2703 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index); 2704 return; 2705 } 2706 2707 if (offset & (ctx->Const.UniformBufferOffsetAlignment - 1)) { 2708 _mesa_error(ctx, GL_INVALID_VALUE, 2709 "glBindBufferRange(offset misalgned %d/%d)", (int) offset, 2710 ctx->Const.UniformBufferOffsetAlignment); 2711 return; 2712 } 2713 2714 if (bufObj == ctx->Shared->NullBufferObj) { 2715 offset = -1; 2716 size = -1; 2717 } 2718 2719 _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, bufObj); 2720 bind_uniform_buffer(ctx, index, bufObj, offset, size, GL_FALSE); 2721} 2722 2723 2724/** 2725 * Bind a buffer object to a uniform block binding point. 2726 * As above, but offset = 0. 2727 */ 2728static void 2729bind_buffer_base_uniform_buffer(struct gl_context *ctx, 2730 GLuint index, 2731 struct gl_buffer_object *bufObj) 2732{ 2733 if (index >= ctx->Const.MaxUniformBufferBindings) { 2734 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index); 2735 return; 2736 } 2737 2738 _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, bufObj); 2739 2740 if (bufObj == ctx->Shared->NullBufferObj) 2741 bind_uniform_buffer(ctx, index, bufObj, -1, -1, GL_TRUE); 2742 else 2743 bind_uniform_buffer(ctx, index, bufObj, 0, 0, GL_TRUE); 2744} 2745 2746/** 2747 * Binds a buffer object to an atomic buffer binding point. 2748 * 2749 * The caller is responsible for validating the offset, 2750 * flushing the vertices and updating NewDriverState. 2751 */ 2752static void 2753set_atomic_buffer_binding(struct gl_context *ctx, 2754 struct gl_atomic_buffer_binding *binding, 2755 struct gl_buffer_object *bufObj, 2756 GLintptr offset, 2757 GLsizeiptr size) 2758{ 2759 _mesa_reference_buffer_object(ctx, &binding->BufferObject, bufObj); 2760 2761 if (bufObj == ctx->Shared->NullBufferObj) { 2762 binding->Offset = -1; 2763 binding->Size = -1; 2764 } else { 2765 binding->Offset = offset; 2766 binding->Size = size; 2767 } 2768} 2769 2770/** 2771 * Binds a buffer object to an atomic buffer binding point. 2772 * 2773 * Unlike set_atomic_buffer_binding(), this function also validates the 2774 * index and offset, flushes vertices, and updates NewDriverState. 2775 * It also checks if the binding has actually changing before 2776 * updating it. 2777 */ 2778static void 2779bind_atomic_buffer(struct gl_context *ctx, 2780 unsigned index, 2781 struct gl_buffer_object *bufObj, 2782 GLintptr offset, 2783 GLsizeiptr size, 2784 const char *name) 2785{ 2786 struct gl_atomic_buffer_binding *binding; 2787 2788 if (index >= ctx->Const.MaxAtomicBufferBindings) { 2789 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%d)", name, index); 2790 return; 2791 } 2792 2793 if (offset & (ATOMIC_COUNTER_SIZE - 1)) { 2794 _mesa_error(ctx, GL_INVALID_VALUE, 2795 "%s(offset misalgned %d/%d)", name, (int) offset, 2796 ATOMIC_COUNTER_SIZE); 2797 return; 2798 } 2799 2800 _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, bufObj); 2801 2802 binding = &ctx->AtomicBufferBindings[index]; 2803 if (binding->BufferObject == bufObj && 2804 binding->Offset == offset && 2805 binding->Size == size) { 2806 return; 2807 } 2808 2809 FLUSH_VERTICES(ctx, 0); 2810 ctx->NewDriverState |= ctx->DriverFlags.NewAtomicBuffer; 2811 2812 set_atomic_buffer_binding(ctx, binding, bufObj, offset, size); 2813} 2814 2815static inline bool 2816bind_buffers_check_offset_and_size(struct gl_context *ctx, 2817 GLuint index, 2818 const GLintptr *offsets, 2819 const GLsizeiptr *sizes) 2820{ 2821 if (offsets[index] < 0) { 2822 /* The ARB_multi_bind spec says: 2823 * 2824 * "An INVALID_VALUE error is generated by BindBuffersRange if any 2825 * value in <offsets> is less than zero (per binding)." 2826 */ 2827 _mesa_error(ctx, GL_INVALID_VALUE, 2828 "glBindBuffersRange(offsets[%u]=%" PRId64 " < 0)", 2829 index, (int64_t) offsets[index]); 2830 return false; 2831 } 2832 2833 if (sizes[index] <= 0) { 2834 /* The ARB_multi_bind spec says: 2835 * 2836 * "An INVALID_VALUE error is generated by BindBuffersRange if any 2837 * value in <sizes> is less than or equal to zero (per binding)." 2838 */ 2839 _mesa_error(ctx, GL_INVALID_VALUE, 2840 "glBindBuffersRange(sizes[%u]=%" PRId64 " <= 0)", 2841 index, (int64_t) sizes[index]); 2842 return false; 2843 } 2844 2845 return true; 2846} 2847 2848static bool 2849error_check_bind_uniform_buffers(struct gl_context *ctx, 2850 GLuint first, GLsizei count, 2851 const char *caller) 2852{ 2853 if (!ctx->Extensions.ARB_uniform_buffer_object) { 2854 _mesa_error(ctx, GL_INVALID_ENUM, 2855 "%s(target=GL_UNIFORM_BUFFER)", caller); 2856 return false; 2857 } 2858 2859 /* The ARB_multi_bind_spec says: 2860 * 2861 * "An INVALID_OPERATION error is generated if <first> + <count> is 2862 * greater than the number of target-specific indexed binding points, 2863 * as described in section 6.7.1." 2864 */ 2865 if (first + count > ctx->Const.MaxUniformBufferBindings) { 2866 _mesa_error(ctx, GL_INVALID_OPERATION, 2867 "%s(first=%u + count=%d > the value of " 2868 "GL_MAX_UNIFORM_BUFFER_BINDINGS=%u)", 2869 caller, first, count, 2870 ctx->Const.MaxUniformBufferBindings); 2871 return false; 2872 } 2873 2874 return true; 2875} 2876 2877/** 2878 * Unbind all uniform buffers in the range 2879 * <first> through <first>+<count>-1 2880 */ 2881static void 2882unbind_uniform_buffers(struct gl_context *ctx, GLuint first, GLsizei count) 2883{ 2884 struct gl_buffer_object *bufObj = ctx->Shared->NullBufferObj; 2885 GLuint i; 2886 2887 for (i = 0; i < count; i++) 2888 set_ubo_binding(ctx, &ctx->UniformBufferBindings[first + i], 2889 bufObj, -1, -1, GL_TRUE); 2890} 2891 2892static void 2893bind_uniform_buffers_base(struct gl_context *ctx, GLuint first, GLsizei count, 2894 const GLuint *buffers) 2895{ 2896 GLuint i; 2897 2898 if (!error_check_bind_uniform_buffers(ctx, first, count, "glBindBuffersBase")) 2899 return; 2900 2901 /* Assume that at least one binding will be changed */ 2902 FLUSH_VERTICES(ctx, 0); 2903 ctx->NewDriverState |= ctx->DriverFlags.NewUniformBuffer; 2904 2905 if (!buffers) { 2906 /* The ARB_multi_bind spec says: 2907 * 2908 * "If <buffers> is NULL, all bindings from <first> through 2909 * <first>+<count>-1 are reset to their unbound (zero) state." 2910 */ 2911 unbind_uniform_buffers(ctx, first, count); 2912 return; 2913 } 2914 2915 /* Note that the error semantics for multi-bind commands differ from 2916 * those of other GL commands. 2917 * 2918 * The Issues section in the ARB_multi_bind spec says: 2919 * 2920 * "(11) Typically, OpenGL specifies that if an error is generated by a 2921 * command, that command has no effect. This is somewhat 2922 * unfortunate for multi-bind commands, because it would require a 2923 * first pass to scan the entire list of bound objects for errors 2924 * and then a second pass to actually perform the bindings. 2925 * Should we have different error semantics? 2926 * 2927 * RESOLVED: Yes. In this specification, when the parameters for 2928 * one of the <count> binding points are invalid, that binding point 2929 * is not updated and an error will be generated. However, other 2930 * binding points in the same command will be updated if their 2931 * parameters are valid and no other error occurs." 2932 */ 2933 2934 _mesa_begin_bufferobj_lookups(ctx); 2935 2936 for (i = 0; i < count; i++) { 2937 struct gl_uniform_buffer_binding *binding = 2938 &ctx->UniformBufferBindings[first + i]; 2939 struct gl_buffer_object *bufObj; 2940 2941 if (binding->BufferObject && binding->BufferObject->Name == buffers[i]) 2942 bufObj = binding->BufferObject; 2943 else 2944 bufObj = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, 2945 "glBindBuffersBase"); 2946 2947 if (bufObj) { 2948 if (bufObj == ctx->Shared->NullBufferObj) 2949 set_ubo_binding(ctx, binding, bufObj, -1, -1, GL_TRUE); 2950 else 2951 set_ubo_binding(ctx, binding, bufObj, 0, 0, GL_TRUE); 2952 } 2953 } 2954 2955 _mesa_end_bufferobj_lookups(ctx); 2956} 2957 2958static void 2959bind_uniform_buffers_range(struct gl_context *ctx, GLuint first, GLsizei count, 2960 const GLuint *buffers, 2961 const GLintptr *offsets, const GLsizeiptr *sizes) 2962{ 2963 GLuint i; 2964 2965 if (!error_check_bind_uniform_buffers(ctx, first, count, 2966 "glBindBuffersRange")) 2967 return; 2968 2969 /* Assume that at least one binding will be changed */ 2970 FLUSH_VERTICES(ctx, 0); 2971 ctx->NewDriverState |= ctx->DriverFlags.NewUniformBuffer; 2972 2973 if (!buffers) { 2974 /* The ARB_multi_bind spec says: 2975 * 2976 * "If <buffers> is NULL, all bindings from <first> through 2977 * <first>+<count>-1 are reset to their unbound (zero) state. 2978 * In this case, the offsets and sizes associated with the 2979 * binding points are set to default values, ignoring 2980 * <offsets> and <sizes>." 2981 */ 2982 unbind_uniform_buffers(ctx, first, count); 2983 return; 2984 } 2985 2986 /* Note that the error semantics for multi-bind commands differ from 2987 * those of other GL commands. 2988 * 2989 * The Issues section in the ARB_multi_bind spec says: 2990 * 2991 * "(11) Typically, OpenGL specifies that if an error is generated by a 2992 * command, that command has no effect. This is somewhat 2993 * unfortunate for multi-bind commands, because it would require a 2994 * first pass to scan the entire list of bound objects for errors 2995 * and then a second pass to actually perform the bindings. 2996 * Should we have different error semantics? 2997 * 2998 * RESOLVED: Yes. In this specification, when the parameters for 2999 * one of the <count> binding points are invalid, that binding point 3000 * is not updated and an error will be generated. However, other 3001 * binding points in the same command will be updated if their 3002 * parameters are valid and no other error occurs." 3003 */ 3004 3005 _mesa_begin_bufferobj_lookups(ctx); 3006 3007 for (i = 0; i < count; i++) { 3008 struct gl_uniform_buffer_binding *binding = 3009 &ctx->UniformBufferBindings[first + i]; 3010 struct gl_buffer_object *bufObj; 3011 3012 if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes)) 3013 continue; 3014 3015 /* The ARB_multi_bind spec says: 3016 * 3017 * "An INVALID_VALUE error is generated by BindBuffersRange if any 3018 * pair of values in <offsets> and <sizes> does not respectively 3019 * satisfy the constraints described for those parameters for the 3020 * specified target, as described in section 6.7.1 (per binding)." 3021 * 3022 * Section 6.7.1 refers to table 6.5, which says: 3023 * 3024 * "┌───────────────────────────────────────────────────────────────┐ 3025 * │ Uniform buffer array bindings (see sec. 7.6) │ 3026 * ├─────────────────────┬─────────────────────────────────────────┤ 3027 * │ ... │ ... │ 3028 * │ offset restriction │ multiple of value of UNIFORM_BUFFER_- │ 3029 * │ │ OFFSET_ALIGNMENT │ 3030 * │ ... │ ... │ 3031 * │ size restriction │ none │ 3032 * └─────────────────────┴─────────────────────────────────────────┘" 3033 */ 3034 if (offsets[i] & (ctx->Const.UniformBufferOffsetAlignment - 1)) { 3035 _mesa_error(ctx, GL_INVALID_VALUE, 3036 "glBindBuffersRange(offsets[%u]=%" PRId64 3037 " is misaligned; it must be a multiple of the value of " 3038 "GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT=%u when " 3039 "target=GL_UNIFORM_BUFFER)", 3040 i, (int64_t) offsets[i], 3041 ctx->Const.UniformBufferOffsetAlignment); 3042 continue; 3043 } 3044 3045 if (binding->BufferObject && binding->BufferObject->Name == buffers[i]) 3046 bufObj = binding->BufferObject; 3047 else 3048 bufObj = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, 3049 "glBindBuffersRange"); 3050 3051 if (bufObj) { 3052 if (bufObj == ctx->Shared->NullBufferObj) 3053 set_ubo_binding(ctx, binding, bufObj, -1, -1, GL_FALSE); 3054 else 3055 set_ubo_binding(ctx, binding, bufObj, 3056 offsets[i], sizes[i], GL_FALSE); 3057 } 3058 } 3059 3060 _mesa_end_bufferobj_lookups(ctx); 3061} 3062 3063static bool 3064error_check_bind_xfb_buffers(struct gl_context *ctx, 3065 struct gl_transform_feedback_object *tfObj, 3066 GLuint first, GLsizei count, const char *caller) 3067{ 3068 if (!ctx->Extensions.EXT_transform_feedback) { 3069 _mesa_error(ctx, GL_INVALID_ENUM, 3070 "%s(target=GL_TRANSFORM_FEEDBACK_BUFFER)", caller); 3071 return false; 3072 } 3073 3074 /* Page 398 of the PDF of the OpenGL 4.4 (Core Profile) spec says: 3075 * 3076 * "An INVALID_OPERATION error is generated : 3077 * 3078 * ... 3079 * • by BindBufferRange or BindBufferBase if target is TRANSFORM_- 3080 * FEEDBACK_BUFFER and transform feedback is currently active." 3081 * 3082 * We assume that this is also meant to apply to BindBuffersRange 3083 * and BindBuffersBase. 3084 */ 3085 if (tfObj->Active) { 3086 _mesa_error(ctx, GL_INVALID_OPERATION, 3087 "%s(Changing transform feedback buffers while " 3088 "transform feedback is active)", caller); 3089 return false; 3090 } 3091 3092 /* The ARB_multi_bind_spec says: 3093 * 3094 * "An INVALID_OPERATION error is generated if <first> + <count> is 3095 * greater than the number of target-specific indexed binding points, 3096 * as described in section 6.7.1." 3097 */ 3098 if (first + count > ctx->Const.MaxTransformFeedbackBuffers) { 3099 _mesa_error(ctx, GL_INVALID_OPERATION, 3100 "%s(first=%u + count=%d > the value of " 3101 "GL_MAX_TRANSFORM_FEEDBACK_BUFFERS=%u)", 3102 caller, first, count, 3103 ctx->Const.MaxTransformFeedbackBuffers); 3104 return false; 3105 } 3106 3107 return true; 3108} 3109 3110/** 3111 * Unbind all transform feedback buffers in the range 3112 * <first> through <first>+<count>-1 3113 */ 3114static void 3115unbind_xfb_buffers(struct gl_context *ctx, 3116 struct gl_transform_feedback_object *tfObj, 3117 GLuint first, GLsizei count) 3118{ 3119 struct gl_buffer_object * const bufObj = ctx->Shared->NullBufferObj; 3120 GLuint i; 3121 3122 for (i = 0; i < count; i++) 3123 _mesa_set_transform_feedback_binding(ctx, tfObj, first + i, 3124 bufObj, 0, 0); 3125} 3126 3127static void 3128bind_xfb_buffers_base(struct gl_context *ctx, 3129 GLuint first, GLsizei count, 3130 const GLuint *buffers) 3131{ 3132 struct gl_transform_feedback_object *tfObj = 3133 ctx->TransformFeedback.CurrentObject; 3134 GLuint i; 3135 3136 if (!error_check_bind_xfb_buffers(ctx, tfObj, first, count, 3137 "glBindBuffersBase")) 3138 return; 3139 3140 /* Assume that at least one binding will be changed */ 3141 FLUSH_VERTICES(ctx, 0); 3142 ctx->NewDriverState |= ctx->DriverFlags.NewTransformFeedback; 3143 3144 if (!buffers) { 3145 /* The ARB_multi_bind spec says: 3146 * 3147 * "If <buffers> is NULL, all bindings from <first> through 3148 * <first>+<count>-1 are reset to their unbound (zero) state." 3149 */ 3150 unbind_xfb_buffers(ctx, tfObj, first, count); 3151 return; 3152 } 3153 3154 /* Note that the error semantics for multi-bind commands differ from 3155 * those of other GL commands. 3156 * 3157 * The Issues section in the ARB_multi_bind spec says: 3158 * 3159 * "(11) Typically, OpenGL specifies that if an error is generated by a 3160 * command, that command has no effect. This is somewhat 3161 * unfortunate for multi-bind commands, because it would require a 3162 * first pass to scan the entire list of bound objects for errors 3163 * and then a second pass to actually perform the bindings. 3164 * Should we have different error semantics? 3165 * 3166 * RESOLVED: Yes. In this specification, when the parameters for 3167 * one of the <count> binding points are invalid, that binding point 3168 * is not updated and an error will be generated. However, other 3169 * binding points in the same command will be updated if their 3170 * parameters are valid and no other error occurs." 3171 */ 3172 3173 _mesa_begin_bufferobj_lookups(ctx); 3174 3175 for (i = 0; i < count; i++) { 3176 struct gl_buffer_object * const boundBufObj = tfObj->Buffers[first + i]; 3177 struct gl_buffer_object *bufObj; 3178 3179 if (boundBufObj && boundBufObj->Name == buffers[i]) 3180 bufObj = boundBufObj; 3181 else 3182 bufObj = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, 3183 "glBindBuffersBase"); 3184 3185 if (bufObj) 3186 _mesa_set_transform_feedback_binding(ctx, tfObj, first + i, 3187 bufObj, 0, 0); 3188 } 3189 3190 _mesa_end_bufferobj_lookups(ctx); 3191} 3192 3193static void 3194bind_xfb_buffers_range(struct gl_context *ctx, 3195 GLuint first, GLsizei count, 3196 const GLuint *buffers, 3197 const GLintptr *offsets, 3198 const GLsizeiptr *sizes) 3199{ 3200 struct gl_transform_feedback_object *tfObj = 3201 ctx->TransformFeedback.CurrentObject; 3202 GLuint i; 3203 3204 if (!error_check_bind_xfb_buffers(ctx, tfObj, first, count, 3205 "glBindBuffersRange")) 3206 return; 3207 3208 /* Assume that at least one binding will be changed */ 3209 FLUSH_VERTICES(ctx, 0); 3210 ctx->NewDriverState |= ctx->DriverFlags.NewTransformFeedback; 3211 3212 if (!buffers) { 3213 /* The ARB_multi_bind spec says: 3214 * 3215 * "If <buffers> is NULL, all bindings from <first> through 3216 * <first>+<count>-1 are reset to their unbound (zero) state. 3217 * In this case, the offsets and sizes associated with the 3218 * binding points are set to default values, ignoring 3219 * <offsets> and <sizes>." 3220 */ 3221 unbind_xfb_buffers(ctx, tfObj, first, count); 3222 return; 3223 } 3224 3225 /* Note that the error semantics for multi-bind commands differ from 3226 * those of other GL commands. 3227 * 3228 * The Issues section in the ARB_multi_bind spec says: 3229 * 3230 * "(11) Typically, OpenGL specifies that if an error is generated by a 3231 * command, that command has no effect. This is somewhat 3232 * unfortunate for multi-bind commands, because it would require a 3233 * first pass to scan the entire list of bound objects for errors 3234 * and then a second pass to actually perform the bindings. 3235 * Should we have different error semantics? 3236 * 3237 * RESOLVED: Yes. In this specification, when the parameters for 3238 * one of the <count> binding points are invalid, that binding point 3239 * is not updated and an error will be generated. However, other 3240 * binding points in the same command will be updated if their 3241 * parameters are valid and no other error occurs." 3242 */ 3243 3244 _mesa_begin_bufferobj_lookups(ctx); 3245 3246 for (i = 0; i < count; i++) { 3247 const GLuint index = first + i; 3248 struct gl_buffer_object * const boundBufObj = tfObj->Buffers[index]; 3249 struct gl_buffer_object *bufObj; 3250 3251 if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes)) 3252 continue; 3253 3254 /* The ARB_multi_bind spec says: 3255 * 3256 * "An INVALID_VALUE error is generated by BindBuffersRange if any 3257 * pair of values in <offsets> and <sizes> does not respectively 3258 * satisfy the constraints described for those parameters for the 3259 * specified target, as described in section 6.7.1 (per binding)." 3260 * 3261 * Section 6.7.1 refers to table 6.5, which says: 3262 * 3263 * "┌───────────────────────────────────────────────────────────────┐ 3264 * │ Transform feedback array bindings (see sec. 13.2.2) │ 3265 * ├───────────────────────┬───────────────────────────────────────┤ 3266 * │ ... │ ... │ 3267 * │ offset restriction │ multiple of 4 │ 3268 * │ ... │ ... │ 3269 * │ size restriction │ multiple of 4 │ 3270 * └───────────────────────┴───────────────────────────────────────┘" 3271 */ 3272 if (offsets[i] & 0x3) { 3273 _mesa_error(ctx, GL_INVALID_VALUE, 3274 "glBindBuffersRange(offsets[%u]=%" PRId64 3275 " is misaligned; it must be a multiple of 4 when " 3276 "target=GL_TRANSFORM_FEEDBACK_BUFFER)", 3277 i, (int64_t) offsets[i]); 3278 continue; 3279 } 3280 3281 if (sizes[i] & 0x3) { 3282 _mesa_error(ctx, GL_INVALID_VALUE, 3283 "glBindBuffersRange(sizes[%u]=%" PRId64 3284 " is misaligned; it must be a multiple of 4 when " 3285 "target=GL_TRANSFORM_FEEDBACK_BUFFER)", 3286 i, (int64_t) sizes[i]); 3287 continue; 3288 } 3289 3290 if (boundBufObj && boundBufObj->Name == buffers[i]) 3291 bufObj = boundBufObj; 3292 else 3293 bufObj = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, 3294 "glBindBuffersRange"); 3295 3296 if (bufObj) 3297 _mesa_set_transform_feedback_binding(ctx, tfObj, index, bufObj, 3298 offsets[i], sizes[i]); 3299 } 3300 3301 _mesa_end_bufferobj_lookups(ctx); 3302} 3303 3304static bool 3305error_check_bind_atomic_buffers(struct gl_context *ctx, 3306 GLuint first, GLsizei count, 3307 const char *caller) 3308{ 3309 if (!ctx->Extensions.ARB_shader_atomic_counters) { 3310 _mesa_error(ctx, GL_INVALID_ENUM, 3311 "%s(target=GL_ATOMIC_COUNTER_BUFFER)", caller); 3312 return false; 3313 } 3314 3315 /* The ARB_multi_bind_spec says: 3316 * 3317 * "An INVALID_OPERATION error is generated if <first> + <count> is 3318 * greater than the number of target-specific indexed binding points, 3319 * as described in section 6.7.1." 3320 */ 3321 if (first + count > ctx->Const.MaxAtomicBufferBindings) { 3322 _mesa_error(ctx, GL_INVALID_OPERATION, 3323 "%s(first=%u + count=%d > the value of " 3324 "GL_MAX_ATOMIC_BUFFER_BINDINGS=%u)", 3325 caller, first, count, ctx->Const.MaxAtomicBufferBindings); 3326 return false; 3327 } 3328 3329 return true; 3330} 3331 3332/** 3333 * Unbind all atomic counter buffers in the range 3334 * <first> through <first>+<count>-1 3335 */ 3336static void 3337unbind_atomic_buffers(struct gl_context *ctx, GLuint first, GLsizei count) 3338{ 3339 struct gl_buffer_object * const bufObj = ctx->Shared->NullBufferObj; 3340 GLuint i; 3341 3342 for (i = 0; i < count; i++) 3343 set_atomic_buffer_binding(ctx, &ctx->AtomicBufferBindings[first + i], 3344 bufObj, -1, -1); 3345} 3346 3347static void 3348bind_atomic_buffers_base(struct gl_context *ctx, 3349 GLuint first, 3350 GLsizei count, 3351 const GLuint *buffers) 3352{ 3353 GLuint i; 3354 3355 if (!error_check_bind_atomic_buffers(ctx, first, count, 3356 "glBindBuffersBase")) 3357 return; 3358 3359 /* Assume that at least one binding will be changed */ 3360 FLUSH_VERTICES(ctx, 0); 3361 ctx->NewDriverState |= ctx->DriverFlags.NewAtomicBuffer; 3362 3363 if (!buffers) { 3364 /* The ARB_multi_bind spec says: 3365 * 3366 * "If <buffers> is NULL, all bindings from <first> through 3367 * <first>+<count>-1 are reset to their unbound (zero) state." 3368 */ 3369 unbind_atomic_buffers(ctx, first, count); 3370 return; 3371 } 3372 3373 /* Note that the error semantics for multi-bind commands differ from 3374 * those of other GL commands. 3375 * 3376 * The Issues section in the ARB_multi_bind spec says: 3377 * 3378 * "(11) Typically, OpenGL specifies that if an error is generated by a 3379 * command, that command has no effect. This is somewhat 3380 * unfortunate for multi-bind commands, because it would require a 3381 * first pass to scan the entire list of bound objects for errors 3382 * and then a second pass to actually perform the bindings. 3383 * Should we have different error semantics? 3384 * 3385 * RESOLVED: Yes. In this specification, when the parameters for 3386 * one of the <count> binding points are invalid, that binding point 3387 * is not updated and an error will be generated. However, other 3388 * binding points in the same command will be updated if their 3389 * parameters are valid and no other error occurs." 3390 */ 3391 3392 _mesa_begin_bufferobj_lookups(ctx); 3393 3394 for (i = 0; i < count; i++) { 3395 struct gl_atomic_buffer_binding *binding = 3396 &ctx->AtomicBufferBindings[first + i]; 3397 struct gl_buffer_object *bufObj; 3398 3399 if (binding->BufferObject && binding->BufferObject->Name == buffers[i]) 3400 bufObj = binding->BufferObject; 3401 else 3402 bufObj = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, 3403 "glBindBuffersBase"); 3404 3405 if (bufObj) 3406 set_atomic_buffer_binding(ctx, binding, bufObj, 0, 0); 3407 } 3408 3409 _mesa_end_bufferobj_lookups(ctx); 3410} 3411 3412static void 3413bind_atomic_buffers_range(struct gl_context *ctx, 3414 GLuint first, 3415 GLsizei count, 3416 const GLuint *buffers, 3417 const GLintptr *offsets, 3418 const GLsizeiptr *sizes) 3419{ 3420 GLuint i; 3421 3422 if (!error_check_bind_atomic_buffers(ctx, first, count, 3423 "glBindBuffersRange")) 3424 return; 3425 3426 /* Assume that at least one binding will be changed */ 3427 FLUSH_VERTICES(ctx, 0); 3428 ctx->NewDriverState |= ctx->DriverFlags.NewAtomicBuffer; 3429 3430 if (!buffers) { 3431 /* The ARB_multi_bind spec says: 3432 * 3433 * "If <buffers> is NULL, all bindings from <first> through 3434 * <first>+<count>-1 are reset to their unbound (zero) state. 3435 * In this case, the offsets and sizes associated with the 3436 * binding points are set to default values, ignoring 3437 * <offsets> and <sizes>." 3438 */ 3439 unbind_atomic_buffers(ctx, first, count); 3440 return; 3441 } 3442 3443 /* Note that the error semantics for multi-bind commands differ from 3444 * those of other GL commands. 3445 * 3446 * The Issues section in the ARB_multi_bind spec says: 3447 * 3448 * "(11) Typically, OpenGL specifies that if an error is generated by a 3449 * command, that command has no effect. This is somewhat 3450 * unfortunate for multi-bind commands, because it would require a 3451 * first pass to scan the entire list of bound objects for errors 3452 * and then a second pass to actually perform the bindings. 3453 * Should we have different error semantics? 3454 * 3455 * RESOLVED: Yes. In this specification, when the parameters for 3456 * one of the <count> binding points are invalid, that binding point 3457 * is not updated and an error will be generated. However, other 3458 * binding points in the same command will be updated if their 3459 * parameters are valid and no other error occurs." 3460 */ 3461 3462 _mesa_begin_bufferobj_lookups(ctx); 3463 3464 for (i = 0; i < count; i++) { 3465 struct gl_atomic_buffer_binding *binding = 3466 &ctx->AtomicBufferBindings[first + i]; 3467 struct gl_buffer_object *bufObj; 3468 3469 if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes)) 3470 continue; 3471 3472 /* The ARB_multi_bind spec says: 3473 * 3474 * "An INVALID_VALUE error is generated by BindBuffersRange if any 3475 * pair of values in <offsets> and <sizes> does not respectively 3476 * satisfy the constraints described for those parameters for the 3477 * specified target, as described in section 6.7.1 (per binding)." 3478 * 3479 * Section 6.7.1 refers to table 6.5, which says: 3480 * 3481 * "┌───────────────────────────────────────────────────────────────┐ 3482 * │ Atomic counter array bindings (see sec. 7.7.2) │ 3483 * ├───────────────────────┬───────────────────────────────────────┤ 3484 * │ ... │ ... │ 3485 * │ offset restriction │ multiple of 4 │ 3486 * │ ... │ ... │ 3487 * │ size restriction │ none │ 3488 * └───────────────────────┴───────────────────────────────────────┘" 3489 */ 3490 if (offsets[i] & (ATOMIC_COUNTER_SIZE - 1)) { 3491 _mesa_error(ctx, GL_INVALID_VALUE, 3492 "glBindBuffersRange(offsets[%u]=%" PRId64 3493 " is misaligned; it must be a multiple of %d when " 3494 "target=GL_ATOMIC_COUNTER_BUFFER)", 3495 i, (int64_t) offsets[i], ATOMIC_COUNTER_SIZE); 3496 continue; 3497 } 3498 3499 if (binding->BufferObject && binding->BufferObject->Name == buffers[i]) 3500 bufObj = binding->BufferObject; 3501 else 3502 bufObj = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, 3503 "glBindBuffersRange"); 3504 3505 if (bufObj) 3506 set_atomic_buffer_binding(ctx, binding, bufObj, offsets[i], sizes[i]); 3507 } 3508 3509 _mesa_end_bufferobj_lookups(ctx); 3510} 3511 3512void GLAPIENTRY 3513_mesa_BindBufferRange(GLenum target, GLuint index, 3514 GLuint buffer, GLintptr offset, GLsizeiptr size) 3515{ 3516 GET_CURRENT_CONTEXT(ctx); 3517 struct gl_buffer_object *bufObj; 3518 3519 if (buffer == 0) { 3520 bufObj = ctx->Shared->NullBufferObj; 3521 } else { 3522 bufObj = _mesa_lookup_bufferobj(ctx, buffer); 3523 } 3524 if (!_mesa_handle_bind_buffer_gen(ctx, target, buffer, 3525 &bufObj, "glBindBufferRange")) 3526 return; 3527 3528 if (!bufObj) { 3529 _mesa_error(ctx, GL_INVALID_OPERATION, 3530 "glBindBufferRange(invalid buffer=%u)", buffer); 3531 return; 3532 } 3533 3534 if (buffer != 0) { 3535 if (size <= 0) { 3536 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size=%d)", 3537 (int) size); 3538 return; 3539 } 3540 } 3541 3542 switch (target) { 3543 case GL_TRANSFORM_FEEDBACK_BUFFER: 3544 _mesa_bind_buffer_range_transform_feedback(ctx, index, bufObj, 3545 offset, size); 3546 return; 3547 case GL_UNIFORM_BUFFER: 3548 bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size); 3549 return; 3550 case GL_ATOMIC_COUNTER_BUFFER: 3551 bind_atomic_buffer(ctx, index, bufObj, offset, size, 3552 "glBindBufferRange"); 3553 return; 3554 default: 3555 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferRange(target)"); 3556 return; 3557 } 3558} 3559 3560void GLAPIENTRY 3561_mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer) 3562{ 3563 GET_CURRENT_CONTEXT(ctx); 3564 struct gl_buffer_object *bufObj; 3565 3566 if (buffer == 0) { 3567 bufObj = ctx->Shared->NullBufferObj; 3568 } else { 3569 bufObj = _mesa_lookup_bufferobj(ctx, buffer); 3570 } 3571 if (!_mesa_handle_bind_buffer_gen(ctx, target, buffer, 3572 &bufObj, "glBindBufferBase")) 3573 return; 3574 3575 if (!bufObj) { 3576 _mesa_error(ctx, GL_INVALID_OPERATION, 3577 "glBindBufferBase(invalid buffer=%u)", buffer); 3578 return; 3579 } 3580 3581 /* Note that there's some oddness in the GL 3.1-GL 3.3 specifications with 3582 * regards to BindBufferBase. It says (GL 3.1 core spec, page 63): 3583 * 3584 * "BindBufferBase is equivalent to calling BindBufferRange with offset 3585 * zero and size equal to the size of buffer." 3586 * 3587 * but it says for glGetIntegeri_v (GL 3.1 core spec, page 230): 3588 * 3589 * "If the parameter (starting offset or size) was not specified when the 3590 * buffer object was bound, zero is returned." 3591 * 3592 * What happens if the size of the buffer changes? Does the size of the 3593 * buffer at the moment glBindBufferBase was called still play a role, like 3594 * the first quote would imply, or is the size meaningless in the 3595 * glBindBufferBase case like the second quote would suggest? The GL 4.1 3596 * core spec page 45 says: 3597 * 3598 * "It is equivalent to calling BindBufferRange with offset zero, while 3599 * size is determined by the size of the bound buffer at the time the 3600 * binding is used." 3601 * 3602 * My interpretation is that the GL 4.1 spec was a clarification of the 3603 * behavior, not a change. In particular, this choice will only make 3604 * rendering work in cases where it would have had undefined results. 3605 */ 3606 3607 switch (target) { 3608 case GL_TRANSFORM_FEEDBACK_BUFFER: 3609 _mesa_bind_buffer_base_transform_feedback(ctx, index, bufObj); 3610 return; 3611 case GL_UNIFORM_BUFFER: 3612 bind_buffer_base_uniform_buffer(ctx, index, bufObj); 3613 return; 3614 case GL_ATOMIC_COUNTER_BUFFER: 3615 bind_atomic_buffer(ctx, index, bufObj, 0, 0, 3616 "glBindBufferBase"); 3617 return; 3618 default: 3619 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferBase(target)"); 3620 return; 3621 } 3622} 3623 3624void GLAPIENTRY 3625_mesa_BindBuffersRange(GLenum target, GLuint first, GLsizei count, 3626 const GLuint *buffers, 3627 const GLintptr *offsets, const GLsizeiptr *sizes) 3628{ 3629 GET_CURRENT_CONTEXT(ctx); 3630 3631 switch (target) { 3632 case GL_TRANSFORM_FEEDBACK_BUFFER: 3633 bind_xfb_buffers_range(ctx, first, count, buffers, offsets, sizes); 3634 return; 3635 case GL_UNIFORM_BUFFER: 3636 bind_uniform_buffers_range(ctx, first, count, buffers, offsets, sizes); 3637 return; 3638 case GL_ATOMIC_COUNTER_BUFFER: 3639 bind_atomic_buffers_range(ctx, first, count, buffers, 3640 offsets, sizes); 3641 return; 3642 default: 3643 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBuffersRange(target=%s)", 3644 _mesa_lookup_enum_by_nr(target)); 3645 break; 3646 } 3647} 3648 3649void GLAPIENTRY 3650_mesa_BindBuffersBase(GLenum target, GLuint first, GLsizei count, 3651 const GLuint *buffers) 3652{ 3653 GET_CURRENT_CONTEXT(ctx); 3654 3655 switch (target) { 3656 case GL_TRANSFORM_FEEDBACK_BUFFER: 3657 bind_xfb_buffers_base(ctx, first, count, buffers); 3658 return; 3659 case GL_UNIFORM_BUFFER: 3660 bind_uniform_buffers_base(ctx, first, count, buffers); 3661 return; 3662 case GL_ATOMIC_COUNTER_BUFFER: 3663 bind_atomic_buffers_base(ctx, first, count, buffers); 3664 return; 3665 default: 3666 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBuffersBase(target=%s)", 3667 _mesa_lookup_enum_by_nr(target)); 3668 break; 3669 } 3670} 3671 3672void GLAPIENTRY 3673_mesa_InvalidateBufferSubData(GLuint buffer, GLintptr offset, 3674 GLsizeiptr length) 3675{ 3676 GET_CURRENT_CONTEXT(ctx); 3677 struct gl_buffer_object *bufObj; 3678 const GLintptr end = offset + length; 3679 3680 bufObj = _mesa_lookup_bufferobj(ctx, buffer); 3681 if (!bufObj) { 3682 _mesa_error(ctx, GL_INVALID_VALUE, 3683 "glInvalidateBufferSubData(name = 0x%x) invalid object", 3684 buffer); 3685 return; 3686 } 3687 3688 /* The GL_ARB_invalidate_subdata spec says: 3689 * 3690 * "An INVALID_VALUE error is generated if <offset> or <length> is 3691 * negative, or if <offset> + <length> is greater than the value of 3692 * BUFFER_SIZE." 3693 */ 3694 if (end < 0 || end > bufObj->Size) { 3695 _mesa_error(ctx, GL_INVALID_VALUE, 3696 "glInvalidateBufferSubData(invalid offset or length)"); 3697 return; 3698 } 3699 3700 /* The OpenGL 4.4 (Core Profile) spec says: 3701 * 3702 * "An INVALID_OPERATION error is generated if buffer is currently 3703 * mapped by MapBuffer or if the invalidate range intersects the range 3704 * currently mapped by MapBufferRange, unless it was mapped 3705 * with MAP_PERSISTENT_BIT set in the MapBufferRange access flags." 3706 */ 3707 if (!(bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_PERSISTENT_BIT) && 3708 bufferobj_range_mapped(bufObj, offset, length)) { 3709 _mesa_error(ctx, GL_INVALID_OPERATION, 3710 "glInvalidateBufferSubData(intersection with mapped " 3711 "range)"); 3712 return; 3713 } 3714 3715 /* We don't actually do anything for this yet. Just return after 3716 * validating the parameters and generating the required errors. 3717 */ 3718 return; 3719} 3720 3721void GLAPIENTRY 3722_mesa_InvalidateBufferData(GLuint buffer) 3723{ 3724 GET_CURRENT_CONTEXT(ctx); 3725 struct gl_buffer_object *bufObj; 3726 3727 bufObj = _mesa_lookup_bufferobj(ctx, buffer); 3728 if (!bufObj) { 3729 _mesa_error(ctx, GL_INVALID_VALUE, 3730 "glInvalidateBufferData(name = 0x%x) invalid object", 3731 buffer); 3732 return; 3733 } 3734 3735 /* The OpenGL 4.4 (Core Profile) spec says: 3736 * 3737 * "An INVALID_OPERATION error is generated if buffer is currently 3738 * mapped by MapBuffer or if the invalidate range intersects the range 3739 * currently mapped by MapBufferRange, unless it was mapped 3740 * with MAP_PERSISTENT_BIT set in the MapBufferRange access flags." 3741 */ 3742 if (_mesa_check_disallowed_mapping(bufObj)) { 3743 _mesa_error(ctx, GL_INVALID_OPERATION, 3744 "glInvalidateBufferData(intersection with mapped " 3745 "range)"); 3746 return; 3747 } 3748 3749 /* We don't actually do anything for this yet. Just return after 3750 * validating the parameters and generating the required errors. 3751 */ 3752 return; 3753} 3754