1428d7b3dSmrg#include <stdint.h> 2428d7b3dSmrg#include <stdio.h> 3428d7b3dSmrg#include <stdlib.h> 4428d7b3dSmrg 5428d7b3dSmrg#include <X11/Xlib.h> 6428d7b3dSmrg#include <X11/Xutil.h> 7428d7b3dSmrg#include <X11/extensions/Xfixes.h> 8428d7b3dSmrg#include <unistd.h> 9428d7b3dSmrg#include <fcntl.h> 10428d7b3dSmrg#include <string.h> 11428d7b3dSmrg#include <time.h> 12428d7b3dSmrg 13428d7b3dSmrg#include <xf86drm.h> 14428d7b3dSmrg#include <drm.h> 15428d7b3dSmrg 16428d7b3dSmrg#include "dri2.h" 17428d7b3dSmrg 18428d7b3dSmrg#define COUNT 60 19428d7b3dSmrg 20428d7b3dSmrgstatic int dri2_open(Display *dpy) 21428d7b3dSmrg{ 22428d7b3dSmrg drm_auth_t auth; 23428d7b3dSmrg char *driver, *device; 24428d7b3dSmrg int fd; 25428d7b3dSmrg 26428d7b3dSmrg if (!DRI2Connect(dpy, DefaultRootWindow(dpy), &driver, &device)) 27428d7b3dSmrg return -1; 28428d7b3dSmrg 29428d7b3dSmrg printf ("Connecting to %s driver on %s\n", driver, device); 30428d7b3dSmrg 31428d7b3dSmrg fd = open(device, O_RDWR); 32428d7b3dSmrg if (fd < 0) 33428d7b3dSmrg return -1; 34428d7b3dSmrg 35428d7b3dSmrg if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth)) 36428d7b3dSmrg return -1; 37428d7b3dSmrg 38428d7b3dSmrg if (!DRI2Authenticate(dpy, DefaultRootWindow(dpy), auth.magic)) 39428d7b3dSmrg return -1; 40428d7b3dSmrg 41428d7b3dSmrg return fd; 42428d7b3dSmrg} 43428d7b3dSmrg 44428d7b3dSmrgstatic void dri2_copy_swap(Display *dpy, Drawable d, 45428d7b3dSmrg int width, int height, int has_front) 46428d7b3dSmrg{ 47428d7b3dSmrg XRectangle rect; 48428d7b3dSmrg XserverRegion region; 49428d7b3dSmrg 50428d7b3dSmrg rect.x = 0; 51428d7b3dSmrg rect.y = 0; 52428d7b3dSmrg rect.width = width; 53428d7b3dSmrg rect.height = height; 54428d7b3dSmrg 55428d7b3dSmrg region = XFixesCreateRegion(dpy, &rect, 1); 56428d7b3dSmrg DRI2CopyRegion(dpy, d, region, DRI2BufferFrontLeft, DRI2BufferBackLeft); 57428d7b3dSmrg if (has_front) 58428d7b3dSmrg DRI2CopyRegion(dpy, d, region, DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); 59428d7b3dSmrg XFixesDestroyRegion(dpy, region); 60428d7b3dSmrg} 61428d7b3dSmrg 62428d7b3dSmrgstatic void xsync(Display *dpy, Window win) 63428d7b3dSmrg{ 64428d7b3dSmrg XImage *image; 65428d7b3dSmrg 66428d7b3dSmrg image = XGetImage(dpy, win, 0, 0, 1, 1, ~0, ZPixmap); 67428d7b3dSmrg if (image) 68428d7b3dSmrg XDestroyImage(image); 69428d7b3dSmrg} 70428d7b3dSmrg 71428d7b3dSmrgstatic double elapsed(const struct timespec *start, 72428d7b3dSmrg const struct timespec *end) 73428d7b3dSmrg{ 74428d7b3dSmrg return (end->tv_sec - start->tv_sec) + 75428d7b3dSmrg 1e-9*(end->tv_nsec - start->tv_nsec); 76428d7b3dSmrg} 77428d7b3dSmrg 78428d7b3dSmrgstatic void run(Display *dpy, int width, int height, 79428d7b3dSmrg unsigned int *attachments, int nattachments, 80428d7b3dSmrg const char *name) 81428d7b3dSmrg{ 82428d7b3dSmrg Window win; 83428d7b3dSmrg XSetWindowAttributes attr; 84428d7b3dSmrg int count; 85428d7b3dSmrg DRI2Buffer *buffers; 86428d7b3dSmrg struct timespec start, end; 87428d7b3dSmrg 88428d7b3dSmrg /* Be nasty and install a fullscreen window on top so that we 89428d7b3dSmrg * can guarantee we do not get clipped by children. 90428d7b3dSmrg */ 91428d7b3dSmrg attr.override_redirect = 1; 92428d7b3dSmrg win = XCreateWindow(dpy, DefaultRootWindow(dpy), 93428d7b3dSmrg 0, 0, width, height, 0, 94428d7b3dSmrg DefaultDepth(dpy, DefaultScreen(dpy)), 95428d7b3dSmrg InputOutput, 96428d7b3dSmrg DefaultVisual(dpy, DefaultScreen(dpy)), 97428d7b3dSmrg CWOverrideRedirect, &attr); 98428d7b3dSmrg XMapWindow(dpy, win); 99428d7b3dSmrg xsync(dpy, win); 100428d7b3dSmrg 101428d7b3dSmrg DRI2CreateDrawable(dpy, win); 102428d7b3dSmrg 103428d7b3dSmrg buffers = DRI2GetBuffers(dpy, win, &width, &height, 104428d7b3dSmrg attachments, nattachments, &count); 105428d7b3dSmrg if (count != nattachments) 106428d7b3dSmrg return; 107428d7b3dSmrg 108428d7b3dSmrg xsync(dpy, win); 109428d7b3dSmrg clock_gettime(CLOCK_MONOTONIC, &start); 110428d7b3dSmrg for (count = 0; count < COUNT; count++) 111428d7b3dSmrg DRI2SwapBuffers(dpy, win, 0, 0, 0); 112428d7b3dSmrg xsync(dpy, win); 113428d7b3dSmrg clock_gettime(CLOCK_MONOTONIC, &end); 114428d7b3dSmrg printf("%d %s (%dx%d) swaps in %fs.\n", 115428d7b3dSmrg count, name, width, height, elapsed(&start, &end)); 116428d7b3dSmrg 117428d7b3dSmrg xsync(dpy, win); 118428d7b3dSmrg clock_gettime(CLOCK_MONOTONIC, &start); 119428d7b3dSmrg for (count = 0; count < COUNT; count++) 120428d7b3dSmrg dri2_copy_swap(dpy, win, width, height, nattachments == 2); 121428d7b3dSmrg xsync(dpy, win); 122428d7b3dSmrg clock_gettime(CLOCK_MONOTONIC, &end); 123428d7b3dSmrg 124428d7b3dSmrg printf("%d %s (%dx%d) blits in %fs.\n", 125428d7b3dSmrg count, name, width, height, elapsed(&start, &end)); 126428d7b3dSmrg 127428d7b3dSmrg DRI2SwapInterval(dpy, win, 0); 128428d7b3dSmrg 129428d7b3dSmrg xsync(dpy, win); 130428d7b3dSmrg clock_gettime(CLOCK_MONOTONIC, &start); 131428d7b3dSmrg for (count = 0; count < COUNT; count++) 132428d7b3dSmrg DRI2SwapBuffers(dpy, win, 0, 0, 0); 133428d7b3dSmrg xsync(dpy, win); 134428d7b3dSmrg clock_gettime(CLOCK_MONOTONIC, &end); 135428d7b3dSmrg printf("%d %s (%dx%d) vblank=0 swaps in %fs.\n", 136428d7b3dSmrg count, name, width, height, elapsed(&start, &end)); 137428d7b3dSmrg 138428d7b3dSmrg XDestroyWindow(dpy, win); 139428d7b3dSmrg free(buffers); 140428d7b3dSmrg 141428d7b3dSmrg XSync(dpy, 1); 142428d7b3dSmrg} 143428d7b3dSmrg 144428d7b3dSmrgint main(void) 145428d7b3dSmrg{ 146428d7b3dSmrg Display *dpy; 147428d7b3dSmrg int width, height, fd; 148428d7b3dSmrg unsigned int attachments[] = { 149428d7b3dSmrg DRI2BufferBackLeft, 150428d7b3dSmrg DRI2BufferFrontLeft, 151428d7b3dSmrg }; 152428d7b3dSmrg 153428d7b3dSmrg dpy = XOpenDisplay (NULL); 154428d7b3dSmrg if (dpy == NULL) 155428d7b3dSmrg return 77; 156428d7b3dSmrg 157428d7b3dSmrg fd = dri2_open(dpy); 158428d7b3dSmrg if (fd < 0) 159428d7b3dSmrg return 1; 160428d7b3dSmrg 161428d7b3dSmrg width = WidthOfScreen(DefaultScreenOfDisplay(dpy)); 162428d7b3dSmrg height = HeightOfScreen(DefaultScreenOfDisplay(dpy)); 163428d7b3dSmrg run(dpy, width, height, attachments, 1, "fullscreen"); 164428d7b3dSmrg run(dpy, width, height, attachments, 2, "fullscreen (with front)"); 165428d7b3dSmrg 166428d7b3dSmrg width /= 2; 167428d7b3dSmrg height /= 2; 168428d7b3dSmrg run(dpy, width, height, attachments, 1, "windowed"); 169428d7b3dSmrg run(dpy, width, height, attachments, 2, "windowed (with front)"); 170428d7b3dSmrg 171428d7b3dSmrg return 0; 172428d7b3dSmrg} 173