diff --git a/Makefile b/Makefile index cdd43ef..a93c8c7 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,7 @@ endif ifndef DISABLE_GLX CFLAGS_GLX = -DGLAVA_GLX - LDFLAGS_GLX = -lGLX -lXrender + LDFLAGS_GLX = -lXrender endif ifeq ($(INSTALL),osx) diff --git a/README.md b/README.md index cb09583..ca2c2a4 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,6 @@ You can pass `BUILD=debug` to the makefile for debug builds of both glad and gla - glad (included as a submodule) - python (required to generate bindings with glad) - GCC (this program uses GNU C features) -- GLX headers (optional, disable direct GLX support with `DISABLE_GLX=1`), usually the development packages for `libgl` include this on your distro **Ubuntu/Debian users:** the following command ensures you have all the needed packages and headers to compile GLava: ```bash diff --git a/glad b/glad index 0a146b6..ec01ac5 160000 --- a/glad +++ b/glad @@ -1 +1 @@ -Subproject commit 0a146b6723fa812393455bbd1416781257eb5448 +Subproject commit ec01ac515dba0730dca375887bb1bd60bc92013c diff --git a/glx_wcb.c b/glx_wcb.c index 9876acd..65be661 100644 --- a/glx_wcb.c +++ b/glx_wcb.c @@ -13,22 +13,154 @@ #include #include +#include + #include #include #include #include #include -#include #include "render.h" #include "xwin.h" +typedef struct __GLXcontextRec *GLXContext; +typedef XID GLXPixmap; +typedef XID GLXDrawable; + +typedef void (*__GLXextFuncPtr)(void); + +/* GLX 1.3 and later */ +typedef struct __GLXFBConfigRec *GLXFBConfig; +typedef XID GLXFBConfigID; +typedef XID GLXContextID; +typedef XID GLXWindow; +typedef XID GLXPbuffer; + +/* + * Tokens for glXChooseVisual and glXGetConfig: + */ +#define GLX_USE_GL 1 +#define GLX_BUFFER_SIZE 2 +#define GLX_LEVEL 3 +#define GLX_RGBA 4 +#define GLX_DOUBLEBUFFER 5 +#define GLX_STEREO 6 +#define GLX_AUX_BUFFERS 7 +#define GLX_RED_SIZE 8 +#define GLX_GREEN_SIZE 9 +#define GLX_BLUE_SIZE 10 +#define GLX_ALPHA_SIZE 11 +#define GLX_DEPTH_SIZE 12 +#define GLX_STENCIL_SIZE 13 +#define GLX_ACCUM_RED_SIZE 14 +#define GLX_ACCUM_GREEN_SIZE 15 +#define GLX_ACCUM_BLUE_SIZE 16 +#define GLX_ACCUM_ALPHA_SIZE 17 + + +/* + * Error codes returned by glXGetConfig: + */ +#define GLX_BAD_SCREEN 1 +#define GLX_BAD_ATTRIBUTE 2 +#define GLX_NO_EXTENSION 3 +#define GLX_BAD_VISUAL 4 +#define GLX_BAD_CONTEXT 5 +#define GLX_BAD_VALUE 6 +#define GLX_BAD_ENUM 7 + +/* + * GLX 1.1 and later: + */ +#define GLX_VENDOR 1 +#define GLX_VERSION 2 +#define GLX_EXTENSIONS 3 + + +/* + * GLX 1.3 and later: + */ +#define GLX_CONFIG_CAVEAT 0x20 +#define GLX_DONT_CARE 0xFFFFFFFF +#define GLX_X_VISUAL_TYPE 0x22 +#define GLX_TRANSPARENT_TYPE 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE 0x24 +#define GLX_TRANSPARENT_RED_VALUE 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE 0x28 +#define GLX_WINDOW_BIT 0x00000001 +#define GLX_PIXMAP_BIT 0x00000002 +#define GLX_PBUFFER_BIT 0x00000004 +#define GLX_AUX_BUFFERS_BIT 0x00000010 +#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001 +#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002 +#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008 +#define GLX_DEPTH_BUFFER_BIT 0x00000020 +#define GLX_STENCIL_BUFFER_BIT 0x00000040 +#define GLX_ACCUM_BUFFER_BIT 0x00000080 +#define GLX_NONE 0x8000 +#define GLX_SLOW_CONFIG 0x8001 +#define GLX_TRUE_COLOR 0x8002 +#define GLX_DIRECT_COLOR 0x8003 +#define GLX_PSEUDO_COLOR 0x8004 +#define GLX_STATIC_COLOR 0x8005 +#define GLX_GRAY_SCALE 0x8006 +#define GLX_STATIC_GRAY 0x8007 +#define GLX_TRANSPARENT_RGB 0x8008 +#define GLX_TRANSPARENT_INDEX 0x8009 +#define GLX_VISUAL_ID 0x800B +#define GLX_SCREEN 0x800C +#define GLX_NON_CONFORMANT_CONFIG 0x800D +#define GLX_DRAWABLE_TYPE 0x8010 +#define GLX_RENDER_TYPE 0x8011 +#define GLX_X_RENDERABLE 0x8012 +#define GLX_FBCONFIG_ID 0x8013 +#define GLX_RGBA_TYPE 0x8014 +#define GLX_COLOR_INDEX_TYPE 0x8015 +#define GLX_MAX_PBUFFER_WIDTH 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT 0x8017 +#define GLX_MAX_PBUFFER_PIXELS 0x8018 +#define GLX_PRESERVED_CONTENTS 0x801B +#define GLX_LARGEST_PBUFFER 0x801C +#define GLX_WIDTH 0x801D +#define GLX_HEIGHT 0x801E +#define GLX_EVENT_MASK 0x801F +#define GLX_DAMAGED 0x8020 +#define GLX_SAVED 0x8021 +#define GLX_WINDOW 0x8022 +#define GLX_PBUFFER 0x8023 +#define GLX_PBUFFER_HEIGHT 0x8040 +#define GLX_PBUFFER_WIDTH 0x8041 +#define GLX_RGBA_BIT 0x00000001 +#define GLX_COLOR_INDEX_BIT 0x00000002 +#define GLX_PBUFFER_CLOBBER_MASK 0x08000000 + +/* + * GLX 1.4 and later: + */ +#define GLX_SAMPLE_BUFFERS 0x186a0 /*100000*/ +#define GLX_SAMPLES 0x186a1 /*100001*/ + +/* glXCreateContextAttribsARB extension definitions */ + #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 + typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); typedef void (*glXSwapIntervalEXTProc) (Display*, GLXDrawable, int); +GLXFBConfig* (*glXChooseFBConfig) (Display* dpy, int screen, const int* attribList, int* nitems); +XVisualInfo* (*glXGetVisualFromFBConfig)(Display* dpy, GLXFBConfig config); +int (*glXGetFBConfigAttrib) (Display* dpy, GLXFBConfig config, int attribute, int *value ); +Bool (*glXMakeCurrent) (Display* dpy, GLXDrawable drawable, GLXContext ctx); +GLXDrawable (*glXGetCurrentDrawable) (void); +__GLXextFuncPtr (*glXGetProcAddressARB) (const GLubyte *); +void (*glXSwapBuffers) (Display* dpy, GLXDrawable drawable); + extern struct gl_wcb wcb_glx; static Display* display; @@ -55,6 +187,39 @@ static void init(void) { focused = false; maximized = false; transparent = false; + + void* hgl = dlopen("libGL.so", RTLD_LAZY); + void* hglx = dlopen("libGLX.so", RTLD_LAZY); + + if (!hgl && !hglx) { + fprintf(stderr, "Failed to load GLX functions (libGL and libGLX do not exist!)\n"); + exit(EXIT_FAILURE); + } + + /* Depending on the graphics driver, the GLX functions that we need may either be in libGL or + libGLX. */ + void* resolve_f(const char* symbol) { + void* s = NULL; + if (hgl) s = dlsym(hgl, symbol); + if (!s && hglx) s = dlsym(hglx, symbol); + if (!s) { + fprintf(stderr, "Failed to resolve GLX symbol: `%s`\n", symbol); + exit(EXIT_FAILURE); + } + return s; + } + + #define resolve(name) do { name = (typeof(name)) resolve_f(#name); } while (0) + + resolve(glXChooseFBConfig); + resolve(glXGetVisualFromFBConfig); + resolve(glXGetFBConfigAttrib); + resolve(glXMakeCurrent); + resolve(glXGetCurrentDrawable); + resolve(glXGetProcAddressARB); + resolve(glXSwapBuffers); + + #undef resolve } static void apply_decorations(Window w) {