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"
37 typedef void (*ilo_cp_callback
)(struct ilo_cp
*cp
, void *data
);
40 ilo_cp_callback release_callback
;
48 struct intel_winsys
*winsys
;
49 struct intel_context
*render_ctx
;
51 ilo_cp_callback flush_callback
;
52 void *flush_callback_data
;
54 const struct ilo_cp_owner
*owner
;
57 enum intel_ring_type ring
;
58 bool no_implicit_flush
;
59 unsigned one_off_flags
;
66 int size
, used
, stolen
;
72 * Jump buffer to save command parser state for rewind.
74 struct ilo_cp_jmp_buf
{
76 int size
, used
, stolen
;
81 ilo_cp_create(struct intel_winsys
*winsys
, int size
, bool direct_map
);
84 ilo_cp_destroy(struct ilo_cp
*cp
);
87 ilo_cp_flush_internal(struct ilo_cp
*cp
);
90 ilo_cp_flush(struct ilo_cp
*cp
, const char *reason
)
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",
96 (float) (100 * (cp
->used
+ cp
->stolen
)) / cp
->bo_size
,
100 ilo_cp_flush_internal(cp
);
104 ilo_cp_dump(struct ilo_cp
*cp
);
107 ilo_cp_setjmp(struct ilo_cp
*cp
, struct ilo_cp_jmp_buf
*jmp
);
110 ilo_cp_longjmp(struct ilo_cp
*cp
, const struct ilo_cp_jmp_buf
*jmp
);
113 * Return true if the parser buffer is empty.
116 ilo_cp_empty(struct ilo_cp
*cp
)
122 * Return the remaining space (in dwords) in the parser buffer.
125 ilo_cp_space(struct ilo_cp
*cp
)
127 return cp
->size
- cp
->used
;
131 * Internal function called by functions that flush implicitly.
134 ilo_cp_implicit_flush(struct ilo_cp
*cp
)
136 if (cp
->no_implicit_flush
) {
137 assert(!"unexpected command parser flush");
138 /* discard the commands */
142 ilo_cp_flush(cp
, "out of space (implicit)");
146 * Set the ring buffer.
149 ilo_cp_set_ring(struct ilo_cp
*cp
, enum intel_ring_type ring
)
151 if (cp
->ring
!= ring
) {
152 ilo_cp_implicit_flush(cp
);
158 * Assert that no function should flush implicitly.
161 ilo_cp_assert_no_implicit_flush(struct ilo_cp
*cp
, bool enable
)
163 cp
->no_implicit_flush
= enable
;
167 * Set one-off flags. They will be cleared after flushing.
170 ilo_cp_set_one_off_flags(struct ilo_cp
*cp
, unsigned flags
)
172 cp
->one_off_flags
|= flags
;
176 * Set flush callback. The callback is invoked after the bo has been
177 * successfully executed, and before the bo is reallocated.
180 ilo_cp_set_flush_callback(struct ilo_cp
*cp
, ilo_cp_callback callback
,
183 cp
->flush_callback
= callback
;
184 cp
->flush_callback_data
= data
;
188 * Set the parser owner. If this is a new owner, the previous owner is
189 * notified and the space it reserved is reclaimed.
191 * \return true if this is a new owner
194 ilo_cp_set_owner(struct ilo_cp
*cp
, const struct ilo_cp_owner
*owner
,
197 const bool new_owner
= (cp
->owner
!= owner
);
199 /* release current owner */
200 if (new_owner
&& cp
->owner
) {
201 const bool no_implicit_flush
= cp
->no_implicit_flush
;
203 /* reclaim the reserved space */
204 cp
->size
+= cp
->owner_reserve
;
205 cp
->owner_reserve
= 0;
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
;
215 if (cp
->owner_reserve
!= reserve
) {
216 const int extra
= reserve
- cp
->owner_reserve
;
218 if (cp
->used
> cp
->size
- extra
) {
219 ilo_cp_implicit_flush(cp
);
220 assert(cp
->used
<= cp
->size
- reserve
);
223 cp
->owner_reserve
= reserve
;
227 cp
->owner_reserve
+= extra
;
231 /* set owner last because of the possible flush above */
238 * Begin writing a command.
241 ilo_cp_begin(struct ilo_cp
*cp
, int cmd_size
)
243 if (cp
->used
+ cmd_size
> cp
->size
) {
244 ilo_cp_implicit_flush(cp
);
245 assert(cp
->used
+ cmd_size
<= cp
->size
);
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
;
255 * Begin writing data to a space stolen from the top of the parser buffer.
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
263 ilo_cp_steal(struct ilo_cp
*cp
, const char *desc
,
264 int data_size
, int align
, uint32_t *bo_offset
)
271 pad
= (cp
->bo_size
- cp
->stolen
- data_size
) % align
;
272 steal
= data_size
+ pad
;
274 /* flush if there is not enough space after stealing */
275 if (cp
->used
> cp
->size
- steal
) {
276 ilo_cp_implicit_flush(cp
);
278 pad
= (cp
->bo_size
- cp
->stolen
- data_size
) % align
;
279 steal
= data_size
+ steal
;
281 assert(cp
->used
<= cp
->size
- steal
);
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
;
291 /* offset in cp->bo */
293 *bo_offset
= cp
->cmd_cur
* 4;
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().
301 ilo_cp_write(struct ilo_cp
*cp
, uint32_t val
)
303 assert(cp
->cmd_cur
< cp
->cmd_end
);
304 cp
->ptr
[cp
->cmd_cur
++] = val
;
308 * Write multiple dwords to the parser buffer.
311 ilo_cp_write_multi(struct ilo_cp
*cp
, const void *vals
, int num_vals
)
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
;
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.
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
)
326 uint64_t presumed_offset
;
329 intel_bo_add_reloc(cp
->bo
, cp
->cmd_cur
* 4, bo
, val
,
330 read_domains
, write_domain
, &presumed_offset
);
336 /* 32-bit addressing */
337 assert(presumed_offset
== (uint64_t) ((uint32_t) presumed_offset
));
339 ilo_cp_write(cp
, (uint32_t) presumed_offset
);
343 * End a command. Every ilo_cp_begin() or ilo_cp_steal() must have a
344 * matching ilo_cp_end().
347 ilo_cp_end(struct ilo_cp
*cp
)
349 assert(cp
->cmd_cur
== cp
->cmd_end
);
353 * A variant of ilo_cp_steal() where the data are written via the returned
356 * \return ptr pointer where the data are written to. It is valid until any
357 * change is made to the parser.
360 ilo_cp_steal_ptr(struct ilo_cp
*cp
, const char *desc
,
361 int data_size
, int align
, uint32_t *bo_offset
)
365 ilo_cp_steal(cp
, desc
, data_size
, align
, bo_offset
);
367 ptr
= &cp
->ptr
[cp
->cmd_cur
];
368 cp
->cmd_cur
= cp
->cmd_end
;
375 #endif /* ILO_CP_H */