aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_gem.c
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2014-06-19 10:01:59 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-06-19 12:14:47 -0400
commitf99d70690e0755696e4e68404c8993431efda469 (patch)
tree2b5db420af053264781ce68dbb6dc37a7e4852a8 /drivers/gpu/drm/i915/i915_gem.c
parentcc36513ca36a03e4fd8693d127bac5fe48185786 (diff)
drm/i915: Track frontbuffer invalidation/flushing
So these are the guts of the new beast. This tracks when a frontbuffer gets invalidated (due to frontbuffer rendering) and hence should be constantly scaned out, and when it's flushed again and can be compressed/one-shot-upload. Rules for flushing are simple: The frontbuffer needs one more full upload starting from the next vblank. Which means that the flushing can _only_ be called once the frontbuffer update has been latched. But this poses a problem for pageflips: We can't just delay the flushing until the pageflip is latched, since that would pose the risk that we override frontbuffer rendering that has been scheduled in-between the pageflip ioctl and the actual latching. To handle this track asynchronous invalidations (and also pageflip) state per-ring and delay any in-between flushing until the rendering has completed. And also cancel any delayed flushing if we get a new invalidation request (whether delayed or not). Also call intel_mark_fb_busy in both cases in all cases to make sure that we keep the screen at the highest refresh rate both on flips, synchronous plane updates and for frontbuffer rendering. v2: Lots of improvements Suggestions from Chris: - Move invalidate/flush in flush_*_domain and set_to_*_domain. - Drop the flush in busy_ioctl since it's redundant. Was a leftover from an earlier concept to track flips/delayed flushes. - Don't forget about the initial modeset enable/final disable. Suggested by Chris. Track flips accurately, too. Since flips complete independently of rendering we need to track pending flips in a separate mask. Again if an invalidate happens we need to cancel the evenutal flush to avoid races. v3: Provide correct header declarations for flip functions. Currently not needed outside of intel_display.c, but part of the proper interface. v4: Add proper domain management to fbcon so that the fbcon buffer is also tracked correctly. v5: Fixup locking around the fbcon set_to_gtt_domain call. v6: More comments from Chris: - Split out fbcon changes. - Drop superflous checks for potential scanout before calling intel_fb functions - we can micro-optimize this later. - s/intel_fb_/intel_fb_obj_/ to make it clear that this deals in gem object. We already have precedence for fb_obj in the pin_and_fence functions. v7: Clarify the semantics of the flip flush handling by renaming things a bit: - Don't go through a gem object but take the relevant frontbuffer bits directly. These functions center on the plane, the actual object is irrelevant - even a flip to the same object as already active should cause a flush. - Add a new intel_frontbuffer_flip for synchronous plane updates. It currently just calls intel_frontbuffer_flush since the implemenation differs. This way we achieve a clear split between one-shot update events on one side and frontbuffer rendering with potentially a very long delay between the invalidate and flush. Chris and I also had some discussions about mark_busy and whether it is appropriate to call from flush. But mark busy is a state which should be derived from the 3 events (invalidate, flush, flip) we now have by the users, like psr does by tracking relevant information in psr.busy_frontbuffer_bits. DRRS (the only real use of mark_busy for frontbuffer) needs to have similar logic. With that the overall mark_busy in the core could be removed. v8: Only when retiring gpu buffers only flush frontbuffer bits we actually invalidated in a batch. Just for safety since before any additional usage/invalidate we should always retire current rendering. Suggested by Chris Wilson. v9: Actually use intel_frontbuffer_flip in all appropriate places. Spotted by Chris. v10: Address more comments from Chris: - Don't call _flip in set_base when the crtc is inactive, avoids redunancy in the modeset case with the initial enabling of all planes. - Add comments explaining that the initial/final plane enable/disable still has work left to do before it's fully generic. v11: Only invalidate for gtt/cpu access when writing. Spotted by Chris. v12: s/_flush/_flip/ in intel_overlay.c per Chris' comment. Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index caed6621d71a..f6d123828926 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1395,8 +1395,6 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
1395 goto unlock; 1395 goto unlock;
1396 } 1396 }
1397 1397
1398 intel_edp_psr_exit(dev);
1399
1400 /* Try to flush the object off the GPU without holding the lock. 1398 /* Try to flush the object off the GPU without holding the lock.
1401 * We will repeat the flush holding the lock in the normal manner 1399 * We will repeat the flush holding the lock in the normal manner
1402 * to catch cases where we are gazumped. 1400 * to catch cases where we are gazumped.
@@ -1442,8 +1440,6 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
1442 if (ret) 1440 if (ret)
1443 return ret; 1441 return ret;
1444 1442
1445 intel_edp_psr_exit(dev);
1446
1447 obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); 1443 obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
1448 if (&obj->base == NULL) { 1444 if (&obj->base == NULL) {
1449 ret = -ENOENT; 1445 ret = -ENOENT;
@@ -2223,6 +2219,8 @@ i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj)
2223 list_move_tail(&vma->mm_list, &vm->inactive_list); 2219 list_move_tail(&vma->mm_list, &vm->inactive_list);
2224 } 2220 }
2225 2221
2222 intel_fb_obj_flush(obj, true);
2223
2226 list_del_init(&obj->ring_list); 2224 list_del_init(&obj->ring_list);
2227 obj->ring = NULL; 2225 obj->ring = NULL;
2228 2226
@@ -3552,6 +3550,8 @@ i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj)
3552 old_write_domain = obj->base.write_domain; 3550 old_write_domain = obj->base.write_domain;
3553 obj->base.write_domain = 0; 3551 obj->base.write_domain = 0;
3554 3552
3553 intel_fb_obj_flush(obj, false);
3554
3555 trace_i915_gem_object_change_domain(obj, 3555 trace_i915_gem_object_change_domain(obj,
3556 obj->base.read_domains, 3556 obj->base.read_domains,
3557 old_write_domain); 3557 old_write_domain);
@@ -3573,6 +3573,8 @@ i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj,
3573 old_write_domain = obj->base.write_domain; 3573 old_write_domain = obj->base.write_domain;
3574 obj->base.write_domain = 0; 3574 obj->base.write_domain = 0;
3575 3575
3576 intel_fb_obj_flush(obj, false);
3577
3576 trace_i915_gem_object_change_domain(obj, 3578 trace_i915_gem_object_change_domain(obj,
3577 obj->base.read_domains, 3579 obj->base.read_domains,
3578 old_write_domain); 3580 old_write_domain);
@@ -3626,6 +3628,9 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
3626 obj->dirty = 1; 3628 obj->dirty = 1;
3627 } 3629 }
3628 3630
3631 if (write)
3632 intel_fb_obj_invalidate(obj, NULL);
3633
3629 trace_i915_gem_object_change_domain(obj, 3634 trace_i915_gem_object_change_domain(obj,
3630 old_read_domains, 3635 old_read_domains,
3631 old_write_domain); 3636 old_write_domain);
@@ -3962,6 +3967,9 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)
3962 obj->base.write_domain = I915_GEM_DOMAIN_CPU; 3967 obj->base.write_domain = I915_GEM_DOMAIN_CPU;
3963 } 3968 }
3964 3969
3970 if (write)
3971 intel_fb_obj_invalidate(obj, NULL);
3972
3965 trace_i915_gem_object_change_domain(obj, 3973 trace_i915_gem_object_change_domain(obj,
3966 old_read_domains, 3974 old_read_domains,
3967 old_write_domain); 3975 old_write_domain);
@@ -4236,8 +4244,6 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
4236 if (ret) 4244 if (ret)
4237 return ret; 4245 return ret;
4238 4246
4239 intel_edp_psr_exit(dev);
4240
4241 obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); 4247 obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
4242 if (&obj->base == NULL) { 4248 if (&obj->base == NULL) {
4243 ret = -ENOENT; 4249 ret = -ENOENT;
@@ -4937,6 +4943,8 @@ i915_gem_load(struct drm_device *dev)
4937 4943
4938 dev_priv->mm.oom_notifier.notifier_call = i915_gem_shrinker_oom; 4944 dev_priv->mm.oom_notifier.notifier_call = i915_gem_shrinker_oom;
4939 register_oom_notifier(&dev_priv->mm.oom_notifier); 4945 register_oom_notifier(&dev_priv->mm.oom_notifier);
4946
4947 mutex_init(&dev_priv->fb_tracking.lock);
4940} 4948}
4941 4949
4942void i915_gem_release(struct drm_device *dev, struct drm_file *file) 4950void i915_gem_release(struct drm_device *dev, struct drm_file *file)