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