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_internal(struct ilo_cp
*cp
);
97 ilo_cp_flush(struct ilo_cp
*cp
, const char *reason
)
99 if (ilo_debug
& ILO_DEBUG_FLUSH
) {
100 ilo_printf("cp flushed for %s with %d+%d DWords (%.1f%%) because of %s\n",
101 (cp
->ring
== ILO_CP_RING_RENDER
) ? "render" : "blt",
102 cp
->used
, cp
->stolen
,
103 (float) (100 * (cp
->used
+ cp
->stolen
)) / cp
->bo_size
,
107 ilo_cp_flush_internal(cp
);
111 ilo_cp_dump(struct ilo_cp
*cp
);
114 ilo_cp_setjmp(struct ilo_cp
*cp
, struct ilo_cp_jmp_buf
*jmp
);
117 ilo_cp_longjmp(struct ilo_cp
*cp
, const struct ilo_cp_jmp_buf
*jmp
);
120 * Return true if the parser buffer is empty.
123 ilo_cp_empty(struct ilo_cp
*cp
)
129 * Return the remaining space (in dwords) in the parser buffer.
132 ilo_cp_space(struct ilo_cp
*cp
)
134 return cp
->size
- cp
->used
;
138 * Internal function called by functions that flush implicitly.
141 ilo_cp_implicit_flush(struct ilo_cp
*cp
)
143 if (cp
->no_implicit_flush
) {
144 assert(!"unexpected command parser flush");
145 /* discard the commands */
149 ilo_cp_flush(cp
, "out of space (implicit)");
153 * Set the ring buffer.
156 ilo_cp_set_ring(struct ilo_cp
*cp
, enum ilo_cp_ring ring
)
158 if (cp
->ring
!= ring
) {
159 ilo_cp_implicit_flush(cp
);
165 * Assert that no function should flush implicitly.
168 ilo_cp_assert_no_implicit_flush(struct ilo_cp
*cp
, bool enable
)
170 cp
->no_implicit_flush
= enable
;
174 * Set one-off flags. They will be cleared after flushing.
177 ilo_cp_set_one_off_flags(struct ilo_cp
*cp
, unsigned flags
)
179 cp
->one_off_flags
|= flags
;
183 * Set flush callback. The callback is invoked after the bo has been
184 * successfully executed, and before the bo is reallocated.
187 ilo_cp_set_flush_callback(struct ilo_cp
*cp
, ilo_cp_callback callback
,
190 cp
->flush_callback
= callback
;
191 cp
->flush_callback_data
= data
;
195 * Set the parser owner. If this is a new owner, the previous owner is
196 * notified and the space it reserved is reclaimed.
198 * \return true if this is a new owner
201 ilo_cp_set_owner(struct ilo_cp
*cp
, const struct ilo_cp_owner
*owner
,
204 const bool new_owner
= (cp
->owner
!= owner
);
206 /* release current owner */
207 if (new_owner
&& cp
->owner
) {
208 const bool no_implicit_flush
= cp
->no_implicit_flush
;
210 /* reclaim the reserved space */
211 cp
->size
+= cp
->owner_reserve
;
212 cp
->owner_reserve
= 0;
214 /* invoke the release callback */
215 cp
->no_implicit_flush
= true;
216 cp
->owner
->release_callback(cp
, cp
->owner
->release_data
);
217 cp
->no_implicit_flush
= no_implicit_flush
;
222 if (cp
->owner_reserve
!= reserve
) {
223 const int extra
= reserve
- cp
->owner_reserve
;
225 if (cp
->used
> cp
->size
- extra
) {
226 ilo_cp_implicit_flush(cp
);
227 assert(cp
->used
<= cp
->size
- reserve
);
230 cp
->owner_reserve
= reserve
;
234 cp
->owner_reserve
+= extra
;
238 /* set owner last because of the possible flush above */
245 * Begin writing a command.
248 ilo_cp_begin(struct ilo_cp
*cp
, int cmd_size
)
250 if (cp
->used
+ cmd_size
> cp
->size
) {
251 ilo_cp_implicit_flush(cp
);
252 assert(cp
->used
+ cmd_size
<= cp
->size
);
255 assert(cp
->cmd_cur
== cp
->cmd_end
);
256 cp
->cmd_cur
= cp
->used
;
257 cp
->cmd_end
= cp
->cmd_cur
+ cmd_size
;
258 cp
->used
= cp
->cmd_end
;
262 * Begin writing data to a space stolen from the top of the parser buffer.
264 * \param desc informative description of the data to be written
265 * \param data_size in dwords
266 * \param align in dwords
267 * \param bo_offset in bytes to the stolen space
270 ilo_cp_steal(struct ilo_cp
*cp
, const char *desc
,
271 int data_size
, int align
, uint32_t *bo_offset
)
278 pad
= (cp
->bo_size
- cp
->stolen
- data_size
) % align
;
279 steal
= data_size
+ pad
;
281 /* flush if there is not enough space after stealing */
282 if (cp
->used
> cp
->size
- steal
) {
283 ilo_cp_implicit_flush(cp
);
285 pad
= (cp
->bo_size
- cp
->stolen
- data_size
) % align
;
286 steal
= data_size
+ steal
;
288 assert(cp
->used
<= cp
->size
- steal
);
294 assert(cp
->cmd_cur
== cp
->cmd_end
);
295 cp
->cmd_cur
= cp
->bo_size
- cp
->stolen
;
296 cp
->cmd_end
= cp
->cmd_cur
+ data_size
;
298 /* offset in cp->bo */
300 *bo_offset
= cp
->cmd_cur
* 4;
304 * Write a dword to the parser buffer. This function must be enclosed by
305 * ilo_cp_begin()/ilo_cp_steal() and ilo_cp_end().
308 ilo_cp_write(struct ilo_cp
*cp
, uint32_t val
)
310 assert(cp
->cmd_cur
< cp
->cmd_end
);
311 cp
->ptr
[cp
->cmd_cur
++] = val
;
315 * Write multiple dwords to the parser buffer.
318 ilo_cp_write_multi(struct ilo_cp
*cp
, const void *vals
, int num_vals
)
320 assert(cp
->cmd_cur
+ num_vals
<= cp
->cmd_end
);
321 memcpy(cp
->ptr
+ cp
->cmd_cur
, vals
, num_vals
* 4);
322 cp
->cmd_cur
+= num_vals
;
326 * Write a bo to the parser buffer. In addition to writing the offset of the
327 * bo to the buffer, it also emits a relocation.
330 ilo_cp_write_bo(struct ilo_cp
*cp
, uint32_t val
, struct intel_bo
*bo
,
331 uint32_t read_domains
, uint32_t write_domain
)
333 uint64_t presumed_offset
;
336 intel_bo_add_reloc(cp
->bo
, cp
->cmd_cur
* 4, bo
, val
,
337 read_domains
, write_domain
, &presumed_offset
);
343 /* 32-bit addressing */
344 assert(presumed_offset
== (uint64_t) ((uint32_t) presumed_offset
));
346 ilo_cp_write(cp
, (uint32_t) presumed_offset
);
350 * End a command. Every ilo_cp_begin() or ilo_cp_steal() must have a
351 * matching ilo_cp_end().
354 ilo_cp_end(struct ilo_cp
*cp
)
356 assert(cp
->cmd_cur
== cp
->cmd_end
);
360 * A variant of ilo_cp_steal() where the data are written via the returned
363 * \return ptr pointer where the data are written to. It is valid until any
364 * change is made to the parser.
367 ilo_cp_steal_ptr(struct ilo_cp
*cp
, const char *desc
,
368 int data_size
, int align
, uint32_t *bo_offset
)
372 ilo_cp_steal(cp
, desc
, data_size
, align
, bo_offset
);
374 ptr
= &cp
->ptr
[cp
->cmd_cur
];
375 cp
->cmd_cur
= cp
->cmd_end
;
382 #endif /* ILO_CP_H */