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 can only be called in the flush
41 ilo_cp_dump(struct ilo_cp
*cp
)
43 ilo_printf("dumping %d bytes\n", cp
->used
* 4);
45 intel_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
= intel_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 intel_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 ilo_cp_private are added to cp->size in
98 * ilo_cp_end_buffer().
100 cp
->size
= cp
->bo_size
- 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
)
135 intel_bo_unmap(cp
->bo
);
139 err
= intel_bo_pwrite(cp
->bo
, 0, cp
->used
* 4, cp
->ptr
);
140 if (likely(!err
&& cp
->stolen
)) {
141 const int offset
= cp
->bo_size
- cp
->stolen
;
143 err
= intel_bo_pwrite(cp
->bo
, offset
* 4,
144 cp
->stolen
* 4, &cp
->ptr
[offset
]);
151 * Reallocate the parser bo.
154 ilo_cp_realloc_bo(struct ilo_cp
*cp
)
159 * allocate the new bo before unreferencing the old one so that they
160 * won't point at the same address, which is needed for jmpbuf
162 bo
= intel_winsys_alloc_buffer(cp
->winsys
,
163 "batch buffer", cp
->bo_size
* 4, 0);
165 /* reuse the old one */
167 intel_bo_reference(bo
);
171 intel_bo_unreference(cp
->bo
);
175 intel_bo_map(cp
->bo
, true);
176 cp
->ptr
= intel_bo_get_virtual(cp
->bo
);
181 * Execute the parser bo.
184 ilo_cp_exec_bo(struct ilo_cp
*cp
)
186 const bool do_exec
= !(ilo_debug
& ILO_DEBUG_NOHW
);
187 struct intel_context
*ctx
;
192 case ILO_CP_RING_RENDER
:
193 ctx
= cp
->render_ctx
;
194 flags
= INTEL_EXEC_RENDER
;
196 case ILO_CP_RING_BLT
:
198 flags
= INTEL_EXEC_BLT
;
206 flags
|= cp
->one_off_flags
;
209 err
= intel_bo_exec(cp
->bo
, cp
->used
* 4, ctx
, flags
);
213 cp
->one_off_flags
= 0;
219 * Flush the command parser and execute the commands. When the parser buffer
220 * is empty, the callback is not invoked.
223 ilo_cp_flush(struct ilo_cp
*cp
)
227 ilo_cp_set_owner(cp
, NULL
, 0);
230 assert(cp
->bo_size
== cp
->size
+ cp
->stolen
+ ilo_cp_private
);
233 /* return the space stolen and etc. */
234 ilo_cp_clear_buffer(cp
);
239 ilo_cp_end_buffer(cp
);
241 /* upload and execute */
242 err
= ilo_cp_upload_buffer(cp
);
244 err
= ilo_cp_exec_bo(cp
);
246 if (likely(!err
&& cp
->flush_callback
))
247 cp
->flush_callback(cp
, cp
->flush_callback_data
);
249 ilo_cp_clear_buffer(cp
);
250 ilo_cp_realloc_bo(cp
);
254 * Destroy the command parser.
257 ilo_cp_destroy(struct ilo_cp
*cp
)
261 intel_bo_unmap(cp
->bo
);
263 intel_bo_unreference(cp
->bo
);
267 intel_winsys_destroy_context(cp
->winsys
, cp
->render_ctx
);
274 * Create a command parser.
277 ilo_cp_create(struct intel_winsys
*winsys
, bool direct_map
)
281 cp
= CALLOC_STRUCT(ilo_cp
);
286 cp
->render_ctx
= intel_winsys_create_context(winsys
);
288 cp
->ring
= ILO_CP_RING_RENDER
;
289 cp
->no_implicit_flush
= false;
294 cp
->sys
= MALLOC(cp
->bo_size
* 4);
303 ilo_cp_realloc_bo(cp
);
310 ilo_cp_clear_buffer(cp
);