1/* 2 * Copyright (c) 2014 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 */ 24 25#ifdef HAVE_CONFIG_H 26#include "config.h" 27#endif 28 29#include <X11/Xlib.h> 30#include <X11/Xutil.h> 31#include <X11/Xlibint.h> 32#include <X11/extensions/Xrender.h> 33#include <X11/extensions/XShm.h> 34#if HAVE_X11_EXTENSIONS_SHMPROTO_H 35#include <X11/extensions/shmproto.h> 36#elif HAVE_X11_EXTENSIONS_SHMSTR_H 37#include <X11/extensions/shmstr.h> 38#else 39#error Failed to find the right header for X11 MIT-SHM protocol definitions 40#endif 41 42#include <stdio.h> 43#include <string.h> 44#include <fcntl.h> 45#include <unistd.h> 46#include <assert.h> 47#include <errno.h> 48 49#include <sys/mman.h> 50#include <sys/ipc.h> 51#include <sys/shm.h> 52#include <pciaccess.h> 53 54static int _x_error_occurred; 55 56static int 57can_use_shm(Display *dpy) 58{ 59 int major, minor, has_pixmap; 60 61 if (!XShmQueryExtension(dpy)) 62 return 0; 63 64 XShmQueryVersion(dpy, &major, &minor, &has_pixmap); 65 return has_pixmap; 66} 67 68static int test_subpage(Display *dpy) 69{ 70 const int width = 10; 71 const int height = 10; 72 uint32_t pixel = 0xffffffff; 73 char *expected; 74 XShmSegmentInfo shm; 75 Pixmap pixmap, source; 76 XGCValues gcv; 77 GC gc; 78 79 printf("Creating %dx%d SHM pixmap\n", width, height); 80 _x_error_occurred = 0; 81 82 expected = malloc(4096); 83 if (expected == NULL) 84 return 0; 85 86 shm.shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT | 0666); 87 if (shm.shmid == -1) 88 return 0; 89 90 shm.shmaddr = shmat(shm.shmid, 0, 0); 91 if (shm.shmaddr == (char *) -1) { 92 shmctl(shm.shmid, IPC_RMID, NULL); 93 return 0; 94 } 95 96 shm.readOnly = False; 97 XShmAttach(dpy, &shm); 98 99 memset(shm.shmaddr, 0xcc, 4096); 100 memset(expected, 0xcc, 4096); 101 memset(expected + 64, 0xff, 4*width * height); 102 103 pixmap = XShmCreatePixmap(dpy, DefaultRootWindow(dpy), 104 shm.shmaddr + 64, &shm, width, height, 24); 105 XSync(dpy, False); 106 shmctl(shm.shmid, IPC_RMID, NULL); 107 108 source = XCreatePixmap(dpy, DefaultRootWindow(dpy), 109 width, height, 24); 110 111 gcv.graphics_exposures = False; 112 gcv.subwindow_mode = IncludeInferiors; 113 gcv.foreground = pixel; 114 gcv.function = GXcopy; 115 gcv.fill_style = FillSolid; 116 gc = XCreateGC(dpy, pixmap, GCGraphicsExposures | GCSubwindowMode | GCFillStyle | GCForeground | GCFunction, &gcv); 117 118 XCopyArea(dpy, pixmap, source, gc, 119 0, 0, width, height, 0, 0); 120 121 XFillRectangle(dpy, source, gc, 0, 0, width, height); 122 123 XCopyArea(dpy, source, pixmap, gc, 124 0, 0, width, height, 0, 0); 125 XSync(dpy, True); 126 127 if (_x_error_occurred == 0) 128 _x_error_occurred = memcmp(shm.shmaddr, expected, 4096); 129 130 printf("%s: %s\n", __func__, _x_error_occurred ? "failed" : "passed"); 131 132 XShmDetach(dpy, &shm); 133 shmdt(shm.shmaddr); 134 free(expected); 135 136 137 return !_x_error_occurred;; 138} 139 140static int 141_check_error_handler(Display *display, 142 XErrorEvent *event) 143{ 144 printf("X11 error from display %s, serial=%ld, error=%d, req=%d.%d\n", 145 DisplayString(display), 146 event->serial, 147 event->error_code, 148 event->request_code, 149 event->minor_code); 150 _x_error_occurred++; 151 return False; /* ignored */ 152} 153 154int main(void) 155{ 156 Display *dpy; 157 int error = 0; 158 159 dpy = XOpenDisplay(NULL); 160 if (dpy == NULL) 161 return 77; 162 163 if (DefaultDepth(dpy, DefaultScreen(dpy)) != 24) 164 return 77; 165 166 if (!can_use_shm(dpy)) 167 return 0; 168 169 XSetErrorHandler(_check_error_handler); 170 171 error += test_subpage(dpy); 172 173 return !!error; 174} 175