diff --git a/config.in b/config.in index 11c11ec5..15727bbe 100644 --- a/config.in +++ b/config.in @@ -36,7 +36,7 @@ shadow_blur_radius 20 shadow_color #0000007F # inactive window fade amount. 0.0 = no dimming, 1.0 = fully dimmed -dim_inactive 0.0 +default_dim_inactive 0.0 dim_inactive_colors.unfocused #000000FF dim_inactive_colors.urgent #900000FF diff --git a/include/sway/desktop/fx_renderer/fx_framebuffer.h b/include/sway/desktop/fx_renderer/fx_framebuffer.h index 965c1def..289b4d87 100644 --- a/include/sway/desktop/fx_renderer/fx_framebuffer.h +++ b/include/sway/desktop/fx_renderer/fx_framebuffer.h @@ -12,10 +12,9 @@ struct fx_framebuffer { GLuint fb; }; -void fx_framebuffer_bind(struct fx_framebuffer *buffer, GLsizei width, GLsizei height); +void fx_framebuffer_bind(struct fx_framebuffer *buffer); -void fx_framebuffer_create(struct wlr_output *output, struct fx_framebuffer *buffer, - bool bind); +void fx_framebuffer_create(struct fx_framebuffer *buffer, int width, int height, bool bind); void fx_framebuffer_release(struct fx_framebuffer *buffer); diff --git a/include/sway/desktop/fx_renderer/fx_renderer.h b/include/sway/desktop/fx_renderer/fx_renderer.h index 00e912e7..b03db984 100644 --- a/include/sway/desktop/fx_renderer/fx_renderer.h +++ b/include/sway/desktop/fx_renderer/fx_renderer.h @@ -4,11 +4,12 @@ #include #include #include +#include #include "sway/desktop/fx_renderer/fx_framebuffer.h" #include "sway/desktop/fx_renderer/fx_texture.h" -enum corner_location { ALL, TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, NONE }; +enum corner_location { TOP_LEFT, TOP_RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT, ALL, NONE }; enum fx_tex_shader_source { SHADER_SOURCE_TEXTURE_RGBA = 1, @@ -20,6 +21,8 @@ enum fx_rounded_quad_shader_source { SHADER_SOURCE_QUAD_ROUND = 1, SHADER_SOURCE_QUAD_ROUND_TOP_LEFT = 2, SHADER_SOURCE_QUAD_ROUND_TOP_RIGHT = 3, + SHADER_SOURCE_QUAD_ROUND_BOTTOM_RIGHT = 4, + SHADER_SOURCE_QUAD_ROUND_BOTTOM_LEFT = 5, }; struct decoration_data { @@ -77,11 +80,9 @@ struct blur_shader { }; struct fx_renderer { - struct wlr_egl *egl; - float projection[9]; - struct sway_output *sway_output; + int viewport_width, viewport_height; GLuint stencil_buffer_id; @@ -115,6 +116,8 @@ struct fx_renderer { struct rounded_quad_shader rounded_quad; struct rounded_quad_shader rounded_tl_quad; struct rounded_quad_shader rounded_tr_quad; + struct rounded_quad_shader rounded_bl_quad; + struct rounded_quad_shader rounded_br_quad; struct blur_shader blur1; struct blur_shader blur2; @@ -155,7 +158,7 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl); void fx_renderer_fini(struct fx_renderer *renderer); -void fx_renderer_begin(struct fx_renderer *renderer, struct sway_output *output); +void fx_renderer_begin(struct fx_renderer *renderer, int width, int height); void fx_renderer_end(struct fx_renderer *renderer); @@ -174,18 +177,19 @@ 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_rounded_rect(struct fx_renderer *renderer, const struct wlr_box *box, - const float color[static 4], const float projection[static 9], - int radius, enum corner_location corner_location); + const float color[static 4], const float matrix[static 9], int radius, + enum corner_location corner_location); void fx_render_border_corner(struct fx_renderer *renderer, const struct wlr_box *box, - const float color[static 4], const float projection[static 9], + const float color[static 4], const float matrix[static 9], enum corner_location corner_location, int radius, int border_thickness); void fx_render_box_shadow(struct fx_renderer *renderer, const struct wlr_box *box, - const float color[static 4], const float projection[static 9], int radius, float blur_sigma); + const float color[static 4], const float matrix[static 9], int radius, + float blur_sigma); -void fx_render_blur(struct fx_renderer *renderer, struct sway_output *output, - const float matrix[static 9], struct fx_framebuffer **buffer, - struct blur_shader *shader, const struct wlr_box *box, int blur_radius); +void fx_render_blur(struct fx_renderer *renderer, const float matrix[static 9], + struct fx_framebuffer **buffer, struct blur_shader *shader, const struct wlr_box *box, + int blur_radius); #endif diff --git a/sway/desktop/fx_renderer/fx_framebuffer.c b/sway/desktop/fx_renderer/fx_framebuffer.c index db6f8928..6cc1dbf3 100644 --- a/sway/desktop/fx_renderer/fx_framebuffer.c +++ b/sway/desktop/fx_renderer/fx_framebuffer.c @@ -1,12 +1,11 @@ #include "log.h" #include "sway/desktop/fx_renderer/fx_framebuffer.h" -void fx_framebuffer_bind(struct fx_framebuffer *buffer, GLsizei width, GLsizei height) { +void fx_framebuffer_bind(struct fx_framebuffer *buffer) { glBindFramebuffer(GL_FRAMEBUFFER, buffer->fb); - glViewport(0, 0, width, height); } -void fx_framebuffer_create(struct wlr_output *output, struct fx_framebuffer *buffer, bool bind) { +void fx_framebuffer_create(struct fx_framebuffer *buffer, int width, int height, bool bind) { bool firstAlloc = false; // Create a new framebuffer @@ -25,9 +24,6 @@ void fx_framebuffer_create(struct wlr_output *output, struct fx_framebuffer *buf glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } - int width, height; - wlr_output_transformed_resolution(output, &width, &height); - if (firstAlloc || buffer->texture.width != width || buffer->texture.height != height) { glBindTexture(GL_TEXTURE_2D, buffer->texture.id); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); @@ -51,7 +47,7 @@ void fx_framebuffer_create(struct wlr_output *output, struct fx_framebuffer *buf // Bind the default framebuffer glBindTexture(GL_TEXTURE_2D, 0); if (bind) { - fx_framebuffer_bind(buffer, width, height); + fx_framebuffer_bind(buffer); } } diff --git a/sway/desktop/fx_renderer/fx_renderer.c b/sway/desktop/fx_renderer/fx_renderer.c index 715c5b15..8de11874 100644 --- a/sway/desktop/fx_renderer/fx_renderer.c +++ b/sway/desktop/fx_renderer/fx_renderer.c @@ -15,7 +15,6 @@ #include "log.h" #include "sway/desktop/fx_renderer/fx_renderer.h" #include "sway/desktop/fx_renderer/matrix.h" -#include "sway/output.h" #include "sway/server.h" // shaders @@ -35,14 +34,11 @@ static const GLfloat verts[] = { 0, 1, // bottom left }; -static void create_stencil_buffer(struct wlr_output* output, GLuint *buffer_id) { +static void create_stencil_buffer(GLuint *buffer_id, int width, int height) { if (*buffer_id != (uint32_t) -1) { return; } - int width, height; - wlr_output_transformed_resolution(output, &width, &height); - glGenRenderbuffers(1, buffer_id); glBindRenderbuffer(GL_RENDERBUFFER, *buffer_id); glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height); @@ -205,8 +201,6 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl) { sway_log(SWAY_ERROR, "GLES2 RENDERER: Could not make EGL current"); return NULL; } - // TODO: needed? - renderer->egl = egl; renderer->main_buffer.fb = -1; @@ -263,6 +257,14 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl) { SHADER_SOURCE_QUAD_ROUND_TOP_RIGHT)) { goto error; } + if (!link_rounded_quad_program(renderer, &renderer->shaders.rounded_bl_quad, + SHADER_SOURCE_QUAD_ROUND_BOTTOM_LEFT)) { + goto error; + } + if (!link_rounded_quad_program(renderer, &renderer->shaders.rounded_br_quad, + SHADER_SOURCE_QUAD_ROUND_BOTTOM_RIGHT)) { + goto error; + } // Border corner shader prog = link_program(corner_frag_src); @@ -337,7 +339,7 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl) { } - if (!eglMakeCurrent(wlr_egl_get_display(renderer->egl), + if (!eglMakeCurrent(wlr_egl_get_display(egl), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) { sway_log(SWAY_ERROR, "GLES2 RENDERER: Could not unset current EGL"); goto error; @@ -351,6 +353,8 @@ error: glDeleteProgram(renderer->shaders.rounded_quad.program); glDeleteProgram(renderer->shaders.rounded_tl_quad.program); glDeleteProgram(renderer->shaders.rounded_tr_quad.program); + glDeleteProgram(renderer->shaders.rounded_bl_quad.program); + glDeleteProgram(renderer->shaders.rounded_br_quad.program); glDeleteProgram(renderer->shaders.corner.program); glDeleteProgram(renderer->shaders.box_shadow.program); glDeleteProgram(renderer->shaders.blur1.program); @@ -359,7 +363,7 @@ error: glDeleteProgram(renderer->shaders.tex_rgbx.program); glDeleteProgram(renderer->shaders.tex_ext.program); - if (!eglMakeCurrent(wlr_egl_get_display(renderer->egl), + if (!eglMakeCurrent(wlr_egl_get_display(egl), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) { sway_log(SWAY_ERROR, "GLES2 RENDERER: Could not unset current EGL"); } @@ -379,13 +383,11 @@ void fx_renderer_fini(struct fx_renderer *renderer) { release_stencil_buffer(&renderer->stencil_buffer_id); } -void fx_renderer_begin(struct fx_renderer *renderer, struct sway_output *sway_output) { - struct wlr_output *output = sway_output->wlr_output; +void fx_renderer_begin(struct fx_renderer *renderer, int width, int height) { + glViewport(0, 0, width, height); + renderer->viewport_width = width; + renderer->viewport_height = height; - int width, height; - wlr_output_transformed_resolution(output, &width, &height); - - renderer->sway_output = sway_output; // Store the wlr framebuffer GLint wlr_fb = -1; glGetIntegerv(GL_FRAMEBUFFER_BINDING, &wlr_fb); @@ -395,14 +397,11 @@ void fx_renderer_begin(struct fx_renderer *renderer, struct sway_output *sway_ou } renderer->wlr_buffer.fb = wlr_fb; - // Create the main framebuffer - fx_framebuffer_create(output, &renderer->main_buffer, true); - // Create the stencil buffer and attach it to our main_buffer - create_stencil_buffer(output, &renderer->stencil_buffer_id); - - // Create a new blur/effects framebuffers - fx_framebuffer_create(output, &renderer->effects_buffer, false); - fx_framebuffer_create(output, &renderer->effects_buffer_swapped, false); + // Create the framebuffers + fx_framebuffer_create(&renderer->main_buffer, width, height, true); + fx_framebuffer_create(&renderer->effects_buffer, width, height, false); + fx_framebuffer_create(&renderer->effects_buffer_swapped, width, height, false); + create_stencil_buffer(&renderer->stencil_buffer_id, width, height); // refresh projection matrix matrix_projection(renderer->projection, width, height, @@ -411,7 +410,7 @@ void fx_renderer_begin(struct fx_renderer *renderer, struct sway_output *sway_ou glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // Bind to our main framebuffer - fx_framebuffer_bind(&renderer->main_buffer, width, height); + fx_framebuffer_bind(&renderer->main_buffer); } void fx_renderer_end(struct fx_renderer *renderer) { @@ -578,8 +577,8 @@ void fx_render_rect(struct fx_renderer *renderer, const struct wlr_box *box, } void fx_render_rounded_rect(struct fx_renderer *renderer, const struct wlr_box *box, - const float color[static 4], const float projection[static 9], - int radius, enum corner_location corner_location) { + const float color[static 4], const float matrix[static 9], int radius, + enum corner_location corner_location) { if (box->width == 0 || box->height == 0) { return; } @@ -597,14 +596,17 @@ void fx_render_rounded_rect(struct fx_renderer *renderer, const struct wlr_box * case TOP_RIGHT: shader = &renderer->shaders.rounded_tr_quad; break; + case BOTTOM_LEFT: + shader = &renderer->shaders.rounded_bl_quad; + break; + case BOTTOM_RIGHT: + shader = &renderer->shaders.rounded_br_quad; + break; default: sway_log(SWAY_ERROR, "Invalid Corner Location. Aborting render"); abort(); } - float matrix[9]; - wlr_matrix_project_box(matrix, box, WL_OUTPUT_TRANSFORM_NORMAL, 0, projection); - float gl_matrix[9]; wlr_matrix_multiply(gl_matrix, renderer->projection, matrix); @@ -636,14 +638,12 @@ void fx_render_rounded_rect(struct fx_renderer *renderer, const struct wlr_box * } void fx_render_border_corner(struct fx_renderer *renderer, const struct wlr_box *box, - const float color[static 4], const float projection[static 9], + const float color[static 4], const float matrix[static 9], enum corner_location corner_location, int radius, int border_thickness) { if (border_thickness == 0 || box->width == 0 || box->height == 0) { return; } assert(box->width > 0 && box->height > 0); - float matrix[9]; - wlr_matrix_project_box(matrix, box, WL_OUTPUT_TRANSFORM_NORMAL, 0, projection); float gl_matrix[9]; wlr_matrix_multiply(gl_matrix, renderer->projection, matrix); @@ -686,14 +686,12 @@ void fx_render_border_corner(struct fx_renderer *renderer, const struct wlr_box // TODO: alpha input arg? void fx_render_box_shadow(struct fx_renderer *renderer, const struct wlr_box *box, - const float color[static 4], const float projection[static 9], - int corner_radius, float blur_sigma) { + const float color[static 4], const float matrix [static 9], int corner_radius, + float blur_sigma) { if (box->width == 0 || box->height == 0) { return; } assert(box->width > 0 && box->height > 0); - float matrix[9]; - wlr_matrix_project_box(matrix, box, WL_OUTPUT_TRANSFORM_NORMAL, 0, projection); float gl_matrix[9]; wlr_matrix_multiply(gl_matrix, renderer->projection, matrix); @@ -722,7 +720,7 @@ void fx_render_box_shadow(struct fx_renderer *renderer, const struct wlr_box *bo // Disable writing to color buffer glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Draw the rounded rect as a mask - fx_render_rounded_rect(renderer, &inner_box, col, projection, corner_radius, ALL); + fx_render_rounded_rect(renderer, &inner_box, col, matrix, corner_radius, ALL); // Close the mask glStencilFunc(GL_NOTEQUAL, 1, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); @@ -761,9 +759,9 @@ void fx_render_box_shadow(struct fx_renderer *renderer, const struct wlr_box *bo glDisable(GL_STENCIL_TEST); } -void fx_render_blur(struct fx_renderer *renderer, struct sway_output *output, - const float matrix[static 9], struct fx_framebuffer **buffer, - struct blur_shader *shader, const struct wlr_box *box, int blur_radius) { +void fx_render_blur(struct fx_renderer *renderer, const float matrix[static 9], + struct fx_framebuffer **buffer, struct blur_shader *shader, + const struct wlr_box *box, int blur_radius) { glDisable(GL_BLEND); glDisable(GL_STENCIL_TEST); @@ -784,12 +782,10 @@ void fx_render_blur(struct fx_renderer *renderer, struct sway_output *output, glUniform1i(shader->tex, 0); glUniform1f(shader->radius, blur_radius); - int width, height; - wlr_output_transformed_resolution(output->wlr_output, &width, &height); if (shader == &renderer->shaders.blur1) { - glUniform2f(shader->halfpixel, 0.5f / (width / 2.0f), 0.5f / (height / 2.0f)); + glUniform2f(shader->halfpixel, 0.5f / (renderer->viewport_width / 2.0f), 0.5f / (renderer->viewport_height / 2.0f)); } else { - glUniform2f(shader->halfpixel, 0.5f / (width * 2.0f), 0.5f / (height * 2.0f)); + glUniform2f(shader->halfpixel, 0.5f / (renderer->viewport_width * 2.0f), 0.5f / (renderer->viewport_height * 2.0f)); } glVertexAttribPointer(shader->pos_attrib, 2, GL_FLOAT, GL_FALSE, 0, verts); diff --git a/sway/desktop/fx_renderer/shaders/quad_round.frag b/sway/desktop/fx_renderer/shaders/quad_round.frag index 4dcf0c53..4099e60a 100644 --- a/sway/desktop/fx_renderer/shaders/quad_round.frag +++ b/sway/desktop/fx_renderer/shaders/quad_round.frag @@ -1,6 +1,8 @@ #define SOURCE_QUAD_ROUND 1 #define SOURCE_QUAD_ROUND_TOP_LEFT 2 #define SOURCE_QUAD_ROUND_TOP_RIGHT 3 +#define SOURCE_QUAD_ROUND_BOTTOM_RIGHT 4 +#define SOURCE_QUAD_ROUND_BOTTOM_LEFT 5 #if !defined(SOURCE) #error "Missing shader preamble" @@ -22,6 +24,10 @@ vec2 getCornerDist() { return abs(gl_FragCoord.xy - position - size) - size + radius; #elif SOURCE == SOURCE_QUAD_ROUND_TOP_RIGHT return abs(gl_FragCoord.xy - position - vec2(0, size.y)) - size + radius; +#elif SOURCE == SOURCE_QUAD_ROUND_BOTTOM_RIGHT + return abs(gl_FragCoord.xy - position) - size + radius; +#elif SOURCE == SOURCE_QUAD_ROUND_BOTTOM_LEFT + return abs(gl_FragCoord.xy - position - vec2(size.x, 0)) - size + radius; #endif } diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 6fc541b6..d89ce72e 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -64,6 +64,43 @@ bool should_parameters_shadow() { return config->shadow_blur_sigma > 0 && config->shadow_color[3] > 0.0; } +// TODO: contribute wlroots function to allow creating an fbox from a box? +struct wlr_fbox wlr_fbox_from_wlr_box(struct wlr_box *box) { + return (struct wlr_fbox) { + .x = box->x, + .y = box->y, + .width = box->width, + .height = box->height, + }; +} + +// TODO: Remove this ugly abomination with a complete border rework... +enum corner_location get_rotated_corner(enum corner_location corner_location, + enum wl_output_transform transform) { + if (corner_location == ALL || corner_location == NONE) { + return corner_location; + } + switch (transform) { + case WL_OUTPUT_TRANSFORM_NORMAL: + return corner_location; + case WL_OUTPUT_TRANSFORM_90: + return (corner_location + 1) % 4; + case WL_OUTPUT_TRANSFORM_180: + return (corner_location + 2) % 4; + case WL_OUTPUT_TRANSFORM_270: + return (corner_location + 3) % 4; + case WL_OUTPUT_TRANSFORM_FLIPPED: + return (corner_location + (1 - 2 * (corner_location % 2))) % 4; + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + return (corner_location + (4 - 2 * (corner_location % 2))) % 4; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + return (corner_location + (3 - 2 * (corner_location % 2))) % 4; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + return (corner_location + (2 - 2 * (corner_location % 2))) % 4; + } + return corner_location; +} + /** * Apply scale to a width or height. * @@ -148,16 +185,23 @@ static void render_texture(struct wlr_output *wlr_output, goto damage_finish; } + // ensure the box is updated as per the output orientation + struct wlr_box transformed_box; + int width, height; + wlr_output_transformed_resolution(wlr_output, &width, &height); + wlr_box_transform(&transformed_box, dst_box, + wlr_output_transform_invert(wlr_output->transform), width, height); + int nrects; pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); for (int i = 0; i < nrects; ++i) { 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, dst_box, + fx_render_subtexture_with_matrix(renderer, texture, src_box, &transformed_box, matrix, deco_data); } else { - fx_render_texture_with_matrix(renderer, texture, dst_box, matrix, deco_data); + fx_render_texture_with_matrix(renderer, texture, &transformed_box, matrix, deco_data); } } @@ -166,17 +210,14 @@ damage_finish: } /* Renders the blur for each damaged rect and swaps the buffer */ -void render_blur_segments(struct fx_renderer *renderer, struct sway_output *output, +void render_blur_segments(struct fx_renderer *renderer, const float matrix[static 9], pixman_region32_t* damage, struct fx_framebuffer **buffer, struct blur_shader* shader, const struct wlr_box *box, int blur_radius) { - int width, height; - wlr_output_transformed_resolution(output->wlr_output, &width, &height); - if (*buffer == &renderer->effects_buffer) { - fx_framebuffer_bind(&renderer->effects_buffer_swapped, width, height); + fx_framebuffer_bind(&renderer->effects_buffer_swapped); } else { - fx_framebuffer_bind(&renderer->effects_buffer, width, height); + fx_framebuffer_bind(&renderer->effects_buffer); } if (pixman_region32_not_empty(damage)) { @@ -186,7 +227,7 @@ void render_blur_segments(struct fx_renderer *renderer, struct sway_output *outp const pixman_box32_t box = rects[i]; struct wlr_box new_box = { box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1 }; fx_renderer_scissor(&new_box); - fx_render_blur(renderer, output, matrix, buffer, shader, &new_box, blur_radius); + fx_render_blur(renderer, matrix, buffer, shader, &new_box, blur_radius); } } @@ -197,14 +238,15 @@ void render_blur_segments(struct fx_renderer *renderer, struct sway_output *outp } } -/** Blurs the main_buffer content and returns the blurred framebuffer */ +// Blurs the main_buffer content and returns the blurred framebuffer struct fx_framebuffer *get_main_buffer_blur(struct fx_renderer *renderer, struct sway_output *output, pixman_region32_t *original_damage, const float box_matrix[static 9], const struct wlr_box *box) { - struct wlr_box monitor_box = get_monitor_box(output->wlr_output); + struct wlr_output *wlr_output = output->wlr_output; + struct wlr_box monitor_box = get_monitor_box(wlr_output); - const enum wl_output_transform transform = wlr_output_transform_invert(output->wlr_output->transform); + const enum wl_output_transform transform = wlr_output_transform_invert(wlr_output->transform); float matrix[9]; - wlr_matrix_project_box(matrix, &monitor_box, transform, 0, output->wlr_output->transform_matrix); + wlr_matrix_project_box(matrix, &monitor_box, transform, 0, wlr_output->transform_matrix); float gl_matrix[9]; wlr_matrix_multiply(gl_matrix, renderer->projection, matrix); @@ -212,7 +254,7 @@ struct fx_framebuffer *get_main_buffer_blur(struct fx_renderer *renderer, struct pixman_region32_t damage; pixman_region32_init(&damage); pixman_region32_copy(&damage, original_damage); - wlr_region_transform(&damage, &damage, wlr_output_transform_invert(output->wlr_output->transform), + wlr_region_transform(&damage, &damage, transform, monitor_box.width, monitor_box.height); wlr_region_expand(&damage, &damage, get_blur_size()); @@ -220,7 +262,7 @@ struct fx_framebuffer *get_main_buffer_blur(struct fx_renderer *renderer, struct struct fx_framebuffer *current_buffer = &renderer->main_buffer; // Bind to blur framebuffer - fx_framebuffer_bind(&renderer->effects_buffer, monitor_box.width, monitor_box.height); + fx_framebuffer_bind(&renderer->effects_buffer); glBindTexture(renderer->main_buffer.texture.target, renderer->main_buffer.texture.id); // damage region will be scaled, make a temp @@ -233,13 +275,13 @@ struct fx_framebuffer *get_main_buffer_blur(struct fx_renderer *renderer, struct int blur_passes = config->blur_params.num_passes; // First pass - render_blur_segments(renderer, output, gl_matrix, &tempDamage, ¤t_buffer, + render_blur_segments(renderer, gl_matrix, &tempDamage, ¤t_buffer, &renderer->shaders.blur1, box, blur_radius); // Downscale for (int i = 1; i < blur_passes; ++i) { wlr_region_scale(&tempDamage, &damage, 1.0f / (1 << (i + 1))); - render_blur_segments(renderer, output, gl_matrix, &tempDamage, ¤t_buffer, + render_blur_segments(renderer, gl_matrix, &tempDamage, ¤t_buffer, &renderer->shaders.blur1, box, blur_radius); } @@ -247,7 +289,7 @@ struct fx_framebuffer *get_main_buffer_blur(struct fx_renderer *renderer, struct for (int i = blur_passes - 1; i >= 0; --i) { // when upsampling we make the region twice as big wlr_region_scale(&tempDamage, &damage, 1.0f / (1 << i)); - render_blur_segments(renderer, output, gl_matrix, &tempDamage, ¤t_buffer, + render_blur_segments(renderer, gl_matrix, &tempDamage, ¤t_buffer, &renderer->shaders.blur2, box, blur_radius); } @@ -255,7 +297,7 @@ struct fx_framebuffer *get_main_buffer_blur(struct fx_renderer *renderer, struct pixman_region32_fini(&damage); // Bind back to the default buffer - fx_framebuffer_bind(&renderer->main_buffer, monitor_box.width, monitor_box.height); + fx_framebuffer_bind(&renderer->main_buffer); return current_buffer; } @@ -360,13 +402,24 @@ void render_box_shadow(struct sway_output *output, pixman_region32_t *output_dam goto damage_finish; } + float matrix[9]; + wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0, + wlr_output->transform_matrix); + + // ensure the box is updated as per the output orientation + struct wlr_box transformed_box; + int width, height; + wlr_output_transformed_resolution(wlr_output, &width, &height); + wlr_box_transform(&transformed_box, &box, + wlr_output_transform_invert(wlr_output->transform), width, height); + int nrects; pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); for (int i = 0; i < nrects; ++i) { scissor_output(wlr_output, &rects[i]); - fx_render_box_shadow(renderer, &box, color, - wlr_output->transform_matrix, corner_radius, blur_sigma); + fx_render_box_shadow(renderer, &transformed_box, color, matrix, + corner_radius, blur_sigma); } damage_finish: @@ -387,6 +440,7 @@ static void render_surface_iterator(struct sway_output *output, } struct wlr_box proj_box = *_box; + scale_box(&proj_box, wlr_output->scale); float matrix[9]; @@ -431,9 +485,10 @@ static void render_surface_iterator(struct sway_output *output, } if (has_alpha) { - int width, height; - wlr_output_transformed_resolution(wlr_output, &width, &height); - struct wlr_fbox blur_src_box = { 0, 0, width, height }; + struct wlr_box monitor_box = get_monitor_box(wlr_output); + wlr_box_transform(&monitor_box, &monitor_box, + wlr_output_transform_invert(wlr_output->transform), monitor_box.width, monitor_box.height); + struct wlr_fbox blur_src_box = wlr_fbox_from_wlr_box(&monitor_box); render_blur(should_optimize_blur, output, output_damage, &blur_src_box, &dst_box, &opaque_region, surface->current.width, surface->current.height, surface->current.scale, deco_data.corner_radius); } @@ -523,14 +578,13 @@ static void render_drag_icons(struct sway_output *output, render_surface_iterator, &data); } -void render_whole_output(struct fx_renderer *renderer, pixman_region32_t *original_damage, - struct fx_texture *texture) { - struct wlr_output *output = renderer->sway_output->wlr_output; - struct wlr_box monitor_box = get_monitor_box(output); +void render_whole_output(struct fx_renderer *renderer, struct wlr_output *wlr_output, + pixman_region32_t *original_damage, struct fx_texture *texture) { + struct wlr_box monitor_box = get_monitor_box(wlr_output); - enum wl_output_transform transform = wlr_output_transform_invert(output->transform); + enum wl_output_transform transform = wlr_output_transform_invert(wlr_output->transform); float matrix[9]; - wlr_matrix_project_box(matrix, &monitor_box, transform, 0.0, output->transform_matrix); + wlr_matrix_project_box(matrix, &monitor_box, transform, 0.0, wlr_output->transform_matrix); pixman_region32_t damage; pixman_region32_init(&damage); @@ -545,7 +599,7 @@ void render_whole_output(struct fx_renderer *renderer, pixman_region32_t *origin int nrects; pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); for (int i = 0; i < nrects; ++i) { - scissor_output(output, &rects[i]); + scissor_output(wlr_output, &rects[i]); fx_render_texture_with_matrix(renderer, texture, &monitor_box, matrix, get_undecorated_decoration_data()); } @@ -566,7 +620,8 @@ void render_monitor_blur(struct sway_output *output, pixman_region32_t *damage) wlr_output->transform_matrix, &monitor_box); // Render the newly blurred content into the blur_buffer - fx_framebuffer_create(wlr_output, &renderer->blur_buffer, true); + fx_framebuffer_create(&renderer->blur_buffer, + output->renderer->viewport_width, output->renderer->viewport_height, true); // Clear the damaged region of the blur_buffer float clear_color[] = { 0, 0, 0, 0 }; int nrects; @@ -575,8 +630,8 @@ void render_monitor_blur(struct sway_output *output, pixman_region32_t *damage) scissor_output(wlr_output, &rects[i]); fx_renderer_clear(clear_color); } - render_whole_output(renderer, &fake_damage, &buffer->texture); - fx_framebuffer_bind(&renderer->main_buffer, monitor_box.width, monitor_box.height); + render_whole_output(renderer, wlr_output, &fake_damage, &buffer->texture); + fx_framebuffer_bind(&renderer->main_buffer); pixman_region32_fini(&fake_damage); @@ -630,11 +685,25 @@ void render_rounded_rect(struct sway_output *output, pixman_region32_t *output_d goto damage_finish; } + float matrix[9]; + wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0, + wlr_output->transform_matrix); + + enum wl_output_transform transform = wlr_output_transform_invert(wlr_output->transform); + + // ensure the box is updated as per the output orientation + struct wlr_box transformed_box; + int width, height; + wlr_output_transformed_resolution(wlr_output, &width, &height); + wlr_box_transform(&transformed_box, &box, transform, width, height); + + corner_location = get_rotated_corner(corner_location, transform); + int nrects; pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); for (int i = 0; i < nrects; ++i) { scissor_output(wlr_output, &rects[i]); - fx_render_rounded_rect(renderer, &box, color, wlr_output->transform_matrix, + fx_render_rounded_rect(renderer, &transformed_box, color, matrix, corner_radius, corner_location); } @@ -661,11 +730,25 @@ void render_border_corner(struct sway_output *output, pixman_region32_t *output_ goto damage_finish; } + float matrix[9]; + wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0, + wlr_output->transform_matrix); + + enum wl_output_transform transform = wlr_output_transform_invert(wlr_output->transform); + + // ensure the box is updated as per the output orientation + struct wlr_box transformed_box; + int width, height; + wlr_output_transformed_resolution(wlr_output, &width, &height); + wlr_box_transform(&transformed_box, &box, transform, width, height); + + corner_location = get_rotated_corner(corner_location, transform); + int nrects; pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); for (int i = 0; i < nrects; ++i) { scissor_output(wlr_output, &rects[i]); - fx_render_border_corner(renderer, &box, color, wlr_output->transform_matrix, + fx_render_border_corner(renderer, &transformed_box, color, matrix, corner_location, corner_radius, border_thickness); } @@ -694,7 +777,8 @@ static void render_view_toplevels(struct sway_view *view, struct sway_output *ou clip_box.y = state.y - output->ly; clip_box.width = state.width; clip_box.height = state.height; - if (state.border == B_PIXEL || state.border == B_NORMAL) { + if (state.fullscreen_mode == FULLSCREEN_NONE + && (state.border == B_PIXEL || state.border == B_NORMAL)) { clip_box.x += state.border_thickness; clip_box.y += state.border_thickness; clip_box.width -= state.border_thickness * 2; @@ -782,8 +866,9 @@ static void render_saved_view(struct sway_view *view, struct sway_output *output pixman_region32_union_rect(&opaque_region, &opaque_region, 0, 0, 0, 0); struct wlr_box monitor_box = get_monitor_box(wlr_output); - // TODO: contribute wlroots function to allow creating an fbox from a box? - struct wlr_fbox src_box = { monitor_box.x, monitor_box.y, monitor_box.width, monitor_box.height }; + wlr_box_transform(&monitor_box, &monitor_box, + wlr_output_transform_invert(wlr_output->transform), monitor_box.width, monitor_box.height); + struct wlr_fbox src_box = wlr_fbox_from_wlr_box(&monitor_box); bool should_optimize_blur = !container_is_floating(con); render_blur(should_optimize_blur, output, damage, &src_box, &dst_box, &opaque_region, saved_buf->width, saved_buf->height, 1, deco_data.corner_radius); @@ -1824,9 +1909,6 @@ void output_render(struct sway_output *output, struct timespec *when, struct wlr_output *wlr_output = output->wlr_output; struct fx_renderer *renderer = output->renderer; - int width, height; - wlr_output_transformed_resolution(wlr_output, &width, &height); - struct sway_workspace *workspace = output->current.active_workspace; if (workspace == NULL) { return; @@ -1837,6 +1919,16 @@ void output_render(struct sway_output *output, struct timespec *when, fullscreen_con = workspace->current.fullscreen; } + + struct wlr_box monitor_box = get_monitor_box(wlr_output); + wlr_box_transform(&monitor_box, &monitor_box, + wlr_output_transform_invert(wlr_output->transform), + monitor_box.width, monitor_box.height); + + fx_renderer_begin(renderer, monitor_box.width, monitor_box.height); + + int width, height; + wlr_output_transformed_resolution(wlr_output, &width, &height); if (debug.damage == DAMAGE_RERENDER) { pixman_region32_union_rect(damage, damage, 0, 0, width, height); } @@ -1880,8 +1972,6 @@ void output_render(struct sway_output *output, struct timespec *when, fx_renderer_clear((float[]){1, 1, 0, 1}); } - fx_renderer_begin(renderer, output); - if (!damage_not_empty) { // Output isn't damaged but needs buffer swap goto renderer_end; @@ -2025,7 +2115,7 @@ render_overlay: renderer_end: // Draw the contents of our buffer into the wlr buffer - fx_framebuffer_bind(&renderer->wlr_buffer, width, height); + fx_framebuffer_bind(&renderer->wlr_buffer); float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; if (pixman_region32_not_empty(&extended_damage)) { int nrects; @@ -2035,7 +2125,7 @@ renderer_end: fx_renderer_clear(clear_color); } } - render_whole_output(renderer, &extended_damage, &renderer->main_buffer.texture); + render_whole_output(renderer, wlr_output, &extended_damage, &renderer->main_buffer.texture); fx_renderer_scissor(NULL); fx_renderer_end(renderer);