142542f5fSchristos/* 242542f5fSchristos * Copyright (c) 2014 Intel Corporation 342542f5fSchristos * 442542f5fSchristos * Permission is hereby granted, free of charge, to any person obtaining a 542542f5fSchristos * copy of this software and associated documentation files (the "Software"), 642542f5fSchristos * to deal in the Software without restriction, including without limitation 742542f5fSchristos * the rights to use, copy, modify, merge, publish, distribute, sublicense, 842542f5fSchristos * and/or sell copies of the Software, and to permit persons to whom the 942542f5fSchristos * Software is furnished to do so, subject to the following conditions: 1042542f5fSchristos * 1142542f5fSchristos * The above copyright notice and this permission notice (including the next 1242542f5fSchristos * paragraph) shall be included in all copies or substantial portions of the 1342542f5fSchristos * Software. 1442542f5fSchristos * 1542542f5fSchristos * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1642542f5fSchristos * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1742542f5fSchristos * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1842542f5fSchristos * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1942542f5fSchristos * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2042542f5fSchristos * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2142542f5fSchristos * SOFTWARE. 2242542f5fSchristos * 2342542f5fSchristos */ 2442542f5fSchristos 2542542f5fSchristos#ifdef HAVE_CONFIG_H 2642542f5fSchristos#include "config.h" 2742542f5fSchristos#endif 2842542f5fSchristos 2942542f5fSchristos#include <X11/Xlib.h> 3042542f5fSchristos#include <X11/Xutil.h> 3142542f5fSchristos#include <X11/Xlibint.h> 3242542f5fSchristos#include <X11/extensions/Xrender.h> 3342542f5fSchristos#include <X11/extensions/XShm.h> 3442542f5fSchristos#if HAVE_X11_EXTENSIONS_SHMPROTO_H 3542542f5fSchristos#include <X11/extensions/shmproto.h> 3642542f5fSchristos#elif HAVE_X11_EXTENSIONS_SHMSTR_H 3742542f5fSchristos#include <X11/extensions/shmstr.h> 3842542f5fSchristos#else 3942542f5fSchristos#error Failed to find the right header for X11 MIT-SHM protocol definitions 4042542f5fSchristos#endif 4142542f5fSchristos 4242542f5fSchristos#include <stdio.h> 4342542f5fSchristos#include <string.h> 4442542f5fSchristos#include <fcntl.h> 4542542f5fSchristos#include <unistd.h> 4642542f5fSchristos#include <assert.h> 4742542f5fSchristos#include <errno.h> 4842542f5fSchristos 4942542f5fSchristos#include <sys/mman.h> 5042542f5fSchristos#include <sys/ipc.h> 5142542f5fSchristos#include <sys/shm.h> 5242542f5fSchristos#include <pciaccess.h> 5342542f5fSchristos 5442542f5fSchristosstatic int _x_error_occurred; 5542542f5fSchristos 5642542f5fSchristosstatic int 5742542f5fSchristoscan_use_shm(Display *dpy) 5842542f5fSchristos{ 5942542f5fSchristos int major, minor, has_pixmap; 6042542f5fSchristos 6142542f5fSchristos if (!XShmQueryExtension(dpy)) 6242542f5fSchristos return 0; 6342542f5fSchristos 6442542f5fSchristos XShmQueryVersion(dpy, &major, &minor, &has_pixmap); 6542542f5fSchristos return has_pixmap; 6642542f5fSchristos} 6742542f5fSchristos 6842542f5fSchristosstatic int test_subpage(Display *dpy) 6942542f5fSchristos{ 7042542f5fSchristos const int width = 10; 7142542f5fSchristos const int height = 10; 7242542f5fSchristos uint32_t pixel = 0xffffffff; 7342542f5fSchristos char *expected; 7442542f5fSchristos XShmSegmentInfo shm; 7542542f5fSchristos Pixmap pixmap, source; 7642542f5fSchristos XGCValues gcv; 7742542f5fSchristos GC gc; 7842542f5fSchristos 7942542f5fSchristos printf("Creating %dx%d SHM pixmap\n", width, height); 8042542f5fSchristos _x_error_occurred = 0; 8142542f5fSchristos 8242542f5fSchristos expected = malloc(4096); 8342542f5fSchristos if (expected == NULL) 8442542f5fSchristos return 0; 8542542f5fSchristos 8642542f5fSchristos shm.shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT | 0666); 8742542f5fSchristos if (shm.shmid == -1) 8842542f5fSchristos return 0; 8942542f5fSchristos 9042542f5fSchristos shm.shmaddr = shmat(shm.shmid, 0, 0); 9142542f5fSchristos if (shm.shmaddr == (char *) -1) { 9242542f5fSchristos shmctl(shm.shmid, IPC_RMID, NULL); 9342542f5fSchristos return 0; 9442542f5fSchristos } 9542542f5fSchristos 9642542f5fSchristos shm.readOnly = False; 9742542f5fSchristos XShmAttach(dpy, &shm); 9842542f5fSchristos 9942542f5fSchristos memset(shm.shmaddr, 0xcc, 4096); 10042542f5fSchristos memset(expected, 0xcc, 4096); 10142542f5fSchristos memset(expected + 64, 0xff, 4*width * height); 10242542f5fSchristos 10342542f5fSchristos pixmap = XShmCreatePixmap(dpy, DefaultRootWindow(dpy), 10442542f5fSchristos shm.shmaddr + 64, &shm, width, height, 24); 10542542f5fSchristos XSync(dpy, False); 10642542f5fSchristos shmctl(shm.shmid, IPC_RMID, NULL); 10742542f5fSchristos 10842542f5fSchristos source = XCreatePixmap(dpy, DefaultRootWindow(dpy), 10942542f5fSchristos width, height, 24); 11042542f5fSchristos 11142542f5fSchristos gcv.graphics_exposures = False; 11242542f5fSchristos gcv.subwindow_mode = IncludeInferiors; 11342542f5fSchristos gcv.foreground = pixel; 11442542f5fSchristos gcv.function = GXcopy; 11542542f5fSchristos gcv.fill_style = FillSolid; 11642542f5fSchristos gc = XCreateGC(dpy, pixmap, GCGraphicsExposures | GCSubwindowMode | GCFillStyle | GCForeground | GCFunction, &gcv); 11742542f5fSchristos 11842542f5fSchristos XCopyArea(dpy, pixmap, source, gc, 11942542f5fSchristos 0, 0, width, height, 0, 0); 12042542f5fSchristos 12142542f5fSchristos XFillRectangle(dpy, source, gc, 0, 0, width, height); 12242542f5fSchristos 12342542f5fSchristos XCopyArea(dpy, source, pixmap, gc, 12442542f5fSchristos 0, 0, width, height, 0, 0); 12542542f5fSchristos XSync(dpy, True); 12642542f5fSchristos 12742542f5fSchristos if (_x_error_occurred == 0) 12842542f5fSchristos _x_error_occurred = memcmp(shm.shmaddr, expected, 4096); 12942542f5fSchristos 13042542f5fSchristos printf("%s: %s\n", __func__, _x_error_occurred ? "failed" : "passed"); 13142542f5fSchristos 13242542f5fSchristos XShmDetach(dpy, &shm); 13342542f5fSchristos shmdt(shm.shmaddr); 13442542f5fSchristos free(expected); 13542542f5fSchristos 13642542f5fSchristos 13742542f5fSchristos return !_x_error_occurred;; 13842542f5fSchristos} 13942542f5fSchristos 14042542f5fSchristosstatic int 14142542f5fSchristos_check_error_handler(Display *display, 14242542f5fSchristos XErrorEvent *event) 14342542f5fSchristos{ 14442542f5fSchristos printf("X11 error from display %s, serial=%ld, error=%d, req=%d.%d\n", 14542542f5fSchristos DisplayString(display), 14642542f5fSchristos event->serial, 14742542f5fSchristos event->error_code, 14842542f5fSchristos event->request_code, 14942542f5fSchristos event->minor_code); 15042542f5fSchristos _x_error_occurred++; 15142542f5fSchristos return False; /* ignored */ 15242542f5fSchristos} 15342542f5fSchristos 15442542f5fSchristosint main(void) 15542542f5fSchristos{ 15642542f5fSchristos Display *dpy; 15742542f5fSchristos int error = 0; 15842542f5fSchristos 15942542f5fSchristos dpy = XOpenDisplay(NULL); 16042542f5fSchristos if (dpy == NULL) 16142542f5fSchristos return 77; 16242542f5fSchristos 16342542f5fSchristos if (DefaultDepth(dpy, DefaultScreen(dpy)) != 24) 16442542f5fSchristos return 77; 16542542f5fSchristos 16642542f5fSchristos if (!can_use_shm(dpy)) 16742542f5fSchristos return 0; 16842542f5fSchristos 16942542f5fSchristos XSetErrorHandler(_check_error_handler); 17042542f5fSchristos 17142542f5fSchristos error += test_subpage(dpy); 17242542f5fSchristos 17342542f5fSchristos return !!error; 17442542f5fSchristos} 175