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 |
||
29 | #include |
||
30 | #ifndef ETIME |
||
31 | #define ETIME ETIMEDOUT |
||
32 | #endif |
||
33 | |||
34 | #include |
||
35 | #include |
||
36 | #include |
||
37 | |||
38 | #include "state_tracker/drm_driver.h" |
||
39 | #include "pipe/p_state.h" |
||
40 | #include "util/u_inlines.h" |
||
41 | #include "util/u_memory.h" |
||
42 | #include "util/u_debug.h" |
||
43 | #include "../intel_winsys.h" |
||
44 | |||
45 | #define BATCH_SZ (8192 * sizeof(uint32_t)) |
||
46 | |||
47 | struct intel_winsys { |
||
48 | int fd; |
||
49 | drm_intel_bufmgr *bufmgr; |
||
50 | struct intel_winsys_info info; |
||
51 | |||
52 | struct drm_intel_decode *decode; |
||
53 | }; |
||
54 | |||
55 | static bool |
||
56 | get_param(struct intel_winsys *winsys, int param, int *value) |
||
57 | { |
||
58 | struct drm_i915_getparam gp; |
||
59 | int err; |
||
60 | |||
61 | *value = 0; |
||
62 | |||
63 | memset(&gp, 0, sizeof(gp)); |
||
64 | gp.param = param; |
||
65 | gp.value = value; |
||
66 | |||
5063 | serge | 67 | err = drmIoctl(winsys->fd, DRM_I915_GETPARAM, &gp); |
68 | |||
4358 | Serge | 69 | if (err) { |
70 | *value = 0; |
||
71 | return false; |
||
72 | } |
||
73 | |||
74 | return true; |
||
75 | } |
||
76 | |||
77 | static bool |
||
78 | test_address_swizzling(struct intel_winsys *winsys) |
||
79 | { |
||
80 | drm_intel_bo *bo; |
||
81 | uint32_t tiling = I915_TILING_X, swizzle; |
||
82 | unsigned long pitch; |
||
83 | |||
84 | bo = drm_intel_bo_alloc_tiled(winsys->bufmgr, |
||
85 | "address swizzling test", 64, 64, 4, &tiling, &pitch, 0); |
||
86 | if (bo) { |
||
87 | drm_intel_bo_get_tiling(bo, &tiling, &swizzle); |
||
88 | drm_intel_bo_unreference(bo); |
||
89 | } |
||
90 | else { |
||
91 | swizzle = I915_BIT_6_SWIZZLE_NONE; |
||
92 | } |
||
93 | |||
94 | return (swizzle != I915_BIT_6_SWIZZLE_NONE); |
||
95 | } |
||
96 | |||
97 | static bool |
||
98 | init_info(struct intel_winsys *winsys) |
||
99 | { |
||
100 | struct intel_winsys_info *info = &winsys->info; |
||
101 | int val; |
||
102 | |||
103 | /* follow the classic driver here */ |
||
104 | get_param(winsys, I915_PARAM_HAS_RELAXED_DELTA, &val); |
||
105 | if (!val) { |
||
106 | debug_error("kernel 2.6.39 required"); |
||
107 | return false; |
||
108 | } |
||
109 | |||
110 | info->devid = drm_intel_bufmgr_gem_get_devid(winsys->bufmgr); |
||
111 | |||
112 | get_param(winsys, I915_PARAM_HAS_LLC, &val); |
||
113 | info->has_llc = val; |
||
114 | |||
115 | get_param(winsys, I915_PARAM_HAS_GEN7_SOL_RESET, &val); |
||
116 | info->has_gen7_sol_reset = val; |
||
117 | |||
118 | info->has_address_swizzling = test_address_swizzling(winsys); |
||
119 | |||
120 | return true; |
||
121 | } |
||
122 | |||
123 | struct intel_winsys * |
||
124 | intel_winsys_create_for_fd(int fd) |
||
125 | { |
||
126 | struct intel_winsys *winsys; |
||
127 | |||
128 | winsys = CALLOC_STRUCT(intel_winsys); |
||
129 | if (!winsys) |
||
130 | return NULL; |
||
131 | |||
132 | winsys->fd = fd; |
||
133 | |||
134 | winsys->bufmgr = drm_intel_bufmgr_gem_init(winsys->fd, BATCH_SZ); |
||
135 | if (!winsys->bufmgr) { |
||
136 | debug_error("failed to create GEM buffer manager"); |
||
137 | FREE(winsys); |
||
138 | return NULL; |
||
139 | } |
||
140 | |||
141 | if (!init_info(winsys)) { |
||
142 | drm_intel_bufmgr_destroy(winsys->bufmgr); |
||
143 | FREE(winsys); |
||
144 | return NULL; |
||
145 | } |
||
146 | |||
147 | drm_intel_bufmgr_gem_enable_fenced_relocs(winsys->bufmgr); |
||
148 | |||
149 | return winsys; |
||
150 | } |
||
151 | |||
152 | void |
||
153 | intel_winsys_destroy(struct intel_winsys *winsys) |
||
154 | { |
||
5063 | serge | 155 | // if (winsys->decode) |
156 | // drm_intel_decode_context_free(winsys->decode); |
||
4358 | Serge | 157 | |
158 | drm_intel_bufmgr_destroy(winsys->bufmgr); |
||
159 | FREE(winsys); |
||
160 | } |
||
161 | |||
162 | const struct intel_winsys_info * |
||
163 | intel_winsys_get_info(const struct intel_winsys *winsys) |
||
164 | { |
||
165 | return &winsys->info; |
||
166 | } |
||
167 | |||
168 | void |
||
169 | intel_winsys_enable_reuse(struct intel_winsys *winsys) |
||
170 | { |
||
171 | drm_intel_bufmgr_gem_enable_reuse(winsys->bufmgr); |
||
172 | } |
||
173 | |||
174 | struct intel_context * |
||
175 | intel_winsys_create_context(struct intel_winsys *winsys) |
||
176 | { |
||
177 | return (struct intel_context *) |
||
178 | drm_intel_gem_context_create(winsys->bufmgr); |
||
179 | } |
||
180 | |||
181 | void |
||
182 | intel_winsys_destroy_context(struct intel_winsys *winsys, |
||
183 | struct intel_context *ctx) |
||
184 | { |
||
185 | drm_intel_gem_context_destroy((drm_intel_context *) ctx); |
||
186 | } |
||
187 | |||
188 | int |
||
189 | intel_winsys_read_reg(struct intel_winsys *winsys, |
||
190 | uint32_t reg, uint64_t *val) |
||
191 | { |
||
192 | return drm_intel_reg_read(winsys->bufmgr, reg, val); |
||
193 | } |
||
194 | |||
195 | struct intel_bo * |
||
196 | intel_winsys_alloc_buffer(struct intel_winsys *winsys, |
||
197 | const char *name, |
||
198 | unsigned long size, |
||
199 | unsigned long flags) |
||
200 | { |
||
201 | const int alignment = 4096; /* always page-aligned */ |
||
202 | drm_intel_bo *bo; |
||
203 | |||
204 | if (flags == INTEL_ALLOC_FOR_RENDER) { |
||
205 | bo = drm_intel_bo_alloc_for_render(winsys->bufmgr, |
||
206 | name, size, alignment); |
||
207 | } |
||
208 | else { |
||
209 | assert(!flags); |
||
210 | bo = drm_intel_bo_alloc(winsys->bufmgr, name, size, alignment); |
||
211 | } |
||
212 | |||
213 | return (struct intel_bo *) bo; |
||
214 | } |
||
215 | |||
216 | struct intel_bo * |
||
217 | intel_winsys_alloc_texture(struct intel_winsys *winsys, |
||
218 | const char *name, |
||
219 | int width, int height, int cpp, |
||
220 | enum intel_tiling_mode tiling, |
||
221 | unsigned long flags, |
||
222 | unsigned long *pitch) |
||
223 | { |
||
224 | uint32_t real_tiling = tiling; |
||
225 | drm_intel_bo *bo; |
||
226 | |||
227 | bo = drm_intel_bo_alloc_tiled(winsys->bufmgr, name, |
||
228 | width, height, cpp, &real_tiling, pitch, flags); |
||
229 | if (!bo) |
||
230 | return NULL; |
||
231 | |||
232 | if (real_tiling != tiling) { |
||
233 | assert(!"tiling mismatch"); |
||
234 | drm_intel_bo_unreference(bo); |
||
235 | return NULL; |
||
236 | } |
||
237 | |||
238 | return (struct intel_bo *) bo; |
||
239 | } |
||
240 | |||
241 | struct intel_bo * |
||
242 | intel_winsys_import_handle(struct intel_winsys *winsys, |
||
243 | const char *name, |
||
244 | const struct winsys_handle *handle, |
||
245 | int width, int height, int cpp, |
||
246 | enum intel_tiling_mode *tiling, |
||
247 | unsigned long *pitch) |
||
248 | { |
||
249 | uint32_t real_tiling, swizzle; |
||
250 | drm_intel_bo *bo; |
||
251 | int err; |
||
252 | |||
253 | switch (handle->type) { |
||
254 | case DRM_API_HANDLE_TYPE_SHARED: |
||
255 | { |
||
256 | const uint32_t gem_name = handle->handle; |
||
257 | bo = drm_intel_bo_gem_create_from_name(winsys->bufmgr, |
||
258 | name, gem_name); |
||
259 | } |
||
260 | break; |
||
261 | #if 0 |
||
262 | case DRM_API_HANDLE_TYPE_FD: |
||
263 | { |
||
264 | const int fd = (int) handle->handle; |
||
265 | bo = drm_intel_bo_gem_create_from_prime(winsys->bufmgr, |
||
266 | fd, height * handle->stride); |
||
267 | } |
||
268 | break; |
||
269 | #endif |
||
270 | default: |
||
271 | bo = NULL; |
||
272 | break; |
||
273 | } |
||
274 | |||
275 | if (!bo) |
||
276 | return NULL; |
||
277 | |||
278 | err = drm_intel_bo_get_tiling(bo, &real_tiling, &swizzle); |
||
279 | if (err) { |
||
280 | drm_intel_bo_unreference(bo); |
||
281 | return NULL; |
||
282 | } |
||
283 | |||
284 | *tiling = real_tiling; |
||
285 | *pitch = handle->stride; |
||
286 | |||
287 | return (struct intel_bo *) bo; |
||
288 | } |
||
289 | |||
290 | int |
||
291 | intel_winsys_export_handle(struct intel_winsys *winsys, |
||
292 | struct intel_bo *bo, |
||
293 | enum intel_tiling_mode tiling, |
||
294 | unsigned long pitch, |
||
295 | struct winsys_handle *handle) |
||
296 | { |
||
297 | int err = 0; |
||
298 | |||
299 | switch (handle->type) { |
||
300 | case DRM_API_HANDLE_TYPE_SHARED: |
||
301 | { |
||
302 | uint32_t name; |
||
303 | |||
304 | err = drm_intel_bo_flink((drm_intel_bo *) bo, &name); |
||
305 | if (!err) |
||
306 | handle->handle = name; |
||
307 | } |
||
308 | break; |
||
309 | case DRM_API_HANDLE_TYPE_KMS: |
||
310 | handle->handle = ((drm_intel_bo *) bo)->handle; |
||
311 | break; |
||
312 | #if 0 |
||
313 | case DRM_API_HANDLE_TYPE_FD: |
||
314 | { |
||
315 | int fd; |
||
316 | |||
317 | err = drm_intel_bo_gem_export_to_prime((drm_intel_bo *) bo, &fd); |
||
318 | if (!err) |
||
319 | handle->handle = fd; |
||
320 | } |
||
321 | break; |
||
322 | #endif |
||
323 | default: |
||
324 | err = -EINVAL; |
||
325 | break; |
||
326 | } |
||
327 | |||
328 | if (err) |
||
329 | return err; |
||
330 | |||
331 | handle->stride = pitch; |
||
332 | |||
333 | return 0; |
||
334 | } |
||
335 | |||
336 | int |
||
337 | intel_winsys_check_aperture_space(struct intel_winsys *winsys, |
||
338 | struct intel_bo **bo_array, |
||
339 | int count) |
||
340 | { |
||
341 | return drm_intel_bufmgr_check_aperture_space((drm_intel_bo **) bo_array, |
||
342 | count); |
||
343 | } |
||
344 | |||
5063 | serge | 345 | #if 0 |
4358 | Serge | 346 | void |
347 | intel_winsys_decode_commands(struct intel_winsys *winsys, |
||
348 | struct intel_bo *bo, int used) |
||
349 | { |
||
350 | int err; |
||
351 | |||
352 | if (!winsys->decode) { |
||
353 | winsys->decode = drm_intel_decode_context_alloc(winsys->info.devid); |
||
354 | if (!winsys->decode) |
||
355 | return; |
||
356 | |||
357 | /* debug_printf()/debug_error() uses stderr by default */ |
||
358 | drm_intel_decode_set_output_file(winsys->decode, stderr); |
||
359 | } |
||
360 | |||
361 | err = intel_bo_map(bo, false); |
||
362 | if (err) { |
||
363 | debug_printf("failed to map buffer for decoding\n"); |
||
364 | return; |
||
365 | } |
||
366 | |||
367 | /* in dwords */ |
||
368 | used /= 4; |
||
369 | |||
370 | drm_intel_decode_set_batch_pointer(winsys->decode, |
||
371 | intel_bo_get_virtual(bo), intel_bo_get_offset(bo), used); |
||
372 | |||
373 | drm_intel_decode(winsys->decode); |
||
374 | |||
375 | intel_bo_unmap(bo); |
||
376 | } |
||
5063 | serge | 377 | #endif |
4358 | Serge | 378 | |
379 | void |
||
380 | intel_bo_reference(struct intel_bo *bo) |
||
381 | { |
||
382 | drm_intel_bo_reference((drm_intel_bo *) bo); |
||
383 | } |
||
384 | |||
385 | void |
||
386 | intel_bo_unreference(struct intel_bo *bo) |
||
387 | { |
||
388 | drm_intel_bo_unreference((drm_intel_bo *) bo); |
||
389 | } |
||
390 | |||
391 | unsigned long |
||
392 | intel_bo_get_size(const struct intel_bo *bo) |
||
393 | { |
||
394 | return ((drm_intel_bo *) bo)->size; |
||
395 | } |
||
396 | |||
397 | unsigned long |
||
398 | intel_bo_get_offset(const struct intel_bo *bo) |
||
399 | { |
||
400 | return ((drm_intel_bo *) bo)->offset; |
||
401 | } |
||
402 | |||
403 | void * |
||
404 | intel_bo_get_virtual(const struct intel_bo *bo) |
||
405 | { |
||
406 | return ((drm_intel_bo *) bo)->virtual; |
||
407 | } |
||
408 | |||
409 | int |
||
410 | intel_bo_map(struct intel_bo *bo, bool write_enable) |
||
411 | { |
||
412 | return drm_intel_bo_map((drm_intel_bo *) bo, write_enable); |
||
413 | } |
||
414 | |||
415 | int |
||
416 | intel_bo_map_gtt(struct intel_bo *bo) |
||
417 | { |
||
418 | return drm_intel_gem_bo_map_gtt((drm_intel_bo *) bo); |
||
419 | } |
||
420 | |||
421 | int |
||
422 | intel_bo_map_unsynchronized(struct intel_bo *bo) |
||
423 | { |
||
424 | return drm_intel_gem_bo_map_unsynchronized((drm_intel_bo *) bo); |
||
425 | } |
||
426 | |||
427 | void |
||
428 | intel_bo_unmap(struct intel_bo *bo) |
||
429 | { |
||
430 | int err; |
||
431 | |||
432 | err = drm_intel_bo_unmap((drm_intel_bo *) bo); |
||
433 | assert(!err); |
||
434 | } |
||
435 | |||
436 | int |
||
437 | intel_bo_pwrite(struct intel_bo *bo, unsigned long offset, |
||
438 | unsigned long size, const void *data) |
||
439 | { |
||
440 | return drm_intel_bo_subdata((drm_intel_bo *) bo, offset, size, data); |
||
441 | } |
||
442 | |||
443 | int |
||
444 | intel_bo_pread(struct intel_bo *bo, unsigned long offset, |
||
445 | unsigned long size, void *data) |
||
446 | { |
||
447 | return drm_intel_bo_get_subdata((drm_intel_bo *) bo, offset, size, data); |
||
448 | } |
||
449 | |||
450 | int |
||
451 | intel_bo_emit_reloc(struct intel_bo *bo, uint32_t offset, |
||
452 | struct intel_bo *target_bo, uint32_t target_offset, |
||
453 | uint32_t read_domains, uint32_t write_domain) |
||
454 | { |
||
455 | return drm_intel_bo_emit_reloc((drm_intel_bo *) bo, offset, |
||
456 | (drm_intel_bo *) target_bo, target_offset, |
||
457 | read_domains, write_domain); |
||
458 | } |
||
459 | |||
460 | int |
||
461 | intel_bo_get_reloc_count(struct intel_bo *bo) |
||
462 | { |
||
463 | return drm_intel_gem_bo_get_reloc_count((drm_intel_bo *) bo); |
||
464 | } |
||
465 | |||
466 | void |
||
467 | intel_bo_clear_relocs(struct intel_bo *bo, int start) |
||
468 | { |
||
469 | return drm_intel_gem_bo_clear_relocs((drm_intel_bo *) bo, start); |
||
470 | } |
||
471 | |||
472 | bool |
||
473 | intel_bo_references(struct intel_bo *bo, struct intel_bo *target_bo) |
||
474 | { |
||
475 | return drm_intel_bo_references((drm_intel_bo *) bo, |
||
476 | (drm_intel_bo *) target_bo); |
||
477 | } |
||
478 | |||
479 | int |
||
480 | intel_bo_exec(struct intel_bo *bo, int used, |
||
481 | struct intel_context *ctx, unsigned long flags) |
||
482 | { |
||
483 | if (ctx) { |
||
484 | return drm_intel_gem_bo_context_exec((drm_intel_bo *) bo, |
||
485 | (drm_intel_context *) ctx, used, flags); |
||
486 | } |
||
487 | else { |
||
488 | return drm_intel_bo_mrb_exec((drm_intel_bo *) bo, |
||
489 | used, NULL, 0, 0, flags); |
||
490 | } |
||
491 | } |
||
492 | |||
493 | int |
||
494 | intel_bo_wait(struct intel_bo *bo, int64_t timeout) |
||
495 | { |
||
496 | int err; |
||
497 | |||
498 | err = drm_intel_gem_bo_wait((drm_intel_bo *) bo, timeout); |
||
499 | /* consider the bo idle on errors */ |
||
500 | if (err && err != -ETIME) |
||
501 | err = 0; |
||
502 | |||
503 | return err; |
||
504 | } |