1#include <stdint.h> 2#include <stdio.h> 3#include <stdlib.h> 4 5#include <X11/Xlib.h> 6#include <X11/Xutil.h> 7#include <X11/extensions/Xfixes.h> 8#include <unistd.h> 9#include <fcntl.h> 10#include <string.h> 11#include <time.h> 12 13#include <xf86drm.h> 14#include <drm.h> 15 16#include "dri2.h" 17 18#define COUNT 60 19 20static int dri2_open(Display *dpy) 21{ 22 drm_auth_t auth; 23 char *driver, *device; 24 int fd; 25 26 if (!DRI2Connect(dpy, DefaultRootWindow(dpy), &driver, &device)) 27 return -1; 28 29 printf ("Connecting to %s driver on %s\n", driver, device); 30 31 fd = open(device, O_RDWR); 32 if (fd < 0) 33 return -1; 34 35 if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth)) 36 return -1; 37 38 if (!DRI2Authenticate(dpy, DefaultRootWindow(dpy), auth.magic)) 39 return -1; 40 41 return fd; 42} 43 44static void dri2_copy_swap(Display *dpy, Drawable d, 45 int width, int height, int has_front) 46{ 47 XRectangle rect; 48 XserverRegion region; 49 50 rect.x = 0; 51 rect.y = 0; 52 rect.width = width; 53 rect.height = height; 54 55 region = XFixesCreateRegion(dpy, &rect, 1); 56 DRI2CopyRegion(dpy, d, region, DRI2BufferFrontLeft, DRI2BufferBackLeft); 57 if (has_front) 58 DRI2CopyRegion(dpy, d, region, DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); 59 XFixesDestroyRegion(dpy, region); 60} 61 62static void xsync(Display *dpy, Window win) 63{ 64 XImage *image; 65 66 image = XGetImage(dpy, win, 0, 0, 1, 1, ~0, ZPixmap); 67 if (image) 68 XDestroyImage(image); 69} 70 71static double elapsed(const struct timespec *start, 72 const struct timespec *end) 73{ 74 return (end->tv_sec - start->tv_sec) + 75 1e-9*(end->tv_nsec - start->tv_nsec); 76} 77 78static void run(Display *dpy, int width, int height, 79 unsigned int *attachments, int nattachments, 80 const char *name) 81{ 82 Window win; 83 XSetWindowAttributes attr; 84 int count; 85 DRI2Buffer *buffers; 86 struct timespec start, end; 87 88 /* Be nasty and install a fullscreen window on top so that we 89 * can guarantee we do not get clipped by children. 90 */ 91 attr.override_redirect = 1; 92 win = XCreateWindow(dpy, DefaultRootWindow(dpy), 93 0, 0, width, height, 0, 94 DefaultDepth(dpy, DefaultScreen(dpy)), 95 InputOutput, 96 DefaultVisual(dpy, DefaultScreen(dpy)), 97 CWOverrideRedirect, &attr); 98 XMapWindow(dpy, win); 99 xsync(dpy, win); 100 101 DRI2CreateDrawable(dpy, win); 102 103 buffers = DRI2GetBuffers(dpy, win, &width, &height, 104 attachments, nattachments, &count); 105 if (count != nattachments) 106 return; 107 108 xsync(dpy, win); 109 clock_gettime(CLOCK_MONOTONIC, &start); 110 for (count = 0; count < COUNT; count++) 111 DRI2SwapBuffers(dpy, win, 0, 0, 0); 112 xsync(dpy, win); 113 clock_gettime(CLOCK_MONOTONIC, &end); 114 printf("%d %s (%dx%d) swaps in %fs.\n", 115 count, name, width, height, elapsed(&start, &end)); 116 117 xsync(dpy, win); 118 clock_gettime(CLOCK_MONOTONIC, &start); 119 for (count = 0; count < COUNT; count++) 120 dri2_copy_swap(dpy, win, width, height, nattachments == 2); 121 xsync(dpy, win); 122 clock_gettime(CLOCK_MONOTONIC, &end); 123 124 printf("%d %s (%dx%d) blits in %fs.\n", 125 count, name, width, height, elapsed(&start, &end)); 126 127 DRI2SwapInterval(dpy, win, 0); 128 129 xsync(dpy, win); 130 clock_gettime(CLOCK_MONOTONIC, &start); 131 for (count = 0; count < COUNT; count++) 132 DRI2SwapBuffers(dpy, win, 0, 0, 0); 133 xsync(dpy, win); 134 clock_gettime(CLOCK_MONOTONIC, &end); 135 printf("%d %s (%dx%d) vblank=0 swaps in %fs.\n", 136 count, name, width, height, elapsed(&start, &end)); 137 138 XDestroyWindow(dpy, win); 139 free(buffers); 140 141 XSync(dpy, 1); 142} 143 144int main(void) 145{ 146 Display *dpy; 147 int width, height, fd; 148 unsigned int attachments[] = { 149 DRI2BufferBackLeft, 150 DRI2BufferFrontLeft, 151 }; 152 153 dpy = XOpenDisplay (NULL); 154 if (dpy == NULL) 155 return 77; 156 157 fd = dri2_open(dpy); 158 if (fd < 0) 159 return 1; 160 161 width = WidthOfScreen(DefaultScreenOfDisplay(dpy)); 162 height = HeightOfScreen(DefaultScreenOfDisplay(dpy)); 163 run(dpy, width, height, attachments, 1, "fullscreen"); 164 run(dpy, width, height, attachments, 2, "fullscreen (with front)"); 165 166 width /= 2; 167 height /= 2; 168 run(dpy, width, height, attachments, 1, "windowed"); 169 run(dpy, width, height, attachments, 2, "windowed (with front)"); 170 171 return 0; 172} 173