summaryrefslogtreecommitdiffstats
path: root/opengl.c
diff options
context:
space:
mode:
authorRichard Grenville <[email protected]>2013-03-21 13:05:56 +0800
committerRichard Grenville <[email protected]>2013-03-21 13:05:56 +0800
commit2dfe9d52ed6d83fd0f2cc6cc0d921701dcb8b017 (patch)
tree734b354c4c6c1ed99343bd958d53d072c4d776cb /opengl.c
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.
Diffstat (limited to 'opengl.c')
-rw-r--r--opengl.c48
1 files changed, 45 insertions, 3 deletions
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) {