summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/state_tracker/st_cb_bufferobjects.c191
1 files changed, 104 insertions, 87 deletions
diff --git a/src/mesa/state_tracker/st_cb_bufferobjects.c b/src/mesa/state_tracker/st_cb_bufferobjects.c
index a9104a90095..6b64ba132c7 100644
--- a/src/mesa/state_tracker/st_cb_bufferobjects.c
+++ b/src/mesa/state_tracker/st_cb_bufferobjects.c
@@ -164,107 +164,84 @@ st_bufferobj_get_subdata(struct gl_context *ctx,
offset, size, data);
}
-static ALWAYS_INLINE GLboolean
-bufferobj_data(struct gl_context *ctx,
- GLenum target,
- GLsizeiptrARB size,
- const void *data,
- struct gl_memory_object *memObj,
- GLuint64 offset,
- GLenum usage,
- GLbitfield storageFlags,
- struct gl_buffer_object *obj)
-{
- struct st_context *st = st_context(ctx);
- struct pipe_context *pipe = st->pipe;
- struct pipe_screen *screen = pipe->screen;
- struct st_buffer_object *st_obj = st_buffer_object(obj);
- struct st_memory_object *st_mem_obj = st_memory_object(memObj);
- unsigned bind, pipe_usage, pipe_flags = 0;
-
- if (target != GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD &&
- size && st_obj->buffer &&
- st_obj->Base.Size == size &&
- st_obj->Base.Usage == usage &&
- st_obj->Base.StorageFlags == storageFlags) {
- if (data) {
- /* Just discard the old contents and write new data.
- * This should be the same as creating a new buffer, but we avoid
- * a lot of validation in Mesa.
- */
- pipe->buffer_subdata(pipe, st_obj->buffer,
- PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE,
- 0, size, data);
- return GL_TRUE;
- } else if (screen->get_param(screen, PIPE_CAP_INVALIDATE_BUFFER)) {
- pipe->invalidate_resource(pipe, st_obj->buffer);
- return GL_TRUE;
- }
- }
-
- st_obj->Base.Size = size;
- st_obj->Base.Usage = usage;
- st_obj->Base.StorageFlags = storageFlags;
+/**
+ * Return bitmask of PIPE_BIND_x flags corresponding a GL buffer target.
+ */
+static unsigned
+buffer_target_to_bind_flags(GLenum target)
+{
switch (target) {
case GL_PIXEL_PACK_BUFFER_ARB:
case GL_PIXEL_UNPACK_BUFFER_ARB:
- bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
- break;
+ return PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
case GL_ARRAY_BUFFER_ARB:
- bind = PIPE_BIND_VERTEX_BUFFER;
- break;
+ return PIPE_BIND_VERTEX_BUFFER;
case GL_ELEMENT_ARRAY_BUFFER_ARB:
- bind = PIPE_BIND_INDEX_BUFFER;
- break;
+ return PIPE_BIND_INDEX_BUFFER;
case GL_TEXTURE_BUFFER:
- bind = PIPE_BIND_SAMPLER_VIEW;
- break;
+ return PIPE_BIND_SAMPLER_VIEW;
case GL_TRANSFORM_FEEDBACK_BUFFER:
- bind = PIPE_BIND_STREAM_OUTPUT;
- break;
+ return PIPE_BIND_STREAM_OUTPUT;
case GL_UNIFORM_BUFFER:
- bind = PIPE_BIND_CONSTANT_BUFFER;
- break;
+ return PIPE_BIND_CONSTANT_BUFFER;
case GL_DRAW_INDIRECT_BUFFER:
case GL_PARAMETER_BUFFER_ARB:
- bind = PIPE_BIND_COMMAND_ARGS_BUFFER;
- break;
+ return PIPE_BIND_COMMAND_ARGS_BUFFER;
case GL_ATOMIC_COUNTER_BUFFER:
case GL_SHADER_STORAGE_BUFFER:
- bind = PIPE_BIND_SHADER_BUFFER;
- break;
+ return PIPE_BIND_SHADER_BUFFER;
case GL_QUERY_BUFFER:
- bind = PIPE_BIND_QUERY_BUFFER;
- break;
+ return PIPE_BIND_QUERY_BUFFER;
default:
- bind = 0;
+ return 0;
}
+}
- /* Set usage. */
- if (st_obj->Base.Immutable) {
+
+/**
+ * Return bitmask of PIPE_RESOURCE_x flags corresponding to GL_MAP_x flags.
+ */
+static unsigned
+storage_flags_to_buffer_flags(GLbitfield storageFlags)
+{
+ unsigned flags = 0;
+ if (storageFlags & GL_MAP_PERSISTENT_BIT)
+ flags |= PIPE_RESOURCE_FLAG_MAP_PERSISTENT;
+ if (storageFlags & GL_MAP_COHERENT_BIT)
+ flags |= PIPE_RESOURCE_FLAG_MAP_COHERENT;
+ if (storageFlags & GL_SPARSE_STORAGE_BIT_ARB)
+ flags |= PIPE_RESOURCE_FLAG_SPARSE;
+ return flags;
+}
+
+
+/**
+ * From a buffer object's target, immutability flag, storage flags and
+ * usage hint, return a pipe_resource_usage value (PIPE_USAGE_DYNAMIC,
+ * STREAM, etc).
+ */
+static const enum pipe_resource_usage
+buffer_usage(GLenum target, GLboolean immutable,
+ GLbitfield storageFlags, GLenum usage)
+{
+ if (immutable) {
/* BufferStorage */
if (storageFlags & GL_CLIENT_STORAGE_BIT) {
if (storageFlags & GL_MAP_READ_BIT)
- pipe_usage = PIPE_USAGE_STAGING;
+ return PIPE_USAGE_STAGING;
else
- pipe_usage = PIPE_USAGE_STREAM;
+ return PIPE_USAGE_STREAM;
} else {
- pipe_usage = PIPE_USAGE_DEFAULT;
+ return PIPE_USAGE_DEFAULT;
}
}
else {
/* BufferData */
switch (usage) {
- case GL_STATIC_DRAW:
- case GL_STATIC_COPY:
- default:
- pipe_usage = PIPE_USAGE_DEFAULT;
- break;
case GL_DYNAMIC_DRAW:
case GL_DYNAMIC_COPY:
- pipe_usage = PIPE_USAGE_DYNAMIC;
- break;
+ return PIPE_USAGE_DYNAMIC;
case GL_STREAM_DRAW:
case GL_STREAM_COPY:
/* XXX: Remove this test and fall-through when we have PBO unpacking
@@ -272,31 +249,70 @@ bufferobj_data(struct gl_context *ctx,
* have to make sure CPU reads are fast.
*/
if (target != GL_PIXEL_UNPACK_BUFFER_ARB) {
- pipe_usage = PIPE_USAGE_STREAM;
- break;
+ return PIPE_USAGE_STREAM;
}
/* fall through */
case GL_STATIC_READ:
case GL_DYNAMIC_READ:
case GL_STREAM_READ:
- pipe_usage = PIPE_USAGE_STAGING;
- break;
+ return PIPE_USAGE_STAGING;
+ case GL_STATIC_DRAW:
+ case GL_STATIC_COPY:
+ default:
+ return PIPE_USAGE_DEFAULT;
}
}
+}
- /* Set flags. */
- if (storageFlags & GL_MAP_PERSISTENT_BIT)
- pipe_flags |= PIPE_RESOURCE_FLAG_MAP_PERSISTENT;
- if (storageFlags & GL_MAP_COHERENT_BIT)
- pipe_flags |= PIPE_RESOURCE_FLAG_MAP_COHERENT;
- if (storageFlags & GL_SPARSE_STORAGE_BIT_ARB)
- pipe_flags |= PIPE_RESOURCE_FLAG_SPARSE;
+
+static ALWAYS_INLINE GLboolean
+bufferobj_data(struct gl_context *ctx,
+ GLenum target,
+ GLsizeiptrARB size,
+ const void *data,
+ struct gl_memory_object *memObj,
+ GLuint64 offset,
+ GLenum usage,
+ GLbitfield storageFlags,
+ struct gl_buffer_object *obj)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+ struct st_memory_object *st_mem_obj = st_memory_object(memObj);
+
+ if (target != GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD &&
+ size && st_obj->buffer &&
+ st_obj->Base.Size == size &&
+ st_obj->Base.Usage == usage &&
+ st_obj->Base.StorageFlags == storageFlags) {
+ if (data) {
+ /* Just discard the old contents and write new data.
+ * This should be the same as creating a new buffer, but we avoid
+ * a lot of validation in Mesa.
+ */
+ pipe->buffer_subdata(pipe, st_obj->buffer,
+ PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE,
+ 0, size, data);
+ return GL_TRUE;
+ } else if (screen->get_param(screen, PIPE_CAP_INVALIDATE_BUFFER)) {
+ pipe->invalidate_resource(pipe, st_obj->buffer);
+ return GL_TRUE;
+ }
+ }
+
+ st_obj->Base.Size = size;
+ st_obj->Base.Usage = usage;
+ st_obj->Base.StorageFlags = storageFlags;
pipe_resource_reference( &st_obj->buffer, NULL );
+ const unsigned bindings = buffer_target_to_bind_flags(target);
+
if (ST_DEBUG & DEBUG_BUFFER) {
debug_printf("Create buffer size %" PRId64 " bind 0x%x\n",
- (int64_t) size, bind);
+ (int64_t) size, bindings);
}
if (size != 0) {
@@ -305,9 +321,10 @@ bufferobj_data(struct gl_context *ctx,
memset(&buffer, 0, sizeof buffer);
buffer.target = PIPE_BUFFER;
buffer.format = PIPE_FORMAT_R8_UNORM; /* want TYPELESS or similar */
- buffer.bind = bind;
- buffer.usage = pipe_usage;
- buffer.flags = pipe_flags;
+ buffer.bind = bindings;
+ buffer.usage =
+ buffer_usage(target, st_obj->Base.Immutable, storageFlags, usage);
+ buffer.flags = storage_flags_to_buffer_flags(storageFlags);
buffer.width0 = size;
buffer.height0 = 1;
buffer.depth0 = 1;