diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-04-14 04:41:17 -0400 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2011-06-10 00:51:19 -0400 |
commit | 2da3b9b940e2a18147422c54ed8b29d01e1ade88 (patch) | |
tree | afffe23550ffcc446e70559c4f75cd1f308cca33 | |
parent | c411964209508e32cf36f6512ed339996751f55f (diff) |
drm/i915: Combine pinning with setting to the display plane
We need to perform a few operations in order to move the object into the
display plane (where it can be accessed coherently by the display
engine) that are important for future safety to forbid whilst pinned. As a
result, we want to need to perform some of the operations before pinning,
but some are required once we have been bound into the GTT. So combine
the pinning performed by all the callers with set_to_display_plane(), so
this complication is contained within the single function.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 37 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_overlay.c | 6 |
4 files changed, 33 insertions, 31 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e552aa6bc859..8a9fd9177860 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -1209,7 +1209,8 @@ int __must_check | |||
1209 | i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, | 1209 | i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, |
1210 | bool write); | 1210 | bool write); |
1211 | int __must_check | 1211 | int __must_check |
1212 | i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj, | 1212 | i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, |
1213 | u32 alignment, | ||
1213 | struct intel_ring_buffer *pipelined); | 1214 | struct intel_ring_buffer *pipelined); |
1214 | int i915_gem_attach_phys_object(struct drm_device *dev, | 1215 | int i915_gem_attach_phys_object(struct drm_device *dev, |
1215 | struct drm_i915_gem_object *obj, | 1216 | struct drm_i915_gem_object *obj, |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e6915072ba72..8a439f0c21f5 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -3095,40 +3095,55 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, | |||
3095 | } | 3095 | } |
3096 | 3096 | ||
3097 | /* | 3097 | /* |
3098 | * Prepare buffer for display plane. Use uninterruptible for possible flush | 3098 | * Prepare buffer for display plane (scanout, cursors, etc). |
3099 | * wait, as in modesetting process we're not supposed to be interrupted. | 3099 | * Can be called from an uninterruptible phase (modesetting) and allows |
3100 | * any flushes to be pipelined (for pageflips). | ||
3101 | * | ||
3102 | * For the display plane, we want to be in the GTT but out of any write | ||
3103 | * domains. So in many ways this looks like set_to_gtt_domain() apart from the | ||
3104 | * ability to pipeline the waits, pinning and any additional subtleties | ||
3105 | * that may differentiate the display plane from ordinary buffers. | ||
3100 | */ | 3106 | */ |
3101 | int | 3107 | int |
3102 | i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj, | 3108 | i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, |
3109 | u32 alignment, | ||
3103 | struct intel_ring_buffer *pipelined) | 3110 | struct intel_ring_buffer *pipelined) |
3104 | { | 3111 | { |
3105 | uint32_t old_read_domains; | 3112 | u32 old_read_domains, old_write_domain; |
3106 | int ret; | 3113 | int ret; |
3107 | 3114 | ||
3108 | /* Not valid to be called on unbound objects. */ | ||
3109 | if (obj->gtt_space == NULL) | ||
3110 | return -EINVAL; | ||
3111 | |||
3112 | ret = i915_gem_object_flush_gpu_write_domain(obj); | 3115 | ret = i915_gem_object_flush_gpu_write_domain(obj); |
3113 | if (ret) | 3116 | if (ret) |
3114 | return ret; | 3117 | return ret; |
3115 | 3118 | ||
3116 | |||
3117 | /* Currently, we are always called from an non-interruptible context. */ | ||
3118 | if (pipelined != obj->ring) { | 3119 | if (pipelined != obj->ring) { |
3119 | ret = i915_gem_object_wait_rendering(obj); | 3120 | ret = i915_gem_object_wait_rendering(obj); |
3120 | if (ret) | 3121 | if (ret) |
3121 | return ret; | 3122 | return ret; |
3122 | } | 3123 | } |
3123 | 3124 | ||
3125 | /* As the user may map the buffer once pinned in the display plane | ||
3126 | * (e.g. libkms for the bootup splash), we have to ensure that we | ||
3127 | * always use map_and_fenceable for all scanout buffers. | ||
3128 | */ | ||
3129 | ret = i915_gem_object_pin(obj, alignment, true); | ||
3130 | if (ret) | ||
3131 | return ret; | ||
3132 | |||
3124 | i915_gem_object_flush_cpu_write_domain(obj); | 3133 | i915_gem_object_flush_cpu_write_domain(obj); |
3125 | 3134 | ||
3135 | old_write_domain = obj->base.write_domain; | ||
3126 | old_read_domains = obj->base.read_domains; | 3136 | old_read_domains = obj->base.read_domains; |
3137 | |||
3138 | /* It should now be out of any other write domains, and we can update | ||
3139 | * the domain values for our changes. | ||
3140 | */ | ||
3141 | BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) != 0); | ||
3127 | obj->base.read_domains |= I915_GEM_DOMAIN_GTT; | 3142 | obj->base.read_domains |= I915_GEM_DOMAIN_GTT; |
3128 | 3143 | ||
3129 | trace_i915_gem_object_change_domain(obj, | 3144 | trace_i915_gem_object_change_domain(obj, |
3130 | old_read_domains, | 3145 | old_read_domains, |
3131 | obj->base.write_domain); | 3146 | old_write_domain); |
3132 | 3147 | ||
3133 | return 0; | 3148 | return 0; |
3134 | } | 3149 | } |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f79863a9a693..86a3ec1469ba 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -1812,14 +1812,10 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev, | |||
1812 | } | 1812 | } |
1813 | 1813 | ||
1814 | dev_priv->mm.interruptible = false; | 1814 | dev_priv->mm.interruptible = false; |
1815 | ret = i915_gem_object_pin(obj, alignment, true); | 1815 | ret = i915_gem_object_pin_to_display_plane(obj, alignment, pipelined); |
1816 | if (ret) | 1816 | if (ret) |
1817 | goto err_interruptible; | 1817 | goto err_interruptible; |
1818 | 1818 | ||
1819 | ret = i915_gem_object_set_to_display_plane(obj, pipelined); | ||
1820 | if (ret) | ||
1821 | goto err_unpin; | ||
1822 | |||
1823 | /* Install a fence for tiled scan-out. Pre-i965 always needs a | 1819 | /* Install a fence for tiled scan-out. Pre-i965 always needs a |
1824 | * fence, whereas 965+ only requires a fence if using | 1820 | * fence, whereas 965+ only requires a fence if using |
1825 | * framebuffer compression. For simplicity, we always install | 1821 | * framebuffer compression. For simplicity, we always install |
@@ -5434,21 +5430,15 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
5434 | goto fail_locked; | 5430 | goto fail_locked; |
5435 | } | 5431 | } |
5436 | 5432 | ||
5437 | ret = i915_gem_object_pin(obj, PAGE_SIZE, true); | 5433 | ret = i915_gem_object_pin_to_display_plane(obj, 0, NULL); |
5438 | if (ret) { | ||
5439 | DRM_ERROR("failed to pin cursor bo\n"); | ||
5440 | goto fail_locked; | ||
5441 | } | ||
5442 | |||
5443 | ret = i915_gem_object_set_to_display_plane(obj, NULL); | ||
5444 | if (ret) { | 5434 | if (ret) { |
5445 | DRM_ERROR("failed to move cursor bo into the GTT\n"); | 5435 | DRM_ERROR("failed to move cursor bo into the GTT\n"); |
5446 | goto fail_unpin; | 5436 | goto fail_locked; |
5447 | } | 5437 | } |
5448 | 5438 | ||
5449 | ret = i915_gem_object_put_fence(obj); | 5439 | ret = i915_gem_object_put_fence(obj); |
5450 | if (ret) { | 5440 | if (ret) { |
5451 | DRM_ERROR("failed to move cursor bo into the GTT\n"); | 5441 | DRM_ERROR("failed to release fence for cursor"); |
5452 | goto fail_unpin; | 5442 | goto fail_unpin; |
5453 | } | 5443 | } |
5454 | 5444 | ||
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index e0903c5f0ca2..fcf6fcb0b482 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c | |||
@@ -773,14 +773,10 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, | |||
773 | if (ret != 0) | 773 | if (ret != 0) |
774 | return ret; | 774 | return ret; |
775 | 775 | ||
776 | ret = i915_gem_object_pin(new_bo, PAGE_SIZE, true); | 776 | ret = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL); |
777 | if (ret != 0) | 777 | if (ret != 0) |
778 | return ret; | 778 | return ret; |
779 | 779 | ||
780 | ret = i915_gem_object_set_to_display_plane(new_bo, NULL); | ||
781 | if (ret != 0) | ||
782 | goto out_unpin; | ||
783 | |||
784 | ret = i915_gem_object_put_fence(new_bo); | 780 | ret = i915_gem_object_put_fence(new_bo); |
785 | if (ret) | 781 | if (ret) |
786 | goto out_unpin; | 782 | goto out_unpin; |