dri/nouveau: Keep small DYNAMIC_DRAW vertex buffers in system ram.
authorFrancisco Jerez <currojerez@riseup.net>
Sat, 30 Oct 2010 23:37:47 +0000 (01:37 +0200)
committerFrancisco Jerez <currojerez@riseup.net>
Sun, 31 Oct 2010 01:01:24 +0000 (02:01 +0100)
src/mesa/drivers/dri/nouveau/nouveau_array.c
src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c
src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h
src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c

index 1fee3603092a31f799e1b9e7d33b9adb32fc4e6e..17e6d163a02704147bfbdec2559bf080a552bf22 100644 (file)
@@ -90,7 +90,7 @@ nouveau_init_array(struct nouveau_array *a, int attr, int stride,
        a->buf = NULL;
 
        if (obj) {
-               if (_mesa_is_bufferobj(obj)) {
+               if (nouveau_bufferobj_hw(obj)) {
                        struct nouveau_bufferobj *nbo =
                                to_nouveau_bufferobj(obj);
 
@@ -107,7 +107,8 @@ nouveau_init_array(struct nouveau_array *a, int attr, int stride,
                        a->offset = 0;
 
                        if (map)
-                               a->buf = ptr;
+                               a->buf = ADD_POINTERS(
+                                       nouveau_bufferobj_sys(obj), ptr);
                }
        }
 
index c1453416347de52f1534357b1c8f47f0c39f3ad8..e60b91f64be082eda41f2c6988f861469af1cd20 100644 (file)
@@ -36,7 +36,9 @@ get_bufferobj_map(struct gl_buffer_object *obj, unsigned flags)
        struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj);
        void *map = NULL;
 
-       if (nbo->bo) {
+       if (nbo->sys) {
+               map = nbo->sys;
+       } else if (nbo->bo) {
                nouveau_bo_map(nbo->bo, flags);
                map = nbo->bo->map;
                nouveau_bo_unmap(nbo->bo);
@@ -65,6 +67,7 @@ nouveau_bufferobj_del(struct gl_context *ctx, struct gl_buffer_object *obj)
        struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj);
 
        nouveau_bo_ref(NULL, &nbo->bo);
+       FREE(nbo->sys);
        FREE(nbo);
 }
 
@@ -79,11 +82,23 @@ nouveau_bufferobj_data(struct gl_context *ctx, GLenum target, GLsizeiptrARB size
        obj->Size = size;
        obj->Usage = usage;
 
+       /* Free previous storage */
        nouveau_bo_ref(NULL, &nbo->bo);
-       ret = nouveau_bo_new(context_dev(ctx),
-                            NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
-                            size, &nbo->bo);
-       assert(!ret);
+       FREE(nbo->sys);
+
+       if (target == GL_ELEMENT_ARRAY_BUFFER_ARB ||
+           (size < 512 && usage == GL_DYNAMIC_DRAW_ARB) ||
+           context_chipset(ctx) < 0x10) {
+               /* Heuristic: keep it in system ram */
+               nbo->sys = MALLOC(size);
+
+       } else {
+               /* Get a hardware BO */
+               ret = nouveau_bo_new(context_dev(ctx),
+                                    NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
+                                    size, &nbo->bo);
+               assert(!ret);
+       }
 
        if (data)
                memcpy(get_bufferobj_map(obj, NOUVEAU_BO_WR), data, size);
index acfc4cb9a90ff7c607712dda3f3d8deb6111bb17..01ef0bad0fd4a6b45d292577125a8253e26e38e9 100644 (file)
 struct nouveau_bufferobj {
        struct gl_buffer_object base;
        struct nouveau_bo *bo;
+       void *sys;
 };
 #define to_nouveau_bufferobj(x) ((struct nouveau_bufferobj *)(x))
 
+#define nouveau_bufferobj_hw(x) \
+       (_mesa_is_bufferobj(x) ? to_nouveau_bufferobj(x)->bo : NULL)
+
+#define nouveau_bufferobj_sys(x) \
+       (_mesa_is_bufferobj(x) ? to_nouveau_bufferobj(x)->sys : NULL)
+
 void
 nouveau_bufferobj_functions_init(struct dd_function_table *functions);
 
index bf5885f8b170a8f5bcbc14712011e9a3755290af..9437fc9878802f6c28ad4fac14d62f97db4f15b7 100644 (file)
@@ -297,22 +297,21 @@ vbo_bind_vertices(struct gl_context *ctx, const struct gl_client_array **arrays,
 
        FOR_EACH_BOUND_ATTR(render, i, attr) {
                const struct gl_client_array *array = arrays[attr];
+               struct gl_buffer_object *obj = array->BufferObj;
                struct nouveau_array *a = &render->attrs[attr];
                unsigned delta = (base + min_index) * array->StrideB;
 
                bo[i] = NULL;
 
-               if (_mesa_is_bufferobj(array->BufferObj)) {
-                       struct nouveau_bufferobj *nbo =
-                               to_nouveau_bufferobj(array->BufferObj);
-
+               if (nouveau_bufferobj_hw(obj)) {
                        /* Array in a buffer obj. */
-                       nouveau_bo_ref(nbo->bo, &bo[i]);
+                       nouveau_bo_ref(to_nouveau_bufferobj(obj)->bo, &bo[i]);
                        offset[i] = delta + (intptr_t)array->Ptr;
 
                } else {
                        int n = max_index - min_index + 1;
-                       char *sp = (char *)array->Ptr + delta;
+                       char *sp = (char *)ADD_POINTERS(
+                               nouveau_bufferobj_sys(obj), array->Ptr) + delta;
                        char *dp  = nouveau_get_scratch(ctx, n * a->stride,
                                                        &bo[i], &offset[i]);