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 "genhw/genhw.h"
29 #include "intel_winsys.h"
33 #define MI_NOOP GEN_MI_CMD(MI_NOOP)
34 #define MI_BATCH_BUFFER_END GEN_MI_CMD(MI_BATCH_BUFFER_END)
36 /* the size of the private space */
37 static const int ilo_cp_private
= 2;
40 * Dump the contents of the parser bo. This can only be called in the flush
44 ilo_cp_dump(struct ilo_cp
*cp
)
46 ilo_printf("dumping %d bytes\n", cp
->used
* 4);
48 intel_winsys_decode_bo(cp
->winsys
, cp
->bo
, cp
->used
* 4);
52 * Save the command parser state for rewind.
54 * Note that this cannot rewind a flush, and the caller must make sure
55 * that does not happend.
58 ilo_cp_setjmp(struct ilo_cp
*cp
, struct ilo_cp_jmp_buf
*jmp
)
60 jmp
->id
= pointer_to_intptr(cp
->bo
);
64 jmp
->stolen
= cp
->stolen
;
65 /* save reloc count to rewind ilo_cp_write_bo() */
66 jmp
->reloc_count
= intel_bo_get_reloc_count(cp
->bo
);
70 * Rewind to the saved state.
73 ilo_cp_longjmp(struct ilo_cp
*cp
, const struct ilo_cp_jmp_buf
*jmp
)
75 if (jmp
->id
!= pointer_to_intptr(cp
->bo
)) {
76 assert(!"invalid use of CP longjmp");
82 cp
->stolen
= jmp
->stolen
;
83 intel_bo_truncate_relocs(cp
->bo
, jmp
->reloc_count
);
87 * Clear the parser buffer.
90 ilo_cp_clear_buffer(struct ilo_cp
*cp
)
99 * Recalculate cp->size. This is needed not only because cp->stolen is
100 * reset above, but also that ilo_cp_private are added to cp->size in
101 * ilo_cp_end_buffer().
103 cp
->size
= cp
->bo_size
- ilo_cp_private
;
107 * Add MI_BATCH_BUFFER_END to the private space of the parser buffer.
110 ilo_cp_end_buffer(struct ilo_cp
*cp
)
112 /* make the private space available */
113 cp
->size
+= ilo_cp_private
;
115 assert(cp
->used
+ 2 <= cp
->size
);
117 cp
->ptr
[cp
->used
++] = MI_BATCH_BUFFER_END
;
120 * From the Sandy Bridge PRM, volume 1 part 1, page 107:
122 * "The batch buffer must be QWord aligned and a multiple of QWords in
126 cp
->ptr
[cp
->used
++] = MI_NOOP
;
130 * Upload the parser buffer to the bo.
133 ilo_cp_upload_buffer(struct ilo_cp
*cp
)
138 intel_bo_unmap(cp
->bo
);
142 err
= intel_bo_pwrite(cp
->bo
, 0, cp
->used
* 4, cp
->ptr
);
143 if (likely(!err
&& cp
->stolen
)) {
144 const int offset
= cp
->bo_size
- cp
->stolen
;
146 err
= intel_bo_pwrite(cp
->bo
, offset
* 4,
147 cp
->stolen
* 4, &cp
->ptr
[offset
]);
154 * Reallocate the parser bo.
157 ilo_cp_realloc_bo(struct ilo_cp
*cp
)
162 * allocate the new bo before unreferencing the old one so that they
163 * won't point at the same address, which is needed for jmpbuf
165 bo
= intel_winsys_alloc_buffer(cp
->winsys
,
166 "batch buffer", cp
->bo_size
* 4, INTEL_DOMAIN_CPU
);
168 /* reuse the old one */
170 intel_bo_reference(bo
);
174 intel_bo_unreference(cp
->bo
);
178 cp
->ptr
= intel_bo_map(cp
->bo
, true);
182 * Execute the parser bo.
185 ilo_cp_exec_bo(struct ilo_cp
*cp
)
187 const bool do_exec
= !(ilo_debug
& ILO_DEBUG_NOHW
);
190 if (likely(do_exec
)) {
191 err
= intel_winsys_submit_bo(cp
->winsys
, cp
->ring
,
192 cp
->bo
, cp
->used
* 4, cp
->render_ctx
, cp
->one_off_flags
);
198 cp
->one_off_flags
= 0;
204 * Flush the command parser and execute the commands. When the parser buffer
205 * is empty, the callback is not invoked.
208 ilo_cp_flush_internal(struct ilo_cp
*cp
)
212 ilo_cp_set_owner(cp
, NULL
, 0);
215 assert(cp
->bo_size
== cp
->size
+ cp
->stolen
+ ilo_cp_private
);
218 /* return the space stolen and etc. */
219 ilo_cp_clear_buffer(cp
);
224 ilo_cp_end_buffer(cp
);
226 /* upload and execute */
227 err
= ilo_cp_upload_buffer(cp
);
229 err
= ilo_cp_exec_bo(cp
);
231 if (likely(!err
&& cp
->flush_callback
))
232 cp
->flush_callback(cp
, cp
->flush_callback_data
);
234 ilo_cp_clear_buffer(cp
);
235 ilo_cp_realloc_bo(cp
);
239 * Destroy the command parser.
242 ilo_cp_destroy(struct ilo_cp
*cp
)
246 intel_bo_unmap(cp
->bo
);
248 intel_bo_unreference(cp
->bo
);
251 intel_winsys_destroy_context(cp
->winsys
, cp
->render_ctx
);
258 * Create a command parser.
261 ilo_cp_create(struct intel_winsys
*winsys
, int size
, bool direct_map
)
265 cp
= CALLOC_STRUCT(ilo_cp
);
270 cp
->render_ctx
= intel_winsys_create_context(winsys
);
271 if (!cp
->render_ctx
) {
276 cp
->ring
= INTEL_RING_RENDER
;
277 cp
->no_implicit_flush
= false;
282 cp
->sys
= MALLOC(cp
->bo_size
* 4);
291 ilo_cp_realloc_bo(cp
);
298 ilo_cp_clear_buffer(cp
);