summaryrefslogtreecommitdiff
path: root/intel
diff options
context:
space:
mode:
Diffstat (limited to 'intel')
-rw-r--r--intel/intel_bufmgr_gem.c96
1 files changed, 92 insertions, 4 deletions
diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c
index 023af61f..3c522eab 100644
--- a/intel/intel_bufmgr_gem.c
+++ b/intel/intel_bufmgr_gem.c
@@ -1732,6 +1732,82 @@ drm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo)
return drm_intel_gem_bo_unmap(bo);
}
+static bool is_cache_coherent(drm_intel_bo *bo)
+{
+ drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
+ drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+ struct drm_i915_gem_caching arg = {};
+
+ arg.handle = bo_gem->gem_handle;
+ if (drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_GET_CACHING, &arg))
+ assert(false);
+ return arg.caching != I915_CACHING_NONE;
+}
+
+static void set_domain(drm_intel_bo *bo, uint32_t read, uint32_t write)
+{
+ drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
+ drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+ struct drm_i915_gem_set_domain arg = {};
+
+ arg.handle = bo_gem->gem_handle;
+ arg.read_domains = read;
+ arg.write_domain = write;
+ if (drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &arg))
+ assert(false);
+}
+
+static int mmap_write(drm_intel_bo *bo, unsigned long offset,
+ unsigned long length, const void *buf)
+{
+ void *map = NULL;
+
+ if (!length)
+ return 0;
+
+ if (is_cache_coherent(bo)) {
+ map = drm_intel_gem_bo_map__cpu(bo);
+ if (map)
+ set_domain(bo, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
+ }
+ if (!map) {
+ map = drm_intel_gem_bo_map__wc(bo);
+ if (map)
+ set_domain(bo, I915_GEM_DOMAIN_WC, I915_GEM_DOMAIN_WC);
+ }
+
+ assert(map);
+ memcpy((char *)map + offset, buf, length);
+ drm_intel_gem_bo_unmap(bo);
+ return 0;
+}
+
+static int mmap_read(drm_intel_bo *bo, unsigned long offset,
+ unsigned long length, void *buf)
+{
+ drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
+ void *map = NULL;
+
+ if (!length)
+ return 0;
+
+ if (bufmgr_gem->has_llc || is_cache_coherent(bo)) {
+ map = drm_intel_gem_bo_map__cpu(bo);
+ if (map)
+ set_domain(bo, I915_GEM_DOMAIN_CPU, 0);
+ }
+ if (!map) {
+ map = drm_intel_gem_bo_map__wc(bo);
+ if (map)
+ set_domain(bo, I915_GEM_DOMAIN_WC, 0);
+ }
+
+ assert(map);
+ memcpy(buf, (char *)map + offset, length);
+ drm_intel_gem_bo_unmap(bo);
+ return 0;
+}
+
static int
drm_intel_gem_bo_subdata(drm_intel_bo *bo, unsigned long offset,
unsigned long size, const void *data)
@@ -1752,14 +1828,20 @@ drm_intel_gem_bo_subdata(drm_intel_bo *bo, unsigned long offset,
ret = drmIoctl(bufmgr_gem->fd,
DRM_IOCTL_I915_GEM_PWRITE,
&pwrite);
- if (ret != 0) {
+ if (ret)
ret = -errno;
+
+ if (ret != 0 && ret != -EOPNOTSUPP) {
DBG("%s:%d: Error writing data to buffer %d: (%d %d) %s .\n",
__FILE__, __LINE__, bo_gem->gem_handle, (int)offset,
(int)size, strerror(errno));
+ return ret;
}
- return ret;
+ if (ret == -EOPNOTSUPP)
+ mmap_write(bo, offset, size, data);
+
+ return 0;
}
static int
@@ -1807,14 +1889,20 @@ drm_intel_gem_bo_get_subdata(drm_intel_bo *bo, unsigned long offset,
ret = drmIoctl(bufmgr_gem->fd,
DRM_IOCTL_I915_GEM_PREAD,
&pread);
- if (ret != 0) {
+ if (ret)
ret = -errno;
+
+ if (ret != 0 && ret != -EOPNOTSUPP) {
DBG("%s:%d: Error reading data from buffer %d: (%d %d) %s .\n",
__FILE__, __LINE__, bo_gem->gem_handle, (int)offset,
(int)size, strerror(errno));
+ return ret;
}
- return ret;
+ if (ret == -EOPNOTSUPP)
+ mmap_read(bo, offset, size, data);
+
+ return 0;
}
/** Waits for all GPU rendering with the object to have completed. */