1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 composite.c for the Openbox window manager
4 Copyright (c) 2010 Dana Jansens
5 Copyright (c) 2010 Derek Foreman
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 See the COPYING file for a copy of the GNU General Public License.
20 #include "composite.h"
22 #include "obt/display.h"
32 #ifdef USE_COMPOSITING
34 static gboolean composite(gpointer data);
36 static struct ObCompositor obcomp;
39 time_fix(struct timeval *tv)
41 while (tv->tv_usec >= 1000000) {
42 tv->tv_usec -= 1000000;
45 while (tv->tv_usec < 0) {
46 tv->tv_usec += 1000000;
51 static gboolean composite_need_redraw(void)
56 static void get_best_fbcon(GLXFBConfig *in, int count, int depth, GLXFBConfig *out)
60 int i, value, has_alpha;
62 for (i = 0; i < count; i++) {
64 vi = glXGetVisualFromFBConfig(obt_display, in[i]);
76 obcomp.GetFBConfigAttrib(obt_display, in[i], GLX_BIND_TO_TEXTURE_RGBA_EXT, &value);
79 obcomp.GetFBConfigAttrib(obt_display, in[i], GLX_BIND_TO_TEXTURE_RGB_EXT, &value);
81 if (!value) // neither bind to texture? no dice
89 void composite_startup(gboolean reconfig)
91 /* This function will try enable composite if config_comp is TRUE. At the
92 end of this process, config_comp will be set to TRUE only if composite
93 is enabled, and FALSE otherwise. */
94 #ifdef USE_COMPOSITING
102 const char *glstring;
109 if (reconfig) return;
110 if (!config_comp) return;
114 root = RootWindow(obt_display, ob_screen);
116 astr = g_strdup_printf("_NET_WM_CM_S%d", ob_screen);
117 cm_atom = XInternAtom(obt_display, astr, 0);
120 cm_owner = XGetSelectionOwner(obt_display, cm_atom);
121 if (cm_owner != None) {
122 g_message("Failed to enable composite. There is already a compositor running.");
126 timestamp = event_time();
127 XSetSelectionOwner(obt_display, cm_atom, screen_support_win, timestamp);
129 if (XGetSelectionOwner(obt_display, cm_atom) != screen_support_win) {
130 g_message("Failed to enable composite. Could not acquire the composite manager selection on screen %d", ob_screen);
134 if (!obt_display_extension_composite) {
135 g_message("Failed to enable composite. The XComposite extension is missing.");
139 if (!obt_display_extension_damage) {
140 g_message("Failed to enable composite. The XDamage extension is missing.");
144 if (!obt_display_extension_fixes) {
145 g_message("Failed to enable composite. The XFixes extension is missing.");
149 glstring = glXQueryExtensionsString(obt_display, ob_screen);
150 if (!strstr(glstring, "GLX_EXT_texture_from_pixmap")) {
151 g_message("Failed to enable composite. GLX_EXT_texture_from_pixmap is not present.");
155 obcomp.CreatePixmap = (CreatePixmapT)glXGetProcAddress("glXCreatePixmap");
156 if (!obcomp.CreatePixmap) {
157 g_message("Failed to enable composite. glXCreatePixmap unavailable.");
161 obcomp.BindTexImage = (BindTexImageT)glXGetProcAddress("glXBindTexImageEXT");
162 if (!obcomp.BindTexImage) {
163 g_message("Failed to enable composite. glXBindTexImage unavailable.");
167 obcomp.ReleaseTexImage = (ReleaseTexImageT)glXGetProcAddress("glXReleaseTexImageEXT");
168 if (!obcomp.ReleaseTexImage) {
169 g_message("Failed to enable composite. glXReleaseTexImage unavailable.");
173 obcomp.GetFBConfigs = (GetFBConfigsT)glXGetProcAddress("glXGetFBConfigs");
174 if (!obcomp.GetFBConfigs) {
175 g_message("Failed to enable composite. glXGetFBConfigs unavailable.");
179 obcomp.GetFBConfigAttrib = (GetFBConfigAttribT)glXGetProcAddress("glXGetFBConfigAttrib");
180 if (!obcomp.GetFBConfigAttrib) {
181 g_message("Failed to enable composite. glXGetFBConfigAttrib unavailable.");
185 obcomp.overlay = XCompositeGetOverlayWindow(obt_display, root);
186 //now you've done it. better release this if we fail later!
187 //or move this get to the end?
189 xr = XFixesCreateRegion(obt_display, NULL, 0);
190 XFixesSetWindowShapeRegion(obt_display, obcomp.overlay, ShapeBounding, 0, 0, 0);
191 XFixesSetWindowShapeRegion(obt_display, obcomp.overlay, ShapeInput, 0, 0, xr);
192 XFixesDestroyRegion(obt_display, xr);
194 if (!XGetWindowAttributes(obt_display, root, &xa)) {
195 g_message("Failed to enable composite. XGetWindowAttributes failed.");
199 tmp.visualid = XVisualIDFromVisual(xa.visual);
200 vi = XGetVisualInfo(obt_display, VisualIDMask, &tmp, &count);
203 g_message("Failed to enable composite. Couldn't get visual info.");
208 glXGetConfig(obt_display, vi, GLX_USE_GL, &val);
210 g_message("Failed to enable composite. Visual is not GL capable");
214 glXGetConfig(obt_display, vi, GLX_DOUBLEBUFFER, &val);
216 g_message("Failed to enable composite. Visual is not double buffered");
220 obcomp.ctx = glXCreateContext(obt_display, vi, NULL, True);
223 fbcs = obcomp.GetFBConfigs(obt_display, ob_screen, &count);
226 g_message("Failed to enable composite. No valid FBConfigs.");
230 memset(&obcomp.PixmapConfig, 0, sizeof(obcomp.PixmapConfig));
232 for (i = 0; i < MAX_DEPTH + 1; i++) {
233 get_best_fbcon(fbcs, count, i, &obcomp.PixmapConfig[i]);
239 printf("Best visual for 24bpp was 0x%x\n", obcomp.PixmapConfig[24]);
240 printf("Best visual for 32bpp was 0x%x\n", obcomp.PixmapConfig[32]);
242 g_idle_add(composite, NULL);
244 glXMakeCurrent(obt_display, obcomp.overlay, obcomp.ctx);
246 obcomp.screendims = screen_physical_area_all_monitors();
247 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
248 glXSwapBuffers(obt_display, obcomp.overlay);
249 glMatrixMode(GL_PROJECTION);
252 glOrtho(obcomp.screendims->x,
253 obcomp.screendims->x + obcomp.screendims->width,
254 obcomp.screendims->y + obcomp.screendims->height,
255 obcomp.screendims->y,
257 glMatrixMode(GL_MODELVIEW);
259 glDisable(GL_DEPTH_TEST);
260 glEnable(GL_TEXTURE_2D);
262 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
266 void composite_shutdown(gboolean reconfig)
268 #ifdef USE_COMPOSITING
269 if (reconfig) return;
273 static gboolean composite(gpointer data)
275 #ifdef USE_COMPOSITING
277 GLX_TEXTURE_FORMAT_EXT,
281 struct timeval start, end, dif;
287 // if (!obcomp.need_redraw)
289 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
291 // for (it = stacking_list; it; it = g_list_next(it)) {
292 for (it = g_list_last(stacking_list); it; it = g_list_previous(it)) {
294 if (win->type != OB_WINDOW_CLASS_CLIENT)
297 client = WINDOW_AS_CLIENT(win);
298 if (client->desktop != screen_desktop)
301 if (win->depth == 32)
302 attribs[1] = GLX_TEXTURE_FORMAT_RGBA_EXT;
304 attribs[1] = GLX_TEXTURE_FORMAT_RGB_EXT;
306 if (win->gpixmap == None)
307 win->gpixmap = obcomp.CreatePixmap(obt_display, obcomp.PixmapConfig[win->depth], win->pixmap, attribs);
309 glBindTexture(GL_TEXTURE_2D, win->texture);
310 gettimeofday(&start, NULL);
311 obcomp.BindTexImage(obt_display, win->gpixmap, GLX_FRONT_LEFT_EXT, NULL);
312 gettimeofday(&end, NULL);
313 dif.tv_sec = end.tv_sec - start.tv_sec;
314 dif.tv_usec = end.tv_usec - start.tv_usec;
316 //printf("took %f ms\n", dif.tv_sec * 1000.0 + dif.tv_usec / 1000.0);
317 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
318 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
319 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
320 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
321 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
325 glVertex3f(client->frame->area.x, client->frame->area.y, 0.0);
327 glVertex3f(client->frame->area.x, client->frame->area.y + client->frame->area.height, 0.0);
329 glVertex3f(client->frame->area.x + client->frame->area.width, client->frame->area.y + client->frame->area.height, 0.0);
331 glVertex3f(client->frame->area.x + client->frame->area.width, client->frame->area.y, 0.0);
334 glXSwapBuffers(obt_display, obcomp.overlay);
336 obcomp.need_redraw = 0;