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>
28 #include "intel_reg.h" /* for MI_xxx */
29 #include "intel_winsys.h"
33 /* the size of the private space */
34 static const int ilo_cp_private = 2;
37 * Dump the contents of the parser bo. This must be called in a post-flush
41 ilo_cp_dump(struct ilo_cp *cp)
43 ilo_printf("dumping %d bytes\n", cp->used * 4);
45 cp->winsys->decode_commands(cp->winsys, cp->bo, cp->used * 4);
49 * Save the command parser state for rewind.
51 * Note that this cannot rewind a flush, and the caller must make sure
52 * that does not happend.
55 ilo_cp_setjmp(struct ilo_cp *cp, struct ilo_cp_jmp_buf *jmp)
57 jmp->id = pointer_to_intptr(cp->bo);
61 jmp->stolen = cp->stolen;
62 /* save reloc count to rewind ilo_cp_write_bo() */
63 jmp->reloc_count = cp->bo->get_reloc_count(cp->bo);
67 * Rewind to the saved state.
70 ilo_cp_longjmp(struct ilo_cp *cp, const struct ilo_cp_jmp_buf *jmp)
72 if (jmp->id != pointer_to_intptr(cp->bo)) {
73 assert(!"invalid use of CP longjmp");
79 cp->stolen = jmp->stolen;
80 cp->bo->clear_relocs(cp->bo, jmp->reloc_count);
84 * Clear the parser buffer.
87 ilo_cp_clear_buffer(struct ilo_cp *cp)
96 * Recalculate cp->size. This is needed not only because cp->stolen is
97 * reset above, but also that we added cp->reserve_for_pre_flush and
98 * ilo_cp_private to cp->size in ilo_cp_flush().
100 cp->size = cp->bo_size - (cp->reserve_for_pre_flush + ilo_cp_private);
104 * Add MI_BATCH_BUFFER_END to the private space of the parser buffer.
107 ilo_cp_end_buffer(struct ilo_cp *cp)
109 /* make the private space available */
110 cp->size += ilo_cp_private;
112 assert(cp->used + 2 <= cp->size);
114 cp->ptr[cp->used++] = MI_BATCH_BUFFER_END;
117 * From the Sandy Bridge PRM, volume 1 part 1, page 107:
119 * "The batch buffer must be QWord aligned and a multiple of QWords in
123 cp->ptr[cp->used++] = MI_NOOP;
127 * Upload the parser buffer to the bo.
130 ilo_cp_upload_buffer(struct ilo_cp *cp)
134 err = cp->bo->pwrite(cp->bo, 0, cp->used * 4, cp->ptr);
135 if (likely(!err && cp->stolen)) {
136 const int offset = cp->bo_size - cp->stolen;
138 err = cp->bo->pwrite(cp->bo, offset * 4,
139 cp->stolen * 4, &cp->ptr[offset]);
146 * Reallocate the parser bo.
149 ilo_cp_realloc_bo(struct ilo_cp *cp)
154 * allocate the new bo before unreferencing the old one so that they
155 * won't point at the same address, which is needed for jmpbuf
157 bo = cp->winsys->alloc_buffer(cp->winsys,
158 "batch buffer", cp->bo_size * 4, 0);
163 cp->bo->unreference(cp->bo);
167 cp->bo->map(cp->bo, true);
168 cp->ptr = cp->bo->get_virtual(cp->bo);
173 * Execute the parser bo.
176 ilo_cp_exec_bo(struct ilo_cp *cp)
178 const bool do_exec = !(ilo_debug & ILO_DEBUG_NOHW);
183 case ILO_CP_RING_RENDER:
184 flags = INTEL_EXEC_RENDER;
186 case ILO_CP_RING_BLT:
187 flags = INTEL_EXEC_BLT;
195 err = cp->bo->exec(cp->bo, cp->used * 4, cp->hw_ctx, flags);
203 ilo_cp_call_hook(struct ilo_cp *cp, enum ilo_cp_hook hook)
205 const bool no_implicit_flush = cp->no_implicit_flush;
207 if (!cp->hooks[hook].func)
210 /* no implicit flush in hooks */
211 cp->no_implicit_flush = true;
212 cp->hooks[hook].func(cp, cp->hooks[hook].data);
214 cp->no_implicit_flush = no_implicit_flush;
218 * Flush the command parser and execute the commands. When the parser buffer
219 * is empty, the hooks are not invoked.
222 ilo_cp_flush(struct ilo_cp *cp)
227 assert(cp->bo_size == cp->size +
228 cp->reserve_for_pre_flush + ilo_cp_private + cp->stolen);
231 ilo_cp_clear_buffer(cp);
235 /* make the reserved space available temporarily */
236 cp->size += cp->reserve_for_pre_flush;
237 ilo_cp_call_hook(cp, ILO_CP_HOOK_PRE_FLUSH);
239 ilo_cp_end_buffer(cp);
242 err = ilo_cp_upload_buffer(cp);
244 err = ilo_cp_exec_bo(cp);
247 cp->bo->unmap(cp->bo);
248 err = ilo_cp_exec_bo(cp);
252 ilo_cp_call_hook(cp, ILO_CP_HOOK_POST_FLUSH);
253 ilo_cp_clear_buffer(cp);
256 /* reset first so that post-flush hook knows nothing was executed */
257 ilo_cp_clear_buffer(cp);
258 ilo_cp_call_hook(cp, ILO_CP_HOOK_POST_FLUSH);
261 ilo_cp_realloc_bo(cp);
262 ilo_cp_call_hook(cp, ILO_CP_HOOK_NEW_BATCH);
266 * Destroy the command parser.
269 ilo_cp_destroy(struct ilo_cp *cp)
272 cp->bo->unreference(cp->bo);
274 cp->winsys->destroy_context(cp->winsys, cp->hw_ctx);
281 * Create a command parser.
284 ilo_cp_create(struct intel_winsys *winsys, bool direct_map)
288 cp = CALLOC_STRUCT(ilo_cp);
293 cp->hw_ctx = winsys->create_context(winsys);
295 cp->ring = ILO_CP_RING_RENDER;
296 cp->no_implicit_flush = false;
297 cp->reserve_for_pre_flush = 0;
299 memset(cp->hooks, 0, sizeof(cp->hooks));
304 cp->sys = MALLOC(cp->bo_size * 4);
313 ilo_cp_realloc_bo(cp);
320 ilo_cp_clear_buffer(cp);