OSDN Git Service

minigbm: Reformat with clang-format.
[android-x86/external-minigbm.git] / i915.c
1 /*
2  * Copyright 2014 The Chromium OS Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6
7 #ifdef DRV_I915
8
9 #include <assert.h>
10 #include <errno.h>
11 #include <i915_drm.h>
12 #include <stdbool.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <sys/mman.h>
16 #include <unistd.h>
17 #include <xf86drm.h>
18
19 #include "drv_priv.h"
20 #include "helpers.h"
21 #include "util.h"
22
23 #define I915_CACHELINE_SIZE 64
24 #define I915_CACHELINE_MASK (I915_CACHELINE_SIZE - 1)
25
26 static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR16161616F, DRM_FORMAT_ABGR2101010,
27                                                   DRM_FORMAT_ABGR8888,      DRM_FORMAT_ARGB2101010,
28                                                   DRM_FORMAT_ARGB8888,      DRM_FORMAT_RGB565,
29                                                   DRM_FORMAT_XBGR2101010,   DRM_FORMAT_XBGR8888,
30                                                   DRM_FORMAT_XRGB2101010,   DRM_FORMAT_XRGB8888 };
31
32 static const uint32_t texture_source_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_NV12, DRM_FORMAT_P010,
33                                                    DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID };
34
35 struct i915_device {
36         uint32_t gen;
37         int32_t has_llc;
38 };
39
40 static uint32_t i915_get_gen(int device_id)
41 {
42         const uint16_t gen3_ids[] = { 0x2582, 0x2592, 0x2772, 0x27A2, 0x27AE,
43                                       0x29C2, 0x29B2, 0x29D2, 0xA001, 0xA011 };
44         unsigned i;
45         for (i = 0; i < ARRAY_SIZE(gen3_ids); i++)
46                 if (gen3_ids[i] == device_id)
47                         return 3;
48
49         return 4;
50 }
51
52 /*
53  * We allow allocation of ARGB formats for SCANOUT if the corresponding XRGB
54  * formats supports it. It's up to the caller (chrome ozone) to ultimately not
55  * scan out ARGB if the display controller only supports XRGB, but we'll allow
56  * the allocation of the bo here.
57  */
58 static bool format_compatible(const struct combination *combo, uint32_t format)
59 {
60         if (combo->format == format)
61                 return true;
62
63         switch (format) {
64         case DRM_FORMAT_XRGB8888:
65                 return combo->format == DRM_FORMAT_ARGB8888;
66         case DRM_FORMAT_XBGR8888:
67                 return combo->format == DRM_FORMAT_ABGR8888;
68         case DRM_FORMAT_RGBX8888:
69                 return combo->format == DRM_FORMAT_RGBA8888;
70         case DRM_FORMAT_BGRX8888:
71                 return combo->format == DRM_FORMAT_BGRA8888;
72         case DRM_FORMAT_XRGB2101010:
73                 return combo->format == DRM_FORMAT_ARGB2101010;
74         case DRM_FORMAT_XBGR2101010:
75                 return combo->format == DRM_FORMAT_ABGR2101010;
76         default:
77                 return false;
78         }
79 }
80
81 static int i915_add_kms_item(struct driver *drv, const struct kms_item *item)
82 {
83         uint32_t i;
84         struct combination *combo;
85
86         /*
87          * Older hardware can't scanout Y-tiled formats. Newer devices can, and
88          * report this functionality via format modifiers.
89          */
90         for (i = 0; i < drv_array_size(drv->combos); i++) {
91                 combo = (struct combination *)drv_array_at_idx(drv->combos, i);
92                 if (!format_compatible(combo, item->format))
93                         continue;
94
95                 if (item->modifier == DRM_FORMAT_MOD_LINEAR &&
96                     combo->metadata.tiling == I915_TILING_X) {
97                         /*
98                          * FIXME: drv_query_kms() does not report the available modifiers
99                          * yet, but we know that all hardware can scanout from X-tiled
100                          * buffers, so let's add this to our combinations, except for
101                          * cursor, which must not be tiled.
102                          */
103                         combo->use_flags |= item->use_flags & ~BO_USE_CURSOR;
104                 }
105
106                 /* If we can scanout NV12, we support all tiling modes. */
107                 if (item->format == DRM_FORMAT_NV12)
108                         combo->use_flags |= item->use_flags;
109
110                 if (combo->metadata.modifier == item->modifier)
111                         combo->use_flags |= item->use_flags;
112         }
113
114         return 0;
115 }
116
117 static int i915_add_combinations(struct driver *drv)
118 {
119         int ret;
120         uint32_t i;
121         struct drv_array *kms_items;
122         struct format_metadata metadata;
123         uint64_t render_use_flags, texture_use_flags;
124
125         render_use_flags = BO_USE_RENDER_MASK;
126         texture_use_flags = BO_USE_TEXTURE_MASK;
127
128         metadata.tiling = I915_TILING_NONE;
129         metadata.priority = 1;
130         metadata.modifier = DRM_FORMAT_MOD_LINEAR;
131
132         drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
133                              &metadata, render_use_flags);
134
135         drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
136                              &metadata, texture_use_flags);
137
138         /*
139          * Chrome uses DMA-buf mmap to write to YV12 buffers, which are then accessed by the
140          * Video Encoder Accelerator (VEA). It could also support NV12 potentially in the future.
141          */
142         drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata, BO_USE_HW_VIDEO_ENCODER);
143         drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata,
144                                BO_USE_HW_VIDEO_ENCODER | BO_USE_HW_VIDEO_DECODER);
145
146         /* Android CTS tests require this. */
147         drv_add_combination(drv, DRM_FORMAT_BGR888, &metadata, BO_USE_SW_MASK);
148
149         drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT);
150         drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT);
151
152         /* IPU3 camera ISP supports only NV12 output. */
153         drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata,
154                                BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
155         /*
156          * R8 format is used for Android's HAL_PIXEL_FORMAT_BLOB and is used for JPEG snapshots
157          * from camera.
158          */
159         drv_modify_combination(drv, DRM_FORMAT_R8, &metadata,
160                                BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
161
162         render_use_flags &= ~BO_USE_RENDERSCRIPT;
163         render_use_flags &= ~BO_USE_SW_WRITE_OFTEN;
164         render_use_flags &= ~BO_USE_SW_READ_OFTEN;
165         render_use_flags &= ~BO_USE_LINEAR;
166         render_use_flags &= ~BO_USE_PROTECTED;
167
168         texture_use_flags &= ~BO_USE_RENDERSCRIPT;
169         texture_use_flags &= ~BO_USE_SW_WRITE_OFTEN;
170         texture_use_flags &= ~BO_USE_SW_READ_OFTEN;
171         texture_use_flags &= ~BO_USE_LINEAR;
172         texture_use_flags &= ~BO_USE_PROTECTED;
173
174         metadata.tiling = I915_TILING_X;
175         metadata.priority = 2;
176         metadata.modifier = I915_FORMAT_MOD_X_TILED;
177
178         drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
179                              &metadata, render_use_flags);
180
181         metadata.tiling = I915_TILING_Y;
182         metadata.priority = 3;
183         metadata.modifier = I915_FORMAT_MOD_Y_TILED;
184
185         drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
186                              &metadata, render_use_flags);
187
188         /* Support y-tiled NV12 and P010 for libva */
189         drv_add_combination(drv, DRM_FORMAT_NV12, &metadata,
190                             BO_USE_TEXTURE | BO_USE_HW_VIDEO_DECODER);
191         drv_add_combination(drv, DRM_FORMAT_P010, &metadata,
192                             BO_USE_TEXTURE | BO_USE_HW_VIDEO_DECODER);
193
194         kms_items = drv_query_kms(drv);
195         if (!kms_items)
196                 return 0;
197
198         for (i = 0; i < drv_array_size(kms_items); i++) {
199                 ret = i915_add_kms_item(drv, (struct kms_item *)drv_array_at_idx(kms_items, i));
200                 if (ret) {
201                         drv_array_destroy(kms_items);
202                         return ret;
203                 }
204         }
205
206         drv_array_destroy(kms_items);
207         return 0;
208 }
209
210 static int i915_align_dimensions(struct bo *bo, uint32_t tiling, uint32_t *stride,
211                                  uint32_t *aligned_height)
212 {
213         struct i915_device *i915 = bo->drv->priv;
214         uint32_t horizontal_alignment;
215         uint32_t vertical_alignment;
216
217         switch (tiling) {
218         default:
219         case I915_TILING_NONE:
220                 /*
221                  * The Intel GPU doesn't need any alignment in linear mode,
222                  * but libva requires the allocation stride to be aligned to
223                  * 16 bytes and height to 4 rows. Further, we round up the
224                  * horizontal alignment so that row start on a cache line (64
225                  * bytes).
226                  */
227                 horizontal_alignment = 64;
228                 vertical_alignment = 4;
229                 break;
230
231         case I915_TILING_X:
232                 horizontal_alignment = 512;
233                 vertical_alignment = 8;
234                 break;
235
236         case I915_TILING_Y:
237                 if (i915->gen == 3) {
238                         horizontal_alignment = 512;
239                         vertical_alignment = 8;
240                 } else {
241                         horizontal_alignment = 128;
242                         vertical_alignment = 32;
243                 }
244                 break;
245         }
246
247         *aligned_height = ALIGN(*aligned_height, vertical_alignment);
248         if (i915->gen > 3) {
249                 *stride = ALIGN(*stride, horizontal_alignment);
250         } else {
251                 while (*stride > horizontal_alignment)
252                         horizontal_alignment <<= 1;
253
254                 *stride = horizontal_alignment;
255         }
256
257         if (i915->gen <= 3 && *stride > 8192)
258                 return -EINVAL;
259
260         return 0;
261 }
262
263 static void i915_clflush(void *start, size_t size)
264 {
265         void *p = (void *)(((uintptr_t)start) & ~I915_CACHELINE_MASK);
266         void *end = (void *)((uintptr_t)start + size);
267
268         __builtin_ia32_mfence();
269         while (p < end) {
270                 __builtin_ia32_clflush(p);
271                 p = (void *)((uintptr_t)p + I915_CACHELINE_SIZE);
272         }
273 }
274
275 static int i915_init(struct driver *drv)
276 {
277         int ret;
278         int device_id;
279         struct i915_device *i915;
280         drm_i915_getparam_t get_param;
281
282         i915 = calloc(1, sizeof(*i915));
283         if (!i915)
284                 return -ENOMEM;
285
286         memset(&get_param, 0, sizeof(get_param));
287         get_param.param = I915_PARAM_CHIPSET_ID;
288         get_param.value = &device_id;
289         ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GETPARAM, &get_param);
290         if (ret) {
291                 drv_log("Failed to get I915_PARAM_CHIPSET_ID\n");
292                 free(i915);
293                 return -EINVAL;
294         }
295
296         i915->gen = i915_get_gen(device_id);
297
298         memset(&get_param, 0, sizeof(get_param));
299         get_param.param = I915_PARAM_HAS_LLC;
300         get_param.value = &i915->has_llc;
301         ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GETPARAM, &get_param);
302         if (ret) {
303                 drv_log("Failed to get I915_PARAM_HAS_LLC\n");
304                 free(i915);
305                 return -EINVAL;
306         }
307
308         drv->priv = i915;
309
310         return i915_add_combinations(drv);
311 }
312
313 static int i915_bo_from_format(struct bo *bo, uint32_t width, uint32_t height, uint32_t format)
314 {
315         uint32_t offset;
316         size_t plane;
317         int ret, pagesize;
318
319         offset = 0;
320         pagesize = getpagesize();
321         for (plane = 0; plane < drv_num_planes_from_format(format); plane++) {
322                 uint32_t stride = drv_stride_from_format(format, width, plane);
323                 uint32_t plane_height = drv_height_from_format(format, height, plane);
324
325                 if (bo->meta.tiling != I915_TILING_NONE)
326                         assert(IS_ALIGNED(offset, pagesize));
327
328                 ret = i915_align_dimensions(bo, bo->meta.tiling, &stride, &plane_height);
329                 if (ret)
330                         return ret;
331
332                 bo->meta.strides[plane] = stride;
333                 bo->meta.sizes[plane] = stride * plane_height;
334                 bo->meta.offsets[plane] = offset;
335                 offset += bo->meta.sizes[plane];
336         }
337
338         bo->meta.total_size = ALIGN(offset, pagesize);
339
340         return 0;
341 }
342
343 static int i915_bo_create_for_modifier(struct bo *bo, uint32_t width, uint32_t height,
344                                        uint32_t format, uint64_t modifier)
345 {
346         int ret;
347         size_t plane;
348         struct drm_i915_gem_create gem_create;
349         struct drm_i915_gem_set_tiling gem_set_tiling;
350
351         switch (modifier) {
352         case DRM_FORMAT_MOD_LINEAR:
353                 bo->meta.tiling = I915_TILING_NONE;
354                 break;
355         case I915_FORMAT_MOD_X_TILED:
356                 bo->meta.tiling = I915_TILING_X;
357                 break;
358         case I915_FORMAT_MOD_Y_TILED:
359                 bo->meta.tiling = I915_TILING_Y;
360                 break;
361         }
362
363         bo->meta.format_modifiers[0] = modifier;
364
365         if (format == DRM_FORMAT_YVU420_ANDROID) {
366                 /*
367                  * We only need to be able to use this as a linear texture,
368                  * which doesn't put any HW restrictions on how we lay it
369                  * out. The Android format does require the stride to be a
370                  * multiple of 16 and expects the Cr and Cb stride to be
371                  * ALIGN(Y_stride / 2, 16), which we can make happen by
372                  * aligning to 32 bytes here.
373                  */
374                 uint32_t stride = ALIGN(width, 32);
375                 drv_bo_from_format(bo, stride, height, format);
376         } else {
377                 i915_bo_from_format(bo, width, height, format);
378         }
379
380         memset(&gem_create, 0, sizeof(gem_create));
381         gem_create.size = bo->meta.total_size;
382
383         ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create);
384         if (ret) {
385                 drv_log("DRM_IOCTL_I915_GEM_CREATE failed (size=%llu)\n", gem_create.size);
386                 return -errno;
387         }
388
389         for (plane = 0; plane < bo->meta.num_planes; plane++)
390                 bo->handles[plane].u32 = gem_create.handle;
391
392         memset(&gem_set_tiling, 0, sizeof(gem_set_tiling));
393         gem_set_tiling.handle = bo->handles[0].u32;
394         gem_set_tiling.tiling_mode = bo->meta.tiling;
395         gem_set_tiling.stride = bo->meta.strides[0];
396
397         ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_SET_TILING, &gem_set_tiling);
398         if (ret) {
399                 struct drm_gem_close gem_close;
400                 memset(&gem_close, 0, sizeof(gem_close));
401                 gem_close.handle = bo->handles[0].u32;
402                 drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
403
404                 drv_log("DRM_IOCTL_I915_GEM_SET_TILING failed with %d\n", errno);
405                 return -errno;
406         }
407
408         return 0;
409 }
410
411 static int i915_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
412                           uint64_t use_flags)
413 {
414         struct combination *combo;
415
416         combo = drv_get_combination(bo->drv, format, use_flags);
417         if (!combo)
418                 return -EINVAL;
419
420         return i915_bo_create_for_modifier(bo, width, height, format, combo->metadata.modifier);
421 }
422
423 static int i915_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint32_t height,
424                                          uint32_t format, const uint64_t *modifiers, uint32_t count)
425 {
426         static const uint64_t modifier_order[] = {
427                 I915_FORMAT_MOD_Y_TILED,
428                 I915_FORMAT_MOD_X_TILED,
429                 DRM_FORMAT_MOD_LINEAR,
430         };
431         uint64_t modifier;
432
433         modifier = drv_pick_modifier(modifiers, count, modifier_order, ARRAY_SIZE(modifier_order));
434
435         return i915_bo_create_for_modifier(bo, width, height, format, modifier);
436 }
437
438 static void i915_close(struct driver *drv)
439 {
440         free(drv->priv);
441         drv->priv = NULL;
442 }
443
444 static int i915_bo_import(struct bo *bo, struct drv_import_fd_data *data)
445 {
446         int ret;
447         struct drm_i915_gem_get_tiling gem_get_tiling;
448
449         ret = drv_prime_bo_import(bo, data);
450         if (ret)
451                 return ret;
452
453         /* TODO(gsingh): export modifiers and get rid of backdoor tiling. */
454         memset(&gem_get_tiling, 0, sizeof(gem_get_tiling));
455         gem_get_tiling.handle = bo->handles[0].u32;
456
457         ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_GET_TILING, &gem_get_tiling);
458         if (ret) {
459                 drv_gem_bo_destroy(bo);
460                 drv_log("DRM_IOCTL_I915_GEM_GET_TILING failed.\n");
461                 return ret;
462         }
463
464         bo->meta.tiling = gem_get_tiling.tiling_mode;
465         return 0;
466 }
467
468 static void *i915_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
469 {
470         int ret;
471         void *addr;
472
473         if (bo->meta.tiling == I915_TILING_NONE) {
474                 struct drm_i915_gem_mmap gem_map;
475                 memset(&gem_map, 0, sizeof(gem_map));
476
477                 /* TODO(b/118799155): We don't seem to have a good way to
478                  * detect the use cases for which WC mapping is really needed.
479                  * The current heuristic seems overly coarse and may be slowing
480                  * down some other use cases unnecessarily.
481                  *
482                  * For now, care must be taken not to use WC mappings for
483                  * Renderscript and camera use cases, as they're
484                  * performance-sensitive. */
485                 if ((bo->meta.use_flags & BO_USE_SCANOUT) &&
486                     !(bo->meta.use_flags &
487                       (BO_USE_RENDERSCRIPT | BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)))
488                         gem_map.flags = I915_MMAP_WC;
489
490                 gem_map.handle = bo->handles[0].u32;
491                 gem_map.offset = 0;
492                 gem_map.size = bo->meta.total_size;
493
494                 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_MMAP, &gem_map);
495                 if (ret) {
496                         drv_log("DRM_IOCTL_I915_GEM_MMAP failed\n");
497                         return MAP_FAILED;
498                 }
499
500                 addr = (void *)(uintptr_t)gem_map.addr_ptr;
501         } else {
502                 struct drm_i915_gem_mmap_gtt gem_map;
503                 memset(&gem_map, 0, sizeof(gem_map));
504
505                 gem_map.handle = bo->handles[0].u32;
506
507                 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &gem_map);
508                 if (ret) {
509                         drv_log("DRM_IOCTL_I915_GEM_MMAP_GTT failed\n");
510                         return MAP_FAILED;
511                 }
512
513                 addr = mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED,
514                             bo->drv->fd, gem_map.offset);
515         }
516
517         if (addr == MAP_FAILED) {
518                 drv_log("i915 GEM mmap failed\n");
519                 return addr;
520         }
521
522         vma->length = bo->meta.total_size;
523         return addr;
524 }
525
526 static int i915_bo_invalidate(struct bo *bo, struct mapping *mapping)
527 {
528         int ret;
529         struct drm_i915_gem_set_domain set_domain;
530
531         memset(&set_domain, 0, sizeof(set_domain));
532         set_domain.handle = bo->handles[0].u32;
533         if (bo->meta.tiling == I915_TILING_NONE) {
534                 set_domain.read_domains = I915_GEM_DOMAIN_CPU;
535                 if (mapping->vma->map_flags & BO_MAP_WRITE)
536                         set_domain.write_domain = I915_GEM_DOMAIN_CPU;
537         } else {
538                 set_domain.read_domains = I915_GEM_DOMAIN_GTT;
539                 if (mapping->vma->map_flags & BO_MAP_WRITE)
540                         set_domain.write_domain = I915_GEM_DOMAIN_GTT;
541         }
542
543         ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
544         if (ret) {
545                 drv_log("DRM_IOCTL_I915_GEM_SET_DOMAIN with %d\n", ret);
546                 return ret;
547         }
548
549         return 0;
550 }
551
552 static int i915_bo_flush(struct bo *bo, struct mapping *mapping)
553 {
554         struct i915_device *i915 = bo->drv->priv;
555         if (!i915->has_llc && bo->meta.tiling == I915_TILING_NONE)
556                 i915_clflush(mapping->vma->addr, mapping->vma->length);
557
558         return 0;
559 }
560
561 static uint32_t i915_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
562 {
563         switch (format) {
564         case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
565                 /* KBL camera subsystem requires NV12. */
566                 if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE))
567                         return DRM_FORMAT_NV12;
568                 /*HACK: See b/28671744 */
569                 return DRM_FORMAT_XBGR8888;
570         case DRM_FORMAT_FLEX_YCbCr_420_888:
571                 /*
572                  * KBL camera subsystem requires NV12. Our other use cases
573                  * don't care:
574                  * - Hardware video supports NV12,
575                  * - USB Camera HALv3 supports NV12,
576                  * - USB Camera HALv1 doesn't use this format.
577                  * Moreover, NV12 is preferred for video, due to overlay
578                  * support on SKL+.
579                  */
580                 return DRM_FORMAT_NV12;
581         default:
582                 return format;
583         }
584 }
585
586 const struct backend backend_i915 = {
587         .name = "i915",
588         .init = i915_init,
589         .close = i915_close,
590         .bo_create = i915_bo_create,
591         .bo_create_with_modifiers = i915_bo_create_with_modifiers,
592         .bo_destroy = drv_gem_bo_destroy,
593         .bo_import = i915_bo_import,
594         .bo_map = i915_bo_map,
595         .bo_unmap = drv_bo_munmap,
596         .bo_invalidate = i915_bo_invalidate,
597         .bo_flush = i915_bo_flush,
598         .resolve_format = i915_resolve_format,
599 };
600
601 #endif