[libdrm/intel] Reuse entire dri_bo_gem structure

The code was discarding the dri_bo_gem structure and saving only the kernel
handle. This lost the mmap address, causing pain when the next buffer user
wanted to map the buffer.
This commit is contained in:
Keith Packard 2008-06-05 15:58:09 -07:00
parent 5f5badb26f
commit a919ff5d5e

View file

@ -55,14 +55,15 @@
fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, __VA_ARGS__); \
} while (0) } while (0)
typedef struct _dri_bo_gem dri_bo_gem;
struct intel_validate_entry { struct intel_validate_entry {
dri_bo *bo; dri_bo_gem *bo_gem;
struct drm_i915_op_arg bo_arg; struct drm_i915_op_arg bo_arg;
}; };
struct dri_gem_bo_bucket_entry { struct dri_gem_bo_bucket_entry {
uint32_t gem_handle; dri_bo_gem *bo_gem;
uint32_t last_offset;
struct dri_gem_bo_bucket_entry *next; struct dri_gem_bo_bucket_entry *next;
}; };
@ -103,7 +104,7 @@ typedef struct _dri_bufmgr_gem {
struct drm_i915_gem_execbuffer exec_arg; struct drm_i915_gem_execbuffer exec_arg;
} dri_bufmgr_gem; } dri_bufmgr_gem;
typedef struct _dri_bo_gem { struct _dri_bo_gem {
dri_bo bo; dri_bo bo;
int refcount; int refcount;
@ -133,7 +134,7 @@ typedef struct _dri_bo_gem {
int reloc_count; int reloc_count;
/** Mapped address for the buffer */ /** Mapped address for the buffer */
void *virtual; void *virtual;
} dri_bo_gem; };
static int static int
logbase2(int n) logbase2(int n)
@ -270,24 +271,21 @@ dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name,
int ret; int ret;
struct dri_gem_bo_bucket *bucket; struct dri_gem_bo_bucket *bucket;
int alloc_from_cache = 0; int alloc_from_cache = 0;
unsigned long bo_size;
bo_gem = calloc(1, sizeof(*bo_gem));
if (!bo_gem)
return NULL;
/* Round the allocated size up to a power of two number of pages. */ /* Round the allocated size up to a power of two number of pages. */
bo_gem->bo.size = 1 << logbase2(size); bo_size = 1 << logbase2(size);
if (bo_gem->bo.size < page_size) if (bo_size < page_size)
bo_gem->bo.size = page_size; bo_size = page_size;
bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo_gem->bo.size); bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo_size);
/* If we don't have caching at this size, don't actually round the /* If we don't have caching at this size, don't actually round the
* allocation up. * allocation up.
*/ */
if (bucket == NULL || bucket->max_entries == 0) { if (bucket == NULL || bucket->max_entries == 0) {
bo_gem->bo.size = size; bo_size = size;
if (bo_gem->bo.size < page_size) if (bo_size < page_size)
bo_gem->bo.size = page_size; bo_size = page_size;
} }
/* Get a buffer out of the cache if available */ /* Get a buffer out of the cache if available */
@ -295,7 +293,9 @@ dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name,
struct dri_gem_bo_bucket_entry *entry = bucket->head; struct dri_gem_bo_bucket_entry *entry = bucket->head;
struct drm_i915_gem_busy busy; struct drm_i915_gem_busy busy;
busy.handle = entry->gem_handle; bo_gem = entry->bo_gem;
busy.handle = bo_gem->gem_handle;
ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_BUSY, &busy); ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
alloc_from_cache = (ret == 0 && busy.busy == 0); alloc_from_cache = (ret == 0 && busy.busy == 0);
@ -305,8 +305,6 @@ dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name,
bucket->tail = &bucket->head; bucket->tail = &bucket->head;
bucket->num_entries--; bucket->num_entries--;
bo_gem->gem_handle = entry->gem_handle;
bo_gem->bo.offset = entry->last_offset;
free(entry); free(entry);
} }
} }
@ -314,8 +312,13 @@ dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name,
if (!alloc_from_cache) { if (!alloc_from_cache) {
struct drm_gem_create create; struct drm_gem_create create;
bo_gem = calloc(1, sizeof(*bo_gem));
if (!bo_gem)
return NULL;
bo_gem->bo.size = bo_size;
memset(&create, 0, sizeof(create)); memset(&create, 0, sizeof(create));
create.size = bo_gem->bo.size; create.size = bo_size;
ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CREATE, &create); ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CREATE, &create);
bo_gem->gem_handle = create.handle; bo_gem->gem_handle = create.handle;
@ -323,10 +326,9 @@ dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name,
free(bo_gem); free(bo_gem);
return NULL; return NULL;
} }
bo_gem->bo.bufmgr = bufmgr;
} }
bo_gem->bo.virtual = NULL;
bo_gem->bo.bufmgr = bufmgr;
bo_gem->name = name; bo_gem->name = name;
bo_gem->refcount = 1; bo_gem->refcount = 1;
bo_gem->validate_index = -1; bo_gem->validate_index = -1;
@ -400,9 +402,6 @@ dri_gem_bo_unreference(dri_bo *bo)
struct dri_gem_bo_bucket *bucket; struct dri_gem_bo_bucket *bucket;
int ret; int ret;
if (bo_gem->mapped)
munmap (bo_gem->virtual, bo->size);
if (bo_gem->relocs != NULL) { if (bo_gem->relocs != NULL) {
int i; int i;
@ -413,6 +412,9 @@ dri_gem_bo_unreference(dri_bo *bo)
free(bo_gem->relocs); free(bo_gem->relocs);
} }
DBG("bo_unreference final: %d (%s)\n",
bo_gem->gem_handle, bo_gem->name);
bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo->size); bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo->size);
/* Put the buffer into our internal cache for reuse if we can. */ /* Put the buffer into our internal cache for reuse if we can. */
if (bucket != NULL && if (bucket != NULL &&
@ -422,9 +424,14 @@ dri_gem_bo_unreference(dri_bo *bo)
{ {
struct dri_gem_bo_bucket_entry *entry; struct dri_gem_bo_bucket_entry *entry;
bo_gem->name = 0;
bo_gem->validate_index = -1;
bo_gem->relocs = NULL;
bo_gem->reloc_target_bo = NULL;
bo_gem->reloc_count = 0;
entry = calloc(1, sizeof(*entry)); entry = calloc(1, sizeof(*entry));
entry->gem_handle = bo_gem->gem_handle; entry->bo_gem = bo_gem;
entry->last_offset = bo->offset;
entry->next = NULL; entry->next = NULL;
*bucket->tail = entry; *bucket->tail = entry;
@ -441,12 +448,9 @@ dri_gem_bo_unreference(dri_bo *bo)
"DRM_IOCTL_GEM_CLOSE %d failed (%s): %s\n", "DRM_IOCTL_GEM_CLOSE %d failed (%s): %s\n",
bo_gem->gem_handle, bo_gem->name, strerror(-ret)); bo_gem->gem_handle, bo_gem->name, strerror(-ret));
} }
free(bo);
} }
DBG("bo_unreference final: %d (%s)\n",
bo_gem->gem_handle, bo_gem->name);
free(bo);
return; return;
} }
} }
@ -604,6 +608,7 @@ dri_bufmgr_gem_destroy(dri_bufmgr *bufmgr)
while ((entry = bucket->head) != NULL) { while ((entry = bucket->head) != NULL) {
struct drm_gem_close close; struct drm_gem_close close;
dri_bo_gem *bo_gem;
int ret; int ret;
bucket->head = entry->next; bucket->head = entry->next;
@ -611,14 +616,19 @@ dri_bufmgr_gem_destroy(dri_bufmgr *bufmgr)
bucket->tail = &bucket->head; bucket->tail = &bucket->head;
bucket->num_entries--; bucket->num_entries--;
bo_gem = entry->bo_gem;
if (bo_gem->mapped)
munmap (bo_gem->virtual, bo_gem->bo.size);
/* Close this object */ /* Close this object */
close.handle = entry->gem_handle; close.handle = bo_gem->gem_handle;
ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close); ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close);
if (ret != 0) { if (ret != 0) {
fprintf(stderr, "DRM_IOCTL_GEM_CLOSE failed: %s\n", fprintf(stderr, "DRM_IOCTL_GEM_CLOSE failed: %s\n",
strerror(-ret)); strerror(-ret));
} }
free(bo_gem);
free(entry); free(entry);
} }
} }