diff options
Diffstat (limited to 'src/gallium/winsys/radeon/drm/radeon_drm_bo.c')
-rw-r--r-- | src/gallium/winsys/radeon/drm/radeon_drm_bo.c | 55 |
1 files changed, 53 insertions, 2 deletions
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c index 3f58b00..f9cf2e0 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c @@ -53,7 +53,7 @@ struct radeon_bo_va_hole { uint64_t size; }; -static bool radeon_bo_is_busy(struct radeon_bo *bo) +static bool radeon_real_bo_is_busy(struct radeon_bo *bo) { struct drm_radeon_gem_busy args = {0}; @@ -62,7 +62,31 @@ static bool radeon_bo_is_busy(struct radeon_bo *bo) &args, sizeof(args)) != 0; } -static void radeon_bo_wait_idle(struct radeon_bo *bo) +static bool radeon_bo_is_busy(struct radeon_bo *bo) +{ + unsigned num_idle; + bool busy = false; + + if (bo->handle) + return radeon_real_bo_is_busy(bo); + + pipe_mutex_lock(bo->rws->bo_fence_lock); + for (num_idle = 0; num_idle < bo->u.slab.num_fences; ++num_idle) { + if (radeon_real_bo_is_busy(bo->u.slab.fences[num_idle])) { + busy = true; + break; + } + radeon_bo_reference(&bo->u.slab.fences[num_idle], NULL); + } + memmove(&bo->u.slab.fences[0], &bo->u.slab.fences[num_idle], + (bo->u.slab.num_fences - num_idle) * sizeof(bo->u.slab.fences[0])); + bo->u.slab.num_fences -= num_idle; + pipe_mutex_unlock(bo->rws->bo_fence_lock); + + return busy; +} + +static void radeon_real_bo_wait_idle(struct radeon_bo *bo) { struct drm_radeon_gem_wait_idle args = {0}; @@ -71,6 +95,33 @@ static void radeon_bo_wait_idle(struct radeon_bo *bo) &args, sizeof(args)) == -EBUSY); } +static void radeon_bo_wait_idle(struct radeon_bo *bo) +{ + if (bo->handle) { + radeon_real_bo_wait_idle(bo); + } else { + pipe_mutex_lock(bo->rws->bo_fence_lock); + while (bo->u.slab.num_fences) { + struct radeon_bo *fence = NULL; + radeon_bo_reference(&fence, bo->u.slab.fences[0]); + pipe_mutex_unlock(bo->rws->bo_fence_lock); + + /* Wait without holding the fence lock. */ + radeon_real_bo_wait_idle(fence); + + pipe_mutex_lock(bo->rws->bo_fence_lock); + if (bo->u.slab.num_fences && fence == bo->u.slab.fences[0]) { + radeon_bo_reference(&bo->u.slab.fences[0], NULL); + memmove(&bo->u.slab.fences[0], &bo->u.slab.fences[1], + (bo->u.slab.num_fences - 1) * sizeof(bo->u.slab.fences[0])); + bo->u.slab.num_fences--; + } + radeon_bo_reference(&fence, NULL); + } + pipe_mutex_unlock(bo->rws->bo_fence_lock); + } +} + static bool radeon_bo_wait(struct pb_buffer *_buf, uint64_t timeout, enum radeon_bo_usage usage) { |