mirror of
https://github.com/yshui/picom.git
synced 2024-11-11 13:51:02 -05:00
commit
468d8a0879
5 changed files with 87 additions and 26 deletions
100
src/opengl.c
100
src/opengl.c
|
@ -102,7 +102,9 @@ bool glx_init(session_t *ps, bool need_render) {
|
||||||
ppass->unifm_texcoord = -1;
|
ppass->unifm_texcoord = -1;
|
||||||
ppass->unifm_texsize = -1;
|
ppass->unifm_texsize = -1;
|
||||||
ppass->unifm_borderw = -1;
|
ppass->unifm_borderw = -1;
|
||||||
|
ppass->unifm_borderc = -1;
|
||||||
ppass->unifm_resolution = -1;
|
ppass->unifm_resolution = -1;
|
||||||
|
ppass->unifm_tex_scr = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
glx_session_t *psglx = ps->psglx;
|
glx_session_t *psglx = ps->psglx;
|
||||||
|
@ -448,7 +450,7 @@ bool glx_init_rounded_corners(session_t *ps) {
|
||||||
"%s" // extensions
|
"%s" // extensions
|
||||||
"uniform float u_radius;\n"
|
"uniform float u_radius;\n"
|
||||||
"uniform float u_borderw;\n"
|
"uniform float u_borderw;\n"
|
||||||
"uniform int u_is_focused;\n"
|
"uniform vec4 u_borderc;\n"
|
||||||
"uniform vec2 u_texcoord;\n"
|
"uniform vec2 u_texcoord;\n"
|
||||||
"uniform vec2 u_texsize;\n"
|
"uniform vec2 u_texsize;\n"
|
||||||
"uniform vec2 u_resolution;\n"
|
"uniform vec2 u_resolution;\n"
|
||||||
|
@ -459,23 +461,18 @@ bool glx_init_rounded_corners(session_t *ps) {
|
||||||
" vec2 d = abs(p) - b + vec2(r);\n"
|
" vec2 d = abs(p) - b + vec2(r);\n"
|
||||||
" return min(max(d.x, d.y), 0.0) + length(max(d, 0.0)) - r;\n"
|
" return min(max(d.x, d.y), 0.0) + length(max(d, 0.0)) - r;\n"
|
||||||
"}\n\n"
|
"}\n\n"
|
||||||
"// https://www.shadertoy.com/view/ldfSDj\n"
|
|
||||||
"float udRoundBox( vec2 p, vec2 b, float r )\n"
|
|
||||||
"{\n"
|
|
||||||
" return length(max(abs(p)-b+r,0.0))-r;\n"
|
|
||||||
"}\n\n"
|
|
||||||
"void main()\n"
|
"void main()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" vec2 coord = vec2(u_texcoord.x, "
|
" vec2 coord = vec2(u_texcoord.x, "
|
||||||
"u_resolution.y-u_texsize.y-u_texcoord.y);\n"
|
"u_resolution.y-u_texsize.y-u_texcoord.y);\n"
|
||||||
" vec4 u_v4SrcColor = %s(tex_scr, vec2(gl_TexCoord[0].st));\n"
|
" vec4 u_v4WndBgColor = %s(tex_scr, vec2(gl_TexCoord[0].st));\n"
|
||||||
" float u_fRadiusPx = u_radius;\n"
|
" float u_fRadiusPx = u_radius;\n"
|
||||||
" float u_fHalfBorderThickness = 0.0;\n"
|
" float u_fHalfBorderThickness = u_borderw / 2.0;\n"
|
||||||
" vec4 u_v4BorderColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
|
" vec4 u_v4BorderColor = u_borderc;\n"
|
||||||
" vec4 u_v4FillColor = vec4(0.0, 0.0, 0.0, 0.0);\n"
|
" vec4 u_v4FillColor = vec4(0.0, 0.0, 0.0, 0.0);\n"
|
||||||
" vec4 v4FromColor = u_v4BorderColor; //Always the border "
|
" vec4 v4FromColor = u_v4BorderColor; //Always the border "
|
||||||
"color. If no border, this still should be set\n"
|
"color. If no border, this still should be set\n"
|
||||||
" vec4 v4ToColor = u_v4SrcColor; //Outside color is the "
|
" vec4 v4ToColor = u_v4WndBgColor; //Outside color is the "
|
||||||
"background texture\n"
|
"background texture\n"
|
||||||
"\n"
|
"\n"
|
||||||
" vec2 u_v2HalfShapeSizePx = u_texsize/2.0 - "
|
" vec2 u_v2HalfShapeSizePx = u_texsize/2.0 - "
|
||||||
|
@ -493,7 +490,7 @@ bool glx_init_rounded_corners(session_t *ps) {
|
||||||
" } else {\n"
|
" } else {\n"
|
||||||
" v4FromColor = u_v4FillColor;\n"
|
" v4FromColor = u_v4FillColor;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" float fBlendAmount = clamp(fDist + 0.5, 0.0, 1.0);\n"
|
" float fBlendAmount = smoothstep(-1.0, 1.0, fDist);\n"
|
||||||
" vec4 c = mix(v4FromColor, v4ToColor, fBlendAmount);\n"
|
" vec4 c = mix(v4FromColor, v4ToColor, fBlendAmount);\n"
|
||||||
"\n"
|
"\n"
|
||||||
" // final color\n"
|
" // final color\n"
|
||||||
|
@ -553,8 +550,9 @@ bool glx_init_rounded_corners(session_t *ps) {
|
||||||
P_GET_UNIFM_LOC("u_texcoord", unifm_texcoord);
|
P_GET_UNIFM_LOC("u_texcoord", unifm_texcoord);
|
||||||
P_GET_UNIFM_LOC("u_texsize", unifm_texsize);
|
P_GET_UNIFM_LOC("u_texsize", unifm_texsize);
|
||||||
P_GET_UNIFM_LOC("u_borderw", unifm_borderw);
|
P_GET_UNIFM_LOC("u_borderw", unifm_borderw);
|
||||||
P_GET_UNIFM_LOC("u_is_focused", unifm_is_focused);
|
P_GET_UNIFM_LOC("u_borderc", unifm_borderc);
|
||||||
P_GET_UNIFM_LOC("u_resolution", unifm_resolution);
|
P_GET_UNIFM_LOC("u_resolution", unifm_resolution);
|
||||||
|
P_GET_UNIFM_LOC("tex_scr", unifm_tex_scr);
|
||||||
#undef P_GET_UNIFM_LOC
|
#undef P_GET_UNIFM_LOC
|
||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
|
@ -642,7 +640,7 @@ bool glx_bind_texture(session_t *ps attr_unused, glx_texture_t **pptex, int x, i
|
||||||
|
|
||||||
glx_texture_t *ptex = *pptex;
|
glx_texture_t *ptex = *pptex;
|
||||||
|
|
||||||
// log_trace("Copying xy(%d %d) wh(%d %d)", x, y, width, height);
|
// log_trace("Copying xy(%d %d) wh(%d %d) ptex(%p)", x, y, width, height, ptex);
|
||||||
|
|
||||||
// Release texture if parameters are inconsistent
|
// Release texture if parameters are inconsistent
|
||||||
if (ptex && ptex->texture && (ptex->width != width || ptex->height != height)) {
|
if (ptex && ptex->texture && (ptex->width != width || ptex->height != height)) {
|
||||||
|
@ -1103,9 +1101,56 @@ glx_blur_dst_end:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool glx_round_corners_dst(session_t *ps, struct managed_win *w, const glx_texture_t *ptex,
|
// TODO(bhagwan) this is a mess and needs a more consistent way of getting the border
|
||||||
int dx, int dy, int width, int height, float z, float cr,
|
// pixel I tried looking for a notify event for XCB_CW_BORDER_PIXEL (in
|
||||||
const region_t *reg_tgt attr_unused) {
|
// xcb_create_window()) or a way to get the pixels from xcb_render_picture_t but the
|
||||||
|
// documentation for the xcb_xrender extension is literaly non existent...
|
||||||
|
//
|
||||||
|
// NOTE(yshui) There is no consistent way to get the "border" color of a X window. From
|
||||||
|
// the WM's perspective there are multiple ways to implement window borders. Using
|
||||||
|
// glReadPixel is probably the most reliable way.
|
||||||
|
void glx_read_border_pixel(int root_height, int root_width, int x, int y, int width,
|
||||||
|
int height, float *ppixel) {
|
||||||
|
assert(ppixel);
|
||||||
|
|
||||||
|
// Reset the color so the shader doesn't use it
|
||||||
|
ppixel[0] = ppixel[1] = ppixel[2] = ppixel[3] = -1.0F;
|
||||||
|
|
||||||
|
// First try bottom left corner past the
|
||||||
|
// circle radius (after the rounded corner ends)
|
||||||
|
auto screen_x = x;
|
||||||
|
auto screen_y = root_height - height - y;
|
||||||
|
|
||||||
|
// X is out of bounds
|
||||||
|
// move to the right side
|
||||||
|
if (screen_x < 0) {
|
||||||
|
screen_x += width;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Y is out of bounds
|
||||||
|
// move to to top part
|
||||||
|
if (screen_y < 0) {
|
||||||
|
screen_y += height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All corners are out of bounds, give up
|
||||||
|
if (screen_x < 0 || screen_y < 0 || screen_x >= root_width || screen_y >= root_height) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invert Y-axis so we can query border color from texture (0,0)
|
||||||
|
glReadPixels(screen_x, screen_y, 1, 1, GL_RGBA, GL_FLOAT, (void *)ppixel);
|
||||||
|
|
||||||
|
log_trace("xy(%d, %d), glxy(%d %d) wh(%d %d), border_col(%.2f, %.2f, %.2f, %.2f)",
|
||||||
|
x, y, screen_x, screen_y, width, height, (float)ppixel[0],
|
||||||
|
(float)ppixel[1], (float)ppixel[2], (float)ppixel[3]);
|
||||||
|
|
||||||
|
gl_check_err();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool glx_round_corners_dst(session_t *ps, struct managed_win *w,
|
||||||
|
const glx_texture_t *ptex, int dx, int dy, int width,
|
||||||
|
int height, float z, float cr, const region_t *reg_tgt) {
|
||||||
assert(ps->psglx->round_passes->prog);
|
assert(ps->psglx->round_passes->prog);
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
|
@ -1116,6 +1161,11 @@ bool glx_round_corners_dst(session_t *ps, struct managed_win *w, const glx_textu
|
||||||
int mdx = dx, mdy = dy, mwidth = width, mheight = height;
|
int mdx = dx, mdy = dy, mwidth = width, mheight = height;
|
||||||
log_trace("%d, %d, %d, %d", mdx, mdy, mwidth, mheight);
|
log_trace("%d, %d, %d, %d", mdx, mdy, mwidth, mheight);
|
||||||
|
|
||||||
|
if (w->g.border_width > 0) {
|
||||||
|
glx_read_border_pixel(ps->root_height, ps->root_width, dx, dy, width,
|
||||||
|
height, &w->border_col[0]);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const glx_round_pass_t *ppass = ps->psglx->round_passes;
|
const glx_round_pass_t *ppass = ps->psglx->round_passes;
|
||||||
assert(ppass->prog);
|
assert(ppass->prog);
|
||||||
|
@ -1131,9 +1181,10 @@ bool glx_round_corners_dst(session_t *ps, struct managed_win *w, const glx_textu
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(ptex->target, ptex->texture);
|
glBindTexture(ptex->target, ptex->texture);
|
||||||
GLint loc_sampler = glGetUniformLocation(ppass->prog, "tex_scr");
|
|
||||||
glUniform1i(loc_sampler, (GLint)0);
|
|
||||||
|
|
||||||
|
if (ppass->unifm_tex_scr >= 0) {
|
||||||
|
glUniform1i(ppass->unifm_tex_scr, (GLint)0);
|
||||||
|
}
|
||||||
if (ppass->unifm_radius >= 0) {
|
if (ppass->unifm_radius >= 0) {
|
||||||
glUniform1f(ppass->unifm_radius, cr);
|
glUniform1f(ppass->unifm_radius, cr);
|
||||||
}
|
}
|
||||||
|
@ -1144,10 +1195,13 @@ bool glx_round_corners_dst(session_t *ps, struct managed_win *w, const glx_textu
|
||||||
glUniform2f(ppass->unifm_texsize, (float)mwidth, (float)mheight);
|
glUniform2f(ppass->unifm_texsize, (float)mwidth, (float)mheight);
|
||||||
}
|
}
|
||||||
if (ppass->unifm_borderw >= 0) {
|
if (ppass->unifm_borderw >= 0) {
|
||||||
glUniform1f(ppass->unifm_borderw, w->g.border_width);
|
// Don't render rounded border if we don't know the border color
|
||||||
|
glUniform1f(ppass->unifm_borderw,
|
||||||
|
w->border_col[0] != -1. ? (GLfloat)w->g.border_width : 0);
|
||||||
}
|
}
|
||||||
if (ppass->unifm_is_focused >= 0) {
|
if (ppass->unifm_borderc >= 0) {
|
||||||
glUniform1i(ppass->unifm_is_focused, w->focused);
|
glUniform4f(ppass->unifm_borderc, w->border_col[0],
|
||||||
|
w->border_col[1], w->border_col[2], w->border_col[3]);
|
||||||
}
|
}
|
||||||
if (ppass->unifm_resolution >= 0) {
|
if (ppass->unifm_resolution >= 0) {
|
||||||
glUniform2f(ppass->unifm_resolution, (float)ps->root_width,
|
glUniform2f(ppass->unifm_resolution, (float)ps->root_width,
|
||||||
|
@ -1177,8 +1231,8 @@ bool glx_round_corners_dst(session_t *ps, struct managed_win *w, const glx_textu
|
||||||
|
|
||||||
// Invert Y if needed, this may not work as expected,
|
// Invert Y if needed, this may not work as expected,
|
||||||
// though. I don't have such a FBConfig to test with.
|
// though. I don't have such a FBConfig to test with.
|
||||||
ry = 1.0f - ry;
|
ry = 1.0F - ry;
|
||||||
rye = 1.0f - rye;
|
rye = 1.0F - rye;
|
||||||
|
|
||||||
// log_trace("Rect %d (i:%d): %f, %f, %f, %f -> %f, %f,
|
// log_trace("Rect %d (i:%d): %f, %f, %f, %f -> %f, %f,
|
||||||
// %f, %f", ri ,ptex ? ptex->y_inverted : -1, rx, ry,
|
// %f, %f", ri ,ptex ? ptex->y_inverted : -1, rx, ry,
|
||||||
|
|
|
@ -53,10 +53,13 @@ typedef struct {
|
||||||
GLint unifm_texsize;
|
GLint unifm_texsize;
|
||||||
/// Location of uniform "borderw" in rounded-corners GLSL program.
|
/// Location of uniform "borderw" in rounded-corners GLSL program.
|
||||||
GLint unifm_borderw;
|
GLint unifm_borderw;
|
||||||
/// Location of uniform "is_focused" in rounded-corners GLSL program.
|
/// Location of uniform "borderc" in rounded-corners GLSL program.
|
||||||
GLint unifm_is_focused;
|
GLint unifm_borderc;
|
||||||
/// Location of uniform "resolution" in rounded-corners GLSL program.
|
/// Location of uniform "resolution" in rounded-corners GLSL program.
|
||||||
GLint unifm_resolution;
|
GLint unifm_resolution;
|
||||||
|
/// Location of uniform "texture_scr" in rounded-corners GLSL program.
|
||||||
|
GLint unifm_tex_scr;
|
||||||
|
|
||||||
} glx_round_pass_t;
|
} glx_round_pass_t;
|
||||||
|
|
||||||
/// Structure containing GLX-dependent data for a session.
|
/// Structure containing GLX-dependent data for a session.
|
||||||
|
|
|
@ -1151,7 +1151,7 @@ void paint_all(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
||||||
const auto hei = to_u16_checked(w->heightb);
|
const auto hei = to_u16_checked(w->heightb);
|
||||||
glx_round_corners_dst(ps, w, w->glx_texture_bg, w->g.x,
|
glx_round_corners_dst(ps, w, w->glx_texture_bg, w->g.x,
|
||||||
w->g.y, wid, hei,
|
w->g.y, wid, hei,
|
||||||
(float)ps->psglx->z - 0.5f,
|
(float)ps->psglx->z - 0.5F,
|
||||||
(float)w->corner_radius, ®_tmp);
|
(float)w->corner_radius, ®_tmp);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1085,6 +1085,9 @@ static void win_determine_rounded_corners(session_t *ps, struct managed_win *w)
|
||||||
} else {
|
} else {
|
||||||
w->corner_radius = ps->o.corner_radius;
|
w->corner_radius = ps->o.corner_radius;
|
||||||
log_debug("Rounding corners for window %#010x", w->base.id);
|
log_debug("Rounding corners for window %#010x", w->base.id);
|
||||||
|
// Initialize the border color to an invalid value
|
||||||
|
w->border_col[0] = w->border_col[1] = w->border_col[2] =
|
||||||
|
w->border_col[3] = -1.0F;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -220,6 +220,7 @@ struct managed_win {
|
||||||
|
|
||||||
/// Radius of rounded window corners
|
/// Radius of rounded window corners
|
||||||
int corner_radius;
|
int corner_radius;
|
||||||
|
float border_col[4];
|
||||||
|
|
||||||
// Fading-related members
|
// Fading-related members
|
||||||
/// Override value of window fade state. Set by D-Bus method calls.
|
/// Override value of window fade state. Set by D-Bus method calls.
|
||||||
|
|
Loading…
Reference in a new issue