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; 1942542f5fSchristos w = XCreateWindow(t->dpy, DefaultRootWindow(t->dpy), 2042542f5fSchristos 0, 0, t->width, t->height, 0, 2142542f5fSchristos DefaultDepth(t->dpy, DefaultScreen(t->dpy)), 2242542f5fSchristos InputOutput, 2342542f5fSchristos DefaultVisual(t->dpy, DefaultScreen(t->dpy)), 2442542f5fSchristos CWOverrideRedirect, &attr); 2503b705cfSriastradh XMapWindow(t->dpy, w); 2603b705cfSriastradh 2703b705cfSriastradh return w; 2803b705cfSriastradh} 2903b705cfSriastradh 3042542f5fSchristosstatic Display *out_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) 5542542f5fSchristos die("unable to open out 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{ 10042542f5fSchristos int major, minor; 10103b705cfSriastradh int size; 10203b705cfSriastradh 10342542f5fSchristos XShmQueryVersion(d->dpy, &major, &minor, &d->has_shm_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))); 12842542f5fSchristos dpy->depth = DefaultDepth(dpy->dpy, DefaultScreen(dpy->dpy)); 12903b705cfSriastradh} 13003b705cfSriastradh 13103b705cfSriastradhstatic void test_get_displays(int argc, char **argv, 13242542f5fSchristos struct test_display *out, 13303b705cfSriastradh struct test_display *ref) 13403b705cfSriastradh{ 13542542f5fSchristos out->dpy = out_display(argc, argv); 13642542f5fSchristos default_setup(out); 13742542f5fSchristos shm_setup(out); 13842542f5fSchristos out->root = get_root(out); 13942542f5fSchristos out->target = OUT; 14003b705cfSriastradh 14142542f5fSchristos ref->dpy = ref_display(out->width, out->height, out->depth); 14203b705cfSriastradh default_setup(ref); 14303b705cfSriastradh shm_setup(ref); 14403b705cfSriastradh ref->root = get_root(ref); 14542542f5fSchristos ref->target = REF; 14603b705cfSriastradh} 14703b705cfSriastradh 14803b705cfSriastradhvoid test_init(struct test *test, int argc, char **argv) 14903b705cfSriastradh{ 15003b705cfSriastradh memset(test, 0, sizeof(*test)); 15142542f5fSchristos test_get_displays(argc, argv, &test->out, &test->ref); 15203b705cfSriastradh} 15303b705cfSriastradh 15403b705cfSriastradhvoid test_timer_start(struct test_display *t, struct timespec *tv) 15503b705cfSriastradh{ 15603b705cfSriastradh clock_gettime(CLOCK_MONOTONIC, tv); 15703b705cfSriastradh} 15803b705cfSriastradh 15903b705cfSriastradhdouble test_timer_stop(struct test_display *t, struct timespec *tv) 16003b705cfSriastradh{ 16103b705cfSriastradh XImage *image; 16203b705cfSriastradh struct timespec now; 16303b705cfSriastradh 16403b705cfSriastradh image = XGetImage(t->dpy, t->root, 0, 0, 1, 1, AllPlanes, ZPixmap); 16503b705cfSriastradh clock_gettime(CLOCK_MONOTONIC, &now); 16603b705cfSriastradh XDestroyImage(image); 16703b705cfSriastradh 16803b705cfSriastradh return (now.tv_sec - tv->tv_sec) + 1e-9*(now.tv_nsec - tv->tv_nsec); 16903b705cfSriastradh} 170