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