ilo: move ring types to winsys
[mesa.git] / src / gallium / drivers / ilo / ilo_cp.c
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 <olv@lunarg.com>
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);
44 if (cp->used)
45 intel_winsys_decode_bo(cp->winsys, cp->bo, cp->used * 4);
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_truncate_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, INTEL_DOMAIN_CPU);
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 cp->ptr = intel_bo_map(cp->bo, true);
176 }
177
178 /**
179 * Execute the parser bo.
180 */
181 static int
182 ilo_cp_exec_bo(struct ilo_cp *cp)
183 {
184 const bool do_exec = !(ilo_debug & ILO_DEBUG_NOHW);
185 int err;
186
187 if (likely(do_exec)) {
188 err = intel_winsys_submit_bo(cp->winsys, cp->ring,
189 cp->bo, cp->used * 4, cp->render_ctx, cp->one_off_flags);
190 }
191 else {
192 err = 0;
193 }
194
195 cp->one_off_flags = 0;
196
197 return err;
198 }
199
200 /**
201 * Flush the command parser and execute the commands. When the parser buffer
202 * is empty, the callback is not invoked.
203 */
204 void
205 ilo_cp_flush_internal(struct ilo_cp *cp)
206 {
207 int err;
208
209 ilo_cp_set_owner(cp, NULL, 0);
210
211 /* sanity check */
212 assert(cp->bo_size == cp->size + cp->stolen + ilo_cp_private);
213
214 if (!cp->used) {
215 /* return the space stolen and etc. */
216 ilo_cp_clear_buffer(cp);
217
218 return;
219 }
220
221 ilo_cp_end_buffer(cp);
222
223 /* upload and execute */
224 err = ilo_cp_upload_buffer(cp);
225 if (likely(!err))
226 err = ilo_cp_exec_bo(cp);
227
228 if (likely(!err && cp->flush_callback))
229 cp->flush_callback(cp, cp->flush_callback_data);
230
231 ilo_cp_clear_buffer(cp);
232 ilo_cp_realloc_bo(cp);
233 }
234
235 /**
236 * Destroy the command parser.
237 */
238 void
239 ilo_cp_destroy(struct ilo_cp *cp)
240 {
241 if (cp->bo) {
242 if (!cp->sys)
243 intel_bo_unmap(cp->bo);
244
245 intel_bo_unreference(cp->bo);
246 }
247
248 if (cp->render_ctx)
249 intel_winsys_destroy_context(cp->winsys, cp->render_ctx);
250
251 FREE(cp->sys);
252 FREE(cp);
253 }
254
255 /**
256 * Create a command parser.
257 */
258 struct ilo_cp *
259 ilo_cp_create(struct intel_winsys *winsys, int size, bool direct_map)
260 {
261 struct ilo_cp *cp;
262
263 cp = CALLOC_STRUCT(ilo_cp);
264 if (!cp)
265 return NULL;
266
267 cp->winsys = winsys;
268 cp->render_ctx = intel_winsys_create_context(winsys);
269
270 cp->ring = INTEL_RING_RENDER;
271 cp->no_implicit_flush = false;
272
273 cp->bo_size = size;
274
275 if (!direct_map) {
276 cp->sys = MALLOC(cp->bo_size * 4);
277 if (!cp->sys) {
278 FREE(cp);
279 return NULL;
280 }
281
282 cp->ptr = cp->sys;
283 }
284
285 ilo_cp_realloc_bo(cp);
286 if (!cp->bo) {
287 FREE(cp->sys);
288 FREE(cp);
289 return NULL;
290 }
291
292 ilo_cp_clear_buffer(cp);
293
294 return cp;
295 }