├── LICENSE ├── README.md ├── package.sh ├── scripts ├── glsanity-bbee └── glsanity.in └── src ├── Makefile ├── common.h ├── glsanity-glx.c ├── glsanity-lib.c └── glsanity-x11.c /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Alexander Monakov 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | glsanity 2 | ======== 3 | 4 | Absence of 32-bit OpenGL libraries on 64-bit Linux distributions or mismatch 5 | between OpenGL client library and Xorg GLX module implementations on systems 6 | using proprietary OpenGL drivers is a well-known source of problems. 7 | 8 | 'glsanity' aims to help in diagnosing such problems by providing a few test 9 | programs in one package. 10 | 11 | Both 32-bit and 64-bit tests are included with prebuilt binaries. To download, 12 | navigate to [releases page](https://github.com/amonakov/glsanity/releases) and 13 | grab the `glsanity-bin.zip` file. 14 | 15 | Most users should run the `./glsanity` script. Users of laptops with hybrid 16 | graphics using Bumblebee and primus for offloading can use `./glsanity-bbee`. 17 | 18 | What is tested 19 | -------------- 20 | 21 | The following tests are performed: 22 | 23 | - What OpenGL library (libGL.so.1) is loaded by default 24 | - That GLX extension is available on the X connection 25 | - That direct rendering is available 26 | 27 | The last test also tries to detect software rendering by matching `GL_RENDERER` 28 | for 'llvmpipe' and 'Software' (for Mesa swrast). 29 | 30 | Sample output 31 | ------------- 32 | 33 | **NVIDIA drivers, Gentoo** 34 | 35 | 36 | ``` 37 | Running 32-bit tests 38 | info: libGL.so.1: loaded from: /usr/lib32/libGL.so.1 39 | info: libGL.so.1: symlink to: /usr/lib32/opengl/nvidia/lib/libGL.so.325.15 40 | info: X display: :0.0 41 | info: X Ext. "GLX": present 42 | info: X Ext. "NV-GLX": present 43 | info: GLX server: NVIDIA Corporation 44 | info: GLX client: NVIDIA Corporation 45 | info: GL vendor: NVIDIA Corporation 46 | info: GL renderer: GeForce GTX 460/PCIe/SSE2 47 | info: GL version: 4.3.0 NVIDIA 325.15 48 | Running 64-bit tests 49 | info: libGL.so.1: loaded from: /usr/lib64/libGL.so.1 50 | info: libGL.so.1: symlink to: /usr/lib64/opengl/nvidia/lib/libGL.so.325.15 51 | info: X display: :0.0 52 | info: X Ext. "GLX": present 53 | info: X Ext. "NV-GLX": present 54 | info: GLX server: NVIDIA Corporation 55 | info: GLX client: NVIDIA Corporation 56 | info: GL vendor: NVIDIA Corporation 57 | info: GL renderer: GeForce GTX 460/PCIe/SSE2 58 | info: GL version: 4.3.0 NVIDIA 325.15 59 | ``` 60 | 61 | **Hybrid graphics with primus** 62 | 63 | (showing 64-bit tests only) 64 | 65 | ``` 66 | Checking native (usually Mesa/i965) GL 67 | Running 64-bit tests 68 | info: libGL.so.1: loaded from: /usr/lib64/libGL.so.1 69 | info: libGL.so.1: symlink to: /usr/lib64/opengl/xorg-x11/lib/libGL.so.1.2.0 70 | info: X display: :0.0 71 | info: X Ext. "GLX": present 72 | info: X Ext. "NV-GLX": not present; OK for non-nVidia drivers 73 | info: GLX server: SGI 74 | info: GLX client: Mesa Project and SGI 75 | info: GL vendor: Intel Open Source Technology Center 76 | info: GL renderer: Mesa DRI Intel(R) Ivybridge Mobile 77 | info: GL version: 3.0 Mesa 9.1.3 78 | Checking secondary (usually NVIDIA) GL 79 | Running 64-bit tests 80 | info: libGL.so.1: loaded from: /usr/lib64/opengl/nvidia/lib/libGL.so.1 81 | info: libGL.so.1: symlink to: /usr/lib64/opengl/nvidia/lib/libGL.so.325.15 82 | info: X display: :8 83 | info: X Ext. "GLX": present 84 | info: X Ext. "NV-GLX": present 85 | info: GLX server: NVIDIA Corporation 86 | info: GLX client: NVIDIA Corporation 87 | info: GL vendor: NVIDIA Corporation 88 | info: GL renderer: GeForce GT 650M/PCIe/SSE2 89 | info: GL version: 4.3.0 NVIDIA 325.15 90 | Testing offloading with primus 91 | Running 64-bit tests 92 | info: libGL.so.1: loaded from: /usr/lib/primus/libGL.so.1 93 | info: libGL.so.1: symlink to: /usr/lib64/primus/libGL.so.1 94 | info: X display: :0.0 95 | info: X Ext. "GLX": present 96 | info: X Ext. "NV-GLX": not present; OK for non-nVidia drivers 97 | info: GLX server: NVIDIA Corporation 98 | info: GLX client: primus 99 | info: GL vendor: NVIDIA Corporation 100 | info: GL renderer: GeForce GT 650M/PCIe/SSE2 101 | info: GL version: 4.3.0 NVIDIA 325.15 102 | ``` 103 | -------------------------------------------------------------------------------- /package.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | pkgdir=$(dirname `readlink -ne $0`)/glsanity-bin 4 | 5 | export CFLAGS='-O2 -Wall -s' 6 | 7 | CC='gcc -m32' make -C src clean install instdir=$pkgdir/32 8 | CC='gcc -m64' make -C src clean install instdir=$pkgdir/64 9 | 10 | cp scripts/glsanity-bbee $pkgdir 11 | cp scripts/glsanity.in $pkgdir/glsanity 12 | 13 | sed -i -e 's#@CHECKERS32@#$(dirname `readlink -ne $0`)/32#' $pkgdir/glsanity 14 | sed -i -e 's#@CHECKERS64@#$(dirname `readlink -ne $0`)/64#' $pkgdir/glsanity 15 | chmod +x $pkgdir/glsanity 16 | 17 | zip -r glsanity-bin.zip glsanity-bin 18 | -------------------------------------------------------------------------------- /scripts/glsanity-bbee: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | glsanity=${0%-bbee} 4 | 5 | echo "Checking native (usually Mesa/i965) GL" 6 | $glsanity 7 | 8 | echo "Checking secondary (usually NVIDIA) GL" 9 | optirun -b none env DISPLAY=:8 $glsanity 10 | 11 | echo "Testing offloading with primus" 12 | optirun -b primus $glsanity 13 | -------------------------------------------------------------------------------- /scripts/glsanity.in: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | checkers32=@CHECKERS32@ 4 | checkers64=@CHECKERS64@ 5 | 6 | run_checks() 7 | { 8 | local PATH=$2:$PATH 9 | echo Running $1-bit tests 10 | 11 | glsanity-lib && glsanity-x11 && glsanity-glx 12 | } 13 | 14 | test -x /lib/ld-linux.so.2 && run_checks 32 $checkers32 15 | test -x /lib64/ld-linux-x86-64.so.2 && run_checks 64 $checkers64 16 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | prefix = /usr/local 2 | libdir = $(prefix)/lib 3 | instdir = $(libdir)/glsanity 4 | 5 | INSTALL = install 6 | 7 | EXES = glsanity-x11 glsanity-lib glsanity-glx 8 | 9 | glsanity-x11: LDLIBS=-lX11 10 | glsanity-lib: LDLIBS=-ldl 11 | glsanity-glx: LDLIBS=-lX11 -lGL 12 | 13 | all: $(EXES) 14 | 15 | clean: 16 | -rm $(EXES) 17 | 18 | install: $(EXES) 19 | $(INSTALL) -d $(DESTDIR)$(instdir) 20 | $(INSTALL) $(EXES) $(DESTDIR)$(instdir) 21 | -------------------------------------------------------------------------------- /src/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define die(fmt, ...) ({printf("fatal: %s:\t"fmt"\n", msg1, ## __VA_ARGS__); exit(1);}) 4 | #define inform(fmt, ...) printf("info: %s:\t"fmt"\n", msg1, ## __VA_ARGS__) 5 | -------------------------------------------------------------------------------- /src/glsanity-glx.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "common.h" 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | const char *msg1 = "X display"; 11 | Display *dpy = XOpenDisplay(NULL); 12 | if (!dpy) 13 | die("failed to open connection"); 14 | 15 | //FIXME: screen 0 hard-coded 16 | int screen = 0; 17 | msg1 = "GLX server"; 18 | const char *glx_srv_vnd = glXQueryServerString(dpy, screen, GLX_VENDOR); 19 | if (!glx_srv_vnd) 20 | die("lookup failed"); 21 | inform("%s", glx_srv_vnd); 22 | 23 | msg1 = "GLX client"; 24 | const char *glx_lib_vnd = glXGetClientString(dpy, GLX_VENDOR); 25 | inform("%s", glx_lib_vnd); 26 | 27 | msg1 = "GLX DB RGBA FBConfig"; 28 | int nconfigs, fbattrs[] 29 | = {GLX_CONFIG_CAVEAT, GLX_NONE, 30 | GLX_DOUBLEBUFFER, True, 31 | GLX_RENDER_TYPE, GLX_RGBA_BIT, 32 | GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, 33 | 0}; 34 | GLXFBConfig *fbconfigs = glXChooseFBConfig(dpy, screen, fbattrs, &nconfigs); 35 | if (!fbconfigs) 36 | die("none reported"); 37 | 38 | //FIXME: some errors will be reported via the X11 protocol 39 | msg1 = "GLX Pbuffer"; 40 | int pbattrs[] = {GLX_PBUFFER_WIDTH, 32, GLX_PBUFFER_HEIGHT, 32, 0}; 41 | GLXPbuffer pbuf = glXCreatePbuffer(dpy, fbconfigs[0], pbattrs); 42 | 43 | msg1 = "GLX Context"; 44 | GLXContext ctx = glXCreateNewContext(dpy, fbconfigs[0], GLX_RGBA_TYPE, 0, True); 45 | if (!ctx) 46 | die("failed"); 47 | 48 | if (!glXIsDirect(dpy, ctx)) 49 | inform("direct rendering not available"); 50 | 51 | if (!glXMakeCurrent(dpy, pbuf, ctx)) 52 | die("glXMakeCurrent failed"); 53 | 54 | msg1 = "GL vendor"; 55 | const char *gl_vnd = (const char *)glGetString(GL_VENDOR); 56 | inform("%s", gl_vnd); 57 | msg1 = "GL renderer"; 58 | const char *gl_rnd = (const char *)glGetString(GL_RENDERER); 59 | inform("%s", gl_rnd); 60 | msg1 = "GL version"; 61 | const char *gl_ver = (const char *)glGetString(GL_VERSION); 62 | inform("%s", gl_ver); 63 | 64 | // Direct rendering != hardware accelerated rendering 65 | msg1 = "GL hw accelerated"; 66 | if (strstr(gl_rnd, "llvmpipe") || strstr(gl_rnd, "Software")) 67 | inform("no"); 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /src/glsanity-lib.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "common.h" 8 | 9 | int main(int argc, char *argv[]) 10 | { 11 | const char *msg1 = "libGL.so.1"; 12 | void *libgl = dlopen("libGL.so.1", RTLD_LAZY); 13 | if (!libgl) 14 | die("loading with dlopen failed:\n%s", dlerror()); 15 | void *libgl_sym = dlsym(libgl, "glXQueryVersion"); 16 | if (!libgl_sym) 17 | die("dlsym failed: %s", dlerror()); 18 | Dl_info libgl_info; 19 | if (!dladdr(libgl_sym, &libgl_info)) 20 | die("dladdr failed"); 21 | inform("loaded from: %s", libgl_info.dli_fname); 22 | 23 | char *real_path = canonicalize_file_name(libgl_info.dli_fname); 24 | if (strcmp(real_path, libgl_info.dli_fname)) 25 | inform("symlink to: %s", real_path); 26 | free(real_path); 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /src/glsanity-x11.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include "common.h" 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | const char *msg1 = "X display"; 10 | char *dpyname = getenv("DISPLAY"); 11 | if (!dpyname) 12 | die("DISPLAY not set"); 13 | inform("%s", dpyname); 14 | 15 | Display *dpy = XOpenDisplay(dpyname); 16 | if (!dpy) 17 | die("failed to open connection"); 18 | 19 | msg1 = "X Ext. \"GLX\""; 20 | int dummy; 21 | if (!XQueryExtension(dpy, "GLX", &dummy, &dummy, &dummy)) 22 | die("not present; see the Xorg log for details"); 23 | inform("present"); 24 | 25 | msg1 = "X Ext. \"NV-GLX\""; 26 | if (!XQueryExtension(dpy, "NV-GLX", &dummy, &dummy, &dummy)) 27 | inform("not present; OK for non-nVidia drivers"); 28 | else 29 | inform("present"); 30 | 31 | return 0; 32 | } 33 | --------------------------------------------------------------------------------