|
@@ -3095,40 +3095,55 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * Prepare buffer for display plane. Use uninterruptible for possible flush
|
|
|
- * wait, as in modesetting process we're not supposed to be interrupted.
|
|
|
+ * Prepare buffer for display plane (scanout, cursors, etc).
|
|
|
+ * Can be called from an uninterruptible phase (modesetting) and allows
|
|
|
+ * any flushes to be pipelined (for pageflips).
|
|
|
+ *
|
|
|
+ * For the display plane, we want to be in the GTT but out of any write
|
|
|
+ * domains. So in many ways this looks like set_to_gtt_domain() apart from the
|
|
|
+ * ability to pipeline the waits, pinning and any additional subtleties
|
|
|
+ * that may differentiate the display plane from ordinary buffers.
|
|
|
*/
|
|
|
int
|
|
|
-i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj,
|
|
|
+i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
|
|
|
+ u32 alignment,
|
|
|
struct intel_ring_buffer *pipelined)
|
|
|
{
|
|
|
- uint32_t old_read_domains;
|
|
|
+ u32 old_read_domains, old_write_domain;
|
|
|
int ret;
|
|
|
|
|
|
- /* Not valid to be called on unbound objects. */
|
|
|
- if (obj->gtt_space == NULL)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
ret = i915_gem_object_flush_gpu_write_domain(obj);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
-
|
|
|
- /* Currently, we are always called from an non-interruptible context. */
|
|
|
if (pipelined != obj->ring) {
|
|
|
ret = i915_gem_object_wait_rendering(obj);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+ /* As the user may map the buffer once pinned in the display plane
|
|
|
+ * (e.g. libkms for the bootup splash), we have to ensure that we
|
|
|
+ * always use map_and_fenceable for all scanout buffers.
|
|
|
+ */
|
|
|
+ ret = i915_gem_object_pin(obj, alignment, true);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
i915_gem_object_flush_cpu_write_domain(obj);
|
|
|
|
|
|
+ old_write_domain = obj->base.write_domain;
|
|
|
old_read_domains = obj->base.read_domains;
|
|
|
+
|
|
|
+ /* It should now be out of any other write domains, and we can update
|
|
|
+ * the domain values for our changes.
|
|
|
+ */
|
|
|
+ BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
|
|
|
obj->base.read_domains |= I915_GEM_DOMAIN_GTT;
|
|
|
|
|
|
trace_i915_gem_object_change_domain(obj,
|
|
|
old_read_domains,
|
|
|
- obj->base.write_domain);
|
|
|
+ old_write_domain);
|
|
|
|
|
|
return 0;
|
|
|
}
|