#include "compositor.h" #include #include #include #include static double clock_get_monotonic_seconds(void) { struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = 0; clock_gettime(CLOCK_MONOTONIC, &ts); return (double)ts.tv_sec + (double)ts.tv_nsec * 0.000000001; } static ngxc_window* ngxc_compositor_get_window_by_id(ngxc_compositor *self, Window window) { for(int i = 0; i < self->num_windows; ++i) { ngxc_window *window_obj = &self->windows[i]; if(window_obj->texture.window == window) return window_obj; } return NULL; } 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(); } void ngxc_compositor_deinit(ngxc_compositor *self) { } void ngxc_compositor_add_window(ngxc_compositor *self, Window window) { if(self->num_windows == NGXC_COMPOSITOR_MAX_WINDOWS) { fprintf(stderr, "error: reached max number of trackable windows (%d), ignoring window with id %ld\n", NGXC_COMPOSITOR_MAX_WINDOWS, window); return; } XWindowAttributes xattr; if(!XGetWindowAttributes(self->dpy, window, &xattr)) { fprintf(stderr, "error: failed to get window attributes, ignoring window with id %ld\n", window); return; } //Window c; //XTranslateCoordinates(self->dpy, window, DefaultRootWindow(self->dpy), 0, 0, &xattr.x, &xattr.y, &c); ngxc_window *window_obj = &self->windows[self->num_windows]; if(window_texture_init(&window_obj->texture, self->dpy, window) != 0) { fprintf(stderr, "error: failed to create window texture, ignoring window with id %ld\n", window); return; } window_obj->x = xattr.x; window_obj->y = xattr.y; ++self->num_windows; fprintf(stderr, "ADDED WINDOW: %ld, x: %d, y: %d\n", window, xattr.x, xattr.y); } void ngxc_compositor_remove_window(ngxc_compositor *self, Window window) { for(int i = 0; i < self->num_windows; ++i) { if(self->windows[i].texture.window != window) continue; window_texture_deinit(&self->windows[i].texture); for(int j = i + 1; j < self->num_windows; ++j) { self->windows[j - 1] = self->windows[j]; } self->num_windows--; break; } } static void render_texture(const ngxc_window *window) { float matrix[16] = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, }; matrix[0] = 1.0f / (float)window->texture.width; matrix[5] = 1.0f / (float)window->texture.height; glMatrixMode(GL_TEXTURE); glLoadMatrixf(matrix); glMatrixMode(GL_MODELVIEW); glBindTexture(GL_TEXTURE_2D, window->texture.texture_id); glColor4ub(255, 255, 255, 255); //glTranslatef(window->x, window->y, 0.0f); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2f(window->x, window->y); glTexCoord2f(window->texture.width, 0.0f); glVertex2f(window->x + window->texture.width, window->y); glTexCoord2f(window->texture.width, window->texture.height); glVertex2f(window->x + window->texture.width, window->y + window->texture.height); glTexCoord2f(0.0f, window->texture.height); glVertex2f(window->x, window->y + window->texture.height); glEnd(); glLoadIdentity(); glBindTexture(GL_TEXTURE_2D, 0); } /* 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); glClear(GL_COLOR_BUFFER_BIT); for(int i = 0; i < self->num_windows; ++i) { const ngxc_window *window_obj = &self->windows[i]; render_texture(window_obj); } const double now = clock_get_monotonic_seconds(); const double frame_duration = now - self->frame_timer; glXSwapBuffers(self->dpy, self->composite_window); glFlush(); glFinish(); const double time_limit = 1.0f / 60.0f; // TODO: Get from randr const double delayed_update = time_limit - frame_duration - 0.001; //fprintf(stderr, "delayed update: %f\n", delayed_update); if(delayed_update > 0.0) usleep(delayed_update * 1000000.0); self->frame_timer = clock_get_monotonic_seconds(); } void ngxc_compositor_on_configure(ngxc_compositor *self, const XConfigureEvent *configure_event) { ngxc_window *window_obj = ngxc_compositor_get_window_by_id(self, configure_event->window); if(!window_obj) return; window_obj->x = configure_event->x; window_obj->y = configure_event->y; if(configure_event->width != window_obj->texture.width || configure_event->height != window_obj->texture.height) { window_texture_on_resize(&window_obj->texture); } }