Merge remote-tracking branch 'mesa-public/master' into vulkan
[mesa.git] / src / gallium / drivers / nouveau / nvc0 / nvc0_context.c
index 83c8c34fa5b35074f4ef241166e134628f442f75..547b8f5d309e0d20af1f4b268f3685cd1ba48b58 100644 (file)
 #include "pipe/p_defines.h"
 #include "util/u_framebuffer.h"
 
-#ifdef NVC0_WITH_DRAW_MODULE
-#include "draw/draw_context.h"
-#endif
-
 #include "nvc0/nvc0_context.h"
 #include "nvc0/nvc0_screen.h"
 #include "nvc0/nvc0_resource.h"
@@ -60,19 +56,43 @@ static void
 nvc0_memory_barrier(struct pipe_context *pipe, unsigned flags)
 {
    struct nvc0_context *nvc0 = nvc0_context(pipe);
-   int i;
+   struct nouveau_pushbuf *push = nvc0->base.pushbuf;
+   int i, s;
 
    if (flags & PIPE_BARRIER_MAPPED_BUFFER) {
       for (i = 0; i < nvc0->num_vtxbufs; ++i) {
          if (!nvc0->vtxbuf[i].buffer)
             continue;
          if (nvc0->vtxbuf[i].buffer->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT)
-            nvc0->base.vbo_dirty = TRUE;
+            nvc0->base.vbo_dirty = true;
       }
 
       if (nvc0->idxbuf.buffer &&
           nvc0->idxbuf.buffer->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT)
-         nvc0->base.vbo_dirty = TRUE;
+         nvc0->base.vbo_dirty = true;
+
+      for (s = 0; s < 5 && !nvc0->cb_dirty; ++s) {
+         uint32_t valid = nvc0->constbuf_valid[s];
+
+         while (valid && !nvc0->cb_dirty) {
+            const unsigned i = ffs(valid) - 1;
+            struct pipe_resource *res;
+
+            valid &= ~(1 << i);
+            if (nvc0->constbuf[s][i].user)
+               continue;
+
+            res = nvc0->constbuf[s][i].u.buf;
+            if (!res)
+               continue;
+
+            if (res->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT)
+               nvc0->cb_dirty = true;
+         }
+      }
+   }
+   if (flags & PIPE_BARRIER_SHADER_BUFFER) {
+      IMMED_NVC0(push, NVC0_3D(MEM_BARRIER), 0x1011);
    }
 }
 
@@ -106,6 +126,10 @@ nvc0_context_unreference_resources(struct nvc0_context *nvc0)
          pipe_surface_reference(&nvc0->surfaces[s][i], NULL);
    }
 
+   for (s = 0; s < 6; ++s)
+      for (i = 0; i < NVC0_MAX_BUFFERS; ++i)
+         pipe_resource_reference(&nvc0->buffers[s][i].buffer, NULL);
+
    for (i = 0; i < nvc0->num_tfbbufs; ++i)
       pipe_so_target_reference(&nvc0->tfbbuf[i], NULL);
 
@@ -116,6 +140,9 @@ nvc0_context_unreference_resources(struct nvc0_context *nvc0)
       pipe_resource_reference(res, NULL);
    }
    util_dynarray_fini(&nvc0->global_residents);
+
+   if (nvc0->tcp_empty)
+      nvc0->base.pipe.delete_tcs_state(&nvc0->base.pipe, nvc0->tcp_empty);
 }
 
 static void
@@ -124,19 +151,20 @@ nvc0_destroy(struct pipe_context *pipe)
    struct nvc0_context *nvc0 = nvc0_context(pipe);
 
    if (nvc0->screen->cur_ctx == nvc0) {
-      nvc0->base.pushbuf->kick_notify = NULL;
       nvc0->screen->cur_ctx = NULL;
-      nouveau_pushbuf_bufctx(nvc0->base.pushbuf, NULL);
+      nvc0->screen->save_state = nvc0->state;
+      nvc0->screen->save_state.tfb = NULL;
    }
