summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/r300/r300_screen_buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/r300/r300_screen_buffer.c')
-rw-r--r--src/gallium/drivers/r300/r300_screen_buffer.c260
1 files changed, 123 insertions, 137 deletions
diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c
index 37a080b..cc3c1d7 100644
--- a/src/gallium/drivers/r300/r300_screen_buffer.c
+++ b/src/gallium/drivers/r300/r300_screen_buffer.c
@@ -40,10 +40,10 @@ unsigned r300_buffer_is_referenced(struct pipe_context *context,
struct r300_context *r300 = r300_context(context);
struct r300_buffer *rbuf = r300_buffer(buf);
- if (r300_buffer_is_user_buffer(buf))
+ if (r300_is_user_buffer(buf))
return PIPE_UNREFERENCED;
- if (r300->rws->cs_is_buffer_referenced(r300->cs, rbuf->buf, domain))
+ if (r300->rws->cs_is_buffer_referenced(r300->cs, rbuf->cs_buf, domain))
return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
return PIPE_UNREFERENCED;
@@ -51,76 +51,86 @@ unsigned r300_buffer_is_referenced(struct pipe_context *context,
static unsigned r300_buffer_is_referenced_by_cs(struct pipe_context *context,
struct pipe_resource *buf,
- unsigned face, unsigned level)
+ unsigned level, int layer)
{
return r300_buffer_is_referenced(context, buf, R300_REF_CS);
}
-/* External helper, not required to implent u_resource_vtbl:
- */
-int r300_upload_index_buffer(struct r300_context *r300,
- struct pipe_resource **index_buffer,
- unsigned index_size,
- unsigned start,
- unsigned count,
- unsigned *out_offset)
+void r300_upload_index_buffer(struct r300_context *r300,
+ struct pipe_resource **index_buffer,
+ unsigned index_size, unsigned *start,
+ unsigned count)
{
- struct pipe_resource *upload_buffer = NULL;
- unsigned index_offset = start * index_size;
- int ret = 0;
-
- if (r300_buffer_is_user_buffer(*index_buffer)) {
- ret = u_upload_buffer(r300->upload_ib,
- index_offset,
- count * index_size,
- *index_buffer,
- &index_offset,
- &upload_buffer);
- if (ret) {
- goto done;
- }
- *index_buffer = upload_buffer;
- *out_offset = index_offset / index_size;
- } else
- *out_offset = start;
-
- done:
- // if (upload_buffer)
- // pipe_resource_reference(&upload_buffer, NULL);
- return ret;
+ unsigned index_offset;
+ uint8_t *ptr = r300_buffer(*index_buffer)->user_buffer;
+ boolean flushed;
+
+ *index_buffer = NULL;
+
+ u_upload_data(r300->upload_ib,
+ 0, count * index_size,
+ ptr + (*start * index_size),
+ &index_offset,
+ index_buffer, &flushed);
+
+ *start = index_offset / index_size;
+
+ if (flushed || !r300->upload_ib_validated) {
+ r300->upload_ib_validated = FALSE;
+ r300->validate_buffers = TRUE;
+ }
}
-/* External helper, not required to implement u_resource_vtbl:
- */
-int r300_upload_user_buffers(struct r300_context *r300)
+void r300_upload_user_buffers(struct r300_context *r300,
+ int min_index, int max_index)
{
- enum pipe_error ret = PIPE_OK;
- int i, nr;
-
- nr = r300->velems->count;
+ int i, nr = r300->velems->count;
+ unsigned count = max_index + 1 - min_index;
+ boolean flushed;
+ boolean uploaded[16] = {0};
for (i = 0; i < nr; i++) {
- struct pipe_vertex_buffer *vb =
- &r300->vertex_buffer[r300->velems->velem[i].vertex_buffer_index];
-
- if (r300_buffer_is_user_buffer(vb->buffer)) {
- struct pipe_resource *upload_buffer = NULL;
- unsigned offset = 0; /*vb->buffer_offset * 4;*/
- unsigned size = vb->buffer->width0;
- unsigned upload_offset;
- ret = u_upload_buffer(r300->upload_vb,
- offset, size,
- vb->buffer,
- &upload_offset, &upload_buffer);
- if (ret)
- return ret;
-
- pipe_resource_reference(&vb->buffer, NULL);
- vb->buffer = upload_buffer;
- vb->buffer_offset = upload_offset;
+ unsigned index = r300->velems->velem[i].vertex_buffer_index;
+ struct pipe_vertex_buffer *vb = &r300->vertex_buffer[index];
+ struct r300_buffer *userbuf = r300_buffer(vb->buffer);
+
+ if (userbuf && userbuf->user_buffer && !uploaded[index]) {
+ unsigned first, size;
+
+ if (vb->stride) {
+ first = vb->stride * min_index;
+ size = vb->stride * count;
+ } else {
+ first = 0;
+ size = r300->velems->hw_format_size[i];
+ }
+
+ DBG(r300, DBG_UPLOAD,
+ "Uploading %i bytes, index: %i, buffer: %p, userptr: %p "
+ "offset: %i, stride: %i.\n",
+ size, index, userbuf, userbuf->user_buffer,
+ vb->buffer_offset, vb->stride);
+
+ u_upload_data(r300->upload_vb, first, size,
+ userbuf->user_buffer + first,
+ &vb->buffer_offset,
+ &r300->valid_vertex_buffer[index],
+ &flushed);
+
+ vb->buffer_offset -= first;
+
+ r300->vertex_arrays_dirty = TRUE;
+
+ if (flushed || !r300->upload_vb_validated) {
+ r300->upload_vb_validated = FALSE;
+ r300->validate_buffers = TRUE;
+ }
+ uploaded[index] = TRUE;
+ } else {
+ assert(r300->valid_vertex_buffer[index]);
}
}
- return ret;
+ DBG(r300, DBG_UPLOAD, "-------\n");
}
static void r300_buffer_destroy(struct pipe_screen *screen,
@@ -136,26 +146,26 @@ static void r300_buffer_destroy(struct pipe_screen *screen,
if (rbuf->buf)
rws->buffer_reference(rws, &rbuf->buf, NULL);
- util_mempool_free(&r300screen->pool_buffers, rbuf);
+ util_slab_free(&r300screen->pool_buffers, rbuf);
}
static struct pipe_transfer*
-r300_default_get_transfer(struct pipe_context *context,
- struct pipe_resource *resource,
- struct pipe_subresource sr,
- unsigned usage,
- const struct pipe_box *box)
+r300_buffer_get_transfer(struct pipe_context *context,
+ struct pipe_resource *resource,
+ unsigned level,
+ unsigned usage,
+ const struct pipe_box *box)
{
struct r300_context *r300 = r300_context(context);
struct pipe_transfer *transfer =
- util_mempool_malloc(&r300->pool_transfers);
+ util_slab_alloc(&r300->pool_transfers);
transfer->resource = resource;
- transfer->sr = sr;
+ transfer->level = level;
transfer->usage = usage;
transfer->box = *box;
transfer->stride = 0;
- transfer->slice_stride = 0;
+ transfer->layer_stride = 0;
transfer->data = NULL;
/* Note strides are zero, this is ok for buffers, but not for
@@ -164,11 +174,11 @@ r300_default_get_transfer(struct pipe_context *context,
return transfer;
}
-static void r300_default_transfer_destroy(struct pipe_context *pipe,
- struct pipe_transfer *transfer)
+static void r300_buffer_transfer_destroy(struct pipe_context *pipe,
+ struct pipe_transfer *transfer)
{
struct r300_context *r300 = r300_context(pipe);
- util_mempool_free(&r300->pool_transfers, transfer);
+ util_slab_free(&r300->pool_transfers, transfer);
}
static void *
@@ -180,46 +190,17 @@ r300_buffer_transfer_map( struct pipe_context *pipe,
struct r300_winsys_screen *rws = r300screen->rws;
struct r300_buffer *rbuf = r300_buffer(transfer->resource);
uint8_t *map;
- boolean flush = FALSE;
- unsigned i;
if (rbuf->user_buffer)
return (uint8_t *) rbuf->user_buffer + transfer->box.x;
if (rbuf->constant_buffer)
return (uint8_t *) rbuf->constant_buffer + transfer->box.x;
- /* check if the mapping is to a range we already flushed */
- if (transfer->usage & PIPE_TRANSFER_DISCARD) {
- for (i = 0; i < rbuf->num_ranges; i++) {
- if ((transfer->box.x >= rbuf->ranges[i].start) &&
- (transfer->box.x < rbuf->ranges[i].end))
- flush = TRUE;
-
- if (flush) {
- /* unreference this hw buffer and allocate a new one */
- rws->buffer_reference(rws, &rbuf->buf, NULL);
-
- rbuf->num_ranges = 0;
- rbuf->buf =
- r300screen->rws->buffer_create(r300screen->rws,
- rbuf->b.b.width0, 16,
- rbuf->b.b.bind,
- rbuf->b.b.usage,
- rbuf->domain);
- break;
- }
- }
- }
-
map = rws->buffer_map(rws, rbuf->buf, r300->cs, transfer->usage);
if (map == NULL)
return NULL;
- /* map_buffer() returned a pointer to the beginning of the buffer,
- * but transfers are expected to return a pointer to just the
- * region specified in the box.
- */
return map + transfer->box.x;
}
@@ -227,30 +208,7 @@ static void r300_buffer_transfer_flush_region( struct pipe_context *pipe,
struct pipe_transfer *transfer,
const struct pipe_box *box)
{
- struct r300_buffer *rbuf = r300_buffer(transfer->resource);
- unsigned i;
- unsigned offset = transfer->box.x + box->x;
- unsigned length = box->width;
-
- assert(box->x + box->width <= transfer->box.width);
-
- if (rbuf->user_buffer)
- return;
- if (rbuf->constant_buffer)
- return;
-
- /* mark the range as used */
- for(i = 0; i < rbuf->num_ranges; ++i) {
- if(offset <= rbuf->ranges[i].end && rbuf->ranges[i].start <= (offset+box->width)) {
- rbuf->ranges[i].start = MIN2(rbuf->ranges[i].start, offset);
- rbuf->ranges[i].end = MAX2(rbuf->ranges[i].end, (offset+length));
- return;
- }
- }
-
- rbuf->ranges[rbuf->num_ranges].start = offset;
- rbuf->ranges[rbuf->num_ranges].end = offset+length;
- rbuf->num_ranges++;
+ /* no-op */
}
static void r300_buffer_transfer_unmap( struct pipe_context *pipe,
@@ -265,17 +223,45 @@ static void r300_buffer_transfer_unmap( struct pipe_context *pipe,
}
}
-struct u_resource_vtbl r300_buffer_vtbl =
+static void r300_buffer_transfer_inline_write(struct pipe_context *pipe,
+ struct pipe_resource *resource,
+ unsigned level,
+ unsigned usage,
+ const struct pipe_box *box,
+ const void *data,
+ unsigned stride,
+ unsigned layer_stride)
+{
+ struct r300_context *r300 = r300_context(pipe);
+ struct r300_winsys_screen *rws = r300->screen->rws;
+ struct r300_buffer *rbuf = r300_buffer(resource);
+ uint8_t *map = NULL;
+
+ if (rbuf->constant_buffer) {
+ memcpy(rbuf->constant_buffer + box->x, data, box->width);
+ return;
+ }
+ assert(rbuf->user_buffer == NULL);
+
+ map = rws->buffer_map(rws, rbuf->buf, r300->cs,
+ PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD | usage);
+
+ memcpy(map + box->x, data, box->width);
+
+ rws->buffer_unmap(rws, rbuf->buf);
+}
+
+struct u_resource_vtbl r300_buffer_vtbl =
{
u_default_resource_get_handle, /* get_handle */
r300_buffer_destroy, /* resource_destroy */
r300_buffer_is_referenced_by_cs, /* is_buffer_referenced */
- r300_default_get_transfer, /* get_transfer */
- r300_default_transfer_destroy, /* transfer_destroy */
+ r300_buffer_get_transfer, /* get_transfer */
+ r300_buffer_transfer_destroy, /* transfer_destroy */
r300_buffer_transfer_map, /* transfer_map */
r300_buffer_transfer_flush_region, /* transfer_flush_region */
r300_buffer_transfer_unmap, /* transfer_unmap */
- u_default_transfer_inline_write /* transfer_inline_write */
+ r300_buffer_transfer_inline_write /* transfer_inline_write */
};
struct pipe_resource *r300_buffer_create(struct pipe_screen *screen,
@@ -285,7 +271,7 @@ struct pipe_resource *r300_buffer_create(struct pipe_screen *screen,
struct r300_buffer *rbuf;
unsigned alignment = 16;
- rbuf = util_mempool_malloc(&r300screen->pool_buffers);
+ rbuf = util_slab_alloc(&r300screen->pool_buffers);
rbuf->magic = R300_BUFFER_MAGIC;
@@ -294,7 +280,6 @@ struct pipe_resource *r300_buffer_create(struct pipe_screen *screen,
pipe_reference_init(&rbuf->b.b.reference, 1);
rbuf->b.b.screen = screen;
rbuf->domain = R300_DOMAIN_GTT;
- rbuf->num_ranges = 0;
rbuf->buf = NULL;
rbuf->constant_buffer = NULL;
rbuf->user_buffer = NULL;
@@ -310,9 +295,11 @@ struct pipe_resource *r300_buffer_create(struct pipe_screen *screen,
rbuf->b.b.width0, alignment,
rbuf->b.b.bind, rbuf->b.b.usage,
rbuf->domain);
+ rbuf->cs_buf =
+ r300screen->rws->buffer_get_cs_handle(r300screen->rws, rbuf->buf);
if (!rbuf->buf) {
- util_mempool_free(&r300screen->pool_buffers, rbuf);
+ util_slab_free(&r300screen->pool_buffers, rbuf);
return NULL;
}
@@ -320,14 +307,13 @@ struct pipe_resource *r300_buffer_create(struct pipe_screen *screen,
}
struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen,
- void *ptr,
- unsigned bytes,
+ void *ptr, unsigned size,
unsigned bind)
{
struct r300_screen *r300screen = r300_screen(screen);
struct r300_buffer *rbuf;
- rbuf = util_mempool_malloc(&r300screen->pool_buffers);
+ rbuf = util_slab_alloc(&r300screen->pool_buffers);
rbuf->magic = R300_BUFFER_MAGIC;
@@ -338,12 +324,12 @@ struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen,
rbuf->b.b.format = PIPE_FORMAT_R8_UNORM;
rbuf->b.b.usage = PIPE_USAGE_IMMUTABLE;
rbuf->b.b.bind = bind;
- rbuf->b.b.width0 = bytes;
+ rbuf->b.b.width0 = ~0;
rbuf->b.b.height0 = 1;
rbuf->b.b.depth0 = 1;
+ rbuf->b.b.array_size = 1;
rbuf->b.b.flags = 0;
rbuf->domain = R300_DOMAIN_GTT;
- rbuf->num_ranges = 0;
rbuf->buf = NULL;
rbuf->constant_buffer = NULL;
rbuf->user_buffer = ptr;