Add Anti-Aliased Corner Radius (#18)
This commit is contained in:
parent
3b287a73b9
commit
c1f4cf17db
|
@ -2,7 +2,7 @@
|
|||
|
||||
Sway is an incredible window manager, and certainly one of the most well established wayland window managers. However, it is restricted to only include the functionality that existed in i3. This fork ditches the simple wlr_renderer, and replaces it with a fancy GLES2 renderer with functionality borrowed from the original simple renderer and [Hyprland](https://github.com/vaxerski/Hyprland). This, along with a couple of minor changes, expands sway's featureset to include the following:
|
||||
|
||||
+ **Rounded corners**
|
||||
+ **Anti-aliased rounded corners**
|
||||
+ **Scratchpad treated as minimize**: Allows docks, or panels with a taskbar, to correctly interpret minimize / unminimize requests ([thanks to LCBCrion](https://github.com/swaywm/sway/issues/6457))
|
||||
+ **Default to not compiling swaybar**: Many users replace swaybar with the far more capable [waybar](https://github.com/Alexays/Waybar), swayFX cuts out the bloat by not including swaybar by default
|
||||
+ **Add a nix flake to the repo**: Allows nixos users to easily contribute to and test this project
|
||||
|
|
|
@ -8,9 +8,12 @@ struct gles2_tex_shader {
|
|||
GLint proj;
|
||||
GLint tex;
|
||||
GLint alpha;
|
||||
GLint discardOpaque;
|
||||
GLint pos_attrib;
|
||||
GLint tex_attrib;
|
||||
GLint width;
|
||||
GLint height;
|
||||
GLint position;
|
||||
GLint radius;
|
||||
};
|
||||
|
||||
struct fx_renderer {
|
||||
|
@ -42,13 +45,14 @@ void fx_renderer_clear(const float color[static 4]);
|
|||
|
||||
void fx_renderer_scissor(struct wlr_box *box);
|
||||
|
||||
bool fx_render_subtexture_with_matrix(struct fx_renderer *renderer,
|
||||
struct wlr_texture *wlr_texture, const struct wlr_fbox *box,
|
||||
const float matrix[static 9], float alpha, int radius);
|
||||
bool fx_render_subtexture_with_matrix(struct fx_renderer *renderer, struct wlr_texture *wlr_texture,
|
||||
const struct wlr_fbox *src_box, const struct wlr_box *dst_box, const float matrix[static 9],
|
||||
float alpha, int radius);
|
||||
|
||||
bool fx_render_texture_with_matrix(struct fx_renderer *renderer,
|
||||
struct wlr_texture *wlr_texture, const float matrix[static 9], float alpha, int radius);
|
||||
bool fx_render_texture_with_matrix(struct fx_renderer *renderer, struct wlr_texture *wlr_texture,
|
||||
const struct wlr_box *dst_box, const float matrix[static 9], float alpha, int radius);
|
||||
|
||||
void fx_render_rect(struct fx_renderer *renderer, const struct wlr_box *box, const float color[static 4], const float projection[static 9]);
|
||||
void fx_render_rect(struct fx_renderer *renderer, const struct wlr_box *box,
|
||||
const float color[static 4], const float projection[static 9]);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -43,57 +43,19 @@ const GLchar tex_fragment_src_rgba[] =
|
|||
"uniform sampler2D tex;\n"
|
||||
"uniform float alpha;\n"
|
||||
"\n"
|
||||
"uniform vec2 topLeft;\n"
|
||||
"uniform vec2 bottomRight;\n"
|
||||
"uniform vec2 fullSize;\n"
|
||||
"uniform float width;\n"
|
||||
"uniform float height;\n"
|
||||
"uniform vec2 position;\n"
|
||||
"uniform float radius;\n"
|
||||
"\n"
|
||||
"uniform int discardOpaque;\n"
|
||||
"\n"
|
||||
"void main() {\n"
|
||||
" vec4 pixColor = texture2D(tex, v_texcoord);\n"
|
||||
"\n"
|
||||
" if (discardOpaque == 1 && pixColor[3] * alpha == 1.0) {\n"
|
||||
" discard;\n"
|
||||
" return;\n"
|
||||
" gl_FragColor = texture2D(tex, v_texcoord) * alpha;\n"
|
||||
" vec2 corner_distance = min(gl_FragCoord.xy - position, position + vec2(width, height) - gl_FragCoord.xy);\n"
|
||||
" if (max(corner_distance.x, corner_distance.y) < radius) {\n"
|
||||
" float d = radius - distance(corner_distance, vec2(radius, radius));\n"
|
||||
" float smooth = smoothstep(-1.0f, 1.0f, d);\n"
|
||||
" gl_FragColor = mix(vec4(0), gl_FragColor, smooth);\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" vec2 pixCoord = fullSize * v_texcoord;\n"
|
||||
"\n"
|
||||
" if (pixCoord[0] < topLeft[0]) {\n"
|
||||
" // we're close left\n"
|
||||
" if (pixCoord[1] < topLeft[1]) {\n"
|
||||
// top
|
||||
" if (distance(topLeft, pixCoord) > radius) {\n"
|
||||
" discard;\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
" } else if (pixCoord[1] > bottomRight[1]) {\n"
|
||||
// bottom
|
||||
" if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord) > radius) {\n"
|
||||
" discard;\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" else if (pixCoord[0] > bottomRight[0]) {\n"
|
||||
// we're close right
|
||||
" if (pixCoord[1] < topLeft[1]) {\n"
|
||||
// top
|
||||
" if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord) > radius) {\n"
|
||||
" discard;\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
" } else if (pixCoord[1] > bottomRight[1]) {\n"
|
||||
// bottom
|
||||
" if (distance(bottomRight, pixCoord) > radius) {\n"
|
||||
" discard;\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" gl_FragColor = pixColor * alpha;\n"
|
||||
"}\n";
|
||||
|
||||
const GLchar tex_fragment_src_rgbx[] =
|
||||
|
@ -102,56 +64,19 @@ const GLchar tex_fragment_src_rgbx[] =
|
|||
"uniform sampler2D tex;\n"
|
||||
"uniform float alpha;\n"
|
||||
"\n"
|
||||
"uniform vec2 topLeft;\n"
|
||||
"uniform vec2 bottomRight;\n"
|
||||
"uniform vec2 fullSize;\n"
|
||||
"uniform float width;\n"
|
||||
"uniform float height;\n"
|
||||
"uniform vec2 position;\n"
|
||||
"uniform float radius;\n"
|
||||
"\n"
|
||||
"uniform int discardOpaque;\n"
|
||||
"\n"
|
||||
"void main() {\n"
|
||||
"\n"
|
||||
" if (discardOpaque == 1 && alpha == 1.0) {\n"
|
||||
" discard;\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" vec2 pixCoord = fullSize * v_texcoord;\n"
|
||||
"\n"
|
||||
" if (pixCoord[0] < topLeft[0]) {\n"
|
||||
// we're close left
|
||||
" if (pixCoord[1] < topLeft[1]) {\n"
|
||||
// top
|
||||
" if (distance(topLeft, pixCoord) > radius) {\n"
|
||||
" discard;\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
" } else if (pixCoord[1] > bottomRight[1]) {\n"
|
||||
// bottom
|
||||
" if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord) > radius) {\n"
|
||||
" discard;\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" else if (pixCoord[0] > bottomRight[0]) {\n"
|
||||
// we're close right
|
||||
" if (pixCoord[1] < topLeft[1]) {\n"
|
||||
// top
|
||||
" if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord) > radius) {\n"
|
||||
" discard;\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
" } else if (pixCoord[1] > bottomRight[1]) {\n"
|
||||
// bottom
|
||||
" if (distance(bottomRight, pixCoord) > radius) {\n"
|
||||
" discard;\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0) * alpha;\n"
|
||||
" vec2 corner_distance = min(gl_FragCoord.xy - position, position + vec2(width, height) - gl_FragCoord.xy);\n"
|
||||
" if (max(corner_distance.x, corner_distance.y) < radius) {\n"
|
||||
" float d = radius - distance(corner_distance, vec2(radius, radius));\n"
|
||||
" float smooth = smoothstep(-1.0f, 1.0f, d);\n"
|
||||
" gl_FragColor = mix(vec4(0), gl_FragColor, smooth);\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
const GLchar tex_fragment_src_external[] =
|
||||
|
@ -161,58 +86,19 @@ const GLchar tex_fragment_src_external[] =
|
|||
"uniform samplerExternalOES texture0;\n"
|
||||
"uniform float alpha;\n"
|
||||
"\n"
|
||||
"uniform vec2 topLeft;\n"
|
||||
"uniform vec2 bottomRight;\n"
|
||||
"uniform vec2 fullSize;\n"
|
||||
"uniform float width;\n"
|
||||
"uniform float height;\n"
|
||||
"uniform vec2 position;\n"
|
||||
"uniform float radius;\n"
|
||||
"\n"
|
||||
"uniform int discardOpaque;\n"
|
||||
"\n"
|
||||
"void main() {\n"
|
||||
"\n"
|
||||
" vec4 pixColor = texture2D(texture0, v_texcoord);\n"
|
||||
"\n"
|
||||
" if (discardOpaque == 1 && pixColor[3] * alpha == 1.0) {\n"
|
||||
" discard;\n"
|
||||
" return;\n"
|
||||
" gl_FragColor = texture2D(texture0, v_texcoord) * alpha;\n"
|
||||
" vec2 corner_distance = min(gl_FragCoord.xy - position, position + vec2(width, height) - gl_FragCoord.xy);\n"
|
||||
" if (max(corner_distance.x, corner_distance.y) < radius) {\n"
|
||||
" float d = radius - distance(corner_distance, vec2(radius, radius));\n"
|
||||
" float smooth = smoothstep(-1.0f, 1.0f, d);\n"
|
||||
" gl_FragColor = mix(vec4(0), gl_FragColor, smooth);\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" vec2 pixCoord = fullSize * v_texcoord;\n"
|
||||
"\n"
|
||||
" if (pixCoord[0] < topLeft[0]) {\n"
|
||||
// we're close left
|
||||
" if (pixCoord[1] < topLeft[1]) {\n"
|
||||
// top
|
||||
" if (distance(topLeft, pixCoord) > radius) {\n"
|
||||
" discard;\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
" } else if (pixCoord[1] > bottomRight[1]) {\n"
|
||||
// bottom
|
||||
" if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord) > radius) {\n"
|
||||
" discard;\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" else if (pixCoord[0] > bottomRight[0]) {\n"
|
||||
// we're close right
|
||||
" if (pixCoord[1] < topLeft[1]) {\n"
|
||||
// top
|
||||
" if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord) > radius) {\n"
|
||||
" discard;\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
" } else if (pixCoord[1] > bottomRight[1]) {\n"
|
||||
// bottom
|
||||
" if (distance(bottomRight, pixCoord) > radius) {\n"
|
||||
" discard;\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" gl_FragColor = pixColor * alpha;\n"
|
||||
"}\n";
|
||||
|
||||
const GLchar frag_blur_1[] =
|
||||
|
@ -259,4 +145,3 @@ const GLchar frag_blur_2[] =
|
|||
"}\n";
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -140,7 +140,10 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl) {
|
|||
renderer->shaders.tex_rgba.alpha = glGetUniformLocation(prog, "alpha");
|
||||
renderer->shaders.tex_rgba.pos_attrib = glGetAttribLocation(prog, "pos");
|
||||
renderer->shaders.tex_rgba.tex_attrib = glGetAttribLocation(prog, "texcoord");
|
||||
renderer->shaders.tex_rgba.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
|
||||
renderer->shaders.tex_rgba.width = glGetUniformLocation(prog, "width");
|
||||
renderer->shaders.tex_rgba.height = glGetUniformLocation(prog, "height");
|
||||
renderer->shaders.tex_rgba.position = glGetUniformLocation(prog, "position");
|
||||
renderer->shaders.tex_rgba.radius = glGetUniformLocation(prog, "radius");
|
||||
|
||||
prog = link_program(tex_vertex_src, tex_fragment_src_rgbx);
|
||||
renderer->shaders.tex_rgbx.program = prog;
|
||||
|
@ -152,7 +155,10 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl) {
|
|||
renderer->shaders.tex_rgbx.alpha = glGetUniformLocation(prog, "alpha");
|
||||
renderer->shaders.tex_rgbx.pos_attrib = glGetAttribLocation(prog, "pos");
|
||||
renderer->shaders.tex_rgbx.tex_attrib = glGetAttribLocation(prog, "texcoord");
|
||||
renderer->shaders.tex_rgbx.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
|
||||
renderer->shaders.tex_rgbx.width = glGetUniformLocation(prog, "width");
|
||||
renderer->shaders.tex_rgbx.height = glGetUniformLocation(prog, "height");
|
||||
renderer->shaders.tex_rgbx.position = glGetUniformLocation(prog, "position");
|
||||
renderer->shaders.tex_rgbx.radius = glGetUniformLocation(prog, "radius");
|
||||
|
||||
prog = link_program(tex_vertex_src, tex_fragment_src_external);
|
||||
renderer->shaders.tex_ext.program = prog;
|
||||
|
@ -164,7 +170,11 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl) {
|
|||
renderer->shaders.tex_ext.alpha = glGetUniformLocation(prog, "alpha");
|
||||
renderer->shaders.tex_ext.pos_attrib = glGetAttribLocation(prog, "pos");
|
||||
renderer->shaders.tex_ext.tex_attrib = glGetAttribLocation(prog, "texcoord");
|
||||
renderer->shaders.tex_ext.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
|
||||
renderer->shaders.tex_ext.width = glGetUniformLocation(prog, "width");
|
||||
renderer->shaders.tex_ext.height = glGetUniformLocation(prog, "height");
|
||||
renderer->shaders.tex_ext.position = glGetUniformLocation(prog, "position");
|
||||
renderer->shaders.tex_ext.radius = glGetUniformLocation(prog, "radius");
|
||||
prog = link_program(tex_vertex_src, tex_fragment_src_rgba);
|
||||
|
||||
wlr_egl_unset_current(renderer->egl);
|
||||
|
||||
|
@ -218,9 +228,9 @@ void fx_renderer_scissor(struct wlr_box *box) {
|
|||
Rendering Functions
|
||||
*************************/
|
||||
|
||||
bool fx_render_subtexture_with_matrix(struct fx_renderer *renderer,
|
||||
struct wlr_texture *wlr_texture, const struct wlr_fbox *box,
|
||||
const float matrix[static 9], float alpha, int radius) {
|
||||
bool fx_render_subtexture_with_matrix(struct fx_renderer *renderer, struct wlr_texture *wlr_texture,
|
||||
const struct wlr_fbox *src_box, const struct wlr_box *dst_box, const float matrix[static 9],
|
||||
float alpha, int radius) {
|
||||
|
||||
assert(wlr_texture_is_gles2(wlr_texture));
|
||||
struct wlr_gles2_texture_attribs texture_attrs;
|
||||
|
@ -260,7 +270,8 @@ bool fx_render_subtexture_with_matrix(struct fx_renderer *renderer,
|
|||
// to GL_FALSE
|
||||
wlr_matrix_transpose(gl_matrix, gl_matrix);
|
||||
|
||||
if (!texture_attrs.has_alpha && alpha == 1.0) {
|
||||
// if there's no opacity or rounded corners we don't need to blend
|
||||
if (!texture_attrs.has_alpha && alpha == 1.0 && !radius) {
|
||||
glDisable(GL_BLEND);
|
||||
} else {
|
||||
glEnable(GL_BLEND);
|
||||
|
@ -276,12 +287,17 @@ bool fx_render_subtexture_with_matrix(struct fx_renderer *renderer,
|
|||
glUniformMatrix3fv(shader->proj, 1, GL_FALSE, gl_matrix);
|
||||
glUniform1i(shader->tex, 0);
|
||||
glUniform1f(shader->alpha, alpha);
|
||||
glUniform1i(shader->discardOpaque, 0); // TODO
|
||||
|
||||
const GLfloat x1 = box->x / wlr_texture->width;
|
||||
const GLfloat y1 = box->y / wlr_texture->height;
|
||||
const GLfloat x2 = (box->x + box->width) / wlr_texture->width;
|
||||
const GLfloat y2 = (box->y + box->height) / wlr_texture->height;
|
||||
// rounded corners
|
||||
glUniform1f(shader->width, dst_box->width);
|
||||
glUniform1f(shader->height, dst_box->height);
|
||||
glUniform2f(shader->position, dst_box->x, dst_box->y);
|
||||
glUniform1f(shader->radius, radius);
|
||||
|
||||
const GLfloat x1 = src_box->x / wlr_texture->width;
|
||||
const GLfloat y1 = src_box->y / wlr_texture->height;
|
||||
const GLfloat x2 = (src_box->x + src_box->width) / wlr_texture->width;
|
||||
const GLfloat y2 = (src_box->y + src_box->height) / wlr_texture->height;
|
||||
const GLfloat texcoord[] = {
|
||||
x2, y1, // top right
|
||||
x1, y1, // top left
|
||||
|
@ -289,23 +305,6 @@ bool fx_render_subtexture_with_matrix(struct fx_renderer *renderer,
|
|||
x1, y2, // bottom left
|
||||
};
|
||||
|
||||
glUniform2f(
|
||||
glGetUniformLocation(shader->program, "topLeft"),
|
||||
radius,
|
||||
radius
|
||||
);
|
||||
glUniform2f(
|
||||
glGetUniformLocation(shader->program, "bottomRight"),
|
||||
wlr_texture->width - radius,
|
||||
wlr_texture->height - radius
|
||||
);
|
||||
glUniform2f(
|
||||
glGetUniformLocation(shader->program, "fullSize"),
|
||||
wlr_texture->width,
|
||||
wlr_texture->height
|
||||
);
|
||||
glUniform1f(glGetUniformLocation(shader->program, "radius"), radius);
|
||||
|
||||
glVertexAttribPointer(shader->pos_attrib, 2, GL_FLOAT, GL_FALSE, 0, verts);
|
||||
glVertexAttribPointer(shader->tex_attrib, 2, GL_FLOAT, GL_FALSE, 0, texcoord);
|
||||
|
||||
|
@ -322,15 +321,15 @@ bool fx_render_subtexture_with_matrix(struct fx_renderer *renderer,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool fx_render_texture_with_matrix(struct fx_renderer *renderer,
|
||||
struct wlr_texture *wlr_texture, const float matrix[static 9], float alpha, int radius) {
|
||||
struct wlr_fbox box = {
|
||||
bool fx_render_texture_with_matrix(struct fx_renderer *renderer, struct wlr_texture *wlr_texture,
|
||||
const struct wlr_box *dst_box, const float matrix[static 9], float alpha, int radius) {
|
||||
struct wlr_fbox src_box = {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = wlr_texture->width,
|
||||
.height = wlr_texture->height,
|
||||
};
|
||||
return fx_render_subtexture_with_matrix(renderer, wlr_texture, &box, matrix, alpha, radius);
|
||||
return fx_render_subtexture_with_matrix(renderer, wlr_texture, &src_box, dst_box, matrix, alpha, radius);
|
||||
}
|
||||
|
||||
void fx_render_rect(struct fx_renderer *renderer, const struct wlr_box *box, const float color[static 4], const float projection[static 9]) {
|
||||
|
@ -369,4 +368,3 @@ void fx_render_rect(struct fx_renderer *renderer, const struct wlr_box *box, con
|
|||
|
||||
glDisableVertexAttribArray(renderer->shaders.quad.pos_attrib);
|
||||
}
|
||||
|
||||
|
|
|
@ -122,9 +122,9 @@ static void render_texture(struct wlr_output *wlr_output,
|
|||
scissor_output(wlr_output, &rects[i]);
|
||||
set_scale_filter(wlr_output, texture, output->scale_filter);
|
||||
if (src_box != NULL) {
|
||||
fx_render_subtexture_with_matrix(renderer, texture, src_box, matrix, alpha, corner_radius);
|
||||
fx_render_subtexture_with_matrix(renderer, texture, src_box, dst_box, matrix, alpha, corner_radius);
|
||||
} else {
|
||||
fx_render_texture_with_matrix(renderer, texture, matrix, alpha, corner_radius);
|
||||
fx_render_texture_with_matrix(renderer, texture, dst_box, matrix, alpha, corner_radius);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue