OSDN Git Service

ilo: unmap cp bo before destroying it
[android-x86/external-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       cp->winsys->decode_commands(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 = cp->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    cp->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       cp->bo->unmap(cp->bo);
136       return 0;
137    }
138
139    err = cp->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 = cp->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 = cp->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       bo->reference(bo);
168    }
169
170    if (cp->bo)
171       cp->bo->unreference(cp->bo);
172    cp->bo = bo;
173
174    if (!cp->sys) {
175       cp->bo->map(cp->bo, true);
176       cp->ptr = cp->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 = cp->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          cp->bo->unmap(cp->bo);
262
263       cp->bo->unreference(cp->bo);
264    }
265
266    if (cp->render_ctx)
267       cp->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 = 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 }