diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c index 3a9ac445b24..600ced924ba 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c @@ -101,30 +101,54 @@ static struct radeon_bo *get_radeon_bo(struct pb_buffer *_buf) return bo; } +static bool radeon_bo_is_busy(struct radeon_bo *bo) +{ + struct drm_radeon_gem_busy args = {0}; + + args.handle = bo->handle; + return drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_BUSY, + &args, sizeof(args)) != 0; +} + +static void radeon_bo_wait_idle(struct radeon_bo *bo) +{ + struct drm_radeon_gem_wait_idle args = {0}; + + args.handle = bo->handle; + while (drmCommandWrite(bo->rws->fd, DRM_RADEON_GEM_WAIT_IDLE, + &args, sizeof(args)) == -EBUSY); +} + static bool radeon_bo_wait(struct pb_buffer *_buf, uint64_t timeout, enum radeon_bo_usage usage) { - struct radeon_bo *bo = get_radeon_bo(_buf); + struct radeon_bo *bo = get_radeon_bo(_buf); + int64_t abs_timeout; - /* Wait if any ioctl is being submitted with this buffer. */ - if (!os_wait_until_zero(&bo->num_active_ioctls, timeout)) - return false; + /* No timeout. Just query. */ + if (timeout == 0) + return !bo->num_active_ioctls && !radeon_bo_is_busy(bo); - /* TODO: handle arbitrary timeout */ - if (!timeout) { - struct drm_radeon_gem_busy args = {0}; + abs_timeout = os_time_get_absolute_timeout(timeout); - args.handle = bo->handle; - return drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_BUSY, - &args, sizeof(args)) == 0; - } else { - struct drm_radeon_gem_wait_idle args = {0}; + /* Wait if any ioctl is being submitted with this buffer. */ + if (!os_wait_until_zero_abs_timeout(&bo->num_active_ioctls, abs_timeout)) + return false; - args.handle = bo->handle; - while (drmCommandWrite(bo->rws->fd, DRM_RADEON_GEM_WAIT_IDLE, - &args, sizeof(args)) == -EBUSY); + /* Infinite timeout. */ + if (abs_timeout == PIPE_TIMEOUT_INFINITE) { + radeon_bo_wait_idle(bo); return true; } + + /* Other timeouts need to be emulated with a loop. */ + while (radeon_bo_is_busy(bo)) { + if (os_time_get_nano() >= abs_timeout) + return false; + os_time_sleep(10); + } + + return true; } static enum radeon_bo_domain get_valid_domain(enum radeon_bo_domain domain) diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c index f04a696988a..341af55df8b 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c @@ -645,29 +645,8 @@ static bool radeon_fence_wait(struct radeon_winsys *ws, struct pipe_fence_handle *fence, uint64_t timeout) { - struct pb_buffer *rfence = (struct pb_buffer*)fence; - - if (timeout == 0) - return ws->buffer_wait(rfence, 0, RADEON_USAGE_READWRITE); - - if (timeout != PIPE_TIMEOUT_INFINITE) { - int64_t start_time = os_time_get(); - - /* Convert to microseconds. */ - timeout /= 1000; - - /* Wait in a loop. */ - while (!ws->buffer_wait(rfence, 0, RADEON_USAGE_READWRITE)) { - if (os_time_get() - start_time >= timeout) { - return FALSE; - } - os_time_sleep(10); - } - return TRUE; - } - - ws->buffer_wait(rfence, PIPE_TIMEOUT_INFINITE, RADEON_USAGE_READWRITE); - return TRUE; + return ws->buffer_wait((struct pb_buffer*)fence, timeout, + RADEON_USAGE_READWRITE); } static void radeon_fence_reference(struct pipe_fence_handle **dst,