nouveau: send back a debug message when waiting for a fence to complete
[mesa.git] / src / gallium / drivers / nouveau / nouveau_context.h
index 19bf7c84ac7350fde934a24963f6966c4a64a956..c3bbb11bd6047b332ba52d3f978cc23e8c0cb236 100644 (file)
@@ -2,22 +2,61 @@
 #define __NOUVEAU_CONTEXT_H__
 
 #include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include <nouveau.h>
+
+#define NOUVEAU_MAX_SCRATCH_BUFS 4
+
+struct nv04_resource;
 
 struct nouveau_context {
    struct pipe_context pipe;
    struct nouveau_screen *screen;
 
-   boolean vbo_dirty;
+   struct nouveau_client *client;
+   struct nouveau_pushbuf *pushbuf;
+   struct pipe_debug_callback debug;
+
+   bool vbo_dirty;
 
    void (*copy_data)(struct nouveau_context *,
                      struct nouveau_bo *dst, unsigned, unsigned,
                      struct nouveau_bo *src, unsigned, unsigned, unsigned);
    void (*push_data)(struct nouveau_context *,
                      struct nouveau_bo *dst, unsigned, unsigned,
-                     unsigned, void *);
+                     unsigned, const void *);
+   /* base, size refer to the whole constant buffer */
+   void (*push_cb)(struct nouveau_context *,
+                   struct nv04_resource *,
+                   unsigned offset, unsigned words, const uint32_t *);
+
+   /* @return: @ref reduced by nr of references found in context */
+   int (*invalidate_resource_storage)(struct nouveau_context *,
+                                      struct pipe_resource *,
+                                      int ref);
+
+   struct {
+      uint8_t *map;
+      unsigned id;
+      unsigned wrap;
+      unsigned offset;
+      unsigned end;
+      struct nouveau_bo *bo[NOUVEAU_MAX_SCRATCH_BUFS];
+      struct nouveau_bo *current;
+      struct runout {
+         unsigned nr;
+         struct nouveau_bo *bo[0];
+      } *runout;
+      unsigned bo_size;
+   } scratch;
+
+   struct {
+      uint32_t buf_cache_count;
+      uint32_t buf_cache_frame;
+   } stats;
 };
 
-static INLINE struct nouveau_context *
+static inline struct nouveau_context *
 nouveau_context(struct pipe_context *pipe)
 {
    return (struct nouveau_context *)pipe;
@@ -26,4 +65,53 @@ nouveau_context(struct pipe_context *pipe)
 void
 nouveau_context_init_vdec(struct nouveau_context *);
 
+void
+nouveau_context_init(struct nouveau_context *);
+
+void
+nouveau_scratch_runout_release(struct nouveau_context *);
+
+/* This is needed because we don't hold references outside of context::scratch,
+ * because we don't want to un-bo_ref each allocation every time. This is less
+ * work, and we need the wrap index anyway for extreme situations.
+ */
+static inline void
+nouveau_scratch_done(struct nouveau_context *nv)
+{
+   nv->scratch.wrap = nv->scratch.id;
+   if (unlikely(nv->scratch.runout))
+      nouveau_scratch_runout_release(nv);
+}
+
+/* Get pointer to scratch buffer.
+ * The returned nouveau_bo is only referenced by the context, don't un-ref it !
+ */
+void *
+nouveau_scratch_get(struct nouveau_context *, unsigned size, uint64_t *gpu_addr,
+                    struct nouveau_bo **);
+
+static inline void
+nouveau_context_destroy(struct nouveau_context *ctx)
+{
+   int i;
+
+   for (i = 0; i < NOUVEAU_MAX_SCRATCH_BUFS; ++i)
+      if (ctx->scratch.bo[i])
+         nouveau_bo_ref(NULL, &ctx->scratch.bo[i]);
+
+   FREE(ctx);
+}
+
+static inline  void
+nouveau_context_update_frame_stats(struct nouveau_context *nv)
+{
+   nv->stats.buf_cache_frame <<= 1;
+   if (nv->stats.buf_cache_count) {
+      nv->stats.buf_cache_count = 0;
+      nv->stats.buf_cache_frame |= 1;
+      if ((nv->stats.buf_cache_frame & 0xf) == 0xf)
+         nv->screen->hint_buf_keep_sysmem_copy = true;
+   }
+}
+
 #endif