Rev 4358 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /* |
2 | * Mesa 3-D graphics library |
||
3 | * |
||
4 | * Copyright (C) 2012-2013 LunarG, Inc. |
||
5 | * |
||
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: |
||
12 | * |
||
13 | * The above copyright notice and this permission notice shall be included |
||
14 | * in all copies or substantial portions of the Software. |
||
15 | * |
||
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. |
||
23 | * |
||
24 | * Authors: |
||
25 | * Chia-I Wu |
||
26 | */ |
||
27 | |||
28 | #include "intel_reg.h" /* for MI_xxx */ |
||
29 | #include "intel_winsys.h" |
||
30 | |||
31 | #include "ilo_cp.h" |
||
32 | |||
33 | /* the size of the private space */ |
||
34 | static const int ilo_cp_private = 2; |
||
35 | |||
36 | /** |
||
37 | * Dump the contents of the parser bo. This can only be called in the flush |
||
38 | * callback. |
||
39 | */ |
||
40 | void |
||
41 | ilo_cp_dump(struct ilo_cp *cp) |
||
42 | { |
||
43 | ilo_printf("dumping %d bytes\n", cp->used * 4); |
||
5063 | serge | 44 | // if (cp->used) |
45 | // intel_winsys_decode_commands(cp->winsys, cp->bo, cp->used * 4); |
||
4358 | Serge | 46 | } |
47 | |||
48 | /** |
||
49 | * Save the command parser state for rewind. |
||
50 | * |
||
51 | * Note that this cannot rewind a flush, and the caller must make sure |
||
52 | * that does not happend. |
||
53 | */ |
||
54 | void |
||
55 | ilo_cp_setjmp(struct ilo_cp *cp, struct ilo_cp_jmp_buf *jmp) |
||
56 | { |
||
57 | jmp->id = pointer_to_intptr(cp->bo); |
||
58 | |||
59 | jmp->size = cp->size; |
||
60 | jmp->used = cp->used; |
||
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); |
||
64 | } |
||
65 | |||
66 | /** |
||
67 | * Rewind to the saved state. |
||
68 | */ |
||
69 | void |
||
70 | ilo_cp_longjmp(struct ilo_cp *cp, const struct ilo_cp_jmp_buf *jmp) |
||
71 | { |
||
72 | if (jmp->id != pointer_to_intptr(cp->bo)) { |
||
73 | assert(!"invalid use of CP longjmp"); |
||
74 | return; |
||
75 | } |
||
76 | |||
77 | cp->size = jmp->size; |
||
78 | cp->used = jmp->used; |
||
79 | cp->stolen = jmp->stolen; |
||
80 | intel_bo_clear_relocs(cp->bo, jmp->reloc_count); |
||
81 | } |
||
82 | |||
83 | /** |
||
84 | * Clear the parser buffer. |
||
85 | */ |
||
86 | static void |
||
87 | ilo_cp_clear_buffer(struct ilo_cp *cp) |
||
88 | { |
||
89 | cp->cmd_cur = 0; |
||
90 | cp->cmd_end = 0; |
||
91 | |||
92 | cp->used = 0; |
||
93 | cp->stolen = 0; |
||
94 | |||
95 | /* |
||
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(). |
||
99 | */ |
||
100 | cp->size = cp->bo_size - ilo_cp_private; |
||
101 | } |
||
102 | |||
103 | /** |
||
104 | * Add MI_BATCH_BUFFER_END to the private space of the parser buffer. |
||
105 | */ |
||
106 | static void |
||
107 | ilo_cp_end_buffer(struct ilo_cp *cp) |
||
108 | { |
||
109 | /* make the private space available */ |
||
110 | cp->size += ilo_cp_private; |
||
111 | |||
112 | assert(cp->used + 2 <= cp->size); |
||
113 | |||
114 | cp->ptr[cp->used++] = MI_BATCH_BUFFER_END; |
||
115 | |||
116 | /* |
||
117 | * From the Sandy Bridge PRM, volume 1 part 1, page 107: |
||
118 | * |
||
119 | * "The batch buffer must be QWord aligned and a multiple of QWords in |
||
120 | * length." |
||
121 | */ |
||
122 | if (cp->used & 1) |
||
123 | cp->ptr[cp->used++] = MI_NOOP; |
||
124 | } |
||
125 | |||
126 | /** |
||
127 | * Upload the parser buffer to the bo. |
||
128 | */ |
||
129 | static int |
||
130 | ilo_cp_upload_buffer(struct ilo_cp *cp) |
||
131 | { |
||
132 | int err; |
||
133 | |||
134 | if (!cp->sys) { |
||
135 | intel_bo_unmap(cp->bo); |
||
136 | return 0; |
||
137 | } |
||
138 | |||
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; |
||
142 | |||
143 | err = intel_bo_pwrite(cp->bo, offset * 4, |
||
144 | cp->stolen * 4, &cp->ptr[offset]); |
||
145 | } |
||
146 | |||
147 | return err; |
||
148 | } |
||
149 | |||
150 | /** |
||
151 | * Reallocate the parser bo. |
||
152 | */ |
||
153 | static void |
||
154 | ilo_cp_realloc_bo(struct ilo_cp *cp) |
||
155 | { |
||
156 | struct intel_bo *bo; |
||
157 | |||
158 | /* |
||
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 |
||
161 | */ |
||
162 | bo = intel_winsys_alloc_buffer(cp->winsys, |
||
163 | "batch buffer", cp->bo_size * 4, 0); |
||
164 | if (unlikely(!bo)) { |
||
165 | /* reuse the old one */ |
||
166 | bo = cp->bo; |
||
167 | intel_bo_reference(bo); |
||
168 | } |
||
169 | |||
170 | if (cp->bo) |
||
171 | intel_bo_unreference(cp->bo); |
||
172 | cp->bo = bo; |
||
173 | |||
174 | if (!cp->sys) { |
||
175 | intel_bo_map(cp->bo, true); |
||
176 | cp->ptr = intel_bo_get_virtual(cp->bo); |
||
177 | } |
||
178 | } |
||
179 | |||
180 | /** |
||
181 | * Execute the parser bo. |
||
182 | */ |
||
183 | static int |
||
184 | ilo_cp_exec_bo(struct ilo_cp *cp) |
||
185 | { |
||
186 | const bool do_exec = !(ilo_debug & ILO_DEBUG_NOHW); |
||
187 | struct intel_context *ctx; |
||
188 | unsigned long flags; |
||
189 | int err; |
||
190 | |||
191 | switch (cp->ring) { |
||
192 | case ILO_CP_RING_RENDER: |
||
193 | ctx = cp->render_ctx; |
||
194 | flags = INTEL_EXEC_RENDER; |
||
195 | break; |
||
196 | case ILO_CP_RING_BLT: |
||
197 | ctx = NULL; |
||
198 | flags = INTEL_EXEC_BLT; |
||
199 | break; |
||
200 | default: |
||
201 | ctx = NULL; |
||
202 | flags = 0; |
||
203 | break; |
||
204 | } |
||
205 | |||
206 | flags |= cp->one_off_flags; |
||
207 | |||
208 | if (likely(do_exec)) |
||
209 | err = intel_bo_exec(cp->bo, cp->used * 4, ctx, flags); |
||
210 | else |
||
211 | err = 0; |
||
212 | |||
213 | cp->one_off_flags = 0; |
||
214 | |||
215 | return err; |
||
216 | } |
||
217 | |||
218 | /** |
||
219 | * Flush the command parser and execute the commands. When the parser buffer |
||
220 | * is empty, the callback is not invoked. |
||
221 | */ |
||
222 | void |
||
223 | ilo_cp_flush(struct ilo_cp *cp) |
||
224 | { |
||
225 | int err; |
||
226 | |||
227 | ilo_cp_set_owner(cp, NULL, 0); |
||
228 | |||
229 | /* sanity check */ |
||
230 | assert(cp->bo_size == cp->size + cp->stolen + ilo_cp_private); |
||
231 | |||
232 | if (!cp->used) { |
||
233 | /* return the space stolen and etc. */ |
||
234 | ilo_cp_clear_buffer(cp); |
||
235 | |||
236 | return; |
||
237 | } |
||
238 | |||
239 | ilo_cp_end_buffer(cp); |
||
240 | |||
241 | /* upload and execute */ |
||
242 | err = ilo_cp_upload_buffer(cp); |
||
243 | if (likely(!err)) |
||
244 | err = ilo_cp_exec_bo(cp); |
||
245 | |||
246 | if (likely(!err && cp->flush_callback)) |
||
247 | cp->flush_callback(cp, cp->flush_callback_data); |
||
248 | |||
249 | ilo_cp_clear_buffer(cp); |
||
250 | ilo_cp_realloc_bo(cp); |
||
251 | } |
||
252 | |||
253 | /** |
||
254 | * Destroy the command parser. |
||
255 | */ |
||
256 | void |
||
257 | ilo_cp_destroy(struct ilo_cp *cp) |
||
258 | { |
||
259 | if (cp->bo) { |
||
260 | if (!cp->sys) |
||
261 | intel_bo_unmap(cp->bo); |
||
262 | |||
263 | intel_bo_unreference(cp->bo); |
||
264 | } |
||
265 | |||
266 | if (cp->render_ctx) |
||
267 | intel_winsys_destroy_context(cp->winsys, cp->render_ctx); |
||
268 | |||
269 | FREE(cp->sys); |
||
270 | FREE(cp); |
||
271 | } |
||
272 | |||
273 | /** |
||
274 | * Create a command parser. |
||
275 | */ |
||
276 | struct ilo_cp * |
||
277 | ilo_cp_create(struct intel_winsys *winsys, bool direct_map) |
||
278 | { |
||
279 | struct ilo_cp *cp; |
||
280 | |||
281 | cp = CALLOC_STRUCT(ilo_cp); |
||
282 | if (!cp) |
||
283 | return NULL; |
||
284 | |||
285 | cp->winsys = winsys; |
||
286 | cp->render_ctx = intel_winsys_create_context(winsys); |
||
287 | |||
288 | cp->ring = ILO_CP_RING_RENDER; |
||
289 | cp->no_implicit_flush = false; |
||
290 | |||
291 | cp->bo_size = 8192; |
||
292 | |||
293 | if (!direct_map) { |
||
294 | cp->sys = MALLOC(cp->bo_size * 4); |
||
295 | if (!cp->sys) { |
||
296 | FREE(cp); |
||
297 | return NULL; |
||
298 | } |
||
299 | |||
300 | cp->ptr = cp->sys; |
||
301 | } |
||
302 | |||
303 | ilo_cp_realloc_bo(cp); |
||
304 | if (!cp->bo) { |
||
305 | FREE(cp->sys); |
||
306 | FREE(cp); |
||
307 | return NULL; |
||
308 | } |
||
309 | |||
310 | ilo_cp_clear_buffer(cp); |
||
311 | |||
312 | return cp; |
||
313 | }=> |