xf86-video-intel: 4 commits - src/sna/sna_dri2.c src/sna/sna_present.c test/dri2-test.c test/present-speed.c
Chris Wilson
ickle at kemper.freedesktop.org
Thu Apr 2 15:11:53 PDT 2015
src/sna/sna_dri2.c | 29 +++++----
src/sna/sna_present.c | 13 ++--
test/dri2-test.c | 48 ++++++++++-----
test/present-speed.c | 159 +++++++++++++++++++++++++++++++++++---------------
4 files changed, 171 insertions(+), 78 deletions(-)
New commits:
commit 459efa036e64bd4875b79d42bdd8416ede2223d3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Apr 2 22:50:54 2015 +0100
test/dri2: Reset swap-interval after testing async swapping
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/test/dri2-test.c b/test/dri2-test.c
index b88e65c..88c0e4c 100644
--- a/test/dri2-test.c
+++ b/test/dri2-test.c
@@ -154,6 +154,7 @@ static void run(Display *dpy, int width, int height,
XMapWindow(dpy, win);
DRI2CreateDrawable(dpy, win);
+ DRI2SwapInterval(dpy, win, 1);
start_msc = check_msc(dpy, win, 0);
buffers = DRI2GetBuffers(dpy, win, &width, &height,
commit 3c3f7d7df4cfb6e1f22fe850f3cf35c6e334b4a1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Apr 2 22:50:19 2015 +0100
test/dri2: Check vblank waits
Make sure that waiting 60 times for a vblank, 60 msc pass
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/test/dri2-test.c b/test/dri2-test.c
index d44ed99..b88e65c 100644
--- a/test/dri2-test.c
+++ b/test/dri2-test.c
@@ -105,6 +105,12 @@ static uint64_t check_msc(Display *dpy, Window win, uint64_t last_msc)
return current_msc;
}
+static void wait_next_vblank(Display *dpy, Window win)
+{
+ uint64_t msc, ust, sbc;
+ DRI2WaitMSC(dpy, win, 0, 1, 0, &ust, &msc, &sbc);
+}
+
static void swap_buffers(xcb_connection_t *c, Window win,
unsigned int *attachments, int nattachments)
{
@@ -133,7 +139,7 @@ static void run(Display *dpy, int width, int height,
int count;
DRI2Buffer *buffers;
struct timespec start, end;
- uint64_t msc;
+ uint64_t start_msc, end_msc;
/* Be nasty and install a fullscreen window on top so that we
* can guarantee we do not get clipped by children.
@@ -148,7 +154,7 @@ static void run(Display *dpy, int width, int height,
XMapWindow(dpy, win);
DRI2CreateDrawable(dpy, win);
- msc = check_msc(dpy, win, 0);
+ start_msc = check_msc(dpy, win, 0);
buffers = DRI2GetBuffers(dpy, win, &width, &height,
attachments, nattachments, &count);
@@ -156,37 +162,50 @@ static void run(Display *dpy, int width, int height,
return;
swap_buffers(c, win, attachments, nattachments);
- msc = check_msc(dpy, win, msc);
+ start_msc = check_msc(dpy, win, start_msc);
clock_gettime(CLOCK_MONOTONIC, &start);
for (count = 0; count < COUNT; count++)
swap_buffers(c, win, attachments, nattachments);
- msc = check_msc(dpy, win, msc);
+ end_msc = check_msc(dpy, win, start_msc);
clock_gettime(CLOCK_MONOTONIC, &end);
- printf("%d %s (%dx%d) swaps in %fs.\n",
- count, name, width, height, elapsed(&start, &end));
+ printf("%d [%ld] %s (%dx%d) swaps in %fs.\n",
+ count, (long)(end_msc - start_msc),
+ name, width, height, elapsed(&start, &end));
swap_buffers(c, win, attachments, nattachments);
- msc = check_msc(dpy, win, msc);
+ start_msc = check_msc(dpy, win, end_msc);
clock_gettime(CLOCK_MONOTONIC, &start);
for (count = 0; count < COUNT; count++)
dri2_copy_swap(dpy, win, width, height, nattachments == 2);
- msc = check_msc(dpy, win, msc);
+ end_msc = check_msc(dpy, win, start_msc);
clock_gettime(CLOCK_MONOTONIC, &end);
- printf("%d %s (%dx%d) blits in %fs.\n",
- count, name, width, height, elapsed(&start, &end));
+ printf("%d [%ld] %s (%dx%d) blits in %fs.\n",
+ count, (long)(end_msc - start_msc),
+ name, width, height, elapsed(&start, &end));
DRI2SwapInterval(dpy, win, 0);
swap_buffers(c, win, attachments, nattachments);
- msc = check_msc(dpy, win, msc);
+ start_msc = check_msc(dpy, win, end_msc);
clock_gettime(CLOCK_MONOTONIC, &start);
for (count = 0; count < COUNT; count++)
swap_buffers(c, win, attachments, nattachments);
- msc = check_msc(dpy, win, msc);
+ end_msc = check_msc(dpy, win, start_msc);
+ clock_gettime(CLOCK_MONOTONIC, &end);
+ printf("%d [%ld] %s (%dx%d) vblank=0 swaps in %fs.\n",
+ count, (long)(end_msc - start_msc),
+ name, width, height, elapsed(&start, &end));
+
+ start_msc = check_msc(dpy, win, end_msc);
+ clock_gettime(CLOCK_MONOTONIC, &start);
+ for (count = 0; count < COUNT; count++)
+ wait_next_vblank(dpy, win);
+ end_msc = check_msc(dpy, win, start_msc);
clock_gettime(CLOCK_MONOTONIC, &end);
- printf("%d %s (%dx%d) vblank=0 swaps in %fs.\n",
- count, name, width, height, elapsed(&start, &end));
+ printf("%d [%ld] %s waits in %fs.\n",
+ count, (long)(end_msc - start_msc),
+ name, elapsed(&start, &end));
XDestroyWindow(dpy, win);
free(buffers);
commit ef8f5236f2b7698d026be42de99cb8e7f86a4a6b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Apr 2 15:14:24 2015 +0100
sna/dri2: Fix multimonitor swap elision
We were not updating the window->crtc for the immediate swaps with the
result that after switching CRTCs, we were requesting a vblank on the
wrong pipe and triggering an error path (forcing the blit and negating
the elision).
Testcase: test/dri2-speed
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 7868d03..4eec9db 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -1450,7 +1450,10 @@ static bool add_event_to_client(struct sna_dri2_event *info, struct sna *sna, Cl
}
static struct sna_dri2_event *
-sna_dri2_add_event(struct sna *sna, DrawablePtr draw, ClientPtr client)
+sna_dri2_add_event(struct sna *sna,
+ DrawablePtr draw,
+ ClientPtr client,
+ xf86CrtcPtr crtc)
{
struct dri2_window *priv;
struct sna_dri2_event *info, *chain;
@@ -1470,8 +1473,8 @@ sna_dri2_add_event(struct sna *sna, DrawablePtr draw, ClientPtr client)
list_init(&info->cache);
info->sna = sna;
info->draw = draw;
- info->crtc = priv->crtc;
- info->pipe = sna_crtc_to_pipe(priv->crtc);
+ info->crtc = crtc;
+ info->pipe = sna_crtc_to_pipe(crtc);
if (!add_event_to_client(info, sna, client)) {
free(info);
@@ -2349,8 +2352,8 @@ sna_dri2_immediate_blit(struct sna *sna,
if (sna->flags & SNA_NO_WAIT)
sync = false;
- DBG(("%s: emitting immediate blit, throttling client, synced? %d, chained? %d\n",
- __FUNCTION__, sync, chain != info));
+ DBG(("%s: emitting immediate blit, throttling client, synced? %d, chained? %d, pipe %d\n",
+ __FUNCTION__, sync, chain != info, info->pipe));
info->type = SWAP_THROTTLE;
info->sync = sync;
@@ -2557,13 +2560,15 @@ static uint64_t
get_current_msc(struct sna *sna, DrawablePtr draw, xf86CrtcPtr crtc)
{
union drm_wait_vblank vbl;
- uint64_t ret = -1;
+ uint64_t ret;
VG_CLEAR(vbl);
vbl.request.type = _DRM_VBLANK_RELATIVE;
vbl.request.sequence = 0;
if (sna_wait_vblank(sna, &vbl, sna_crtc_to_pipe(crtc)) == 0)
ret = sna_crtc_record_vblank(crtc, &vbl);
+ else
+ ret = sna_crtc_last_swap(crtc)->msc;
return draw_current_msc(draw, crtc, ret);
}
@@ -2703,7 +2708,7 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
goto new_back;
}
- info = sna_dri2_add_event(sna, draw, client);
+ info = sna_dri2_add_event(sna, draw, client, crtc);
if (info == NULL)
return false;
@@ -2761,7 +2766,7 @@ queue:
info->keepalive = 1;
}
- info = sna_dri2_add_event(sna, draw, client);
+ info = sna_dri2_add_event(sna, draw, client, crtc);
if (info == NULL)
return false;
@@ -2823,7 +2828,7 @@ sna_dri2_schedule_xchg(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
if (sync) {
struct sna_dri2_event *info;
- info = sna_dri2_add_event(sna, draw, client);
+ info = sna_dri2_add_event(sna, draw, client, crtc);
if (!info)
goto complete;
@@ -2885,7 +2890,7 @@ sna_dri2_schedule_xchg_crtc(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc
if (sync) {
struct sna_dri2_event *info;
- info = sna_dri2_add_event(sna, draw, client);
+ info = sna_dri2_add_event(sna, draw, client, crtc);
if (!info)
goto complete;
@@ -3067,7 +3072,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
VG_CLEAR(vbl);
- info = sna_dri2_add_event(sna, draw, client);
+ info = sna_dri2_add_event(sna, draw, client, crtc);
if (!info)
goto blit;
@@ -3218,7 +3223,7 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
if (divisor == 0 && current_msc >= target_msc)
goto out_complete;
- info = sna_dri2_add_event(sna, draw, client);
+ info = sna_dri2_add_event(sna, draw, client, crtc);
if (!info)
goto out_complete;
diff --git a/src/sna/sna_present.c b/src/sna/sna_present.c
index 1992b9b..912bbe7 100644
--- a/src/sna/sna_present.c
+++ b/src/sna/sna_present.c
@@ -178,7 +178,7 @@ static bool sna_fake_vblank(struct sna_present_event *info)
delay = 0;
DBG(("%s(event=%lld, target_msc=%lld, msc=%lld, delay=%ums)\n",
- __FUNCTION__, (long long)info->event_id[0], (long long)info->target_msc, msc, delay));
+ __FUNCTION__, (long long)info->event_id[0], (long long)info->target_msc, (long long)msc, delay));
if (delay == 0) {
const struct ust_msc *swap = sna_crtc_last_swap(info->crtc);
present_event_notify(info->event_id[0], swap_ust(swap), swap->msc);
@@ -197,7 +197,10 @@ sna_present_get_crtc(WindowPtr window)
BoxRec box;
xf86CrtcPtr crtc;
- DBG(("%s\n", __FUNCTION__));
+ DBG(("%s: window=%ld (pixmap=%ld), box=(%d, %d)x(%d, %d)\n",
+ __FUNCTION__, window->drawable.id, get_window_pixmap(window)->drawable.serialNumber,
+ window->drawable.x, window->drawable.y,
+ window->drawable.width, window->drawable.height));
box.x1 = window->drawable.x;
box.y1 = window->drawable.y;
@@ -440,9 +443,9 @@ flip__async(struct sna *sna,
return FALSE;
}
- DBG(("%s: pipe=%d tv=%d.%06d msc=%lld (target=%lld), event=%lld complete\n", __FUNCTION__,
+ DBG(("%s: pipe=%d tv=%ld.%06d msc=%lld (target=%lld), event=%lld complete\n", __FUNCTION__,
pipe_from_crtc(crtc),
- gettime_ust64() / 1000000, gettime_ust64() % 1000000,
+ (long)(gettime_ust64() / 1000000), (int)(gettime_ust64() % 1000000),
crtc ? (long long)sna_crtc_last_swap(crtc->devPrivate)->msc : 0LL,
(long long)target_msc, (long long)event_id));
present_event_notify(event_id, gettime_ust64(), target_msc);
@@ -474,7 +477,7 @@ present_flip_handler(struct drm_event_vblank *event, void *data)
present_event_notify(info->event_id[0], swap_ust(&swap), swap.msc);
if (info->sna->present.unflip) {
- DBG(("%s: executing queued unflip (event=%lld)\n", __FUNCTION__, info->sna->present.unflip));
+ DBG(("%s: executing queued unflip (event=%lld)\n", __FUNCTION__, (long long)info->sna->present.unflip));
sna_present_unflip(xf86ScrnToScreen(info->sna->scrn),
info->sna->present.unflip);
info->sna->present.unflip = 0;
commit 0814dc41c3fa23c1d6d20f5696a9fb87671ae0c7
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Apr 2 15:13:43 2015 +0100
test/present-speed: Include a measure for fence signalling overhead
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/test/present-speed.c b/test/present-speed.c
index 1d3411b..60add81 100644
--- a/test/present-speed.c
+++ b/test/present-speed.c
@@ -37,6 +37,7 @@
#include <X11/extensions/Xrandr.h>
#include <xcb/xcb.h>
#include <xcb/present.h>
+#include <xcb/dri3.h>
#include <xf86drm.h>
#include <i915_drm.h>
@@ -49,6 +50,8 @@
#include <setjmp.h>
#include <signal.h>
+#include "dri3.h"
+
static int _x_error_occurred;
static uint32_t stamp;
@@ -86,12 +89,13 @@ static double elapsed(const struct timespec *start,
return 1e6*(end->tv_sec - start->tv_sec) + (end->tv_nsec - start->tv_nsec)/1000;
}
-static void run(Display *dpy, Window win, const char *name)
+static void run(Display *dpy, Window win, const char *name, int use_dri3)
{
xcb_connection_t *c = XGetXCBConnection(dpy);
struct timespec start, end;
Pixmap pixmap[4];
int busy[4];
+ struct dri3_fence fence[4];
Window root;
unsigned int width, height;
unsigned border, depth;
@@ -106,6 +110,12 @@ static void run(Display *dpy, Window win, const char *name)
for (n = 0; n < 4; n++) {
pixmap[n] = XCreatePixmap(dpy, win, width, height, depth);
+ if (use_dri3) {
+ if (dri3_create_fence(dpy, win, &fence[n]))
+ return;
+ /* start idle */
+ xshmfence_trigger(fence[n].addr);
+ }
busy[n] = 0;
}
@@ -143,35 +153,43 @@ static void run(Display *dpy, Window win, const char *name)
back = j;
busy[back] = 1;
-
- xcb_present_pixmap(c, win, p, back++,
+ if (use_dri3) {
+ xshmfence_await(fence[back].addr);
+ xshmfence_reset(fence[back].addr);
+ }
+ xcb_present_pixmap(c, win, p, back,
0, /* valid */
0, /* update */
0, /* x_off */
0, /* y_off */
None,
None, /* wait fence */
- None,
+ use_dri3 ? fence[back].xid : None,
XCB_PRESENT_OPTION_ASYNC,
0, /* target msc */
0, /* divisor */
0, /* remainder */
0, NULL);
xcb_flush(c);
+ back++;
}
clock_gettime(CLOCK_MONOTONIC, &end);
} while (end.tv_sec < start.tv_sec + 10);
- for (n = 0; n < 4; n++)
+ for (n = 0; n < 4; n++) {
+ if (use_dri3)
+ dri3_fence_free(dpy, &fence[n]);
XFreePixmap(dpy, pixmap[n]);
+ }
XSync(dpy, True);
teardown_msc(dpy, Q);
if (_x_error_occurred)
abort();
- printf("%s: Completed %d presents in %.1fs, %.3fus each (%.1f FPS)\n",
- name, completed, elapsed(&start, &end) / 1000000,
+ printf("%s%s: Completed %d presents in %.1fs, %.3fus each (%.1f FPS)\n",
+ name, use_dri3 ? " (dri3)" : "",
+ completed, elapsed(&start, &end) / 1000000,
elapsed(&start, &end) / completed,
completed / (elapsed(&start, &end) / 1000000));
}
@@ -198,6 +216,45 @@ static int has_present(Display *dpy)
return 1;
}
+static int dri3_query_version(Display *dpy, int *major, int *minor)
+{
+ xcb_connection_t *c = XGetXCBConnection(dpy);
+ xcb_dri3_query_version_reply_t *reply;
+ xcb_generic_error_t *error;
+
+ *major = *minor = -1;
+
+ reply = xcb_dri3_query_version_reply(c,
+ xcb_dri3_query_version(c,
+ XCB_DRI3_MAJOR_VERSION,
+ XCB_DRI3_MINOR_VERSION),
+ &error);
+ free(error);
+ if (reply == NULL)
+ return -1;
+
+ *major = reply->major_version;
+ *minor = reply->minor_version;
+ free(reply);
+
+ return 0;
+}
+
+static int has_dri3(Display *dpy)
+{
+ const xcb_query_extension_reply_t *ext;
+ int major, minor;
+
+ ext = xcb_get_extension_data(XGetXCBConnection(dpy), &xcb_dri3_id);
+ if (ext == NULL || !ext->present)
+ return 0;
+
+ if (dri3_query_version(dpy, &major, &minor) < 0)
+ return 0;
+
+ return major >= 0;
+}
+
static inline XRRScreenResources *_XRRGetScreenResourcesCurrent(Display *dpy, Window window)
{
XRRScreenResources *res;
@@ -230,48 +287,16 @@ static void fullscreen(Display *dpy, Window win)
(unsigned char *)&atom, 1);
}
-int main(void)
+static void loop(Display *dpy, XRRScreenResources *res, int use_dri3)
{
- Display *dpy;
- Window root, win;
- XRRScreenResources *res;
- XRRCrtcInfo **original_crtc;
+ Window root = DefaultRootWindow(dpy);
+ Window win;
XSetWindowAttributes attr;
int i, j;
attr.override_redirect = 1;
- dpy = XOpenDisplay(NULL);
- if (dpy == NULL)
- return 77;
-
- if (!has_present(dpy))
- return 77;
-
- if (DPMSQueryExtension(dpy, &i, &i))
- DPMSDisable(dpy);
-
- root = DefaultRootWindow(dpy);
-
- signal(SIGALRM, SIG_IGN);
- XSetErrorHandler(_check_error_handler);
-
- res = NULL;
- if (XRRQueryVersion(dpy, &i, &i))
- res = _XRRGetScreenResourcesCurrent(dpy, root);
- if (res == NULL)
- return 77;
-
- original_crtc = malloc(sizeof(XRRCrtcInfo *)*res->ncrtc);
- for (i = 0; i < res->ncrtc; i++)
- original_crtc[i] = XRRGetCrtcInfo(dpy, res, res->crtcs[i]);
-
- printf("noutput=%d, ncrtc=%d\n", res->noutput, res->ncrtc);
- for (i = 0; i < res->ncrtc; i++)
- XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
- 0, 0, None, RR_Rotate_0, NULL, 0);
-
- run(dpy, root, "off");
+ run(dpy, root, "off", use_dri3);
for (i = 0; i < res->noutput; i++) {
XRROutputInfo *output;
@@ -296,7 +321,7 @@ int main(void)
XRRSetCrtcConfig(dpy, res, output->crtcs[c], CurrentTime,
0, 0, output->modes[0], RR_Rotate_0, &res->outputs[i], 1);
- run(dpy, root, "root");
+ run(dpy, root, "root", use_dri3);
win = XCreateWindow(dpy, root,
0, 0, mode->width, mode->height, 0,
@@ -306,7 +331,7 @@ int main(void)
CWOverrideRedirect, &attr);
fullscreen(dpy, win);
XMapWindow(dpy, win);
- run(dpy, win, "fullscreen");
+ run(dpy, win, "fullscreen", use_dri3);
XDestroyWindow(dpy, win);
win = XCreateWindow(dpy, root,
@@ -316,7 +341,7 @@ int main(void)
DefaultVisual(dpy, DefaultScreen(dpy)),
CWOverrideRedirect, &attr);
XMapWindow(dpy, win);
- run(dpy, win, "windowed");
+ run(dpy, win, "windowed", use_dri3);
XDestroyWindow(dpy, win);
win = XCreateWindow(dpy, root,
@@ -326,7 +351,7 @@ int main(void)
DefaultVisual(dpy, DefaultScreen(dpy)),
CWOverrideRedirect, &attr);
XMapWindow(dpy, win);
- run(dpy, win, "half");
+ run(dpy, win, "half", use_dri3);
XDestroyWindow(dpy, win);
XRRSetCrtcConfig(dpy, res, output->crtcs[c], CurrentTime,
@@ -335,6 +360,46 @@ int main(void)
XRRFreeOutputInfo(output);
}
+}
+
+int main(void)
+{
+ Display *dpy;
+ XRRScreenResources *res;
+ XRRCrtcInfo **original_crtc;
+ int i;
+
+ dpy = XOpenDisplay(NULL);
+ if (dpy == NULL)
+ return 77;
+
+ if (!has_present(dpy))
+ return 77;
+
+ if (DPMSQueryExtension(dpy, &i, &i))
+ DPMSDisable(dpy);
+
+ signal(SIGALRM, SIG_IGN);
+ XSetErrorHandler(_check_error_handler);
+
+ res = NULL;
+ if (XRRQueryVersion(dpy, &i, &i))
+ res = _XRRGetScreenResourcesCurrent(dpy, DefaultRootWindow(dpy));
+ if (res == NULL)
+ return 77;
+
+ original_crtc = malloc(sizeof(XRRCrtcInfo *)*res->ncrtc);
+ for (i = 0; i < res->ncrtc; i++)
+ original_crtc[i] = XRRGetCrtcInfo(dpy, res, res->crtcs[i]);
+
+ printf("noutput=%d, ncrtc=%d\n", res->noutput, res->ncrtc);
+ for (i = 0; i < res->ncrtc; i++)
+ XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
+ 0, 0, None, RR_Rotate_0, NULL, 0);
+
+ loop(dpy, res, 0);
+ if (has_dri3(dpy))
+ loop(dpy, res, 1);
for (i = 0; i < res->ncrtc; i++)
XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
More information about the xorg-commit
mailing list