1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4#include <unistd.h> 5#include <sys/ipc.h> 6#include <sys/shm.h> 7 8#include "test.h" 9 10static Window get_root(struct test_display *t) 11{ 12 XSetWindowAttributes attr; 13 Window w; 14 15 /* Be nasty and install a fullscreen window on top so that we 16 * can guarantee we do not get clipped by children. 17 */ 18 attr.override_redirect = 1; 19 w = XCreateWindow(t->dpy, DefaultRootWindow(t->dpy), 20 0, 0, t->width, t->height, 0, 21 DefaultDepth(t->dpy, DefaultScreen(t->dpy)), 22 InputOutput, 23 DefaultVisual(t->dpy, DefaultScreen(t->dpy)), 24 CWOverrideRedirect, &attr); 25 XMapWindow(t->dpy, w); 26 27 return w; 28} 29 30static Display *out_display(int argc, char **argv) 31{ 32 Display *dpy; 33 const char *name = NULL; 34 int i; 35 36 for (i = 0; i < argc; i++) { 37 if (strncmp(argv[i], "-d", 2) == 0) { 38 if (argv[i][2] == '\0') { 39 if (i+1 < argc) { 40 name = argv[i+1]; 41 i++; 42 } 43 } else 44 name = argv[i] + 2; 45 } 46 } 47 48 if (name == NULL) 49 name = getenv("DISPLAY"); 50 if (name == NULL) 51 name = ":0"; /* useful default */ 52 53 dpy = XOpenDisplay(name); 54 if (dpy == NULL) 55 die("unable to open out display %s\n", name); 56 57 printf("Opened connection to %s for testing.\n", name); 58 return dpy; 59} 60 61static Display *ref_display(int width, int height, int depth) 62{ 63 Display *dpy; 64 char buf[160]; 65 const char *name; 66 int try; 67 68 name = getenv("REF_DISPLAY"); 69 if (name) { 70 dpy = XOpenDisplay(name); 71 if (dpy == NULL) 72 die("unable to open reference display %s\n", name); 73 74 printf("Opened connection to %s for reference.\n", name); 75 return dpy; 76 } 77 78 snprintf(buf, sizeof(buf), 79 "Xvfb -ac -terminate -screen 0 %dx%dx%d :99 >/dev/null 2>&1 &", 80 width, height, depth); 81 if (system(buf)) 82 die("unable to spawn '%s' for reference display\n", buf); 83 84 try = 0; 85 while (try++ < 1000) { 86 dpy = XOpenDisplay(":99"); 87 if (dpy) 88 break; 89 usleep(1000); 90 } 91 92 if (dpy == NULL) 93 die("unable to open reference display\n"); 94 95 return dpy; 96} 97 98static void shm_setup(struct test_display *d) 99{ 100 int major, minor; 101 int size; 102 103 XShmQueryVersion(d->dpy, &major, &minor, &d->has_shm_pixmaps); 104 if (major == 0 && minor == 0) 105 die("XSHM not supported\n"); 106 107 size = d->width * d->height * 4; 108 d->max_shm_size = size; 109 110 d->shm.shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0600); 111 if (d->shm.shmid == -1) 112 die("failed to allocated %d bytes for a shm segment\n", size); 113 114 d->shm.shmaddr = shmat(d->shm.shmid, NULL, 0); 115 d->shm.readOnly = 0; 116 XShmAttach(d->dpy, &d->shm); 117 XSync(d->dpy, 1); 118} 119 120static void default_setup(struct test_display *dpy) 121{ 122 dpy->width = WidthOfScreen(DefaultScreenOfDisplay(dpy->dpy)); 123 dpy->height = HeightOfScreen(DefaultScreenOfDisplay(dpy->dpy)); 124 dpy->format = 125 XRenderFindVisualFormat(dpy->dpy, 126 DefaultVisual(dpy->dpy, 127 DefaultScreen(dpy->dpy))); 128 dpy->depth = DefaultDepth(dpy->dpy, DefaultScreen(dpy->dpy)); 129} 130 131static void test_get_displays(int argc, char **argv, 132 struct test_display *out, 133 struct test_display *ref) 134{ 135 out->dpy = out_display(argc, argv); 136 default_setup(out); 137 shm_setup(out); 138 out->root = get_root(out); 139 out->target = OUT; 140 141 ref->dpy = ref_display(out->width, out->height, out->depth); 142 default_setup(ref); 143 shm_setup(ref); 144 ref->root = get_root(ref); 145 ref->target = REF; 146} 147 148void test_init(struct test *test, int argc, char **argv) 149{ 150 memset(test, 0, sizeof(*test)); 151 test_get_displays(argc, argv, &test->out, &test->ref); 152} 153 154void test_timer_start(struct test_display *t, struct timespec *tv) 155{ 156 clock_gettime(CLOCK_MONOTONIC, tv); 157} 158 159double test_timer_stop(struct test_display *t, struct timespec *tv) 160{ 161 XImage *image; 162 struct timespec now; 163 164 image = XGetImage(t->dpy, t->root, 0, 0, 1, 1, AllPlanes, ZPixmap); 165 clock_gettime(CLOCK_MONOTONIC, &now); 166 XDestroyImage(image); 167 168 return (now.tv_sec - tv->tv_sec) + 1e-9*(now.tv_nsec - tv->tv_nsec); 169} 170