From: Dave Airlie <airlied@gmail.com>
To: dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org
Subject: [PATCH 10/11] drm/tiled: add page_flip support for multi-crtc monitors
Date: Tue, 9 Sep 2014 16:28:15 +1000 [thread overview]
Message-ID: <1410244096-9854-11-git-send-email-airlied@gmail.com> (raw)
In-Reply-To: <1410244096-9854-1-git-send-email-airlied@gmail.com>
From: Dave Airlie <airlied@redhat.com>
This is OMG bad, but in order to get semantics that don't defeat
userspace we have to wait for both flips to complete.
So rewrite the event handling code to make sure we wait for
all crtcs in the tile group to complete flipping.
The main problem otherwise is userspace does
add_fb
ioctl(PAGE_FLIP, crtc, fb)
wait_for_event
--> page_flip event
rm_fb
This rm_fb will forcefully nuke the framebuffer from all crtcs
that are currently running, however that causes bad things to happen
like the crtc gets turned off. So we need to wait before sending
the event so userspace doesn't do this. Otherwise gnome-shell
turns off half the display after 5-10 frames.
Signed-off-by: Dave Airlie <airlied@redhat.com>
---
drivers/gpu/drm/drm_crtc.c | 31 ++++++++++++++++++++++++++++++-
drivers/gpu/drm/drm_irq.c | 7 ++++++-
drivers/gpu/drm/i915/intel_display.c | 12 ++++++++----
include/drm/drmP.h | 2 ++
4 files changed, 46 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index e30518b..dd0649a0 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -4771,7 +4771,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
struct drm_pending_vblank_event *e = NULL;
unsigned long flags;
int ret = -EINVAL;
-
+ int crtc_count = 1;
if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
page_flip->reserved != 0)
return -EINVAL;
@@ -4833,14 +4833,43 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
e->event.base.length = sizeof e->event;
e->event.user_data = page_flip->user_data;
+ e->master = crtc;
e->base.event = &e->event.base;
e->base.file_priv = file_priv;
e->base.destroy =
(void (*) (struct drm_pending_event *)) kfree;
}
+ if (!list_empty(&crtc->tile_crtc_list)) {
+ struct drm_crtc *tile;
+
+ list_for_each_entry(tile, &crtc->tile_crtc_list, tile) {
+ crtc_count++;
+ }
+ if (e)
+ e->crtc_count = crtc_count;
+ list_for_each_entry(tile, &crtc->tile_crtc_list, tile) {
+ struct drm_framebuffer *tile_fb = fb;
+
+ drm_framebuffer_reference(fb);
+ old_fb = tile->primary->fb;
+
+ ret = tile->funcs->page_flip(tile, fb, e, page_flip->flags);
+ if (ret) {
+ old_fb = NULL;
+ } else {
+ tile_fb = NULL;
+ }
+ if (tile_fb)
+ drm_framebuffer_unreference(tile_fb);
+ if (old_fb)
+ drm_framebuffer_unreference(old_fb);
+ }
+ }
old_fb = crtc->primary->fb;
+
ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
+
if (ret) {
if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
spin_lock_irqsave(&dev->event_lock, flags);
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 08ba120..9eee6e9 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -783,10 +783,15 @@ static void send_vblank_event(struct drm_device *dev,
* Caller must hold event lock.
*/
void drm_send_vblank_event(struct drm_device *dev, int crtc,
- struct drm_pending_vblank_event *e)
+ struct drm_pending_vblank_event *e)
{
struct timeval now;
unsigned int seq;
+
+ e->crtc_count--;
+ if (e->crtc_count > 0)
+ return;
+
if (crtc >= 0) {
seq = drm_vblank_count_and_time(dev, crtc, &now);
} else {
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index d074d70..11a6ff3 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9153,8 +9153,10 @@ static void do_intel_finish_page_flip(struct drm_device *dev,
intel_crtc->unpin_work = NULL;
- if (work->event)
- drm_send_vblank_event(dev, intel_crtc->pipe, work->event);
+ if (work->event) {
+ struct intel_crtc *tmp = to_intel_crtc(work->event->master);
+ drm_send_vblank_event(dev, tmp->pipe, work->event);
+ }
drm_crtc_vblank_put(crtc);
@@ -9795,8 +9797,10 @@ free_work:
out_hang:
intel_crtc_wait_for_pending_flips(crtc);
ret = intel_pipe_set_base(crtc, crtc->x, crtc->y, fb);
- if (ret == 0 && event)
- drm_send_vblank_event(dev, pipe, event);
+ if (ret == 0 && event) {
+ struct intel_crtc *tmp = to_intel_crtc(event->master);
+ drm_send_vblank_event(dev, tmp->pipe, event);
+ }
}
return ret;
}
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 1968907..c6005f6 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -982,6 +982,8 @@ struct drm_pending_vblank_event {
struct drm_pending_event base;
int pipe;
struct drm_event_vblank event;
+ int crtc_count;
+ struct drm_crtc *master;
};
struct drm_vblank_crtc {
--
1.9.3
next prev parent reply other threads:[~2014-09-09 6:28 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-09-09 6:28 [RFC] attempting to hide 30" monitor in kernel (raw) Dave Airlie
2014-09-09 6:28 ` [PATCH 01/11] drm/mst: rework payload table allocation to conform better Dave Airlie
2014-09-09 6:28 ` [PATCH 02/11] drm/i915: add config option to enable/disable DP MST Dave Airlie
2014-09-09 7:51 ` Jani Nikula
2014-09-09 6:28 ` [PATCH 03/11] drm/mst: start caching edid for logical ports Dave Airlie
2014-09-09 6:28 ` [PATCH 04/11] drm/displayid: add some DisplayID related defines/structs Dave Airlie
2014-09-09 6:28 ` [PATCH 05/11] drm/dp/mst: add concept of base connector id Dave Airlie
2014-09-09 6:28 ` [PATCH 06/11] drm/tile: attempt to set tiled crtcs up Dave Airlie
2014-09-09 6:28 ` [PATCH 07/11] drm/edid: allow patching the EDID to report monster mode Dave Airlie
2014-09-09 6:28 ` [PATCH 08/11] drm/crtc: attempt to set tiled modes from userspace Dave Airlie
2014-09-09 6:28 ` [PATCH 09/11] drm/crtc: workaround userspace trying to derail crtc stealing Dave Airlie
2014-09-09 6:28 ` Dave Airlie [this message]
2014-09-09 6:28 ` [PATCH 11/11] drm/tiled: vague attempt at waving at cursors Dave Airlie
2014-09-09 8:54 ` [RFC] attempting to hide 30" monitor in kernel (raw) Daniel Vetter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1410244096-9854-11-git-send-email-airlied@gmail.com \
--to=airlied@gmail.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=intel-gfx@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox