diff options
Diffstat (limited to 'src/gallium/drivers/i965/brw_resource_buffer.c')
-rw-r--r-- | src/gallium/drivers/i965/brw_resource_buffer.c | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/src/gallium/drivers/i965/brw_resource_buffer.c b/src/gallium/drivers/i965/brw_resource_buffer.c new file mode 100644 index 0000000000..488fe13c71 --- /dev/null +++ b/src/gallium/drivers/i965/brw_resource_buffer.c @@ -0,0 +1,201 @@ + +#include "util/u_memory.h" +#include "util/u_math.h" + +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "util/u_inlines.h" + +#include "brw_resource.h" +#include "brw_context.h" +#include "brw_batchbuffer.h" +#include "brw_winsys.h" + +static boolean +brw_buffer_get_handle(struct pipe_screen *screen, + struct pipe_resource *resource, + struct winsys_handle *handle) +{ + return FALSE; +} + + +static void +brw_buffer_destroy(struct pipe_screen *screen, + struct pipe_resource *resource) +{ + struct brw_buffer *buf = brw_buffer( resource ); + + bo_reference(&buf->bo, NULL); + FREE(buf); +} + + +static void * +brw_buffer_transfer_map( struct pipe_context *pipe, + struct pipe_transfer *transfer) +{ + struct brw_screen *bscreen = brw_screen(pipe->screen); + struct brw_winsys_screen *sws = bscreen->sws; + struct brw_buffer *buf = brw_buffer(transfer->resource); + unsigned offset = transfer->box.x; + unsigned length = transfer->box.width; + unsigned usage = transfer->usage; + uint8_t *map; + + if (buf->user_buffer) + map = buf->user_buffer; + else + map = sws->bo_map( buf->bo, + BRW_DATA_OTHER, + offset, + length, + (usage & PIPE_TRANSFER_WRITE) ? TRUE : FALSE, + (usage & PIPE_TRANSFER_DISCARD) ? TRUE : FALSE, + (usage & PIPE_TRANSFER_FLUSH_EXPLICIT) ? TRUE : FALSE); + + return map + offset; +} + + +static void +brw_buffer_transfer_flush_region( struct pipe_context *pipe, + struct pipe_transfer *transfer, + const struct pipe_box *box) +{ + struct brw_screen *bscreen = brw_screen(pipe->screen); + struct brw_winsys_screen *sws = bscreen->sws; + struct brw_buffer *buf = brw_buffer(transfer->resource); + unsigned offset = box->x; + unsigned length = box->width; + + if (buf->user_buffer) + return; + + sws->bo_flush_range( buf->bo, + offset, + length ); +} + + +static void +brw_buffer_transfer_unmap( struct pipe_context *pipe, + struct pipe_transfer *transfer) +{ + struct brw_screen *bscreen = brw_screen(pipe->screen); + struct brw_winsys_screen *sws = bscreen->sws; + struct brw_buffer *buf = brw_buffer( transfer->resource ); + + if (buf->bo) + sws->bo_unmap(buf->bo); +} + + +static unsigned brw_buffer_is_referenced( struct pipe_context *pipe, + struct pipe_resource *resource, + unsigned face, + unsigned level) +{ + struct brw_context *brw = brw_context(pipe); + struct brw_winsys_buffer *batch_bo = brw->batch->buf; + struct brw_buffer *buf = brw_buffer(resource); + + if (buf->bo == NULL) + return PIPE_UNREFERENCED; + + if (!brw_screen(pipe->screen)->sws->bo_references( batch_bo, buf->bo )) + return PIPE_UNREFERENCED; + + return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; +} + + +struct u_resource_vtbl brw_buffer_vtbl = +{ + brw_buffer_get_handle, /* get_handle */ + brw_buffer_destroy, /* resource_destroy */ + brw_buffer_is_referenced, /* is_resource_referenced */ + u_default_get_transfer, /* get_transfer */ + u_default_transfer_destroy, /* transfer_destroy */ + brw_buffer_transfer_map, /* transfer_map */ + brw_buffer_transfer_flush_region, /* transfer_flush_region */ + brw_buffer_transfer_unmap, /* transfer_unmap */ + u_default_transfer_inline_write /* transfer_inline_write */ +}; + + +struct pipe_resource * +brw_buffer_create(struct pipe_screen *screen, + const struct pipe_resource *template) +{ + struct brw_screen *bscreen = brw_screen(screen); + struct brw_winsys_screen *sws = bscreen->sws; + struct brw_buffer *buf; + unsigned buffer_type; + enum pipe_error ret; + + buf = CALLOC_STRUCT(brw_buffer); + if (!buf) + return NULL; + + buf->b.b = *template; + buf->b.vtbl = &brw_buffer_vtbl; + pipe_reference_init(&buf->b.b.reference, 1); + buf->b.b.screen = screen; + + switch (template->bind & (PIPE_BIND_VERTEX_BUFFER | + PIPE_BIND_INDEX_BUFFER | + PIPE_BIND_CONSTANT_BUFFER)) + { + case PIPE_BIND_VERTEX_BUFFER: + case PIPE_BIND_INDEX_BUFFER: + case (PIPE_BIND_VERTEX_BUFFER|PIPE_BIND_INDEX_BUFFER): + buffer_type = BRW_BUFFER_TYPE_VERTEX; + break; + + case PIPE_BIND_CONSTANT_BUFFER: + buffer_type = BRW_BUFFER_TYPE_SHADER_CONSTANTS; + break; + + default: + buffer_type = BRW_BUFFER_TYPE_GENERIC; + break; + } + + ret = sws->bo_alloc( sws, buffer_type, + template->width0, + 64, /* alignment */ + &buf->bo ); + if (ret != PIPE_OK) + return NULL; + + return &buf->b.b; +} + + +struct pipe_resource * +brw_user_buffer_create(struct pipe_screen *screen, + void *ptr, + unsigned bytes, + unsigned bind) +{ + struct brw_buffer *buf; + + buf = CALLOC_STRUCT(brw_buffer); + if (!buf) + return NULL; + + pipe_reference_init(&buf->b.b.reference, 1); + buf->b.vtbl = &brw_buffer_vtbl; + buf->b.b.screen = screen; + buf->b.b.format = PIPE_FORMAT_R8_UNORM; /* ?? */ + buf->b.b._usage = PIPE_USAGE_IMMUTABLE; + buf->b.b.bind = bind; + buf->b.b.width0 = bytes; + buf->b.b.height0 = 1; + buf->b.b.depth0 = 1; + + buf->user_buffer = ptr; + + return &buf->b.b; +} |