mesa: GL_EXT_secondary_color is not optional
[mesa.git] / src / mesa / drivers / dri / nouveau / nv04_render.c
index ad45093edd1f10531b4bfa1859bd15aecb2d83cc..30e9f9aad964cffb6a87986f23cae1e872c30de7 100644 (file)
@@ -55,7 +55,7 @@ swtnl_emit_attr(struct gl_context *ctx, struct tnl_attr_map *m, int attr, int em
 {
        TNLcontext *tnl = TNL_CONTEXT(ctx);
 
-       if (RENDERINPUTS_TEST(tnl->render_inputs_bitset, attr))
+       if (tnl->render_inputs_bitset & BITFIELD64_BIT(attr))
                *m = (struct tnl_attr_map) {
                        .attrib = attr,
                        .format = emit,
@@ -71,7 +71,7 @@ static void
 swtnl_choose_attrs(struct gl_context *ctx)
 {
        TNLcontext *tnl = TNL_CONTEXT(ctx);
-       struct nouveau_grobj *fahrenheit = nv04_context_engine(ctx);
+       struct nouveau_object *fahrenheit = nv04_context_engine(ctx);
        struct nv04_context *nctx = to_nv04_context(ctx);
        static struct tnl_attr_map map[NUM_VERTEX_ATTRS];
        int n = 0;
@@ -93,16 +93,101 @@ swtnl_choose_attrs(struct gl_context *ctx)
 
 /* TnL renderer entry points */
 
+static void
+swtnl_restart_ttri(struct nv04_context *nv04, struct nouveau_pushbuf *push)
+{
+       BEGIN_NV04(push, NV04_TTRI(COLORKEY), 7);
+       PUSH_DATA (push, nv04->colorkey);
+       PUSH_RELOC(push, nv04->texture[0]->bo, nv04->texture[0]->offset,
+                        NOUVEAU_BO_LOW, 0, 0);
+       PUSH_RELOC(push, nv04->texture[0]->bo, nv04->format[0], NOUVEAU_BO_OR,
+                        NV04_TEXTURED_TRIANGLE_FORMAT_DMA_A,
+                        NV04_TEXTURED_TRIANGLE_FORMAT_DMA_B);
+       PUSH_DATA (push, nv04->filter[0]);
+       PUSH_DATA (push, nv04->blend);
+       PUSH_DATA (push, nv04->ctrl[0] & ~0x3e000000);
+       PUSH_DATA (push, nv04->fog);
+}
+
+static void
+swtnl_restart_mtri(struct nv04_context *nv04, struct nouveau_pushbuf *push)
+{
+       BEGIN_NV04(push, NV04_MTRI(OFFSET(0)), 8);
+       PUSH_RELOC(push, nv04->texture[0]->bo, nv04->texture[0]->offset,
+                        NOUVEAU_BO_LOW, 0, 0);
+       PUSH_RELOC(push, nv04->texture[1]->bo, nv04->texture[1]->offset,
+                        NOUVEAU_BO_LOW, 0, 0);
+       PUSH_RELOC(push, nv04->texture[0]->bo, nv04->format[0], NOUVEAU_BO_OR,
+                        NV04_TEXTURED_TRIANGLE_FORMAT_DMA_A,
+                        NV04_TEXTURED_TRIANGLE_FORMAT_DMA_B);
+       PUSH_RELOC(push, nv04->texture[1]->bo, nv04->format[1], NOUVEAU_BO_OR,
+                        NV04_TEXTURED_TRIANGLE_FORMAT_DMA_A,
+                        NV04_TEXTURED_TRIANGLE_FORMAT_DMA_B);
+       PUSH_DATA (push, nv04->filter[0]);
+       PUSH_DATA (push, nv04->filter[1]);
+       PUSH_DATA (push, nv04->alpha[0]);
+       PUSH_DATA (push, nv04->color[0]);
+       BEGIN_NV04(push, NV04_MTRI(COMBINE_ALPHA(1)), 8);
+       PUSH_DATA (push, nv04->alpha[1]);
+       PUSH_DATA (push, nv04->color[1]);
+       PUSH_DATA (push, nv04->factor);
+       PUSH_DATA (push, nv04->blend & ~0x0000000f);
+       PUSH_DATA (push, nv04->ctrl[0]);
+       PUSH_DATA (push, nv04->ctrl[1]);
+       PUSH_DATA (push, nv04->ctrl[2]);
+       PUSH_DATA (push, nv04->fog);
+}
+
+static inline bool
+swtnl_restart(struct gl_context *ctx, int multi, unsigned vertex_size)
+{
+       const int tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
+       struct nv04_context *nv04 = to_nv04_context(ctx);
+       struct nouveau_pushbuf *push = context_push(ctx);
+       struct nouveau_pushbuf_refn refs[] = {
+               { nv04->texture[0]->bo, tex_flags },
+               { nv04->texture[1]->bo, tex_flags },
+       };
+
+       /* wait for enough space for state, and at least one whole primitive */
+       if (nouveau_pushbuf_space(push, 32 + (4 * vertex_size), 4, 0) ||
+           nouveau_pushbuf_refn (push, refs, multi ? 2 : 1))
+               return false;
+
+       /* emit engine state */
+       if (multi)
+               swtnl_restart_mtri(nv04, push);
+       else
+               swtnl_restart_ttri(nv04, push);
+
+       return true;
+}
+
 static void
 swtnl_start(struct gl_context *ctx)
 {
+       struct nouveau_object *eng3d = nv04_context_engine(ctx);
+       struct nouveau_pushbuf *push = context_push(ctx);
+       unsigned vertex_size;
+
+       nouveau_pushbuf_bufctx(push, push->user_priv);
+       nouveau_pushbuf_validate(push);
+
        swtnl_choose_attrs(ctx);
+
+       vertex_size = TNL_CONTEXT(ctx)->clipspace.vertex_size / 4;
+       if (eng3d->oclass == NV04_MULTITEX_TRIANGLE_CLASS)
+               swtnl_restart(ctx, 1, vertex_size);
+       else
+               swtnl_restart(ctx, 0, vertex_size);
 }
 
 static void
 swtnl_finish(struct gl_context *ctx)
 {
-       FIRE_RING(context_chan(ctx));
+       struct nouveau_pushbuf *push = context_push(ctx);
+
+       nouveau_pushbuf_bufctx(push, NULL);
 }
 
 static void
@@ -118,31 +203,28 @@ swtnl_reset_stipple(struct gl_context *ctx)
 /* Primitive rendering */
 
 #define BEGIN_PRIMITIVE(n)                                             \
-       struct nouveau_channel *chan = context_chan(ctx);               \
-       struct nouveau_grobj *fahrenheit = nv04_context_engine(ctx);    \
-       int vertex_len = TNL_CONTEXT(ctx)->clipspace.vertex_size / 4;   \
+       struct nouveau_object *eng3d = to_nv04_context(ctx)->eng3d;     \
+       struct nouveau_pushbuf *push = context_push(ctx);               \
+       int vertex_size = TNL_CONTEXT(ctx)->clipspace.vertex_size / 4;  \
+       int multi = (eng3d->oclass == NV04_MULTITEX_TRIANGLE_CLASS);    \
                                                                        \
-       if (nv04_mtex_engine(fahrenheit))                               \
-               BEGIN_RING(chan, fahrenheit,                            \
-                          NV04_MULTITEX_TRIANGLE_TLMTVERTEX_SX(0),     \
-                          n * vertex_len);                             \
-       else                                                            \
-               BEGIN_RING(chan, fahrenheit,                            \
-                          NV04_TEXTURED_TRIANGLE_TLVERTEX_SX(0),       \
-                          n * vertex_len);                             \
-
-#define OUT_VERTEX(i)                                          \
-       OUT_RINGp(chan, _tnl_get_vertex(ctx, i), vertex_len);
+       if (PUSH_AVAIL(push) < 32 + (n * vertex_size)) {                \
+               if (!swtnl_restart(ctx, multi, vertex_size))            \
+                       return;                                         \
+       }                                                               \
+                                                                       \
+       BEGIN_NV04(push, NV04_TTRI(TLVERTEX_SX(0)), n * vertex_size);
+
+#define OUT_VERTEX(i)                                                  \
+       PUSH_DATAp(push, _tnl_get_vertex(ctx, i), vertex_size);
 
 #define END_PRIMITIVE(draw)                                            \
-       if (nv04_mtex_engine(fahrenheit)) {                             \
-               BEGIN_RING(chan, fahrenheit,                            \
-                          NV04_MULTITEX_TRIANGLE_DRAWPRIMITIVE(0), 1); \
-               OUT_RING(chan, draw);                                   \
+       if (multi) {                                                    \
+               BEGIN_NV04(push, NV04_MTRI(DRAWPRIMITIVE(0)), 1);       \
+               PUSH_DATA (push, draw);                                 \
        } else {                                                        \
-               BEGIN_RING(chan, fahrenheit,                            \
-                          NV04_TEXTURED_TRIANGLE_DRAWPRIMITIVE(0), 1); \
-               OUT_RING(chan, draw);                                   \
+               BEGIN_NV04(push, NV04_TTRI(DRAWPRIMITIVE(0)), 1);       \
+               PUSH_DATA (push, draw);                                 \
        }
 
 static void