summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Grenville <pyxlcy@gmail.com>2013-03-21 13:05:56 +0800
committerRichard Grenville <pyxlcy@gmail.com>2013-03-21 13:05:56 +0800
commit2dfe9d52ed6d83fd0f2cc6cc0d921701dcb8b017 (patch)
tree734b354c4c6c1ed99343bd958d53d072c4d776cb
parentda85de48a9d078eeb5a437482c41c85884496318 (diff)
downloadtdebase-2dfe9d52ed6d83fd0f2cc6cc0d921701dcb8b017.tar.gz
tdebase-2dfe9d52ed6d83fd0f2cc6cc0d921701dcb8b017.zip
Improvement: --glx-use-copysubbuffermesa
- GLX backend: Add --glx-use-copysubbuffermesa, to use MESA_copy_sub_buffer to do partial screen update. Huge performance boost on mesa drivers for partial screen updates, but does not work for nvidia-drivers and may break VSync. Automagically overrides --glx-copy-from-front. - Add rect_is_fullscreen() to reuse code. Misc changes.
-rw-r--r--common.h18
-rw-r--r--compton.c24
-rw-r--r--compton.h6
-rw-r--r--opengl.c48
4 files changed, 84 insertions, 12 deletions
diff --git a/common.h b/common.h
index 977643b60..2f8b6e20d 100644
--- a/common.h
+++ b/common.h
@@ -284,6 +284,8 @@ typedef int (*f_SwapIntervalSGI) (int interval);
typedef void (*f_BindTexImageEXT) (Display *display, GLXDrawable drawable, int buffer, const int *attrib_list);
typedef void (*f_ReleaseTexImageEXT) (Display *display, GLXDrawable drawable, int buffer);
+typedef void (*f_CopySubBuffer) (Display *dpy, GLXDrawable drawable, int x, int y, int width, int height);
+
/// @brief Wrapper of a GLX FBConfig.
typedef struct {
GLXFBConfig cfg;
@@ -344,6 +346,8 @@ typedef struct {
bool glx_no_stencil;
/// Whether to copy unmodified regions from front buffer.
bool glx_copy_from_front;
+ /// Whether to use glXCopySubBufferMESA() to update screen.
+ bool glx_use_copysubbuffermesa;
/// Whether to try to detect WM windows and mark them as focused.
bool mark_wmwin_focused;
/// Whether to mark override-redirect windows as focused.
@@ -624,6 +628,8 @@ typedef struct {
f_BindTexImageEXT glXBindTexImageProc;
/// Pointer to glXReleaseTexImageEXT function.
f_ReleaseTexImageEXT glXReleaseTexImageProc;
+ /// Pointer to glXCopySubBufferMESA function.
+ f_CopySubBuffer glXCopySubBufferProc;
/// FBConfig-s for GLX pixmap of different depths.
glx_fbconfig_t *glx_fbconfigs[OPENGL_MAX_DEPTH + 1];
#ifdef CONFIG_VSYNC_OPENGL_GLSL
@@ -1491,6 +1497,15 @@ free_region(session_t *ps, XserverRegion *p) {
}
/**
+ * Check if a rectangle includes the whole screen.
+ */
+static inline bool
+rect_is_fullscreen(session_t *ps, int x, int y, unsigned wid, unsigned hei) {
+ return (x <= 0 && y <= 0
+ && (x + wid) >= ps->root_width && (y + hei) >= ps->root_height);
+}
+
+/**
* Determine if a window has a specific property.
*
* @param ps current session
@@ -1621,6 +1636,9 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
int x, int y, int dx, int dy, int width, int height, int z,
double opacity, bool neg, XserverRegion reg_tgt);
+void
+glx_swap_copysubbuffermesa(session_t *ps, XserverRegion reg);
+
#ifdef CONFIG_VSYNC_OPENGL_GLSL
GLuint
glx_create_shader(GLenum shader_type, const char *shader_str);
diff --git a/compton.c b/compton.c
index 9e8623ea8..811bbf17e 100644
--- a/compton.c
+++ b/compton.c
@@ -1736,7 +1736,6 @@ paint_all(session_t *ps, XserverRegion region, win *t) {
}
// Free up all temporary regions
- XFixesDestroyRegion(ps->dpy, region);
XFixesDestroyRegion(ps->dpy, reg_tmp);
XFixesDestroyRegion(ps->dpy, reg_tmp2);
@@ -1783,7 +1782,10 @@ paint_all(session_t *ps, XserverRegion region, win *t) {
break;
#ifdef CONFIG_VSYNC_OPENGL
case BKEND_GLX:
- glXSwapBuffers(ps->dpy, get_tgt_window(ps));
+ if (ps->o.glx_use_copysubbuffermesa)
+ glx_swap_copysubbuffermesa(ps, region);
+ else
+ glXSwapBuffers(ps->dpy, get_tgt_window(ps));
break;
#endif
default:
@@ -1802,6 +1804,8 @@ paint_all(session_t *ps, XserverRegion region, win *t) {
}
#endif
+ XFixesDestroyRegion(ps->dpy, region);
+
#ifdef DEBUG_REPAINT
print_timestamp(ps);
struct timespec now = get_time_timespec();
@@ -4151,9 +4155,14 @@ usage(void) {
" negative effect on performance. (My test shows a 10% slowdown.)\n"
"--glx-copy-from-front\n"
" GLX backend: Copy unmodified regions from front buffer instead of\n"
- " redrawing them all. My tests show a 10% decrease in performance\n"
- " when the whole screen is modified, but a 20% increase when only 1/4\n"
- " is, so this optimization is not enabled by default.\n"
+ " redrawing them all. My tests with nvidia-drivers show a 10% decrease\n"
+ " in performance when the whole screen is modified, but a 20% increase\n"
+ " when only 1/4 is. My tests on nouveau show terrible slowdown.\n"
+ "--glx-use-copysubbuffermesa\n"
+ " GLX backend: Use MESA_copy_sub_buffer to do partial screen update.\n"
+ " My tests on nouveau shows a 200% performance boost when only 1/4 of\n"
+ " the screen is updated. May break VSync and is not available on some\n"
+ " drivers. Overrides --glx-copy-from-front.\n"
#undef WARNING
#ifndef CONFIG_DBUS
#define WARNING WARNING_DISABLED
@@ -4620,6 +4629,7 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
{ "glx-copy-from-front", no_argument, NULL, 292 },
{ "benchmark", required_argument, NULL, 293 },
{ "benchmark-wid", required_argument, NULL, 294 },
+ { "glx-use-copysubbuffermesa", no_argument, NULL, 295 },
// Must terminate with a NULL entry
{ NULL, 0, NULL, 0 },
};
@@ -4898,6 +4908,10 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
// --benchmark-wid
ps->o.benchmark_wid = strtol(optarg, NULL, 0);
break;
+ case 295:
+ // --glx-use-copysubbuffermesa
+ ps->o.glx_use_copysubbuffermesa = true;
+ break;
default:
usage();
break;
diff --git a/compton.h b/compton.h
index c16c59612..b590b0ead 100644
--- a/compton.h
+++ b/compton.h
@@ -427,10 +427,8 @@ dump_drawable(session_t *ps, Drawable drawable) {
*/
static inline bool
win_is_fullscreen(session_t *ps, const win *w) {
- return (w->a.x <= 0 && w->a.y <= 0
- && (w->a.x + w->widthb) >= ps->root_width
- && (w->a.y + w->heightb) >= ps->root_height
- && !w->bounding_shaped);
+ return rect_is_fullscreen(ps, w->a.x, w->a.y, w->widthb, w->heightb)
+ && !w->bounding_shaped;
}
static void
diff --git a/opengl.c b/opengl.c
index a0bed63bb..3f1f419b7 100644
--- a/opengl.c
+++ b/opengl.c
@@ -96,6 +96,15 @@ glx_init(session_t *ps, bool need_render) {
printf_errf("(): Failed to acquire glXBindTexImageEXT() / glXReleaseTexImageEXT().");
goto glx_init_end;
}
+
+ if (ps->o.glx_use_copysubbuffermesa) {
+ ps->glXCopySubBufferProc = (f_CopySubBuffer)
+ glXGetProcAddress((const GLubyte *) "glXCopySubBufferMESA");
+ if (!ps->glXCopySubBufferProc) {
+ printf_errf("(): Failed to acquire glXCopySubBufferMESA().");
+ goto glx_init_end;
+ }
+ }
}
// Acquire FBConfigs
@@ -543,10 +552,13 @@ void
glx_paint_pre(session_t *ps, XserverRegion *preg) {
ps->glx_z = 0.0;
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
// OpenGL doesn't support partial repaint without GLX_MESA_copy_sub_buffer,
- // we currently redraw the whole screen or copy unmodified pixels from
+ // we could redraw the whole screen or copy unmodified pixels from
// front buffer with --glx-copy-from-front.
- if (!ps->o.glx_copy_from_front || !*preg) {
+ if (ps->o.glx_use_copysubbuffermesa || !*preg) {
+ }
+ else if (!ps->o.glx_copy_from_front) {
free_region(ps, preg);
}
else {
@@ -612,7 +624,6 @@ glx_set_clip(session_t *ps, XserverRegion reg) {
glDepthMask(GL_FALSE);
glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);
-
glBegin(GL_QUADS);
for (int i = 0; i < nrects; ++i) {
@@ -853,6 +864,37 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
return true;
}
+/**
+ * Swap buffer with glXCopySubBufferMESA().
+ */
+void
+glx_swap_copysubbuffermesa(session_t *ps, XserverRegion reg) {
+ int nrects = 0;
+ XRectangle *rects = XFixesFetchRegion(ps->dpy, reg, &nrects);
+
+ if (1 == nrects && rect_is_fullscreen(ps, rects[0].x, rects[0].y,
+ rects[0].width, rects[0].height)) {
+ glXSwapBuffers(ps->dpy, get_tgt_window(ps));
+ }
+ else {
+ glx_set_clip(ps, None);
+ for (int i = 0; i < nrects; ++i) {
+ const int x = rects[i].x;
+ const int y = ps->root_height - rects[i].y - rects[i].height;
+ const int wid = rects[i].width;
+ const int hei = rects[i].height;
+
+#ifdef DEBUG_GLX
+ printf_dbgf("(): %d, %d, %d, %d\n", x, y, wid, hei);
+#endif
+ ps->glXCopySubBufferProc(ps->dpy, get_tgt_window(ps), x, y, wid, hei);
+ }
+ }
+
+ if (rects)
+ XFree(rects);
+}
+
#ifdef CONFIG_VSYNC_OPENGL_GLSL
GLuint
glx_create_shader(GLenum shader_type, const char *shader_str) {