From 1e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Sun, 7 Aug 2011 19:04:37 +0200 Subject: [PATCH] winsys/radeon: hook up the new DRM_RADEON_GEM_WAIT ioctl Reviewed-by: Alex Deucher --- src/gallium/drivers/r300/r300_screen.c | 6 +- src/gallium/drivers/r300/r300_transfer.c | 2 +- src/gallium/winsys/radeon/drm/radeon_drm_bo.c | 67 ++++++++++++++----- src/gallium/winsys/radeon/drm/radeon_winsys.h | 14 +++- 4 files changed, 65 insertions(+), 24 deletions(-) diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 674bd24953c..13d25ba7dba 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -454,7 +454,7 @@ static boolean r300_fence_signalled(struct pipe_screen *screen, struct radeon_winsys *rws = r300_screen(screen)->rws; struct pb_buffer *rfence = (struct pb_buffer*)fence; - return !rws->buffer_is_busy(rfence); + return !rws->buffer_is_busy(rfence, RADEON_USAGE_READWRITE); } static boolean r300_fence_finish(struct pipe_screen *screen, @@ -471,7 +471,7 @@ static boolean r300_fence_finish(struct pipe_screen *screen, timeout /= 1000; /* Wait in a loop. */ - while (rws->buffer_is_busy(rfence)) { + while (rws->buffer_is_busy(rfence, RADEON_USAGE_READWRITE)) { if (os_time_get() - start_time >= timeout) { return FALSE; } @@ -480,7 +480,7 @@ static boolean r300_fence_finish(struct pipe_screen *screen, return TRUE; } - rws->buffer_wait(rfence); + rws->buffer_wait(rfence, RADEON_USAGE_READWRITE); return TRUE; } diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c index e2ea4cbf6c5..65964020adc 100644 --- a/src/gallium/drivers/r300/r300_transfer.c +++ b/src/gallium/drivers/r300/r300_transfer.c @@ -97,7 +97,7 @@ r300_texture_get_transfer(struct pipe_context *ctx, referenced_hw = TRUE; } else { referenced_hw = - r300->rws->buffer_is_busy(tex->buf); + r300->rws->buffer_is_busy(tex->buf, RADEON_USAGE_READWRITE); } blittable = desc->layout == UTIL_FORMAT_LAYOUT_PLAIN || diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c index 1c8a2b8305e..5c91ec48942 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c @@ -43,6 +43,21 @@ #define RADEON_BO_FLAGS_MICRO_TILE 2 #define RADEON_BO_FLAGS_MICRO_TILE_SQUARE 0x20 +#ifndef DRM_RADEON_GEM_WAIT +#define DRM_RADEON_GEM_WAIT 0x2b + +#define RADEON_GEM_NO_WAIT 0x1 +#define RADEON_GEM_USAGE_READ 0x2 +#define RADEON_GEM_USAGE_WRITE 0x4 + +struct drm_radeon_gem_wait { + uint32_t handle; + uint32_t flags; /* one of RADEON_GEM_* */ +}; + +#endif + + extern const struct pb_vtbl radeon_bo_vtbl; @@ -87,35 +102,49 @@ static struct radeon_bo *get_radeon_bo(struct pb_buffer *_buf) return bo; } -static void radeon_bo_wait(struct pb_buffer *_buf) +static void radeon_bo_wait(struct pb_buffer *_buf, enum radeon_bo_usage usage) { struct radeon_bo *bo = get_radeon_bo(_buf); - struct drm_radeon_gem_wait_idle args = {}; while (p_atomic_read(&bo->num_active_ioctls)) { sched_yield(); } - args.handle = bo->handle; - while (drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT_IDLE, - &args, sizeof(args)) == -EBUSY); + if (bo->rws->info.drm_minor >= 12) { + struct drm_radeon_gem_wait args = {}; + args.handle = bo->handle; + args.flags = usage; + while (drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT, + &args, sizeof(args)) == -EBUSY); + } else { + struct drm_radeon_gem_wait_idle args = {}; + args.handle = bo->handle; + while (drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT_IDLE, + &args, sizeof(args)) == -EBUSY); + } } -static boolean radeon_bo_is_busy(struct pb_buffer *_buf) +static boolean radeon_bo_is_busy(struct pb_buffer *_buf, + enum radeon_bo_usage usage) { struct radeon_bo *bo = get_radeon_bo(_buf); - struct drm_radeon_gem_busy args = {}; - boolean busy; if (p_atomic_read(&bo->num_active_ioctls)) { return TRUE; } - args.handle = bo->handle; - busy = drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_BUSY, - &args, sizeof(args)) != 0; - - return busy; + if (bo->rws->info.drm_minor >= 12) { + struct drm_radeon_gem_wait args = {}; + args.handle = bo->handle; + args.flags = usage | RADEON_GEM_NO_WAIT; + return drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT, + &args, sizeof(args)) != 0; + } else { + struct drm_radeon_gem_busy args = {}; + args.handle = bo->handle; + return drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_BUSY, + &args, sizeof(args)) != 0; + } } static void radeon_bo_destroy(struct pb_buffer *_buf) @@ -173,7 +202,7 @@ static void *radeon_bo_map_internal(struct pb_buffer *_buf, return NULL; } - if (radeon_bo_is_busy((struct pb_buffer*)bo)) { + if (radeon_bo_is_busy((struct pb_buffer*)bo, RADEON_USAGE_READWRITE)) { return NULL; } } else { @@ -187,10 +216,12 @@ static void *radeon_bo_map_internal(struct pb_buffer *_buf, * Only check whether the buffer is being used for write. */ if (radeon_bo_is_referenced_by_cs_for_write(cs, bo)) { cs->flush_cs(cs->flush_data, 0); - radeon_bo_wait((struct pb_buffer*)bo); + radeon_bo_wait((struct pb_buffer*)bo, + RADEON_USAGE_READWRITE); } else { /* XXX We could check whether the buffer is busy for write here. */ - radeon_bo_wait((struct pb_buffer*)bo); + radeon_bo_wait((struct pb_buffer*)bo, + RADEON_USAGE_READWRITE); } } else { /* Mapping for write. */ @@ -202,7 +233,7 @@ static void *radeon_bo_map_internal(struct pb_buffer *_buf, radeon_drm_cs_sync_flush(cs); } - radeon_bo_wait((struct pb_buffer*)bo); + radeon_bo_wait((struct pb_buffer*)bo, RADEON_USAGE_READWRITE); } } } @@ -338,7 +369,7 @@ static boolean radeon_bomgr_is_buffer_busy(struct pb_manager *_mgr, return TRUE; } - if (radeon_bo_is_busy((struct pb_buffer*)bo)) { + if (radeon_bo_is_busy((struct pb_buffer*)bo, RADEON_USAGE_READWRITE)) { return TRUE; } diff --git a/src/gallium/winsys/radeon/drm/radeon_winsys.h b/src/gallium/winsys/radeon/drm/radeon_winsys.h index bf5b144fe2c..90583e3ab8c 100644 --- a/src/gallium/winsys/radeon/drm/radeon_winsys.h +++ b/src/gallium/winsys/radeon/drm/radeon_winsys.h @@ -61,6 +61,12 @@ enum radeon_bo_domain { /* bitfield */ RADEON_DOMAIN_VRAM = 4 }; +enum radeon_bo_usage { /* bitfield */ + RADEON_USAGE_READ = 2, + RADEON_USAGE_WRITE = 4, + RADEON_USAGE_READWRITE = RADEON_USAGE_READ | RADEON_USAGE_WRITE +}; + struct winsys_handle; struct radeon_winsys_cs_handle; /* for write_reloc etc. */ @@ -162,8 +168,10 @@ struct radeon_winsys { * Return TRUE if a buffer object is being used by the GPU. * * \param buf A winsys buffer object. + * \param usage Only check whether the buffer is busy for the given usage. */ - boolean (*buffer_is_busy)(struct pb_buffer *buf); + boolean (*buffer_is_busy)(struct pb_buffer *buf, + enum radeon_bo_usage usage); /** * Wait for a buffer object until it is not used by a GPU. This is @@ -171,8 +179,10 @@ struct radeon_winsys { * and synchronizing to the fence. * * \param buf A winsys buffer object to wait for. + * \param usage Only wait until the buffer is idle for the given usage, + * but may still be busy for some other usage. */ - void (*buffer_wait)(struct pb_buffer *buf); + void (*buffer_wait)(struct pb_buffer *buf, enum radeon_bo_usage usage); /** * Return tiling flags describing a memory layout of a buffer object. -- 2.30.2