* \sa glBufferGetSubDataARB, dd_function_table::GetBufferSubData.
*/
static void
-_mesa_buffer_get_subdata( struct gl_context *ctx, GLintptrARB offset,
- GLsizeiptrARB size, GLvoid * data,
- struct gl_buffer_object * bufObj )
+buffer_get_subdata(struct gl_context *ctx, GLintptrARB offset,
+ GLsizeiptrARB size, GLvoid *data,
+ struct gl_buffer_object *bufObj )
{
(void) ctx;
driver->DeleteBuffer = _mesa_delete_buffer_object;
driver->BufferData = buffer_data_fallback;
driver->BufferSubData = buffer_sub_data_fallback;
- driver->GetBufferSubData = _mesa_buffer_get_subdata;
+ driver->GetBufferSubData = buffer_get_subdata;
driver->UnmapBuffer = unmap_buffer_fallback;
/* GL_ARB_clear_buffer_object */
_mesa_buffer_unmap_all_mappings(struct gl_context *ctx,
struct gl_buffer_object *bufObj)
{
- int i;
-
- for (i = 0; i < MAP_COUNT; i++) {
+ for (int i = 0; i < MAP_COUNT; i++) {
if (_mesa_bufferobj_mapped(bufObj, i)) {
ctx->Driver.UnmapBuffer(ctx, bufObj, i);
assert(bufObj->Mappings[i].Pointer == NULL);
/* API Functions */
/**********************************************************************/
+void GLAPIENTRY
+_mesa_BindBuffer_no_error(GLenum target, GLuint buffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ struct gl_buffer_object **bindTarget = get_buffer_target(ctx, target);
+ bind_buffer_object(ctx, bindTarget, buffer);
+}
+
+
void GLAPIENTRY
_mesa_BindBuffer(GLenum target, GLuint buffer)
{
{
GET_CURRENT_CONTEXT(ctx);
GLuint first;
- GLint i;
struct gl_buffer_object *buf;
const char *func = dsa ? "glCreateBuffers" : "glGenBuffers";
* DummyBufferObject. Otherwise, create a new buffer object and insert
* it.
*/
- for (i = 0; i < n; i++) {
+ for (int i = 0; i < n; i++) {
buffers[i] = first + i;
if (dsa) {
assert(ctx->Driver.NewBufferObject);
}
-void
-_mesa_buffer_storage(struct gl_context *ctx, struct gl_buffer_object *bufObj,
- GLenum target, GLsizeiptr size, const GLvoid *data,
- GLbitfield flags, const char *func)
+static bool
+validate_buffer_storage(struct gl_context *ctx,
+ struct gl_buffer_object *bufObj, GLsizeiptr size,
+ GLbitfield flags, const char *func)
{
if (size <= 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "%s(size <= 0)", func);
- return;
+ return false;
}
GLbitfield valid_flags = GL_MAP_READ_BIT |
if (flags & ~valid_flags) {
_mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid flag bits set)", func);
- return;
+ return false;
}
/* The Errors section of the GL_ARB_sparse_buffer spec says:
if (flags & GL_SPARSE_STORAGE_BIT_ARB &&
flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) {
_mesa_error(ctx, GL_INVALID_VALUE, "%s(SPARSE_STORAGE and READ/WRITE)", func);
- return;
+ return false;
}
if (flags & GL_MAP_PERSISTENT_BIT &&
!(flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT))) {
_mesa_error(ctx, GL_INVALID_VALUE,
"%s(PERSISTENT and flags!=READ/WRITE)", func);
- return;
+ return false;
}
if (flags & GL_MAP_COHERENT_BIT && !(flags & GL_MAP_PERSISTENT_BIT)) {
_mesa_error(ctx, GL_INVALID_VALUE,
"%s(COHERENT and flags!=PERSISTENT)", func);
- return;
+ return false;
}
- if (bufObj->Immutable) {
+ if (bufObj->Immutable || bufObj->HandleAllocated) {
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func);
- return;
+ return false;
}
+ return true;
+}
+
+
+static void
+buffer_storage(struct gl_context *ctx, struct gl_buffer_object *bufObj,
+ GLenum target, GLsizeiptr size, const GLvoid *data,
+ GLbitfield flags, const char *func)
+{
/* Unmap the existing buffer. We'll replace it now. Not an error. */
_mesa_buffer_unmap_all_mappings(ctx, bufObj);
- FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT);
+ FLUSH_VERTICES(ctx, 0);
bufObj->Written = GL_TRUE;
bufObj->Immutable = GL_TRUE;
}
}
+
+static ALWAYS_INLINE void
+inlined_buffer_storage(GLenum target, GLuint buffer, GLsizeiptr size,
+ const GLvoid *data, GLbitfield flags, bool dsa,
+ bool no_error, const char *func)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+
+ if (dsa) {
+ if (no_error) {
+ bufObj = _mesa_lookup_bufferobj(ctx, buffer);
+ } else {
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, func);
+ if (!bufObj)
+ return;
+ }
+ } else {
+ if (no_error) {
+ struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target);
+ bufObj = *bufObjPtr;
+ } else {
+ bufObj = get_buffer(ctx, func, target, GL_INVALID_OPERATION);
+ if (!bufObj)
+ return;
+ }
+ }
+
+ if (no_error || validate_buffer_storage(ctx, bufObj, size, flags, func))
+ buffer_storage(ctx, bufObj, target, size, data, flags, func);
+}
+
+
+void GLAPIENTRY
+_mesa_BufferStorage_no_error(GLenum target, GLsizeiptr size,
+ const GLvoid *data, GLbitfield flags)
+{
+ inlined_buffer_storage(target, 0, size, data, flags, false, true,
+ "glBufferStorage");
+}
+
+
void GLAPIENTRY
_mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data,
GLbitfield flags)
{
- GET_CURRENT_CONTEXT(ctx);
- struct gl_buffer_object *bufObj;
+ inlined_buffer_storage(target, 0, size, data, flags, false, false,
+ "glBufferStorage");
+}
- bufObj = get_buffer(ctx, "glBufferStorage", target, GL_INVALID_OPERATION);
- if (!bufObj)
- return;
- _mesa_buffer_storage(ctx, bufObj, target, size, data, flags,
- "glBufferStorage");
+void GLAPIENTRY
+_mesa_NamedBufferStorage_no_error(GLuint buffer, GLsizeiptr size,
+ const GLvoid *data, GLbitfield flags)
+{
+ /* In direct state access, buffer objects have an unspecified target
+ * since they are not required to be bound.
+ */
+ inlined_buffer_storage(GL_NONE, buffer, size, data, flags, true, true,
+ "glNamedBufferStorage");
}
+
void GLAPIENTRY
_mesa_NamedBufferStorage(GLuint buffer, GLsizeiptr size, const GLvoid *data,
GLbitfield flags)
{
- GET_CURRENT_CONTEXT(ctx);
- struct gl_buffer_object *bufObj;
-
- bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferStorage");
- if (!bufObj)
- return;
-
- /*
- * In direct state access, buffer objects have an unspecified target since
- * they are not required to be bound.
+ /* In direct state access, buffer objects have an unspecified target
+ * since they are not required to be bound.
*/
- _mesa_buffer_storage(ctx, bufObj, GL_NONE, size, data, flags,
- "glNamedBufferStorage");
+ inlined_buffer_storage(GL_NONE, buffer, size, data, flags, true, false,
+ "glNamedBufferStorage");
}
return;
}
- if (bufObj->Immutable) {
+ if (bufObj->Immutable || bufObj->HandleAllocated) {
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func);
return;
}
/* Unmap the existing buffer. We'll replace it now. Not an error. */
_mesa_buffer_unmap_all_mappings(ctx, bufObj);
- FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT);
+ FLUSH_VERTICES(ctx, 0);
bufObj->Written = GL_TRUE;
bufObj->MinMaxCacheDirty = true;
}
-/**
- * Implementation for glBufferSubData and glNamedBufferSubData.
- *
- * \param ctx GL context.
- * \param bufObj The buffer object.
- * \param offset Offset of the first byte of the subdata range.
- * \param size Size, in bytes, of the subdata range.
- * \param data The data store.
- * \param func Name of calling function for recording errors.
- *
- */
-void
-_mesa_buffer_sub_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
- GLintptr offset, GLsizeiptr size, const GLvoid *data,
- const char *func)
+static bool
+validate_buffer_sub_data(struct gl_context *ctx,
+ struct gl_buffer_object *bufObj,
+ GLintptr offset, GLsizeiptr size,
+ const char *func)
{
if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size,
true, func)) {
/* error already recorded */
- return;
+ return false;
}
if (bufObj->Immutable &&
!(bufObj->StorageFlags & GL_DYNAMIC_STORAGE_BIT)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
- return;
+ return false;
}
- if (size == 0)
- return;
-
- bufObj->NumSubDataCalls++;
-
if ((bufObj->Usage == GL_STATIC_DRAW ||
bufObj->Usage == GL_STATIC_COPY) &&
- bufObj->NumSubDataCalls >= BUFFER_WARNING_CALL_COUNT) {
+ bufObj->NumSubDataCalls >= BUFFER_WARNING_CALL_COUNT - 1) {
/* If the application declared the buffer as static draw/copy or stream
* draw, it should not be frequently modified with glBufferSubData.
*/
_mesa_enum_to_string(bufObj->Usage));
}
+ return true;
+}
+
+
+/**
+ * Implementation for glBufferSubData and glNamedBufferSubData.
+ *
+ * \param ctx GL context.
+ * \param bufObj The buffer object.
+ * \param offset Offset of the first byte of the subdata range.
+ * \param size Size, in bytes, of the subdata range.
+ * \param data The data store.
+ * \param func Name of calling function for recording errors.
+ *
+ */
+void
+_mesa_buffer_sub_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
+ GLintptr offset, GLsizeiptr size, const GLvoid *data)
+{
+ if (size == 0)
+ return;
+
+ bufObj->NumSubDataCalls++;
bufObj->Written = GL_TRUE;
bufObj->MinMaxCacheDirty = true;
ctx->Driver.BufferSubData(ctx, offset, size, data, bufObj);
}
-void GLAPIENTRY
-_mesa_BufferSubData(GLenum target, GLintptr offset,
- GLsizeiptr size, const GLvoid *data)
+
+static ALWAYS_INLINE void
+buffer_sub_data(GLenum target, GLuint buffer, GLintptr offset,
+ GLsizeiptr size, const GLvoid *data,
+ bool dsa, bool no_error, const char *func)
{
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
- bufObj = get_buffer(ctx, "glBufferSubData", target, GL_INVALID_OPERATION);
- if (!bufObj)
- return;
+ if (dsa) {
+ if (no_error) {
+ bufObj = _mesa_lookup_bufferobj(ctx, buffer);
+ } else {
+ bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, func);
+ if (!bufObj)
+ return;
+ }
+ } else {
+ if (no_error) {
+ struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target);
+ bufObj = *bufObjPtr;
+ } else {
+ bufObj = get_buffer(ctx, func, target, GL_INVALID_OPERATION);
+ if (!bufObj)
+ return;
+ }
+ }
- _mesa_buffer_sub_data(ctx, bufObj, offset, size, data, "glBufferSubData");
+ if (no_error || validate_buffer_sub_data(ctx, bufObj, offset, size, func))
+ _mesa_buffer_sub_data(ctx, bufObj, offset, size, data);
}
+
void GLAPIENTRY
-_mesa_NamedBufferSubData(GLuint buffer, GLintptr offset,
- GLsizeiptr size, const GLvoid *data)
+_mesa_BufferSubData_no_error(GLenum target, GLintptr offset,
+ GLsizeiptr size, const GLvoid *data)
{
- GET_CURRENT_CONTEXT(ctx);
- struct gl_buffer_object *bufObj;
+ buffer_sub_data(target, 0, offset, size, data, false, true,
+ "glBufferSubData");
+}
- bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferSubData");
- if (!bufObj)
- return;
- _mesa_buffer_sub_data(ctx, bufObj, offset, size, data,
- "glNamedBufferSubData");
+void GLAPIENTRY
+_mesa_BufferSubData(GLenum target, GLintptr offset,
+ GLsizeiptr size, const GLvoid *data)
+{
+ buffer_sub_data(target, 0, offset, size, data, false, false,
+ "glBufferSubData");
+}
+
+void GLAPIENTRY
+_mesa_NamedBufferSubData_no_error(GLuint buffer, GLintptr offset,
+ GLsizeiptr size, const GLvoid *data)
+{
+ buffer_sub_data(0, buffer, offset, size, data, true, true,
+ "glNamedBufferSubData");
+}
+
+void GLAPIENTRY
+_mesa_NamedBufferSubData(GLuint buffer, GLintptr offset,
+ GLsizeiptr size, const GLvoid *data)
+{
+ buffer_sub_data(0, buffer, offset, size, data, true, false,
+ "glNamedBufferSubData");
}
/**
* \param subdata true if caller is *SubData, false if *Data
*/
-void
-_mesa_clear_buffer_sub_data(struct gl_context *ctx,
- struct gl_buffer_object *bufObj,
- GLenum internalformat,
- GLintptr offset, GLsizeiptr size,
- GLenum format, GLenum type,
- const GLvoid *data,
- const char *func, bool subdata)
+static void
+clear_buffer_sub_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
+ GLenum internalformat, GLintptr offset, GLsizeiptr size,
+ GLenum format, GLenum type, const GLvoid *data,
+ const char *func, bool subdata)
{
mesa_format mesaFormat;
GLubyte clearValue[MAX_PIXEL_BYTES];
if (!bufObj)
return;
- _mesa_clear_buffer_sub_data(ctx, bufObj, internalformat, 0, bufObj->Size,
- format, type, data,
- "glClearBufferData", false);
+ clear_buffer_sub_data(ctx, bufObj, internalformat, 0, bufObj->Size,
+ format, type, data, "glClearBufferData", false);
}
void GLAPIENTRY
if (!bufObj)
return;
- _mesa_clear_buffer_sub_data(ctx, bufObj, internalformat, 0, bufObj->Size,
- format, type, data,
- "glClearNamedBufferData", false);
+ clear_buffer_sub_data(ctx, bufObj, internalformat, 0, bufObj->Size,
+ format, type, data, "glClearNamedBufferData", false);
}
if (!bufObj)
return;
- _mesa_clear_buffer_sub_data(ctx, bufObj, internalformat, offset, size,
- format, type, data,
- "glClearBufferSubData", true);
+ clear_buffer_sub_data(ctx, bufObj, internalformat, offset, size,
+ format, type, data, "glClearBufferSubData", true);
}
void GLAPIENTRY
if (!bufObj)
return;
- _mesa_clear_buffer_sub_data(ctx, bufObj, internalformat, offset, size,
- format, type, data,
- "glClearNamedBufferSubData", true);
+ clear_buffer_sub_data(ctx, bufObj, internalformat, offset, size, format,
+ type, data, "glClearNamedBufferSubData", true);
}
+static GLboolean
+unmap_buffer(struct gl_context *ctx, struct gl_buffer_object *bufObj)
+{
+ GLboolean status = ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_USER);
+ bufObj->Mappings[MAP_USER].AccessFlags = 0;
+ assert(bufObj->Mappings[MAP_USER].Pointer == NULL);
+ assert(bufObj->Mappings[MAP_USER].Offset == 0);
+ assert(bufObj->Mappings[MAP_USER].Length == 0);
+
+ return status;
+}
-GLboolean
-_mesa_unmap_buffer(struct gl_context *ctx, struct gl_buffer_object *bufObj,
- const char *func)
+static GLboolean
+validate_and_unmap_buffer(struct gl_context *ctx,
+ struct gl_buffer_object *bufObj,
+ const char *func)
{
- GLboolean status = GL_TRUE;
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
}
#endif
- status = ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_USER);
- bufObj->Mappings[MAP_USER].AccessFlags = 0;
- assert(bufObj->Mappings[MAP_USER].Pointer == NULL);
- assert(bufObj->Mappings[MAP_USER].Offset == 0);
- assert(bufObj->Mappings[MAP_USER].Length == 0);
+ return unmap_buffer(ctx, bufObj);
+}
- return status;
+GLboolean GLAPIENTRY
+_mesa_UnmapBuffer_no_error(GLenum target)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target);
+ struct gl_buffer_object *bufObj = *bufObjPtr;
+
+ return unmap_buffer(ctx, bufObj);
}
GLboolean GLAPIENTRY
if (!bufObj)
return GL_FALSE;
- return _mesa_unmap_buffer(ctx, bufObj, "glUnmapBuffer");
+ return validate_and_unmap_buffer(ctx, bufObj, "glUnmapBuffer");
+}
+
+GLboolean GLAPIENTRY
+_mesa_UnmapNamedBuffer_no_error(GLuint buffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
+
+ return unmap_buffer(ctx, bufObj);
}
GLboolean GLAPIENTRY
if (!bufObj)
return GL_FALSE;
- return _mesa_unmap_buffer(ctx, bufObj, "glUnmapNamedBuffer");
+ return validate_and_unmap_buffer(ctx, bufObj, "glUnmapNamedBuffer");
}
}
-void
-_mesa_copy_buffer_sub_data(struct gl_context *ctx,
- struct gl_buffer_object *src,
- struct gl_buffer_object *dst,
- GLintptr readOffset, GLintptr writeOffset,
- GLsizeiptr size, const char *func)
+static void
+copy_buffer_sub_data(struct gl_context *ctx, struct gl_buffer_object *src,
+ struct gl_buffer_object *dst, GLintptr readOffset,
+ GLintptr writeOffset, GLsizeiptr size, const char *func)
{
if (_mesa_check_disallowed_mapping(src)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset, size);
}
+void GLAPIENTRY
+_mesa_CopyBufferSubData_no_error(GLenum readTarget, GLenum writeTarget,
+ GLintptr readOffset, GLintptr writeOffset,
+ GLsizeiptr size)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ struct gl_buffer_object **src_ptr = get_buffer_target(ctx, readTarget);
+ struct gl_buffer_object *src = *src_ptr;
+
+ struct gl_buffer_object **dst_ptr = get_buffer_target(ctx, writeTarget);
+ struct gl_buffer_object *dst = *dst_ptr;
+
+ dst->MinMaxCacheDirty = true;
+ ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset,
+ size);
+}
+
void GLAPIENTRY
_mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
GLintptr readOffset, GLintptr writeOffset,
if (!dst)
return;
- _mesa_copy_buffer_sub_data(ctx, src, dst, readOffset, writeOffset, size,
- "glCopyBufferSubData");
+ copy_buffer_sub_data(ctx, src, dst, readOffset, writeOffset, size,
+ "glCopyBufferSubData");
+}
+
+void GLAPIENTRY
+_mesa_CopyNamedBufferSubData_no_error(GLuint readBuffer, GLuint writeBuffer,
+ GLintptr readOffset,
+ GLintptr writeOffset, GLsizeiptr size)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ struct gl_buffer_object *src = _mesa_lookup_bufferobj(ctx, readBuffer);
+ struct gl_buffer_object *dst = _mesa_lookup_bufferobj(ctx, writeBuffer);
+
+ dst->MinMaxCacheDirty = true;
+ ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset,
+ size);
}
void GLAPIENTRY
if (!dst)
return;
- _mesa_copy_buffer_sub_data(ctx, src, dst, readOffset, writeOffset, size,
- "glCopyNamedBufferSubData");
+ copy_buffer_sub_data(ctx, src, dst, readOffset, writeOffset, size,
+ "glCopyNamedBufferSubData");
}
-
-static void *
-map_buffer_range(struct gl_context *ctx, struct gl_buffer_object *bufObj,
- GLintptr offset, GLsizeiptr length, GLbitfield access,
- const char *func)
+static bool
+validate_map_buffer_range(struct gl_context *ctx,
+ struct gl_buffer_object *bufObj, GLintptr offset,
+ GLsizeiptr length, GLbitfield access,
+ const char *func)
{
- void *map;
GLbitfield allowed_access;
- ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, false);
if (offset < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
"%s(offset %ld < 0)", func, (long) offset);
- return NULL;
+ return false;
}
if (length < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
"%s(length %ld < 0)", func, (long) length);
- return NULL;
+ return false;
}
/* Page 38 of the PDF of the OpenGL ES 3.0 spec says:
*/
if (length == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(length = 0)", func);
- return NULL;
+ return false;
}
allowed_access = GL_MAP_READ_BIT |
/* generate an error if any bits other than those allowed are set */
_mesa_error(ctx, GL_INVALID_VALUE,
"%s(access has undefined bits set)", func);
- return NULL;
+ return false;
}
if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(access indicates neither read or write)", func);
- return NULL;
+ return false;
}
if ((access & GL_MAP_READ_BIT) &&
GL_MAP_UNSYNCHRONIZED_BIT))) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(read access with disallowed bits)", func);
- return NULL;
+ return false;
}
if ((access & GL_MAP_FLUSH_EXPLICIT_BIT) &&
((access & GL_MAP_WRITE_BIT) == 0)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(access has flush explicit without write)", func);
- return NULL;
+ return false;
}
if (access & GL_MAP_READ_BIT &&
!(bufObj->StorageFlags & GL_MAP_READ_BIT)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(buffer does not allow read access)", func);
- return NULL;
+ return false;
}
if (access & GL_MAP_WRITE_BIT &&
!(bufObj->StorageFlags & GL_MAP_WRITE_BIT)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(buffer does not allow write access)", func);
- return NULL;
+ return false;
}
if (access & GL_MAP_COHERENT_BIT &&
!(bufObj->StorageFlags & GL_MAP_COHERENT_BIT)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(buffer does not allow coherent access)", func);
- return NULL;
+ return false;
}
if (access & GL_MAP_PERSISTENT_BIT &&
!(bufObj->StorageFlags & GL_MAP_PERSISTENT_BIT)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(buffer does not allow persistent access)", func);
- return NULL;
+ return false;
}
if (offset + length > bufObj->Size) {
"%s(offset %lu + length %lu > buffer_size %lu)", func,
(unsigned long) offset, (unsigned long) length,
(unsigned long) bufObj->Size);
- return NULL;
+ return false;
}
if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(buffer already mapped)", func);
- return NULL;
- }
-
- if (!bufObj->Size) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(buffer size = 0)", func);
- return NULL;
+ return false;
}
if (access & GL_MAP_WRITE_BIT) {
}
}
+ return true;
+}
+
+static void *
+map_buffer_range(struct gl_context *ctx, struct gl_buffer_object *bufObj,
+ GLintptr offset, GLsizeiptr length, GLbitfield access,
+ const char *func)
+{
+ if (!bufObj->Size) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(buffer size = 0)", func);
+ return NULL;
+ }
+
assert(ctx->Driver.MapBufferRange);
- map = ctx->Driver.MapBufferRange(ctx, offset, length, access, bufObj,
- MAP_USER);
+ void *map = ctx->Driver.MapBufferRange(ctx, offset, length, access, bufObj,
+ MAP_USER);
if (!map) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(map failed)", func);
}
return map;
}
+void * GLAPIENTRY
+_mesa_MapBufferRange_no_error(GLenum target, GLintptr offset,
+ GLsizeiptr length, GLbitfield access)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target);
+ struct gl_buffer_object *bufObj = *bufObjPtr;
+
+ return map_buffer_range(ctx, bufObj, offset, length, access,
+ "glMapBufferRange");
+}
+
void * GLAPIENTRY
_mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
GLbitfield access)
if (!bufObj)
return NULL;
+ if (!validate_map_buffer_range(ctx, bufObj, offset, length, access,
+ "glMapBufferRange"))
+ return NULL;
+
return map_buffer_range(ctx, bufObj, offset, length, access,
"glMapBufferRange");
}
+void * GLAPIENTRY
+_mesa_MapNamedBufferRange_no_error(GLuint buffer, GLintptr offset,
+ GLsizeiptr length, GLbitfield access)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
+
+ return map_buffer_range(ctx, bufObj, offset, length, access,
+ "glMapNamedBufferRange");
+}
+
void * GLAPIENTRY
_mesa_MapNamedBufferRange(GLuint buffer, GLintptr offset, GLsizeiptr length,
GLbitfield access)
if (!bufObj)
return NULL;
+ if (!validate_map_buffer_range(ctx, bufObj, offset, length, access,
+ "glMapNamedBufferRange"))
+ return NULL;
+
return map_buffer_range(ctx, bufObj, offset, length, access,
"glMapNamedBufferRange");
}
}
}
+void * GLAPIENTRY
+_mesa_MapBuffer_no_error(GLenum target, GLenum access)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ GLbitfield accessFlags;
+ get_map_buffer_access_flags(ctx, access, &accessFlags);
+
+ struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target);
+ struct gl_buffer_object *bufObj = *bufObjPtr;
+
+ return map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
+ "glMapBuffer");
+}
+
void * GLAPIENTRY
_mesa_MapBuffer(GLenum target, GLenum access)
{
if (!bufObj)
return NULL;
+ if (!validate_map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
+ "glMapBuffer"))
+ return NULL;
+
return map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
"glMapBuffer");
}
+void * GLAPIENTRY
+_mesa_MapNamedBuffer_no_error(GLuint buffer, GLenum access)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ GLbitfield accessFlags;
+ get_map_buffer_access_flags(ctx, access, &accessFlags);
+
+ struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
+
+ return map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
+ "glMapNamedBuffer");
+}
+
void * GLAPIENTRY
_mesa_MapNamedBuffer(GLuint buffer, GLenum access)
{
if (!bufObj)
return NULL;
+ if (!validate_map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
+ "glMapNamedBuffer"))
+ return NULL;
+
return map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
"glMapNamedBuffer");
}
-void
-_mesa_flush_mapped_buffer_range(struct gl_context *ctx,
- struct gl_buffer_object *bufObj,
- GLintptr offset, GLsizeiptr length,
- const char *func)
+static void
+flush_mapped_buffer_range(struct gl_context *ctx,
+ struct gl_buffer_object *bufObj,
+ GLintptr offset, GLsizeiptr length,
+ const char *func)
{
if (!ctx->Extensions.ARB_map_buffer_range) {
_mesa_error(ctx, GL_INVALID_OPERATION,
MAP_USER);
}
+void GLAPIENTRY
+_mesa_FlushMappedBufferRange_no_error(GLenum target, GLintptr offset,
+ GLsizeiptr length)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target);
+ struct gl_buffer_object *bufObj = *bufObjPtr;
+
+ if (ctx->Driver.FlushMappedBufferRange)
+ ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj,
+ MAP_USER);
+}
+
void GLAPIENTRY
_mesa_FlushMappedBufferRange(GLenum target, GLintptr offset,
GLsizeiptr length)
if (!bufObj)
return;
- _mesa_flush_mapped_buffer_range(ctx, bufObj, offset, length,
- "glFlushMappedBufferRange");
+ flush_mapped_buffer_range(ctx, bufObj, offset, length,
+ "glFlushMappedBufferRange");
+}
+
+void GLAPIENTRY
+_mesa_FlushMappedNamedBufferRange_no_error(GLuint buffer, GLintptr offset,
+ GLsizeiptr length)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
+
+ if (ctx->Driver.FlushMappedBufferRange)
+ ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj,
+ MAP_USER);
}
void GLAPIENTRY
if (!bufObj)
return;
- _mesa_flush_mapped_buffer_range(ctx, bufObj, offset, length,
- "glFlushMappedNamedBufferRange");
+ flush_mapped_buffer_range(ctx, bufObj, offset, length,
+ "glFlushMappedNamedBufferRange");
}
set_ssbo_binding(ctx, binding, bufObj, offset, size, autoSize);
}
+static void
+bind_buffer_range_uniform_buffer(struct gl_context *ctx, GLuint index,
+ struct gl_buffer_object *bufObj,
+ GLintptr offset, GLsizeiptr size)
+{
+ if (bufObj == ctx->Shared->NullBufferObj) {
+ offset = -1;
+ size = -1;
+ }
+
+ _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, bufObj);
+ bind_uniform_buffer(ctx, index, bufObj, offset, size, GL_FALSE);
+}
+
/**
* Bind a region of a buffer object to a uniform block binding point.
* \param index the uniform buffer binding point index
* \param size size of the buffer object region
*/
static void
-bind_buffer_range_uniform_buffer(struct gl_context *ctx,
- GLuint index,
- struct gl_buffer_object *bufObj,
- GLintptr offset,
- GLsizeiptr size)
+bind_buffer_range_uniform_buffer_err(struct gl_context *ctx, GLuint index,
+ struct gl_buffer_object *bufObj,
+ GLintptr offset, GLsizeiptr size)
{
if (index >= ctx->Const.MaxUniformBufferBindings) {
_mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index);
return;
}
+ bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size);
+}
+
+static void
+bind_buffer_range_shader_storage_buffer(struct gl_context *ctx,
+ GLuint index,
+ struct gl_buffer_object *bufObj,
+ GLintptr offset,
+ GLsizeiptr size)
+{
if (bufObj == ctx->Shared->NullBufferObj) {
offset = -1;
size = -1;
}
- _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, bufObj);
- bind_uniform_buffer(ctx, index, bufObj, offset, size, GL_FALSE);
+ _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer, bufObj);
+ bind_shader_storage_buffer(ctx, index, bufObj, offset, size, GL_FALSE);
}
/**
* \param size size of the buffer object region
*/
static void
-bind_buffer_range_shader_storage_buffer(struct gl_context *ctx,
- GLuint index,
- struct gl_buffer_object *bufObj,
- GLintptr offset,
- GLsizeiptr size)
+bind_buffer_range_shader_storage_buffer_err(struct gl_context *ctx,
+ GLuint index,
+ struct gl_buffer_object *bufObj,
+ GLintptr offset, GLsizeiptr size)
{
if (index >= ctx->Const.MaxShaderStorageBufferBindings) {
_mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index);
return;
}
- if (bufObj == ctx->Shared->NullBufferObj) {
- offset = -1;
- size = -1;
- }
-
- _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer, bufObj);
- bind_shader_storage_buffer(ctx, index, bufObj, offset, size, GL_FALSE);
+ bind_buffer_range_shader_storage_buffer(ctx, index, bufObj, offset, size);
}
/**
}
}
+static void
+bind_atomic_buffer(struct gl_context *ctx, unsigned index,
+ struct gl_buffer_object *bufObj, GLintptr offset,
+ GLsizeiptr size)
+{
+ _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, bufObj);
+
+ struct gl_atomic_buffer_binding *binding =
+ &ctx->AtomicBufferBindings[index];
+ if (binding->BufferObject == bufObj &&
+ binding->Offset == offset &&
+ binding->Size == size) {
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, 0);
+ ctx->NewDriverState |= ctx->DriverFlags.NewAtomicBuffer;
+
+ set_atomic_buffer_binding(ctx, binding, bufObj, offset, size);
+}
+
/**
* Binds a buffer object to an atomic buffer binding point.
*
* updating it.
*/
static void
-bind_atomic_buffer(struct gl_context *ctx,
- unsigned index,
- struct gl_buffer_object *bufObj,
- GLintptr offset,
- GLsizeiptr size,
- const char *name)
+bind_atomic_buffer_err(struct gl_context *ctx, unsigned index,
+ struct gl_buffer_object *bufObj, GLintptr offset,
+ GLsizeiptr size, const char *name)
{
- struct gl_atomic_buffer_binding *binding;
-
if (index >= ctx->Const.MaxAtomicBufferBindings) {
_mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%d)", name, index);
return;
return;
}
- _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, bufObj);
-
- binding = &ctx->AtomicBufferBindings[index];
- if (binding->BufferObject == bufObj &&
- binding->Offset == offset &&
- binding->Size == size) {
- return;
- }
-
- FLUSH_VERTICES(ctx, 0);
- ctx->NewDriverState |= ctx->DriverFlags.NewAtomicBuffer;
-
- set_atomic_buffer_binding(ctx, binding, bufObj, offset, size);
+ bind_atomic_buffer(ctx, index, bufObj, offset, size);
}
static inline bool
unbind_uniform_buffers(struct gl_context *ctx, GLuint first, GLsizei count)
{
struct gl_buffer_object *bufObj = ctx->Shared->NullBufferObj;
- GLint i;
- for (i = 0; i < count; i++)
+ for (int i = 0; i < count; i++)
set_ubo_binding(ctx, &ctx->UniformBufferBindings[first + i],
bufObj, -1, -1, GL_TRUE);
}
GLsizei count)
{
struct gl_buffer_object *bufObj = ctx->Shared->NullBufferObj;
- GLint i;
- for (i = 0; i < count; i++)
+ for (int i = 0; i < count; i++)
set_ssbo_binding(ctx, &ctx->ShaderStorageBufferBindings[first + i],
bufObj, -1, -1, GL_TRUE);
}
const GLintptr *offsets, const GLsizeiptr *sizes,
const char *caller)
{
- GLint i;
-
if (!error_check_bind_uniform_buffers(ctx, first, count, caller))
return;
_mesa_HashLockMutex(ctx->Shared->BufferObjects);
- for (i = 0; i < count; i++) {
+ for (int i = 0; i < count; i++) {
struct gl_uniform_buffer_binding *binding =
&ctx->UniformBufferBindings[first + i];
struct gl_buffer_object *bufObj;
const GLsizeiptr *sizes,
const char *caller)
{
- GLint i;
-
if (!error_check_bind_shader_storage_buffers(ctx, first, count, caller))
return;
_mesa_HashLockMutex(ctx->Shared->BufferObjects);
- for (i = 0; i < count; i++) {
+ for (int i = 0; i < count; i++) {
struct gl_shader_storage_buffer_binding *binding =
&ctx->ShaderStorageBufferBindings[first + i];
struct gl_buffer_object *bufObj;
GLuint first, GLsizei count)
{
struct gl_buffer_object * const bufObj = ctx->Shared->NullBufferObj;
- GLint i;
- for (i = 0; i < count; i++)
+ for (int i = 0; i < count; i++)
_mesa_set_transform_feedback_binding(ctx, tfObj, first + i,
bufObj, 0, 0);
}
{
struct gl_transform_feedback_object *tfObj =
ctx->TransformFeedback.CurrentObject;
- GLint i;
if (!error_check_bind_xfb_buffers(ctx, tfObj, first, count, caller))
return;
_mesa_HashLockMutex(ctx->Shared->BufferObjects);
- for (i = 0; i < count; i++) {
+ for (int i = 0; i < count; i++) {
const GLuint index = first + i;
struct gl_buffer_object * const boundBufObj = tfObj->Buffers[index];
struct gl_buffer_object *bufObj;
unbind_atomic_buffers(struct gl_context *ctx, GLuint first, GLsizei count)
{
struct gl_buffer_object * const bufObj = ctx->Shared->NullBufferObj;
- GLint i;
- for (i = 0; i < count; i++)
+ for (int i = 0; i < count; i++)
set_atomic_buffer_binding(ctx, &ctx->AtomicBufferBindings[first + i],
bufObj, -1, -1);
}
const GLsizeiptr *sizes,
const char *caller)
{
- GLint i;
-
if (!error_check_bind_atomic_buffers(ctx, first, count, caller))
return;
_mesa_HashLockMutex(ctx->Shared->BufferObjects);
- for (i = 0; i < count; i++) {
+ for (int i = 0; i < count; i++) {
struct gl_atomic_buffer_binding *binding =
&ctx->AtomicBufferBindings[first + i];
struct gl_buffer_object *bufObj;
_mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
}
-void GLAPIENTRY
-_mesa_BindBufferRange(GLenum target, GLuint index,
- GLuint buffer, GLintptr offset, GLsizeiptr size)
+static ALWAYS_INLINE void
+bind_buffer_range(GLenum target, GLuint index, GLuint buffer, GLintptr offset,
+ GLsizeiptr size, bool no_error)
{
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
&bufObj, "glBindBufferRange"))
return;
- if (!bufObj) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBindBufferRange(invalid buffer=%u)", buffer);
- return;
- }
+ if (no_error) {
+ switch (target) {
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ _mesa_bind_buffer_range_xfb(ctx, ctx->TransformFeedback.CurrentObject,
+ index, bufObj, offset, size);
+ return;
+ case GL_UNIFORM_BUFFER:
+ bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size);
+ return;
+ case GL_SHADER_STORAGE_BUFFER:
+ bind_buffer_range_shader_storage_buffer(ctx, index, bufObj, offset,
+ size);
+ return;
+ case GL_ATOMIC_COUNTER_BUFFER:
+ bind_atomic_buffer(ctx, index, bufObj, offset, size);
+ return;
+ default:
+ unreachable("invalid BindBufferRange target with KHR_no_error");
+ }
+ } else {
+ if (!bufObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBindBufferRange(invalid buffer=%u)", buffer);
+ return;
+ }
+
+ if (buffer != 0) {
+ if (size <= 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size=%d)",
+ (int) size);
+ return;
+ }
+ }
+
+ switch (target) {
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ if (!_mesa_validate_buffer_range_xfb(ctx,
+ ctx->TransformFeedback.CurrentObject,
+ index, bufObj, offset, size,
+ false))
+ return;
- if (buffer != 0) {
- if (size <= 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size=%d)",
- (int) size);
+ _mesa_bind_buffer_range_xfb(ctx, ctx->TransformFeedback.CurrentObject,
+ index, bufObj, offset, size);
+ return;
+ case GL_UNIFORM_BUFFER:
+ bind_buffer_range_uniform_buffer_err(ctx, index, bufObj, offset,
+ size);
+ return;
+ case GL_SHADER_STORAGE_BUFFER:
+ bind_buffer_range_shader_storage_buffer_err(ctx, index, bufObj,
+ offset, size);
+ return;
+ case GL_ATOMIC_COUNTER_BUFFER:
+ bind_atomic_buffer_err(ctx, index, bufObj, offset, size,
+ "glBindBufferRange");
+ return;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferRange(target)");
return;
}
}
+}
- switch (target) {
- case GL_TRANSFORM_FEEDBACK_BUFFER:
- _mesa_bind_buffer_range_transform_feedback(ctx,
- ctx->TransformFeedback.CurrentObject,
- index, bufObj, offset, size,
- false);
- return;
- case GL_UNIFORM_BUFFER:
- bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size);
- return;
- case GL_SHADER_STORAGE_BUFFER:
- bind_buffer_range_shader_storage_buffer(ctx, index, bufObj, offset, size);
- return;
- case GL_ATOMIC_COUNTER_BUFFER:
- bind_atomic_buffer(ctx, index, bufObj, offset, size,
- "glBindBufferRange");
- return;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferRange(target)");
- return;
- }
+void GLAPIENTRY
+_mesa_BindBufferRange_no_error(GLenum target, GLuint index, GLuint buffer,
+ GLintptr offset, GLsizeiptr size)
+{
+ bind_buffer_range(target, index, buffer, offset, size, true);
+}
+
+void GLAPIENTRY
+_mesa_BindBufferRange(GLenum target, GLuint index,
+ GLuint buffer, GLintptr offset, GLsizeiptr size)
+{
+ bind_buffer_range(target, index, buffer, offset, size, false);
}
void GLAPIENTRY
bind_buffer_base_shader_storage_buffer(ctx, index, bufObj);
return;
case GL_ATOMIC_COUNTER_BUFFER:
- bind_atomic_buffer(ctx, index, bufObj, 0, 0,
- "glBindBufferBase");
+ bind_atomic_buffer_err(ctx, index, bufObj, 0, 0,
+ "glBindBufferBase");
return;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferBase(target)");
}
}
+static ALWAYS_INLINE void
+invalidate_buffer_subdata(struct gl_context *ctx,
+ struct gl_buffer_object *bufObj, GLintptr offset,
+ GLsizeiptr length)
+{
+ if (ctx->Driver.InvalidateBufferSubData)
+ ctx->Driver.InvalidateBufferSubData(ctx, bufObj, offset, length);
+}
+
+void GLAPIENTRY
+_mesa_InvalidateBufferSubData_no_error(GLuint buffer, GLintptr offset,
+ GLsizeiptr length)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
+ invalidate_buffer_subdata(ctx, bufObj, offset, length);
+}
+
void GLAPIENTRY
_mesa_InvalidateBufferSubData(GLuint buffer, GLintptr offset,
GLsizeiptr length)
return;
}
- if (ctx->Driver.InvalidateBufferSubData)
- ctx->Driver.InvalidateBufferSubData(ctx, bufObj, offset, length);
+ invalidate_buffer_subdata(ctx, bufObj, offset, length);
+}
+
+void GLAPIENTRY
+_mesa_InvalidateBufferData_no_error(GLuint buffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ struct gl_buffer_object *bufObj =_mesa_lookup_bufferobj(ctx, buffer);
+ invalidate_buffer_subdata(ctx, bufObj, 0, bufObj->Size);
}
void GLAPIENTRY
return;
}
- if (ctx->Driver.InvalidateBufferSubData)
- ctx->Driver.InvalidateBufferSubData(ctx, bufObj, 0, bufObj->Size);
+ invalidate_buffer_subdata(ctx, bufObj, 0, bufObj->Size);
}
static void