From f021457abda59ddc2380209f7e3cab5bbabf1259 Mon Sep 17 00:00:00 2001 From: Jarcode Date: Mon, 12 Feb 2018 12:47:59 -0800 Subject: [PATCH] Added GLX window creation backend, addresses #18 --- Makefile | 16 ++- README.md | 14 ++- glava.c | 12 ++- glfw_wcb.c | 10 +- glx_wcb.c | 279 ++++++++++++++++++++++++++++++++++++++++++++++++ render.c | 65 +++++++---- render.h | 16 +-- shaders/rc.glsl | 4 +- 8 files changed, 365 insertions(+), 51 deletions(-) create mode 100644 glx_wcb.c diff --git a/Makefile b/Makefile index ebb62a3..d3b004e 100644 --- a/Makefile +++ b/Makefile @@ -38,20 +38,30 @@ ifeq ($(INSTALL),unix) endif endif +ifndef DISABLE_GLFW + CFLAGS_GLFW = -DGLAVA_GLFW + LDFLAGS_GLFW = -lglfw +endif + +ifndef DISABLE_GLX + CFLAGS_GLX = -DGLAVA_GLX + LDFLAGS_GLX = -lGLX -lXrender +endif + ifeq ($(INSTALL),osx) CFLAGS_INSTALL = -DGLAVA_OSX SHADER_DIR = Library/glava endif -LDFLAGS = $(ASAN) -lpulse -lpulse-simple -pthread -lglfw -ldl -lm -lX11 -lXext -lXcomposite +LDFLAGS = $(ASAN) -lpulse -lpulse-simple -pthread $(LDFLAGS_GLFW) -ldl -lm -lX11 -lXext $(LDFLAGS_GLX) PYTHON = python GLAD_INSTALL_DIR = glad GLAD_SRCFILE = ./glad/src/glad.c GLAD_ARGS = --generator=$(GLAD_GEN) --extensions=GL_EXT_framebuffer_multisample,GL_EXT_texture_filter_anisotropic -CFLAGS_COMMON = -DGLAVA_GLFW -DGLAVA_GLX -I glad/include -CFLAGS_USE = $(CFLAGS_COMMON) $(CFLAGS_BUILD) $(CFLAGS_INSTALL) $(CFLAGS) +CFLAGS_COMMON = -I glad/include +CFLAGS_USE = $(CFLAGS_COMMON) $(CFLAGS_GLX) $(CFLAGS_GLFW) $(CFLAGS_BUILD) $(CFLAGS_INSTALL) $(CFLAGS) all: glava diff --git a/README.md b/README.md index d4cfe02..e46cd4f 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ You can pass `BUILD=debug` to the makefile for debug builds of both glad and gla - X11 - PulseAudio -- GLFW 3.1+ +- GLFW 3.1+ (optional, disable with `DISABLE_GLFW=1`) - Linux or BSD **Additional compile time requirements:** @@ -27,8 +27,9 @@ 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 and run GLava: +**Ubuntu/Debian users:** the following command ensures you have all the needed packages and headers to compile GLava: ```bash sudo apt-get install libpulse libpulse-dev libglfw3 libglfw3-dev libxext6 libxext6-dev python make gcc ``` @@ -43,28 +44,25 @@ To embed GLava in your desktop (for EWMH compliant window managers), use `#reque \* On an XDG compliant Linux or BSD system. OSX will use `/Library/glava` and `~/Library/Preferences/glava` instead. -**Note for `#request setopacity`:** While most users will prefer the faster `xroot` transparency, GLFW 3.3 (unreleased) is needed in order to support the `native` transparency option (older versions still work). Arch users can install `glfw-x11-git` from the AUR and recompile GLava for this feature. - ## Desktop window compatibility GLava aims to be compatible with _most_ EWMH compliant window managers. Below is a list of common window managers and issues specific to them for trying to get GLava to behave as a desktop window or widget: | WM | ! | Details | :---: | --- | --- | -| GNOME (on X11) | ![-](https://placehold.it/15/118932/000000?text=+) | No notable issues +| Mutter (GNOME, Budgie) | ![-](https://placehold.it/15/118932/000000?text=+) | `"native"` (default) opacity should be used | Openbox (LXDE or standalone) | ![-](https://placehold.it/15/118932/000000?text=+) | [Some tweaks may be required](https://www.reddit.com/r/unixporn/comments/7vcgi4/oc_after_receiving_positive_feedback_here_i/dtrkvja/) | Xfwm (XFCE) | ![-](https://placehold.it/15/118932/000000?text=+) | Untested, but should work without issues | Fluxbox | ![-](https://placehold.it/15/118932/000000?text=+) | Untested, but should work without issues | iceWM | ![-](https://placehold.it/15/118932/000000?text=+) | No notable issues -| AwesomeWM | ![-](https://placehold.it/15/f09c00/000000?text=+) | Requires the WM to be restarted (`Super + Ctl + R`) in order for new desktop windows to behave correctly, can still be focused, may require other changes to config depending on layout -| Budgie Desktop | ![-](https://placehold.it/15/f09c00/000000?text=+) | `"xroot"` transparency breaks with Budgie's wallpaper window +| Herbstluftwm | ![-](https://placehold.it/15/118932/000000?text=+) | `hc rule windowtype~'_NET_WM_WINDOW_TYPE_DESKTOP' manage=off` can be used to unmanage desktop windows +| AwesomeWM | ![-](https://placehold.it/15/f09c00/000000?text=+) | Can still be focused, may require other changes to config depending on layout | kwin (KDE) | ![-](https://placehold.it/15/f09c00/000000?text=+) | [Issues with workspaces and stacking](https://github.com/wacossusca34/glava/issues/4), needs further testing | i3 (and i3-gaps) | ![-](https://placehold.it/15/f03c15/000000?text=+) | [i3 does not respect the `"desktop"` window type](https://github.com/wacossusca34/glava/issues/6) | EXWM | ![-](https://placehold.it/15/f03c15/000000?text=+) | EXWM does not have a desktop, and forces window decorations | Unity | ![-](https://placehold.it/15/1589F0/000000?text=+) | Needs testing | Enlightenment | ![-](https://placehold.it/15/1589F0/000000?text=+) | Needs testing | Bspwm | ![-](https://placehold.it/15/1589F0/000000?text=+) | Needs testing -| Herbstluftwm | ![-](https://placehold.it/15/1589F0/000000?text=+) | Needs testing | xmonad | ![-](https://placehold.it/15/1589F0/000000?text=+) | Needs testing | Any non EWMH-compliant WM | ![-](https://placehold.it/15/f03c15/000000?text=+) | Window types and hints will not work if the window manager does not support the EWMH standards. diff --git a/glava.c b/glava.c index 83a371d..48ea48a 100644 --- a/glava.c +++ b/glava.c @@ -18,7 +18,7 @@ #include "render.h" #include "xwin.h" -#define GLAVA_VERSION "1.3" +#define GLAVA_VERSION "1.4" #ifdef GLAD_DEBUG #define GLAVA_RELEASE_TYPE_PREFIX "debug, " #else @@ -167,18 +167,22 @@ static const char* help_str = "-C, --copy-config creates copies and symbolic links in the user configuration\n" " directory for glava, copying any files in the root directory\n" " of the installed shader directory, and linking any modules.\n" + "-b, --backend specifies a window creation backend to use. By default, the most\n" + " appropriate backend will be used for the underlying windowing\n" + " system.\n" "-V, --version print application version and exit\n" "\n" GLAVA_VERSION_STRING "\n" " -- Copyright (C) 2017 Levi Webb\n"; -static const char* opt_str = "hvVe:Cm:"; +static const char* opt_str = "hvVe:Cm:b:"; static struct option p_opts[] = { {"help", no_argument, 0, 'h'}, {"verbose", no_argument, 0, 'v'}, {"entry", required_argument, 0, 'e'}, {"force-mod", required_argument, 0, 'm'}, {"copy-config", no_argument, 0, 'C'}, + {"backend", required_argument, 0, 'b'}, {"version", no_argument, 0, 'V'}, {0, 0, 0, 0 } }; @@ -190,6 +194,7 @@ int main(int argc, char** argv) { const char* user_path = SHADER_USER_PATH; const char* entry = "rc.glsl"; const char* force = NULL; + const char* backend = NULL; const char* system_shader_paths[] = { user_path, install_path, NULL }; bool verbose = false; bool copy_mode = false; @@ -201,6 +206,7 @@ int main(int argc, char** argv) { case 'C': copy_mode = true; break; case 'e': entry = optarg; break; case 'm': force = optarg; break; + case 'b': backend = optarg; break; case '?': exit(EXIT_FAILURE); break; case 'V': puts(GLAVA_VERSION_STRING); @@ -219,7 +225,7 @@ int main(int argc, char** argv) { exit(EXIT_SUCCESS); } - renderer* r = rd_new(system_shader_paths, entry, force); + renderer* r = rd_new(system_shader_paths, entry, force, backend); float b0[r->bufsize_request], b1[r->bufsize_request]; size_t t; diff --git a/glfw_wcb.c b/glfw_wcb.c index 208e9e8..9d74a21 100644 --- a/glfw_wcb.c +++ b/glfw_wcb.c @@ -37,9 +37,9 @@ #endif #define DECL_WINDOW_HINT(F, H) \ - static void F(void* _, bool var) { glfwWindowHint(H, var); } + static void F(bool var) { glfwWindowHint(H, var); } #define DECL_WINDOW_HINT_STUB(F) \ - static void F(void* _, bool _) { fprintf(stderr, "Warning: " #F " not implemented for GLFW backend\n"); } + static void F(bool _) { fprintf(stderr, "Warning: " #F " not implemented for GLFW backend\n"); } static void init(void) { if (!glfwInit()) { @@ -97,7 +97,7 @@ static void* create_and_bind(const char* name, const char* class, return w; } -static void set_transparent(GLFWwindow* w, bool transparent) { +static void set_transparent(bool transparent) { #ifdef GLFW_TRANSPARENT_FRAMEBUFFER glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, transparent ? GLFW_TRUE : GLFW_FALSE); #elif GLFW_TRANSPARENT @@ -124,14 +124,14 @@ static bool swap_buffers(GLFWwindow* w) { glfwPollEvents(); } -static Display* get_x11_display(GLFWwindow* w) { return glfwGetX11Display(); } +static Display* get_x11_display(void) { return glfwGetX11Display(); } static Window get_x11_window (GLFWwindow* w) { return glfwGetX11Window(w); } static bool should_close (GLFWwindow* w) { return glfwWindowShouldClose(w); } static void get_fbsize (GLFWwindow* w, int* d, int* h) { glfwGetFramebufferSize(w, d, h); } static void get_pos (GLFWwindow* w, int* x, int* y) { glfwGetWindowPos(w, x, y); } static double get_time (GLFWwindow* w) { return glfwGetTime(); } static void set_time (GLFWwindow* w, double time) { glfwSetTime(time); } -static void set_swap (GLFWwindow* w, int i) { glfwSwapInterval(i); } +static void set_swap (int i) { glfwSwapInterval(i); } WCB_ATTACH("glfw", wcb_glfw); diff --git a/glx_wcb.c b/glx_wcb.c new file mode 100644 index 0000000..659cca0 --- /dev/null +++ b/glx_wcb.c @@ -0,0 +1,279 @@ + +/* Xlib window creation and GLX context creation backend */ + +#ifdef GLAVA_GLX + +#define GLAVA_RDX11 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "render.h" +#include "xwin.h" + +#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); + +extern struct gl_wcb wcb_glx; + +static Display* display; + +static int swap; + +static bool floating, decorated, focused, maximized, transparent; + +struct glxwin { + Window w; + GLXContext context; + double time; + bool should_close; +}; + +static void init(void) { + display = XOpenDisplay(NULL); + if (!display) { + fprintf(stderr, "XOpenDisplay(): could not establish connection to X11 server\n"); + abort(); + } + floating = false; + decorated = true; + focused = false; + maximized = false; + transparent = false; +} + +static void apply_decorations(Window w) { + if (!decorated) { + struct { + unsigned long flags, functions, decorations; + long input_mode; + unsigned long status; + } hints; + + hints.flags = 2; + hints.decorations = 0; + + Atom motif = XInternAtom(display, "_MOTIF_WM_HINTS", false); + + XChangeProperty(display, w, motif, motif, 32, PropModeReplace, + (unsigned char*) &hints, sizeof(hints) / sizeof(long)); + } +} + +static void* create_and_bind(const char* name, const char* class, + const char* type, const char** states, + size_t states_sz, + int d, int h, + int x, int y, + int version_major, int version_minor) { + struct glxwin* w = malloc(sizeof(struct glxwin)); + w->time = 0.0D; + w->should_close = false; + + XVisualInfo* vi; + XSetWindowAttributes attr; + GC gc; + GLXFBConfig* fbc; + int fb_sz, best = -1, samp = -1; + + static int gl_attrs[] = { + GLX_X_RENDERABLE, True, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, + GLX_DOUBLEBUFFER, True, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + None + }; + + int context_attrs[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, version_major, + GLX_CONTEXT_MINOR_VERSION_ARB, version_minor, + // GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + None + }; + + fbc = glXChooseFBConfig(display, DefaultScreen(display), gl_attrs, &fb_sz); + if (!fbc) { + fprintf(stderr, "glXChooseFBConfig(): failed\n" ); + abort(); + } + + for (int t = 0; t < fb_sz; ++t) { + XVisualInfo* xvi = glXGetVisualFromFBConfig(display, fbc[t]); + if (xvi) { + int samp_buf, samples; + glXGetFBConfigAttrib(display, fbc[t], GLX_SAMPLE_BUFFERS, &samp_buf); + glXGetFBConfigAttrib(display, fbc[t], GLX_SAMPLES, &samples ); + XRenderPictFormat* fmt = XRenderFindVisualFormat(display, xvi->visual); + + if (!fmt || (transparent ? fmt->direct.alphaMask == 0 : fmt->direct.alphaMask != 0)) + continue; + + if (best < 0 || samp_buf && samples > samp) { + best = t; + samp = samples; + } + XFree(xvi); + } + } + + if (best == -1) { + fprintf(stderr, "Could not find suitable format for FBConfig\n"); + abort(); + } + + GLXFBConfig config = fbc[best]; + XFree(fbc); + + vi = glXGetVisualFromFBConfig(display, config); + + attr.colormap = XCreateColormap(display, DefaultRootWindow(display), vi->visual, AllocNone); + attr.event_mask = ExposureMask | KeyPressMask | StructureNotifyMask; + attr.background_pixmap = None; + attr.border_pixel = 0; + + if (!(w->w = XCreateWindow(display, DefaultRootWindow(display), + x, y, d, h, 0, + vi->depth, InputOutput, vi->visual, + CWColormap | CWEventMask | CWBackPixmap | CWBorderPixel, + &attr))) { + fprintf(stderr, "XCreateWindow(): failed\n"); + abort(); + } + + if (type) + xwin_settype(&wcb_glx, w, type); + + for (size_t t = 0; t < states_sz; ++t) + xwin_addstate(&wcb_glx, w, states[t]); + + if (floating) xwin_addstate(&wcb_glx, w, "above"); + if (maximized) { + xwin_addstate(&wcb_glx, w, "maximized_horz"); + xwin_addstate(&wcb_glx, w, "maximized_vert"); + } + + apply_decorations(w->w); + + XFree(vi); + + gc = XCreateGC(display, w->w, 0, 0); + + XStoreName(display, w->w, name); + + Atom dwin = XInternAtom(display, "WM_DELETE_WINDOW", false); + XSetWMProtocols(display, w->w, &dwin, 1); + + glXCreateContextAttribsARBProc glXCreateContextAttribsARB = NULL; + glXSwapIntervalEXTProc glXSwapIntervalEXT = NULL; + glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) + glXGetProcAddressARB((const GLubyte*) "glXCreateContextAttribsARB"); + glXSwapIntervalEXT = (glXSwapIntervalEXTProc) + glXGetProcAddressARB((const GLubyte*) "glXSwapIntervalEXT"); + + if (!glXCreateContextAttribsARB) { + fprintf(stderr, "glXGetProcAddressARB(\"glXCreateContextAttribsARB\"): failed\n"); + abort(); + } + + if (!(w->context = glXCreateContextAttribsARB(display, config, 0, True, context_attrs))) { + fprintf(stderr, "glXCreateContextAttribsARB(): failed\n"); + abort(); + } + + XSync(display, False); + + glXMakeCurrent(display, w->w, w->context); + gladLoadGL(); + + GLXDrawable drawable = glXGetCurrentDrawable(); + + if (glXSwapIntervalEXT) glXSwapIntervalEXT(display, drawable, swap); + + return w; +} + +static void set_swap (int _swap) { swap = _swap; } +static void set_floating (bool _floating) { floating = _floating; } +static void set_decorated (bool _decorated) { decorated = _decorated; } +static void set_focused (bool _focused) { focused = _focused; } +static void set_maximized (bool _maximized) { maximized = _maximized; } +static void set_transparent(bool _transparent) { transparent = _transparent; } + +static void set_geometry(struct glxwin* w, int x, int y, int d, int h) { + XMoveResizeWindow(display, w->w, x, y, (unsigned int) d, (unsigned int) h); +} + +static void set_visible(struct glxwin* w, bool visible) { + if (visible) XMapWindow(display, w->w); + else XUnmapWindow(display, w->w); +} + +static bool should_close(struct glxwin* w) { + return w->should_close; +} + +static void swap_buffers(struct glxwin* w) { + glXSwapBuffers(display, w->w); + + while (XPending(display) > 0) { + XEvent ev; + XNextEvent(display, &ev); + switch (ev.type) { + case ClientMessage: + if (ev.xclient.message_type == XInternAtom(display, "WM_PROTOCOLS", 1) + && ev.xclient.data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", 1)) { + w->should_close = true; + } + default: break; + } + } +} + +static void get_fbsize(struct glxwin* w, int* d, int* h) { + XWindowAttributes a; + XGetWindowAttributes(display, w->w, &a); + *d = a.width; + *h = a.height; +} + +static void get_pos(struct glxwin* w, int* x, int* y) { + XWindowAttributes a; + Window _ignored; + XTranslateCoordinates(display, w->w, DefaultRootWindow(display), 0, 0, x, y, &_ignored); +} + +static double get_timert(void) { + struct timespec tv; + if (clock_gettime(CLOCK_REALTIME, &tv)) { + fprintf(stderr, "clock_gettime(CLOCK_REALTIME, ...): %s\n", strerror(errno)); + } + return (double) tv.tv_sec + ((double) tv.tv_nsec / 1000000000.0D); +} + +static double get_time (struct glxwin* w) { return get_timert() - w->time; } +static void set_time (struct glxwin* w, double time) { w->time = get_timert() - time; } +static Display* get_x11_display(struct glxwin* w) { return display; } +static Window get_x11_window (struct glxwin* w) { return w->w; } + +WCB_ATTACH("glx", wcb_glx); + +#endif /* GLAVA_GLX */ diff --git a/render.c b/render.c index c14e62c..3a94648 100644 --- a/render.c +++ b/render.c @@ -35,18 +35,17 @@ #define VERTEX_SHADER_SRC \ "layout(location = 0) in vec3 pos; void main() { gl_Position = vec4(pos.x, pos.y, 0.0F, 1.0F); }" -/* Window creation backend interfaces */ -#ifdef GLAVA_GLFW -extern struct gl_wcb wcb_glfw; -#endif +struct gl_wcb* wcbs[2] = {}; +static size_t wcbs_idx = 0; -#define INIT_WCBS() \ +static inline void register_wcb(struct gl_wcb* wcb) { wcbs[wcbs_idx++] = wcb; } + +#define DECL_WCB(N) \ do { \ - wcbs[0] = wcb_glfw; \ + extern struct gl_wcb N; \ + register_wcb(&N); \ } while (0) -struct gl_wcb wcbs[2] = {}; - /* GLSL bind source */ struct gl_bind_src { @@ -682,7 +681,8 @@ static struct gl_bind_src* lookup_bind_src(const char* str) { return NULL; } -struct renderer* rd_new(const char** paths, const char* entry, const char* force_mod) { +struct renderer* rd_new(const char** paths, const char* entry, + const char* force_mod, const char* force_backend) { renderer* r = malloc(sizeof(struct renderer)); *r = (struct renderer) { @@ -727,19 +727,40 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force .clear_color = { 0.0F, 0.0F, 0.0F, 0.0F } }; - const char* backend = "glfw"; + bool forced = force_backend != NULL; + const char* backend = force_backend; - INIT_WCBS(); + /* Window creation backend interfaces */ + #ifdef GLAVA_GLFW + DECL_WCB(wcb_glfw); + if (!forced) backend = "glfw"; + #endif - #ifdef GLAVA_UNIX - if (!getenv("WAYLAND_DISPLAY") && getenv("DISPLAY")) { - // backend = "glx"; + #ifdef GLAVA_GLX + DECL_WCB(wcb_glx); + if (!forced && !getenv("WAYLAND_DISPLAY") && getenv("DISPLAY")) { + backend = "glx"; } #endif - for (size_t t = 0; t < sizeof(wcbs) / sizeof(*wcbs); ++t) { - if (wcbs[t].name && !strcmp(wcbs[t].name, backend)) { - gl->wcb = &wcbs[t]; + if (!backend) { + fprintf(stderr, "No backend available for the active windowing system\n"); + if (wcbs_idx == 0) { + fprintf(stderr, "None have been compiled into this build.\n"); + } else { + fprintf(stderr, "Available backends:\n"); + for (size_t t = 0; t < wcbs_idx; ++t) { + fprintf(stderr, "\t\"%s\"\n", wcbs[t]->name); + } + } + exit(EXIT_FAILURE); + } + + printf("Using backend: '%s'\n", backend); + + for (size_t t = 0; t < wcbs_idx; ++t) { + if (wcbs[t]->name && !strcmp(wcbs[t]->name, backend)) { + gl->wcb = wcbs[t]; break; } }; @@ -773,7 +794,7 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force #define WINDOW_HINT(request) \ { .name = "set" #request, .fmt = "b", \ - .handler = RHANDLER(name, args, { gl->wcb->set_##request(gl->w, *(bool*) args[0]); }) } + .handler = RHANDLER(name, args, { gl->wcb->set_##request(*(bool*) args[0]); }) } struct request_handler handlers[] = { { @@ -784,7 +805,7 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force gl->use_alpha = true; - gl->wcb->set_transparent(gl->w, native_opacity); + gl->wcb->set_transparent(native_opacity); if (!strcmp("xroot", (char*) args[0])) gl->copy_desktop = true; @@ -870,7 +891,7 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force { .name = "setshaderversion", .fmt = "i", .handler = RHANDLER(name, args, { shader_version = *(int*) args[0]; }) }, { .name = "setswap", .fmt = "i", - .handler = RHANDLER(name, args, { gl->wcb->set_swap(gl->w, *(int*) args[0]); }) }, + .handler = RHANDLER(name, args, { gl->wcb->set_swap(*(int*) args[0]); }) }, { .name = "setframerate", .fmt = "i", .handler = RHANDLER(name, args, { gl->rate = *(int*) args[0]; }) }, { .name = "setprintframes", .fmt = "b", @@ -1334,8 +1355,8 @@ void rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi "out vec4 fragment;" "\n" "in vec4 gl_FragCoord;" "\n" "void main() {" "\n" - " fragment = texture(tex, vec2(gl_FragCoord.x / screen.x, " "\n" - " (screen.y - gl_FragCoord.y) / screen.y));" "\n" + " fragment = texelFetch(tex, ivec2(gl_FragCoord.x, " "\n" + " screen.y - gl_FragCoord.y), 0);" "\n" " fragment.a = 1.0F;" "\n" "}" "\n"; if (!setup) { diff --git a/render.h b/render.h index ed6dcc5..25f03c2 100644 --- a/render.h +++ b/render.h @@ -12,7 +12,7 @@ typedef struct renderer { } renderer; struct renderer* rd_new (const char** paths, const char* entry, - const char* force_mod); + const char* force_mod, const char* force_backend); void rd_update (struct renderer*, float* lb, float* rb, size_t bsz, bool modified); void rd_destroy (struct renderer*); @@ -22,7 +22,7 @@ struct gl_wcb* rd_get_wcb (struct renderer*); /* gl_wcb - OpenGL Window Creation Backend interface */ struct gl_wcb { - const char* name;\ + const char* name; void (*init) (void); void* (*create_and_bind)(const char* name, const char* class, const char* type, const char** states, @@ -32,15 +32,15 @@ struct gl_wcb { int version_major, int version_minor); bool (*should_close) (void* ptr); bool (*swap_buffers) (void* ptr); - void (*set_swap) (void* ptr, int interval); void (*get_pos) (void* ptr, int* x, int* y); void (*get_fbsize) (void* ptr, int* w, int* h); void (*set_geometry) (void* ptr, int x, int y, int w, int h); - void (*set_floating) (void* ptr, bool floating); - void (*set_decorated) (void* ptr, bool decorated); - void (*set_focused) (void* ptr, bool focused); - void (*set_maximized) (void* ptr, bool maximized); - void (*set_transparent)(void* ptr, bool transparent); + void (*set_swap) (int interval); + void (*set_floating) (bool floating); + void (*set_decorated) (bool decorated); + void (*set_focused) (bool focused); + void (*set_maximized) (bool maximized); + void (*set_transparent)(bool transparent); double (*get_time) (void* ptr); void (*set_time) (void* ptr, double time); void (*set_visible) (void* ptr, bool visible); diff --git a/shaders/rc.glsl b/shaders/rc.glsl index cf1dc47..f5a31a7 100644 --- a/shaders/rc.glsl +++ b/shaders/rc.glsl @@ -51,7 +51,7 @@ #request settitle "GLava" /* GLFW window geometry (x, y, width, height) */ -#request setgeometry 0 0 400 600 +#request setgeometry 0 0 800 600 /* Window background color (RGB format). Only works with `setopacity "none"` */ @@ -68,7 +68,7 @@ https://standards.freedesktop.org/wm-spec/wm-spec-1.3.html#idm140130317606816 */ -#request setxwintype "normal" +#request setxwintype "desktop" /* (X11 only) EWMH Window state atoms (multiple can be specified). Possible values are: