summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Grenville <pyxlcy@gmail.com>2013-03-01 12:41:16 +0800
committerRichard Grenville <pyxlcy@gmail.com>2013-03-01 12:41:16 +0800
commit71fdda46e615df29ac1b2c8d3d1984a7be3b44fd (patch)
treefe7ce77c65bc09925a39b393078fa922baa0c5d5
parentd1fb8649a4e5d2ec165bd4226d53703043678eb2 (diff)
downloadtdebase-71fdda46.tar.gz
tdebase-71fdda46.zip
Bug fix #91: Using pkg-config to find drm.h & OpenGL changes
- #91: Use pkg-config to find drm.h to avoid issues on FreeBSD. Thanks to hun7err for pointing out and providing patch. - #89: Add default shadow exclusion rule for notify-osd. Thanks to DanielRS. - Check for abundant positional arguments. - Use paint target window (root window / overlay window) instead of ps->reg_win to create GLXContext. (May have negative effects on OpenGL VSync.) Add new OpenGL helpers functions, to prepare for the new OpenGL backend. - Dump more info of a PropertyNotify with DEBUG_EVENTS.
-rw-r--r--common.h18
-rw-r--r--compton.c236
-rw-r--r--compton.h76
3 files changed, 234 insertions, 96 deletions
diff --git a/common.h b/common.h
index 995553bae..0d4f5a541 100644
--- a/common.h
+++ b/common.h
@@ -258,6 +258,14 @@ typedef int (*f_GetVideoSync) (unsigned *);
typedef Bool (*f_GetSyncValuesOML) (Display* dpy, GLXDrawable drawable, int64_t* ust, int64_t* msc, int64_t* sbc);
typedef Bool (*f_WaitForMscOML) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t* ust, int64_t* msc, int64_t* sbc);
+
+typedef void (*f_BindTexImageEXT) (Display *display, GLXDrawable drawable, int buffer, const int *attrib_list);
+typedef void (*f_ReleaseTexImageEXT) (Display *display, GLXDrawable drawable, int buffer);
+
+struct glx_fbconfig {
+ GLXFBConfig cfg;
+ bool y_inverted;
+};
#endif
typedef struct {
@@ -536,7 +544,7 @@ typedef struct {
#endif
#ifdef CONFIG_VSYNC_OPENGL
- // === OpenGL VSync related ===
+ // === OpenGL related ===
/// GLX context.
GLXContext glx_context;
/// Pointer to glXGetVideoSyncSGI function.
@@ -547,6 +555,14 @@ typedef struct {
f_GetSyncValuesOML glXGetSyncValuesOML;
/// Pointer to glXWaitForMscOML function.
f_WaitForMscOML glXWaitForMscOML;
+ /// Pointer to glXBindTexImageEXT function.
+ f_BindTexImageEXT glXBindTexImageEXT;
+ /// Pointer to glXReleaseTexImageEXT function.
+ f_ReleaseTexImageEXT glXReleaseTexImageEXT;
+ /// FBConfig for RGB GLX pixmap.
+ struct glx_fbconfig *glx_fbconfig_rgb;
+ /// FBConfig for RGBA GLX pixmap.
+ struct glx_fbconfig *glx_fbconfig_rgba;
#endif
// === X extension related ===
diff --git a/compton.c b/compton.c
index 12dc72ff3..edd387823 100644
--- a/compton.c
+++ b/compton.c
@@ -3542,6 +3542,16 @@ update_ewmh_active_win(session_t *ps) {
inline static void
ev_property_notify(session_t *ps, XPropertyEvent *ev) {
+#ifdef DEBUG_EVENTS
+ {
+ // Print out changed atom
+ char *name = XGetAtomName(ps->dpy, ev->atom);
+ printf_dbg(" { atom = %s }\n", name);
+ if (name)
+ XFree(name);
+ }
+#endif
+
if (ps->root == ev->window) {
if (ps->o.track_focus && ps->o.use_ewmh_active_win
&& ps->atom_ewmh_active_win == ev->atom) {
@@ -3992,40 +4002,11 @@ usage(void) {
* Register a window as symbol, and initialize GLX context if wanted.
*/
static bool
-register_cm(session_t *ps, bool glx) {
+register_cm(session_t *ps) {
assert(!ps->reg_win);
- XVisualInfo *pvi = NULL;
-
-#ifdef CONFIG_VSYNC_OPENGL
- // Create a window with the wanted GLX visual
- if (glx) {
- // Get visual for the window
- int attribs[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, None };
- pvi = glXChooseVisual(ps->dpy, ps->scr, attribs);
-
- if (!pvi) {
- printf_errf("(): Failed to choose GLX visual.");
- return false;
- }
-
- // Create the window
- XSetWindowAttributes swa = {
- .colormap = XCreateColormap(ps->dpy, ps->root, pvi->visual, AllocNone),
- .border_pixel = 0,
- };
-
- pvi->screen = ps->scr;
- ps->reg_win = XCreateWindow(ps->dpy, ps->root, 0, 0, 1, 1, 0, pvi->depth,
- InputOutput, pvi->visual, CWBorderPixel | CWColormap, &swa);
- }
- // Otherwise, create a simple window
- else
-#endif
- {
- ps->reg_win = XCreateSimpleWindow(ps->dpy, ps->root, 0, 0, 1, 1, 0,
+ ps->reg_win = XCreateSimpleWindow(ps->dpy, ps->root, 0, 0, 1, 1, 0,
None, None);
- }
if (!ps->reg_win) {
printf_errf("(): Failed to create window.");
@@ -4036,26 +4017,6 @@ register_cm(session_t *ps, bool glx) {
if (ps->redirected)
XCompositeUnredirectWindow(ps->dpy, ps->reg_win, CompositeRedirectManual);
-#ifdef CONFIG_VSYNC_OPENGL
- if (glx) {
- // Get GLX context
- ps->glx_context = glXCreateContext(ps->dpy, pvi, None, GL_TRUE);
- if (!ps->glx_context) {
- printf_errf("(): Failed to get GLX context.");
- return false;
- }
-
- // Attach GLX context
- if (!glXMakeCurrent(ps->dpy, ps->reg_win, ps->glx_context)) {
- printf_errf("(): Failed to attach GLX context.");
- return false;
- }
- }
-#endif
-
- if (pvi)
- XFree(pvi);
-
Xutf8SetWMProperties(ps->dpy, ps->reg_win, "xcompmgr", "xcompmgr",
NULL, 0, NULL, NULL, NULL);
@@ -4478,6 +4439,10 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
usage();
}
+ // Check for abundant positional arguments
+ if (optind < argc)
+ printf_errfq(1, "(): compton doesn't accept positional arguments.");
+
return;
}
@@ -4893,6 +4858,155 @@ swopti_handle_timeout(session_t *ps, struct timeval *ptv) {
}
}
+#ifdef CONFIG_VSYNC_OPENGL
+/**
+ * Get a GLX FBConfig.
+ */
+static inline bool
+opengl_update_fbconfig(session_t *ps, bool alpha, struct glx_fbconfig **ppcfg) {
+ const int FBCONFIG_ATTRS[] = {
+ (alpha ? GLX_BIND_TO_TEXTURE_RGBA_EXT: GLX_BIND_TO_TEXTURE_RGB_EXT), True,
+ GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
+ GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
+ GLX_DOUBLEBUFFER, True,
+ GLX_Y_INVERTED_EXT, GLX_DONT_CARE,
+ None
+ };
+
+ if (*ppcfg) {
+ free(*ppcfg);
+ *ppcfg = NULL;
+ }
+
+ int count = 0;
+ GLXFBConfig *cfgs = glXChooseFBConfig(ps->dpy, ps->scr, FBCONFIG_ATTRS, &count);
+ if (!count || !cfgs) {
+ if (cfgs)
+ XFree(cfgs);
+ return false;
+ };
+
+ *ppcfg = malloc(sizeof(struct glx_fbconfig));
+ (*ppcfg)->cfg = cfgs[0];
+
+ {
+ int inverted = 0;
+ glXGetFBConfigAttrib(ps->dpy, (*ppcfg)->cfg, GLX_Y_INVERTED_EXT, &inverted);
+ (*ppcfg)->y_inverted = inverted;
+ }
+
+ XFree(cfgs);
+
+ return true;
+}
+
+/**
+ * Initialize OpenGL.
+ */
+static bool
+opengl_init(session_t *ps, bool need_render) {
+ // Check for GLX extension
+ if (!ps->glx_exists) {
+ if (glXQueryExtension(ps->dpy, &ps->glx_event, &ps->glx_error))
+ ps->glx_exists = true;
+ else {
+ printf_errf("(): No GLX extension.");
+ goto opengl_init_err;
+ }
+ }
+
+ // Ensure GLX_EXT_texture_from_pixmap exists
+ if (need_render && !opengl_hasext(ps, "GLX_EXT_texture_from_pixmap")) {
+ goto opengl_init_err;
+ }
+
+ {
+ // Get XVisualInfo
+ XVisualInfo *pvis = NULL;
+ {
+ XVisualInfo vreq = { .visualid = XVisualIDFromVisual(ps->vis) };
+ int nitems = 0;
+ pvis = XGetVisualInfo(ps->dpy, VisualIDMask, &vreq, &nitems);
+ }
+
+ if (!pvis) {
+ printf_errf("(): Failed to acquire XVisualInfo for current visual.");
+ goto opengl_init_err;
+ }
+
+ // Ensure the visual is double-buffered
+ if (need_render) {
+ int value = 0;
+ glXGetConfig(ps->dpy, pvis, GLX_DOUBLEBUFFER, &value);
+ if (!value) {
+ XFree(pvis);
+ printf_errf("(): Default GLX visual is not double-buffered.");
+ goto opengl_init_err;
+ }
+ }
+
+ // Get GLX context
+ ps->glx_context = glXCreateContext(ps->dpy, pvis, None, GL_TRUE);
+ XFree(pvis);
+ }
+
+ if (!ps->glx_context) {
+ printf_errf("(): Failed to get GLX context.");
+ goto opengl_init_err;
+ }
+
+ // Attach GLX context
+ if (!glXMakeCurrent(ps->dpy, get_tgt_window(ps), ps->glx_context)) {
+ printf_errf("(): Failed to attach GLX context.");
+ goto opengl_init_err;
+ }
+
+ // Acquire function addresses
+ if (need_render) {
+ ps->glXBindTexImageEXT = (f_BindTexImageEXT)
+ glXGetProcAddress((const GLubyte *) "glXBindTexImageEXT");
+ ps->glXReleaseTexImageEXT = (f_ReleaseTexImageEXT)
+ glXGetProcAddress((const GLubyte *) "glXReleaseTexImageEXT");
+ if (!ps->glXBindTexImageEXT || !ps->glXReleaseTexImageEXT) {
+ printf_errf("(): Failed to acquire glXBindTexImageEXT() / glXReleaseTexImageEXT().");
+ goto opengl_init_err;
+ }
+ }
+
+ // Acquire FBConfigs
+ if (need_render
+ && (!(ps->glx_fbconfig_rgb || opengl_update_fbconfig(ps, false, &ps->glx_fbconfig_rgb))
+ || !(ps->glx_fbconfig_rgba || opengl_update_fbconfig(ps, true, &ps->glx_fbconfig_rgba)))) {
+ printf_errf("(): Failed to acquire GLX fbconfig.");
+ goto opengl_init_err;
+ }
+
+ if (need_render) {
+ glViewport(0, 0, ps->root_width, ps->root_height);
+ }
+
+ return true;
+
+opengl_init_err:
+ opengl_destroy(ps);
+
+ return false;
+}
+
+static void
+opengl_destroy(session_t *ps) {
+ if (ps->glx_context) {
+ glXDestroyContext(ps->dpy, ps->glx_context);
+ ps->glx_context = None;
+ }
+
+ free(ps->glx_fbconfig_rgb);
+ ps->glx_fbconfig_rgb = NULL;
+ free(ps->glx_fbconfig_rgba);
+ ps->glx_fbconfig_rgba = NULL;
+}
+#endif
+
/**
* Initialize DRM VSync.
*
@@ -4962,10 +5076,10 @@ vsync_opengl_init(session_t *ps) {
// Get video sync functions
if (!ps->glXWaitVideoSyncSGI)
ps->glXGetVideoSyncSGI = (f_GetVideoSync)
- glXGetProcAddress ((const GLubyte *) "glXGetVideoSyncSGI");
+ glXGetProcAddress((const GLubyte *) "glXGetVideoSyncSGI");
if (!ps->glXWaitVideoSyncSGI)
ps->glXWaitVideoSyncSGI = (f_WaitVideoSync)
- glXGetProcAddress ((const GLubyte *) "glXWaitVideoSyncSGI");
+ glXGetProcAddress((const GLubyte *) "glXWaitVideoSyncSGI");
if (!ps->glXWaitVideoSyncSGI || !ps->glXGetVideoSyncSGI) {
printf_errf("(): Failed to get glXWait/GetVideoSyncSGI function.");
return false;
@@ -5168,9 +5282,14 @@ redir_start(session_t *ps) {
XCompositeRedirectSubwindows(ps->dpy, ps->root, CompositeRedirectManual);
- // Unredirect reg_win as this may have an effect on VSync:
+ /*
+ // Unredirect GL context window as this may have an effect on VSync:
// < http://dri.freedesktop.org/wiki/CompositeSwap >
XCompositeUnredirectWindow(ps->dpy, ps->reg_win, CompositeRedirectManual);
+ if (ps->o.paint_on_overlay && ps->overlay) {
+ XCompositeUnredirectWindow(ps->dpy, ps->overlay,
+ CompositeRedirectManual);
+ } */
// Must call XSync() here
XSync(ps->dpy, False);
@@ -5729,8 +5848,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
exit(1);
// Create registration window
- // Must not precede VSync init functions because they may create the window
- if (!ps->reg_win && !register_cm(ps, false))
+ if (!ps->reg_win && !register_cm(ps))
exit(1);
init_atoms(ps);
@@ -5961,11 +6079,9 @@ session_destroy(session_t *ps) {
XDestroyWindow(ps->dpy, ps->reg_win);
ps->reg_win = None;
}
+
#ifdef CONFIG_VSYNC_OPENGL
- if (ps->glx_context) {
- glXDestroyContext(ps->dpy, ps->glx_context);
- ps->glx_context = None;
- }
+ opengl_destroy(ps);
#endif
// Free double buffer
diff --git a/compton.h b/compton.h
index b4f5bfd44..f0af56482 100644
--- a/compton.h
+++ b/compton.h
@@ -9,6 +9,7 @@
#include "common.h"
+#include <ctype.h>
#include <math.h>
#include <sys/select.h>
#include <limits.h>
@@ -22,7 +23,7 @@
// We references some definitions in drm.h, which could also be found in
// /usr/src/linux/include/drm/drm.h, but that path is probably even less
// reliable than libdrm
-#include <libdrm/drm.h>
+#include <drm.h>
#include <sys/ioctl.h>
#include <errno.h>
#endif
@@ -705,40 +706,7 @@ static void __attribute__ ((noreturn))
usage(void);
static bool
-register_cm(session_t *ps, bool glx);
-
-#ifdef CONFIG_VSYNC_OPENGL
-/**
- * Ensure we have a GLX context.
- */
-static inline bool
-ensure_glx_context(session_t *ps) {
- if (ps->glx_context)
- return true;
-
- // Check for GLX extension
- if (!ps->glx_exists) {
- if (glXQueryExtension(ps->dpy, &ps->glx_event, &ps->glx_error))
- ps->glx_exists = true;
- else {
- printf_errf("(): No GLX extension.");
- return false;
- }
- }
-
- // Create GLX context
- if (ps->reg_win) {
- XDestroyWindow(ps->dpy, ps->reg_win);
- ps->reg_win = None;
- }
- if (!register_cm(ps, true) || !ps->glx_context) {
- printf_errf("(): Failed to acquire GLX context.");
- return false;
- }
-
- return true;
-}
-#endif
+register_cm(session_t *ps);
inline static void
ev_focus_in(session_t *ps, XFocusChangeEvent *ev);
@@ -920,6 +888,44 @@ static void
swopti_handle_timeout(session_t *ps, struct timeval *ptv);
static bool
+opengl_init(session_t *ps, bool need_render);
+
+static void
+opengl_destroy(session_t *ps);
+
+#ifdef CONFIG_VSYNC_OPENGL
+/**
+ * Check if a GLX extension exists.
+ */
+static inline bool
+opengl_hasext(session_t *ps, const char *ext) {
+ const char *glx_exts = glXQueryExtensionsString(ps->dpy, ps->scr);
+ const char *pos = strstr(glx_exts, ext);
+ // Make sure the extension string is matched as a whole word
+ if (!pos
+ || ((pos - glx_exts) && !isspace(*(pos - 1)))
+ || (strlen(pos) > strlen(ext) && !isspace(pos[strlen(ext)]))) {
+ printf_errf("(): Missing OpenGL extension %s.", ext);
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Ensure we have a GLX context.
+ */
+static inline bool
+ensure_glx_context(session_t *ps) {
+ // Create GLX context
+ if (!ps->glx_context)
+ opengl_init(ps, false);
+
+ return ps->glx_context;
+}
+#endif
+
+static bool
vsync_drm_init(session_t *ps);
#ifdef CONFIG_VSYNC_DRM