r600g: keep a mapping around for each bo
Save a lot of call into the kernel and thus improve performances. Signed-off-by: Jerome Glisse <jglisse@redhat.com>
This commit is contained in:
@@ -33,7 +33,6 @@
|
||||
#include <pipebuffer/pb_bufmgr.h>
|
||||
#include "r600.h"
|
||||
|
||||
|
||||
struct radeon {
|
||||
int fd;
|
||||
int refcount;
|
||||
@@ -83,8 +82,6 @@ struct radeon_bo *radeon_bo_pb_get_bo(struct pb_buffer *_buf);
|
||||
void r600_context_bo_reloc(struct r600_context *ctx, u32 *pm4, struct radeon_bo *bo);
|
||||
struct radeon_bo *radeon_bo(struct radeon *radeon, unsigned handle,
|
||||
unsigned size, unsigned alignment, void *ptr);
|
||||
int radeon_bo_map(struct radeon *radeon, struct radeon_bo *bo);
|
||||
void radeon_bo_unmap(struct radeon *radeon, struct radeon_bo *bo);
|
||||
void radeon_bo_reference(struct radeon *radeon, struct radeon_bo **dst,
|
||||
struct radeon_bo *src);
|
||||
int radeon_bo_wait(struct radeon *radeon, struct radeon_bo *bo);
|
||||
@@ -145,4 +142,15 @@ static inline void r600_context_block_emit_dirty(struct r600_context *ctx, struc
|
||||
block->status ^= R600_BLOCK_STATUS_DIRTY;
|
||||
}
|
||||
|
||||
static inline int radeon_bo_map(struct radeon *radeon, struct radeon_bo *bo)
|
||||
{
|
||||
bo->map_count++;
|
||||
}
|
||||
|
||||
static inline void radeon_bo_unmap(struct radeon *radeon, struct radeon_bo *bo)
|
||||
{
|
||||
bo->map_count--;
|
||||
assert(bo->map_count >= 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,6 +33,43 @@
|
||||
#include "xf86drm.h"
|
||||
#include "radeon_drm.h"
|
||||
|
||||
static int radeon_bo_fixed_map(struct radeon *radeon, struct radeon_bo *bo)
|
||||
{
|
||||
struct drm_radeon_gem_mmap args;
|
||||
void *ptr;
|
||||
int r;
|
||||
|
||||
/* Zero out args to make valgrind happy */
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.handle = bo->handle;
|
||||
args.offset = 0;
|
||||
args.size = (uint64_t)bo->size;
|
||||
r = drmCommandWriteRead(radeon->fd, DRM_RADEON_GEM_MMAP,
|
||||
&args, sizeof(args));
|
||||
if (r) {
|
||||
fprintf(stderr, "error mapping %p 0x%08X (error = %d)\n",
|
||||
bo, bo->handle, r);
|
||||
return r;
|
||||
}
|
||||
ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, radeon->fd, args.addr_ptr);
|
||||
if (ptr == MAP_FAILED) {
|
||||
fprintf(stderr, "%s failed to map bo\n", __func__);
|
||||
return -errno;
|
||||
}
|
||||
bo->data = ptr;
|
||||
|
||||
success:
|
||||
bo->map_count++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void radeon_bo_fixed_unmap(struct radeon *radeon, struct radeon_bo *bo)
|
||||
{
|
||||
munmap(bo->data, bo->size);
|
||||
bo->data = NULL;
|
||||
}
|
||||
|
||||
struct radeon_bo *radeon_bo(struct radeon *radeon, unsigned handle,
|
||||
unsigned size, unsigned alignment, void *ptr)
|
||||
{
|
||||
@@ -79,65 +116,23 @@ struct radeon_bo *radeon_bo(struct radeon *radeon, unsigned handle,
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (radeon_bo_fixed_map(radeon, bo)) {
|
||||
R600_ERR("failed to map bo\n");
|
||||
radeon_bo_reference(radeon, &bo, NULL);
|
||||
return bo;
|
||||
}
|
||||
if (ptr) {
|
||||
if (radeon_bo_map(radeon, bo)) {
|
||||
fprintf(stderr, "%s failed to copy data into bo\n", __func__);
|
||||
radeon_bo_reference(radeon, &bo, NULL);
|
||||
return bo;
|
||||
}
|
||||
memcpy(bo->data, ptr, size);
|
||||
radeon_bo_unmap(radeon, bo);
|
||||
}
|
||||
return bo;
|
||||
}
|
||||
|
||||
int radeon_bo_map(struct radeon *radeon, struct radeon_bo *bo)
|
||||
{
|
||||
struct drm_radeon_gem_mmap args;
|
||||
void *ptr;
|
||||
int r;
|
||||
|
||||
if (bo->map_count != 0) {
|
||||
goto success;
|
||||
}
|
||||
/* Zero out args to make valgrind happy */
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.handle = bo->handle;
|
||||
args.offset = 0;
|
||||
args.size = (uint64_t)bo->size;
|
||||
r = drmCommandWriteRead(radeon->fd, DRM_RADEON_GEM_MMAP,
|
||||
&args, sizeof(args));
|
||||
if (r) {
|
||||
fprintf(stderr, "error mapping %p 0x%08X (error = %d)\n",
|
||||
bo, bo->handle, r);
|
||||
return r;
|
||||
}
|
||||
ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, radeon->fd, args.addr_ptr);
|
||||
if (ptr == MAP_FAILED) {
|
||||
fprintf(stderr, "%s failed to map bo\n", __func__);
|
||||
return -errno;
|
||||
}
|
||||
bo->data = ptr;
|
||||
|
||||
success:
|
||||
bo->map_count++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void radeon_bo_unmap(struct radeon *radeon, struct radeon_bo *bo)
|
||||
{
|
||||
if (--bo->map_count > 0) {
|
||||
return;
|
||||
}
|
||||
munmap(bo->data, bo->size);
|
||||
bo->data = NULL;
|
||||
}
|
||||
|
||||
static void radeon_bo_destroy(struct radeon *radeon, struct radeon_bo *bo)
|
||||
{
|
||||
struct drm_gem_close args;
|
||||
|
||||
radeon_bo_fixed_unmap(radeon, bo);
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.handle = bo->handle;
|
||||
drmIoctl(radeon->fd, DRM_IOCTL_GEM_CLOSE, &args);
|
||||
|
||||
Reference in New Issue
Block a user