103b705cfSriastradh#include <stdint.h> 203b705cfSriastradh#include <stdio.h> 303b705cfSriastradh#include <stdlib.h> 403b705cfSriastradh 503b705cfSriastradh#include <X11/Xlib.h> 603b705cfSriastradh#include <X11/Xutil.h> 703b705cfSriastradh#include <X11/extensions/Xfixes.h> 803b705cfSriastradh#include <unistd.h> 903b705cfSriastradh#include <fcntl.h> 1003b705cfSriastradh#include <string.h> 1103b705cfSriastradh#include <time.h> 1203b705cfSriastradh 1303b705cfSriastradh#include <xf86drm.h> 1403b705cfSriastradh#include <drm.h> 1503b705cfSriastradh 1603b705cfSriastradh#include "dri2.h" 1703b705cfSriastradh 1803b705cfSriastradh#define COUNT 60 1903b705cfSriastradh 2003b705cfSriastradhstatic int dri2_open(Display *dpy) 2103b705cfSriastradh{ 2203b705cfSriastradh drm_auth_t auth; 2303b705cfSriastradh char *driver, *device; 2403b705cfSriastradh int fd; 2503b705cfSriastradh 2603b705cfSriastradh if (!DRI2Connect(dpy, DefaultRootWindow(dpy), &driver, &device)) 2703b705cfSriastradh return -1; 2803b705cfSriastradh 2903b705cfSriastradh printf ("Connecting to %s driver on %s\n", driver, device); 3003b705cfSriastradh 3142542f5fSchristos fd = open(device, O_RDWR); 3203b705cfSriastradh if (fd < 0) 3303b705cfSriastradh return -1; 3403b705cfSriastradh 3503b705cfSriastradh if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth)) 3603b705cfSriastradh return -1; 3703b705cfSriastradh 3803b705cfSriastradh if (!DRI2Authenticate(dpy, DefaultRootWindow(dpy), auth.magic)) 3903b705cfSriastradh return -1; 4003b705cfSriastradh 4103b705cfSriastradh return fd; 4203b705cfSriastradh} 4303b705cfSriastradh 4403b705cfSriastradhstatic void dri2_copy_swap(Display *dpy, Drawable d, 4503b705cfSriastradh int width, int height, int has_front) 4603b705cfSriastradh{ 4703b705cfSriastradh XRectangle rect; 4803b705cfSriastradh XserverRegion region; 4903b705cfSriastradh 5003b705cfSriastradh rect.x = 0; 5103b705cfSriastradh rect.y = 0; 5203b705cfSriastradh rect.width = width; 5303b705cfSriastradh rect.height = height; 5403b705cfSriastradh 5503b705cfSriastradh region = XFixesCreateRegion(dpy, &rect, 1); 5603b705cfSriastradh DRI2CopyRegion(dpy, d, region, DRI2BufferFrontLeft, DRI2BufferBackLeft); 5703b705cfSriastradh if (has_front) 5803b705cfSriastradh DRI2CopyRegion(dpy, d, region, DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); 5903b705cfSriastradh XFixesDestroyRegion(dpy, region); 6003b705cfSriastradh} 6103b705cfSriastradh 6203b705cfSriastradhstatic void xsync(Display *dpy, Window win) 6303b705cfSriastradh{ 6403b705cfSriastradh XImage *image; 6503b705cfSriastradh 6603b705cfSriastradh image = XGetImage(dpy, win, 0, 0, 1, 1, ~0, ZPixmap); 6703b705cfSriastradh if (image) 6803b705cfSriastradh XDestroyImage(image); 6903b705cfSriastradh} 7003b705cfSriastradh 7103b705cfSriastradhstatic double elapsed(const struct timespec *start, 7203b705cfSriastradh const struct timespec *end) 7303b705cfSriastradh{ 7403b705cfSriastradh return (end->tv_sec - start->tv_sec) + 7503b705cfSriastradh 1e-9*(end->tv_nsec - start->tv_nsec); 7603b705cfSriastradh} 7703b705cfSriastradh 7803b705cfSriastradhstatic void run(Display *dpy, int width, int height, 7903b705cfSriastradh unsigned int *attachments, int nattachments, 8003b705cfSriastradh const char *name) 8103b705cfSriastradh{ 8203b705cfSriastradh Window win; 8303b705cfSriastradh XSetWindowAttributes attr; 8403b705cfSriastradh int count; 8503b705cfSriastradh DRI2Buffer *buffers; 8603b705cfSriastradh struct timespec start, end; 8703b705cfSriastradh 8803b705cfSriastradh /* Be nasty and install a fullscreen window on top so that we 8903b705cfSriastradh * can guarantee we do not get clipped by children. 9003b705cfSriastradh */ 9103b705cfSriastradh attr.override_redirect = 1; 9203b705cfSriastradh win = XCreateWindow(dpy, DefaultRootWindow(dpy), 9303b705cfSriastradh 0, 0, width, height, 0, 9403b705cfSriastradh DefaultDepth(dpy, DefaultScreen(dpy)), 9503b705cfSriastradh InputOutput, 9603b705cfSriastradh DefaultVisual(dpy, DefaultScreen(dpy)), 9703b705cfSriastradh CWOverrideRedirect, &attr); 9803b705cfSriastradh XMapWindow(dpy, win); 9903b705cfSriastradh xsync(dpy, win); 10003b705cfSriastradh 10103b705cfSriastradh DRI2CreateDrawable(dpy, win); 10203b705cfSriastradh 10303b705cfSriastradh buffers = DRI2GetBuffers(dpy, win, &width, &height, 10403b705cfSriastradh attachments, nattachments, &count); 10503b705cfSriastradh if (count != nattachments) 10603b705cfSriastradh return; 10703b705cfSriastradh 10803b705cfSriastradh xsync(dpy, win); 10903b705cfSriastradh clock_gettime(CLOCK_MONOTONIC, &start); 11003b705cfSriastradh for (count = 0; count < COUNT; count++) 11103b705cfSriastradh DRI2SwapBuffers(dpy, win, 0, 0, 0); 11203b705cfSriastradh xsync(dpy, win); 11303b705cfSriastradh clock_gettime(CLOCK_MONOTONIC, &end); 11403b705cfSriastradh printf("%d %s (%dx%d) swaps in %fs.\n", 11503b705cfSriastradh count, name, width, height, elapsed(&start, &end)); 11603b705cfSriastradh 11703b705cfSriastradh xsync(dpy, win); 11803b705cfSriastradh clock_gettime(CLOCK_MONOTONIC, &start); 11903b705cfSriastradh for (count = 0; count < COUNT; count++) 12003b705cfSriastradh dri2_copy_swap(dpy, win, width, height, nattachments == 2); 12103b705cfSriastradh xsync(dpy, win); 12203b705cfSriastradh clock_gettime(CLOCK_MONOTONIC, &end); 12303b705cfSriastradh 12403b705cfSriastradh printf("%d %s (%dx%d) blits in %fs.\n", 12503b705cfSriastradh count, name, width, height, elapsed(&start, &end)); 12603b705cfSriastradh 12703b705cfSriastradh DRI2SwapInterval(dpy, win, 0); 12803b705cfSriastradh 12903b705cfSriastradh xsync(dpy, win); 13003b705cfSriastradh clock_gettime(CLOCK_MONOTONIC, &start); 13103b705cfSriastradh for (count = 0; count < COUNT; count++) 13203b705cfSriastradh DRI2SwapBuffers(dpy, win, 0, 0, 0); 13303b705cfSriastradh xsync(dpy, win); 13403b705cfSriastradh clock_gettime(CLOCK_MONOTONIC, &end); 13503b705cfSriastradh printf("%d %s (%dx%d) vblank=0 swaps in %fs.\n", 13603b705cfSriastradh count, name, width, height, elapsed(&start, &end)); 13703b705cfSriastradh 13803b705cfSriastradh XDestroyWindow(dpy, win); 13903b705cfSriastradh free(buffers); 14003b705cfSriastradh 14103b705cfSriastradh XSync(dpy, 1); 14203b705cfSriastradh} 14303b705cfSriastradh 14403b705cfSriastradhint main(void) 14503b705cfSriastradh{ 14603b705cfSriastradh Display *dpy; 14703b705cfSriastradh int width, height, fd; 14803b705cfSriastradh unsigned int attachments[] = { 14903b705cfSriastradh DRI2BufferBackLeft, 15003b705cfSriastradh DRI2BufferFrontLeft, 15103b705cfSriastradh }; 15203b705cfSriastradh 15303b705cfSriastradh dpy = XOpenDisplay (NULL); 15403b705cfSriastradh if (dpy == NULL) 15503b705cfSriastradh return 77; 15603b705cfSriastradh 15703b705cfSriastradh fd = dri2_open(dpy); 15803b705cfSriastradh if (fd < 0) 15903b705cfSriastradh return 1; 16003b705cfSriastradh 16103b705cfSriastradh width = WidthOfScreen(DefaultScreenOfDisplay(dpy)); 16203b705cfSriastradh height = HeightOfScreen(DefaultScreenOfDisplay(dpy)); 16303b705cfSriastradh run(dpy, width, height, attachments, 1, "fullscreen"); 16403b705cfSriastradh run(dpy, width, height, attachments, 2, "fullscreen (with front)"); 16503b705cfSriastradh 16603b705cfSriastradh width /= 2; 16703b705cfSriastradh height /= 2; 16803b705cfSriastradh run(dpy, width, height, attachments, 1, "windowed"); 16903b705cfSriastradh run(dpy, width, height, attachments, 2, "windowed (with front)"); 17003b705cfSriastradh 17103b705cfSriastradh return 0; 17203b705cfSriastradh} 173