if (st_obj->buffer)
pipe_resource_reference(&st_obj->buffer, NULL);
- free(st_obj->Base.Label);
- free(st_obj);
+ _mesa_delete_buffer_object(ctx, obj);
}
st_bufferobj_subdata(struct gl_context *ctx,
GLintptrARB offset,
GLsizeiptrARB size,
- const GLvoid * data, struct gl_buffer_object *obj)
+ const void * data, struct gl_buffer_object *obj)
{
struct st_buffer_object *st_obj = st_buffer_object(obj);
/* we may be called from VBO code, so double-check params here */
- ASSERT(offset >= 0);
- ASSERT(size >= 0);
- ASSERT(offset + size <= obj->Size);
+ assert(offset >= 0);
+ assert(size >= 0);
+ assert(offset + size <= obj->Size);
if (!size)
return;
st_bufferobj_get_subdata(struct gl_context *ctx,
GLintptrARB offset,
GLsizeiptrARB size,
- GLvoid * data, struct gl_buffer_object *obj)
+ void * data, struct gl_buffer_object *obj)
{
struct st_buffer_object *st_obj = st_buffer_object(obj);
/* we may be called from VBO code, so double-check params here */
- ASSERT(offset >= 0);
- ASSERT(size >= 0);
- ASSERT(offset + size <= obj->Size);
+ assert(offset >= 0);
+ assert(size >= 0);
+ assert(offset + size <= obj->Size);
if (!size)
return;
st_bufferobj_data(struct gl_context *ctx,
GLenum target,
GLsizeiptrARB size,
- const GLvoid * data,
+ const void * data,
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);
unsigned bind, pipe_usage, pipe_flags = 0;
- if (size && data && st_obj->buffer &&
+ 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) {
- /* 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.
- */
- struct pipe_box box;
-
- u_box_1d(0, size, &box);
- pipe->transfer_inline_write(pipe, st_obj->buffer, 0,
- PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE,
- &box, data, 0, 0);
- return GL_TRUE;
+ 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;
bind = PIPE_BIND_CONSTANT_BUFFER;
break;
case GL_DRAW_INDIRECT_BUFFER:
+ case GL_PARAMETER_BUFFER_ARB:
bind = PIPE_BIND_COMMAND_ARGS_BUFFER;
break;
+ case GL_ATOMIC_COUNTER_BUFFER:
+ case GL_SHADER_STORAGE_BUFFER:
+ bind = PIPE_BIND_SHADER_BUFFER;
+ break;
+ case GL_QUERY_BUFFER:
+ bind = PIPE_BIND_QUERY_BUFFER;
+ break;
default:
bind = 0;
}
/* Set usage. */
if (st_obj->Base.Immutable) {
/* BufferStorage */
- if (storageFlags & GL_CLIENT_STORAGE_BIT)
- pipe_usage = PIPE_USAGE_STAGING;
- else
+ if (storageFlags & GL_CLIENT_STORAGE_BIT) {
+ if (storageFlags & GL_MAP_READ_BIT)
+ pipe_usage = PIPE_USAGE_STAGING;
+ else
+ pipe_usage = PIPE_USAGE_STREAM;
+ } else {
pipe_usage = PIPE_USAGE_DEFAULT;
+ }
}
else {
/* BufferData */
buffer.depth0 = 1;
buffer.array_size = 1;
- st_obj->buffer = pipe->screen->resource_create(pipe->screen, &buffer);
+ if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {
+ st_obj->buffer =
+ screen->resource_from_user_memory(screen, &buffer, (void*)data);
+ }
+ else {
+ st_obj->buffer = screen->resource_create(screen, &buffer);
+
+ if (st_obj->buffer && data)
+ pipe_buffer_write(pipe, st_obj->buffer, 0, size, data);
+ }
if (!st_obj->buffer) {
/* out of memory */
st_obj->Base.Size = 0;
return GL_FALSE;
}
-
- if (data)
- pipe_buffer_write(pipe, st_obj->buffer, 0, size, data);
}
- /* BufferData may change an array or uniform buffer, need to update it */
- st->dirty.st |= ST_NEW_VERTEX_ARRAYS | ST_NEW_UNIFORM_BUFFER;
+ /* The current buffer may be bound, so we have to revalidate all atoms that
+ * might be using it.
+ */
+ /* TODO: Add arrays to usage history */
+ ctx->NewDriverState |= ST_NEW_VERTEX_ARRAYS;
+ if (st_obj->Base.UsageHistory & USAGE_UNIFORM_BUFFER)
+ ctx->NewDriverState |= ST_NEW_UNIFORM_BUFFER;
+ if (st_obj->Base.UsageHistory & USAGE_SHADER_STORAGE_BUFFER)
+ ctx->NewDriverState |= ST_NEW_STORAGE_BUFFER;
+ if (st_obj->Base.UsageHistory & USAGE_TEXTURE_BUFFER)
+ ctx->NewDriverState |= ST_NEW_SAMPLER_VIEWS | ST_NEW_IMAGE_UNITS;
+ if (st_obj->Base.UsageHistory & USAGE_ATOMIC_COUNTER_BUFFER)
+ ctx->NewDriverState |= ST_NEW_ATOMIC_BUFFER;
return GL_TRUE;
}
+/**
+ * Called via glInvalidateBuffer(Sub)Data.
+ */
+static void
+st_bufferobj_invalidate(struct gl_context *ctx,
+ struct gl_buffer_object *obj,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_context *pipe = st->pipe;
+ struct st_buffer_object *st_obj = st_buffer_object(obj);
+
+ /* We ignore partial invalidates. */
+ if (offset != 0 || size != obj->Size)
+ return;
+
+ /* Nothing to invalidate. */
+ if (!st_obj->buffer)
+ return;
+
+ pipe->invalidate_resource(pipe, st_obj->buffer);
+}
+
+
/**
* Called via glMapBufferRange().
*/
static void
st_clear_buffer_subdata(struct gl_context *ctx,
GLintptr offset, GLsizeiptr size,
- const GLvoid *clearValue,
+ const void *clearValue,
GLsizeiptr clearValueSize,
struct gl_buffer_object *bufObj)
{
static const char zeros[16] = {0};
if (!pipe->clear_buffer) {
- _mesa_buffer_clear_subdata(ctx, offset, size,
- clearValue, clearValueSize, bufObj);
+ _mesa_ClearBufferSubData_sw(ctx, offset, size,
+ clearValue, clearValueSize, bufObj);
return;
}
void
-st_init_bufferobject_functions(struct dd_function_table *functions)
+st_init_bufferobject_functions(struct pipe_screen *screen,
+ struct dd_function_table *functions)
{
/* plug in default driver fallbacks (such as for ClearBufferSubData) */
_mesa_init_buffer_object_functions(functions);
functions->CopyBufferSubData = st_copy_buffer_subdata;
functions->ClearBufferSubData = st_clear_buffer_subdata;
- /* For GL_APPLE_vertex_array_object */
- functions->NewArrayObject = _mesa_new_vao;
- functions->DeleteArrayObject = _mesa_delete_vao;
+ if (screen->get_param(screen, PIPE_CAP_INVALIDATE_BUFFER))
+ functions->InvalidateBufferSubData = st_bufferobj_invalidate;
}