util: remove LIST_IS_EMPTY macro
[mesa.git] / src / gallium / drivers / nouveau / nouveau_mm.c
index 6c6d28c17f6ed0764bda693532a6e0caf8d895d7..3ba6ea95d1d79b86eb5acf6aed29944cdfc393c0 100644 (file)
@@ -1,15 +1,23 @@
 
+#include <inttypes.h>
+
 #include "util/u_inlines.h"
 #include "util/u_memory.h"
-#include "util/u_double_list.h"
+#include "util/list.h"
 
+#include "nouveau_winsys.h"
 #include "nouveau_screen.h"
 #include "nouveau_mm.h"
 
-#include "nouveau/nouveau_bo.h"
+/* TODO: Higher orders can waste a lot of space for npot size buffers, should
+ * add an extra cache for such buffer objects.
+ *
+ * HACK: Max order == 21 to accommodate TF2's 1.5 MiB, frequently reallocated
+ * vertex buffer (VM flush (?) decreases performance dramatically).
+ */
 
-#define MM_MIN_ORDER 7
-#define MM_MAX_ORDER 20
+#define MM_MIN_ORDER 7 /* >= 6 to not violate ARB_map_buffer_alignment */
+#define MM_MAX_ORDER 21
 
 #define MM_NUM_BUCKETS (MM_MAX_ORDER - MM_MIN_ORDER + 1)
 
@@ -26,8 +34,8 @@ struct mm_bucket {
 struct nouveau_mman {
    struct nouveau_device *dev;
    struct mm_bucket bucket[MM_NUM_BUCKETS];
-   uint32_t storage_type;
    uint32_t domain;
+   union nouveau_bo_config config;
    uint64_t allocated;
 };
 
@@ -62,7 +70,7 @@ mm_slab_alloc(struct mm_slab *slab)
    return -1;
 }
 
-static INLINE void
+static inline void
 mm_slab_free(struct mm_slab *slab, int i)
 {
    assert(i < slab->count);
@@ -71,7 +79,7 @@ mm_slab_free(struct mm_slab *slab, int i)
    assert(slab->free <= slab->count);
 }
 
-static INLINE int
+static inline int
 mm_get_order(uint32_t size)
 {
    int s = __builtin_clz(size) ^ 31;
@@ -96,12 +104,12 @@ mm_bucket_by_size(struct nouveau_mman *cache, unsigned size)
 }
 
 /* size of bo allocation for slab with chunks of (1 << chunk_order) bytes */
-static INLINE uint32_t
+static inline uint32_t
 mm_default_slab_size(unsigned chunk_order)
 {
    static const int8_t slab_order[MM_MAX_ORDER - MM_MIN_ORDER + 1] =
    {
-      12, 12, 13, 14, 14, 17, 17, 17, 17, 19, 19, 20, 21, 22
+      12, 12, 13, 14, 14, 17, 17, 17, 17, 19, 19, 20, 21, 22, 22
    };
 
    assert(chunk_order <= MM_MAX_ORDER && chunk_order >= MM_MIN_ORDER);
@@ -126,25 +134,27 @@ mm_slab_new(struct nouveau_mman *cache, int chunk_order)
    memset(&slab->bits[0], ~0, words * 4);
 
    slab->bo = NULL;
-   ret = nouveau_bo_new_tile(cache->dev, cache->domain, 0, size,
-                             0, cache->storage_type, &slab->bo);
+
+   ret = nouveau_bo_new(cache->dev, cache->domain, 0, size, &cache->config,
+                        &slab->bo);
    if (ret) {
       FREE(slab);
       return PIPE_ERROR_OUT_OF_MEMORY;
    }
 
-   LIST_INITHEAD(&slab->head);
+   list_inithead(&slab->head);
 
    slab->cache = cache;
    slab->order = chunk_order;
    slab->count = slab->free = size >> chunk_order;
 
-   LIST_ADD(&slab->head, &mm_bucket_by_order(cache, chunk_order)->free);
+   list_add(&slab->head, &mm_bucket_by_order(cache, chunk_order)->free);
 
    cache->allocated += size;
 
-   debug_printf("MM: new slab, total memory = %llu KiB\n",
-                cache->allocated / 1024);
+   if (nouveau_mesa_debug)
+      debug_printf("MM: new slab, total memory = %"PRIu64" KiB\n",
+                   cache->allocated / 1024);
 
    return PIPE_OK;
 }
