ilo: replace a boolean by bool
[mesa.git] / src / gallium / drivers / ilo / ilo_cp.h
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2012-2013 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
26 */
27
28 #ifndef ILO_CP_H
29 #define ILO_CP_H
30
31 #include "intel_winsys.h"
32
33 #include "ilo_common.h"
34
35 struct ilo_cp;
36
37 enum ilo_cp_ring {
38 ILO_CP_RING_RENDER,
39 ILO_CP_RING_BLT,
40
41 ILO_CP_RING_COUNT,
42 };
43
44 typedef void (*ilo_cp_callback)(struct ilo_cp *cp, void *data);
45
46 struct ilo_cp_owner {
47 ilo_cp_callback release_callback;
48 void *release_data;
49 };
50
51 /**
52 * Command parser.
53 */
54 struct ilo_cp {
55 struct intel_winsys *winsys;
56 struct intel_context *render_ctx;
57
58 ilo_cp_callback flush_callback;
59 void *flush_callback_data;
60
61 const struct ilo_cp_owner *owner;
62 int owner_reserve;
63
64 enum ilo_cp_ring ring;
65 bool no_implicit_flush;
66 unsigned one_off_flags;
67
68 int bo_size;
69 struct intel_bo *bo;
70 uint32_t *sys;
71
72 uint32_t *ptr;
73 int size, used, stolen;
74
75 int cmd_cur, cmd_end;
76 };
77
78 /**
79 * Jump buffer to save command parser state for rewind.
80 */
81 struct ilo_cp_jmp_buf {
82 intptr_t id;
83 int size, used, stolen;
84 int reloc_count;
85 };
86
87 struct ilo_cp *
88 ilo_cp_create(struct intel_winsys *winsys, bool direct_map);
89
90 void
91 ilo_cp_destroy(struct ilo_cp *cp);
92
93 void
94 ilo_cp_flush(struct ilo_cp *cp);
95
96 void
97 ilo_cp_dump(struct ilo_cp *cp);
98
99 void
100 ilo_cp_setjmp(struct ilo_cp *cp, struct ilo_cp_jmp_buf *jmp);
101
102 void
103 ilo_cp_longjmp(struct ilo_cp *cp, const struct ilo_cp_jmp_buf *jmp);
104
105 /**
106 * Return true if the parser buffer is empty.
107 */
108 static inline bool
109 ilo_cp_empty(struct ilo_cp *cp)
110 {
111 return !cp->used;
112 }
113
114 /**
115 * Return the remaining space (in dwords) in the parser buffer.
116 */
117 static inline int
118 ilo_cp_space(struct ilo_cp *cp)
119 {
120 return cp->size - cp->used;
121 }
122
123 /**
124 * Internal function called by functions that flush implicitly.
125 */
126 static inline void
127 ilo_cp_implicit_flush(struct ilo_cp *cp)
128 {
129 if (cp->no_implicit_flush) {
130 assert(!"unexpected command parser flush");
131 /* discard the commands */
132 cp->used = 0;
133 }
134
135 ilo_cp_flush(cp);
136 }
137
138 /**
139 * Set the ring buffer.
140 */
141 static inline void
142 ilo_cp_set_ring(struct ilo_cp *cp, enum ilo_cp_ring ring)
143 {
144 if (cp->ring != ring) {
145 ilo_cp_implicit_flush(cp);
146 cp->ring = ring;
147 }
148 }
149
150 /**
151 * Assert that no function should flush implicitly.
152 */
153 static inline void
154 ilo_cp_assert_no_implicit_flush(struct ilo_cp *cp, bool enable)
155 {
156 cp->no_implicit_flush = enable;
157 }
158
159 /**
160 * Set one-off flags. They will be cleared after flushing.
161 */
162 static inline void
163 ilo_cp_set_one_off_flags(struct ilo_cp *cp, unsigned flags)
164 {
165 cp->one_off_flags |= flags;
166 }
167
168 /**
169 * Set flush callback. The callback is invoked after the bo has been
170 * successfully executed, and before the bo is reallocated.
171 */
172 static inline void
173 ilo_cp_set_flush_callback(struct ilo_cp *cp, ilo_cp_callback callback,
174 void *data)
175 {
176 cp->flush_callback = callback;
177 cp->flush_callback_data = data;
178 }
179
180 /**
181 * Set the parser owner. If this is a new owner, the previous owner is
182 * notified and the space it reserved is reclaimed.
183 *
184 * \return true if this is a new owner
185 */
186 static inline bool
187 ilo_cp_set_owner(struct ilo_cp *cp, const struct ilo_cp_owner *owner,
188 int reserve)
189 {
190 const bool new_owner = (cp->owner != owner);
191
192 /* release current owner */
193 if (new_owner && cp->owner) {
194 const bool no_implicit_flush = cp->no_implicit_flush;
195
196 /* reclaim the reserved space */
197 cp->size += cp->owner_reserve;
198 cp->owner_reserve = 0;
199
200 /* invoke the release callback */
201 cp->no_implicit_flush = true;
202 cp->owner->release_callback(cp, cp->owner->release_data);
203 cp->no_implicit_flush = no_implicit_flush;
204
205 cp->owner = NULL;
206 }
207
208 if (cp->owner_reserve != reserve) {
209 const int extra = reserve - cp->owner_reserve;
210
211 if (cp->used > cp->size - extra) {
212 ilo_cp_implicit_flush(cp);
213 assert(cp->used <= cp->size - reserve);
214
215 cp->size -= reserve;
216 cp->owner_reserve = reserve;
217 }
218 else {
219 cp->size -= extra;
220 cp->owner_reserve += extra;
221 }
222 }
223
224 /* set owner last because of the possible flush above */
225 cp->owner = owner;
226
227 return new_owner;
228 }
229
230 /**
231 * Begin writing a command.
232 */
233 static inline void
234 ilo_cp_begin(struct ilo_cp *cp, int cmd_size)
235 {
236 if (cp->used + cmd_size > cp->size) {
237 ilo_cp_implicit_flush(cp);
238 assert(cp->used + cmd_size <= cp->size);
239 }
240
241 assert(cp->cmd_cur == cp->cmd_end);
242 cp->cmd_cur = cp->used;
243 cp->cmd_end = cp->cmd_cur + cmd_size;
244 cp->used = cp->cmd_end;
245 }
246
247 /**
248 * Begin writing data to a space stolen from the top of the parser buffer.
249 *
250 * \param desc informative description of the data to be written
251 * \param data_size in dwords
252 * \param align in dwords
253 * \param bo_offset in bytes to the stolen space
254 */
255 static inline void
256 ilo_cp_steal(struct ilo_cp *cp, const char *desc,
257 int data_size, int align, uint32_t *bo_offset)
258 {
259 int pad, steal;
260
261 if (!align)
262 align = 1;
263
264 pad = (cp->bo_size - cp->stolen - data_size) % align;
265 steal = data_size + pad;
266
267 /* flush if there is not enough space after stealing */
268 if (cp->used > cp->size - steal) {
269 ilo_cp_implicit_flush(cp);
270
271 pad = (cp->bo_size - cp->stolen - data_size) % align;
272 steal = data_size + steal;
273
274 assert(cp->used <= cp->size - steal);
275 }
276
277 cp->size -= steal;
278 cp->stolen += steal;
279
280 assert(cp->cmd_cur == cp->cmd_end);
281 cp->cmd_cur = cp->bo_size - cp->stolen;
282 cp->cmd_end = cp->cmd_cur + data_size;
283
284 /* offset in cp->bo */
285 if (bo_offset)
286 *bo_offset = cp->cmd_cur * 4;
287 }
288
289 /**
290 * Write a dword to the parser buffer. This function must be enclosed by
291 * ilo_cp_begin()/ilo_cp_steal() and ilo_cp_end().
292 */
293 static inline void
294 ilo_cp_write(struct ilo_cp *cp, uint32_t val)
295 {
296 assert(cp->cmd_cur < cp->cmd_end);
297 cp->ptr[cp->cmd_cur++] = val;
298 }
299
300 /**
301 * Write multiple dwords to the parser buffer.
302 */
303 static inline void
304 ilo_cp_write_multi(struct ilo_cp *cp, const void *vals, int num_vals)
305 {
306 assert(cp->cmd_cur + num_vals <= cp->cmd_end);
307 memcpy(cp->ptr + cp->cmd_cur, vals, num_vals * 4);
308 cp->cmd_cur += num_vals;
309 }
310
311 /**
312 * Write a bo to the parser buffer. In addition to writing the offset of the
313 * bo to the buffer, it also emits a relocation.
314 */
315 static inline void
316 ilo_cp_write_bo(struct ilo_cp *cp, uint32_t val, struct intel_bo *bo,
317 uint32_t read_domains, uint32_t write_domain)
318 {
319 if (bo) {
320 intel_bo_emit_reloc(cp->bo, cp->cmd_cur * 4,
321 bo, val, read_domains, write_domain);
322
323 ilo_cp_write(cp, val + intel_bo_get_offset(bo));
324 }
325 else {
326 ilo_cp_write(cp, val);
327 }
328 }
329
330 /**
331 * End a command. Every ilo_cp_begin() or ilo_cp_steal() must have a
332 * matching ilo_cp_end().
333 */
334 static inline void
335 ilo_cp_end(struct ilo_cp *cp)
336 {
337 assert(cp->cmd_cur == cp->cmd_end);
338 }
339
340 /**
341 * A variant of ilo_cp_steal() where the data are written via the returned
342 * pointer.
343 *
344 * \return ptr pointer where the data are written to. It is valid until any
345 * change is made to the parser.
346 */
347 static inline void *
348 ilo_cp_steal_ptr(struct ilo_cp *cp, const char *desc,
349 int data_size, int align, uint32_t *bo_offset)
350 {
351 void *ptr;
352
353 ilo_cp_steal(cp, desc, data_size, align, bo_offset);
354
355 ptr = &cp->ptr[cp->cmd_cur];
356 cp->cmd_cur = cp->cmd_end;
357
358 ilo_cp_end(cp);
359
360 return ptr;
361 }
362
363 #endif /* ILO_CP_H */