winsys/radeon: hook up the new DRM_RADEON_GEM_WAIT ioctl

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Marek Olšák 2011-08-07 19:04:37 +02:00
parent 296b899095
commit 1e3c81a068
4 changed files with 65 additions and 24 deletions

View file

@ -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;
}

View file

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

View file

@ -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;
}

View file

@ -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.