Subversion Repositories Kolibri OS

Rev

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
}