|
|
@@ -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) { |