OSDN Git Service

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