Feature: OpenGL backend
- Add experimental OpenGL backend (--opengl). --blur-background is currently not possible with this backend, because I'm still trying to find a proper way to do blur with OpenGL. Flipping backend on-the-fly is really hard, so it isn't supported right now. No configuration file option exists to enable this, because it isn't stable enough. - Add `opengl-swc` VSync method that uses SGI_swap_control to control buffer swap, with OpenGL backend. (#7) - Fix a potential read-from-freed-memory issue in paint_all(). - Correctly reattach GLX context after fork. - Dump error text in error(). Add GLX error code handling. - Code clean-up. - Known issues: Region operations take a lot of time in glx_render(). I'm hesitating about what to do.
This commit is contained in:
137
src/compton.h
137
src/compton.h
@ -9,7 +9,6 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <sys/select.h>
|
||||
#include <limits.h>
|
||||
@ -52,14 +51,6 @@ set_ignore_next(session_t *ps) {
|
||||
static int
|
||||
should_ignore(session_t *ps, unsigned long sequence);
|
||||
|
||||
/**
|
||||
* Return the painting target window.
|
||||
*/
|
||||
static inline Window
|
||||
get_tgt_window(session_t *ps) {
|
||||
return ps->o.paint_on_overlay ? ps->overlay: ps->root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset filter on a <code>Picture</code>.
|
||||
*/
|
||||
@ -119,16 +110,6 @@ array_wid_exists(const Window *arr, int count, Window wid) {
|
||||
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Destroy a <code>XserverRegion</code>.
|
||||
*/
|
||||
inline static void
|
||||
free_region(session_t *ps, XserverRegion *p) {
|
||||
if (*p) {
|
||||
XFixesDestroyRegion(ps->dpy, *p);
|
||||
*p = None;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a <code>Picture</code>.
|
||||
@ -176,16 +157,58 @@ free_wincondlst(c2_lptr_t **pcondlst) {
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Check whether a paint_t contains enough data.
|
||||
*/
|
||||
static inline bool
|
||||
paint_isvalid(session_t *ps, const paint_t *ppaint) {
|
||||
if (!ppaint || !ppaint->pixmap)
|
||||
return false;
|
||||
|
||||
if (BKEND_XRENDER == ps->o.backend && !ppaint->pict)
|
||||
return false;
|
||||
|
||||
#ifdef CONFIG_VSYNC_OPENGL
|
||||
if (BKEND_GLX == ps->o.backend && !glx_tex_binded(ppaint->ptex))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Bind texture in paint_t if we are using OpenGL backend.
|
||||
*/
|
||||
static inline bool
|
||||
paint_bind_tex(session_t *ps, paint_t *ppaint, int wid, int hei, int depth) {
|
||||
#ifdef CONFIG_VSYNC_OPENGL
|
||||
// TODO: Make sure we have the same Pixmap binded?
|
||||
if (BKEND_GLX == ps->o.backend && !glx_tex_binded(ppaint->ptex)) {
|
||||
return glx_bind_pixmap(ps, &ppaint->ptex, ppaint->pixmap, wid, hei, depth);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free paint_t.
|
||||
*/
|
||||
static inline void
|
||||
free_paint(session_t *ps, paint_t *ppaint) {
|
||||
free_texture(ps, &ppaint->ptex);
|
||||
free_picture(ps, &ppaint->pict);
|
||||
free_pixmap(ps, &ppaint->pixmap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy all resources in a <code>struct _win</code>.
|
||||
*/
|
||||
inline static void
|
||||
static inline void
|
||||
free_win_res(session_t *ps, win *w) {
|
||||
free_region(ps, &w->extents);
|
||||
free_pixmap(ps, &w->pixmap);
|
||||
free_picture(ps, &w->picture);
|
||||
free_paint(ps, &w->paint);
|
||||
free_region(ps, &w->border_size);
|
||||
free_picture(ps, &w->shadow_pict);
|
||||
free_paint(ps, &w->shadow_paint);
|
||||
free_damage(ps, &w->damage);
|
||||
free_region(ps, &w->reg_ignore);
|
||||
free(w->name);
|
||||
@ -194,6 +217,19 @@ free_win_res(session_t *ps, win *w) {
|
||||
free(w->role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free root tile related things.
|
||||
*/
|
||||
static inline void
|
||||
free_root_tile(session_t *ps) {
|
||||
free_picture(ps, &ps->root_tile_paint.pict);
|
||||
free_texture(ps, &ps->root_tile_paint.ptex);
|
||||
if (ps->root_tile_fill)
|
||||
free_pixmap(ps, &ps->root_tile_paint.pixmap);
|
||||
ps->root_tile_paint.pixmap = None;
|
||||
ps->root_tile_fill = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current system clock in milliseconds.
|
||||
*/
|
||||
@ -274,8 +310,8 @@ presum_gaussian(session_t *ps, conv *map);
|
||||
static XImage *
|
||||
make_shadow(session_t *ps, double opacity, int width, int height);
|
||||
|
||||
static Picture
|
||||
shadow_picture(session_t *ps, double opacity, int width, int height);
|
||||
static bool
|
||||
win_build_shadow(session_t *ps, win *w, double opacity);
|
||||
|
||||
static Picture
|
||||
solid_picture(session_t *ps, bool argb, double a,
|
||||
@ -463,11 +499,11 @@ group_is_focused(session_t *ps, Window leader) {
|
||||
static win *
|
||||
recheck_focus(session_t *ps);
|
||||
|
||||
static Picture
|
||||
root_tile_f(session_t *ps);
|
||||
static bool
|
||||
get_root_tile(session_t *ps);
|
||||
|
||||
static void
|
||||
paint_root(session_t *ps, Picture tgt_buffer);
|
||||
paint_root(session_t *ps, XserverRegion reg_paint);
|
||||
|
||||
static XserverRegion
|
||||
win_get_region(session_t *ps, win *w, bool use_offset);
|
||||
@ -490,6 +526,22 @@ get_frame_extents(session_t *ps, win *w, Window client);
|
||||
static win *
|
||||
paint_preprocess(session_t *ps, win *list);
|
||||
|
||||
static void
|
||||
render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei,
|
||||
double opacity, bool argb, bool neg,
|
||||
Picture pict, glx_texture_t *ptex, XserverRegion reg_paint);
|
||||
|
||||
static inline void
|
||||
win_render(session_t *ps, win *w, int x, int y, int wid, int hei, double opacity, XserverRegion reg_paint, Picture pict) {
|
||||
const int dx = (w ? w->a.x: 0) + x;
|
||||
const int dy = (w ? w->a.y: 0) + y;
|
||||
const bool argb = (w && w->mode == WMODE_ARGB);
|
||||
const bool neg = (w && w->invert_color);
|
||||
|
||||
render(ps, x, y, dx, dy, wid, hei, opacity, argb, neg,
|
||||
pict, (w ? w->paint.ptex: ps->root_tile_paint.ptex), reg_paint);
|
||||
}
|
||||
|
||||
static void
|
||||
paint_all(session_t *ps, XserverRegion region, win *t);
|
||||
|
||||
@ -887,31 +939,7 @@ swopti_init(session_t *ps);
|
||||
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.
|
||||
*/
|
||||
@ -919,7 +947,7 @@ static inline bool
|
||||
ensure_glx_context(session_t *ps) {
|
||||
// Create GLX context
|
||||
if (!ps->glx_context)
|
||||
opengl_init(ps, false);
|
||||
glx_init(ps, false);
|
||||
|
||||
return ps->glx_context;
|
||||
}
|
||||
@ -939,6 +967,9 @@ vsync_opengl_init(session_t *ps);
|
||||
static bool
|
||||
vsync_opengl_oml_init(session_t *ps);
|
||||
|
||||
static bool
|
||||
vsync_opengl_swc_init(session_t *ps);
|
||||
|
||||
#ifdef CONFIG_VSYNC_OPENGL
|
||||
static int
|
||||
vsync_opengl_wait(session_t *ps);
|
||||
|
Reference in New Issue
Block a user