ilo: hook up pipe context blit functions
[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 enum ilo_cp_hook {
45 ILO_CP_HOOK_NEW_BATCH,
46 ILO_CP_HOOK_PRE_FLUSH,
47 ILO_CP_HOOK_POST_FLUSH,
48
49 ILO_CP_HOOK_COUNT,
50 };
51
52 typedef void (*ilo_cp_hook_func)(struct ilo_cp *cp, void *data);
53
54 /**
55 * Command parser.
56 */
57 struct ilo_cp {
58 struct intel_winsys *winsys;
59 struct intel_context *hw_ctx;
60
61 enum ilo_cp_ring ring;
62 bool no_implicit_flush;
63 int reserve_for_pre_flush;
64
65 struct {
66 ilo_cp_hook_func func;
67 void *data;
68 } hooks[ILO_CP_HOOK_COUNT];
69
70 int bo_size;
71 struct intel_bo *bo;
72 uint32_t *sys;
73
74 uint32_t *ptr;
75 int size, used, stolen;
76
77 int cmd_cur, cmd_end;
78 };
79
80 /**
81 * Jump buffer to save command parser state for rewind.
82 */
83 struct ilo_cp_jmp_buf {
84 intptr_t id;
85 int size, used, stolen;
86 int reloc_count;
87 };
88
89 struct ilo_cp *
90 ilo_cp_create(struct intel_winsys *winsys, bool direct_map);
91
92 void
93 ilo_cp_destroy(struct ilo_cp *cp);
94
95 void
96 ilo_cp_flush(struct ilo_cp *cp);
97
98 void
99 ilo_cp_dump(struct ilo_cp *cp);
100
101 void
102 ilo_cp_setjmp(struct ilo_cp *cp, struct ilo_cp_jmp_buf *jmp);
103
104 void
105 ilo_cp_longjmp(struct ilo_cp *cp, const struct ilo_cp_jmp_buf *jmp);
106
107 /**
108 * Return true if the parser buffer is empty.
109 */
110 static inline bool
111 ilo_cp_empty(struct ilo_cp *cp)
112 {
113 return !cp->used;
114 }
115
116 /**
117 * Return the remaining space (in dwords) in the parser buffer.
118 */
119 static inline int
120 ilo_cp_space(struct ilo_cp *cp)
121 {
122 return cp->size - cp->used;
123 }
124
125 /**
126 * Internal function called by functions that flush implicitly.
127 */
128 static inline void
129 ilo_cp_implicit_flush(struct ilo_cp *cp)
130 {
131 if (cp->no_implicit_flush) {
132 assert(!"unexpected command parser flush");
133 /* discard the commands */
134 cp->used = 0;
135 }
136
137 ilo_cp_flush(cp);
138 }
139
140 /**
141 * Set the ring buffer.
142 */
143 static inline void
144 ilo_cp_set_ring(struct ilo_cp *cp, enum ilo_cp_ring ring)
145 {
146 if (cp->ring != ring) {
147 ilo_cp_implicit_flush(cp);
148 cp->ring = ring;
149 }
150 }
151
152 /**
153 * Assert that no function should flush implicitly.
154 */
155 static inline void
156 ilo_cp_assert_no_implicit_flush(struct ilo_cp *cp, bool enable)
157 {
158 cp->no_implicit_flush = enable;
159 }
160
161 /**
162 * Reserve the given size of space from the parser buffer. The reserved space
163 * will be made available temporarily for the pre-flush hook.
164 *
165 * \param reserve size in dwords to reserve. It may be negative.
166 */
167 static inline void
168 ilo_cp_reserve_for_pre_flush(struct ilo_cp *cp, int reserve)
169 {
170 assert(cp->reserve_for_pre_flush + reserve >= 0);
171
172 if (cp->used > cp->size - reserve) {
173 ilo_cp_implicit_flush(cp);
174 assert(cp->used <= cp->size - reserve);
175 }
176
177 cp->size -= reserve;
178 cp->reserve_for_pre_flush += reserve;
179 }
180
181 /**
182 * Set a command parser hook.
183 */
184 static inline void
185 ilo_cp_set_hook(struct ilo_cp *cp, enum ilo_cp_hook hook,
186 ilo_cp_hook_func func, void *data)
187 {
188 cp->hooks[hook].func = func;
189 cp->hooks[hook].data = data;
190 }
191
192 /**
193 * Begin writing a command.
194 */
195 static inline void
196 ilo_cp_begin(struct ilo_cp *cp, int cmd_size)
197 {
198 if (cp->used + cmd_size > cp->size) {
199 ilo_cp_implicit_flush(cp);
200 assert(cp->used + cmd_size <= cp->size);
201 }
202
203 assert(cp->cmd_cur == cp->cmd_end);
204 cp->cmd_cur = cp->used;
205 cp->cmd_end = cp->cmd_cur + cmd_size;
206 cp->used = cp->cmd_end;
207 }
208
209 /**
210 * Begin writing data to a space stolen from the top of the parser buffer.
211 *
212 * \param desc informative description of the data to be written
213 * \param data_size in dwords
214 * \param align in dwords
215 * \param bo_offset in bytes to the stolen space
216 */
217 static inline void
218 ilo_cp_steal(struct ilo_cp *cp, const char *desc,
219 int data_size, int align, uint32_t *bo_offset)
220 {
221 int pad, steal;
222
223 if (!align)
224 align = 1;
225
226 pad = (cp->bo_size - cp->stolen - data_size) % align;
227 steal = data_size + pad;
228
229 /* flush if there is not enough space after stealing */
230 if (cp->used > cp->size - steal) {
231 ilo_cp_implicit_flush(cp);
232
233 pad = (cp->bo_size - cp->stolen - data_size) % align;
234 steal = data_size + steal;
235
236 assert(cp->used <= cp->size - steal);
237 }
238
239 cp->size -= steal;
240 cp->stolen += steal;
241
242 assert(cp->cmd_cur == cp->cmd_end);
243 cp->cmd_cur = cp->bo_size - cp->stolen;
244 cp->cmd_end = cp->cmd_cur + data_size;
245
246 /* offset in cp->bo */
247 if (bo_offset)
248 *bo_offset = cp->cmd_cur * 4;
249 }
250
251 /**
252 * Write a dword to the parser buffer. This function must be enclosed by
253 * ilo_cp_begin()/ilo_cp_steal() and ilo_cp_end().
254 */
255 static inline void
256 ilo_cp_write(struct ilo_cp *cp, uint32_t val)
257 {
258 assert(cp->cmd_cur < cp->cmd_end);
259 cp->ptr[cp->cmd_cur++] = val;
260 }
261
262 /**
263 * Write multiple dwords to the parser buffer.
264 */
265 static inline void
266 ilo_cp_write_multi(struct ilo_cp *cp, const void *vals, int num_vals)
267 {
268 assert(cp->cmd_cur + num_vals <= cp->cmd_end);
269 memcpy(cp->ptr + cp->cmd_cur, vals, num_vals * 4);
270 cp->cmd_cur += num_vals;
271 }
272
273 /**
274 * Write a bo to the parser buffer. In addition to writing the offset of the
275 * bo to the buffer, it also emits a relocation.
276 */
277 static inline void
278 ilo_cp_write_bo(struct ilo_cp *cp, uint32_t val, struct intel_bo *bo,
279 uint32_t read_domains, uint32_t write_domain)
280 {
281 if (bo) {
282 cp->bo->emit_reloc(cp->bo, cp->cmd_cur * 4,
283 bo, val, read_domains, write_domain);
284
285 ilo_cp_write(cp, val + bo->get_offset(bo));
286 }
287 else {
288 ilo_cp_write(cp, val);
289 }
290 }
291
292 /**
293 * End a command. Every ilo_cp_begin() or ilo_cp_steal() must have a
294 * matching ilo_cp_end().
295 */
296 static inline void
297 ilo_cp_end(struct ilo_cp *cp)
298 {
299 assert(cp->cmd_cur == cp->cmd_end);
300 }
301
302 /**
303 * A variant of ilo_cp_steal() where the data are written via the returned
304 * pointer.
305 *
306 * \return ptr pointer where the data are written to. It is valid until any
307 * change is made to the parser.
308 */
309 static inline void *
310 ilo_cp_steal_ptr(struct ilo_cp *cp, const char *desc,
311 int data_size, int align, uint32_t *bo_offset)
312 {
313 void *ptr;
314
315 ilo_cp_steal(cp, desc, data_size, align, bo_offset);
316
317 ptr = &cp->ptr[cp->cmd_cur];
318 cp->cmd_cur = cp->cmd_end;
319
320 ilo_cp_end(cp);
321
322 return ptr;
323 }
324
325 #endif /* ILO_CP_H */