1 #ifndef NOUVEAU_WINSYS_H
2 #define NOUVEAU_WINSYS_H
3
4 #include <stdint.h>
5 #include <inttypes.h>
6
7 #include "pipe/p_defines.h"
8 #include "util/os_misc.h"
9
10 #include "drm-uapi/drm.h"
11 #include <nouveau.h>
12
13 #include "nouveau_screen.h"
14
15 #ifndef NV04_PFIFO_MAX_PACKET_LEN
16 #define NV04_PFIFO_MAX_PACKET_LEN 2047
17 #endif
18
19 #define NOUVEAU_MIN_BUFFER_MAP_ALIGN 64
20 #define NOUVEAU_MIN_BUFFER_MAP_ALIGN_MASK (NOUVEAU_MIN_BUFFER_MAP_ALIGN - 1)
21
22 static inline uint32_t
PUSH_AVAIL(struct nouveau_pushbuf * push)23 PUSH_AVAIL(struct nouveau_pushbuf *push)
24 {
25 return push->end - push->cur;
26 }
27
28 static inline bool
PUSH_SPACE_EX(struct nouveau_pushbuf * push,uint32_t size,uint32_t relocs,uint32_t pushes)29 PUSH_SPACE_EX(struct nouveau_pushbuf *push, uint32_t size, uint32_t relocs, uint32_t pushes)
30 {
31 struct nouveau_pushbuf_priv *ppush = push->user_priv;
32 simple_mtx_lock(&ppush->screen->fence.lock);
33 bool res = nouveau_pushbuf_space(push, size, relocs, pushes) == 0;
34 simple_mtx_unlock(&ppush->screen->fence.lock);
35 return res;
36 }
37
38 static inline bool
PUSH_SPACE(struct nouveau_pushbuf * push,uint32_t size)39 PUSH_SPACE(struct nouveau_pushbuf *push, uint32_t size)
40 {
41 /* Provide a buffer so that fences always have room to be emitted */
42 size += 8;
43 if (PUSH_AVAIL(push) < size)
44 return PUSH_SPACE_EX(push, size, 0, 0);
45 return true;
46 }
47
48 static inline void
PUSH_DATA(struct nouveau_pushbuf * push,uint32_t data)49 PUSH_DATA(struct nouveau_pushbuf *push, uint32_t data)
50 {
51 *push->cur++ = data;
52 }
53
54 static inline void
PUSH_DATAp(struct nouveau_pushbuf * push,const void * data,uint32_t size)55 PUSH_DATAp(struct nouveau_pushbuf *push, const void *data, uint32_t size)
56 {
57 memcpy(push->cur, data, size * 4);
58 push->cur += size;
59 }
60
61 static inline void
PUSH_DATAb(struct nouveau_pushbuf * push,const void * data,uint32_t size)62 PUSH_DATAb(struct nouveau_pushbuf *push, const void *data, uint32_t size)
63 {
64 memcpy(push->cur, data, size);
65 push->cur += DIV_ROUND_UP(size, 4);
66 }
67
68 static inline void
PUSH_DATAf(struct nouveau_pushbuf * push,float f)69 PUSH_DATAf(struct nouveau_pushbuf *push, float f)
70 {
71 union { float f; uint32_t i; } u;
72 u.f = f;
73 PUSH_DATA(push, u.i);
74 }
75
76 static inline int
PUSH_REFN(struct nouveau_pushbuf * push,struct nouveau_pushbuf_refn * refs,int nr)77 PUSH_REFN(struct nouveau_pushbuf *push, struct nouveau_pushbuf_refn *refs, int nr)
78 {
79 struct nouveau_pushbuf_priv *ppush = push->user_priv;
80 simple_mtx_lock(&ppush->screen->fence.lock);
81 int ret = nouveau_pushbuf_refn(push, refs, nr);
82 simple_mtx_unlock(&ppush->screen->fence.lock);
83 return ret;
84 }
85
86 static inline int
PUSH_REF1(struct nouveau_pushbuf * push,struct nouveau_bo * bo,uint32_t flags)87 PUSH_REF1(struct nouveau_pushbuf *push, struct nouveau_bo *bo, uint32_t flags)
88 {
89 struct nouveau_pushbuf_refn ref = { bo, flags };
90 return PUSH_REFN(push, &ref, 1);
91 }
92
93 static inline void
PUSH_KICK(struct nouveau_pushbuf * push)94 PUSH_KICK(struct nouveau_pushbuf *push)
95 {
96 struct nouveau_pushbuf_priv *ppush = push->user_priv;
97 simple_mtx_lock(&ppush->screen->fence.lock);
98 nouveau_pushbuf_kick(push, push->channel);
99 simple_mtx_unlock(&ppush->screen->fence.lock);
100 }
101
102 static inline int
PUSH_VAL(struct nouveau_pushbuf * push)103 PUSH_VAL(struct nouveau_pushbuf *push)
104 {
105 struct nouveau_pushbuf_priv *ppush = push->user_priv;
106 simple_mtx_lock(&ppush->screen->fence.lock);
107 int res = nouveau_pushbuf_validate(push);
108 simple_mtx_unlock(&ppush->screen->fence.lock);
109 return res;
110 }
111
112 static inline uint32_t
NV04_FIFO_PKHDR(int subc,int mthd,unsigned size)113 NV04_FIFO_PKHDR(int subc, int mthd, unsigned size)
114 {
115 return 0x00000000 | (size << 18) | (subc << 13) | mthd;
116 }
117
118 static inline uint32_t
NV04_FIFO_PKHDR_NI(int subc,int mthd,unsigned size)119 NV04_FIFO_PKHDR_NI(int subc, int mthd, unsigned size)
120 {
121 return 0x40000000 | (size << 18) | (subc << 13) | mthd;
122 }
123
124 static inline void
BEGIN_NV04(struct nouveau_pushbuf * push,int subc,int mthd,unsigned size)125 BEGIN_NV04(struct nouveau_pushbuf *push, int subc, int mthd, unsigned size)
126 {
127 #ifndef NV50_PUSH_EXPLICIT_SPACE_CHECKING
128 PUSH_SPACE(push, size + 1);
129 #endif
130 PUSH_DATA (push, NV04_FIFO_PKHDR(subc, mthd, size));
131 }
132
133 static inline void
BEGIN_NI04(struct nouveau_pushbuf * push,int subc,int mthd,unsigned size)134 BEGIN_NI04(struct nouveau_pushbuf *push, int subc, int mthd, unsigned size)
135 {
136 #ifndef NV50_PUSH_EXPLICIT_SPACE_CHECKING
137 PUSH_SPACE(push, size + 1);
138 #endif
139 PUSH_DATA (push, NV04_FIFO_PKHDR_NI(subc, mthd, size));
140 }
141
142 static inline int
BO_MAP(struct nouveau_screen * screen,struct nouveau_bo * bo,uint32_t access,struct nouveau_client * client)143 BO_MAP(struct nouveau_screen *screen, struct nouveau_bo *bo, uint32_t access, struct nouveau_client *client)
144 {
145 int res;
146 simple_mtx_lock(&screen->fence.lock);
147 res = nouveau_bo_map(bo, access, client);
148 simple_mtx_unlock(&screen->fence.lock);
149 return res;
150 }
151
152 static inline int
BO_WAIT(struct nouveau_screen * screen,struct nouveau_bo * bo,uint32_t access,struct nouveau_client * client)153 BO_WAIT(struct nouveau_screen *screen, struct nouveau_bo *bo, uint32_t access, struct nouveau_client *client)
154 {
155 int res;
156 simple_mtx_lock(&screen->fence.lock);
157 res = nouveau_bo_wait(bo, access, client);
158 simple_mtx_unlock(&screen->fence.lock);
159 return res;
160 }
161
162 #define NOUVEAU_RESOURCE_FLAG_LINEAR (PIPE_RESOURCE_FLAG_DRV_PRIV << 0)
163 #define NOUVEAU_RESOURCE_FLAG_DRV_PRIV (PIPE_RESOURCE_FLAG_DRV_PRIV << 1)
164
165 static inline uint32_t
nouveau_screen_transfer_flags(unsigned pipe)166 nouveau_screen_transfer_flags(unsigned pipe)
167 {
168 uint32_t flags = 0;
169
170 if (!(pipe & PIPE_MAP_UNSYNCHRONIZED)) {
171 if (pipe & PIPE_MAP_READ)
172 flags |= NOUVEAU_BO_RD;
173 if (pipe & PIPE_MAP_WRITE)
174 flags |= NOUVEAU_BO_WR;
175 if (pipe & PIPE_MAP_DONTBLOCK)
176 flags |= NOUVEAU_BO_NOBLOCK;
177 }
178
179 return flags;
180 }
181
182 extern struct nouveau_screen *
183 nv30_screen_create(struct nouveau_device *);
184
185 extern struct nouveau_screen *
186 nv50_screen_create(struct nouveau_device *);
187
188 extern struct nouveau_screen *
189 nvc0_screen_create(struct nouveau_device *);
190
191 static inline uint64_t
nouveau_device_get_global_mem_size(struct nouveau_device * dev)192 nouveau_device_get_global_mem_size(struct nouveau_device *dev)
193 {
194 uint64_t size = dev->vram_size;
195
196 if (!size) {
197 os_get_available_system_memory(&size);
198 size = MIN2(dev->gart_size, size);
199 }
200
201 /* cap to 32 bit on nv50 and older */
202 if (dev->chipset < 0xc0)
203 size = MIN2(size, 1ull << 32);
204 else
205 size = MIN2(size, 1ull << 40);
206
207 return size;
208 }
209
210 #endif
211