1
0
Fork 0
mirror of https://github.com/yshui/picom.git synced 2024-11-11 13:51:02 -05:00

legacy glx: extend the border into the corners when they are rounded

Authored-By: bhagwan <bhagwan@disroot.org>
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
bhagwan 2020-04-01 22:56:42 -07:00 committed by Yuxuan Shui
parent 9cb552ecd9
commit d9bfd0192d
No known key found for this signature in database
GPG key ID: D3A4405BE6CC17F4
5 changed files with 79 additions and 24 deletions

View file

@ -102,6 +102,7 @@ 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;
} }
@ -448,7 +449,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 +460,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 +489,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,7 +549,7 @@ 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);
#undef P_GET_UNIFM_LOC #undef P_GET_UNIFM_LOC
@ -642,7 +638,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 +1099,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 +1159,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);
@ -1144,10 +1192,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 +1228,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,

View file

@ -53,8 +53,8 @@ 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;
} glx_round_pass_t; } glx_round_pass_t;

View file

@ -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, &reg_tmp); (float)w->corner_radius, &reg_tmp);
} }
#endif #endif

View file

@ -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;
} }
} }

View file

@ -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.