Created
March 16, 2014 23:29
-
-
Save richardgv/9591390 to your computer and use it in GitHub Desktop.
chjj/compton #181: Add X Sync fence support, second revision
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/Makefile b/Makefile | |
index 701308b..9eb5b7e 100644 | |
--- a/Makefile | |
+++ b/Makefile | |
@@ -73,6 +73,11 @@ ifeq "$(NO_DBUS)" "" | |
OBJS += dbus.o | |
endif | |
+# ==== D-Bus ==== | |
+ifeq "$(NO_XSYNC)" "" | |
+ CFG += -DCONFIG_XSYNC | |
+endif | |
+ | |
# ==== C2 ==== | |
ifeq "$(NO_C2)" "" | |
CFG += -DCONFIG_C2 | |
diff --git a/src/common.h b/src/common.h | |
index e87651c..5e87b82 100644 | |
--- a/src/common.h | |
+++ b/src/common.h | |
@@ -55,11 +55,19 @@ | |
// #define CONFIG_DBUS 1 | |
// Whether to enable condition support. | |
// #define CONFIG_C2 1 | |
+// Whether to enable X Sync support. | |
+// #define CONFIG_XSYNC 1 | |
+// Whether to enable GLX Sync support. | |
+// #define CONFIG_GLX_XSYNC 1 | |
#if !defined(CONFIG_C2) && defined(DEBUG_C2) | |
#error Cannot enable c2 debugging without c2 support. | |
#endif | |
+#if (!defined(CONFIG_XSYNC) || !defined(CONFIG_VSYNC_OPENGL)) && defined(CONFIG_GLX_SYNC) | |
+#error Cannot enable GL sync without X Sync / OpenGL support. | |
+#endif | |
+ | |
#ifndef COMPTON_VERSION | |
#define COMPTON_VERSION "unknown" | |
#endif | |
@@ -89,6 +97,9 @@ | |
#include <X11/extensions/shape.h> | |
#include <X11/extensions/Xrandr.h> | |
#include <X11/extensions/Xdbe.h> | |
+#ifdef CONFIG_XSYNC | |
+#include <X11/extensions/sync.h> | |
+#endif | |
#ifdef CONFIG_XINERAMA | |
#include <X11/extensions/Xinerama.h> | |
@@ -338,6 +349,16 @@ enum { | |
typedef struct _glx_texture glx_texture_t; | |
#ifdef CONFIG_VSYNC_OPENGL | |
+#ifdef DEBUG_GLX_DEBUG_CONTEXT | |
+typedef GLXContext (*f_glXCreateContextAttribsARB) (Display *dpy, | |
+ GLXFBConfig config, GLXContext share_context, Bool direct, | |
+ const int *attrib_list); | |
+typedef void (*GLDEBUGPROC) (GLenum source, GLenum type, | |
+ GLuint id, GLenum severity, GLsizei length, const GLchar* message, | |
+ GLvoid* userParam); | |
+typedef void (*f_DebugMessageCallback) (GLDEBUGPROC, void *userParam); | |
+#endif | |
+ | |
typedef int (*f_WaitVideoSync) (int, int, unsigned *); | |
typedef int (*f_GetVideoSync) (unsigned *); | |
@@ -352,6 +373,47 @@ typedef void (*f_ReleaseTexImageEXT) (Display *display, GLXDrawable drawable, in | |
typedef void (*f_CopySubBuffer) (Display *dpy, GLXDrawable drawable, int x, int y, int width, int height); | |
+#ifdef CONFIG_GLX_SYNC | |
+// Looks like duplicate typedef of the same type is safe? | |
+typedef int64_t GLint64; | |
+typedef uint64_t GLuint64; | |
+typedef struct __GLsync *GLsync; | |
+ | |
+#ifndef GL_SYNC_FLUSH_COMMANDS_BIT | |
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 | |
+#endif | |
+ | |
+#ifndef GL_TIMEOUT_IGNORED | |
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull | |
+#endif | |
+ | |
+#ifndef GL_ALREADY_SIGNALED | |
+#define GL_ALREADY_SIGNALED 0x911A | |
+#endif | |
+ | |
+#ifndef GL_TIMEOUT_EXPIRED | |
+#define GL_TIMEOUT_EXPIRED 0x911B | |
+#endif | |
+ | |
+#ifndef GL_CONDITION_SATISFIED | |
+#define GL_CONDITION_SATISFIED 0x911C | |
+#endif | |
+ | |
+#ifndef GL_WAIT_FAILED | |
+#define GL_WAIT_FAILED 0x911D | |
+#endif | |
+ | |
+typedef GLsync (*f_FenceSync) (GLenum condition, GLbitfield flags); | |
+typedef GLboolean (*f_IsSync) (GLsync sync); | |
+typedef void (*f_DeleteSync) (GLsync sync); | |
+typedef GLenum (*f_ClientWaitSync) (GLsync sync, GLbitfield flags, | |
+ GLuint64 timeout); | |
+typedef void (*f_WaitSync) (GLsync sync, GLbitfield flags, | |
+ GLuint64 timeout); | |
+typedef GLsync (*f_ImportSyncEXT) (GLenum external_sync_type, | |
+ GLintptr external_sync, GLbitfield flags); | |
+#endif | |
+ | |
#ifdef DEBUG_GLX_MARK | |
typedef void (*f_StringMarkerGREMEDY) (GLsizei len, const void *string); | |
typedef void (*f_FrameTerminatorGREMEDY) (void); | |
@@ -617,7 +679,7 @@ typedef struct { | |
} options_t; | |
/// Structure containing all necessary data for a compton session. | |
-typedef struct { | |
+typedef struct _session_t { | |
// === Display related === | |
/// Display in use. | |
Display *dpy; | |
@@ -650,6 +712,9 @@ typedef struct { | |
Picture tgt_picture; | |
/// Temporary buffer to paint to before sending to display. | |
paint_t tgt_buffer; | |
+#ifdef CONFIG_XSYNC | |
+ XSyncFence tgt_buffer_fence; | |
+#endif | |
/// DBE back buffer for root window. Used in DBE painting mode. | |
XdbeBackBuffer root_dbe; | |
/// Window ID of the window we register as a symbol. | |
@@ -783,6 +848,20 @@ typedef struct { | |
f_ReleaseTexImageEXT glXReleaseTexImageProc; | |
/// Pointer to glXCopySubBufferMESA function. | |
f_CopySubBuffer glXCopySubBufferProc; | |
+#ifdef CONFIG_GLX_SYNC | |
+ /// Pointer to the glFenceSync() function. | |
+ f_FenceSync glFenceSyncProc; | |
+ /// Pointer to the glIsSync() function. | |
+ f_IsSync glIsSyncProc; | |
+ /// Pointer to the glDeleteSync() function. | |
+ f_DeleteSync glDeleteSyncProc; | |
+ /// Pointer to the glClientWaitSync() function. | |
+ f_ClientWaitSync glClientWaitSyncProc; | |
+ /// Pointer to the glWaitSync() function. | |
+ f_WaitSync glWaitSyncProc; | |
+ /// Pointer to the glImportSyncEXT() function. | |
+ f_ImportSyncEXT glImportSyncEXT; | |
+#endif | |
#ifdef DEBUG_GLX_MARK | |
/// Pointer to StringMarkerGREMEDY function. | |
f_StringMarkerGREMEDY glStringMarkerGREMEDY; | |
@@ -850,6 +929,14 @@ typedef struct { | |
/// Number of Xinerama screens. | |
int xinerama_nscrs; | |
#endif | |
+#ifdef CONFIG_XSYNC | |
+ /// Whether X Sync extension exists. | |
+ bool xsync_exists; | |
+ /// Event base number for X Sync extension. | |
+ int xsync_event; | |
+ /// Error base number for X Sync extension. | |
+ int xsync_error; | |
+#endif | |
/// Whether X Render convolution filter exists. | |
bool xrfilter_convolution_exists; | |
@@ -915,6 +1002,10 @@ typedef struct _win { | |
winmode_t mode; | |
/// Whether the window has been damaged at least once. | |
bool damaged; | |
+#ifdef CONFIG_XSYNC | |
+ /// X Sync fence of drawable. | |
+ XSyncFence fence; | |
+#endif | |
/// Whether the window was damaged after last paint. | |
bool pixmap_damaged; | |
/// Damage of the window. | |
@@ -1802,6 +1893,20 @@ free_all_damage_last(session_t *ps) { | |
free_region(ps, &ps->all_damage_last[i]); | |
} | |
+#ifdef CONFIG_XSYNC | |
+/** | |
+ * Free a XSync fence. | |
+ */ | |
+static inline void | |
+free_fence(session_t *ps, XSyncFence *pfence) { | |
+ if (*pfence) | |
+ XSyncDestroyFence(ps->dpy, *pfence); | |
+ *pfence = None; | |
+} | |
+#else | |
+#define free_fence(ps, pfence) ((void) 0) | |
+#endif | |
+ | |
/** | |
* Crop a rectangle by another rectangle. | |
* | |
@@ -1927,6 +2032,11 @@ vsync_deinit(session_t *ps); | |
*/ | |
///@{ | |
+#ifdef CONFIG_GLX_SYNC | |
+void | |
+xr_glx_sync(session_t *ps, Drawable d, XSyncFence *pfence); | |
+#endif | |
+ | |
bool | |
glx_init(session_t *ps, bool need_render); | |
@@ -2096,6 +2206,55 @@ glx_mark_frame(session_t *ps) { | |
///@} | |
+#ifdef CONFIG_XSYNC | |
+#define xr_sync(ps, d, pfence) xr_sync_(ps, d, pfence) | |
+#else | |
+#define xr_sync(ps, d, pfence) xr_sync_(ps, d) | |
+#endif | |
+ | |
+/** | |
+ * Synchronizes a X Render drawable to ensure all pending painting requests | |
+ * are completed. | |
+ */ | |
+static inline void | |
+xr_sync_(session_t *ps, Drawable d | |
+#ifdef CONFIG_XSYNC | |
+ , XSyncFence *pfence | |
+#endif | |
+ ) { | |
+#ifdef CONFIG_XSYNC | |
+ if (ps->xsync_exists) { | |
+ // TODO: If everybody just follows the rules stated in X Sync prototype, | |
+ // we need only one fence per screen, but let's stay a bit cautious right | |
+ // now | |
+ XSyncFence tmp_fence = None; | |
+ if (!pfence) | |
+ pfence = &tmp_fence; | |
+ assert(pfence); | |
+ if (!*pfence) | |
+ *pfence = XSyncCreateFence(ps->dpy, d, False); | |
+ if (*pfence) { | |
+ Bool triggered = False; | |
+ // The fence may fail to be created (e.g. because of died drawable) | |
+ assert(!XSyncQueryFence(ps->dpy, *pfence, &triggered) || !triggered); | |
+ XSyncTriggerFence(ps->dpy, *pfence); | |
+ XSyncAwaitFence(ps->dpy, pfence, 1); | |
+ assert(!XSyncQueryFence(ps->dpy, *pfence, &triggered) || triggered); | |
+ } | |
+ else { | |
+ printf_errf("(%#010lx): Failed to create X Sync fence.", d); | |
+ } | |
+ free_fence(ps, &tmp_fence); | |
+ if (*pfence) | |
+ XSyncResetFence(ps->dpy, *pfence); | |
+ } | |
+#endif | |
+ XSync(ps->dpy, False); | |
+#ifdef CONFIG_GLX_SYNC | |
+ xr_glx_sync(ps, d, pfence); | |
+#endif | |
+} | |
+ | |
/** @name DBus handling | |
*/ | |
///@{ | |
diff --git a/src/compton.c b/src/compton.c | |
index 645aa5c..eb12c2c 100644 | |
--- a/src/compton.c | |
+++ b/src/compton.c | |
@@ -489,6 +489,8 @@ win_build_shadow(session_t *ps, win *w, double opacity) { | |
w->shadow_paint.pixmap = shadow_pixmap_argb; | |
w->shadow_paint.pict = shadow_picture_argb; | |
+ xr_sync(ps, w->shadow_paint.pixmap, NULL); | |
+ | |
bool success = paint_bind_tex(ps, &w->shadow_paint, shadow_image->width, shadow_image->height, 32, true); | |
XFreeGC(ps->dpy, gc); | |
@@ -1513,12 +1515,16 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint, | |
if (!w->paint.pixmap && ps->has_name_pixmap) { | |
set_ignore_next(ps); | |
w->paint.pixmap = XCompositeNameWindowPixmap(ps->dpy, w->id); | |
+ if (w->paint.pixmap) | |
+ free_fence(ps, &w->fence); | |
} | |
+ | |
+ Drawable draw = w->paint.pixmap; | |
+ if (!draw) | |
+ draw = w->id; | |
+ | |
// XRender: Build picture | |
if (bkend_use_xrender(ps) && !w->paint.pict) { | |
- Drawable draw = w->paint.pixmap; | |
- if (!draw) | |
- draw = w->id; | |
{ | |
XRenderPictureAttributes pa = { | |
.subwindow_mode = IncludeInferiors, | |
@@ -1528,6 +1534,9 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint, | |
CPSubwindowMode, &pa); | |
} | |
} | |
+ | |
+ xr_sync(ps, draw, &w->fence); | |
+ | |
// GLX: Build texture | |
// Let glx_bind_pixmap() determine pixmap size, because if the user | |
// is resizing windows, the width and height we get may not be up-to-date, | |
@@ -1948,10 +1957,13 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t | |
else | |
glFlush(); | |
glXWaitX(); | |
+ assert(ps->tgt_buffer.pixmap); | |
+ xr_sync(ps, ps->tgt_buffer.pixmap, &ps->tgt_buffer_fence); | |
paint_bind_tex_real(ps, &ps->tgt_buffer, | |
ps->root_width, ps->root_height, ps->depth, | |
!ps->o.glx_no_rebind_pixmap); | |
// See #163 | |
+ xr_sync(ps, ps->tgt_buffer.pixmap, &ps->tgt_buffer_fence); | |
XSync(ps->dpy, False); | |
if (ps->o.vsync_use_glfinish) | |
glFinish(); | |
@@ -2205,7 +2217,7 @@ finish_unmap_win(session_t *ps, win *w) { | |
w->extents = None; | |
} | |
- free_paint(ps, &w->paint); | |
+ free_wpaint(ps, w); | |
free_region(ps, &w->border_size); | |
free_paint(ps, &w->shadow_paint); | |
} | |
@@ -3037,7 +3049,7 @@ configure_win(session_t *ps, XConfigureEvent *ce) { | |
if (w->a.width != ce->width || w->a.height != ce->height | |
|| w->a.border_width != ce->border_width) | |
- free_paint(ps, &w->paint); | |
+ free_wpaint(ps, w); | |
if (w->a.width != ce->width || w->a.height != ce->height | |
|| w->a.border_width != ce->border_width) { | |
@@ -3188,10 +3200,10 @@ damage_win(session_t *ps, XDamageNotifyEvent *de) { | |
* Xlib error handler function. | |
*/ | |
static int | |
-error(Display __attribute__((unused)) *dpy, XErrorEvent *ev) { | |
+xerror(Display __attribute__((unused)) *dpy, XErrorEvent *ev) { | |
session_t * const ps = ps_g; | |
- int o; | |
+ int o = 0; | |
const char *name = "Unknown"; | |
if (should_ignore(ps, ev->serial)) { | |
@@ -3240,6 +3252,17 @@ error(Display __attribute__((unused)) *dpy, XErrorEvent *ev) { | |
} | |
#endif | |
+#ifdef CONFIG_XSYNC | |
+ if (ps->xsync_exists) { | |
+ o = ev->error_code - ps->xsync_error; | |
+ switch (o) { | |
+ CASESTRRET2(XSyncBadCounter); | |
+ CASESTRRET2(XSyncBadAlarm); | |
+ CASESTRRET2(XSyncBadFence); | |
+ } | |
+ } | |
+#endif | |
+ | |
switch (ev->error_code) { | |
CASESTRRET2(BadAccess); | |
CASESTRRET2(BadAlloc); | |
@@ -3771,18 +3794,27 @@ ev_name(session_t *ps, XEvent *ev) { | |
CASESTRRET(Expose); | |
CASESTRRET(PropertyNotify); | |
CASESTRRET(ClientMessage); | |
- default: | |
- if (isdamagenotify(ps, ev)) | |
- return "Damage"; | |
+ } | |
- if (ps->shape_exists && ev->type == ps->shape_event) { | |
- return "ShapeNotify"; | |
- } | |
+ if (isdamagenotify(ps, ev)) | |
+ return "Damage"; | |
- sprintf(buf, "Event %d", ev->type); | |
+ if (ps->shape_exists && ev->type == ps->shape_event) | |
+ return "ShapeNotify"; | |
- return buf; | |
+#ifdef CONFIG_XSYNC | |
+ if (ps->xsync_exists) { | |
+ int o = ev->type - ps->xsync_event; | |
+ switch (o) { | |
+ CASESTRRET(CounterNotify); | |
+ CASESTRRET(AlarmNotify); | |
+ } | |
} | |
+#endif | |
+ | |
+ sprintf(buf, "Event %d", ev->type); | |
+ | |
+ return buf; | |
} | |
static Window | |
@@ -6478,7 +6510,7 @@ redir_stop(session_t *ps) { | |
// If we don't destroy them here, looks like the resources are just | |
// kept inaccessible somehow | |
for (win *w = ps->list; w; w = w->next) | |
- free_paint(ps, &w->paint); | |
+ free_wpaint(ps, w); | |
XCompositeUnredirectSubwindows(ps->dpy, ps->root, CompositeRedirectManual); | |
// Unmap overlay window | |
@@ -6852,7 +6884,7 @@ session_init(session_t *ps_old, int argc, char **argv) { | |
} | |
} | |
- XSetErrorHandler(error); | |
+ XSetErrorHandler(xerror); | |
if (ps->o.synchronize) { | |
XSynchronize(ps->dpy, 1); | |
} | |
@@ -6912,6 +6944,16 @@ session_init(session_t *ps_old, int argc, char **argv) { | |
ps->shape_exists = true; | |
} | |
+#ifdef CONFIG_XSYNC | |
+ // Query X Sync | |
+ if (XSyncQueryExtension(ps->dpy, &ps->xsync_event, &ps->xsync_error)) { | |
+ // TODO: Fencing may require version >= 3.0? | |
+ int major_version_return = 0, minor_version_return = 0; | |
+ if (XSyncInitialize(ps->dpy, &major_version_return, &minor_version_return)) | |
+ ps->xsync_exists = true; | |
+ } | |
+#endif | |
+ | |
// Build a safe representation of display name | |
{ | |
char *display_repr = DisplayString(ps->dpy); | |
@@ -7219,6 +7261,7 @@ session_destroy(session_t *ps) { | |
ps->tgt_picture = None; | |
else | |
free_picture(ps, &ps->tgt_picture); | |
+ free_fence(ps, &ps->tgt_buffer_fence); | |
free_picture(ps, &ps->root_picture); | |
free_paint(ps, &ps->tgt_buffer); | |
diff --git a/src/compton.h b/src/compton.h | |
index 22ee195..a4e838e 100644 | |
--- a/src/compton.h | |
+++ b/src/compton.h | |
@@ -276,6 +276,15 @@ free_paint(session_t *ps, paint_t *ppaint) { | |
} | |
/** | |
+ * Free w->paint. | |
+ */ | |
+static inline void | |
+free_wpaint(session_t *ps, win *w) { | |
+ free_paint(ps, &w->paint); | |
+ free_fence(ps, &w->fence); | |
+} | |
+ | |
+/** | |
* Destroy all resources in a <code>struct _win</code>. | |
*/ | |
static inline void | |
@@ -883,7 +892,7 @@ static void | |
damage_win(session_t *ps, XDamageNotifyEvent *de); | |
static int | |
-error(Display *dpy, XErrorEvent *ev); | |
+xerror(Display *dpy, XErrorEvent *ev); | |
static void | |
expose_root(session_t *ps, XRectangle *rects, int nrects); | |
diff --git a/src/opengl.c b/src/opengl.c | |
index d557aea..39aac33 100644 | |
--- a/src/opengl.c | |
+++ b/src/opengl.c | |
@@ -10,6 +10,50 @@ | |
#include "opengl.h" | |
+#ifdef CONFIG_GLX_SYNC | |
+void | |
+xr_glx_sync(session_t *ps, Drawable d, XSyncFence *pfence) { | |
+ if (*pfence) { | |
+ // GLsync sync = ps->glFenceSyncProc(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); | |
+ GLsync sync = ps->glImportSyncEXT(GL_SYNC_X11_FENCE_EXT, *pfence, 0); | |
+ XSync(ps->dpy, False); | |
+ glx_check_err(ps); | |
+ /* GLenum ret = ps->glClientWaitSyncProc(sync, GL_SYNC_FLUSH_COMMANDS_BIT, | |
+ 1000); | |
+ assert(GL_CONDITION_SATISFIED == ret); */ | |
+ ps->glWaitSyncProc(sync, 0, GL_TIMEOUT_IGNORED); | |
+ // ps->glDeleteSyncProc(sync); | |
+ // XSyncResetFence(ps->dpy, *pfence); | |
+ } | |
+ glx_check_err(ps); | |
+} | |
+#endif | |
+ | |
+static inline GLXFBConfig | |
+get_fbconfig_from_visualinfo(session_t *ps, const XVisualInfo *visualinfo) { | |
+ int nelements = 0; | |
+ GLXFBConfig *fbconfigs = glXGetFBConfigs(ps->dpy, visualinfo->screen, | |
+ &nelements); | |
+ for (int i = 0; i < nelements; ++i) { | |
+ int visual_id = 0; | |
+ if (Success == glXGetFBConfigAttrib(ps->dpy, fbconfigs[i], GLX_VISUAL_ID, &visual_id) | |
+ && visual_id == visualinfo->visualid) | |
+ return fbconfigs[i]; | |
+ } | |
+ | |
+ return NULL; | |
+} | |
+ | |
+#ifdef DEBUG_GLX_DEBUG_CONTEXT | |
+static void | |
+glx_debug_msg_callback(GLenum source, GLenum type, | |
+ GLuint id, GLenum severity, GLsizei length, const GLchar *message, | |
+ GLvoid *userParam) { | |
+ printf_dbgf("(): source 0x%04X, type 0x%04X, id %u, severity 0x%0X, \"%s\"\n", | |
+ source, type, id, severity, message); | |
+} | |
+#endif | |
+ | |
/** | |
* Initialize OpenGL. | |
*/ | |
@@ -56,7 +100,33 @@ glx_init(session_t *ps, bool need_render) { | |
if (!ps->glx_context) { | |
// Get GLX context | |
+#ifndef DEBUG_GLX_DEBUG_CONTEXT | |
ps->glx_context = glXCreateContext(ps->dpy, pvis, None, GL_TRUE); | |
+#else | |
+ { | |
+ GLXFBConfig fbconfig = get_fbconfig_from_visualinfo(ps, pvis); | |
+ if (!fbconfig) { | |
+ printf_errf("(): Failed to get GLXFBConfig for root visual %#lx.", | |
+ pvis->visualid); | |
+ goto glx_init_end; | |
+ } | |
+ | |
+ f_glXCreateContextAttribsARB p_glXCreateContextAttribsARB = | |
+ (f_glXCreateContextAttribsARB) | |
+ glXGetProcAddress((const GLubyte *) "glXCreateContextAttribsARB"); | |
+ if (!p_glXCreateContextAttribsARB) { | |
+ printf_errf("(): Failed to get glXCreateContextAttribsARB()."); | |
+ goto glx_init_end; | |
+ } | |
+ | |
+ static const int attrib_list[] = { | |
+ GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB, | |
+ None | |
+ }; | |
+ ps->glx_context = p_glXCreateContextAttribsARB(ps->dpy, fbconfig, NULL, | |
+ GL_TRUE, attrib_list); | |
+ } | |
+#endif | |
if (!ps->glx_context) { | |
printf_errf("(): Failed to get GLX context."); | |
@@ -68,6 +138,20 @@ glx_init(session_t *ps, bool need_render) { | |
printf_errf("(): Failed to attach GLX context."); | |
goto glx_init_end; | |
} | |
+ | |
+#ifdef DEBUG_GLX_DEBUG_CONTEXT | |
+ { | |
+ f_DebugMessageCallback p_DebugMessageCallback = | |
+ (f_DebugMessageCallback) | |
+ glXGetProcAddress((const GLubyte *) "glDebugMessageCallback"); | |
+ if (!p_DebugMessageCallback) { | |
+ printf_errf("(): Failed to get glDebugMessageCallback(0."); | |
+ goto glx_init_end; | |
+ } | |
+ p_DebugMessageCallback(glx_debug_msg_callback, ps); | |
+ } | |
+#endif | |
+ | |
} | |
// Ensure we have a stencil buffer. X Fixes does not guarantee rectangles | |
@@ -114,6 +198,27 @@ glx_init(session_t *ps, bool need_render) { | |
goto glx_init_end; | |
} | |
} | |
+ | |
+#ifdef CONFIG_GLX_SYNC | |
+ ps->glFenceSyncProc = (f_FenceSync) | |
+ glXGetProcAddress((const GLubyte *) "glFenceSync"); | |
+ ps->glIsSyncProc = (f_IsSync) | |
+ glXGetProcAddress((const GLubyte *) "glIsSync"); | |
+ ps->glDeleteSyncProc = (f_DeleteSync) | |
+ glXGetProcAddress((const GLubyte *) "glDeleteSync"); | |
+ ps->glClientWaitSyncProc = (f_ClientWaitSync) | |
+ glXGetProcAddress((const GLubyte *) "glClientWaitSync"); | |
+ ps->glWaitSyncProc = (f_WaitSync) | |
+ glXGetProcAddress((const GLubyte *) "glWaitSync"); | |
+ ps->glImportSyncEXT = (f_ImportSyncEXT) | |
+ glXGetProcAddress((const GLubyte *) "glImportSyncEXT"); | |
+ if (!ps->glFenceSyncProc || !ps->glIsSyncProc || !ps->glDeleteSyncProc | |
+ || !ps->glClientWaitSyncProc || !ps->glWaitSyncProc | |
+ || !ps->glImportSyncEXT) { | |
+ printf_errf("(): Failed to acquire GLX sync functions."); | |
+ goto glx_init_end; | |
+ } | |
+#endif | |
} | |
// Acquire FBConfigs | |
@@ -344,9 +449,7 @@ glx_init_blur(session_t *ps) { | |
} | |
-#ifdef DEBUG_GLX_ERR | |
glx_check_err(ps); | |
-#endif | |
return true; | |
#else | |
@@ -655,9 +758,7 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap, | |
glBindTexture(ptex->target, 0); | |
glDisable(ptex->target); | |
-#ifdef DEBUG_GLX_ERR | |
glx_check_err(ps); | |
-#endif | |
return true; | |
} | |
@@ -680,9 +781,7 @@ glx_release_pixmap(session_t *ps, glx_texture_t *ptex) { | |
ptex->glpixmap = 0; | |
} | |
-#ifdef DEBUG_GLX_ERR | |
glx_check_err(ps); | |
-#endif | |
} | |
/** | |
@@ -803,9 +902,7 @@ glx_paint_pre(session_t *ps, XserverRegion *preg) { | |
glx_render_color(ps, 0, 0, ps->root_width, ps->root_height, 0, *preg, NULL); | |
#endif | |
-#ifdef DEBUG_GLX_ERR | |
glx_check_err(ps); | |
-#endif | |
} | |
/** | |
@@ -886,9 +983,7 @@ glx_set_clip(session_t *ps, XserverRegion reg, const reg_data_t *pcache_reg) { | |
cxfree(rects_free); | |
-#ifdef DEBUG_GLX_ERR | |
glx_check_err(ps); | |
-#endif | |
} | |
#define P_PAINTREG_START() \ | |
@@ -1174,9 +1269,7 @@ glx_blur_dst_end: | |
free_glx_bc(ps, pbc); | |
} | |
-#ifdef DEBUG_GLX_ERR | |
glx_check_err(ps); | |
-#endif | |
return ret; | |
} | |
@@ -1212,9 +1305,7 @@ glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z, | |
glColor4f(0.0f, 0.0f, 0.0f, 0.0f); | |
glDisable(GL_BLEND); | |
-#ifdef DEBUG_GLX_ERR | |
glx_check_err(ps); | |
-#endif | |
return true; | |
} | |
@@ -1412,9 +1503,7 @@ glx_render(session_t *ps, const glx_texture_t *ptex, | |
glActiveTexture(GL_TEXTURE0); | |
} | |
-#ifdef DEBUG_GLX_ERR | |
glx_check_err(ps); | |
-#endif | |
return true; | |
} | |
@@ -1452,9 +1541,7 @@ glx_render_color(session_t *ps, int dx, int dy, int width, int height, int z, | |
} | |
glColor4f(0.0f, 0.0f, 0.0f, 0.0f); | |
-#ifdef DEBUG_GLX_ERR | |
glx_check_err(ps); | |
-#endif | |
} | |
/** | |
@@ -1492,9 +1579,7 @@ glx_render_dots(session_t *ps, int dx, int dy, int width, int height, int z, | |
} | |
glColor4f(0.0f, 0.0f, 0.0f, 0.0f); | |
-#ifdef DEBUG_GLX_ERR | |
glx_check_err(ps); | |
-#endif | |
} | |
/** | |
@@ -1524,9 +1609,7 @@ glx_swap_copysubbuffermesa(session_t *ps, XserverRegion reg) { | |
} | |
} | |
-#ifdef DEBUG_GLX_ERR | |
glx_check_err(ps); | |
-#endif | |
cxfree(rects); | |
} | |
diff --git a/src/opengl.h b/src/opengl.h | |
index 564b7e2..8628e36 100644 | |
--- a/src/opengl.h | |
+++ b/src/opengl.h | |
@@ -59,6 +59,8 @@ glx_check_err_(session_t *ps, const char *func, int line) { | |
} | |
#define glx_check_err(ps) glx_check_err_(ps, __func__, __LINE__) | |
+#else | |
+#define glx_check_err(ps) ((void) 0) | |
#endif | |
/** |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment