
Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com> Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27587>
265 lines
9.1 KiB
C
265 lines
9.1 KiB
C
/*
|
|
* Mesa 3-D graphics library
|
|
*
|
|
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
|
|
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included
|
|
* in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
* OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
|
|
|
|
#ifndef BUFFEROBJ_H
|
|
#define BUFFEROBJ_H
|
|
|
|
#include <stdbool.h>
|
|
#include "mtypes.h"
|
|
|
|
|
|
/*
|
|
* Internal functions
|
|
*/
|
|
|
|
static inline struct pipe_resource *
|
|
_mesa_get_bufferobj_reference(struct gl_context *ctx, struct gl_buffer_object *obj)
|
|
{
|
|
if (unlikely(!obj))
|
|
return NULL;
|
|
|
|
struct pipe_resource *buffer = obj->buffer;
|
|
|
|
/* Only one context is using the fast path. All other contexts must use
|
|
* the slow path.
|
|
*/
|
|
if (unlikely(obj->private_refcount_ctx != ctx ||
|
|
obj->private_refcount <= 0)) {
|
|
if (buffer) {
|
|
if (obj->private_refcount_ctx != ctx) {
|
|
p_atomic_inc(&buffer->reference.count);
|
|
} else {
|
|
/* This is the number of atomic increments we will skip. */
|
|
const unsigned count = 100000000;
|
|
p_atomic_add(&buffer->reference.count, count);
|
|
|
|
/* Remove the reference that we return. */
|
|
assert(obj->private_refcount == 0);
|
|
obj->private_refcount = count - 1;
|
|
}
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
/* Return a buffer reference while decrementing the private refcount.
|
|
* The buffer must be non-NULL, which is implied by private_refcount_ctx
|
|
* being non-NULL.
|
|
*/
|
|
assert(buffer);
|
|
obj->private_refcount--;
|
|
return buffer;
|
|
}
|
|
|
|
void _mesa_bufferobj_subdata(struct gl_context *ctx,
|
|
GLintptrARB offset,
|
|
GLsizeiptrARB size,
|
|
const void * data, struct gl_buffer_object *obj);
|
|
GLboolean _mesa_bufferobj_data(struct gl_context *ctx,
|
|
GLenum target,
|
|
GLsizeiptrARB size,
|
|
const void *data,
|
|
GLenum usage,
|
|
GLbitfield storageFlags,
|
|
struct gl_buffer_object *obj);
|
|
void
|
|
_mesa_bufferobj_get_subdata(struct gl_context *ctx,
|
|
GLintptrARB offset,
|
|
GLsizeiptrARB size,
|
|
void *data, struct gl_buffer_object *obj);
|
|
|
|
void *_mesa_bufferobj_map_range(struct gl_context *ctx,
|
|
GLintptr offset, GLsizeiptr length,
|
|
GLbitfield access,
|
|
struct gl_buffer_object *obj,
|
|
gl_map_buffer_index index);
|
|
|
|
void _mesa_bufferobj_flush_mapped_range(struct gl_context *ctx,
|
|
GLintptr offset, GLsizeiptr length,
|
|
struct gl_buffer_object *obj,
|
|
gl_map_buffer_index index);
|
|
GLboolean _mesa_bufferobj_unmap(struct gl_context *ctx, struct gl_buffer_object *obj,
|
|
gl_map_buffer_index index);
|
|
|
|
struct gl_buffer_object *
|
|
_mesa_bufferobj_alloc(struct gl_context *ctx, GLuint id);
|
|
void
|
|
_mesa_bufferobj_release_buffer(struct gl_buffer_object *obj);
|
|
|
|
enum pipe_map_flags
|
|
_mesa_access_flags_to_transfer_flags(GLbitfield access, bool wholeBuffer);
|
|
|
|
/** Is the given buffer object currently mapped by the GL user? */
|
|
static inline GLboolean
|
|
_mesa_bufferobj_mapped(const struct gl_buffer_object *obj,
|
|
gl_map_buffer_index index)
|
|
{
|
|
return obj->Mappings[index].Pointer != NULL;
|
|
}
|
|
|
|
/**
|
|
* Check whether the given buffer object is illegally mapped prior to
|
|
* drawing from (or reading back to) the buffer.
|
|
* Note that it's legal for a buffer to be mapped at draw/readback time
|
|
* if it was mapped persistently (See GL_ARB_buffer_storage spec).
|
|
* \return true if the buffer is illegally mapped, false otherwise
|
|
*/
|
|
static inline bool
|
|
_mesa_check_disallowed_mapping(const struct gl_buffer_object *obj)
|
|
{
|
|
return _mesa_bufferobj_mapped(obj, MAP_USER) &&
|
|
!(obj->Mappings[MAP_USER].AccessFlags &
|
|
GL_MAP_PERSISTENT_BIT);
|
|
}
|
|
|
|
|
|
extern void
|
|
_mesa_init_buffer_objects(struct gl_context *ctx);
|
|
|
|
extern void
|
|
_mesa_free_buffer_objects(struct gl_context *ctx);
|
|
|
|
extern bool
|
|
_mesa_handle_bind_buffer_gen(struct gl_context *ctx,
|
|
GLuint buffer,
|
|
struct gl_buffer_object **buf_handle,
|
|
const char *caller, bool no_error);
|
|
|
|
extern void
|
|
_mesa_update_default_objects_buffer_objects(struct gl_context *ctx);
|
|
|
|
|
|
extern struct gl_buffer_object *
|
|
_mesa_lookup_bufferobj(struct gl_context *ctx, GLuint buffer);
|
|
|
|
extern struct gl_buffer_object *
|
|
_mesa_lookup_bufferobj_locked(struct gl_context *ctx, GLuint buffer);
|
|
|
|
extern struct gl_buffer_object *
|
|
_mesa_lookup_bufferobj_err(struct gl_context *ctx, GLuint buffer,
|
|
const char *caller);
|
|
|
|
extern struct gl_buffer_object *
|
|
_mesa_multi_bind_lookup_bufferobj(struct gl_context *ctx,
|
|
const GLuint *buffers,
|
|
GLuint index, const char *caller,
|
|
bool *error);
|
|
|
|
extern void
|
|
_mesa_delete_buffer_object(struct gl_context *ctx,
|
|
struct gl_buffer_object *bufObj);
|
|
|
|
/**
|
|
* Set ptr to bufObj w/ reference counting.
|
|
* This is normally only called from the _mesa_reference_buffer_object() macro
|
|
* when there's a real pointer change.
|
|
*/
|
|
static inline void
|
|
_mesa_reference_buffer_object_(struct gl_context *ctx,
|
|
struct gl_buffer_object **ptr,
|
|
struct gl_buffer_object *bufObj,
|
|
bool shared_binding)
|
|
{
|
|
if (*ptr) {
|
|
/* Unreference the old buffer */
|
|
struct gl_buffer_object *oldObj = *ptr;
|
|
|
|
assert(oldObj->RefCount >= 1);
|
|
|
|
/* Count references only if the context doesn't own the buffer or if
|
|
* ptr is a binding point shared by multiple contexts (such as a texture
|
|
* buffer object being a buffer bound within a texture object).
|
|
*/
|
|
if (shared_binding || ctx != oldObj->Ctx) {
|
|
if (p_atomic_dec_zero(&oldObj->RefCount)) {
|
|
_mesa_delete_buffer_object(ctx, oldObj);
|
|
}
|
|
} else {
|
|
/* Update the private ref count. */
|
|
assert(oldObj->CtxRefCount >= 1);
|
|
oldObj->CtxRefCount--;
|
|
}
|
|
}
|
|
|
|
if (bufObj) {
|
|
/* reference new buffer */
|
|
if (shared_binding || ctx != bufObj->Ctx)
|
|
p_atomic_inc(&bufObj->RefCount);
|
|
else
|
|
bufObj->CtxRefCount++;
|
|
}
|
|
|
|
*ptr = bufObj;
|
|
}
|
|
|
|
/**
|
|
* Assign a buffer into a pointer with reference counting. The destination
|
|
* must be private within a context.
|
|
*/
|
|
static inline void
|
|
_mesa_reference_buffer_object(struct gl_context *ctx,
|
|
struct gl_buffer_object **ptr,
|
|
struct gl_buffer_object *bufObj)
|
|
{
|
|
if (*ptr != bufObj)
|
|
_mesa_reference_buffer_object_(ctx, ptr, bufObj, false);
|
|
}
|
|
|
|
/**
|
|
* Assign a buffer into a pointer with reference counting. The destination
|
|
* must be shareable among multiple contexts.
|
|
*/
|
|
static inline void
|
|
_mesa_reference_buffer_object_shared(struct gl_context *ctx,
|
|
struct gl_buffer_object **ptr,
|
|
struct gl_buffer_object *bufObj)
|
|
{
|
|
if (*ptr != bufObj)
|
|
_mesa_reference_buffer_object_(ctx, ptr, bufObj, true);
|
|
}
|
|
|
|
extern void
|
|
_mesa_buffer_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
|
|
GLenum target, GLsizeiptr size, const GLvoid *data,
|
|
GLenum usage, const char *func);
|
|
|
|
extern void
|
|
_mesa_buffer_sub_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
|
|
GLintptr offset, GLsizeiptr size, const GLvoid *data);
|
|
|
|
extern void
|
|
_mesa_buffer_unmap_all_mappings(struct gl_context *ctx,
|
|
struct gl_buffer_object *bufObj);
|
|
|
|
extern void
|
|
_mesa_ClearBufferSubData_sw(struct gl_context *ctx,
|
|
GLintptr offset, GLsizeiptr size,
|
|
const GLvoid *clearValue,
|
|
GLsizeiptr clearValueSize,
|
|
struct gl_buffer_object *bufObj);
|
|
|
|
#endif
|