+
+   /* Unset bufctx, we don't want to revalidate any resources after the flush.
+    * Other contexts will always set their bufctx again on action calls.
+    */
+   nouveau_pushbuf_bufctx(nvc0->base.pushbuf, NULL);
    nouveau_pushbuf_kick(nvc0->base.pushbuf, nvc0->base.pushbuf->channel);
 
    nvc0_context_unreference_resources(nvc0);
    nvc0_blitctx_destroy(nvc0);
 
-#ifdef NVC0_WITH_DRAW_MODULE
-   draw_destroy(nvc0->draw);
-#endif
-
    nouveau_context_destroy(&nvc0->base);
 }
 
@@ -147,11 +175,11 @@ nvc0_default_kick_notify(struct nouveau_pushbuf *push)
 
    if (screen) {
       nouveau_fence_next(&screen->base);
-      nouveau_fence_update(&screen->base, TRUE);
+      nouveau_fence_update(&screen->base, true);
       if (screen->cur_ctx)
-         screen->cur_ctx->state.flushed = TRUE;
+         screen->cur_ctx->state.flushed = true;
+      NOUVEAU_DRV_STAT(&screen->base, pushbuf_count, 1);
    }
-   NOUVEAU_DRV_STAT(&screen->base, pushbuf_count, 1);
 }
 
 static int
@@ -183,7 +211,7 @@ nvc0_invalidate_resource_storage(struct nouveau_context *ctx,
       }
    }
 
