OSDN Git Service

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