diff options
Diffstat (limited to 'src/gallium/winsys/drm/vmware/core/vmw_context.c')
-rw-r--r-- | src/gallium/winsys/drm/vmware/core/vmw_context.c | 78 |
1 files changed, 66 insertions, 12 deletions
diff --git a/src/gallium/winsys/drm/vmware/core/vmw_context.c b/src/gallium/winsys/drm/vmware/core/vmw_context.c index 87a3df923f..b5fd4f5a6a 100644 --- a/src/gallium/winsys/drm/vmware/core/vmw_context.c +++ b/src/gallium/winsys/drm/vmware/core/vmw_context.c @@ -41,9 +41,18 @@ #define VMW_COMMAND_SIZE (64*1024) #define VMW_SURFACE_RELOCS (1024) +#define VMW_REGION_RELOCS (512) #define VMW_MUST_FLUSH_STACK 8 +struct vmw_region_relocation +{ + struct SVGAGuestPtr *where; + struct pb_buffer *buffer; + /* TODO: put offset info inside where */ + uint32 offset; +}; + struct vmw_svga_winsys_context { struct svga_winsys_context base; @@ -69,6 +78,14 @@ struct vmw_svga_winsys_context uint32_t staged; uint32_t reserved; } surface; + + struct { + struct vmw_region_relocation relocs[VMW_REGION_RELOCS]; + uint32_t size; + uint32_t used; + uint32_t staged; + uint32_t reserved; + } region; struct pb_validate *validate; @@ -109,6 +126,19 @@ vmw_swc_flush(struct svga_winsys_context *swc, ret = pb_validate_validate(vswc->validate); assert(ret == PIPE_OK); if(ret == PIPE_OK) { + + /* Apply relocations */ + for(i = 0; i < vswc->region.used; ++i) { + struct vmw_region_relocation *reloc = &vswc->region.relocs[i]; + struct SVGAGuestPtr ptr; + + if(!vmw_gmr_bufmgr_region_ptr(reloc->buffer, &ptr)) + assert(0); + + ptr.offset += reloc->offset; + + *reloc->where = ptr; + } if (vswc->command.used) vmw_ioctl_command(vswc->vws, @@ -134,6 +164,13 @@ vmw_swc_flush(struct svga_winsys_context *swc, vswc->surface.used = 0; vswc->surface.reserved = 0; + for(i = 0; i < vswc->region.used + vswc->region.staged; ++i) { + pb_reference(&vswc->region.relocs[i].buffer, NULL); + } + + vswc->region.used = 0; + vswc->region.reserved = 0; + #ifdef DEBUG vswc->must_flush = FALSE; #endif @@ -168,7 +205,8 @@ vmw_swc_reserve(struct svga_winsys_context *swc, if(vswc->preemptive_flush || vswc->command.used + nr_bytes > vswc->command.size || - vswc->surface.used + nr_relocs > vswc->surface.size) { + vswc->surface.used + nr_relocs > vswc->surface.size || + vswc->region.used + nr_relocs > vswc->region.size) { #ifdef DEBUG vswc->must_flush = TRUE; debug_backtrace_capture(vswc->must_flush_stack, 1, @@ -179,11 +217,14 @@ vmw_swc_reserve(struct svga_winsys_context *swc, assert(vswc->command.used + nr_bytes <= vswc->command.size); assert(vswc->surface.used + nr_relocs <= vswc->surface.size); - + assert(vswc->region.used + nr_relocs <= vswc->region.size); + vswc->command.reserved = nr_bytes; vswc->surface.reserved = nr_relocs; vswc->surface.staged = 0; - + vswc->region.reserved = nr_relocs; + vswc->region.staged = 0; + return vswc->command.buffer + vswc->command.used; } @@ -222,18 +263,19 @@ vmw_swc_region_relocation(struct svga_winsys_context *swc, unsigned flags) { struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); - struct SVGAGuestPtr ptr; - struct pb_buffer *buf = vmw_pb_buffer(buffer); + struct vmw_region_relocation *reloc; enum pipe_error ret; + + assert(vswc->region.staged < vswc->region.reserved); - if(!vmw_gmr_bufmgr_region_ptr(buf, &ptr)) - assert(0); + reloc = &vswc->region.relocs[vswc->region.used + vswc->region.staged]; + reloc->where = where; + pb_reference(&reloc->buffer, vmw_pb_buffer(buffer)); + reloc->offset = offset; - ptr.offset += offset; + ++vswc->region.staged; - *where = ptr; - - ret = pb_validate_add_buffer(vswc->validate, buf, flags); + ret = pb_validate_add_buffer(vswc->validate, reloc->buffer, flags); /* TODO: Update pipebuffer to reserve buffers and not fail here */ assert(ret == PIPE_OK); @@ -253,7 +295,7 @@ vmw_swc_region_relocation(struct svga_winsys_context *swc, * SVGA virtual device it's not a performance issue since flushing commands * to the FIFO won't cause flushing in the host. */ - vswc->seen_regions += buf->base.size; + vswc->seen_regions += reloc->buffer->base.size; if(vswc->seen_regions >= VMW_GMR_POOL_SIZE/2) vswc->preemptive_flush = TRUE; } @@ -274,6 +316,12 @@ vmw_swc_commit(struct svga_winsys_context *swc) vswc->surface.used += vswc->surface.staged; vswc->surface.staged = 0; vswc->surface.reserved = 0; + + assert(vswc->region.staged <= vswc->region.reserved); + assert(vswc->region.used + vswc->region.staged <= vswc->region.size); + vswc->region.used += vswc->region.staged; + vswc->region.staged = 0; + vswc->region.reserved = 0; } @@ -282,6 +330,11 @@ vmw_swc_destroy(struct svga_winsys_context *swc) { struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); unsigned i; + + for(i = 0; i < vswc->region.used; ++i) { + pb_reference(&vswc->region.relocs[i].buffer, NULL); + } + for(i = 0; i < vswc->surface.used; ++i) { p_atomic_dec(&vswc->surface.handles[i]->validated); vmw_svga_winsys_surface_reference(&vswc->surface.handles[i], NULL); @@ -315,6 +368,7 @@ vmw_svga_winsys_context_create(struct svga_winsys_screen *sws) vswc->command.size = VMW_COMMAND_SIZE; vswc->surface.size = VMW_SURFACE_RELOCS; + vswc->region.size = VMW_REGION_RELOCS; vswc->validate = pb_validate_create(); if(!vswc->validate) { |