summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/winsys/svga/drm/vmw_context.c30
-rw-r--r--src/gallium/winsys/svga/drm/vmw_screen.c5
-rw-r--r--src/gallium/winsys/svga/drm/vmw_screen.h5
3 files changed, 38 insertions, 2 deletions
diff --git a/src/gallium/winsys/svga/drm/vmw_context.c b/src/gallium/winsys/svga/drm/vmw_context.c
index 002994e9dc9..00c401a0174 100644
--- a/src/gallium/winsys/svga/drm/vmw_context.c
+++ b/src/gallium/winsys/svga/drm/vmw_context.c
@@ -179,11 +179,36 @@ vmw_swc_flush(struct svga_winsys_context *swc,
struct pipe_fence_handle **pfence)
{
struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
+ struct vmw_winsys_screen *vws = vswc->vws;
struct pipe_fence_handle *fence = NULL;
unsigned i;
enum pipe_error ret;
+ /*
+ * If we hit a retry, lock the mutex and retry immediately.
+ * If we then still hit a retry, sleep until another thread
+ * wakes us up after it has released its buffers from the
+ * validate list.
+ *
+ * If we hit another error condition, we still need to broadcast since
+ * pb_validate_validate releases validated buffers in its error path.
+ */
+
ret = pb_validate_validate(vswc->validate);
+ if (ret != PIPE_OK) {
+ pipe_mutex_lock(vws->cs_mutex);
+ while (ret == PIPE_ERROR_RETRY) {
+ ret = pb_validate_validate(vswc->validate);
+ if (ret == PIPE_ERROR_RETRY) {
+ pipe_condvar_wait(vws->cs_cond, vws->cs_mutex);
+ }
+ }
+ if (ret != PIPE_OK) {
+ pipe_condvar_broadcast(vws->cs_cond);
+ }
+ pipe_mutex_unlock(vws->cs_mutex);
+ }
+
assert(ret == PIPE_OK);
if(ret == PIPE_OK) {
@@ -210,7 +235,7 @@ vmw_swc_flush(struct svga_winsys_context *swc,
}
if (vswc->command.used || pfence != NULL)
- vmw_ioctl_command(vswc->vws,
+ vmw_ioctl_command(vws,
vswc->base.cid,
0,
vswc->command.buffer,
@@ -218,6 +243,9 @@ vmw_swc_flush(struct svga_winsys_context *swc,
&fence);
pb_validate_fence(vswc->validate, fence);
+ pipe_mutex_lock(vws->cs_mutex);
+ pipe_condvar_broadcast(vws->cs_cond);
+ pipe_mutex_unlock(vws->cs_mutex);
}
vswc->command.used = 0;
diff --git a/src/gallium/winsys/svga/drm/vmw_screen.c b/src/gallium/winsys/svga/drm/vmw_screen.c
index d0bfcd728bf..6041598cac1 100644
--- a/src/gallium/winsys/svga/drm/vmw_screen.c
+++ b/src/gallium/winsys/svga/drm/vmw_screen.c
@@ -109,6 +109,9 @@ vmw_winsys_create( int fd )
if (util_hash_table_set(dev_hash, &vws->device, vws) != PIPE_OK)
goto out_no_hash_insert;
+ pipe_condvar_init(vws->cs_cond);
+ pipe_mutex_init(vws->cs_mutex);
+
return vws;
out_no_hash_insert:
out_no_svga:
@@ -133,6 +136,8 @@ vmw_winsys_destroy(struct vmw_winsys_screen *vws)
vws->fence_ops->destroy(vws->fence_ops);
vmw_ioctl_cleanup(vws);
close(vws->ioctl.drm_fd);
+ pipe_mutex_destroy(vws->cs_mutex);
+ pipe_condvar_destroy(vws->cs_cond);
FREE(vws);
}
}
diff --git a/src/gallium/winsys/svga/drm/vmw_screen.h b/src/gallium/winsys/svga/drm/vmw_screen.h
index 79d0949e96a..c1cc7c32535 100644
--- a/src/gallium/winsys/svga/drm/vmw_screen.h
+++ b/src/gallium/winsys/svga/drm/vmw_screen.h
@@ -40,7 +40,7 @@
#include "svga_winsys.h"
#include "pipebuffer/pb_buffer_fenced.h"
-
+#include <os/os_thread.h>
#define VMW_GMR_POOL_SIZE (16*1024*1024)
#define VMW_QUERY_POOL_SIZE (8192)
@@ -99,6 +99,9 @@ struct vmw_winsys_screen
*/
dev_t device;
int open_count;
+
+ pipe_condvar cs_cond;
+ pipe_mutex cs_mutex;
};