test_display.c revision 03b705cf
103b705cfSriastradh#include <stdio.h> 203b705cfSriastradh#include <stdlib.h> 303b705cfSriastradh#include <string.h> 403b705cfSriastradh#include <unistd.h> 503b705cfSriastradh#include <sys/ipc.h> 603b705cfSriastradh#include <sys/shm.h> 703b705cfSriastradh 803b705cfSriastradh#include "test.h" 903b705cfSriastradh 1003b705cfSriastradhstatic Window get_root(struct test_display *t) 1103b705cfSriastradh{ 1203b705cfSriastradh XSetWindowAttributes attr; 1303b705cfSriastradh Window w; 1403b705cfSriastradh 1503b705cfSriastradh /* Be nasty and install a fullscreen window on top so that we 1603b705cfSriastradh * can guarantee we do not get clipped by children. 1703b705cfSriastradh */ 1803b705cfSriastradh attr.override_redirect = 1; 1903b705cfSriastradh w= XCreateWindow(t->dpy, DefaultRootWindow(t->dpy), 2003b705cfSriastradh 0, 0, t->width, t->height, 0, 2103b705cfSriastradh DefaultDepth(t->dpy, DefaultScreen(t->dpy)), 2203b705cfSriastradh InputOutput, 2303b705cfSriastradh DefaultVisual(t->dpy, DefaultScreen(t->dpy)), 2403b705cfSriastradh CWOverrideRedirect, &attr); 2503b705cfSriastradh XMapWindow(t->dpy, w); 2603b705cfSriastradh 2703b705cfSriastradh return w; 2803b705cfSriastradh} 2903b705cfSriastradh 3003b705cfSriastradhstatic Display *real_display(int argc, char **argv) 3103b705cfSriastradh{ 3203b705cfSriastradh Display *dpy; 3303b705cfSriastradh const char *name = NULL; 3403b705cfSriastradh int i; 3503b705cfSriastradh 3603b705cfSriastradh for (i = 0; i < argc; i++) { 3703b705cfSriastradh if (strncmp(argv[i], "-d", 2) == 0) { 3803b705cfSriastradh if (argv[i][2] == '\0') { 3903b705cfSriastradh if (i+1 < argc) { 4003b705cfSriastradh name = argv[i+1]; 4103b705cfSriastradh i++; 4203b705cfSriastradh } 4303b705cfSriastradh } else 4403b705cfSriastradh name = argv[i] + 2; 4503b705cfSriastradh } 4603b705cfSriastradh } 4703b705cfSriastradh 4803b705cfSriastradh if (name == NULL) 4903b705cfSriastradh name = getenv("DISPLAY"); 5003b705cfSriastradh if (name == NULL) 5103b705cfSriastradh name = ":0"; /* useful default */ 5203b705cfSriastradh 5303b705cfSriastradh dpy = XOpenDisplay(name); 5403b705cfSriastradh if (dpy == NULL) 5503b705cfSriastradh die("unable to open real display %s\n", name); 5603b705cfSriastradh 5703b705cfSriastradh printf("Opened connection to %s for testing.\n", name); 5803b705cfSriastradh return dpy; 5903b705cfSriastradh} 6003b705cfSriastradh 6103b705cfSriastradhstatic Display *ref_display(int width, int height, int depth) 6203b705cfSriastradh{ 6303b705cfSriastradh Display *dpy; 6403b705cfSriastradh char buf[160]; 6503b705cfSriastradh const char *name; 6603b705cfSriastradh int try; 6703b705cfSriastradh 6803b705cfSriastradh name = getenv("REF_DISPLAY"); 6903b705cfSriastradh if (name) { 7003b705cfSriastradh dpy = XOpenDisplay(name); 7103b705cfSriastradh if (dpy == NULL) 7203b705cfSriastradh die("unable to open reference display %s\n", name); 7303b705cfSriastradh 7403b705cfSriastradh printf("Opened connection to %s for reference.\n", name); 7503b705cfSriastradh return dpy; 7603b705cfSriastradh } 7703b705cfSriastradh 7803b705cfSriastradh snprintf(buf, sizeof(buf), 7903b705cfSriastradh "Xvfb -ac -terminate -screen 0 %dx%dx%d :99 >/dev/null 2>&1 &", 8003b705cfSriastradh width, height, depth); 8103b705cfSriastradh if (system(buf)) 8203b705cfSriastradh die("unable to spawn '%s' for reference display\n", buf); 8303b705cfSriastradh 8403b705cfSriastradh try = 0; 8503b705cfSriastradh while (try++ < 1000) { 8603b705cfSriastradh dpy = XOpenDisplay(":99"); 8703b705cfSriastradh if (dpy) 8803b705cfSriastradh break; 8903b705cfSriastradh usleep(1000); 9003b705cfSriastradh } 9103b705cfSriastradh 9203b705cfSriastradh if (dpy == NULL) 9303b705cfSriastradh die("unable to open reference display\n"); 9403b705cfSriastradh 9503b705cfSriastradh return dpy; 9603b705cfSriastradh} 9703b705cfSriastradh 9803b705cfSriastradhstatic void shm_setup(struct test_display *d) 9903b705cfSriastradh{ 10003b705cfSriastradh int major, minor, has_pixmaps; 10103b705cfSriastradh int size; 10203b705cfSriastradh 10303b705cfSriastradh XShmQueryVersion(d->dpy, &major, &minor, &has_pixmaps); 10403b705cfSriastradh if (major == 0 && minor == 0) 10503b705cfSriastradh die("XSHM not supported\n"); 10603b705cfSriastradh 10703b705cfSriastradh size = d->width * d->height * 4; 10803b705cfSriastradh d->max_shm_size = size; 10903b705cfSriastradh 11003b705cfSriastradh d->shm.shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0600); 11103b705cfSriastradh if (d->shm.shmid == -1) 11203b705cfSriastradh die("failed to allocated %d bytes for a shm segment\n", size); 11303b705cfSriastradh 11403b705cfSriastradh d->shm.shmaddr = shmat(d->shm.shmid, NULL, 0); 11503b705cfSriastradh d->shm.readOnly = 0; 11603b705cfSriastradh XShmAttach(d->dpy, &d->shm); 11703b705cfSriastradh XSync(d->dpy, 1); 11803b705cfSriastradh} 11903b705cfSriastradh 12003b705cfSriastradhstatic void default_setup(struct test_display *dpy) 12103b705cfSriastradh{ 12203b705cfSriastradh dpy->width = WidthOfScreen(DefaultScreenOfDisplay(dpy->dpy)); 12303b705cfSriastradh dpy->height = HeightOfScreen(DefaultScreenOfDisplay(dpy->dpy)); 12403b705cfSriastradh dpy->format = 12503b705cfSriastradh XRenderFindVisualFormat(dpy->dpy, 12603b705cfSriastradh DefaultVisual(dpy->dpy, 12703b705cfSriastradh DefaultScreen(dpy->dpy))); 12803b705cfSriastradh} 12903b705cfSriastradh 13003b705cfSriastradhstatic void test_get_displays(int argc, char **argv, 13103b705cfSriastradh struct test_display *real, 13203b705cfSriastradh struct test_display *ref) 13303b705cfSriastradh{ 13403b705cfSriastradh real->dpy = real_display(argc, argv); 13503b705cfSriastradh default_setup(real); 13603b705cfSriastradh shm_setup(real); 13703b705cfSriastradh real->root = get_root(real); 13803b705cfSriastradh 13903b705cfSriastradh ref->dpy = ref_display(real->width, real->height, 14003b705cfSriastradh DefaultDepth(real->dpy, DefaultScreen(real->dpy))); 14103b705cfSriastradh default_setup(ref); 14203b705cfSriastradh shm_setup(ref); 14303b705cfSriastradh ref->root = get_root(ref); 14403b705cfSriastradh} 14503b705cfSriastradh 14603b705cfSriastradhvoid test_init(struct test *test, int argc, char **argv) 14703b705cfSriastradh{ 14803b705cfSriastradh memset(test, 0, sizeof(*test)); 14903b705cfSriastradh test_get_displays(argc, argv, &test->real, &test->ref); 15003b705cfSriastradh} 15103b705cfSriastradh 15203b705cfSriastradhvoid test_timer_start(struct test_display *t, struct timespec *tv) 15303b705cfSriastradh{ 15403b705cfSriastradh clock_gettime(CLOCK_MONOTONIC, tv); 15503b705cfSriastradh} 15603b705cfSriastradh 15703b705cfSriastradhdouble test_timer_stop(struct test_display *t, struct timespec *tv) 15803b705cfSriastradh{ 15903b705cfSriastradh XImage *image; 16003b705cfSriastradh struct timespec now; 16103b705cfSriastradh 16203b705cfSriastradh image = XGetImage(t->dpy, t->root, 0, 0, 1, 1, AllPlanes, ZPixmap); 16303b705cfSriastradh clock_gettime(CLOCK_MONOTONIC, &now); 16403b705cfSriastradh XDestroyImage(image); 16503b705cfSriastradh 16603b705cfSriastradh return (now.tv_sec - tv->tv_sec) + 1e-9*(now.tv_nsec - tv->tv_nsec); 16703b705cfSriastradh} 168