diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-09-20 15:41:01 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-09-21 11:24:17 +0100 |
commit | 265db9585e570814d2f7aca109c5563bcde9c948 (patch) | |
tree | 5319dd865de1d85c9135b8b9227f32db636b9aca /drivers/gpu | |
parent | c78ec30bba52754b9f21a899eac2e2f5a7486116 (diff) | |
download | lwn-265db9585e570814d2f7aca109c5563bcde9c948.tar.gz lwn-265db9585e570814d2f7aca109c5563bcde9c948.zip |
drm/i915: Drain any pending flips on the fb prior to unpinning
If we have queued a page flip on the current fb and then request a mode
change, wait until the page flip completes before performing the new
request.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 41 |
3 files changed, 26 insertions, 20 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 37a44c80efd2..ce8ff8fdc55c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1024,6 +1024,9 @@ int i915_do_wait_request(struct drm_device *dev, uint32_t seqno, bool interruptible, struct intel_ring_buffer *ring); +int i915_gem_wait_for_pending_flip(struct drm_device *dev, + struct drm_gem_object **object_list, + int count); int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 58baecc821a5..a8ddcd499b3b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3497,7 +3497,7 @@ i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer2 *exec, return 0; } -static int +int i915_gem_wait_for_pending_flip(struct drm_device *dev, struct drm_gem_object **object_list, int count) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 791374c888da..461bf4879e0a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1564,11 +1564,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_device *dev = crtc->dev; struct drm_i915_master_private *master_priv; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_framebuffer *intel_fb; - struct drm_i915_gem_object *obj_priv; - struct drm_gem_object *obj; - int pipe = intel_crtc->pipe; - int plane = intel_crtc->plane; int ret; /* no fb bound */ @@ -1577,38 +1572,46 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, return 0; } - switch (plane) { + switch (intel_crtc->plane) { case 0: case 1: break; default: - DRM_ERROR("Can't update plane %d in SAREA\n", plane); return -EINVAL; } - intel_fb = to_intel_framebuffer(crtc->fb); - obj = intel_fb->obj; - obj_priv = to_intel_bo(obj); - mutex_lock(&dev->struct_mutex); - ret = intel_pin_and_fence_fb_obj(dev, obj, false); + ret = intel_pin_and_fence_fb_obj(dev, + to_intel_framebuffer(crtc->fb)->obj, + false); if (ret != 0) { mutex_unlock(&dev->struct_mutex); return ret; } + if (old_fb) { + struct drm_gem_object *obj = to_intel_framebuffer(old_fb)->obj; + struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); + + if (atomic_read(&obj_priv->pending_flip)) { + ret = i915_gem_wait_for_pending_flip(dev, &obj, 1); + if (ret) { + i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj); + mutex_unlock(&dev->struct_mutex); + return ret; + } + } + } + ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y); if (ret) { - i915_gem_object_unpin(obj); + i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj); mutex_unlock(&dev->struct_mutex); return ret; } - if (old_fb) { - intel_fb = to_intel_framebuffer(old_fb); - obj_priv = to_intel_bo(intel_fb->obj); - i915_gem_object_unpin(intel_fb->obj); - } + if (old_fb) + i915_gem_object_unpin(to_intel_framebuffer(old_fb)->obj); mutex_unlock(&dev->struct_mutex); @@ -1619,7 +1622,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, if (!master_priv->sarea_priv) return 0; - if (pipe) { + if (intel_crtc->pipe) { master_priv->sarea_priv->pipeB_x = x; master_priv->sarea_priv->pipeB_y = y; } else { |