Merge branch '7.8'
[mesa.git] / src / mesa / drivers / dri / nouveau / nouveau_vbo_t.c
index ba1192a17044600c93bd3bc51f7f683dcf268acd..e5858f82684aeb566315d4f9aa9098c0d5ea7835 100644 (file)
  *
  */
 
-#include "main/bufferobj.h"
 #include "nouveau_bufferobj.h"
+#include "nouveau_util.h"
+
+#include "main/bufferobj.h"
+#include "main/image.h"
 
 /* Arbitrary pushbuf length we can assume we can get with a single
  * WAIT_RING. */
@@ -58,7 +61,11 @@ vbo_init_array(struct nouveau_array_state *a, int attr, int stride,
        } else {
                nouveau_bo_ref(NULL, &a->bo);
                a->offset = 0;
-               a->buf = ptr;
+
+               if (map)
+                       a->buf = ptr;
+               else
+                       a->buf = NULL;
        }
 
        if (a->buf)
@@ -78,6 +85,18 @@ vbo_deinit_array(struct nouveau_array_state *a)
        a->fields = 0;
 }
 
+static int
+get_array_stride(GLcontext *ctx, const struct gl_client_array *a)
+{
+       struct nouveau_render_state *render = to_render_state(ctx);
+
+       if (render->mode == VBO && !_mesa_is_bufferobj(a->BufferObj))
+               /* Pack client buffers. */
+               return align(_mesa_sizeof_type(a->Type) * a->Size, 4);
+       else
+               return a->StrideB;
+}
+
 static void
 vbo_init_arrays(GLcontext *ctx, const struct _mesa_index_buffer *ib,
                const struct gl_client_array **arrays)
@@ -96,9 +115,10 @@ vbo_init_arrays(GLcontext *ctx, const struct _mesa_index_buffer *ib,
                        const struct gl_client_array *array = arrays[attr];
 
                        vbo_init_array(&render->attrs[attr], attr,
-                                      array->StrideB, array->Size,
-                                      array->Type, array->BufferObj,
-                                      array->Ptr, render->mode == IMM);
+                                      get_array_stride(ctx, array),
+                                      array->Size, array->Type,
+                                      array->BufferObj, array->Ptr,
+                                      render->mode == IMM);
                }
        }
 }
@@ -208,9 +228,11 @@ vbo_choose_attrs(GLcontext *ctx, const struct gl_client_array **arrays)
        if (ctx->Fog.Enabled && ctx->Fog.FogCoordinateSource == GL_FOG_COORD)
                vbo_emit_attr(ctx, arrays, VERT_ATTRIB_FOG);
 
