rootston: damage tracking for rotated views
This commit is contained in:
		
							parent
							
								
									a011a1cb07
								
							
						
					
					
						commit
						7111dd79ef
					
				| 
						 | 
					@ -164,6 +164,7 @@ void view_move_resize(struct roots_view *view, double x, double y,
 | 
				
			||||||
void view_maximize(struct roots_view *view, bool maximized);
 | 
					void view_maximize(struct roots_view *view, bool maximized);
 | 
				
			||||||
void view_set_fullscreen(struct roots_view *view, bool fullscreen,
 | 
					void view_set_fullscreen(struct roots_view *view, bool fullscreen,
 | 
				
			||||||
	struct wlr_output *output);
 | 
						struct wlr_output *output);
 | 
				
			||||||
 | 
					void view_rotate(struct roots_view *view, float rotation);
 | 
				
			||||||
void view_close(struct roots_view *view);
 | 
					void view_close(struct roots_view *view);
 | 
				
			||||||
bool view_center(struct roots_view *view);
 | 
					bool view_center(struct roots_view *view);
 | 
				
			||||||
void view_setup(struct roots_view *view);
 | 
					void view_setup(struct roots_view *view);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,4 +26,10 @@ void wlr_box_transform(const struct wlr_box *box,
 | 
				
			||||||
	enum wl_output_transform transform, int width, int height,
 | 
						enum wl_output_transform transform, int width, int height,
 | 
				
			||||||
	struct wlr_box *dest);
 | 
						struct wlr_box *dest);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Creates the smallest box that contains a rotated box.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void wlr_box_rotated_bounds(const struct wlr_box *box, float rotation,
 | 
				
			||||||
 | 
						struct wlr_box *dest);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -203,7 +203,7 @@ static void roots_cursor_update_position(struct roots_cursor *cursor,
 | 
				
			||||||
			float angle = atan2(vx*uy - vy*ux, vx*ux + vy*uy);
 | 
								float angle = atan2(vx*uy - vy*ux, vx*ux + vy*uy);
 | 
				
			||||||
			int steps = 12;
 | 
								int steps = 12;
 | 
				
			||||||
			angle = round(angle/M_PI*steps) / (steps/M_PI);
 | 
								angle = round(angle/M_PI*steps) / (steps/M_PI);
 | 
				
			||||||
			view->rotation = cursor->view_rotation + angle;
 | 
								view_rotate(view, cursor->view_rotation + angle);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -200,7 +200,7 @@ void view_maximize(struct roots_view *view, bool maximized) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		view_move_resize(view, output_box->x, output_box->y, output_box->width,
 | 
							view_move_resize(view, output_box->x, output_box->y, output_box->width,
 | 
				
			||||||
			output_box->height);
 | 
								output_box->height);
 | 
				
			||||||
		view->rotation = 0;
 | 
							view_rotate(view, 0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (view->maximized && !maximized) {
 | 
						if (view->maximized && !maximized) {
 | 
				
			||||||
| 
						 | 
					@ -208,7 +208,7 @@ void view_maximize(struct roots_view *view, bool maximized) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		view_move_resize(view, view->saved.x, view->saved.y, view->saved.width,
 | 
							view_move_resize(view, view->saved.x, view->saved.y, view->saved.width,
 | 
				
			||||||
			view->saved.height);
 | 
								view->saved.height);
 | 
				
			||||||
		view->rotation = view->saved.rotation;
 | 
							view_rotate(view, view->saved.rotation);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -249,7 +249,7 @@ void view_set_fullscreen(struct roots_view *view, bool fullscreen,
 | 
				
			||||||
			wlr_output_layout_get_box(view->desktop->layout, output);
 | 
								wlr_output_layout_get_box(view->desktop->layout, output);
 | 
				
			||||||
		view_move_resize(view, output_box->x, output_box->y, output_box->width,
 | 
							view_move_resize(view, output_box->x, output_box->y, output_box->width,
 | 
				
			||||||
			output_box->height);
 | 
								output_box->height);
 | 
				
			||||||
		view->rotation = 0;
 | 
							view_rotate(view, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		roots_output->fullscreen_view = view;
 | 
							roots_output->fullscreen_view = view;
 | 
				
			||||||
		view->fullscreen_output = roots_output;
 | 
							view->fullscreen_output = roots_output;
 | 
				
			||||||
| 
						 | 
					@ -258,13 +258,23 @@ void view_set_fullscreen(struct roots_view *view, bool fullscreen,
 | 
				
			||||||
	if (was_fullscreen && !fullscreen) {
 | 
						if (was_fullscreen && !fullscreen) {
 | 
				
			||||||
		view_move_resize(view, view->saved.x, view->saved.y, view->saved.width,
 | 
							view_move_resize(view, view->saved.x, view->saved.y, view->saved.width,
 | 
				
			||||||
			view->saved.height);
 | 
								view->saved.height);
 | 
				
			||||||
		view->rotation = view->saved.rotation;
 | 
							view_rotate(view, view->saved.rotation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		view->fullscreen_output->fullscreen_view = NULL;
 | 
							view->fullscreen_output->fullscreen_view = NULL;
 | 
				
			||||||
		view->fullscreen_output = NULL;
 | 
							view->fullscreen_output = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void view_rotate(struct roots_view *view, float rotation) {
 | 
				
			||||||
 | 
						if (view->rotation == rotation) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						view_damage_whole(view);
 | 
				
			||||||
 | 
						view->rotation = rotation;
 | 
				
			||||||
 | 
						view_damage_whole(view);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void view_close(struct roots_view *view) {
 | 
					void view_close(struct roots_view *view) {
 | 
				
			||||||
	if (view->close) {
 | 
						if (view->close) {
 | 
				
			||||||
		view->close(view);
 | 
							view->close(view);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -155,7 +155,7 @@ struct render_data {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static bool surface_intersect_output(struct wlr_surface *surface,
 | 
					static bool surface_intersect_output(struct wlr_surface *surface,
 | 
				
			||||||
		struct wlr_output_layout *output_layout, struct wlr_output *wlr_output,
 | 
							struct wlr_output_layout *output_layout, struct wlr_output *wlr_output,
 | 
				
			||||||
		double lx, double ly, struct wlr_box *box) {
 | 
							double lx, double ly, float rotation, struct wlr_box *box) {
 | 
				
			||||||
	double ox = lx, oy = ly;
 | 
						double ox = lx, oy = ly;
 | 
				
			||||||
	wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy);
 | 
						wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy);
 | 
				
			||||||
	box->x = ox * wlr_output->scale;
 | 
						box->x = ox * wlr_output->scale;
 | 
				
			||||||
| 
						 | 
					@ -167,6 +167,7 @@ static bool surface_intersect_output(struct wlr_surface *surface,
 | 
				
			||||||
		.x = lx, .y = ly,
 | 
							.x = lx, .y = ly,
 | 
				
			||||||
		.width = surface->current->width, .height = surface->current->height,
 | 
							.width = surface->current->width, .height = surface->current->height,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
						wlr_box_rotated_bounds(&layout_box, -rotation, &layout_box);
 | 
				
			||||||
	return wlr_output_layout_intersects(output_layout, wlr_output, &layout_box);
 | 
						return wlr_output_layout_intersects(output_layout, wlr_output, &layout_box);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -215,15 +216,18 @@ static void render_surface(struct wlr_surface *surface, double lx, double ly,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wlr_box box;
 | 
						struct wlr_box box;
 | 
				
			||||||
	bool intersects = surface_intersect_output(surface, output->desktop->layout,
 | 
						bool intersects = surface_intersect_output(surface, output->desktop->layout,
 | 
				
			||||||
		output->wlr_output, lx, ly, &box);
 | 
							output->wlr_output, lx, ly, rotation, &box);
 | 
				
			||||||
	if (!intersects) {
 | 
						if (!intersects) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wlr_box rotated;
 | 
				
			||||||
 | 
						wlr_box_rotated_bounds(&box, -rotation, &rotated);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pixman_region32_t damage;
 | 
						pixman_region32_t damage;
 | 
				
			||||||
	pixman_region32_init(&damage);
 | 
						pixman_region32_init(&damage);
 | 
				
			||||||
	pixman_region32_union_rect(&damage, &damage, box.x, box.y,
 | 
						pixman_region32_union_rect(&damage, &damage, rotated.x, rotated.y,
 | 
				
			||||||
		box.width, box.height);
 | 
							rotated.width, rotated.height);
 | 
				
			||||||
	pixman_region32_intersect(&damage, &damage, data->damage);
 | 
						pixman_region32_intersect(&damage, &damage, data->damage);
 | 
				
			||||||
	bool damaged = pixman_region32_not_empty(&damage);
 | 
						bool damaged = pixman_region32_not_empty(&damage);
 | 
				
			||||||
	if (!damaged) {
 | 
						if (!damaged) {
 | 
				
			||||||
| 
						 | 
					@ -415,6 +419,8 @@ static void render_output(struct roots_output *output) {
 | 
				
			||||||
		goto renderer_end;
 | 
							goto renderer_end;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_renderer_clear(output->desktop->server->renderer, 1, 1, 1, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int nrects;
 | 
						int nrects;
 | 
				
			||||||
	pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
 | 
						pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
 | 
				
			||||||
	for (int i = 0; i < nrects; ++i) {
 | 
						for (int i = 0; i < nrects; ++i) {
 | 
				
			||||||
| 
						 | 
					@ -526,12 +532,14 @@ static void damage_whole_surface(struct wlr_surface *surface,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wlr_box box;
 | 
						struct wlr_box box;
 | 
				
			||||||
	bool intersects = surface_intersect_output(surface,
 | 
						bool intersects = surface_intersect_output(surface, output->desktop->layout,
 | 
				
			||||||
		output->desktop->layout, output->wlr_output, lx, ly, &box);
 | 
							output->wlr_output, lx, ly, rotation, &box);
 | 
				
			||||||
	if (!intersects) {
 | 
						if (!intersects) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_box_rotated_bounds(&box, -rotation, &box);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pixman_region32_union_rect(&output->damage, &output->damage,
 | 
						pixman_region32_union_rect(&output->damage, &output->damage,
 | 
				
			||||||
		box.x, box.y, box.width, box.height);
 | 
							box.x, box.y, box.width, box.height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -547,6 +555,8 @@ static void damage_whole_decoration(struct roots_view *view,
 | 
				
			||||||
	struct wlr_box box;
 | 
						struct wlr_box box;
 | 
				
			||||||
	get_decoration_box(view, output, &box);
 | 
						get_decoration_box(view, output, &box);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_box_rotated_bounds(&box, -view->rotation, &box);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pixman_region32_union_rect(&output->damage, &output->damage,
 | 
						pixman_region32_union_rect(&output->damage, &output->damage,
 | 
				
			||||||
		box.x, box.y, box.width, box.height);
 | 
							box.x, box.y, box.width, box.height);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -576,8 +586,8 @@ static void damage_from_surface(struct wlr_surface *surface,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wlr_box box;
 | 
						struct wlr_box box;
 | 
				
			||||||
	bool intersects = surface_intersect_output(surface,
 | 
						bool intersects = surface_intersect_output(surface, output->desktop->layout,
 | 
				
			||||||
		output->desktop->layout, output->wlr_output, lx, ly, &box);
 | 
							output->wlr_output, lx, ly, rotation, &box);
 | 
				
			||||||
	if (!intersects) {
 | 
						if (!intersects) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -599,6 +609,11 @@ void output_damage_from_view(struct roots_output *output,
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (view->rotation != 0) {
 | 
				
			||||||
 | 
							output_damage_whole_view(output, view);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	view_for_each_surface(view, damage_from_surface, output);
 | 
						view_for_each_surface(view, damage_from_surface, output);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -114,3 +114,32 @@ void wlr_box_transform(const struct wlr_box *box,
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_box_rotated_bounds(const struct wlr_box *box, float rotation,
 | 
				
			||||||
 | 
							struct wlr_box *dest) {
 | 
				
			||||||
 | 
						if (rotation == 0) {
 | 
				
			||||||
 | 
							*dest = *box;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						double ox = box->x + (double)box->width/2;
 | 
				
			||||||
 | 
						double oy = box->y + (double)box->height/2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						double c = fabs(cos(rotation));
 | 
				
			||||||
 | 
						double s = fabs(sin(rotation));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						double x1 = ox + (box->x - ox) * c + (box->y - oy) * s;
 | 
				
			||||||
 | 
						double x2 = ox +
 | 
				
			||||||
 | 
							(box->x + box->width - ox) * c +
 | 
				
			||||||
 | 
							(box->y + box->height - oy) * s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						double y1 = oy + (box->x - ox) * s + (box->y - oy) * c;
 | 
				
			||||||
 | 
						double y2 = oy +
 | 
				
			||||||
 | 
							(box->x + box->width - ox) * s +
 | 
				
			||||||
 | 
							(box->y + box->height - oy) * c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dest->x = fmin(x1, x2);
 | 
				
			||||||
 | 
						dest->width = fmax(x1, x2) - fmin(x1, x2);
 | 
				
			||||||
 | 
						dest->y = fmin(y1, y2);
 | 
				
			||||||
 | 
						dest->height = fmax(y1, y2) - fmin(y1, y2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue