mirror of https://github.com/yshui/picom.git
Merge pull request #761 from yshui/new-backend-rounded-corner-2
Rounded border for new glx backend
This commit is contained in:
commit
43f35601bc
|
@ -342,6 +342,18 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
|||
ps->backend_data->ops->set_image_property(
|
||||
ps->backend_data, IMAGE_PROPERTY_CORNER_RADIUS, w->win_image,
|
||||
(double[]){w->corner_radius});
|
||||
if (w->corner_radius) {
|
||||
int border_width = w->g.border_width;
|
||||
if (border_width == 0) {
|
||||
// Some WM has borders implemented as WM frames
|
||||
border_width = min3(w->frame_extents.left,
|
||||
w->frame_extents.right,
|
||||
w->frame_extents.bottom);
|
||||
}
|
||||
ps->backend_data->ops->set_image_property(
|
||||
ps->backend_data, IMAGE_PROPERTY_BORDER_WIDTH,
|
||||
w->win_image, &border_width);
|
||||
}
|
||||
}
|
||||
|
||||
if (w->opacity * MAX_ALPHA < 1) {
|
||||
|
|
|
@ -58,6 +58,9 @@ enum image_properties {
|
|||
// Gives the image a rounded corner.
|
||||
// 1 double, default: 0
|
||||
IMAGE_PROPERTY_CORNER_RADIUS,
|
||||
// Border width
|
||||
// 1 int, default: 0
|
||||
IMAGE_PROPERTY_BORDER_WIDTH,
|
||||
};
|
||||
|
||||
enum image_operations {
|
||||
|
@ -245,20 +248,6 @@ struct backend_operations {
|
|||
bool (*image_op)(backend_t *backend_data, enum image_operations op, void *image_data,
|
||||
const region_t *reg_op, const region_t *reg_visible, void *args);
|
||||
|
||||
/**
|
||||
* Read the color of the pixel at given position of the given image. Image
|
||||
* properties have no effect.
|
||||
*
|
||||
* @param backend_data backend_data
|
||||
* @param image_data an image data structure previously returned by the
|
||||
* backend. the image to read pixel from.
|
||||
* @param x, y coordinate of the pixel to read
|
||||
* @param[out] color the color of the pixel
|
||||
* @return whether the operation is successful
|
||||
*/
|
||||
bool (*read_pixel)(backend_t *backend_data, void *image_data, int x, int y,
|
||||
struct color *output);
|
||||
|
||||
/// Create another instance of the `image_data`. All `image_op` and
|
||||
/// `set_image_property` calls on the returned image should not affect the
|
||||
/// original image
|
||||
|
|
|
@ -451,6 +451,7 @@ bool default_set_image_property(backend_t *base attr_unused, enum image_properti
|
|||
break;
|
||||
case IMAGE_PROPERTY_CORNER_RADIUS: tex->corner_radius = dargs[0]; break;
|
||||
case IMAGE_PROPERTY_MAX_BRIGHTNESS: tex->max_brightness = dargs[0]; break;
|
||||
case IMAGE_PROPERTY_BORDER_WIDTH: tex->border_width = *(int *)arg; break;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -41,6 +41,7 @@ struct backend_image {
|
|||
// Effective size of the image
|
||||
int ewidth, eheight;
|
||||
bool color_inverted;
|
||||
int border_width;
|
||||
};
|
||||
|
||||
bool build_shadow(xcb_connection_t *, xcb_drawable_t, double opacity, int width,
|
||||
|
|
|
@ -57,16 +57,6 @@ struct gl_blur_context {
|
|||
int npasses;
|
||||
};
|
||||
|
||||
static GLint glGetUniformLocationChecked(GLuint p, const char *name) {
|
||||
auto ret = glGetUniformLocation(p, name);
|
||||
if (ret < 0) {
|
||||
log_info("Failed to get location of uniform '%s'. This is normal when "
|
||||
"using custom shaders.",
|
||||
name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
GLuint gl_create_shader(GLenum shader_type, const char *shader_str) {
|
||||
log_trace("===\n%s\n===", shader_str);
|
||||
|
||||
|
@ -383,26 +373,29 @@ static void _gl_compose(backend_t *base, struct backend_image *img, GLuint targe
|
|||
|
||||
assert(gd->win_shader.prog);
|
||||
glUseProgram(gd->win_shader.prog);
|
||||
if (gd->win_shader.unifm_opacity >= 0) {
|
||||
glUniform1f(gd->win_shader.unifm_opacity, (float)img->opacity);
|
||||
if (gd->win_shader.uniform_opacity >= 0) {
|
||||
glUniform1f(gd->win_shader.uniform_opacity, (float)img->opacity);
|
||||
}
|
||||
if (gd->win_shader.unifm_invert_color >= 0) {
|
||||
glUniform1i(gd->win_shader.unifm_invert_color, img->color_inverted);
|
||||
if (gd->win_shader.uniform_invert_color >= 0) {
|
||||
glUniform1i(gd->win_shader.uniform_invert_color, img->color_inverted);
|
||||
}
|
||||
if (gd->win_shader.unifm_tex >= 0) {
|
||||
glUniform1i(gd->win_shader.unifm_tex, 0);
|
||||
if (gd->win_shader.uniform_tex >= 0) {
|
||||
glUniform1i(gd->win_shader.uniform_tex, 0);
|
||||
}
|
||||
if (gd->win_shader.unifm_dim >= 0) {
|
||||
glUniform1f(gd->win_shader.unifm_dim, (float)img->dim);
|
||||
if (gd->win_shader.uniform_dim >= 0) {
|
||||
glUniform1f(gd->win_shader.uniform_dim, (float)img->dim);
|
||||
}
|
||||
if (gd->win_shader.unifm_brightness >= 0) {
|
||||
glUniform1i(gd->win_shader.unifm_brightness, 1);
|
||||
if (gd->win_shader.uniform_brightness >= 0) {
|
||||
glUniform1i(gd->win_shader.uniform_brightness, 1);
|
||||
}
|
||||
if (gd->win_shader.unifm_max_brightness >= 0) {
|
||||
glUniform1f(gd->win_shader.unifm_max_brightness, (float)img->max_brightness);
|
||||
if (gd->win_shader.uniform_max_brightness >= 0) {
|
||||
glUniform1f(gd->win_shader.uniform_max_brightness, (float)img->max_brightness);
|
||||
}
|
||||
if (gd->win_shader.unifm_corner_radius >= 0) {
|
||||
glUniform1f(gd->win_shader.unifm_corner_radius, (float)img->corner_radius);
|
||||
if (gd->win_shader.uniform_corner_radius >= 0) {
|
||||
glUniform1f(gd->win_shader.uniform_corner_radius, (float)img->corner_radius);
|
||||
}
|
||||
if (gd->win_shader.uniform_border_width >= 0) {
|
||||
glUniform1f(gd->win_shader.uniform_border_width, (float)img->border_width);
|
||||
}
|
||||
|
||||
// log_trace("Draw: %d, %d, %d, %d -> %d, %d (%d, %d) z %d\n",
|
||||
|
@ -586,7 +579,7 @@ bool gl_kernel_blur(backend_t *base, double opacity, void *ctx, const rect_t *ex
|
|||
|
||||
glBindTexture(GL_TEXTURE_2D, src_texture);
|
||||
glUseProgram(p->prog);
|
||||
glUniform2f(p->unifm_pixel_norm, 1.0f / (GLfloat)tex_width,
|
||||
glUniform2f(p->uniform_pixel_norm, 1.0f / (GLfloat)tex_width,
|
||||
1.0f / (GLfloat)tex_height);
|
||||
|
||||
// The number of indices in the selected vertex array
|
||||
|
@ -608,7 +601,7 @@ bool gl_kernel_blur(backend_t *base, double opacity, void *ctx, const rect_t *ex
|
|||
return false;
|
||||
}
|
||||
|
||||
glUniform1f(p->unifm_opacity, 1.0);
|
||||
glUniform1f(p->uniform_opacity, 1.0);
|
||||
} else {
|
||||
// last pass, draw directly into the back buffer, with origin
|
||||
// regions
|
||||
|
@ -616,7 +609,7 @@ bool gl_kernel_blur(backend_t *base, double opacity, void *ctx, const rect_t *ex
|
|||
nelems = vao_nelems[0];
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gd->back_fbo);
|
||||
|
||||
glUniform1f(p->unifm_opacity, (float)opacity);
|
||||
glUniform1f(p->uniform_opacity, (float)opacity);
|
||||
}
|
||||
|
||||
glUniform2f(p->texorig_loc, (GLfloat)texorig_x, (GLfloat)texorig_y);
|
||||
|
@ -679,7 +672,7 @@ bool gl_dual_kawase_blur(backend_t *base, double opacity, void *ctx, const rect_
|
|||
|
||||
glUniform1f(down_pass->scale_loc, (GLfloat)scale_factor);
|
||||
|
||||
glUniform2f(down_pass->unifm_pixel_norm, 1.0f / (GLfloat)tex_width,
|
||||
glUniform2f(down_pass->uniform_pixel_norm, 1.0f / (GLfloat)tex_width,
|
||||
1.0f / (GLfloat)tex_height);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, nelems, GL_UNSIGNED_INT, NULL);
|
||||
|
@ -717,18 +710,18 @@ bool gl_dual_kawase_blur(backend_t *base, double opacity, void *ctx, const rect_
|
|||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, bctx->blur_fbos[i - 1]);
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
|
||||
glUniform1f(up_pass->unifm_opacity, (GLfloat)1);
|
||||
glUniform1f(up_pass->uniform_opacity, (GLfloat)1);
|
||||
} else {
|
||||
// last pass, draw directly into the back buffer
|
||||
glBindVertexArray(vao[0]);
|
||||
nelems = vao_nelems[0];
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gd->back_fbo);
|
||||
|
||||
glUniform1f(up_pass->unifm_opacity, (GLfloat)opacity);
|
||||
glUniform1f(up_pass->uniform_opacity, (GLfloat)opacity);
|
||||
}
|
||||
|
||||
glUniform1f(up_pass->scale_loc, (GLfloat)scale_factor);
|
||||
glUniform2f(up_pass->unifm_pixel_norm, 1.0f / (GLfloat)tex_width,
|
||||
glUniform2f(up_pass->uniform_pixel_norm, 1.0f / (GLfloat)tex_width,
|
||||
1.0f / (GLfloat)tex_height);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, nelems, GL_UNSIGNED_INT, NULL);
|
||||
|
@ -896,15 +889,14 @@ static int gl_win_shader_from_string(const char *vshader_str, const char *fshade
|
|||
}
|
||||
|
||||
// Get uniform addresses
|
||||
ret->unifm_opacity = glGetUniformLocationChecked(ret->prog, "opacity");
|
||||
ret->unifm_invert_color = glGetUniformLocationChecked(ret->prog, "invert_color");
|
||||
ret->unifm_tex = glGetUniformLocationChecked(ret->prog, "tex");
|
||||
ret->unifm_dim = glGetUniformLocationChecked(ret->prog, "dim");
|
||||
ret->unifm_brightness = glGetUniformLocationChecked(ret->prog, "brightness");
|
||||
ret->unifm_max_brightness =
|
||||
glGetUniformLocationChecked(ret->prog, "max_brightness");
|
||||
ret->unifm_corner_radius =
|
||||
glGetUniformLocationChecked(ret->prog, "corner_radius");
|
||||
bind_uniform(ret, opacity);
|
||||
bind_uniform(ret, invert_color);
|
||||
bind_uniform(ret, tex);
|
||||
bind_uniform(ret, dim);
|
||||
bind_uniform(ret, brightness);
|
||||
bind_uniform(ret, max_brightness);
|
||||
bind_uniform(ret, corner_radius);
|
||||
bind_uniform(ret, border_width);
|
||||
|
||||
gl_check_err();
|
||||
|
||||
|
@ -1251,9 +1243,8 @@ bool gl_create_kernel_blur_context(void *blur_context, GLfloat *projection,
|
|||
glBindFragDataLocation(pass->prog, 0, "out_color");
|
||||
|
||||
// Get uniform addresses
|
||||
pass->unifm_pixel_norm =
|
||||
glGetUniformLocationChecked(pass->prog, "pixel_norm");
|
||||
pass->unifm_opacity = glGetUniformLocationChecked(pass->prog, "opacity");
|
||||
bind_uniform(pass, pixel_norm);
|
||||
bind_uniform(pass, opacity);
|
||||
pass->texorig_loc = glGetUniformLocationChecked(pass->prog, "texorig");
|
||||
|
||||
// Setup projection matrix
|
||||
|
@ -1271,8 +1262,8 @@ bool gl_create_kernel_blur_context(void *blur_context, GLfloat *projection,
|
|||
// the single pass case
|
||||
auto pass = &ctx->blur_shader[1];
|
||||
pass->prog = gl_create_program_from_str(vertex_shader, dummy_frag);
|
||||
pass->unifm_pixel_norm = -1;
|
||||
pass->unifm_opacity = -1;
|
||||
pass->uniform_pixel_norm = -1;
|
||||
pass->uniform_opacity = -1;
|
||||
pass->texorig_loc = glGetUniformLocationChecked(pass->prog, "texorig");
|
||||
|
||||
// Setup projection matrix
|
||||
|
@ -1371,8 +1362,7 @@ bool gl_create_dual_kawase_blur_context(void *blur_context, GLfloat *projection,
|
|||
glBindFragDataLocation(down_pass->prog, 0, "out_color");
|
||||
|
||||
// Get uniform addresses
|
||||
down_pass->unifm_pixel_norm =
|
||||
glGetUniformLocationChecked(down_pass->prog, "pixel_norm");
|
||||
bind_uniform(down_pass, pixel_norm);
|
||||
down_pass->texorig_loc =
|
||||
glGetUniformLocationChecked(down_pass->prog, "texorig");
|
||||
down_pass->scale_loc =
|
||||
|
@ -1432,10 +1422,8 @@ bool gl_create_dual_kawase_blur_context(void *blur_context, GLfloat *projection,
|
|||
glBindFragDataLocation(up_pass->prog, 0, "out_color");
|
||||
|
||||
// Get uniform addresses
|
||||
up_pass->unifm_pixel_norm =
|
||||
glGetUniformLocationChecked(up_pass->prog, "pixel_norm");
|
||||
up_pass->unifm_opacity =
|
||||
glGetUniformLocationChecked(up_pass->prog, "opacity");
|
||||
bind_uniform(up_pass, pixel_norm);
|
||||
bind_uniform(up_pass, opacity);
|
||||
up_pass->texorig_loc =
|
||||
glGetUniformLocationChecked(up_pass->prog, "texorig");
|
||||
up_pass->scale_loc = glGetUniformLocationChecked(up_pass->prog, "scale");
|
||||
|
@ -1540,6 +1528,7 @@ const char *win_shader_glsl = GLSL(330,
|
|||
uniform float opacity;
|
||||
uniform float dim;
|
||||
uniform float corner_radius;
|
||||
uniform float border_width;
|
||||
uniform bool invert_color;
|
||||
in vec2 texcoord;
|
||||
uniform sampler2D tex;
|
||||
|
@ -1554,6 +1543,7 @@ const char *win_shader_glsl = GLSL(330,
|
|||
|
||||
void main() {
|
||||
vec4 c = texelFetch(tex, ivec2(texcoord), 0);
|
||||
vec4 border_color = texture(tex, vec2(0.0, 0.5));
|
||||
if (invert_color) {
|
||||
c = vec4(c.aaa - c.rgb, c.a);
|
||||
}
|
||||
|
@ -1571,7 +1561,12 @@ const char *win_shader_glsl = GLSL(330,
|
|||
vec2 inner_size = outer_size - vec2(corner_radius) * 2.0f;
|
||||
float rect_distance = rectangle_sdf(texcoord - outer_size / 2.0f,
|
||||
inner_size / 2.0f) - corner_radius;
|
||||
c *= 1.0f - clamp(rect_distance, 0.0f, 1.0f);
|
||||
if (rect_distance > 0.0f) {
|
||||
c = (1.0f - clamp(rect_distance, 0.0f, 1.0f)) * border_color;
|
||||
} else {
|
||||
float factor = clamp(rect_distance + border_width, 0.0f, 1.0f);
|
||||
c = (1.0f - factor) * c + factor * border_color;
|
||||
}
|
||||
|
||||
gl_FragColor = c;
|
||||
}
|
||||
|
@ -1913,20 +1908,3 @@ bool gl_image_op(backend_t *base, enum image_operations op, void *image_data,
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gl_read_pixel(backend_t *base attr_unused, void *image_data, int x, int y,
|
||||
struct color *output) {
|
||||
struct backend_image *tex = image_data;
|
||||
auto inner = (struct gl_texture *)tex->inner;
|
||||
GLfloat color[4];
|
||||
glReadPixels(x, inner->y_inverted ? inner->height - y : y, 1, 1, GL_RGBA,
|
||||
GL_FLOAT, color);
|
||||
output->alpha = color[3];
|
||||
output->red = color[0];
|
||||
output->green = color[1];
|
||||
output->blue = color[2];
|
||||
|
||||
bool ret = glGetError() == GL_NO_ERROR;
|
||||
gl_clear_err();
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -13,16 +13,30 @@
|
|||
#define CASESTRRET(s) \
|
||||
case s: return #s
|
||||
|
||||
static inline GLint glGetUniformLocationChecked(GLuint p, const char *name) {
|
||||
auto ret = glGetUniformLocation(p, name);
|
||||
if (ret < 0) {
|
||||
log_info("Failed to get location of uniform '%s'. This is normal when "
|
||||
"using custom shaders.",
|
||||
name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define bind_uniform(shader, uniform) \
|
||||
(shader)->uniform_##uniform = glGetUniformLocationChecked((shader)->prog, #uniform)
|
||||
|
||||
// Program and uniforms for window shader
|
||||
typedef struct {
|
||||
GLuint prog;
|
||||
GLint unifm_opacity;
|
||||
GLint unifm_invert_color;
|
||||
GLint unifm_tex;
|
||||
GLint unifm_dim;
|
||||
GLint unifm_brightness;
|
||||
GLint unifm_max_brightness;
|
||||
GLint unifm_corner_radius;
|
||||
GLint uniform_opacity;
|
||||
GLint uniform_invert_color;
|
||||
GLint uniform_tex;
|
||||
GLint uniform_dim;
|
||||
GLint uniform_brightness;
|
||||
GLint uniform_max_brightness;
|
||||
GLint uniform_corner_radius;
|
||||
GLint uniform_border_width;
|
||||
} gl_win_shader_t;
|
||||
|
||||
// Program and uniforms for brightness shader
|
||||
|
@ -33,8 +47,8 @@ typedef struct {
|
|||
// Program and uniforms for blur shader
|
||||
typedef struct {
|
||||
GLuint prog;
|
||||
GLint unifm_pixel_norm;
|
||||
GLint unifm_opacity;
|
||||
GLint uniform_pixel_norm;
|
||||
GLint uniform_opacity;
|
||||
GLint texorig_loc;
|
||||
GLint scale_loc;
|
||||
} gl_blur_shader_t;
|
||||
|
|
|
@ -530,7 +530,6 @@ struct backend_operations glx_ops = {
|
|||
.compose = gl_compose,
|
||||
.image_op = gl_image_op,
|
||||
.set_image_property = default_set_image_property,
|
||||
.read_pixel = gl_read_pixel,
|
||||
.clone_image = default_clone_image,
|
||||
.blur = gl_blur,
|
||||
.is_image_transparent = default_is_image_transparent,
|
||||
|
|
|
@ -745,30 +745,6 @@ static void get_blur_size(void *blur_context, int *width, int *height) {
|
|||
*height = ctx->resize_height;
|
||||
}
|
||||
|
||||
static bool
|
||||
read_pixel(backend_t *backend_data, void *image_data, int x, int y, struct color *output) {
|
||||
auto xd = (struct _xrender_data *)backend_data;
|
||||
auto img = (struct backend_image *)image_data;
|
||||
auto inner = (struct _xrender_image_data_inner *)img->inner;
|
||||
|
||||
auto r = XCB_AWAIT(xcb_get_image, xd->base.c, XCB_IMAGE_FORMAT_XY_PIXMAP, inner->pixmap,
|
||||
to_i16_checked(x), to_i16_checked(y), 1, 1, (uint32_t)-1L);
|
||||
|
||||
if (!r) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Color format seems to be BGRA8888, see glamor_format_for_pixmap from the
|
||||
// Xserver codebase.
|
||||
uint8_t *pixels = xcb_get_image_data(r);
|
||||
output->blue = pixels[0] / 255.0;
|
||||
output->green = pixels[1] / 255.0;
|
||||
output->red = pixels[2] / 255.0;
|
||||
output->alpha = pixels[3] / 255.0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static backend_t *backend_xrender_init(session_t *ps) {
|
||||
auto xd = ccalloc(1, struct _xrender_data);
|
||||
init_backend_base(&xd->base, ps);
|
||||
|
@ -888,7 +864,6 @@ struct backend_operations xrender_ops = {
|
|||
.max_buffer_age = 2,
|
||||
|
||||
.image_op = image_op,
|
||||
.read_pixel = read_pixel,
|
||||
.clone_image = clone_image,
|
||||
.set_image_property = set_image_property,
|
||||
.create_blur_context = create_blur_context,
|
||||
|
|
|
@ -134,6 +134,7 @@ static inline int attr_const normalize_i_range(int i, int min, int max) {
|
|||
|
||||
#define min2(a, b) ((a) > (b) ? (b) : (a))
|
||||
#define max2(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define min3(a, b, c) min2(a, min2(b, c))
|
||||
|
||||
/// clamp `val` into interval [min, max]
|
||||
#define clamp(val, min, max) max2(min2(val, max), min)
|
||||
|
|
Loading…
Reference in New Issue