Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 58d09ebd authored by Ville Syrjälä's avatar Ville Syrjälä
Browse files

drm/i915: Fix the overlay frontbuffer tracking



Do the overlay frontbuffer tracking properly so that it matches
the state of the overlay on/off/continue requests.

One slight problem is that intel_frontbuffer_flip_complete()
may get delayed by an arbitrarily liong time due to the fact that
the overlay code likes to bail out when a signal occurs. So the
flip may not get completed until the ioctl is restarted. But fixing
that would require bigger surgery, so I decided to ignore it for now.

Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1481131693-27993-5-git-send-email-ville.syrjala@linux.intel.com


Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent 4a15cdbb
Loading
Loading
Loading
Loading
+41 −23
Original line number Original line Diff line number Diff line
@@ -272,8 +272,30 @@ static int intel_overlay_on(struct intel_overlay *overlay)
	return intel_overlay_do_wait_request(overlay, req, NULL);
	return intel_overlay_do_wait_request(overlay, req, NULL);
}
}


static void intel_overlay_flip_prepare(struct intel_overlay *overlay,
				       struct i915_vma *vma)
{
	enum pipe pipe = overlay->crtc->pipe;

	WARN_ON(overlay->old_vma);

	i915_gem_track_fb(overlay->vma ? overlay->vma->obj : NULL,
			  vma ? vma->obj : NULL,
			  INTEL_FRONTBUFFER_OVERLAY(pipe));

	intel_frontbuffer_flip_prepare(overlay->i915,
				       INTEL_FRONTBUFFER_OVERLAY(pipe));

	overlay->old_vma = overlay->vma;
	if (vma)
		overlay->vma = i915_vma_get(vma);
	else
		overlay->vma = NULL;
}

/* overlay needs to be enabled in OCMD reg */
/* overlay needs to be enabled in OCMD reg */
static int intel_overlay_continue(struct intel_overlay *overlay,
static int intel_overlay_continue(struct intel_overlay *overlay,
				  struct i915_vma *vma,
				  bool load_polyphase_filter)
				  bool load_polyphase_filter)
{
{
	struct drm_i915_private *dev_priv = overlay->i915;
	struct drm_i915_private *dev_priv = overlay->i915;
@@ -308,43 +330,44 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
	intel_ring_emit(ring, flip_addr);
	intel_ring_emit(ring, flip_addr);
	intel_ring_advance(ring);
	intel_ring_advance(ring);


	intel_overlay_flip_prepare(overlay, vma);

	intel_overlay_submit_request(overlay, req, NULL);
	intel_overlay_submit_request(overlay, req, NULL);


	return 0;
	return 0;
}
}


static void intel_overlay_release_old_vid_tail(struct i915_gem_active *active,
static void intel_overlay_release_old_vma(struct intel_overlay *overlay)
					       struct drm_i915_gem_request *req)
{
{
	struct intel_overlay *overlay =
		container_of(active, typeof(*overlay), last_flip);
	struct i915_vma *vma;
	struct i915_vma *vma;


	vma = fetch_and_zero(&overlay->old_vma);
	vma = fetch_and_zero(&overlay->old_vma);
	if (WARN_ON(!vma))
	if (WARN_ON(!vma))
		return;
		return;


	i915_gem_track_fb(vma->obj, NULL,
	intel_frontbuffer_flip_complete(overlay->i915,
					INTEL_FRONTBUFFER_OVERLAY(overlay->crtc->pipe));
					INTEL_FRONTBUFFER_OVERLAY(overlay->crtc->pipe));


	i915_gem_object_unpin_from_display_plane(vma);
	i915_gem_object_unpin_from_display_plane(vma);
	i915_vma_put(vma);
	i915_vma_put(vma);
}
}


static void intel_overlay_off_tail(struct i915_gem_active *active,
static void intel_overlay_release_old_vid_tail(struct i915_gem_active *active,
					       struct drm_i915_gem_request *req)
					       struct drm_i915_gem_request *req)
{
{
	struct intel_overlay *overlay =
	struct intel_overlay *overlay =
		container_of(active, typeof(*overlay), last_flip);
		container_of(active, typeof(*overlay), last_flip);
	struct i915_vma *vma;


	/* never have the overlay hw on without showing a frame */
	intel_overlay_release_old_vma(overlay);
	vma = fetch_and_zero(&overlay->vma);
}
	if (WARN_ON(!vma))
		return;


	i915_gem_object_unpin_from_display_plane(vma);
static void intel_overlay_off_tail(struct i915_gem_active *active,
	i915_vma_put(vma);
				   struct drm_i915_gem_request *req)
{
	struct intel_overlay *overlay =
		container_of(active, typeof(*overlay), last_flip);

	intel_overlay_release_old_vma(overlay);


	overlay->crtc->overlay = NULL;
	overlay->crtc->overlay = NULL;
	overlay->crtc = NULL;
	overlay->crtc = NULL;
@@ -398,6 +421,8 @@ static int intel_overlay_off(struct intel_overlay *overlay)
	}
	}
	intel_ring_advance(ring);
	intel_ring_advance(ring);


	intel_overlay_flip_prepare(overlay, NULL);

	return intel_overlay_do_wait_request(overlay, req,
	return intel_overlay_do_wait_request(overlay, req,
					     intel_overlay_off_tail);
					     intel_overlay_off_tail);
}
}
@@ -836,18 +861,10 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,


	intel_overlay_unmap_regs(overlay, regs);
	intel_overlay_unmap_regs(overlay, regs);


	ret = intel_overlay_continue(overlay, scale_changed);
	ret = intel_overlay_continue(overlay, vma, scale_changed);
	if (ret)
	if (ret)
		goto out_unpin;
		goto out_unpin;


	i915_gem_track_fb(overlay->vma ? overlay->vma->obj : NULL,
			  vma->obj, INTEL_FRONTBUFFER_OVERLAY(pipe));

	overlay->old_vma = overlay->vma;
	overlay->vma = vma;

	intel_frontbuffer_flip(dev_priv, INTEL_FRONTBUFFER_OVERLAY(pipe));

	return 0;
	return 0;


out_unpin:
out_unpin:
@@ -1215,6 +1232,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,


	mutex_unlock(&dev->struct_mutex);
	mutex_unlock(&dev->struct_mutex);
	drm_modeset_unlock_all(dev);
	drm_modeset_unlock_all(dev);
	i915_gem_object_put(new_bo);


	kfree(params);
	kfree(params);