aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2024-01-11 23:47:35 +0100
committerdec05eba <dec05eba@protonmail.com>2024-01-11 23:47:35 +0100
commit705ad3bee5de67725311d4085f0481fa7107ba41 (patch)
tree78879a96cdab04878072db18d51465560d95e094
parentc4fb95cf0025b34ca14c22f4fbbfcef14d56d71c (diff)
Render wallpaper
-rwxr-xr-xbuild.sh1
-rw-r--r--src/compositor.c74
-rw-r--r--src/compositor.h4
-rw-r--r--src/pixmap_texture.c140
-rw-r--r--src/pixmap_texture.h28
-rw-r--r--src/window_texture.c10
6 files changed, 239 insertions, 18 deletions
diff --git a/build.sh b/build.sh
index 4ae804d..b749f9f 100755
--- a/build.sh
+++ b/build.sh
@@ -13,5 +13,6 @@ includes="$(pkg-config --cflags $dependencies)"
mkdir -p build
$CC -c src/compositor.c -o build/compositor.o $opts $includes
$CC -c src/window_texture.c -o build/window_texture.o $opts $includes
+$CC -c src/pixmap_texture.c -o build/pixmap_texture.o $opts $includes
$CC -c src/main.c -o build/main.o $opts $includes
$CC build/*.o -o ngxc $opts $libs
diff --git a/src/compositor.c b/src/compositor.c
index 1e75d77..994404e 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -1,9 +1,14 @@
#include "compositor.h"
+
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
+#include <X11/Xatom.h>
+
+/* TODO: Handle wallpaper change and update on root window resize */
+
static double clock_get_monotonic_seconds(void) {
struct timespec ts;
ts.tv_sec = 0;
@@ -24,15 +29,50 @@ static ngxc_window* ngxc_compositor_get_window_by_id(ngxc_compositor *self, Wind
return NULL;
}
+static Pixmap x11_wallpaper_get_pixmap(ngxc_compositor *self) {
+ const char *background_props[] = {
+ "_XROOTPMAP_ID",
+ "_XSETROOT_ID",
+ NULL
+ };
+
+ const Window root_window = DefaultRootWindow(self->dpy);
+ Pixmap wallpaper_pixmap = None;
+
+ for(int i = 0; background_props[i]; ++i) {
+ const Atom atom = XInternAtom(self->dpy, background_props[i], False);
+ Atom actual_type;
+ int actual_format;
+ unsigned long items_count;
+ unsigned long bytes_after;
+ unsigned char *prop = NULL;
+ if(XGetWindowProperty(self->dpy, root_window, atom, 0, 1, False, XA_PIXMAP, &actual_type, &actual_format, &items_count, &bytes_after, &prop) == Success && prop) {
+ wallpaper_pixmap = *(Pixmap*)prop;
+ XFree(prop);
+ break;
+ }
+
+ if(prop)
+ XFree(prop);
+ }
+
+ return wallpaper_pixmap;
+}
+
void ngxc_compositor_init(ngxc_compositor *self, Display *dpy, Window composite_window) {
memset(self, 0, sizeof(*self));
self->dpy = dpy;
self->composite_window = composite_window;
self->frame_timer = clock_get_monotonic_seconds();
+
+ const Pixmap wallpaper_pixmap = x11_wallpaper_get_pixmap(self);
+ if(!ngxc_pixmap_texture_init(&self->wallpaper_texture, self->dpy, wallpaper_pixmap)) {
+ fprintf(stderr, "error: failed to create texture for wallpaper pixmap %ld\n", wallpaper_pixmap);
+ }
}
void ngxc_compositor_deinit(ngxc_compositor *self) {
-
+ /* TODO: Cleanup? */
}
void ngxc_compositor_add_window(ngxc_compositor *self, Window window) {
@@ -101,7 +141,7 @@ void ngxc_compositor_remove_window(ngxc_compositor *self, Window window) {
}
}
-static void render_texture(const ngxc_window *window) {
+static void render_texture(GLuint texture_id, int x, int y, int width, int height) {
float matrix[16] = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
@@ -109,28 +149,28 @@ static void render_texture(const ngxc_window *window) {
0.0f, 0.0f, 0.0f, 1.0f,
};
- matrix[0] = 1.0f / (float)window->texture.width;
- matrix[5] = 1.0f / (float)window->texture.height;
+ matrix[0] = 1.0f / (float)width;
+ matrix[5] = 1.0f / (float)height;
glMatrixMode(GL_TEXTURE);
glLoadMatrixf(matrix);
glMatrixMode(GL_MODELVIEW);
- glBindTexture(GL_TEXTURE_2D, window->texture.texture_id);
+ glBindTexture(GL_TEXTURE_2D, texture_id);
glColor4ub(255, 255, 255, 255);
- //glTranslatef(window->x, window->y, 0.0f);
+ //glTranslatef(x, y, 0.0f);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
- glVertex2f(window->x, window->y);
+ glVertex2f(x, y);
- glTexCoord2f(window->texture.width, 0.0f);
- glVertex2f(window->x + window->texture.width, window->y);
+ glTexCoord2f(width, 0.0f);
+ glVertex2f(x + width, y);
- glTexCoord2f(window->texture.width, window->texture.height);
- glVertex2f(window->x + window->texture.width, window->y + window->texture.height);
+ glTexCoord2f(width, height);
+ glVertex2f(x + width, y + height);
- glTexCoord2f(0.0f, window->texture.height);
- glVertex2f(window->x, window->y + window->texture.height);
+ glTexCoord2f(0.0f, height);
+ glVertex2f(x, y + height);
glEnd();
glLoadIdentity();
@@ -140,12 +180,16 @@ static void render_texture(const ngxc_window *window) {
/* TODO: Skip windows that are not visible on the screen */
/* TODO: Disable compositing for fullscreen windows, if that option is enabled */
void ngxc_compositor_render(ngxc_compositor *self) {
- glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+ glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
+ if(self->wallpaper_texture.texture_id > 0) {
+ render_texture(self->wallpaper_texture.texture_id, 0, 0, self->wallpaper_texture.width, self->wallpaper_texture.height);
+ }
+
for(int i = 0; i < self->num_windows; ++i) {
const ngxc_window *window_obj = &self->windows[i];
- render_texture(window_obj);
+ render_texture(window_obj->texture.texture_id, window_obj->x, window_obj->y, window_obj->texture.width, window_obj->texture.height);
}
const double now = clock_get_monotonic_seconds();
diff --git a/src/compositor.h b/src/compositor.h
index cf520d5..f6db300 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -2,6 +2,7 @@
#define NGXC_COMPOSITOR_H
#include "window_texture.h"
+#include "pixmap_texture.h"
// TODO: Make dynamic
#define NGXC_COMPOSITOR_MAX_WINDOWS 100
@@ -16,6 +17,9 @@ typedef struct {
Display *dpy;
Window composite_window;
double frame_timer;
+
+ ngxc_pixmap_texture wallpaper_texture;
+
ngxc_window windows[NGXC_COMPOSITOR_MAX_WINDOWS];
int num_windows;
} ngxc_compositor;
diff --git a/src/pixmap_texture.c b/src/pixmap_texture.c
new file mode 100644
index 0000000..b31b346
--- /dev/null
+++ b/src/pixmap_texture.c
@@ -0,0 +1,140 @@
+#include "pixmap_texture.h"
+
+#include <stdio.h>
+
+bool ngxc_pixmap_texture_init(ngxc_pixmap_texture *window_texture, Display *display, Pixmap pixmap) {
+ window_texture->display = display;
+ window_texture->pixmap = pixmap;
+ window_texture->glx_pixmap = None;
+ window_texture->texture_id = 0;
+ window_texture->width = 0;
+ window_texture->height = 0;
+ return ngxc_pixmap_texture_on_resize(window_texture);
+}
+
+static void ngxc_pixmap_texture_cleanup(ngxc_pixmap_texture *self, int delete_texture) {
+ if(delete_texture && self->texture_id) {
+ glDeleteTextures(1, &self->texture_id);
+ self->texture_id = 0;
+ }
+
+ if(self->glx_pixmap) {
+ glXDestroyPixmap(self->display, self->glx_pixmap);
+ glXReleaseTexImageEXT(self->display, self->glx_pixmap, GLX_FRONT_EXT);
+ self->glx_pixmap = None;
+ }
+}
+
+void ngxc_pixmap_texture_deinit(ngxc_pixmap_texture *self) {
+ ngxc_pixmap_texture_cleanup(self, 1);
+}
+
+bool ngxc_pixmap_texture_on_resize(ngxc_pixmap_texture *self) {
+ ngxc_pixmap_texture_cleanup(self, 0);
+
+ GLXFBConfig *configs = NULL;
+ GLXPixmap glx_pixmap = None;
+ GLuint texture_id = 0;
+ int glx_pixmap_bound = 0;
+
+ const int pixmap_config[] = {
+ GLX_BIND_TO_TEXTURE_RGB_EXT, True,
+ GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT | GLX_WINDOW_BIT,
+ GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
+ /*GLX_BIND_TO_MIPMAP_TEXTURE_EXT, True,*/
+ GLX_BUFFER_SIZE, 24,
+ GLX_RED_SIZE, 8,
+ GLX_GREEN_SIZE, 8,
+ GLX_BLUE_SIZE, 8,
+ GLX_ALPHA_SIZE, 0,
+ None
+ };
+
+ const int pixmap_attribs[] = {
+ GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
+ GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
+ /*GLX_MIPMAP_TEXTURE_EXT, True,*/
+ None
+ };
+
+ Window root_window;
+ int x, y;
+ unsigned int width = 0;
+ unsigned int height = 0;
+ unsigned int border_width;
+ unsigned int depth = 32;
+ if(!XGetGeometry(self->display, self->pixmap, &root_window, &x, &y, &width, &height, &border_width, &depth)) {
+ fprintf(stderr, "Failed to get pixmap attributes\n");
+ return false;
+ }
+
+ GLXFBConfig config;
+ int c;
+ configs = glXChooseFBConfig(self->display, 0, pixmap_config, &c);
+ if(!configs) {
+ fprintf(stderr, "Failed to choose fb config\n");
+ return false;
+ }
+
+ int found = 0;
+ for (int i = 0; i < c; i++) {
+ config = configs[i];
+ XVisualInfo *visual = glXGetVisualFromFBConfig(self->display, config);
+ if(!visual)
+ continue;
+
+ if((int)depth != visual->depth) {
+ XFree(visual);
+ continue;
+ }
+ XFree(visual);
+ found = 1;
+ break;
+ }
+
+ if(!found) {
+ fprintf(stderr, "No matching fb config found\n");
+ goto cleanup;
+ }
+
+ glx_pixmap = glXCreatePixmap(self->display, config, self->pixmap, pixmap_attribs);
+ if(!glx_pixmap) {
+ goto cleanup;
+ }
+
+ if(self->texture_id == 0) {
+ glGenTextures(1, &texture_id);
+ if(texture_id == 0) {
+ goto cleanup;
+ }
+ glBindTexture(GL_TEXTURE_2D, texture_id);
+ } else {
+ glBindTexture(GL_TEXTURE_2D, self->texture_id);
+ }
+
+ glXBindTexImageEXT(self->display, glx_pixmap, GLX_FRONT_EXT, NULL);
+ glx_pixmap_bound = 1;
+
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ self->width = width;
+ self->height = height;
+
+ XFree(configs);
+ self->glx_pixmap = glx_pixmap;
+ if(texture_id != 0)
+ self->texture_id = texture_id;
+ return true;
+
+ cleanup:
+ if(texture_id != 0) glDeleteTextures(1, &texture_id);
+ if(glx_pixmap) glXDestroyPixmap(self->display, glx_pixmap);
+ if(glx_pixmap_bound) glXReleaseTexImageEXT(self->display, glx_pixmap, GLX_FRONT_EXT);
+ if(configs) XFree(configs);
+ return false;
+}
diff --git a/src/pixmap_texture.h b/src/pixmap_texture.h
new file mode 100644
index 0000000..37f7ec4
--- /dev/null
+++ b/src/pixmap_texture.h
@@ -0,0 +1,28 @@
+#ifndef NGXC_PIXMAP_TEXTURE_H
+#define NGXC_PIXMAP_TEXTURE_H
+
+#include <stdbool.h>
+
+#define GLX_GLXEXT_PROTOTYPES
+#include <GL/glx.h>
+#include <GL/glxext.h>
+#include <X11/Xlib.h>
+
+typedef struct {
+ Display *display;
+ Pixmap pixmap;
+ GLXPixmap glx_pixmap;
+ GLuint texture_id;
+ int width;
+ int height;
+} ngxc_pixmap_texture;
+
+bool ngxc_pixmap_texture_init(ngxc_pixmap_texture *self, Display *display, Pixmap pixmap);
+void ngxc_pixmap_texture_deinit(ngxc_pixmap_texture *self);
+
+/*
+ This should ONLY be called when the pixmap is resized.
+*/
+bool ngxc_pixmap_texture_on_resize(ngxc_pixmap_texture *self);
+
+#endif /* NGXC_PIXMAP_TEXTURE_H */
diff --git a/src/window_texture.c b/src/window_texture.c
index c3bde72..bd4c558 100644
--- a/src/window_texture.c
+++ b/src/window_texture.c
@@ -1,7 +1,11 @@
#include "window_texture.h"
-#include <X11/extensions/Xcomposite.h>
+
#include <stdio.h>
+#include <X11/extensions/Xcomposite.h>
+
+/* TODO: Use pixmap_texture for window_texture */
+
int window_texture_init(WindowTexture *window_texture, Display *display, Window window) {
window_texture->display = display;
window_texture->window = window;
@@ -137,8 +141,8 @@ int window_texture_on_resize(WindowTexture *self) {
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
/*
float fLargest = 0.0f;