xf86-video-intel: 5 commits - src/sna/kgem.c src/sna/sna_display.c src/sna/sna_dri2.c src/sna/sna.h src/uxa/intel_dri.c
Chris Wilson
ickle at kemper.freedesktop.org
Tue May 20 23:49:39 PDT 2014
src/sna/kgem.c | 2
src/sna/sna.h | 6 ++
src/sna/sna_display.c | 22 ++++++----
src/sna/sna_dri2.c | 109 +++++++++++++++++++++++++++-----------------------
src/uxa/intel_dri.c | 3 -
5 files changed, 84 insertions(+), 58 deletions(-)
New commits:
commit 183a0728ba52be9d052f5a5f6e6b54c4a9ee8253
Author: Dave Airlie <airlied at redhat.com>
Date: Wed May 21 12:41:58 2014 +1000
uxa: fix getmsc to not fail hard
If some outputs go away we race with this call and apps
get X errors and fall over. Do what SNA does and don't
bother trying.
Signed-off-by: Dave Airlie <airlied at redhat.com>
diff --git a/src/uxa/intel_dri.c b/src/uxa/intel_dri.c
index ca58052..01209b9 100644
--- a/src/uxa/intel_dri.c
+++ b/src/uxa/intel_dri.c
@@ -1356,6 +1356,7 @@ I830DRI2GetMSC(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
/* Drawable not displayed, make up a *monotonic* value */
if (pipe == -1) {
+fail:
*ust = gettime_us();
*msc = 0;
return TRUE;
@@ -1374,7 +1375,7 @@ I830DRI2GetMSC(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
strerror(errno));
limit--;
}
- return FALSE;
+ goto fail;
}
*ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
commit 2dbe76c4925e02b8ec20b986069e2ff38cea5bba
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Wed May 21 07:38:35 2014 +0100
sna/dri2: Tidy computation of 64bit ust
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/sna.h b/src/sna/sna.h
index 8cfa98a..a514181 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -463,6 +463,11 @@ extern xf86CrtcPtr sna_covering_crtc(struct sna *sna,
extern bool sna_wait_for_scanline(struct sna *sna, PixmapPtr pixmap,
xf86CrtcPtr crtc, const BoxRec *clip);
+static inline uint64_t ust64(int tv_sec, int tv_usec)
+{
+ return (uint64_t)tv_sec * 1000000 + tv_usec;
+}
+
#if HAVE_DRI2_H
bool sna_dri2_open(struct sna *sna, ScreenPtr pScreen);
void sna_dri2_page_flip_handler(struct sna *sna, struct drm_event_vblank *event);
diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 6991c91..d86c86e 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -2402,8 +2402,8 @@ fail:
if (pipe < 0)
pipe = 0;
*msc = sna->dri2.last_swap[pipe].msc;
- *ust = ((uint64_t)sna->dri2.last_swap[pipe].tv_sec * 100000 +
- sna->dri2.last_swap[pipe].tv_usec);
+ *ust = ust64(sna->dri2.last_swap[pipe].tv_sec,
+ sna->dri2.last_swap[pipe].tv_usec);
return TRUE;
}
@@ -2420,7 +2420,7 @@ fail:
sna->dri2.last_swap[pipe].tv_usec = vbl.reply.tval_usec;
sna->dri2.last_swap[pipe].msc = vbl.reply.sequence;
- *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
+ *ust = ust64(vbl.reply.tval_sec, vbl.reply.tval_usec);
*msc = vbl.reply.sequence;
DBG(("%s: msc=%llu, ust=%llu\n", __FUNCTION__,
(long long)*msc, (long long)*ust));
commit a82f6a7594ee13170aba5bac7fb57cd5550b27ee
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Tue May 20 12:20:38 2014 +0100
sna/dri2: Client cannot be NULL, so drop the checks
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index af1c8b5..6991c91 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -1359,7 +1359,7 @@ static void chain_swap(struct sna *sna,
DRI2SwapComplete(chain->client, draw,
frame, tv_sec, tv_usec,
DRI2_BLIT_COMPLETE,
- chain->client ? chain->event_complete : NULL, chain->event_data);
+ chain->event_complete, chain->event_data);
sna_dri2_frame_event_info_free(sna, draw, chain);
} else {
#if !XORG_CAN_TRIPLE_BUFFER
@@ -1367,7 +1367,7 @@ static void chain_swap(struct sna *sna,
DRI2SwapComplete(chain->client, draw,
frame, tv_sec, tv_usec,
DRI2_BLIT_COMPLETE,
- chain->client ? chain->event_complete : NULL, chain->event_data);
+ chain->event_complete, chain->event_data);
#else
DBG(("%s: setting swap limit to 2\n", __FUNCTION__));
DRI2SwapLimit(draw, 2);
@@ -1475,8 +1475,7 @@ void sna_dri2_vblank_handler(struct sna *sna, struct drm_event_vblank *event)
draw, event->sequence,
event->tv_sec, event->tv_usec,
DRI2_BLIT_COMPLETE,
- info->client ? info->event_complete : NULL,
- info->event_data);
+ info->event_complete, info->event_data);
break;
case SWAP_THROTTLE:
@@ -1494,8 +1493,7 @@ void sna_dri2_vblank_handler(struct sna *sna, struct drm_event_vblank *event)
draw, event->sequence,
event->tv_sec, event->tv_usec,
DRI2_BLIT_COMPLETE,
- info->client ? info->event_complete : NULL,
- info->event_data);
+ info->event_complete, info->event_data);
#endif
break;
@@ -1690,8 +1688,7 @@ sna_dri2_flip_continue(struct sna *sna, struct sna_dri2_frame_event *info)
DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
fake_swap_complete(sna, info->client, info->draw,
DRI2_FLIP_COMPLETE,
- info->client ? info->event_complete : NULL,
- info->event_data);
+ info->event_complete, info->event_data);
#endif
}
@@ -1743,7 +1740,7 @@ static void chain_flip(struct sna *sna)
DBG(("%s: fake triple buffering (or vblank wait failed), unblocking client\n", __FUNCTION__));
fake_swap_complete(sna, chain->client, chain->draw,
DRI2_BLIT_COMPLETE,
- chain->client ? chain->event_complete : NULL, chain->event_data);
+ chain->event_complete, chain->event_data);
sna_dri2_frame_event_info_free(sna, chain->draw, chain);
}
}
@@ -1810,8 +1807,7 @@ static void sna_dri2_flip_event(struct sna *sna,
flip->fe_tv_sec,
flip->fe_tv_usec,
DRI2_FLIP_COMPLETE,
- flip->client ? flip->event_complete : NULL,
- flip->event_data);
+ flip->event_complete, flip->event_data);
}
sna_dri2_frame_event_info_free(sna, flip->draw, flip);
@@ -1829,8 +1825,7 @@ static void sna_dri2_flip_event(struct sna *sna,
flip->fe_tv_sec,
flip->fe_tv_usec,
DRI2_FLIP_COMPLETE,
- flip->client ? flip->event_complete : NULL,
- flip->event_data);
+ flip->event_complete, flip->event_data);
}
case FLIP_COMPLETE:
if (sna->dri2.flip_pending) {
commit c548427e6d3a3fb50acec4b405b9d0ea977d3cc9
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Tue May 20 16:36:31 2014 +0100
sna: Only mark the scanout as being busy for writes (not solitary reads)
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 7e906e8..f635150 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -2486,7 +2486,7 @@ static void kgem_commit(struct kgem *kgem)
__kgem_bo_clear_busy(bo);
}
- kgem->scanout_busy |= bo->scanout;
+ kgem->scanout_busy |= bo->scanout && bo->needs_flush;
}
if (rq == &kgem->static_request) {
commit 61df0ffc0be8d934d86ac45c67da910479998cc7
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Tue May 20 12:07:50 2014 +0100
sna/dri2: Verify that the reference pipe is still active for flipping
We rely on the reference pipe to drive the event wake up. If we issue a
deferred flip, there is a chance that the user could rearrange the
screen on another crtc whilst otherwise preserving the screen geometry.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/sna.h b/src/sna/sna.h
index 0c0508b..8cfa98a 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -483,6 +483,7 @@ extern bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, uint32_t rotation);
extern int sna_crtc_to_pipe(xf86CrtcPtr crtc);
extern uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc);
extern uint32_t sna_crtc_id(xf86CrtcPtr crtc);
+extern int sna_crtc_is_on(xf86CrtcPtr crtc);
CARD32 sna_format_for_depth(int depth);
CARD32 sna_render_format_for_depth(int depth);
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 5671db5..69d42b7 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -222,6 +222,12 @@ uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc)
return to_sna_crtc(crtc)->sprite;
}
+int sna_crtc_is_on(xf86CrtcPtr crtc)
+{
+ assert(to_sna_crtc(crtc));
+ return to_sna_crtc(crtc)->bo != NULL;
+}
+
#ifndef NDEBUG
static void gem_close(int fd, uint32_t handle);
static void assert_scanout(struct kgem *kgem, struct kgem_bo *bo,
@@ -4009,7 +4015,7 @@ sna_cursors_fini(struct sna *sna)
}
static int do_page_flip(struct sna *sna, struct kgem_bo *bo,
- void *data, int ref_crtc_hw_id)
+ void *data, int pipe)
{
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
int width = sna->scrn->virtualX;
@@ -4032,8 +4038,10 @@ static int do_page_flip(struct sna *sna, struct kgem_bo *bo,
DBG(("%s: crtc %d id=%d, pipe=%d active? %d\n",
__FUNCTION__, i, crtc->id, crtc->pipe, crtc->bo != NULL));
- if (crtc->bo == NULL)
+ if (crtc->bo == NULL) {
+ assert(crtc->pipe != pipe);
continue;
+ }
arg.crtc_id = crtc->id;
arg.fb_id = get_fb(sna, bo, width, height);
@@ -4044,16 +4052,16 @@ static int do_page_flip(struct sna *sna, struct kgem_bo *bo,
* completion event. All other crtc's events will be discarded.
*/
arg.user_data = (uintptr_t)data;
- arg.user_data |= crtc->pipe == ref_crtc_hw_id;
+ arg.user_data |= crtc->pipe == pipe;
arg.flags = DRM_MODE_PAGE_FLIP_EVENT;
arg.reserved = 0;
DBG(("%s: crtc %d id=%d, pipe=%d, [ref? %d] --> fb %d\n",
__FUNCTION__, i, crtc->id, crtc->pipe,
- crtc->pipe == ref_crtc_hw_id, arg.fb_id));
+ crtc->pipe == pipe, arg.fb_id));
if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_PAGE_FLIP, &arg)) {
DBG(("%s: flip [fb=%d] on crtc %d id=%d failed - %d\n",
- __FUNCTION__, arg.fb_id, i, crtc->id, crtc->pipe errno));
+ __FUNCTION__, arg.fb_id, i, crtc->id, crtc->pipe, errno));
disable:
if (count == 0)
return 0;
@@ -4080,7 +4088,7 @@ int
sna_page_flip(struct sna *sna,
struct kgem_bo *bo,
void *data,
- int ref_crtc_hw_id)
+ int pipe)
{
int count;
@@ -4099,7 +4107,7 @@ sna_page_flip(struct sna *sna,
* Also, flips queued on disabled or incorrectly configured displays
* may never complete; this is a configuration error.
*/
- count = do_page_flip(sna, bo, data, ref_crtc_hw_id);
+ count = do_page_flip(sna, bo, data, pipe);
DBG(("%s: page flipped %d crtcs\n", __FUNCTION__, count));
return count;
diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 68299b7..af1c8b5 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -877,6 +877,7 @@ inline static uint32_t pipe_select(int pipe)
static inline int sna_wait_vblank(struct sna *sna, drmVBlank *vbl, int pipe)
{
DBG(("%s(pipe=%d)\n", __FUNCTION__, pipe));
+ assert(pipe != -1);
vbl->request.type |= pipe_select(pipe);
return drmIoctl(sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, vbl);
@@ -894,6 +895,7 @@ struct sna_dri2_frame_event {
DrawablePtr draw;
ClientPtr client;
enum frame_event_type type;
+ xf86CrtcPtr crtc;
int pipe;
int count;
@@ -926,33 +928,22 @@ to_frame_event(uintptr_t data)
return (struct sna_dri2_frame_event *)(data & ~1);
}
-static int
-sna_dri2_get_pipe(DrawablePtr draw)
+static xf86CrtcPtr
+sna_dri2_get_crtc(DrawablePtr draw)
{
struct sna *sna = to_sna_from_drawable(draw);
- xf86CrtcPtr crtc;
BoxRec box;
- int pipe;
if (draw->type == DRAWABLE_PIXMAP)
- return -1;
+ return NULL;
box.x1 = draw->x;
box.y1 = draw->y;
box.x2 = box.x1 + draw->width;
box.y2 = box.y1 + draw->height;
- crtc = sna_covering_crtc(sna, &box, NULL);
-
/* Make sure the CRTC is valid and this is the real front buffer */
- pipe = -1;
- if (crtc != NULL)
- pipe = sna_crtc_to_pipe(crtc);
-
- DBG(("%s(box=((%d, %d), (%d, %d)), pipe=%d)\n",
- __FUNCTION__, box.x1, box.y1, box.x2, box.y2, pipe));
-
- return pipe;
+ return sna_covering_crtc(sna, &box, NULL);
}
static struct sna_dri2_frame_event *
@@ -1134,7 +1125,8 @@ static bool
can_flip(struct sna * sna,
DrawablePtr draw,
DRI2BufferPtr front,
- DRI2BufferPtr back)
+ DRI2BufferPtr back,
+ xf86CrtcPtr crtc)
{
WindowPtr win = (WindowPtr)draw;
PixmapPtr pixmap;
@@ -1173,6 +1165,11 @@ can_flip(struct sna * sna,
return false;
}
+ if (!sna_crtc_is_on(crtc)) {
+ DBG(("%s: ref-pipe=%d is disabled\n", __FUNCTION__, sna_crtc_to_pipe(crtc)));
+ return false;
+ }
+
pixmap = get_window_pixmap(win);
if (pixmap != sna->front) {
DBG(("%s: no, window (pixmap=%ld) is not attached to the front buffer (pixmap=%ld)\n",
@@ -1426,6 +1423,7 @@ void sna_dri2_vblank_handler(struct sna *sna, struct drm_event_vblank *event)
drmVBlank vbl;
DBG(("%s(type=%d, sequence=%d)\n", __FUNCTION__, info->type, event->sequence));
+ assert((unsigned)info->pipe < MAX_PIPES);
sna->dri2.last_swap[info->pipe].msc = event->sequence;
sna->dri2.last_swap[info->pipe].tv_sec = event->tv_sec;
sna->dri2.last_swap[info->pipe].tv_usec = event->tv_usec;
@@ -1439,7 +1437,7 @@ void sna_dri2_vblank_handler(struct sna *sna, struct drm_event_vblank *event)
switch (info->type) {
case FLIP:
/* If we can still flip... */
- if (can_flip(sna, draw, info->front, info->back) &&
+ if (can_flip(sna, draw, info->front, info->back, info->crtc) &&
sna_dri2_page_flip(sna, info))
return;
@@ -1680,7 +1678,7 @@ sna_dri2_flip_continue(struct sna *sna, struct sna_dri2_frame_event *info)
if (!info->draw)
return false;
- if (!can_flip(sna, info->draw, info->front, info->back))
+ if (!can_flip(sna, info->draw, info->front, info->back, info->crtc))
return false;
assert(sna_pixmap_get_buffer(get_drawable_pixmap(info->draw)) == info->front);
@@ -1717,7 +1715,7 @@ static void chain_flip(struct sna *sna)
assert(chain == sna_dri2_window_get_chain((WindowPtr)chain->draw));
if (chain->type == FLIP &&
- can_flip(sna, chain->draw, chain->front, chain->back) &&
+ can_flip(sna, chain->draw, chain->front, chain->back, chain->crtc) &&
sna_dri2_page_flip(sna, chain)) {
DBG(("%s: performing chained flip\n", __FUNCTION__));
} else {
@@ -1872,7 +1870,7 @@ static void sna_dri2_flip_event(struct sna *sna,
void
sna_dri2_page_flip_handler(struct sna *sna,
- struct drm_event_vblank *event)
+ struct drm_event_vblank *event)
{
struct sna_dri2_frame_event *info = to_frame_event(event->user_data);
@@ -1993,13 +1991,14 @@ static bool immediate_swap(struct sna *sna,
}
static bool
-sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw,
- DRI2BufferPtr front, DRI2BufferPtr back, int pipe,
+sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
+ DRI2BufferPtr front, DRI2BufferPtr back,
CARD64 *target_msc, CARD64 divisor, CARD64 remainder,
DRI2SwapEventPtr func, void *data)
{
struct sna *sna = to_sna_from_drawable(draw);
struct sna_dri2_frame_event *info;
+ int pipe = sna_crtc_to_pipe(crtc);
drmVBlank vbl;
CARD64 current_msc;
@@ -2045,6 +2044,7 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw,
info->event_data = data;
info->front = front;
info->back = back;
+ info->crtc = crtc;
info->pipe = pipe;
info->scanout[0].bo = ref(get_private(front)->bo);
@@ -2102,6 +2102,7 @@ out:
info->event_data = data;
info->front = front;
info->back = back;
+ info->crtc = crtc;
info->pipe = pipe;
info->type = FLIP;
@@ -2135,16 +2136,19 @@ out:
(int)divisor));
vbl.request.sequence = *target_msc - 1;
} else {
- DBG(("%s: missed target, queueing event for next: current=%d, target=%d, divisor=%d\n",
+ DBG(("%s: missed target, queueing event for next: current=%d, target=%d, divisor=%d, remainder=%d\n",
__FUNCTION__,
(int)current_msc,
(int)*target_msc,
- (int)divisor));
+ (int)divisor,
+ (int)remainder));
vbl.request.sequence = current_msc;
if (divisor)
vbl.request.sequence += remainder - current_msc % divisor;
+ DBG(("%s: initial sequence = %d\n", __FUNCTION__, vbl.request.sequence));
+
/*
* If the calculated deadline vbl.request.sequence is
* smaller than or equal to current_msc, it means
@@ -2160,6 +2164,8 @@ out:
if (vbl.request.sequence <= current_msc)
vbl.request.sequence += divisor;
+ DBG(("%s: flip adjusted sequence = %d\n", __FUNCTION__, vbl.request.sequence));
+
/* Adjust returned value for 1 frame pageflip offset */
*target_msc = vbl.reply.sequence;
}
@@ -2206,7 +2212,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
{
struct sna *sna = to_sna_from_drawable(draw);
drmVBlank vbl;
- int pipe;
+ xf86CrtcPtr crtc;
struct sna_dri2_frame_event *info = NULL;
CARD64 current_msc;
@@ -2249,16 +2255,16 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
assert(sna_pixmap_from_drawable(draw)->flush);
/* Drawable not displayed... just complete the swap */
- pipe = -1;
+ crtc = NULL;
if ((sna->flags & SNA_NO_WAIT) == 0)
- pipe = sna_dri2_get_pipe(draw);
- if (pipe == -1) {
+ crtc = sna_dri2_get_crtc(draw);
+ if (crtc == NULL) {
DBG(("%s: off-screen, immediate update\n", __FUNCTION__));
goto blit;
}
- if (can_flip(sna, draw, front, back) &&
- sna_dri2_schedule_flip(client, draw, front, back, pipe,
+ if (can_flip(sna, draw, front, back, crtc) &&
+ sna_dri2_schedule_flip(client, draw, crtc, front, back,
target_msc, divisor, remainder,
func, data))
return TRUE;
@@ -2276,7 +2282,8 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
info->event_data = data;
info->front = front;
info->back = back;
- info->pipe = pipe;
+ info->crtc = crtc;
+ info->pipe = sna_crtc_to_pipe(crtc);
sna_dri2_add_frame_event(draw, info);
sna_dri2_reference_buffer(front);
@@ -2284,7 +2291,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
info->type = SWAP;
- if (immediate_swap(sna, *target_msc, divisor, pipe, ¤t_msc)) {
+ if (immediate_swap(sna, *target_msc, divisor, info->pipe, ¤t_msc)) {
bool sync = current_msc < *target_msc;
if (!sna_dri2_immediate_blit(sna, info, sync, true))
sna_dri2_frame_event_info_free(sna, draw, info);
@@ -2354,7 +2361,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
}
}
- if (sna_wait_vblank(sna, &vbl, pipe))
+ if (sna_wait_vblank(sna, &vbl, info->pipe))
goto blit;
return TRUE;
@@ -2371,6 +2378,15 @@ skip:
return TRUE;
}
+static int sna_dri2_get_pipe(DrawablePtr draw)
+{
+ int pipe = -1;
+ xf86CrtcPtr crtc = sna_dri2_get_crtc(draw);
+ if (crtc)
+ pipe = sna_crtc_to_pipe(crtc);
+ return pipe;
+}
+
/*
* Get current frame count and frame count timestamp, based on drawable's
* crtc.
More information about the xorg-commit
mailing list