diff options
| -rw-r--r-- | include/sway/desktop/fx_renderer.h | 12 | ||||
| -rw-r--r-- | sway/desktop/fx_renderer.c | 21 | ||||
| -rw-r--r-- | sway/desktop/render.c | 213 | 
3 files changed, 132 insertions, 114 deletions
diff --git a/include/sway/desktop/fx_renderer.h b/include/sway/desktop/fx_renderer.h index d1fd9a3f..05b4458d 100644 --- a/include/sway/desktop/fx_renderer.h +++ b/include/sway/desktop/fx_renderer.h @@ -7,6 +7,13 @@  enum corner_location { ALL, TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT }; +struct decoration_data { +	float alpha; +	float saturation; +	int corner_radius; +	bool has_titlebar; +}; +  struct gles2_tex_shader {  	GLuint program;  	GLint proj; @@ -91,11 +98,10 @@ 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 *src_box, const struct wlr_box *dst_box, const float matrix[static 9], -		float alpha, int radius, float saturation, const bool has_titlebar); +		struct decoration_data deco_data);  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, float saturation, -		const bool has_titlebar); +		const struct wlr_box *dst_box, const float matrix[static 9], struct decoration_data deco_data);  void fx_render_rect(struct fx_renderer *renderer, const struct wlr_box *box,  		const float color[static 4], const float projection[static 9]); diff --git a/sway/desktop/fx_renderer.c b/sway/desktop/fx_renderer.c index ebaa5669..a8dfa561 100644 --- a/sway/desktop/fx_renderer.c +++ b/sway/desktop/fx_renderer.c @@ -295,7 +295,7 @@ 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 *src_box, const struct wlr_box *dst_box, const float matrix[static 9], -		float alpha, int radius, float saturation, const bool has_titlebar) { +		struct decoration_data deco_data) {  	assert(wlr_texture_is_gles2(wlr_texture));  	struct wlr_gles2_texture_attribs texture_attrs;  	wlr_gles2_texture_get_attribs(wlr_texture, &texture_attrs); @@ -332,7 +332,7 @@ bool fx_render_subtexture_with_matrix(struct fx_renderer *renderer, struct wlr_t  	wlr_matrix_transpose(gl_matrix, gl_matrix);  	// if there's no opacity or rounded corners we don't need to blend -	if (!texture_attrs.has_alpha && alpha == 1.0 && !radius) { +	if (!texture_attrs.has_alpha && deco_data.alpha == 1.0 && !deco_data.corner_radius) {  		glDisable(GL_BLEND);  	} else {  		glEnable(GL_BLEND); @@ -347,14 +347,12 @@ bool fx_render_subtexture_with_matrix(struct fx_renderer *renderer, struct wlr_t  	glUniformMatrix3fv(shader->proj, 1, GL_FALSE, gl_matrix);  	glUniform1i(shader->tex, 0); -	glUniform1f(shader->alpha, alpha); -	glUniform1f(shader->has_titlebar, has_titlebar); -	glUniform1f(shader->saturation, saturation); - -	// rounded corners  	glUniform2f(shader->size, dst_box->width, dst_box->height);  	glUniform2f(shader->position, dst_box->x, dst_box->y); -	glUniform1f(shader->radius, radius); +	glUniform1f(shader->alpha, deco_data.alpha); +	glUniform1f(shader->has_titlebar, deco_data.has_titlebar); +	glUniform1f(shader->saturation, deco_data.saturation); +	glUniform1f(shader->radius, deco_data.corner_radius);  	const GLfloat x1 = src_box->x / wlr_texture->width;  	const GLfloat y1 = src_box->y / wlr_texture->height; @@ -384,15 +382,16 @@ bool fx_render_subtexture_with_matrix(struct fx_renderer *renderer, struct wlr_t  }  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, -		float saturation, const bool has_titlebar) { +		const struct wlr_box *dst_box, const float matrix[static 9], +		struct decoration_data deco_data) {  	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, &src_box, dst_box, matrix, alpha, radius, saturation, has_titlebar); +	return fx_render_subtexture_with_matrix(renderer, wlr_texture, &src_box, +			dst_box, matrix, deco_data);  }  void fx_render_rect(struct fx_renderer *renderer, const struct wlr_box *box, diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 076b02cd..d19ccd04 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -32,13 +32,19 @@  struct render_data {  	pixman_region32_t *damage; -	float alpha; -	float saturation; -	int corner_radius; -	bool has_titlebar;  	struct wlr_box *clip_box; +	struct decoration_data deco_data;  }; +struct decoration_data get_undecorated_decoration_data() { +	return (struct decoration_data) { +		.alpha = 1.0f, +		.corner_radius = 0, +		.saturation = 1.0f, +		.has_titlebar = false, +	}; +} +  /**   * Apply scale to a width or height.   * @@ -105,7 +111,7 @@ static void set_scale_filter(struct wlr_output *wlr_output,  static void render_texture(struct wlr_output *wlr_output,  		pixman_region32_t *output_damage, struct wlr_texture *texture,  		const struct wlr_fbox *src_box, const struct wlr_box *dst_box, -		const float matrix[static 9], float alpha, int corner_radius, float saturation, bool has_titlebar) { +		const float matrix[static 9], struct decoration_data deco_data) {  	struct sway_output *output = wlr_output->data;  	struct fx_renderer *renderer = output->server->renderer; @@ -125,11 +131,10 @@ 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, dst_box, matrix, -					alpha, corner_radius, saturation, has_titlebar); +			fx_render_subtexture_with_matrix(renderer, texture, src_box, dst_box, +					matrix, deco_data);  		} else { -			fx_render_texture_with_matrix(renderer, texture, dst_box, matrix, -					alpha, corner_radius, saturation, has_titlebar); +			fx_render_texture_with_matrix(renderer, texture, dst_box, matrix, deco_data);  		}  	} @@ -143,10 +148,6 @@ static void render_surface_iterator(struct sway_output *output,  	struct render_data *data = _data;  	struct wlr_output *wlr_output = output->wlr_output;  	pixman_region32_t *output_damage = data->damage; -	float alpha = data->alpha; -	float saturation = data->saturation; -	int corner_radius = data->corner_radius; -	bool has_titlebar = data->has_titlebar;  	struct wlr_texture *texture = wlr_surface_get_texture(surface);  	if (!texture) { @@ -173,8 +174,9 @@ static void render_surface_iterator(struct sway_output *output,  	}  	scale_box(&dst_box, wlr_output->scale); +	data->deco_data.corner_radius *= wlr_output->scale;  	render_texture(wlr_output, output_damage, texture, &src_box, &dst_box, -		matrix, alpha, corner_radius * wlr_output->scale, saturation,  has_titlebar); +		matrix, data->deco_data);  	wlr_presentation_surface_sampled_on_output(server.presentation, surface,  		wlr_output); @@ -184,10 +186,7 @@ static void render_layer_toplevel(struct sway_output *output,  		pixman_region32_t *damage, struct wl_list *layer_surfaces) {  	struct render_data data = {  		.damage = damage, -		.alpha = 1.0f, -		.saturation = 1.0f, -		.corner_radius = 0, -		.has_titlebar = false, +		.deco_data = get_undecorated_decoration_data(),  	};  	output_layer_for_each_toplevel_surface(output, layer_surfaces,  		render_surface_iterator, &data); @@ -197,10 +196,7 @@ static void render_layer_popups(struct sway_output *output,  		pixman_region32_t *damage, struct wl_list *layer_surfaces) {  	struct render_data data = {  		.damage = damage, -		.alpha = 1.0f, -		.saturation = 1.0f, -		.corner_radius = 0, -		.has_titlebar = false, +		.deco_data = get_undecorated_decoration_data(),  	};  	output_layer_for_each_popup_surface(output, layer_surfaces,  		render_surface_iterator, &data); @@ -211,10 +207,7 @@ static void render_unmanaged(struct sway_output *output,  		pixman_region32_t *damage, struct wl_list *unmanaged) {  	struct render_data data = {  		.damage = damage, -		.alpha = 1.0f, -		.saturation = 1.0f, -		.corner_radius = 0, -		.has_titlebar = false, +		.deco_data = get_undecorated_decoration_data(),  	};  	output_unmanaged_for_each_surface(output, unmanaged,  		render_surface_iterator, &data); @@ -225,10 +218,7 @@ static void render_drag_icons(struct sway_output *output,  		pixman_region32_t *damage, struct wl_list *drag_icons) {  	struct render_data data = {  		.damage = damage, -		.alpha = 1.0f, -		.saturation = 1.0f, -		.corner_radius = 0, -		.has_titlebar = false, +		.deco_data = get_undecorated_decoration_data(),  	};  	output_drag_icons_for_each_surface(output, drag_icons,  		render_surface_iterator, &data); @@ -344,14 +334,10 @@ void premultiply_alpha(float color[4], float opacity) {  }  static void render_view_toplevels(struct sway_view *view, struct sway_output *output, -		pixman_region32_t *damage, float alpha, int corner_radius, -		float saturation, bool has_titlebar) { +		pixman_region32_t *damage, struct decoration_data deco_data) {  	struct render_data data = {  		.damage = damage, -		.alpha = alpha, -		.saturation = saturation, -		.corner_radius = corner_radius, -		.has_titlebar = has_titlebar, +		.deco_data = deco_data,  	};  	struct wlr_box clip_box;  	if (!container_is_current_floating(view->container)) { @@ -371,22 +357,17 @@ static void render_view_toplevels(struct sway_view *view, struct sway_output *ou  }  static void render_view_popups(struct sway_view *view, struct sway_output *output, -		pixman_region32_t *damage, float alpha, int corner_radius, -		float saturation, bool has_titlebar) { +		pixman_region32_t *damage, struct decoration_data deco_data) {  	struct render_data data = {  		.damage = damage, -		.alpha = alpha, -		.saturation = saturation, -		.corner_radius = corner_radius, -		.has_titlebar = has_titlebar, +		.deco_data = deco_data,  	};  	output_view_for_each_popup_surface(output, view,  		render_surface_iterator, &data);  }  static void render_saved_view(struct sway_view *view, struct sway_output *output, -		pixman_region32_t *damage, float alpha, int corner_radius, -		float saturation, bool has_titlebar) { +		pixman_region32_t *damage, struct decoration_data deco_data) {  	struct wlr_output *wlr_output = output->wlr_output;  	if (wl_list_empty(&view->saved_buffers)) { @@ -437,9 +418,9 @@ static void render_saved_view(struct sway_view *view, struct sway_output *output  		}  		scale_box(&dst_box, wlr_output->scale); +		deco_data.corner_radius *= wlr_output->scale;  		render_texture(wlr_output, damage, saved_buf->buffer->texture, -			&saved_buf->source_box, &dst_box, matrix, alpha, corner_radius * wlr_output->scale, -			saturation, has_titlebar); +				&saved_buf->source_box, &dst_box, matrix, deco_data);  	}  	// FIXME: we should set the surface that this saved buffer originates from @@ -451,14 +432,13 @@ static void render_saved_view(struct sway_view *view, struct sway_output *output   * Render a view's surface and left/bottom/right borders.   */  static void render_view(struct sway_output *output, pixman_region32_t *damage, -		struct sway_container *con, struct border_colors *colors, bool has_titlebar) { +		struct sway_container *con, struct border_colors *colors, +		struct decoration_data deco_data) {  	struct sway_view *view = con->view;  	if (!wl_list_empty(&view->saved_buffers)) { -		render_saved_view(view, output, damage, con->alpha, con->corner_radius, -				con->saturation, has_titlebar); +		render_saved_view(view, output, damage, deco_data);  	} else if (view->surface) { -		render_view_toplevels(view, output, damage, con->alpha, con->corner_radius, -				con->saturation, has_titlebar); +		render_view_toplevels(view, output, damage, deco_data);  	}  	if (con->current.border == B_NONE || con->current.border == B_CSD) { @@ -472,18 +452,18 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,  	if (state->border_left) {  		memcpy(&color, colors->child_border, sizeof(float) * 4); -		premultiply_alpha(color, con->alpha); +		premultiply_alpha(color, deco_data.alpha);  		box.x = floor(state->x);  		box.y = floor(state->content_y);  		box.width = state->border_thickness;  		box.height = state->content_height;  		// adjust sizing for rounded border corners -		if (con->corner_radius) { -			if (!has_titlebar) { -				box.y += con->corner_radius; -				box.height -= 2 * con->corner_radius; +		if (deco_data.corner_radius) { +			if (!deco_data.has_titlebar) { +				box.y += deco_data.corner_radius; +				box.height -= 2 * deco_data.corner_radius;  			} else { -				box.height -= con->corner_radius; +				box.height -= deco_data.corner_radius;  			}  		}  		scale_box(&box, output_scale); @@ -500,18 +480,18 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,  		} else {  			memcpy(&color, colors->child_border, sizeof(float) * 4);  		} -		premultiply_alpha(color, con->alpha); +		premultiply_alpha(color, deco_data.alpha);  		box.x = floor(state->content_x + state->content_width);  		box.y = floor(state->content_y);  		box.width = state->border_thickness;  		box.height = state->content_height;  		// adjust sizing for rounded border corners -		if (con->corner_radius) { -			if (!has_titlebar) { -				box.y += con->corner_radius; -				box.height -= 2 * con->corner_radius; +		if (deco_data.corner_radius) { +			if (!deco_data.has_titlebar) { +				box.y += deco_data.corner_radius; +				box.height -= 2 * deco_data.corner_radius;  			} else { -				box.height -= con->corner_radius; +				box.height -= deco_data.corner_radius;  			}  		}  		scale_box(&box, output_scale); @@ -524,24 +504,24 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,  		} else {  			memcpy(&color, colors->child_border, sizeof(float) * 4);  		} -		premultiply_alpha(color, con->alpha); +		premultiply_alpha(color, deco_data.alpha);  		box.x = floor(state->x);  		box.y = floor(state->content_y + state->content_height);  		box.width = state->width;  		box.height = state->border_thickness;  		// adjust sizing for rounded border corners -		if (con->corner_radius) { -			box.x += con->corner_radius; -			box.width -= 2 * con->corner_radius; +		if (deco_data.corner_radius) { +			box.x += deco_data.corner_radius; +			box.width -= 2 * deco_data.corner_radius;  		}  		scale_box(&box, output_scale);  		render_rect(output, damage, &box, color);  		// rounded bottom left & bottom right border corners -		if (con->corner_radius) { -			int size = 2 * (con->corner_radius + state->border_thickness); +		if (deco_data.corner_radius) { +			int size = 2 * (deco_data.corner_radius + state->border_thickness);  			int scaled_thickness = state->border_thickness * output_scale; -			int scaled_corner_radius = con->corner_radius * output_scale; +			int scaled_corner_radius = deco_data.corner_radius * output_scale;  			if (state->border_left) {  				box.width = size;  				box.height = size; @@ -659,6 +639,10 @@ static void render_titlebar(struct sway_output *output,  			(titlebar_v_padding - titlebar_border_thickness) * 2 +  			config->font_height, bg_y, output_scale); +	// title marks textures should have no eyecandy +	struct decoration_data deco_data = get_undecorated_decoration_data(); +	deco_data.alpha = con->alpha; +  	// Marks  	int ob_marks_x = 0; // output-buffer-local  	int ob_marks_width = 0; // output-buffer-local @@ -696,7 +680,7 @@ static void render_titlebar(struct sway_output *output,  			texture_box.width = ob_inner_width;  		}  		render_texture(output->wlr_output, output_damage, marks_texture, -			NULL, &texture_box, matrix, con->alpha, 0, 1.0f, false); +			NULL, &texture_box, matrix, deco_data);  		// Padding above  		memcpy(&color, colors->background, sizeof(float) * 4); @@ -772,7 +756,7 @@ static void render_titlebar(struct sway_output *output,  		}  		render_texture(output->wlr_output, output_damage, title_texture, -			NULL, &texture_box, matrix, con->alpha, 0, 1.0f, false); +			NULL, &texture_box, matrix, deco_data);  		// Padding above  		memcpy(&color, colors->background, sizeof(float) * 4); @@ -863,9 +847,8 @@ static void render_titlebar(struct sway_output *output,   * Render the top border line for a view using "border pixel".   */  static void render_top_border(struct sway_output *output, -		pixman_region32_t *output_damage, struct sway_container *con, -		struct border_colors *colors) { -	struct sway_container_state *state = &con->current; +		pixman_region32_t *output_damage, struct sway_container_state *state, +		struct border_colors *colors, float alpha, int corner_radius) {  	if (!state->border_top) {  		return;  	} @@ -875,24 +858,24 @@ static void render_top_border(struct sway_output *output,  	// Child border - top edge  	memcpy(&color, colors->child_border, sizeof(float) * 4); -	premultiply_alpha(color, con->alpha); +	premultiply_alpha(color, alpha);  	box.x = floor(state->x);  	box.y = floor(state->y);  	box.width = state->width;  	box.height = state->border_thickness;  	// adjust sizing for rounded border corners -	if (con->corner_radius) { -		box.x += con->corner_radius; -		box.width -= 2 * con->corner_radius; +	if (corner_radius) { +		box.x += corner_radius; +		box.width -= 2 * corner_radius;  	}  	scale_box(&box, output_scale);  	render_rect(output, output_damage, &box, color);  	// render rounded top corner borders if corner_radius is set > 0 -	if (con->corner_radius) { -		int size = 2 * (con->corner_radius + state->border_thickness); +	if (corner_radius) { +		int size = 2 * (corner_radius + state->border_thickness);  		int scaled_thickness = state->border_thickness * output_scale; -		int scaled_corner_radius = con->corner_radius * output_scale; +		int scaled_corner_radius = corner_radius * output_scale;  		// top left  		if (state->border_left) { @@ -965,13 +948,19 @@ static void render_containers_linear(struct sway_output *output,  			}  			bool has_titlebar = state->border == B_NORMAL; -			render_view(output, damage, child, colors, has_titlebar); +			struct decoration_data deco_data = { +				.alpha = child->alpha, +				.corner_radius = child->corner_radius, +				.saturation = child->saturation, +				.has_titlebar = has_titlebar, +			}; +			render_view(output, damage, child, colors, deco_data);  			if (has_titlebar) {  				render_titlebar(output, damage, child, floor(state->x),  						floor(state->y), state->width, colors,  						title_texture, marks_texture);  			} else if (state->border == B_PIXEL) { -				render_top_border(output, damage, child, colors); +				render_top_border(output, damage, state, colors, child->alpha, child->corner_radius);  			}  		} else {  			render_container(output, damage, child, @@ -1050,7 +1039,13 @@ static void render_containers_tabbed(struct sway_output *output,  	// Render surface and left/right/bottom borders  	if (current->view) { -		render_view(output, damage, current, current_colors, true); +		struct decoration_data deco_data = { +			.alpha = current->alpha, +			.corner_radius = current->corner_radius, +			.saturation = current->saturation, +			.has_titlebar = true, +		}; +		render_view(output, damage, current, current_colors, deco_data);  	} else {  		render_container(output, damage, current,  				parent->focused || current->current.focused); @@ -1113,7 +1108,13 @@ static void render_containers_stacked(struct sway_output *output,  	// Render surface and left/right/bottom borders  	if (current->view) { -		render_view(output, damage, current, current_colors, true); +		struct decoration_data deco_data = { +			.alpha = current->alpha, +			.saturation = current->saturation, +			.corner_radius = current->corner_radius, +			.has_titlebar = true, +		}; +		render_view(output, damage, current, current_colors, deco_data);  	} else {  		render_container(output, damage, current,  				parent->focused || current->current.focused); @@ -1181,6 +1182,7 @@ static void render_workspace(struct sway_output *output,  static void render_floating_container(struct sway_output *soutput,  		pixman_region32_t *damage, struct sway_container *con) { +	struct sway_container_state *state = &con->current;  	if (con->view) {  		struct sway_view *view = con->view;  		struct border_colors *colors; @@ -1191,7 +1193,7 @@ static void render_floating_container(struct sway_output *soutput,  			colors = &config->border_colors.urgent;  			title_texture = con->title_urgent;  			marks_texture = con->marks_urgent; -		} else if (con->current.focused) { +		} else if (state->focused) {  			colors = &config->border_colors.focused;  			title_texture = con->title_focused;  			marks_texture = con->marks_focused; @@ -1201,17 +1203,23 @@ static void render_floating_container(struct sway_output *soutput,  			marks_texture = con->marks_unfocused;  		} -		bool has_titlebar = con->current.border == B_NORMAL; -		render_view(soutput, damage, con, colors, has_titlebar); +		bool has_titlebar = state->border == B_NORMAL; +		struct decoration_data deco_data = { +			.alpha = con->alpha, +			.saturation = con->saturation, +			.corner_radius = con->corner_radius, +			.has_titlebar = has_titlebar, +		}; +		render_view(soutput, damage, con, colors, deco_data);  		if (has_titlebar) { -			render_titlebar(soutput, damage, con, floor(con->current.x), -					floor(con->current.y), con->current.width, colors, +			render_titlebar(soutput, damage, con, floor(state->x), +					floor(state->y), state->width, colors,  					title_texture, marks_texture); -		} else if (con->current.border == B_PIXEL) { -			render_top_border(soutput, damage, con, colors); +		} else if (state->border == B_PIXEL) { +			render_top_border(soutput, damage, state, colors, con->alpha, con->corner_radius);  		}  	} else { -		render_container(soutput, damage, con, con->current.focused); +		render_container(soutput, damage, con, state->focused);  	}  } @@ -1290,12 +1298,12 @@ void output_render(struct sway_output *output, struct timespec *when,  		}  		if (fullscreen_con->view) { +			struct decoration_data deco_data = get_undecorated_decoration_data(); +			deco_data.saturation = fullscreen_con->saturation;  			if (!wl_list_empty(&fullscreen_con->view->saved_buffers)) { -				render_saved_view(fullscreen_con->view, output, damage, 1.0f, 0, -						fullscreen_con->saturation, false); +				render_saved_view(fullscreen_con->view, output, damage, deco_data);  			} else if (fullscreen_con->view->surface) { -				render_view_toplevels(fullscreen_con->view, output, damage, 1.0f, 0, -						fullscreen_con->saturation, false); +				render_view_toplevels(fullscreen_con->view, output, damage, deco_data);  			}  		} else {  			render_container(output, damage, fullscreen_con, @@ -1348,8 +1356,13 @@ void output_render(struct sway_output *output, struct timespec *when,  	struct sway_seat *seat = input_manager_current_seat();  	struct sway_container *focus = seat_get_focused_container(seat);  	if (focus && focus->view) { -		render_view_popups(focus->view, output, damage, focus->alpha, -			focus->corner_radius, focus->saturation, focus->current.border == B_NORMAL); +		struct decoration_data deco_data = { +			.alpha = focus->alpha, +			.corner_radius = focus->corner_radius, +			.saturation = focus->saturation, +			.has_titlebar = focus->current.border == B_NORMAL, +		}; +		render_view_popups(focus->view, output, damage, deco_data);  	}  render_overlay:  | 
