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