-   if (res->bind & PIPE_BIND_VERTEX_BUFFER) {
+   if (res->target == PIPE_BUFFER) {
       for (i = 0; i < nvc0->num_vtxbufs; ++i) {
          if (nvc0->vtxbuf[i].buffer == res) {
             nvc0->dirty |= NVC0_NEW_ARRAYS;
@@ -192,17 +220,14 @@ nvc0_invalidate_resource_storage(struct nouveau_context *ctx,
                return ref;
          }
       }
-   }
-   if (res->bind & PIPE_BIND_INDEX_BUFFER) {
+
       if (nvc0->idxbuf.buffer == res) {
          nvc0->dirty |= NVC0_NEW_IDXBUF;
          nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_IDX);
          if (!--ref)
             return ref;
       }
-   }
 
-   if (res->bind & PIPE_BIND_SAMPLER_VIEW) {
       for (s = 0; s < 5; ++s) {
       for (i = 0; i < nvc0->num_textures[s]; ++i) {
          if (nvc0->textures[s][i] &&
@@ -215,11 +240,11 @@ nvc0_invalidate_resource_storage(struct nouveau_context *ctx,
          }
       }
       }
-   }
 
-   if (res->bind & PIPE_BIND_CONSTANT_BUFFER) {
       for (s = 0; s < 5; ++s) {
-      for (i = 0; i < nvc0->num_vtxbufs; ++i) {
+      for (i = 0; i < NVC0_MAX_PIPE_CONSTBUFS; ++i) {
+         if (!(nvc0->constbuf_valid[s] & (1 << i)))
+            continue;
          if (!nvc0->constbuf[s][i].user &&
              nvc0->constbuf[s][i].u.buf == res) {
             nvc0->dirty |= NVC0_NEW_CONSTBUF;
@@ -230,6 +255,18 @@ nvc0_invalidate_resource_storage(struct nouveau_context *ctx,
          }
       }
       }
+
+      for (s = 0; s < 5; ++s) {
+      for (i = 0; i < NVC0_MAX_BUFFERS; ++i) {
+         if (nvc0->buffers[s][i].buffer == res) {
+            nvc0->buffers_dirty[s] |= 1 << i;
+            nvc0->dirty |= NVC0_NEW_BUFFERS;
+            nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_BUF);
+            if (!--ref)
+               return ref;
+         }
+      }
+      }
    }
 
    return ref;
@@ -240,7 +277,7 @@ nvc0_context_get_sample_position(struct pipe_context *, unsigned, unsigned,
                                  float *);
 
 struct pipe_context *
-nvc0_create(struct pipe_screen *pscreen, void *priv)
+nvc0_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags)
 {
    struct nvc0_screen *screen = nvc0_screen(pscreen);
    struct nvc0_context *nvc0;
@@ -287,12 +324,7 @@ nvc0_create(struct pipe_screen *pscreen, void *priv)
    pipe->memory_barrier = nvc0_memory_barrier;
    pipe->get_sample_position = nvc0_context_get_sample_position;
 
-   if (!screen->cur_ctx) {
-      screen->cur_ctx = nvc0;
-      nouveau_pushbuf_bufctx(screen->base.pushbuf, nvc0->bufctx);
-   }
-   screen->base.pushbuf->kick_notify = nvc0_default_kick_notify;
-
+   nouveau_context_init(&nvc0->base);
    nvc0_init_query_functions(nvc0);
    nvc0_init_surface_functions(nvc0);
    nvc0_init_state_functions(nvc0);
@@ -301,22 +333,30 @@ nvc0_create(struct pipe_screen *pscreen, void *priv)
 
    nvc0->base.invalidate_resource_storage = nvc0_invalidate_resource_storage;
 
-#ifdef NVC0_WITH_DRAW_MODULE
-   /* no software fallbacks implemented */
-   nvc0->draw = draw_create(pipe);
-   assert(nvc0->draw);
-   draw_set_rasterize_stage(nvc0->draw, nvc0_draw_render_stage(nvc0));
-#endif
-
    pipe->create_video_codec = nvc0_create_decoder;
    pipe->create_video_buffer = nvc0_video_buffer_create;
 
    /* shader builtin library is per-screen, but we need a context for m2mf */
    nvc0_program_library_upload(nvc0);
+   nvc0_program_init_tcp_empty(nvc0);
+   if (!nvc0->tcp_empty)
+      goto out_err;
+   /* set the empty tctl prog on next draw in case one is never set */
+   nvc0->dirty |= NVC0_NEW_TCTLPROG;
+
+   /* now that there are no more opportunities for errors, set the current
+    * context if there isn't already one.
+    */
+   if (!screen->cur_ctx) {
+      nvc0->state = screen->save_state;
+      screen->cur_ctx = nvc0;
+      nouveau_pushbuf_bufctx(screen->base.pushbuf, nvc0->bufctx);
+   }
+   screen->base.pushbuf->kick_notify = nvc0_default_kick_notify;
 
    /* add permanently resident buffers to bufctxts */
 
-   flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;
+   flags = NV_VRAM_DOMAIN(&screen->base) | NOUVEAU_BO_RD;
 
    BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->text);
    BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->uniform_bo);
@@ -327,7 +367,7 @@ nvc0_create(struct pipe_screen *pscreen, void *priv)
       BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->parm);
    }
 
-   flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR;
+   flags = NV_VRAM_DOMAIN(&screen->base) | NOUVEAU_BO_RDWR;
 
    if (screen->poly_cache)
       BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->poly_cache);
@@ -357,8 +397,7 @@ out_err:
          nouveau_bufctx_del(&nvc0->bufctx_cp);
       if (nvc0->bufctx)
          nouveau_bufctx_del(&nvc0->bufctx);
-      if (nvc0->blit)
-         FREE(nvc0->blit);
+      FREE(nvc0->blit);
       FREE(nvc0);
    }
    return NULL;
@@ -366,7 +405,7 @@ out_err:
 
 void
 nvc0_bufctx_fence(struct nvc0_context *nvc0, struct nouveau_bufctx *bufctx,
-                  boolean on_flush)
+                  bool on_flush)
 {
    struct nouveau_list *list = on_flush ? &bufctx->current : &bufctx->pending;
    struct nouveau_list *it;