85f8ed4da49001b75daa7a623aacf4bbfb518a56
[mesa.git] / src / gallium / drivers / nvc0 / nvc0_winsys.h
1
2 #ifndef __NVC0_WINSYS_H__
3 #define __NVC0_WINSYS_H__
4
5 #include <stdint.h>
6 #include <unistd.h>
7 #include "pipe/p_defines.h"
8
9 #include "nouveau/nouveau_bo.h"
10 #include "nouveau/nouveau_channel.h"
11 #include "nouveau/nouveau_grobj.h"
12 #include "nouveau/nouveau_device.h"
13 #include "nouveau/nouveau_resource.h"
14 #include "nouveau/nouveau_reloc.h"
15
16 #include "nvc0_resource.h" /* OUT_RESRC */
17
18 #ifndef NV04_PFIFO_MAX_PACKET_LEN
19 #define NV04_PFIFO_MAX_PACKET_LEN 2047
20 #endif
21
22 #define NVC0_SUBCH_3D 1
23 #define NVC0_SUBCH_2D 2
24 #define NVC0_SUBCH_MF 3
25
26 #define NVC0_MF_(n) NVC0_M2MF_##n
27
28 #define RING_3D(n) ((NVC0_SUBCH_3D << 13) | (NVC0_3D_##n >> 2))
29 #define RING_2D(n) ((NVC0_SUBCH_2D << 13) | (NVC0_2D_##n >> 2))
30 #define RING_MF(n) ((NVC0_SUBCH_MF << 13) | (NVC0_MF_(n) >> 2))
31
32 #define RING_3D_(m) ((NVC0_SUBCH_3D << 13) | ((m) >> 2))
33 #define RING_2D_(m) ((NVC0_SUBCH_2D << 13) | ((m) >> 2))
34 #define RING_MF_(m) ((NVC0_SUBCH_MF << 13) | ((m) >> 2))
35
36 #define RING_GR(gr, m) (((gr)->subc << 13) | ((m) >> 2))
37
38 int nouveau_pushbuf_flush(struct nouveau_channel *, unsigned min);
39
40 static inline uint32_t
41 nouveau_bo_tile_layout(struct nouveau_bo *bo)
42 {
43 return bo->tile_flags & NOUVEAU_BO_TILE_LAYOUT_MASK;
44 }
45
46 static INLINE void
47 WAIT_RING(struct nouveau_channel *chan, unsigned size)
48 {
49 if (chan->cur + size > chan->end)
50 nouveau_pushbuf_flush(chan, size);
51 }
52
53 static INLINE void
54 OUT_RING(struct nouveau_channel *chan, uint32_t data)
55 {
56 *(chan->cur++) = (data);
57 }
58
59 /* incremental methods */
60 static INLINE void
61 BEGIN_RING(struct nouveau_channel *chan, uint32_t mthd, unsigned size)
62 {
63 WAIT_RING(chan, size + 1);
64 OUT_RING (chan, (0x2 << 28) | (size << 16) | mthd);
65 }
66
67 /* non-incremental */
68 static INLINE void
69 BEGIN_RING_NI(struct nouveau_channel *chan, uint32_t mthd, unsigned size)
70 {
71 WAIT_RING(chan, size + 1);
72 OUT_RING (chan, (0x6 << 28) | (size << 16) | mthd);
73 }
74
75 /* increment-once */
76 static INLINE void
77 BEGIN_RING_1I(struct nouveau_channel *chan, uint32_t mthd, unsigned size)
78 {
79 WAIT_RING(chan, size + 1);
80 OUT_RING (chan, (0xa << 28) | (size << 16) | mthd);
81 }
82
83 /* inline-data */
84 static INLINE void
85 IMMED_RING(struct nouveau_channel *chan, uint32_t mthd, unsigned data)
86 {
87 WAIT_RING(chan, 1);
88 OUT_RING (chan, (0x8 << 28) | (data << 16) | mthd);
89 }
90
91 int
92 nouveau_pushbuf_marker_emit(struct nouveau_channel *chan,
93 unsigned wait_dwords, unsigned wait_relocs);
94 int
95 nouveau_pushbuf_emit_reloc(struct nouveau_channel *, void *ptr,
96 struct nouveau_bo *, uint32_t data, uint32_t data2,
97 uint32_t flags, uint32_t vor, uint32_t tor);
98 int
99 nouveau_pushbuf_submit(struct nouveau_channel *chan, struct nouveau_bo *bo,
100 unsigned offset, unsigned length);
101
102 static INLINE int
103 MARK_RING(struct nouveau_channel *chan, unsigned dwords, unsigned relocs)
104 {
105 return nouveau_pushbuf_marker_emit(chan, dwords, relocs);
106 }
107
108 static INLINE void
109 OUT_RINGf(struct nouveau_channel *chan, float data)
110 {
111 union { uint32_t i; float f; } u;
112 u.f = data;
113 OUT_RING(chan, u.i);
114 }
115
116 static INLINE unsigned
117 AVAIL_RING(struct nouveau_channel *chan)
118 {
119 return chan->end - chan->cur;
120 }
121
122 static INLINE void
123 OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned size)
124 {
125 memcpy(chan->cur, data, size * 4);
126 chan->cur += size;
127 }
128
129 static INLINE int
130 OUT_RELOC(struct nouveau_channel *chan, struct nouveau_bo *bo,
131 unsigned data, unsigned flags, unsigned vor, unsigned tor)
132 {
133 return nouveau_pushbuf_emit_reloc(chan, chan->cur++, bo,
134 data, 0, flags, vor, tor);
135 }
136
137 static INLINE int
138 OUT_RELOCl(struct nouveau_channel *chan, struct nouveau_bo *bo,
139 unsigned delta, unsigned flags)
140 {
141 return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_LOW, 0, 0);
142 }
143
144 static INLINE int
145 OUT_RELOCh(struct nouveau_channel *chan, struct nouveau_bo *bo,
146 unsigned delta, unsigned flags)
147 {
148 return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_HIGH, 0, 0);
149 }
150
151 static INLINE int
152 OUT_RESRCh(struct nouveau_channel *chan, struct nvc0_resource *res,
153 unsigned delta, unsigned flags)
154 {
155 return OUT_RELOCh(chan, res->bo, res->offset + delta, res->domain | flags);
156 }
157
158 static INLINE int
159 OUT_RESRCl(struct nouveau_channel *chan, struct nvc0_resource *res,
160 unsigned delta, unsigned flags)
161 {
162 return OUT_RELOCl(chan, res->bo, res->offset + delta, res->domain | flags);
163 }
164
165 static INLINE void
166 FIRE_RING(struct nouveau_channel *chan)
167 {
168 nouveau_pushbuf_flush(chan, 0);
169 }
170
171 static INLINE void
172 BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned s)
173 {
174 struct nouveau_subchannel *subc = &gr->channel->subc[s];
175
176 assert(s < 8);
177 if (subc->gr) {
178 assert(subc->gr->bound != NOUVEAU_GROBJ_BOUND_EXPLICIT);
179 subc->gr->bound = NOUVEAU_GROBJ_UNBOUND;
180 }
181 subc->gr = gr;
182 subc->gr->subc = s;
183 subc->gr->bound = NOUVEAU_GROBJ_BOUND_EXPLICIT;
184
185 BEGIN_RING(chan, RING_GR(gr, 0x0000), 1);
186 OUT_RING (chan, gr->grclass);
187 }
188
189 #endif