OSDN Git Service

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