@@ -152,7 +162,7 @@ mm_slab_new(struct nouveau_mman *cache, int chunk_order)
 /* @return token to identify slab or NULL if we just allocated a new bo */
 struct nouveau_mm_allocation *
 nouveau_mm_allocate(struct nouveau_mman *cache,
-                 uint32_t size, struct nouveau_bo **bo, uint32_t *offset)
+                    uint32_t size, struct nouveau_bo **bo, uint32_t *offset)
 {
    struct mm_bucket *bucket;
    struct mm_slab *slab;
@@ -161,25 +171,26 @@ nouveau_mm_allocate(struct nouveau_mman *cache,
 
    bucket = mm_bucket_by_size(cache, size);
    if (!bucket) {
-      ret = nouveau_bo_new_tile(cache->dev, cache->domain, 0, size,
-                                0, cache->storage_type, bo);
+      ret = nouveau_bo_new(cache->dev, cache->domain, 0, size, &cache->config,
+                           bo);
       if (ret)
-         debug_printf("bo_new(%x, %x): %i\n", size, cache->storage_type, ret);
+         debug_printf("bo_new(%x, %x): %i\n",
+                      size, cache->config.nv50.memtype, ret);
 
       *offset = 0;
       return NULL;
    }
 
-   if (!LIST_IS_EMPTY(&bucket->used)) {
+   if (!list_is_empty(&bucket->used)) {
       slab = LIST_ENTRY(struct mm_slab, bucket->used.next, head);
    } else {
-      if (LIST_IS_EMPTY(&bucket->free)) {
+      if (list_is_empty(&bucket->free)) {
          mm_slab_new(cache, MAX2(mm_get_order(size), MM_MIN_ORDER));
       }
       slab = LIST_ENTRY(struct mm_slab, bucket->free.next, head);
 
-      LIST_DEL(&slab->head);
-      LIST_ADD(&slab->head, &bucket->used);
+      list_del(&slab->head);
+      list_add(&slab->head, &bucket->used);
    }
 
    *offset = mm_slab_alloc(slab) << slab->order;
@@ -191,8 +202,8 @@ nouveau_mm_allocate(struct nouveau_mman *cache,
    nouveau_bo_ref(slab->bo, bo);
 
    if (slab->free == 0) {
-      LIST_DEL(&slab->head);
-      LIST_ADD(&slab->head, &bucket->full);
+      list_del(&slab->head);
+      list_add(&slab->head, &bucket->full);
    }
 
    alloc->next = NULL;
@@ -210,13 +221,13 @@ nouveau_mm_free(struct nouveau_mm_allocation *alloc)
 
    mm_slab_free(slab, alloc->offset >> slab->order);
 
+   if (slab->free == slab->count) {
+      list_del(&slab->head);
+      list_addtail(&slab->head, &bucket->free);
+   } else
    if (slab->free == 1) {
-      LIST_DEL(&slab->head);
-
-      if (slab->count > 1)
-         LIST_ADDTAIL(&slab->head, &bucket->used);
-      else
-         LIST_ADDTAIL(&slab->head, &bucket->free);
+      list_del(&slab->head);
+      list_addtail(&slab->head, &bucket->used);
    }
 
    FREE(alloc);
@@ -230,7 +241,7 @@ nouveau_mm_free_work(void *data)
 
 struct nouveau_mman *
 nouveau_mm_create(struct nouveau_device *dev, uint32_t domain,
-               uint32_t storage_type)
+                  union nouveau_bo_config *config)
 {
    struct nouveau_mman *cache = MALLOC_STRUCT(nouveau_mman);
    int i;
@@ -240,25 +251,25 @@ nouveau_mm_create(struct nouveau_device *dev, uint32_t domain,
 
    cache->dev = dev;
    cache->domain = domain;
-   cache->storage_type = storage_type;
+   cache->config = *config;
    cache->allocated = 0;
 
    for (i = 0; i < MM_NUM_BUCKETS; ++i) {
-      LIST_INITHEAD(&cache->bucket[i].free);
-      LIST_INITHEAD(&cache->bucket[i].used);
-      LIST_INITHEAD(&cache->bucket[i].full);
+      list_inithead(&cache->bucket[i].free);
+      list_inithead(&cache->bucket[i].used);
+      list_inithead(&cache->bucket[i].full);
    }
 
    return cache;
 }
 
-static INLINE void
+static inline void
 nouveau_mm_free_slabs(struct list_head *head)
 {
    struct mm_slab *slab, *next;
 
    LIST_FOR_EACH_ENTRY_SAFE(slab, next, head, head) {
-      LIST_DEL(&slab->head);
+      list_del(&slab->head);
       nouveau_bo_ref(NULL, &slab->bo);
       FREE(slab);
    }
@@ -273,8 +284,8 @@ nouveau_mm_destroy(struct nouveau_mman *cache)
       return;
 
    for (i = 0; i < MM_NUM_BUCKETS; ++i) {
-      if (!LIST_IS_EMPTY(&cache->bucket[i].used) ||
-          !LIST_IS_EMPTY(&cache->bucket[i].full))
+      if (!list_is_empty(&cache->bucket[i].used) ||
+          !list_is_empty(&cache->bucket[i].full))
          debug_printf("WARNING: destroying GPU memory cache "
                       "with some buffers still in use\n");
 
@@ -285,4 +296,3 @@ nouveau_mm_destroy(struct nouveau_mman *cache)
 
    FREE(cache);
 }
-