ilo: avoid brw_wm_barycentric_interp_mode in compiler
[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 typedef void (*ilo_cp_callback)(struct ilo_cp *cp, void *data);
38
39 struct ilo_cp_owner {
40 ilo_cp_callback release_callback;
41 void *release_data;
42 };
43
44 /**
45 * Command parser.
46 */
47 struct ilo_cp {
48 struct intel_winsys *winsys;
49 struct intel_context *render_ctx;
50
51 ilo_cp_callback flush_callback;
52 void *flush_callback_data;
53
54 const struct ilo_cp_owner *owner;
55 int owner_reserve;
56
57 enum intel_ring_type ring;
58 bool no_implicit_flush;
59 unsigned one_off_flags;
60
61 int bo_size;
62 struct intel_bo *bo;
63 uint32_t *sys;
64
65 uint32_t *ptr;
66 int size, used, stolen;
67
68 int cmd_cur, cmd_end;
69 };
70
71 /**
72 * Jump buffer to save command parser state for rewind.
73 */
74 struct ilo_cp_jmp_buf {
75 intptr_t id;
76 int size, used, stolen;
77 int reloc_count;
78 };
79
80 struct ilo_cp *
81 ilo_cp_create(struct intel_winsys *winsys, int size, bool direct_map);
82
83 void
84 ilo_cp_destroy(struct ilo_cp *cp);
85
86 void
87 ilo_cp_flush_internal(struct ilo_cp *cp);
88
89 static inline void
90 ilo_cp_flush(struct ilo_cp *cp, const char *reason)
91 {
92 if (ilo_debug & ILO_DEBUG_FLUSH) {
93 ilo_printf("cp flushed for %s with %d+%d DWords (%.1f%%) because of %s\n",
94 (cp->ring == INTEL_RING_RENDER) ? "render" : "other",
95 cp->used, cp->stolen,
96 (float) (100 * (cp->used + cp->stolen)) / cp->bo_size,
97 reason);
98 }
99
100 ilo_cp_flush_internal(cp);
101 }
102
103 void
104 ilo_cp_dump(struct ilo_cp *cp);
105
106 void
107 ilo_cp_setjmp(struct ilo_cp *cp, struct ilo_cp_jmp_buf *jmp);
108
109 void
110 ilo_cp_longjmp(struct ilo_cp *cp, const struct ilo_cp_jmp_buf *jmp);
111
112 /**
113 * Return true if the parser buffer is empty.
114 */
115 static inline bool
116 ilo_cp_empty(struct ilo_cp *cp)
117 {
118 return !cp->used;
119 }
120
121 /**
122 * Return the remaining space (in dwords) in the parser buffer.
123 */
124 static inline int
125 ilo_cp_space(struct ilo_cp *cp)
126 {
127 return cp->size - cp->used;
128 }
129
130 /**
131 * Internal function called by functions that flush implicitly.
132 */
133 static inline void
134 ilo_cp_implicit_flush(struct ilo_cp *cp)
135 {
136 if (cp->no_implicit_flush) {
137 assert(!"unexpected command parser flush");
138 /* discard the commands */
139 cp->used = 0;
140 }
141
142 ilo_cp_flush(cp, "out of space (implicit)");
143 }
144
145 /**
146 * Set the ring buffer.
147 */
148 static inline void
149 ilo_cp_set_ring(struct ilo_cp *cp, enum intel_ring_type ring)
150 {
151 if (cp->ring != ring) {
152 ilo_cp_implicit_flush(cp);
153 cp->ring = ring;
154 }
155 }
156
157 /**
158 * Assert that no function should flush implicitly.
159 */
160 static inline void
161 ilo_cp_assert_no_implicit_flush(struct ilo_cp *cp, bool enable)
162 {
163 cp->no_implicit_flush = enable;
164 }
165
166 /**
167 * Set one-off flags. They will be cleared after flushing.
168 */
169 static inline void
170 ilo_cp_set_one_off_flags(struct ilo_cp *cp, unsigned flags)
171 {
172 cp->one_off_flags |= flags;
173 }
174
175 /**
176 * Set flush callback. The callback is invoked after the bo has been
177 * successfully executed, and before the bo is reallocated.
178 */
179 static inline void
180 ilo_cp_set_flush_callback(struct ilo_cp *cp, ilo_cp_callback callback,
181 void *data)
182 {
183 cp->flush_callback = callback;
184 cp->flush_callback_data = data;
185 }
186
187 /**
188 * Set the parser owner. If this is a new owner, the previous owner is
189 * notified and the space it reserved is reclaimed.
190 *
191 * \return true if this is a new owner
192 */
193 static inline bool
194 ilo_cp_set_owner(struct ilo_cp *cp, const struct ilo_cp_owner *owner,
195 int reserve)
196 {
197 const bool new_owner = (cp->owner != owner);
198
199 /* release current owner */
200 if (new_owner && cp->owner) {
201 const bool no_implicit_flush = cp->no_implicit_flush;
202
203 /* reclaim the reserved space */
204 cp->size += cp->owner_reserve;
205 cp->owner_reserve = 0;
206
207 /* invoke the release callback */
208 cp->no_implicit_flush = true;
209 cp->owner->release_callback(cp, cp->owner->release_data);
210 cp->no_implicit_flush = no_implicit_flush;
211
212 cp->owner = NULL;
213 }
214
215 if (cp->owner_reserve != reserve) {
216 const int extra = reserve - cp->owner_reserve;
217
218 if (cp->used > cp->size - extra) {
219 ilo_cp_implicit_flush(cp);
220 assert(cp->used <= cp->size - reserve);
221
222 cp->size -= reserve;
223 cp->owner_reserve = reserve;
224 }
225 else {
226 cp->size -= extra;
227 cp->owner_reserve += extra;
228 }
229 }
230
231 /* set owner last because of the possible flush above */
232 cp->owner = owner;
233
234 return new_owner;
235 }
236
237 /**
238 * Begin writing a command.
239 */
240 static inline void
241 ilo_cp_begin(struct ilo_cp *cp, int cmd_size)
242 {
243 if (cp->used + cmd_size > cp->size) {
244 ilo_cp_implicit_flush(cp);
245 assert(cp->used + cmd_size <= cp->size);
246 }
247
248 assert(cp->cmd_cur == cp->cmd_end);
249 cp->cmd_cur = cp->used;
250 cp->cmd_end = cp->cmd_cur + cmd_size;
251 cp->used = cp->cmd_end;
252 }
253
254 /**
255 * Begin writing data to a space stolen from the top of the parser buffer.
256 *
257 * \param desc informative description of the data to be written
258 * \param data_size in dwords
259 * \param align in dwords
260 * \param bo_offset in bytes to the stolen space
261 */
262 static inline void
263 ilo_cp_steal(struct ilo_cp *cp, const char *desc,
264 int data_size, int align, uint32_t *bo_offset)
265 {
266 int pad, steal;
267
268 if (!align)
269 align = 1;
270
271 pad = (cp->bo_size - cp->stolen - data_size) % align;
272 steal = data_size + pad;
273
274 /* flush if there is not enough space after stealing */
275 if (cp->used > cp->size - steal) {
276 ilo_cp_implicit_flush(cp);
277
278 pad = (cp->bo_size - cp->stolen - data_size) % align;
279 steal = data_size + steal;
280
281 assert(cp->used <= cp->size - steal);
282 }
283
284 cp->size -= steal;
285 cp->stolen += steal;
286
287 assert(cp->cmd_cur == cp->cmd_end);
288 cp->cmd_cur = cp->bo_size - cp->stolen;
289 cp->cmd_end = cp->cmd_cur + data_size;
290
291 /* offset in cp->bo */
292 if (bo_offset)
293 *bo_offset = cp->cmd_cur * 4;
294 }
295
296 /**
297 * Write a dword to the parser buffer. This function must be enclosed by
298 * ilo_cp_begin()/ilo_cp_steal() and ilo_cp_end().
299 */
300 static inline void
301 ilo_cp_write(struct ilo_cp *cp, uint32_t val)
302 {
303 assert(cp->cmd_cur < cp->cmd_end);
304 cp->ptr[cp->cmd_cur++] = val;
305 }
306
307 /**
308 * Write multiple dwords to the parser buffer.
309 */
310 static inline void
311 ilo_cp_write_multi(struct ilo_cp *cp, const void *vals, int num_vals)
312 {
313 assert(cp->cmd_cur + num_vals <= cp->cmd_end);
314 memcpy(cp->ptr + cp->cmd_cur, vals, num_vals * 4);
315 cp->cmd_cur += num_vals;
316 }
317
318 /**
319 * Write a bo to the parser buffer. In addition to writing the offset of the
320 * bo to the buffer, it also emits a relocation.
321 */
322 static inline void
323 ilo_cp_write_bo(struct ilo_cp *cp, uint32_t val, struct intel_bo *bo,
324 uint32_t read_domains, uint32_t write_domain)
325 {
326 uint64_t presumed_offset;
327
328 if (bo) {
329 intel_bo_add_reloc(cp->bo, cp->cmd_cur * 4, bo, val,
330 read_domains, write_domain, &presumed_offset);
331 }
332 else {
333 presumed_offset = 0;
334 }
335
336 /* 32-bit addressing */
337 assert(presumed_offset == (uint64_t) ((uint32_t) presumed_offset));
338
339 ilo_cp_write(cp, (uint32_t) presumed_offset);
340 }
341
342 /**
343 * End a command. Every ilo_cp_begin() or ilo_cp_steal() must have a
344 * matching ilo_cp_end().
345 */
346 static inline void
347 ilo_cp_end(struct ilo_cp *cp)
348 {
349 assert(cp->cmd_cur == cp->cmd_end);
350 }
351
352 /**
353 * A variant of ilo_cp_steal() where the data are written via the returned
354 * pointer.
355 *
356 * \return ptr pointer where the data are written to. It is valid until any
357 * change is made to the parser.
358 */
359 static inline void *
360 ilo_cp_steal_ptr(struct ilo_cp *cp, const char *desc,
361 int data_size, int align, uint32_t *bo_offset)
362 {
363 void *ptr;
364
365 ilo_cp_steal(cp, desc, data_size, align, bo_offset);
366
367 ptr = &cp->ptr[cp->cmd_cur];
368 cp->cmd_cur = cp->cmd_end;
369
370 ilo_cp_end(cp);
371
372 return ptr;
373 }
374
375 #endif /* ILO_CP_H */