From a919ff5d5ec2fe716cbf5c593be7cc0705499107 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Jun 2008 15:58:09 -0700 Subject: [PATCH] [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. --- libdrm/intel/intel_bufmgr_gem.c | 76 +++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/libdrm/intel/intel_bufmgr_gem.c b/libdrm/intel/intel_bufmgr_gem.c index 20f39b5..08cb5d6 100644 --- a/libdrm/intel/intel_bufmgr_gem.c +++ b/libdrm/intel/intel_bufmgr_gem.c @@ -55,15 +55,16 @@ fprintf(stderr, __VA_ARGS__); \ } while (0) +typedef struct _dri_bo_gem dri_bo_gem; + struct intel_validate_entry { - dri_bo *bo; + dri_bo_gem *bo_gem; struct drm_i915_op_arg bo_arg; }; struct dri_gem_bo_bucket_entry { - uint32_t gem_handle; - uint32_t last_offset; - struct dri_gem_bo_bucket_entry *next; + dri_bo_gem *bo_gem; + struct dri_gem_bo_bucket_entry *next; }; struct dri_gem_bo_bucket { @@ -103,7 +104,7 @@ typedef struct _dri_bufmgr_gem { struct drm_i915_gem_execbuffer exec_arg; } dri_bufmgr_gem; -typedef struct _dri_bo_gem { +struct _dri_bo_gem { dri_bo bo; int refcount; @@ -133,7 +134,7 @@ typedef struct _dri_bo_gem { int reloc_count; /** Mapped address for the buffer */ void *virtual; -} dri_bo_gem; +}; static int logbase2(int n) @@ -270,24 +271,21 @@ dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name, int ret; struct dri_gem_bo_bucket *bucket; int alloc_from_cache = 0; - - bo_gem = calloc(1, sizeof(*bo_gem)); - if (!bo_gem) - return NULL; + unsigned long bo_size; /* Round the allocated size up to a power of two number of pages. */ - bo_gem->bo.size = 1 << logbase2(size); - if (bo_gem->bo.size < page_size) - bo_gem->bo.size = page_size; - bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo_gem->bo.size); + bo_size = 1 << logbase2(size); + if (bo_size < page_size) + bo_size = page_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 * allocation up. */ if (bucket == NULL || bucket->max_entries == 0) { - bo_gem->bo.size = size; - if (bo_gem->bo.size < page_size) - bo_gem->bo.size = page_size; + bo_size = size; + if (bo_size < page_size) + bo_size = page_size; } /* 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 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); 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->num_entries--; - bo_gem->gem_handle = entry->gem_handle; - bo_gem->bo.offset = entry->last_offset; free(entry); } } @@ -314,8 +312,13 @@ dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name, if (!alloc_from_cache) { 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)); - create.size = bo_gem->bo.size; + create.size = bo_size; ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CREATE, &create); bo_gem->gem_handle = create.handle; @@ -323,10 +326,9 @@ dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name, free(bo_gem); return NULL; } + bo_gem->bo.bufmgr = bufmgr; } - bo_gem->bo.virtual = NULL; - bo_gem->bo.bufmgr = bufmgr; bo_gem->name = name; bo_gem->refcount = 1; bo_gem->validate_index = -1; @@ -400,9 +402,6 @@ dri_gem_bo_unreference(dri_bo *bo) struct dri_gem_bo_bucket *bucket; int ret; - if (bo_gem->mapped) - munmap (bo_gem->virtual, bo->size); - if (bo_gem->relocs != NULL) { int i; @@ -413,6 +412,9 @@ dri_gem_bo_unreference(dri_bo *bo) 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); /* Put the buffer into our internal cache for reuse if we can. */ if (bucket != NULL && @@ -422,9 +424,14 @@ dri_gem_bo_unreference(dri_bo *bo) { 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->gem_handle = bo_gem->gem_handle; - entry->last_offset = bo->offset; + entry->bo_gem = bo_gem; entry->next = NULL; *bucket->tail = entry; @@ -441,12 +448,9 @@ dri_gem_bo_unreference(dri_bo *bo) "DRM_IOCTL_GEM_CLOSE %d failed (%s): %s\n", 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; } } @@ -604,6 +608,7 @@ dri_bufmgr_gem_destroy(dri_bufmgr *bufmgr) while ((entry = bucket->head) != NULL) { struct drm_gem_close close; + dri_bo_gem *bo_gem; int ret; bucket->head = entry->next; @@ -611,14 +616,19 @@ dri_bufmgr_gem_destroy(dri_bufmgr *bufmgr) bucket->tail = &bucket->head; bucket->num_entries--; + bo_gem = entry->bo_gem; + if (bo_gem->mapped) + munmap (bo_gem->virtual, bo_gem->bo.size); + /* Close this object */ - close.handle = entry->gem_handle; + close.handle = bo_gem->gem_handle; ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close); if (ret != 0) { fprintf(stderr, "DRM_IOCTL_GEM_CLOSE failed: %s\n", strerror(-ret)); } + free(bo_gem); free(entry); } } -- 2.7.4