- Add --glx-fshader-win, which specifies a custom fragment shader for painting windows. compton-default-fshader-win.glsl is the shader with default behavior, and compton-fake-transparency-fshader-win.glsl provides a template of fake transparency. (#183) - Add --force-win-blend to force all windows to be painted with blending. - Add --no-fading-destroyed-argb, as a workaround of bugs in some WMs. (#193)
This commit is contained in:
parent
bb55706c05
commit
81c677f28b
|
@ -0,0 +1,11 @@
|
||||||
|
uniform float opacity;
|
||||||
|
uniform bool invert_color;
|
||||||
|
uniform sampler2D tex;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 c = texture2D(tex, gl_TexCoord[0]);
|
||||||
|
if (invert_color)
|
||||||
|
c = vec4(vec3(c.a, c.a, c.a) - vec3(c), c.a);
|
||||||
|
c *= opacity;
|
||||||
|
gl_FragColor = c;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
uniform float opacity;
|
||||||
|
uniform bool invert_color;
|
||||||
|
uniform sampler2D tex;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 c = texture2D(tex, gl_TexCoord[0]);
|
||||||
|
{
|
||||||
|
// Change vec4(1.0, 1.0, 1.0, 1.0) to your desired color
|
||||||
|
vec4 vdiff = abs(vec4(1.0, 1.0, 1.0, 1.0) - c);
|
||||||
|
float diff = max(max(max(vdiff.r, vdiff.g), vdiff.b), vdiff.a);
|
||||||
|
// Change 0.8 to your desired opacity
|
||||||
|
if (diff < 0.001)
|
||||||
|
c *= 0.8;
|
||||||
|
}
|
||||||
|
if (invert_color)
|
||||||
|
c = vec4(vec3(c.a, c.a, c.a) - vec3(c), c.a);
|
||||||
|
c *= opacity;
|
||||||
|
gl_FragColor = c;
|
||||||
|
}
|
|
@ -48,6 +48,7 @@ fading = true;
|
||||||
fade-in-step = 0.03;
|
fade-in-step = 0.03;
|
||||||
fade-out-step = 0.03;
|
fade-out-step = 0.03;
|
||||||
# no-fading-openclose = true;
|
# no-fading-openclose = true;
|
||||||
|
# no-fading-destroyed-argb = true;
|
||||||
fade-exclude = [ ];
|
fade-exclude = [ ];
|
||||||
|
|
||||||
# Other
|
# Other
|
||||||
|
@ -84,5 +85,5 @@ glx-swap-method = "undefined";
|
||||||
# Window type settings
|
# Window type settings
|
||||||
wintypes:
|
wintypes:
|
||||||
{
|
{
|
||||||
tooltip = { fade = true; shadow = false; opacity = 0.75; focus = true; };
|
tooltip = { fade = true; shadow = true; opacity = 0.75; focus = true; };
|
||||||
};
|
};
|
||||||
|
|
76
src/common.h
76
src/common.h
|
@ -469,6 +469,25 @@ typedef struct {
|
||||||
/// Height of the textures.
|
/// Height of the textures.
|
||||||
int height;
|
int height;
|
||||||
} glx_blur_cache_t;
|
} glx_blur_cache_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/// GLSL program.
|
||||||
|
GLuint prog;
|
||||||
|
/// Location of uniform "opacity" in window GLSL program.
|
||||||
|
GLint unifm_opacity;
|
||||||
|
/// Location of uniform "invert_color" in blur GLSL program.
|
||||||
|
GLint unifm_invert_color;
|
||||||
|
/// Location of uniform "tex" in window GLSL program.
|
||||||
|
GLint unifm_tex;
|
||||||
|
} glx_prog_main_t;
|
||||||
|
|
||||||
|
#define GLX_PROG_MAIN_INIT { \
|
||||||
|
.prog = 0, \
|
||||||
|
.unifm_opacity = -1, \
|
||||||
|
.unifm_invert_color = -1, \
|
||||||
|
.unifm_tex = -1, \
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -536,10 +555,12 @@ typedef struct _options_t {
|
||||||
int glx_swap_method;
|
int glx_swap_method;
|
||||||
/// Whether to use GL_EXT_gpu_shader4 to (hopefully) accelerates blurring.
|
/// Whether to use GL_EXT_gpu_shader4 to (hopefully) accelerates blurring.
|
||||||
bool glx_use_gpushader4;
|
bool glx_use_gpushader4;
|
||||||
/// Whether to try to detect WM windows and mark them as focused.
|
/// Custom fragment shader for painting windows, as a string.
|
||||||
bool mark_wmwin_focused;
|
char *glx_fshader_win_str;
|
||||||
/// Whether to mark override-redirect windows as focused.
|
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
||||||
bool mark_ovredir_focused;
|
/// Custom GLX program used for painting window.
|
||||||
|
glx_prog_main_t glx_prog_win;
|
||||||
|
#endif
|
||||||
/// Whether to fork to background.
|
/// Whether to fork to background.
|
||||||
bool fork_after_register;
|
bool fork_after_register;
|
||||||
/// Whether to detect rounded corners.
|
/// Whether to detect rounded corners.
|
||||||
|
@ -547,6 +568,8 @@ typedef struct _options_t {
|
||||||
/// Whether to paint on X Composite overlay window instead of root
|
/// Whether to paint on X Composite overlay window instead of root
|
||||||
/// window.
|
/// window.
|
||||||
bool paint_on_overlay;
|
bool paint_on_overlay;
|
||||||
|
/// Force painting of window content with blending.
|
||||||
|
bool force_win_blend;
|
||||||
/// Resize damage for a specific number of pixels.
|
/// Resize damage for a specific number of pixels.
|
||||||
int resize_damage;
|
int resize_damage;
|
||||||
/// Whether to unredirect all windows if a full-screen opaque window
|
/// Whether to unredirect all windows if a full-screen opaque window
|
||||||
|
@ -622,6 +645,8 @@ typedef struct _options_t {
|
||||||
time_ms_t fade_delta;
|
time_ms_t fade_delta;
|
||||||
/// Whether to disable fading on window open/close.
|
/// Whether to disable fading on window open/close.
|
||||||
bool no_fading_openclose;
|
bool no_fading_openclose;
|
||||||
|
/// Whether to disable fading on ARGB managed destroyed windows.
|
||||||
|
bool no_fading_destroyed_argb;
|
||||||
/// Fading blacklist. A linked list of conditions.
|
/// Fading blacklist. A linked list of conditions.
|
||||||
c2_lptr_t *fade_blacklist;
|
c2_lptr_t *fade_blacklist;
|
||||||
|
|
||||||
|
@ -672,6 +697,10 @@ typedef struct _options_t {
|
||||||
// === Focus related ===
|
// === Focus related ===
|
||||||
/// Consider windows of specific types to be always focused.
|
/// Consider windows of specific types to be always focused.
|
||||||
bool wintype_focus[NUM_WINTYPES];
|
bool wintype_focus[NUM_WINTYPES];
|
||||||
|
/// Whether to try to detect WM windows and mark them as focused.
|
||||||
|
bool mark_wmwin_focused;
|
||||||
|
/// Whether to mark override-redirect windows as focused.
|
||||||
|
bool mark_ovredir_focused;
|
||||||
/// Whether to use EWMH _NET_ACTIVE_WINDOW to find active window.
|
/// Whether to use EWMH _NET_ACTIVE_WINDOW to find active window.
|
||||||
bool use_ewmh_active_win;
|
bool use_ewmh_active_win;
|
||||||
/// A list of windows always to be considered focused.
|
/// A list of windows always to be considered focused.
|
||||||
|
@ -1965,6 +1994,14 @@ win_is_fullscreen(session_t *ps, const win *w) {
|
||||||
&& (!w->bounding_shaped || w->rounded_corners);
|
&& (!w->bounding_shaped || w->rounded_corners);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a window will be painted solid.
|
||||||
|
*/
|
||||||
|
static inline bool
|
||||||
|
win_is_solid(session_t *ps, const win *w) {
|
||||||
|
return WMODE_SOLID == w->mode && !ps->o.force_win_blend;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if a window has a specific property.
|
* Determine if a window has a specific property.
|
||||||
*
|
*
|
||||||
|
@ -2073,6 +2110,13 @@ glx_on_root_change(session_t *ps);
|
||||||
bool
|
bool
|
||||||
glx_init_blur(session_t *ps);
|
glx_init_blur(session_t *ps);
|
||||||
|
|
||||||
|
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
||||||
|
bool
|
||||||
|
glx_load_prog_main(session_t *ps,
|
||||||
|
const char *vshader_str, const char *fshader_str,
|
||||||
|
glx_prog_main_t *pprogram);
|
||||||
|
#endif
|
||||||
|
|
||||||
bool
|
bool
|
||||||
glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap,
|
glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap,
|
||||||
unsigned width, unsigned height, unsigned depth);
|
unsigned width, unsigned height, unsigned depth);
|
||||||
|
@ -2108,10 +2152,24 @@ glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
||||||
GLfloat factor, XserverRegion reg_tgt, const reg_data_t *pcache_reg);
|
GLfloat factor, XserverRegion reg_tgt, const reg_data_t *pcache_reg);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
glx_render(session_t *ps, const glx_texture_t *ptex,
|
glx_render_(session_t *ps, const glx_texture_t *ptex,
|
||||||
int x, int y, int dx, int dy, int width, int height, int z,
|
int x, int y, int dx, int dy, int width, int height, int z,
|
||||||
double opacity, bool neg,
|
double opacity, bool argb, bool neg,
|
||||||
XserverRegion reg_tgt, const reg_data_t *pcache_reg);
|
XserverRegion reg_tgt, const reg_data_t *pcache_reg
|
||||||
|
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
||||||
|
, const glx_prog_main_t *pprogram
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
||||||
|
#define \
|
||||||
|
glx_render(ps, ptex, x, y, dx, dy, width, height, z, opacity, argb, neg, reg_tgt, pcache_reg, pprogram) \
|
||||||
|
glx_render_(ps, ptex, x, y, dx, dy, width, height, z, opacity, argb, neg, reg_tgt, pcache_reg, pprogram)
|
||||||
|
#else
|
||||||
|
#define \
|
||||||
|
glx_render(ps, ptex, x, y, dx, dy, width, height, z, opacity, argb, neg, reg_tgt, pcache_reg, pprogram) \
|
||||||
|
glx_render_(ps, ptex, x, y, dx, dy, width, height, z, opacity, argb, neg, reg_tgt, pcache_reg)
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
glx_swap_copysubbuffermesa(session_t *ps, XserverRegion reg);
|
glx_swap_copysubbuffermesa(session_t *ps, XserverRegion reg);
|
||||||
|
@ -2122,6 +2180,10 @@ glx_create_shader(GLenum shader_type, const char *shader_str);
|
||||||
|
|
||||||
GLuint
|
GLuint
|
||||||
glx_create_program(const GLuint * const shaders, int nshaders);
|
glx_create_program(const GLuint * const shaders, int nshaders);
|
||||||
|
|
||||||
|
GLuint
|
||||||
|
glx_create_program_from_str(const char *vert_shader_str,
|
||||||
|
const char *frag_shader_str);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1206,7 +1206,7 @@ paint_preprocess(session_t *ps, win *list) {
|
||||||
|
|
||||||
// If the window is solid, we add the window region to the
|
// If the window is solid, we add the window region to the
|
||||||
// ignored region
|
// ignored region
|
||||||
if (WMODE_SOLID == w->mode) {
|
if (win_is_solid(ps, w)) {
|
||||||
if (!w->frame_opacity) {
|
if (!w->frame_opacity) {
|
||||||
if (w->border_size)
|
if (w->border_size)
|
||||||
w->reg_ignore = copy_region(ps, w->border_size);
|
w->reg_ignore = copy_region(ps, w->border_size);
|
||||||
|
@ -1240,7 +1240,7 @@ paint_preprocess(session_t *ps, win *list) {
|
||||||
// is not correctly set.
|
// is not correctly set.
|
||||||
if (ps->o.unredir_if_possible && is_highest && to_paint) {
|
if (ps->o.unredir_if_possible && is_highest && to_paint) {
|
||||||
is_highest = false;
|
is_highest = false;
|
||||||
if (WMODE_SOLID == w->mode
|
if (win_is_solid(ps, w)
|
||||||
&& (!w->frame_opacity || !win_has_frame(w))
|
&& (!w->frame_opacity || !win_has_frame(w))
|
||||||
&& win_is_fullscreen(ps, w)
|
&& win_is_fullscreen(ps, w)
|
||||||
&& !w->unredir_if_possible_excluded)
|
&& !w->unredir_if_possible_excluded)
|
||||||
|
@ -1316,7 +1316,7 @@ win_paint_shadow(session_t *ps, win *w,
|
||||||
|
|
||||||
render(ps, 0, 0, w->a.x + w->shadow_dx, w->a.y + w->shadow_dy,
|
render(ps, 0, 0, w->a.x + w->shadow_dx, w->a.y + w->shadow_dy,
|
||||||
w->shadow_width, w->shadow_height, w->shadow_opacity, true, false,
|
w->shadow_width, w->shadow_height, w->shadow_opacity, true, false,
|
||||||
w->shadow_paint.pict, w->shadow_paint.ptex, reg_paint, pcache_reg);
|
w->shadow_paint.pict, w->shadow_paint.ptex, reg_paint, pcache_reg, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1472,7 +1472,7 @@ win_blur_background(session_t *ps, win *w, Picture tgt_buffer,
|
||||||
// Minimize the region we try to blur, if the window itself is not
|
// Minimize the region we try to blur, if the window itself is not
|
||||||
// opaque, only the frame is.
|
// opaque, only the frame is.
|
||||||
XserverRegion reg_noframe = None;
|
XserverRegion reg_noframe = None;
|
||||||
if (WMODE_SOLID == w->mode) {
|
if (win_is_solid(ps, w)) {
|
||||||
XserverRegion reg_all = border_size(ps, w, false);
|
XserverRegion reg_all = border_size(ps, w, false);
|
||||||
reg_noframe = win_get_region_noframe(ps, w, false);
|
reg_noframe = win_get_region_noframe(ps, w, false);
|
||||||
XFixesSubtractRegion(ps->dpy, reg_noframe, reg_all, reg_noframe);
|
XFixesSubtractRegion(ps->dpy, reg_noframe, reg_all, reg_noframe);
|
||||||
|
@ -1496,10 +1496,14 @@ win_blur_background(session_t *ps, win *w, Picture tgt_buffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei,
|
render_(session_t *ps, int x, int y, int dx, int dy, int wid, int hei,
|
||||||
double opacity, bool argb, bool neg,
|
double opacity, bool argb, bool neg,
|
||||||
Picture pict, glx_texture_t *ptex,
|
Picture pict, glx_texture_t *ptex,
|
||||||
XserverRegion reg_paint, const reg_data_t *pcache_reg) {
|
XserverRegion reg_paint, const reg_data_t *pcache_reg
|
||||||
|
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
||||||
|
, const glx_prog_main_t *pprogram
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
switch (ps->o.backend) {
|
switch (ps->o.backend) {
|
||||||
case BKEND_XRENDER:
|
case BKEND_XRENDER:
|
||||||
case BKEND_XR_GLX_HYBRID:
|
case BKEND_XR_GLX_HYBRID:
|
||||||
|
@ -1515,7 +1519,7 @@ render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei,
|
||||||
#ifdef CONFIG_VSYNC_OPENGL
|
#ifdef CONFIG_VSYNC_OPENGL
|
||||||
case BKEND_GLX:
|
case BKEND_GLX:
|
||||||
glx_render(ps, ptex, x, y, dx, dy, wid, hei,
|
glx_render(ps, ptex, x, y, dx, dy, wid, hei,
|
||||||
ps->glx_z, opacity, neg, reg_paint, pcache_reg);
|
ps->glx_z, opacity, argb, neg, reg_paint, pcache_reg, pprogram);
|
||||||
ps->glx_z += 1;
|
ps->glx_z += 1;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1911,7 +1915,7 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t
|
||||||
if (!is_region_empty(ps, reg_paint, &cache_reg)) {
|
if (!is_region_empty(ps, reg_paint, &cache_reg)) {
|
||||||
set_tgt_clip(ps, reg_paint, &cache_reg);
|
set_tgt_clip(ps, reg_paint, &cache_reg);
|
||||||
// Blur window background
|
// Blur window background
|
||||||
if (w->blur_background && (WMODE_SOLID != w->mode
|
if (w->blur_background && (!win_is_solid(ps, w)
|
||||||
|| (ps->o.blur_background_frame && w->frame_opacity))) {
|
|| (ps->o.blur_background_frame && w->frame_opacity))) {
|
||||||
win_blur_background(ps, w, ps->tgt_buffer.pict, reg_paint, &cache_reg);
|
win_blur_background(ps, w, ps->tgt_buffer.pict, reg_paint, &cache_reg);
|
||||||
}
|
}
|
||||||
|
@ -1992,7 +1996,8 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t
|
||||||
glFlush();
|
glFlush();
|
||||||
glXWaitX();
|
glXWaitX();
|
||||||
glx_render(ps, ps->tgt_buffer.ptex, 0, 0, 0, 0,
|
glx_render(ps, ps->tgt_buffer.ptex, 0, 0, 0, 0,
|
||||||
ps->root_width, ps->root_height, 0, 1.0, false, region_real, NULL);
|
ps->root_width, ps->root_height, 0, 1.0, false, false,
|
||||||
|
region_real, NULL, NULL);
|
||||||
// No break here!
|
// No break here!
|
||||||
case BKEND_GLX:
|
case BKEND_GLX:
|
||||||
if (ps->o.glx_use_copysubbuffermesa)
|
if (ps->o.glx_use_copysubbuffermesa)
|
||||||
|
@ -2396,6 +2401,12 @@ win_determine_fade(session_t *ps, win *w) {
|
||||||
w->fade = w->fade_force;
|
w->fade = w->fade_force;
|
||||||
else if (ps->o.no_fading_openclose && w->in_openclose)
|
else if (ps->o.no_fading_openclose && w->in_openclose)
|
||||||
w->fade = false;
|
w->fade = false;
|
||||||
|
else if (ps->o.no_fading_destroyed_argb && w->destroyed
|
||||||
|
&& WMODE_ARGB == w->mode && w->client_win && w->client_win != w->id) {
|
||||||
|
w->fade = false;
|
||||||
|
// Prevent it from being overwritten by last-paint value
|
||||||
|
w->fade_last = false;
|
||||||
|
}
|
||||||
// Ignore other possible causes of fading state changes after window
|
// Ignore other possible causes of fading state changes after window
|
||||||
// gets unmapped
|
// gets unmapped
|
||||||
else if (IsViewable != w->a.map_state) {
|
else if (IsViewable != w->a.map_state) {
|
||||||
|
@ -2548,8 +2559,8 @@ win_set_blur_background(session_t *ps, win *w, bool blur_background_new) {
|
||||||
|
|
||||||
// Only consider window damaged if it's previously painted with background
|
// Only consider window damaged if it's previously painted with background
|
||||||
// blurred
|
// blurred
|
||||||
if ((WMODE_SOLID != w->mode
|
if (!win_is_solid(ps, w)
|
||||||
|| (ps->o.blur_background_frame && w->frame_opacity)))
|
|| (ps->o.blur_background_frame && w->frame_opacity))
|
||||||
add_damage_win(ps, w);
|
add_damage_win(ps, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3206,6 +3217,9 @@ destroy_win(session_t *ps, Window id) {
|
||||||
|
|
||||||
w->destroyed = true;
|
w->destroyed = true;
|
||||||
|
|
||||||
|
if (ps->o.no_fading_destroyed_argb)
|
||||||
|
win_determine_fade(ps, w);
|
||||||
|
|
||||||
// Set fading callback
|
// Set fading callback
|
||||||
set_fade_callback(ps, w, destroy_callback, false);
|
set_fade_callback(ps, w, destroy_callback, false);
|
||||||
|
|
||||||
|
@ -4482,6 +4496,9 @@ usage(int ret) {
|
||||||
" Mark windows that have no WM frame as active.\n"
|
" Mark windows that have no WM frame as active.\n"
|
||||||
"--no-fading-openclose\n"
|
"--no-fading-openclose\n"
|
||||||
" Do not fade on window open/close.\n"
|
" Do not fade on window open/close.\n"
|
||||||
|
"--no-fading-destroyed-argb\n"
|
||||||
|
" Do not fade destroyed ARGB windows with WM frame. Workaround of bugs\n"
|
||||||
|
" in Openbox, Fluxbox, etc.\n"
|
||||||
"--shadow-ignore-shaped\n"
|
"--shadow-ignore-shaped\n"
|
||||||
" Do not paint shadows on shaped windows. (Deprecated, use\n"
|
" Do not paint shadows on shaped windows. (Deprecated, use\n"
|
||||||
" --shadow-exclude \'bounding_shaped\' or\n"
|
" --shadow-exclude \'bounding_shaped\' or\n"
|
||||||
|
@ -4674,6 +4691,12 @@ usage(int ret) {
|
||||||
#else
|
#else
|
||||||
#define WARNING
|
#define WARNING
|
||||||
#endif
|
#endif
|
||||||
|
"--glx-fshader-win shader\n"
|
||||||
|
" GLX backend: Use specified GLSL fragment shader for rendering window\n"
|
||||||
|
" contents.\n"
|
||||||
|
"--force-win-blend\n"
|
||||||
|
" Force all windows to be painted with blending. Useful if you have a\n"
|
||||||
|
" --glx-fshader-win that could turn opaque pixels transparent.\n"
|
||||||
"--dbus\n"
|
"--dbus\n"
|
||||||
" Enable remote control via D-Bus. See the D-BUS API section in the\n"
|
" Enable remote control via D-Bus. See the D-BUS API section in the\n"
|
||||||
" man page for more details." WARNING "\n"
|
" man page for more details." WARNING "\n"
|
||||||
|
@ -5367,6 +5390,9 @@ parse_config(session_t *ps, struct options_tmp *pcfgtmp) {
|
||||||
wintype_arr_enable(ps->o.wintype_fade);
|
wintype_arr_enable(ps->o.wintype_fade);
|
||||||
// --no-fading-open-close
|
// --no-fading-open-close
|
||||||
lcfg_lookup_bool(&cfg, "no-fading-openclose", &ps->o.no_fading_openclose);
|
lcfg_lookup_bool(&cfg, "no-fading-openclose", &ps->o.no_fading_openclose);
|
||||||
|
// --no-fading-destroyed-argb
|
||||||
|
lcfg_lookup_bool(&cfg, "no-fading-destroyed-argb",
|
||||||
|
&ps->o.no_fading_destroyed_argb);
|
||||||
// --shadow-red
|
// --shadow-red
|
||||||
config_lookup_float(&cfg, "shadow-red", &ps->o.shadow_red);
|
config_lookup_float(&cfg, "shadow-red", &ps->o.shadow_red);
|
||||||
// --shadow-green
|
// --shadow-green
|
||||||
|
@ -5583,6 +5609,9 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
|
||||||
{ "xrender-sync", no_argument, NULL, 312 },
|
{ "xrender-sync", no_argument, NULL, 312 },
|
||||||
{ "xrender-sync-fence", no_argument, NULL, 313 },
|
{ "xrender-sync-fence", no_argument, NULL, 313 },
|
||||||
{ "show-all-xerrors", no_argument, NULL, 314 },
|
{ "show-all-xerrors", no_argument, NULL, 314 },
|
||||||
|
{ "no-fading-destroyed-argb", no_argument, NULL, 315 },
|
||||||
|
{ "force-win-blend", no_argument, NULL, 316 },
|
||||||
|
{ "glx-fshader-win", required_argument, NULL, 317 },
|
||||||
// Must terminate with a NULL entry
|
// Must terminate with a NULL entry
|
||||||
{ NULL, 0, NULL, 0 },
|
{ NULL, 0, NULL, 0 },
|
||||||
};
|
};
|
||||||
|
@ -5838,6 +5867,11 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
|
||||||
P_CASEBOOL(311, vsync_use_glfinish);
|
P_CASEBOOL(311, vsync_use_glfinish);
|
||||||
P_CASEBOOL(312, xrender_sync);
|
P_CASEBOOL(312, xrender_sync);
|
||||||
P_CASEBOOL(313, xrender_sync_fence);
|
P_CASEBOOL(313, xrender_sync_fence);
|
||||||
|
P_CASEBOOL(315, no_fading_destroyed_argb);
|
||||||
|
P_CASEBOOL(316, force_win_blend);
|
||||||
|
case 317:
|
||||||
|
ps->o.glx_fshader_win_str = mstrcpy(optarg);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
usage(1);
|
usage(1);
|
||||||
break;
|
break;
|
||||||
|
@ -6776,6 +6810,9 @@ session_init(session_t *ps_old, int argc, char **argv) {
|
||||||
.backend = BKEND_XRENDER,
|
.backend = BKEND_XRENDER,
|
||||||
.glx_no_stencil = false,
|
.glx_no_stencil = false,
|
||||||
.glx_copy_from_front = false,
|
.glx_copy_from_front = false,
|
||||||
|
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
||||||
|
.glx_prog_win = GLX_PROG_MAIN_INIT,
|
||||||
|
#endif
|
||||||
.mark_wmwin_focused = false,
|
.mark_wmwin_focused = false,
|
||||||
.mark_ovredir_focused = false,
|
.mark_ovredir_focused = false,
|
||||||
.fork_after_register = false,
|
.fork_after_register = false,
|
||||||
|
@ -6818,6 +6855,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
|
||||||
.fade_out_step = 0.03 * OPAQUE,
|
.fade_out_step = 0.03 * OPAQUE,
|
||||||
.fade_delta = 10,
|
.fade_delta = 10,
|
||||||
.no_fading_openclose = false,
|
.no_fading_openclose = false,
|
||||||
|
.no_fading_destroyed_argb = false,
|
||||||
.fade_blacklist = NULL,
|
.fade_blacklist = NULL,
|
||||||
|
|
||||||
.wintype_opacity = { 0.0 },
|
.wintype_opacity = { 0.0 },
|
||||||
|
@ -7146,6 +7184,17 @@ session_init(session_t *ps_old, int argc, char **argv) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize window GL shader
|
||||||
|
if (BKEND_GLX == ps->o.backend && ps->o.glx_fshader_win_str) {
|
||||||
|
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
||||||
|
if (!glx_load_prog_main(ps, NULL, ps->o.glx_fshader_win_str, &ps->o.glx_prog_win))
|
||||||
|
exit(1);
|
||||||
|
#else
|
||||||
|
printf_errf("(): GLSL supported not compiled in, can't load shader.");
|
||||||
|
exit(1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize software optimization
|
// Initialize software optimization
|
||||||
if (ps->o.sw_opti)
|
if (ps->o.sw_opti)
|
||||||
ps->o.sw_opti = swopti_init(ps);
|
ps->o.sw_opti = swopti_init(ps);
|
||||||
|
@ -7227,7 +7276,6 @@ session_init(session_t *ps_old, int argc, char **argv) {
|
||||||
cxfree(children);
|
cxfree(children);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (ps->o.track_focus) {
|
if (ps->o.track_focus) {
|
||||||
recheck_focus(ps);
|
recheck_focus(ps);
|
||||||
}
|
}
|
||||||
|
@ -7395,6 +7443,7 @@ session_destroy(session_t *ps) {
|
||||||
free(ps->pfds_read);
|
free(ps->pfds_read);
|
||||||
free(ps->pfds_write);
|
free(ps->pfds_write);
|
||||||
free(ps->pfds_except);
|
free(ps->pfds_except);
|
||||||
|
free(ps->o.glx_fshader_win_str);
|
||||||
free_xinerama_info(ps);
|
free_xinerama_info(ps);
|
||||||
|
|
||||||
#ifdef CONFIG_VSYNC_OPENGL
|
#ifdef CONFIG_VSYNC_OPENGL
|
||||||
|
|
|
@ -675,20 +675,37 @@ static win *
|
||||||
paint_preprocess(session_t *ps, win *list);
|
paint_preprocess(session_t *ps, win *list);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei,
|
render_(session_t *ps, int x, int y, int dx, int dy, int wid, int hei,
|
||||||
double opacity, bool argb, bool neg,
|
double opacity, bool argb, bool neg,
|
||||||
Picture pict, glx_texture_t *ptex,
|
Picture pict, glx_texture_t *ptex,
|
||||||
XserverRegion reg_paint, const reg_data_t *pcache_reg);
|
XserverRegion reg_paint, const reg_data_t *pcache_reg
|
||||||
|
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
||||||
|
, const glx_prog_main_t *pprogram
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
||||||
|
#define \
|
||||||
|
render(ps, x, y, dx, dy, wid, hei, opacity, argb, neg, pict, ptex, reg_paint, pcache_reg, pprogram) \
|
||||||
|
render_(ps, x, y, dx, dy, wid, hei, opacity, argb, neg, pict, ptex, reg_paint, pcache_reg, pprogram)
|
||||||
|
#else
|
||||||
|
#define \
|
||||||
|
render(ps, x, y, dx, dy, wid, hei, opacity, argb, neg, pict, ptex, reg_paint, pcache_reg, pprogram) \
|
||||||
|
render_(ps, x, y, dx, dy, wid, hei, opacity, argb, neg, pict, ptex, reg_paint, pcache_reg)
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
win_render(session_t *ps, win *w, int x, int y, int wid, int hei, double opacity, XserverRegion reg_paint, const reg_data_t *pcache_reg, Picture pict) {
|
win_render(session_t *ps, win *w, int x, int y, int wid, int hei,
|
||||||
|
double opacity, XserverRegion reg_paint, const reg_data_t *pcache_reg,
|
||||||
|
Picture pict) {
|
||||||
const int dx = (w ? w->a.x: 0) + x;
|
const int dx = (w ? w->a.x: 0) + x;
|
||||||
const int dy = (w ? w->a.y: 0) + y;
|
const int dy = (w ? w->a.y: 0) + y;
|
||||||
const bool argb = (w && w->mode == WMODE_ARGB);
|
const bool argb = (w && (WMODE_ARGB == w->mode || ps->o.force_win_blend));
|
||||||
const bool neg = (w && w->invert_color);
|
const bool neg = (w && w->invert_color);
|
||||||
|
|
||||||
render(ps, x, y, dx, dy, wid, hei, opacity, argb, neg,
|
render(ps, x, y, dx, dy, wid, hei, opacity, argb, neg,
|
||||||
pict, (w ? w->paint.ptex: ps->root_tile_paint.ptex), reg_paint, pcache_reg);
|
pict, (w ? w->paint.ptex: ps->root_tile_paint.ptex),
|
||||||
|
reg_paint, pcache_reg, (w ? &ps->o.glx_prog_win: NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
|
135
src/opengl.c
135
src/opengl.c
|
@ -259,6 +259,23 @@ glx_init_end:
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
||||||
|
|
||||||
|
static void
|
||||||
|
glx_free_prog_main(session_t *ps, glx_prog_main_t *pprogram) {
|
||||||
|
if (!pprogram)
|
||||||
|
return;
|
||||||
|
if (pprogram->prog) {
|
||||||
|
glDeleteProgram(pprogram->prog);
|
||||||
|
pprogram->prog = 0;
|
||||||
|
}
|
||||||
|
pprogram->unifm_opacity = -1;
|
||||||
|
pprogram->unifm_invert_color = -1;
|
||||||
|
pprogram->unifm_tex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy GLX related resources.
|
* Destroy GLX related resources.
|
||||||
*/
|
*/
|
||||||
|
@ -273,6 +290,10 @@ glx_destroy(session_t *ps) {
|
||||||
if (ppass->prog)
|
if (ppass->prog)
|
||||||
glDeleteProgram(ppass->prog);
|
glDeleteProgram(ppass->prog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glx_free_prog_main(ps, &ps->o.glx_prog_win);
|
||||||
|
|
||||||
|
glx_check_err(ps);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Free FBConfigs
|
// Free FBConfigs
|
||||||
|
@ -439,6 +460,7 @@ glx_init_blur(session_t *ps) {
|
||||||
P_GET_UNIFM_LOC("offset_x", unifm_offset_x);
|
P_GET_UNIFM_LOC("offset_x", unifm_offset_x);
|
||||||
P_GET_UNIFM_LOC("offset_y", unifm_offset_y);
|
P_GET_UNIFM_LOC("offset_y", unifm_offset_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef P_GET_UNIFM_LOC
|
#undef P_GET_UNIFM_LOC
|
||||||
}
|
}
|
||||||
free(extension);
|
free(extension);
|
||||||
|
@ -458,6 +480,43 @@ glx_init_blur(session_t *ps) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a GLSL main program from shader strings.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
glx_load_prog_main(session_t *ps,
|
||||||
|
const char *vshader_str, const char *fshader_str,
|
||||||
|
glx_prog_main_t *pprogram) {
|
||||||
|
assert(pprogram);
|
||||||
|
|
||||||
|
// Build program
|
||||||
|
pprogram->prog = glx_create_program_from_str(vshader_str, fshader_str);
|
||||||
|
if (!pprogram->prog) {
|
||||||
|
printf_errf("(): Failed to create GLSL program.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get uniform addresses
|
||||||
|
#define P_GET_UNIFM_LOC(name, target) { \
|
||||||
|
pprogram->target = glGetUniformLocation(pprogram->prog, name); \
|
||||||
|
if (pprogram->target < 0) { \
|
||||||
|
printf_errf("(): Failed to get location of uniform '" name "'. Might be troublesome."); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
P_GET_UNIFM_LOC("opacity", unifm_opacity);
|
||||||
|
P_GET_UNIFM_LOC("invert_color", unifm_invert_color);
|
||||||
|
P_GET_UNIFM_LOC("tex", unifm_tex);
|
||||||
|
#undef P_GET_UNIFM_LOC
|
||||||
|
|
||||||
|
glx_check_err(ps);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Update the FBConfig of given depth.
|
* @brief Update the FBConfig of given depth.
|
||||||
*/
|
*/
|
||||||
|
@ -1314,10 +1373,14 @@ glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
||||||
* @brief Render a region with texture data.
|
* @brief Render a region with texture data.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
glx_render(session_t *ps, const glx_texture_t *ptex,
|
glx_render_(session_t *ps, const glx_texture_t *ptex,
|
||||||
int x, int y, int dx, int dy, int width, int height, int z,
|
int x, int y, int dx, int dy, int width, int height, int z,
|
||||||
double opacity, bool neg,
|
double opacity, bool argb, bool neg,
|
||||||
XserverRegion reg_tgt, const reg_data_t *pcache_reg) {
|
XserverRegion reg_tgt, const reg_data_t *pcache_reg
|
||||||
|
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
||||||
|
, const glx_prog_main_t *pprogram
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
if (!ptex || !ptex->texture) {
|
if (!ptex || !ptex->texture) {
|
||||||
printf_errf("(): Missing texture.");
|
printf_errf("(): Missing texture.");
|
||||||
return false;
|
return false;
|
||||||
|
@ -1328,8 +1391,11 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const bool argb = (GLX_TEXTURE_FORMAT_RGBA_EXT ==
|
argb = argb || (GLX_TEXTURE_FORMAT_RGBA_EXT ==
|
||||||
ps->glx_fbconfigs[ptex->depth]->texture_fmt);
|
ps->glx_fbconfigs[ptex->depth]->texture_fmt);
|
||||||
|
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
||||||
|
const bool has_prog = pprogram && pprogram->prog;
|
||||||
|
#endif
|
||||||
bool dual_texture = false;
|
bool dual_texture = false;
|
||||||
|
|
||||||
// It's required by legacy versions of OpenGL to enable texture target
|
// It's required by legacy versions of OpenGL to enable texture target
|
||||||
|
@ -1350,6 +1416,11 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
|
||||||
glColor4f(opacity, opacity, opacity, opacity);
|
glColor4f(opacity, opacity, opacity, opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
||||||
|
if (!has_prog)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
// The default, fixed-function path
|
||||||
// Color negation
|
// Color negation
|
||||||
if (neg) {
|
if (neg) {
|
||||||
// Simple color negation
|
// Simple color negation
|
||||||
|
@ -1421,6 +1492,20 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
||||||
|
else {
|
||||||
|
// Programmable path
|
||||||
|
assert(pprogram->prog);
|
||||||
|
glUseProgram(pprogram->prog);
|
||||||
|
if (pprogram->unifm_opacity >= 0)
|
||||||
|
glUniform1f(pprogram->unifm_opacity, opacity);
|
||||||
|
if (pprogram->unifm_invert_color >= 0)
|
||||||
|
glUniform1i(pprogram->unifm_invert_color, neg);
|
||||||
|
if (pprogram->unifm_tex >= 0)
|
||||||
|
glUniform1i(pprogram->unifm_tex, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG_GLX
|
#ifdef DEBUG_GLX
|
||||||
printf_dbgf("(): Draw: %d, %d, %d, %d -> %d, %d (%d, %d) z %d\n", x, y, width, height, dx, dy, ptex->width, ptex->height, z);
|
printf_dbgf("(): Draw: %d, %d, %d, %d -> %d, %d (%d, %d) z %d\n", x, y, width, height, dx, dy, ptex->width, ptex->height, z);
|
||||||
|
@ -1503,6 +1588,11 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_VSYNC_OPENGL_GLSL
|
||||||
|
if (has_prog)
|
||||||
|
glUseProgram(0);
|
||||||
|
#endif
|
||||||
|
|
||||||
glx_check_err(ps);
|
glx_check_err(ps);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1625,7 +1715,7 @@ glx_create_shader(GLenum shader_type, const char *shader_str) {
|
||||||
bool success = false;
|
bool success = false;
|
||||||
GLuint shader = glCreateShader(shader_type);
|
GLuint shader = glCreateShader(shader_type);
|
||||||
if (!shader) {
|
if (!shader) {
|
||||||
printf_errf("(): Failed to create shader with type %d.", shader_type);
|
printf_errf("(): Failed to create shader with type %#x.", shader_type);
|
||||||
goto glx_create_shader_end;
|
goto glx_create_shader_end;
|
||||||
}
|
}
|
||||||
glShaderSource(shader, 1, &shader_str, NULL);
|
glShaderSource(shader, 1, &shader_str, NULL);
|
||||||
|
@ -1701,5 +1791,40 @@ glx_create_program_end:
|
||||||
|
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a program from vertex and fragment shader strings.
|
||||||
|
*/
|
||||||
|
GLuint
|
||||||
|
glx_create_program_from_str(const char *vert_shader_str,
|
||||||
|
const char *frag_shader_str) {
|
||||||
|
GLuint vert_shader = 0;
|
||||||
|
GLuint frag_shader = 0;
|
||||||
|
GLuint prog = 0;
|
||||||
|
|
||||||
|
if (vert_shader_str)
|
||||||
|
vert_shader = glx_create_shader(GL_VERTEX_SHADER, vert_shader_str);
|
||||||
|
if (frag_shader_str)
|
||||||
|
frag_shader = glx_create_shader(GL_FRAGMENT_SHADER, frag_shader_str);
|
||||||
|
|
||||||
|
{
|
||||||
|
GLuint shaders[2];
|
||||||
|
int count = 0;
|
||||||
|
if (vert_shader)
|
||||||
|
shaders[count++] = vert_shader;
|
||||||
|
if (frag_shader)
|
||||||
|
shaders[count++] = frag_shader;
|
||||||
|
assert(count <= sizeof(shaders) / sizeof(shaders[0]));
|
||||||
|
if (count)
|
||||||
|
prog = glx_create_program(shaders, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vert_shader)
|
||||||
|
glDeleteShader(vert_shader);
|
||||||
|
if (frag_shader)
|
||||||
|
glDeleteShader(frag_shader);
|
||||||
|
|
||||||
|
return prog;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue