1848b8605Smrg#ifndef __NOUVEAU_CONTEXT_H__
2848b8605Smrg#define __NOUVEAU_CONTEXT_H__
3848b8605Smrg
4848b8605Smrg#include "pipe/p_context.h"
5b8e80941Smrg#include "pipe/p_state.h"
6848b8605Smrg#include <nouveau.h>
7848b8605Smrg
8848b8605Smrg#define NOUVEAU_MAX_SCRATCH_BUFS 4
9848b8605Smrg
10b8e80941Smrgstruct nv04_resource;
11b8e80941Smrg
12848b8605Smrgstruct nouveau_context {
13848b8605Smrg   struct pipe_context pipe;
14848b8605Smrg   struct nouveau_screen *screen;
15848b8605Smrg
16848b8605Smrg   struct nouveau_client *client;
17848b8605Smrg   struct nouveau_pushbuf *pushbuf;
18b8e80941Smrg   struct pipe_debug_callback debug;
19848b8605Smrg
20b8e80941Smrg   bool vbo_dirty;
21848b8605Smrg
22848b8605Smrg   void (*copy_data)(struct nouveau_context *,
23848b8605Smrg                     struct nouveau_bo *dst, unsigned, unsigned,
24848b8605Smrg                     struct nouveau_bo *src, unsigned, unsigned, unsigned);
25848b8605Smrg   void (*push_data)(struct nouveau_context *,
26848b8605Smrg                     struct nouveau_bo *dst, unsigned, unsigned,
27848b8605Smrg                     unsigned, const void *);
28848b8605Smrg   /* base, size refer to the whole constant buffer */
29848b8605Smrg   void (*push_cb)(struct nouveau_context *,
30b8e80941Smrg                   struct nv04_resource *,
31848b8605Smrg                   unsigned offset, unsigned words, const uint32_t *);
32848b8605Smrg
33848b8605Smrg   /* @return: @ref reduced by nr of references found in context */
34848b8605Smrg   int (*invalidate_resource_storage)(struct nouveau_context *,
35848b8605Smrg                                      struct pipe_resource *,
36848b8605Smrg                                      int ref);
37848b8605Smrg
38848b8605Smrg   struct {
39848b8605Smrg      uint8_t *map;
40848b8605Smrg      unsigned id;
41848b8605Smrg      unsigned wrap;
42848b8605Smrg      unsigned offset;
43848b8605Smrg      unsigned end;
44848b8605Smrg      struct nouveau_bo *bo[NOUVEAU_MAX_SCRATCH_BUFS];
45848b8605Smrg      struct nouveau_bo *current;
46b8e80941Smrg      struct runout {
47b8e80941Smrg         unsigned nr;
48b8e80941Smrg         struct nouveau_bo *bo[0];
49b8e80941Smrg      } *runout;
50848b8605Smrg      unsigned bo_size;
51848b8605Smrg   } scratch;
52848b8605Smrg
53848b8605Smrg   struct {
54848b8605Smrg      uint32_t buf_cache_count;
55848b8605Smrg      uint32_t buf_cache_frame;
56848b8605Smrg   } stats;
57848b8605Smrg};
58848b8605Smrg
59b8e80941Smrgstatic inline struct nouveau_context *
60848b8605Smrgnouveau_context(struct pipe_context *pipe)
61848b8605Smrg{
62848b8605Smrg   return (struct nouveau_context *)pipe;
63848b8605Smrg}
64848b8605Smrg
65848b8605Smrgvoid
66848b8605Smrgnouveau_context_init_vdec(struct nouveau_context *);
67848b8605Smrg
68b8e80941Smrgvoid
69b8e80941Smrgnouveau_context_init(struct nouveau_context *);
70b8e80941Smrg
71848b8605Smrgvoid
72848b8605Smrgnouveau_scratch_runout_release(struct nouveau_context *);
73848b8605Smrg
74848b8605Smrg/* This is needed because we don't hold references outside of context::scratch,
75848b8605Smrg * because we don't want to un-bo_ref each allocation every time. This is less
76848b8605Smrg * work, and we need the wrap index anyway for extreme situations.
77848b8605Smrg */
78b8e80941Smrgstatic inline void
79848b8605Smrgnouveau_scratch_done(struct nouveau_context *nv)
80848b8605Smrg{
81848b8605Smrg   nv->scratch.wrap = nv->scratch.id;
82b8e80941Smrg   if (unlikely(nv->scratch.runout))
83848b8605Smrg      nouveau_scratch_runout_release(nv);
84848b8605Smrg}
85848b8605Smrg
86848b8605Smrg/* Get pointer to scratch buffer.
87848b8605Smrg * The returned nouveau_bo is only referenced by the context, don't un-ref it !
88848b8605Smrg */
89848b8605Smrgvoid *
90848b8605Smrgnouveau_scratch_get(struct nouveau_context *, unsigned size, uint64_t *gpu_addr,
91848b8605Smrg                    struct nouveau_bo **);
92848b8605Smrg
93b8e80941Smrgstatic inline void
94848b8605Smrgnouveau_context_destroy(struct nouveau_context *ctx)
95848b8605Smrg{
96848b8605Smrg   int i;
97848b8605Smrg
98848b8605Smrg   for (i = 0; i < NOUVEAU_MAX_SCRATCH_BUFS; ++i)
99848b8605Smrg      if (ctx->scratch.bo[i])
100848b8605Smrg         nouveau_bo_ref(NULL, &ctx->scratch.bo[i]);
101848b8605Smrg
102848b8605Smrg   FREE(ctx);
103848b8605Smrg}
104848b8605Smrg
105b8e80941Smrgstatic inline  void
106848b8605Smrgnouveau_context_update_frame_stats(struct nouveau_context *nv)
107848b8605Smrg{
108848b8605Smrg   nv->stats.buf_cache_frame <<= 1;
109848b8605Smrg   if (nv->stats.buf_cache_count) {
110848b8605Smrg      nv->stats.buf_cache_count = 0;
111848b8605Smrg      nv->stats.buf_cache_frame |= 1;
112848b8605Smrg      if ((nv->stats.buf_cache_frame & 0xf) == 0xf)
113b8e80941Smrg         nv->screen->hint_buf_keep_sysmem_copy = true;
114848b8605Smrg   }
115848b8605Smrg}
116848b8605Smrg
117848b8605Smrg#endif
118