14a49301eSmrg#ifndef __NOUVEAU_CONTEXT_H__
24a49301eSmrg#define __NOUVEAU_CONTEXT_H__
34a49301eSmrg
43464ebd5Sriastradh#include "pipe/p_context.h"
501e04c3fSmrg#include "pipe/p_state.h"
6af69d88dSmrg#include <nouveau.h>
7af69d88dSmrg
8af69d88dSmrg#define NOUVEAU_MAX_SCRATCH_BUFS 4
94a49301eSmrg
1001e04c3fSmrgstruct nv04_resource;
1101e04c3fSmrg
123464ebd5Sriastradhstruct nouveau_context {
133464ebd5Sriastradh   struct pipe_context pipe;
143464ebd5Sriastradh   struct nouveau_screen *screen;
153464ebd5Sriastradh
16af69d88dSmrg   struct nouveau_client *client;
17af69d88dSmrg   struct nouveau_pushbuf *pushbuf;
1801e04c3fSmrg   struct pipe_debug_callback debug;
19af69d88dSmrg
2001e04c3fSmrg   bool vbo_dirty;
213464ebd5Sriastradh
223464ebd5Sriastradh   void (*copy_data)(struct nouveau_context *,
233464ebd5Sriastradh                     struct nouveau_bo *dst, unsigned, unsigned,
243464ebd5Sriastradh                     struct nouveau_bo *src, unsigned, unsigned, unsigned);
253464ebd5Sriastradh   void (*push_data)(struct nouveau_context *,
263464ebd5Sriastradh                     struct nouveau_bo *dst, unsigned, unsigned,
27af69d88dSmrg                     unsigned, const void *);
28af69d88dSmrg   /* base, size refer to the whole constant buffer */
29af69d88dSmrg   void (*push_cb)(struct nouveau_context *,
3001e04c3fSmrg                   struct nv04_resource *,
31af69d88dSmrg                   unsigned offset, unsigned words, const uint32_t *);
32af69d88dSmrg
33af69d88dSmrg   /* @return: @ref reduced by nr of references found in context */
34af69d88dSmrg   int (*invalidate_resource_storage)(struct nouveau_context *,
35af69d88dSmrg                                      struct pipe_resource *,
36af69d88dSmrg                                      int ref);
37af69d88dSmrg
38af69d88dSmrg   struct {
39af69d88dSmrg      uint8_t *map;
40af69d88dSmrg      unsigned id;
41af69d88dSmrg      unsigned wrap;
42af69d88dSmrg      unsigned offset;
43af69d88dSmrg      unsigned end;
44af69d88dSmrg      struct nouveau_bo *bo[NOUVEAU_MAX_SCRATCH_BUFS];
45af69d88dSmrg      struct nouveau_bo *current;
4601e04c3fSmrg      struct runout {
4701e04c3fSmrg         unsigned nr;
4801e04c3fSmrg         struct nouveau_bo *bo[0];
4901e04c3fSmrg      } *runout;
50af69d88dSmrg      unsigned bo_size;
51af69d88dSmrg   } scratch;
52af69d88dSmrg
53af69d88dSmrg   struct {
54af69d88dSmrg      uint32_t buf_cache_count;
55af69d88dSmrg      uint32_t buf_cache_frame;
56af69d88dSmrg   } stats;
573464ebd5Sriastradh};
583464ebd5Sriastradh
5901e04c3fSmrgstatic inline struct nouveau_context *
603464ebd5Sriastradhnouveau_context(struct pipe_context *pipe)
613464ebd5Sriastradh{
623464ebd5Sriastradh   return (struct nouveau_context *)pipe;
633464ebd5Sriastradh}
644a49301eSmrg
65af69d88dSmrgvoid
66af69d88dSmrgnouveau_context_init_vdec(struct nouveau_context *);
67af69d88dSmrg
6801e04c3fSmrgvoid
6901e04c3fSmrgnouveau_context_init(struct nouveau_context *);
7001e04c3fSmrg
71af69d88dSmrgvoid
72af69d88dSmrgnouveau_scratch_runout_release(struct nouveau_context *);
73af69d88dSmrg
74af69d88dSmrg/* This is needed because we don't hold references outside of context::scratch,
75af69d88dSmrg * because we don't want to un-bo_ref each allocation every time. This is less
76af69d88dSmrg * work, and we need the wrap index anyway for extreme situations.
77af69d88dSmrg */
7801e04c3fSmrgstatic inline void
79af69d88dSmrgnouveau_scratch_done(struct nouveau_context *nv)
80af69d88dSmrg{
81af69d88dSmrg   nv->scratch.wrap = nv->scratch.id;
8201e04c3fSmrg   if (unlikely(nv->scratch.runout))
83af69d88dSmrg      nouveau_scratch_runout_release(nv);
84af69d88dSmrg}
85af69d88dSmrg
86af69d88dSmrg/* Get pointer to scratch buffer.
87af69d88dSmrg * The returned nouveau_bo is only referenced by the context, don't un-ref it !
88af69d88dSmrg */
89af69d88dSmrgvoid *
90af69d88dSmrgnouveau_scratch_get(struct nouveau_context *, unsigned size, uint64_t *gpu_addr,
91af69d88dSmrg                    struct nouveau_bo **);
92af69d88dSmrg
9301e04c3fSmrgstatic inline void
94af69d88dSmrgnouveau_context_destroy(struct nouveau_context *ctx)
95af69d88dSmrg{
96af69d88dSmrg   int i;
97af69d88dSmrg
98af69d88dSmrg   for (i = 0; i < NOUVEAU_MAX_SCRATCH_BUFS; ++i)
99af69d88dSmrg      if (ctx->scratch.bo[i])
100af69d88dSmrg         nouveau_bo_ref(NULL, &ctx->scratch.bo[i]);
101af69d88dSmrg
102af69d88dSmrg   FREE(ctx);
103af69d88dSmrg}
104af69d88dSmrg
10501e04c3fSmrgstatic inline  void
106af69d88dSmrgnouveau_context_update_frame_stats(struct nouveau_context *nv)
107af69d88dSmrg{
108af69d88dSmrg   nv->stats.buf_cache_frame <<= 1;
109af69d88dSmrg   if (nv->stats.buf_cache_count) {
110af69d88dSmrg      nv->stats.buf_cache_count = 0;
111af69d88dSmrg      nv->stats.buf_cache_frame |= 1;
112af69d88dSmrg      if ((nv->stats.buf_cache_frame & 0xf) == 0xf)
11301e04c3fSmrg         nv->screen->hint_buf_keep_sysmem_copy = true;
114af69d88dSmrg   }
115af69d88dSmrg}
116af69d88dSmrg
1174a49301eSmrg#endif
118