diff options
Diffstat (limited to 'src/gallium/drivers/svga/svga_resource_buffer_upload.c')
-rw-r--r-- | src/gallium/drivers/svga/svga_resource_buffer_upload.c | 91 |
1 files changed, 78 insertions, 13 deletions
diff --git a/src/gallium/drivers/svga/svga_resource_buffer_upload.c b/src/gallium/drivers/svga/svga_resource_buffer_upload.c index 3de5216a94..0bfa8a14a6 100644 --- a/src/gallium/drivers/svga/svga_resource_buffer_upload.c +++ b/src/gallium/drivers/svga/svga_resource_buffer_upload.c @@ -40,6 +40,9 @@ #include "svga_debug.h" +#define MAX_DMA_SIZE (4 * 1024 * 1024) + + /** * Allocate a winsys_buffer (ie. DMA, aka GMR memory). * @@ -57,6 +60,13 @@ svga_winsys_buffer_create( struct svga_context *svga, struct svga_winsys_screen *sws = svgascreen->sws; struct svga_winsys_buffer *buf; + /* XXX this shouldn't be a hard-coded number; it should be queried + * somehow. + */ + if (size > MAX_DMA_SIZE) { + return NULL; + } + /* Just try */ buf = sws->buffer_create(sws, alignment, usage, size); if(!buf) { @@ -242,12 +252,17 @@ svga_buffer_upload_command(struct svga_context *svga, * Patch up the upload DMA command reserved by svga_buffer_upload_command * with the final ranges. */ -static void +void svga_buffer_upload_flush(struct svga_context *svga, struct svga_buffer *sbuf) { SVGA3dCopyBox *boxes; unsigned i; + struct pipe_resource *dummy; + + if (!sbuf->dma.pending) { + return; + } assert(sbuf->handle); assert(sbuf->hwbuf); @@ -285,17 +300,18 @@ svga_buffer_upload_flush(struct svga_context *svga, sbuf->head.next = sbuf->head.prev = NULL; #endif sbuf->dma.pending = FALSE; + sbuf->dma.flags.discard = FALSE; + sbuf->dma.flags.unsynchronized = FALSE; sbuf->dma.svga = NULL; sbuf->dma.boxes = NULL; - /* Decrement reference count */ - pipe_reference(&(sbuf->b.b.reference), NULL); - sbuf = NULL; + /* Decrement reference count (and potentially destroy) */ + dummy = &sbuf->b.b; + pipe_resource_reference(&dummy, NULL); } - /** * Note a dirty range. * @@ -326,12 +342,6 @@ svga_buffer_add_range(struct svga_buffer *sbuf, /* * Try to grow one of the ranges. - * - * Note that it is not this function task to care about overlapping ranges, - * as the GMR was already given so it is too late to do anything. Situations - * where overlapping ranges may pose a problem should be detected via - * pipe_context::is_resource_referenced and the context that refers to the - * buffer should be flushed. */ for(i = 0; i < sbuf->map.num_ranges; ++i) { @@ -346,6 +356,11 @@ svga_buffer_add_range(struct svga_buffer *sbuf, if (dist <= 0) { /* * Ranges are contiguous or overlapping -- extend this one and return. + * + * Note that it is not this function's task to prevent overlapping + * ranges, as the GMR was already given so it is too late to do + * anything. If the ranges overlap here it must surely be because + * PIPE_TRANSFER_UNSYNCHRONIZED was set. */ sbuf->map.ranges[i].start = MIN2(sbuf->map.ranges[i].start, start); @@ -369,8 +384,7 @@ svga_buffer_add_range(struct svga_buffer *sbuf, * pending DMA upload and start clean. */ - if(sbuf->dma.pending) - svga_buffer_upload_flush(sbuf->dma.svga, sbuf); + svga_buffer_upload_flush(sbuf->dma.svga, sbuf); assert(!sbuf->dma.pending); assert(!sbuf->dma.svga); @@ -638,3 +652,54 @@ svga_context_flush_buffers(struct svga_context *svga) next = curr->next; } } + + +void +svga_redefine_user_buffer(struct pipe_context *pipe, + struct pipe_resource *resource, + unsigned offset, + unsigned size) +{ + struct svga_screen *ss = svga_screen(pipe->screen); + struct svga_context *svga = svga_context(pipe); + struct svga_buffer *sbuf = svga_buffer(resource); + + assert(sbuf->user); + + /* + * Release any uploaded user buffer. + * + * TODO: As an optimization, we could try to update the uploaded buffer + * instead. + */ + + pipe_resource_reference(&sbuf->uploaded.buffer, NULL); + + pipe_mutex_lock(ss->swc_mutex); + + if (offset + size > resource->width0) { + /* + * User buffers shouldn't have DMA directly, unless + * SVGA_COMBINE_USERBUFFERS is not set. + */ + + if (sbuf->dma.pending) { + svga_buffer_upload_flush(svga, sbuf); + } + + if (sbuf->handle) { + svga_buffer_destroy_host_surface(ss, sbuf); + } + + if (sbuf->hwbuf) { + svga_buffer_destroy_hw_storage(ss, sbuf); + } + + sbuf->key.size.width = sbuf->b.b.width0 = offset + size; + } + + pipe_mutex_unlock(ss->swc_mutex); + + svga->curr.any_user_vertex_buffers = TRUE; + svga->dirty |= SVGA_NEW_VBUFFER | SVGA_NEW_VELEMENT; +} |