OSDN Git Service

minigbm: i915: use DRM_IOCTL_I915_GEM_MMAP when needed
authorGurchetan Singh <gurchetansingh@chromium.org>
Fri, 6 Jan 2017 04:39:31 +0000 (20:39 -0800)
committerchrome-bot <chrome-bot@chromium.org>
Mon, 1 May 2017 19:20:01 +0000 (12:20 -0700)
The following three CTS tests fail with an i915 backend:

EncodeVirtualDisplayWithCompositionTest#testRendering800x480Locally
EncodeVirtualDisplayWithCompositionTest#testRenderingMaxResolutionRemotely
EncodeVirtualDisplayWithCompositionTest#testVirtualDisplayRecycles

The reason for the failures is the bo_map() function calls
DRM_IOCTL_I915_GEM_MMAP_GTT with untiled buffers, leading to
Surface::dequeueBuffer not completing in time.

Note the final form of unmap will be a clfush.

BUG=none
TEST=The 3 CTS tests pass.
CQ-DEPEND=CL:454104

Change-Id: I60826d0006da345eceb89f26543e1cc436bbf312
Reviewed-on: https://chromium-review.googlesource.com/425716
Commit-Ready: Gurchetan Singh <gurchetansingh@chromium.org>
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
i915.c

diff --git a/i915.c b/i915.c
index 4d6dd89..97fa200 100644 (file)
--- a/i915.c
+++ b/i915.c
@@ -272,24 +272,105 @@ static void i915_close(struct driver *drv)
        drv->priv = NULL;
 }
 
+static int i915_bo_import(struct bo *bo, struct drv_import_fd_data *data)
+{
+       int ret;
+       struct drm_i915_gem_get_tiling gem_get_tiling;
+
+       ret = drv_prime_bo_import(bo, data);
+       if (ret)
+               return ret;
+
+       /* TODO(gsingh): export modifiers and get rid of backdoor tiling. */
+       memset(&gem_get_tiling, 0, sizeof(gem_get_tiling));
+       gem_get_tiling.handle = bo->handles[0].u32;
+
+       ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_GET_TILING, &gem_get_tiling);
+       if (ret) {
+               fprintf(stderr, "drv: DRM_IOCTL_I915_GEM_GET_TILING failed.");
+               return ret;
+       }
+
+       bo->tiling = gem_get_tiling.tiling_mode;
+       return 0;
+}
+
 static void *i915_bo_map(struct bo *bo, struct map_info *data, size_t plane)
 {
        int ret;
-       struct drm_i915_gem_mmap_gtt gem_map;
+       void *addr;
+       struct drm_i915_gem_set_domain set_domain;
+
+       memset(&set_domain, 0, sizeof(set_domain));
+       set_domain.handle = bo->handles[0].u32;
+       if (bo->tiling == I915_TILING_NONE) {
+               struct drm_i915_gem_mmap gem_map;
+               memset(&gem_map, 0, sizeof(gem_map));
+
+               gem_map.handle = bo->handles[0].u32;
+               gem_map.offset = 0;
+               gem_map.size = bo->total_size;
+
+               ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_MMAP, &gem_map);
+               if (ret) {
+                       fprintf(stderr, "drv: DRM_IOCTL_I915_GEM_MMAP failed\n");
+                       return MAP_FAILED;
+               }
 
-       memset(&gem_map, 0, sizeof(gem_map));
-       gem_map.handle = bo->handles[0].u32;
+               addr = (void *)(uintptr_t)gem_map.addr_ptr;
+               set_domain.read_domains = I915_GEM_DOMAIN_CPU;
+               set_domain.write_domain = I915_GEM_DOMAIN_CPU;
 
-       ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &gem_map);
+       } else {
+               struct drm_i915_gem_mmap_gtt gem_map;
+               memset(&gem_map, 0, sizeof(gem_map));
+
+               gem_map.handle = bo->handles[0].u32;
+
+               ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &gem_map);
+               if (ret) {
+                       fprintf(stderr, "drv: DRM_IOCTL_I915_GEM_MMAP_GTT failed\n");
+                       return MAP_FAILED;
+               }
+
+               addr = mmap(0, bo->total_size, PROT_READ | PROT_WRITE, MAP_SHARED, bo->drv->fd,
+                           gem_map.offset);
+
+               set_domain.read_domains = I915_GEM_DOMAIN_GTT;
+               set_domain.write_domain = I915_GEM_DOMAIN_GTT;
+       }
+
+       if (addr == MAP_FAILED) {
+               fprintf(stderr, "drv: i915 GEM mmap failed\n");
+               return addr;
+       }
+
+       ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
        if (ret) {
-               fprintf(stderr, "drv: DRM_IOCTL_I915_GEM_MMAP_GTT failed\n");
+               fprintf(stderr, "drv: DRM_IOCTL_I915_GEM_SET_DOMAIN failed\n");
                return MAP_FAILED;
        }
 
        data->length = bo->total_size;
+       return addr;
+}
+
+static int i915_bo_unmap(struct bo *bo, struct map_info *data)
+{
+       if (bo->tiling == I915_TILING_NONE) {
+               int ret;
+               struct drm_i915_gem_sw_finish sw_finish;
+               memset(&sw_finish, 0, sizeof(sw_finish));
+
+               sw_finish.handle = bo->handles[0].u32;
+               ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_SW_FINISH, &sw_finish);
+               if (ret) {
+                       fprintf(stderr, "drv: DRM_IOCTL_I915_GEM_SW_FINISH failed\n");
+                       return ret;
+               }
+       }
 
-       return mmap(0, bo->total_size, PROT_READ | PROT_WRITE, MAP_SHARED, bo->drv->fd,
-                   gem_map.offset);
+       return munmap(data->addr, data->length);
 }
 
 static uint32_t i915_resolve_format(uint32_t format)
@@ -311,8 +392,9 @@ struct backend backend_i915 = {
        .close = i915_close,
        .bo_create = i915_bo_create,
        .bo_destroy = drv_gem_bo_destroy,
-       .bo_import = drv_prime_bo_import,
+       .bo_import = i915_bo_import,
        .bo_map = i915_bo_map,
+       .bo_unmap = i915_bo_unmap,
        .resolve_format = i915_resolve_format,
 };