nvc0: implement multiple viewports/scissors, enable ARB_viewport_array
authorTobias Klausmann <tobias.johannes.klausmann@mni.thm.de>
Sun, 15 Jun 2014 19:24:04 +0000 (21:24 +0200)
committerIlia Mirkin <imirkin@alum.mit.edu>
Tue, 17 Jun 2014 03:08:03 +0000 (23:08 -0400)
Signed-off-by: Tobias Klausmann <tobias.johannes.klausmann@mni.thm.de>
[imirkin: mark things dirty on ctx switch, 3d blit]
Reviewed-by: Ilia Mirkin <imirkin@alum.mit.edu>
src/gallium/drivers/nouveau/nvc0/nvc0_context.h
src/gallium/drivers/nouveau/nvc0/nvc0_program.c
src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
src/gallium/drivers/nouveau/nvc0/nvc0_screen.h
src/gallium/drivers/nouveau/nvc0/nvc0_state.c
src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c
src/gallium/drivers/nouveau/nvc0/nvc0_surface.c

index 76416a0e3b2b95642b69e44daec8bae4838cddc5..41cee78c10a427983a5c42a2874476253267e884 100644 (file)
@@ -178,8 +178,10 @@ struct nvc0_context {
    struct pipe_blend_color blend_colour;
    struct pipe_stencil_ref stencil_ref;
    struct pipe_poly_stipple stipple;
-   struct pipe_scissor_state scissor;
-   struct pipe_viewport_state viewport;
+   struct pipe_scissor_state scissors[NVC0_MAX_VIEWPORTS];
+   unsigned scissors_dirty;
+   struct pipe_viewport_state viewports[NVC0_MAX_VIEWPORTS];
+   unsigned viewports_dirty;
    struct pipe_clip_state clip;
 
    unsigned sample_mask;
index 1c82a9acffb15c6c4ce8cbafa7901b97fe05e146..667fbc893230d91fae0c4ddc1a3394998b33810a 100644 (file)
@@ -64,7 +64,7 @@ nvc0_shader_output_address(unsigned sn, unsigned si, unsigned ubase)
    case NV50_SEMANTIC_TESSFACTOR:    return 0x000 + si * 0x4;
    case TGSI_SEMANTIC_PRIMID:        return 0x060;
    case TGSI_SEMANTIC_LAYER:         return 0x064;
-   case NV50_SEMANTIC_VIEWPORTINDEX: return 0x068;
+   case TGSI_SEMANTIC_VIEWPORT_INDEX:return 0x068;
    case TGSI_SEMANTIC_PSIZE:         return 0x06c;
    case TGSI_SEMANTIC_POSITION:      return 0x070;
    case TGSI_SEMANTIC_GENERIC:       return ubase + si * 0x10;
index 3e6b0116e3c7f2ee0a6e99e4c0c93a228f7bad9e..3fdb6ae12c80dd216277596612441185a8bc402a 100644 (file)
@@ -183,7 +183,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_FAKE_SW_MSAA:
       return 0;
    case PIPE_CAP_MAX_VIEWPORTS:
-      return 1;
+      return NVC0_MAX_VIEWPORTS;
    case PIPE_CAP_TEXTURE_QUERY_LOD:
    case PIPE_CAP_SAMPLE_SHADING:
    case PIPE_CAP_TEXTURE_GATHER_OFFSETS:
@@ -933,19 +933,23 @@ nvc0_screen_create(struct nouveau_device *dev)
 
    BEGIN_NVC0(push, NVC0_3D(VIEWPORT_TRANSFORM_EN), 1);
    PUSH_DATA (push, 1);
-   BEGIN_NVC0(push, NVC0_3D(DEPTH_RANGE_NEAR(0)), 2);
-   PUSH_DATAf(push, 0.0f);
-   PUSH_DATAf(push, 1.0f);
+   for (i = 0; i < NVC0_MAX_VIEWPORTS; i++) {
+      BEGIN_NVC0(push, NVC0_3D(DEPTH_RANGE_NEAR(i)), 2);
+      PUSH_DATAf(push, 0.0f);
+      PUSH_DATAf(push, 1.0f);
+   }
    BEGIN_NVC0(push, NVC0_3D(VIEW_VOLUME_CLIP_CTRL), 1);
    PUSH_DATA (push, NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1);
 
    /* We use scissors instead of exact view volume clipping,
     * so they're always enabled.
     */
-   BEGIN_NVC0(push, NVC0_3D(SCISSOR_ENABLE(0)), 3);
-   PUSH_DATA (push, 1);
-   PUSH_DATA (push, 8192 << 16);
-   PUSH_DATA (push, 8192 << 16);
+   for (i = 0; i < NVC0_MAX_VIEWPORTS; i++) {
+      BEGIN_NVC0(push, NVC0_3D(SCISSOR_ENABLE(i)), 3);
+      PUSH_DATA (push, 1);
+      PUSH_DATA (push, 8192 << 16);
+      PUSH_DATA (push, 8192 << 16);
+   }
 
 #define MK_MACRO(m, n) i = nvc0_graph_set_macro(screen, m, i, sizeof(n), n);
 
index c58add537880a6893a417ac04fb3c2330715b1bb..4802057f70eec4fe40e38509223dd9cad39dd632 100644 (file)
@@ -20,6 +20,9 @@
 
 #define NVC0_MAX_SURFACE_SLOTS 16
 
+#define NVC0_MAX_VIEWPORTS 16
+
+
 struct nvc0_context;
 
 struct nvc0_blitter;
index 27e5cd82d15be9b42143fcacf5f15239581eee92..c92aaaca5785667197ca2ee5b07dc5d0eadcc98b 100644 (file)
@@ -909,10 +909,17 @@ nvc0_set_scissor_states(struct pipe_context *pipe,
                         unsigned num_scissors,
                         const struct pipe_scissor_state *scissor)
 {
-    struct nvc0_context *nvc0 = nvc0_context(pipe);
+   struct nvc0_context *nvc0 = nvc0_context(pipe);
+   int i;
 
-    nvc0->scissor = *scissor;
-    nvc0->dirty |= NVC0_NEW_SCISSOR;
+   assert(start_slot + num_scissors <= NVC0_MAX_VIEWPORTS);
+   for (i = 0; i < num_scissors; i++) {
+      if (!memcmp(&nvc0->scissors[start_slot + i], &scissor[i], sizeof(*scissor)))
+         continue;
+      nvc0->scissors[start_slot + i] = scissor[i];
+      nvc0->scissors_dirty |= 1 << (start_slot + i);
+      nvc0->dirty |= NVC0_NEW_SCISSOR;
+   }
 }
 
 static void
@@ -921,10 +928,18 @@ nvc0_set_viewport_states(struct pipe_context *pipe,
                          unsigned num_viewports,
                          const struct pipe_viewport_state *vpt)
 {
-    struct nvc0_context *nvc0 = nvc0_context(pipe);
+   struct nvc0_context *nvc0 = nvc0_context(pipe);
+   int i;
+
+   assert(start_slot + num_viewports <= NVC0_MAX_VIEWPORTS);
+   for (i = 0; i < num_viewports; i++) {
+      if (!memcmp(&nvc0->viewports[start_slot + i], &vpt[i], sizeof(*vpt)))
+         continue;
+      nvc0->viewports[start_slot + i] = vpt[i];
+      nvc0->viewports_dirty |= 1 << (start_slot + i);
+      nvc0->dirty |= NVC0_NEW_VIEWPORT;
+   }
 
-    nvc0->viewport = *vpt;
-    nvc0->dirty |= NVC0_NEW_VIEWPORT;
 }
 
 static void
index dcec91089700919fac0770390123792687e9615a..0cc7a5231f15e2fc004578e1352d99530bed2167 100644 (file)
@@ -236,59 +236,82 @@ nvc0_validate_stipple(struct nvc0_context *nvc0)
 static void
 nvc0_validate_scissor(struct nvc0_context *nvc0)
 {
-    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
-    struct pipe_scissor_state *s = &nvc0->scissor;
+   int i;
+   struct nouveau_pushbuf *push = nvc0->base.pushbuf;
+
+   if (!(nvc0->dirty & NVC0_NEW_SCISSOR) &&
+      nvc0->rast->pipe.scissor == nvc0->state.scissor)
+      return;
 
-    if (!(nvc0->dirty & NVC0_NEW_SCISSOR) &&
-        nvc0->rast->pipe.scissor == nvc0->state.scissor)
-       return;
-    nvc0->state.scissor = nvc0->rast->pipe.scissor;
+   if (nvc0->state.scissor != nvc0->rast->pipe.scissor)
+      nvc0->scissors_dirty = (1 << NVC0_MAX_VIEWPORTS) - 1;
 
-    BEGIN_NVC0(push, NVC0_3D(SCISSOR_HORIZ(0)), 2);
-    if (nvc0->rast->pipe.scissor) {
-       PUSH_DATA(push, (s->maxx << 16) | s->minx);
-       PUSH_DATA(push, (s->maxy << 16) | s->miny);
-    } else {
-       PUSH_DATA(push, (0xffff << 16) | 0);
-       PUSH_DATA(push, (0xffff << 16) | 0);
-    }
+   nvc0->state.scissor = nvc0->rast->pipe.scissor;
+
+   for (i = 0; i < NVC0_MAX_VIEWPORTS; i++) {
+      struct pipe_scissor_state *s = &nvc0->scissors[i];
+      if (!(nvc0->scissors_dirty & (1 << i)))
+         continue;
+
+      BEGIN_NVC0(push, NVC0_3D(SCISSOR_HORIZ(i)), 2);
+      if (nvc0->rast->pipe.scissor) {
+         PUSH_DATA(push, (s->maxx << 16) | s->minx);
+         PUSH_DATA(push, (s->maxy << 16) | s->miny);
+      } else {
+         PUSH_DATA(push, (0xffff << 16) | 0);
+         PUSH_DATA(push, (0xffff << 16) | 0);
+      }
+   }
+   nvc0->scissors_dirty = 0;
 }
 
 static void
 nvc0_validate_viewport(struct nvc0_context *nvc0)
 {
-    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
-    struct pipe_viewport_state *vp = &nvc0->viewport;
-    int x, y, w, h;
-    float zmin, zmax;
-
-    BEGIN_NVC0(push, NVC0_3D(VIEWPORT_TRANSLATE_X(0)), 3);
-    PUSH_DATAf(push, vp->translate[0]);
-    PUSH_DATAf(push, vp->translate[1]);
-    PUSH_DATAf(push, vp->translate[2]);
-    BEGIN_NVC0(push, NVC0_3D(VIEWPORT_SCALE_X(0)), 3);
-    PUSH_DATAf(push, vp->scale[0]);
-    PUSH_DATAf(push, vp->scale[1]);
-    PUSH_DATAf(push, vp->scale[2]);
-
-    /* now set the viewport rectangle to viewport dimensions for clipping */
-
-    x = util_iround(MAX2(0.0f, vp->translate[0] - fabsf(vp->scale[0])));
-    y = util_iround(MAX2(0.0f, vp->translate[1] - fabsf(vp->scale[1])));
-    w = util_iround(vp->translate[0] + fabsf(vp->scale[0])) - x;
-    h = util_iround(vp->translate[1] + fabsf(vp->scale[1])) - y;
-
-    zmin = vp->translate[2] - fabsf(vp->scale[2]);
-    zmax = vp->translate[2] + fabsf(vp->scale[2]);
-
-    nvc0->vport_int[0] = (w << 16) | x;
-    nvc0->vport_int[1] = (h << 16) | y;
-    BEGIN_NVC0(push, NVC0_3D(VIEWPORT_HORIZ(0)), 2);
-    PUSH_DATA (push, nvc0->vport_int[0]);
-    PUSH_DATA (push, nvc0->vport_int[1]);
-    BEGIN_NVC0(push, NVC0_3D(DEPTH_RANGE_NEAR(0)), 2);
-    PUSH_DATAf(push, zmin);
-    PUSH_DATAf(push, zmax);
+   struct nouveau_pushbuf *push = nvc0->base.pushbuf;
+   int x, y, w, h, i;
+   float zmin, zmax;
+
+   for (i = 0; i < NVC0_MAX_VIEWPORTS; i++) {
+      struct pipe_viewport_state *vp = &nvc0->viewports[i];
+
+      if (!(nvc0->viewports_dirty & (1 << i)))
+         continue;
+
+      BEGIN_NVC0(push, NVC0_3D(VIEWPORT_TRANSLATE_X(i)), 3);
+      PUSH_DATAf(push, vp->translate[0]);
+      PUSH_DATAf(push, vp->translate[1]);
+      PUSH_DATAf(push, vp->translate[2]);
+
+      BEGIN_NVC0(push, NVC0_3D(VIEWPORT_SCALE_X(i)), 3);
+      PUSH_DATAf(push, vp->scale[0]);
+      PUSH_DATAf(push, vp->scale[1]);
+      PUSH_DATAf(push, vp->scale[2]);
+
+      /* now set the viewport rectangle to viewport dimensions for clipping */
+
+      x = util_iround(MAX2(0.0f, vp->translate[0] - fabsf(vp->scale[0])));
+      y = util_iround(MAX2(0.0f, vp->translate[1] - fabsf(vp->scale[1])));
+      w = util_iround(vp->translate[0] + fabsf(vp->scale[0])) - x;
+      h = util_iround(vp->translate[1] + fabsf(vp->scale[1])) - y;
+
+      BEGIN_NVC0(push, NVC0_3D(VIEWPORT_HORIZ(i)), 2);
+      PUSH_DATA (push, (w << 16) | x);
+      PUSH_DATA (push, (h << 16) | y);
+
+      if (i == 0) {
+         nvc0->vport_int[0] = (w << 16) | x;
+         nvc0->vport_int[1] = (h << 16) | y;
+      }
+
+      zmin = vp->translate[2] - fabsf(vp->scale[2]);
+      zmax = vp->translate[2] + fabsf(vp->scale[2]);
+
+      BEGIN_NVC0(push, NVC0_3D(DEPTH_RANGE_NEAR(i)), 2);
+      PUSH_DATAf(push, zmin);
+      PUSH_DATAf(push, zmax);
+   }
+   nvc0->viewports_dirty = 0;
 }
 
 static INLINE void
@@ -527,6 +550,8 @@ nvc0_switch_pipe_context(struct nvc0_context *ctx_to)
       ctx_to->state = ctx_from->state;
 
    ctx_to->dirty = ~0;
+   ctx_to->viewports_dirty = ~0;
+   ctx_to->scissors_dirty = ~0;
 
    for (s = 0; s < 5; ++s) {
       ctx_to->samplers_dirty[s] = ~0;
index c28ec6d77b9c7ed7499a3e0e5399b5c0de7abe24..f782eec3fb7c0816143d64e0a015ac37166f0468 100644 (file)
@@ -1016,6 +1016,7 @@ nvc0_blitctx_post_blit(struct nvc0_blitctx *blit)
        NVC0_NEW_VERTPROG | NVC0_NEW_FRAGPROG |
        NVC0_NEW_TCTLPROG | NVC0_NEW_TEVLPROG | NVC0_NEW_GMTYPROG |
        NVC0_NEW_TFB_TARGETS | NVC0_NEW_VERTEX | NVC0_NEW_ARRAYS);
+   nvc0->scissors_dirty |= 1;
 
    nvc0->base.pipe.set_min_samples(&nvc0->base.pipe, blit->saved.min_samples);
 }