[Mesa-dev] [PATCH 3/3] intel: allow region hash with offset specification.

Gwenole Beauchesne gb.devel at gmail.com
Fri Apr 20 09:39:05 PDT 2012


Allow regions to be hashed by name + offset in bytes to the base bo.

Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne at intel.com>
---
 src/mesa/drivers/dri/intel/intel_regions.c |  105 ++++++++++++++++++++++++++--
 1 files changed, 99 insertions(+), 6 deletions(-)

diff --git a/src/mesa/drivers/dri/intel/intel_regions.c b/src/mesa/drivers/dri/intel/intel_regions.c
index 235c2cd..0028326 100644
--- a/src/mesa/drivers/dri/intel/intel_regions.c
+++ b/src/mesa/drivers/dri/intel/intel_regions.c
@@ -106,7 +106,7 @@ debug_backtrace(void)
 
 /* Forward declarations */
 static struct intel_region *
-intel_region_hash_lookup(struct _mesa_HashTable *h, uint32_t name);
+intel_region_hash_lookup(struct _mesa_HashTable *h, uint32_t name, uint32_t ofs);
 
 static void
 intel_region_hash_insert(struct _mesa_HashTable *h,
@@ -250,7 +250,7 @@ intel_region_alloc_for_handle(struct intel_screen *screen,
    int ret;
    uint32_t bit_6_swizzle, tiling;
 
-   region = intel_region_hash_lookup(screen->named_regions, handle);
+   region = intel_region_hash_lookup(screen->named_regions, handle, 0);
    if (region != NULL) {
       dummy = NULL;
       if (region->width != width || region->height != height ||
@@ -401,9 +401,55 @@ intel_region_copy(struct intel_context *intel,
 			    logicop);
 }
 
+struct hash_entry {
+    struct intel_region *base_region; /* base region for offset = 0 */
+    struct intel_region **regions;
+    unsigned int num_regions;
+    unsigned int max_regions;
+};
+
+static inline struct hash_entry *
+hash_entry_new(void)
+{
+    return calloc(1, sizeof(struct hash_entry));
+}
+
+static void
+hash_entry_destroy(struct hash_entry *e)
+{
+    if (e->regions) {
+        free(e->regions);
+        e->regions = NULL;
+    }
+    free(e);
+}
+
+static void
+hash_entry_append_region(struct hash_entry *e, struct intel_region *region)
+{
+    struct intel_region **new_regions;
+    unsigned int i, num_regions;
+
+    for (i = 0; i < e->num_regions; i++) {
+        if (e->regions[i]->offset == region->offset)
+            return;
+    }
+
+    if (e->num_regions >= e->max_regions) {
+        num_regions = e->max_regions + 4;
+        new_regions = realloc(e->regions, num_regions * sizeof(*new_regions));
+        if (!new_regions)
+            return;
+        e->regions     = new_regions;
+        e->max_regions = num_regions;
+    }
+    e->regions[e->num_regions++] = region;
+}
+
 static void
 intel_region_hash_destroy_callback(GLuint key, void *data, void *userData)
 {
+    hash_entry_destroy(data);
 }
 
 struct _mesa_HashTable *
@@ -426,19 +472,66 @@ intel_region_hash_destroy(struct _mesa_HashTable **h_ptr)
 }
 
 static struct intel_region *
-intel_region_hash_lookup(struct _mesa_HashTable *h, uint32_t name)
+intel_region_hash_lookup(struct _mesa_HashTable *h, uint32_t name, uint32_t offset)
 {
-    return _mesa_HashLookup(h, name);
+    struct hash_entry * const e = _mesa_HashLookup(h, name);
+    unsigned int i;
+
+    if (!e)
+        return NULL;
+
+    if (offset == 0) {
+        assert(e->base_region);
+        return e->base_region;
+    }
+
+    for (i = 0; i < e->num_regions; i++) {
+        struct intel_region * const region = e->regions[i];
+        if (region->offset == offset)
+            return region;
+    }
+    return NULL;
 }
 
 static void
 intel_region_hash_insert(struct _mesa_HashTable *h, struct intel_region *region)
 {
-    _mesa_HashInsert(h, region->name, region);
+    struct hash_entry *e = _mesa_HashLookup(h, region->name);
+
+    if (!e) {
+        e = hash_entry_new();
+        if (!e)
+            return;
+        _mesa_HashInsert(h, region->name, e);
+    }
+
+    if (region->offset == 0)
+        e->base_region = region;
+    else
+        hash_entry_append_region(e, region);
 }
 
 static void
 intel_region_hash_remove(struct _mesa_HashTable *h, struct intel_region *region)
 {
-    _mesa_HashRemove(h, region->name);
+    struct hash_entry * const e = _mesa_HashLookup(h, region->name);
+    unsigned int i;
+
+    if (region->offset == 0)
+        e->base_region = NULL;
+    else {
+        for (i = 0; i < e->num_regions; i++) {
+            if (e->regions[i]->offset == region->offset) {
+                if (--e->num_regions > i) /* swap with the last entry */
+                    e->regions[i] = e->regions[e->num_regions];
+                e->regions[e->num_regions] = NULL;
+                break;
+            }
+        }
+    }
+
+    if (!e->base_region && e->num_regions == 0) {
+        _mesa_HashRemove(h, region->name);
+        hash_entry_destroy(e);
+    }
 }
-- 
1.7.5.4



More information about the mesa-dev mailing list