2 * Mesa 3-D graphics library
4 * Copyright (C) 2012-2013 LunarG, Inc.
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:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
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.
25 * Chia-I Wu <olv@lunarg.com>
31 #include "intel_winsys.h"
33 #include "ilo_common.h"
44 typedef void (*ilo_cp_callback
)(struct ilo_cp
*cp
, void *data
);
47 ilo_cp_callback release_callback
;
55 struct intel_winsys
*winsys
;
56 struct intel_context
*render_ctx
;
58 ilo_cp_callback flush_callback
;
59 void *flush_callback_data
;
61 const struct ilo_cp_owner
*owner
;
64 enum ilo_cp_ring ring
;
65 bool no_implicit_flush
;
66 unsigned one_off_flags
;
73 int size
, used
, stolen
;
79 * Jump buffer to save command parser state for rewind.
81 struct ilo_cp_jmp_buf
{
83 int size
, used
, stolen
;
88 ilo_cp_create(struct intel_winsys
*winsys
, bool direct_map
);
91 ilo_cp_destroy(struct ilo_cp
*cp
);
94 ilo_cp_flush(struct ilo_cp
*cp
);
97 ilo_cp_dump(struct ilo_cp
*cp
);
100 ilo_cp_setjmp(struct ilo_cp
*cp
, struct ilo_cp_jmp_buf
*jmp
);
103 ilo_cp_longjmp(struct ilo_cp
*cp
, const struct ilo_cp_jmp_buf
*jmp
);
106 * Return true if the parser buffer is empty.
109 ilo_cp_empty(struct ilo_cp
*cp
)
115 * Return the remaining space (in dwords) in the parser buffer.
118 ilo_cp_space(struct ilo_cp
*cp
)
120 return cp
->size
- cp
->used
;
124 * Internal function called by functions that flush implicitly.
127 ilo_cp_implicit_flush(struct ilo_cp
*cp
)
129 if (cp
->no_implicit_flush
) {
130 assert(!"unexpected command parser flush");
131 /* discard the commands */
139 * Set the ring buffer.
142 ilo_cp_set_ring(struct ilo_cp
*cp
, enum ilo_cp_ring ring
)
144 if (cp
->ring
!= ring
) {
145 ilo_cp_implicit_flush(cp
);
151 * Assert that no function should flush implicitly.
154 ilo_cp_assert_no_implicit_flush(struct ilo_cp
*cp
, bool enable
)
156 cp
->no_implicit_flush
= enable
;
160 * Set one-off flags. They will be cleared after flushing.
163 ilo_cp_set_one_off_flags(struct ilo_cp
*cp
, unsigned flags
)
165 cp
->one_off_flags
|= flags
;
169 * Set flush callback. The callback is invoked after the bo has been
170 * successfully executed, and before the bo is reallocated.
173 ilo_cp_set_flush_callback(struct ilo_cp
*cp
, ilo_cp_callback callback
,
176 cp
->flush_callback
= callback
;
177 cp
->flush_callback_data
= data
;
181 * Set the parser owner. If this is a new owner, the previous owner is
182 * notified and the space it reserved is reclaimed.
184 * \return true if this is a new owner
187 ilo_cp_set_owner(struct ilo_cp
*cp
, const struct ilo_cp_owner
*owner
,
190 const bool new_owner
= (cp
->owner
!= owner
);
192 /* release current owner */
193 if (new_owner
&& cp
->owner
) {
194 const bool no_implicit_flush
= cp
->no_implicit_flush
;
196 /* reclaim the reserved space */
197 cp
->size
+= cp
->owner_reserve
;
198 cp
->owner_reserve
= 0;
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
;
208 if (cp
->owner_reserve
!= reserve
) {
209 const int extra
= reserve
- cp
->owner_reserve
;
211 if (cp
->used
> cp
->size
- extra
) {
212 ilo_cp_implicit_flush(cp
);
213 assert(cp
->used
<= cp
->size
- reserve
);
216 cp
->owner_reserve
= reserve
;
220 cp
->owner_reserve
+= extra
;
224 /* set owner last because of the possible flush above */
231 * Begin writing a command.
234 ilo_cp_begin(struct ilo_cp
*cp
, int cmd_size
)
236 if (cp
->used
+ cmd_size
> cp
->size
) {
237 ilo_cp_implicit_flush(cp
);
238 assert(cp
->used
+ cmd_size
<= cp
->size
);
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
;
248 * Begin writing data to a space stolen from the top of the parser buffer.
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
256 ilo_cp_steal(struct ilo_cp
*cp
, const char *desc
,
257 int data_size
, int align
, uint32_t *bo_offset
)
264 pad
= (cp
->bo_size
- cp
->stolen
- data_size
) % align
;
265 steal
= data_size
+ pad
;
267 /* flush if there is not enough space after stealing */
268 if (cp
->used
> cp
->size
- steal
) {
269 ilo_cp_implicit_flush(cp
);
271 pad
= (cp
->bo_size
- cp
->stolen
- data_size
) % align
;
272 steal
= data_size
+ steal
;
274 assert(cp
->used
<= cp
->size
- steal
);
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
;
284 /* offset in cp->bo */
286 *bo_offset
= cp
->cmd_cur
* 4;
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().
294 ilo_cp_write(struct ilo_cp
*cp
, uint32_t val
)
296 assert(cp
->cmd_cur
< cp
->cmd_end
);
297 cp
->ptr
[cp
->cmd_cur
++] = val
;
301 * Write multiple dwords to the parser buffer.
304 ilo_cp_write_multi(struct ilo_cp
*cp
, const void *vals
, int num_vals
)
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
;
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.
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
)
320 intel_bo_emit_reloc(cp
->bo
, cp
->cmd_cur
* 4,
321 bo
, val
, read_domains
, write_domain
);
323 ilo_cp_write(cp
, val
+ intel_bo_get_offset(bo
));
326 ilo_cp_write(cp
, val
);
331 * End a command. Every ilo_cp_begin() or ilo_cp_steal() must have a
332 * matching ilo_cp_end().
335 ilo_cp_end(struct ilo_cp
*cp
)
337 assert(cp
->cmd_cur
== cp
->cmd_end
);
341 * A variant of ilo_cp_steal() where the data are written via the returned
344 * \return ptr pointer where the data are written to. It is valid until any
345 * change is made to the parser.
348 ilo_cp_steal_ptr(struct ilo_cp
*cp
, const char *desc
,
349 int data_size
, int align
, uint32_t *bo_offset
)
353 ilo_cp_steal(cp
, desc
, data_size
, align
, bo_offset
);
355 ptr
= &cp
->ptr
[cp
->cmd_cur
];
356 cp
->cmd_cur
= cp
->cmd_end
;
363 #endif /* ILO_CP_H */