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_builder.h"
34 #include "ilo_common.h"
38 typedef void (*ilo_cp_callback
)(struct ilo_cp
*cp
, void *data
);
41 ilo_cp_callback release_callback
;
49 struct intel_winsys
*winsys
;
50 struct intel_context
*render_ctx
;
52 ilo_cp_callback flush_callback
;
53 void *flush_callback_data
;
55 const struct ilo_cp_owner
*owner
;
58 enum intel_ring_type ring
;
59 bool no_implicit_flush
;
60 unsigned one_off_flags
;
62 struct ilo_builder builder
;
63 struct intel_bo
*last_submitted_bo
;
71 ilo_cp_create(const struct ilo_dev_info
*dev
, struct intel_winsys
*winsys
);
74 ilo_cp_destroy(struct ilo_cp
*cp
);
77 ilo_cp_flush_internal(struct ilo_cp
*cp
);
80 ilo_cp_flush(struct ilo_cp
*cp
, const char *reason
)
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
);
88 ilo_cp_flush_internal(cp
);
92 * Return true if the parser buffer is empty.
95 ilo_cp_empty(struct ilo_cp
*cp
)
97 return !ilo_builder_batch_used(&cp
->builder
);
101 * Return the remaining space (in dwords) in the parser buffer.
104 ilo_cp_space(struct ilo_cp
*cp
)
106 const int space
= ilo_builder_batch_space(&cp
->builder
);
107 const int mi_batch_buffer_end_space
= 2;
109 assert(space
>= cp
->owner_reserve
+ mi_batch_buffer_end_space
);
111 return space
- cp
->owner_reserve
- mi_batch_buffer_end_space
;
115 * Internal function called by functions that flush implicitly.
118 ilo_cp_implicit_flush(struct ilo_cp
*cp
)
120 if (cp
->no_implicit_flush
) {
121 assert(!"unexpected command parser flush");
122 ilo_builder_batch_discard(&cp
->builder
);
125 ilo_cp_flush(cp
, "out of space (implicit)");
129 * Set the ring buffer.
132 ilo_cp_set_ring(struct ilo_cp
*cp
, enum intel_ring_type ring
)
134 if (cp
->ring
!= ring
) {
135 ilo_cp_implicit_flush(cp
);
141 * Assert that no function should flush implicitly.
144 ilo_cp_assert_no_implicit_flush(struct ilo_cp
*cp
, bool enable
)
146 cp
->no_implicit_flush
= enable
;
150 * Set one-off flags. They will be cleared after flushing.
153 ilo_cp_set_one_off_flags(struct ilo_cp
*cp
, unsigned flags
)
155 cp
->one_off_flags
|= flags
;
159 * Set flush callback. The callback is invoked after the bo has been
160 * successfully executed, and before the bo is reallocated.
163 ilo_cp_set_flush_callback(struct ilo_cp
*cp
, ilo_cp_callback callback
,
166 cp
->flush_callback
= callback
;
167 cp
->flush_callback_data
= data
;
171 * Set the parser owner. If this is a new owner, the previous owner is
172 * notified and the space it reserved is reclaimed.
174 * \return true if this is a new owner
177 ilo_cp_set_owner(struct ilo_cp
*cp
, const struct ilo_cp_owner
*owner
,
180 const bool new_owner
= (cp
->owner
!= owner
);
182 /* release current owner */
183 if (new_owner
&& cp
->owner
) {
184 const bool no_implicit_flush
= cp
->no_implicit_flush
;
186 /* reclaim the reserved space */
187 cp
->owner_reserve
= 0;
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
;
197 if (cp
->owner_reserve
!= reserve
) {
198 const int extra
= reserve
- cp
->owner_reserve
;
200 if (ilo_cp_space(cp
) < extra
) {
201 ilo_cp_implicit_flush(cp
);
203 assert(ilo_cp_space(cp
) >= reserve
);
204 cp
->owner_reserve
= reserve
;
207 cp
->owner_reserve
+= extra
;
211 /* set owner last because of the possible flush above */
218 * Begin writing a command.
221 ilo_cp_begin(struct ilo_cp
*cp
, int cmd_size
)
223 if (ilo_cp_space(cp
) < cmd_size
) {
224 ilo_cp_implicit_flush(cp
);
225 assert(ilo_cp_space(cp
) >= cmd_size
);
228 cp
->pos
= ilo_builder_batch_pointer(&cp
->builder
, cmd_size
, &cp
->ptr
);
231 cp
->cmd_end
= cmd_size
;
235 * Begin writing data to a space stolen from the top of the parser buffer.
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
243 ilo_cp_steal(struct ilo_cp
*cp
, enum ilo_builder_item_type item
,
244 int data_size
, int align
, uint32_t *bo_offset
)
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);
255 cp
->pos
= ilo_builder_state_pointer(&cp
->builder
,
256 item
, align
<< 2, data_size
, &cp
->ptr
) >> 2;
259 cp
->cmd_end
= data_size
;
261 /* offset in cp->bo */
263 *bo_offset
= cp
->pos
<< 2;
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().
271 ilo_cp_write(struct ilo_cp
*cp
, uint32_t val
)
273 assert(cp
->cmd_cur
< cp
->cmd_end
);
274 cp
->ptr
[cp
->cmd_cur
++] = val
;
278 * Write multiple dwords to the parser buffer.
281 ilo_cp_write_multi(struct ilo_cp
*cp
, const void *vals
, int num_vals
)
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
;
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.
293 ilo_cp_write_bo(struct ilo_cp
*cp
, uint32_t val
,
294 struct intel_bo
*bo
, uint32_t flags
)
297 ilo_builder_batch_reloc(&cp
->builder
, cp
->pos
+ cp
->cmd_cur
,
307 * End a command. Every ilo_cp_begin() or ilo_cp_steal() must have a
308 * matching ilo_cp_end().
311 ilo_cp_end(struct ilo_cp
*cp
)
313 assert(cp
->cmd_cur
== cp
->cmd_end
);
317 * A variant of ilo_cp_steal() where the data are written via the returned
320 * \return ptr pointer where the data are written to. It is valid until any
321 * change is made to the parser.
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
)
329 ilo_cp_steal(cp
, item
, data_size
, align
, bo_offset
);
331 ptr
= &cp
->ptr
[cp
->cmd_cur
];
332 cp
->cmd_cur
= cp
->cmd_end
;
339 #endif /* ILO_CP_H */