-       if (ctx->Light.Enabled) {
+       if (ctx->Light.Enabled ||
+           (ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS))
                vbo_emit_attr(ctx, arrays, VERT_ATTRIB_NORMAL);
 
+       if (ctx->Light.Enabled) {
                vbo_emit_attr(ctx, arrays, MAT(FRONT_AMBIENT));
                vbo_emit_attr(ctx, arrays, MAT(FRONT_DIFFUSE));
                vbo_emit_attr(ctx, arrays, MAT(FRONT_SPECULAR));
@@ -227,6 +249,26 @@ vbo_choose_attrs(GLcontext *ctx, const struct gl_client_array **arrays)
        vbo_emit_attr(ctx, arrays, VERT_ATTRIB_POS);
 }
 
+static int
+get_max_client_stride(GLcontext *ctx, const struct gl_client_array **arrays)
+{
+       struct nouveau_render_state *render = to_render_state(ctx);
+       int i, s = 0;
+
+       for (i = 0; i < render->attr_count; i++) {
+               int attr = render->map[i];
+
+               if (attr >= 0) {
+                       const struct gl_client_array *a = arrays[attr];
+
+                       if (!_mesa_is_bufferobj(a->BufferObj))
+                               s = MAX2(s, get_array_stride(ctx, a));
+               }
+       }
+
+       return s;
+}
+
 static void
 TAG(vbo_render_prims)(GLcontext *ctx, const struct gl_client_array **arrays,
                      const struct _mesa_prim *prims, GLuint nr_prims,
@@ -241,12 +283,21 @@ vbo_maybe_split(GLcontext *ctx, const struct gl_client_array **arrays,
            GLuint min_index, GLuint max_index)
 {
        struct nouveau_context *nctx = to_nouveau_context(ctx);
-       unsigned pushbuf_avail = PUSHBUF_DWORDS - 2 * nctx->bo.count,
+       struct nouveau_render_state *render = to_render_state(ctx);
+       unsigned pushbuf_avail = PUSHBUF_DWORDS - 2 * (nctx->bo.count +
+                                                      render->attr_count),
                vert_avail = get_max_vertices(ctx, NULL, pushbuf_avail),
                idx_avail = get_max_vertices(ctx, ib, pushbuf_avail);
+       int stride;
+
+       /* Try to keep client buffers smaller than the scratch BOs. */
+       if (render->mode == VBO &&
+           (stride = get_max_client_stride(ctx, arrays)))
+                   vert_avail = MIN2(vert_avail,
+                                     RENDER_SCRATCH_SIZE / stride);
 
-       if ((ib && ib->count > idx_avail) ||
-           (!ib && max_index - min_index > vert_avail)) {
+       if (max_index - min_index > vert_avail ||
+           (ib && ib->count > idx_avail)) {
                struct split_limits limits = {
                        .max_verts = vert_avail,
                        .max_indices = idx_avail,
@@ -276,17 +327,24 @@ vbo_bind_vertices(GLcontext *ctx, const struct gl_client_array **arrays,
                if (attr >= 0) {
                        const struct gl_client_array *array = arrays[attr];
                        struct nouveau_array_state *a = &render->attrs[attr];
-                       unsigned delta = (basevertex + min_index) * a->stride,
-                               size = (max_index - min_index + 1) * a->stride;
+                       unsigned delta = (basevertex + min_index)
+                               * array->StrideB;
 
                        if (a->bo) {
+                               /* Array in a buffer obj. */
                                a->offset = (intptr_t)array->Ptr + delta;
                        } else {
-                               void *scratch = get_scratch_vbo(ctx, size,
-                                                               &a->bo,
-                                                               &a->offset);
-
-                               memcpy(scratch, a->buf + delta, size);
+                               int j, n = max_index - min_index + 1;
+                               char *sp = (char *)array->Ptr + delta;
+                               char *dp = get_scratch_vbo(ctx, n * a->stride,
+                                                          &a->bo, &a->offset);
+
+                               /* Array in client memory, move it to
+                                * a scratch buffer obj. */
+                               for (j = 0; j < n; j++)
+                                       memcpy(dp + j * a->stride,
+                                              sp + j * array->StrideB,
+                                              a->stride);
                        }
                }
        }
@@ -319,15 +377,13 @@ vbo_draw_vbo(GLcontext *ctx, const struct gl_client_array **arrays,
                                          min_index, max_index);
                }
 
-               if (count > get_max_vertices(ctx, ib, chan->pushbuf->remaining))
+               if (count > get_max_vertices(ctx, ib, AVAIL_RING(chan)))
                        WAIT_RING(chan, PUSHBUF_DWORDS);
 
                BATCH_BEGIN(nvgl_primitive(prims[i].mode));
                dispatch(ctx, start, delta, count);
                BATCH_END();
        }
-
-       FIRE_RING(chan);
 }
 
 /* Immediate rendering path. */
@@ -355,7 +411,7 @@ vbo_draw_imm(GLcontext *ctx, const struct gl_client_array **arrays,
                        end = start + prims[i].count;
 
                if (prims[i].count > get_max_vertices(ctx, ib,
-                                                     chan->pushbuf->remaining))
+                                                     AVAIL_RING(chan)))
                        WAIT_RING(chan, PUSHBUF_DWORDS);
 
                BATCH_BEGIN(nvgl_primitive(prims[i].mode));
@@ -371,8 +427,6 @@ vbo_draw_imm(GLcontext *ctx, const struct gl_client_array **arrays,
 
                BATCH_END();
        }
-
-       FIRE_RING(chan);
 }
 
 /* draw_prims entry point when we're doing hw-tnl. */