1428d7b3dSmrg#include <stdio.h> 2428d7b3dSmrg#include <stdlib.h> 3428d7b3dSmrg#include <string.h> 4428d7b3dSmrg#include <unistd.h> 5428d7b3dSmrg#include <sys/ipc.h> 6428d7b3dSmrg#include <sys/shm.h> 7428d7b3dSmrg 8428d7b3dSmrg#include "test.h" 9428d7b3dSmrg 10428d7b3dSmrgstatic Window get_root(struct test_display *t) 11428d7b3dSmrg{ 12428d7b3dSmrg XSetWindowAttributes attr; 13428d7b3dSmrg Window w; 14428d7b3dSmrg 15428d7b3dSmrg /* Be nasty and install a fullscreen window on top so that we 16428d7b3dSmrg * can guarantee we do not get clipped by children. 17428d7b3dSmrg */ 18428d7b3dSmrg attr.override_redirect = 1; 19428d7b3dSmrg w = XCreateWindow(t->dpy, DefaultRootWindow(t->dpy), 20428d7b3dSmrg 0, 0, t->width, t->height, 0, 21428d7b3dSmrg DefaultDepth(t->dpy, DefaultScreen(t->dpy)), 22428d7b3dSmrg InputOutput, 23428d7b3dSmrg DefaultVisual(t->dpy, DefaultScreen(t->dpy)), 24428d7b3dSmrg CWOverrideRedirect, &attr); 25428d7b3dSmrg XMapWindow(t->dpy, w); 26428d7b3dSmrg 27428d7b3dSmrg return w; 28428d7b3dSmrg} 29428d7b3dSmrg 30428d7b3dSmrgstatic Display *out_display(int argc, char **argv) 31428d7b3dSmrg{ 32428d7b3dSmrg Display *dpy; 33428d7b3dSmrg const char *name = NULL; 34428d7b3dSmrg int i; 35428d7b3dSmrg 36428d7b3dSmrg for (i = 0; i < argc; i++) { 37428d7b3dSmrg if (strncmp(argv[i], "-d", 2) == 0) { 38428d7b3dSmrg if (argv[i][2] == '\0') { 39428d7b3dSmrg if (i+1 < argc) { 40428d7b3dSmrg name = argv[i+1]; 41428d7b3dSmrg i++; 42428d7b3dSmrg } 43428d7b3dSmrg } else 44428d7b3dSmrg name = argv[i] + 2; 45428d7b3dSmrg } 46428d7b3dSmrg } 47428d7b3dSmrg 48428d7b3dSmrg if (name == NULL) 49428d7b3dSmrg name = getenv("DISPLAY"); 50428d7b3dSmrg if (name == NULL) 51428d7b3dSmrg name = ":0"; /* useful default */ 52428d7b3dSmrg 53428d7b3dSmrg dpy = XOpenDisplay(name); 54428d7b3dSmrg if (dpy == NULL) 55428d7b3dSmrg die("unable to open out display %s\n", name); 56428d7b3dSmrg 57428d7b3dSmrg printf("Opened connection to %s for testing.\n", name); 58428d7b3dSmrg return dpy; 59428d7b3dSmrg} 60428d7b3dSmrg 61428d7b3dSmrgstatic Display *ref_display(int width, int height, int depth) 62428d7b3dSmrg{ 63428d7b3dSmrg Display *dpy; 64428d7b3dSmrg char buf[160]; 65428d7b3dSmrg const char *name; 66428d7b3dSmrg int try; 67428d7b3dSmrg 68428d7b3dSmrg name = getenv("REF_DISPLAY"); 69428d7b3dSmrg if (name) { 70428d7b3dSmrg dpy = XOpenDisplay(name); 71428d7b3dSmrg if (dpy == NULL) 72428d7b3dSmrg die("unable to open reference display %s\n", name); 73428d7b3dSmrg 74428d7b3dSmrg printf("Opened connection to %s for reference.\n", name); 75428d7b3dSmrg return dpy; 76428d7b3dSmrg } 77428d7b3dSmrg 78428d7b3dSmrg snprintf(buf, sizeof(buf), 79428d7b3dSmrg "Xvfb -ac -terminate -screen 0 %dx%dx%d :99 >/dev/null 2>&1 &", 80428d7b3dSmrg width, height, depth); 81428d7b3dSmrg if (system(buf)) 82428d7b3dSmrg die("unable to spawn '%s' for reference display\n", buf); 83428d7b3dSmrg 84428d7b3dSmrg try = 0; 85428d7b3dSmrg while (try++ < 1000) { 86428d7b3dSmrg dpy = XOpenDisplay(":99"); 87428d7b3dSmrg if (dpy) 88428d7b3dSmrg break; 89428d7b3dSmrg usleep(1000); 90428d7b3dSmrg } 91428d7b3dSmrg 92428d7b3dSmrg if (dpy == NULL) 93428d7b3dSmrg die("unable to open reference display\n"); 94428d7b3dSmrg 95428d7b3dSmrg return dpy; 96428d7b3dSmrg} 97428d7b3dSmrg 98428d7b3dSmrgstatic void shm_setup(struct test_display *d) 99428d7b3dSmrg{ 100428d7b3dSmrg int major, minor; 101428d7b3dSmrg int size; 102428d7b3dSmrg 103428d7b3dSmrg XShmQueryVersion(d->dpy, &major, &minor, &d->has_shm_pixmaps); 104428d7b3dSmrg if (major == 0 && minor == 0) 105428d7b3dSmrg die("XSHM not supported\n"); 106428d7b3dSmrg 107428d7b3dSmrg size = d->width * d->height * 4; 108428d7b3dSmrg d->max_shm_size = size; 109428d7b3dSmrg 110428d7b3dSmrg d->shm.shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0600); 111428d7b3dSmrg if (d->shm.shmid == -1) 112428d7b3dSmrg die("failed to allocated %d bytes for a shm segment\n", size); 113428d7b3dSmrg 114428d7b3dSmrg d->shm.shmaddr = shmat(d->shm.shmid, NULL, 0); 115428d7b3dSmrg d->shm.readOnly = 0; 116428d7b3dSmrg XShmAttach(d->dpy, &d->shm); 117428d7b3dSmrg XSync(d->dpy, 1); 118428d7b3dSmrg} 119428d7b3dSmrg 120428d7b3dSmrgstatic void default_setup(struct test_display *dpy) 121428d7b3dSmrg{ 122428d7b3dSmrg dpy->width = WidthOfScreen(DefaultScreenOfDisplay(dpy->dpy)); 123428d7b3dSmrg dpy->height = HeightOfScreen(DefaultScreenOfDisplay(dpy->dpy)); 124428d7b3dSmrg dpy->format = 125428d7b3dSmrg XRenderFindVisualFormat(dpy->dpy, 126428d7b3dSmrg DefaultVisual(dpy->dpy, 127428d7b3dSmrg DefaultScreen(dpy->dpy))); 128428d7b3dSmrg dpy->depth = DefaultDepth(dpy->dpy, DefaultScreen(dpy->dpy)); 129428d7b3dSmrg} 130428d7b3dSmrg 131428d7b3dSmrgstatic void test_get_displays(int argc, char **argv, 132428d7b3dSmrg struct test_display *out, 133428d7b3dSmrg struct test_display *ref) 134428d7b3dSmrg{ 135428d7b3dSmrg out->dpy = out_display(argc, argv); 136428d7b3dSmrg default_setup(out); 137428d7b3dSmrg shm_setup(out); 138428d7b3dSmrg out->root = get_root(out); 139428d7b3dSmrg out->target = OUT; 140428d7b3dSmrg 141428d7b3dSmrg ref->dpy = ref_display(out->width, out->height, out->depth); 142428d7b3dSmrg default_setup(ref); 143428d7b3dSmrg shm_setup(ref); 144428d7b3dSmrg ref->root = get_root(ref); 145428d7b3dSmrg ref->target = REF; 146428d7b3dSmrg} 147428d7b3dSmrg 148428d7b3dSmrgvoid test_init(struct test *test, int argc, char **argv) 149428d7b3dSmrg{ 150428d7b3dSmrg memset(test, 0, sizeof(*test)); 151428d7b3dSmrg test_get_displays(argc, argv, &test->out, &test->ref); 152428d7b3dSmrg} 153428d7b3dSmrg 154428d7b3dSmrgvoid test_timer_start(struct test_display *t, struct timespec *tv) 155428d7b3dSmrg{ 156428d7b3dSmrg clock_gettime(CLOCK_MONOTONIC, tv); 157428d7b3dSmrg} 158428d7b3dSmrg 159428d7b3dSmrgdouble test_timer_stop(struct test_display *t, struct timespec *tv) 160428d7b3dSmrg{ 161428d7b3dSmrg XImage *image; 162428d7b3dSmrg struct timespec now; 163428d7b3dSmrg 164428d7b3dSmrg image = XGetImage(t->dpy, t->root, 0, 0, 1, 1, AllPlanes, ZPixmap); 165428d7b3dSmrg clock_gettime(CLOCK_MONOTONIC, &now); 166428d7b3dSmrg XDestroyImage(image); 167428d7b3dSmrg 168428d7b3dSmrg return (now.tv_sec - tv->tv_sec) + 1e-9*(now.tv_nsec - tv->tv_nsec); 169428d7b3dSmrg} 170