diff options
| -rw-r--r-- | examples/multi-pointer.c | 2 | ||||
| -rw-r--r-- | examples/output-layout.c | 2 | ||||
| -rw-r--r-- | examples/pointer.c | 2 | ||||
| -rw-r--r-- | examples/rotation.c | 2 | ||||
| -rw-r--r-- | examples/simple.c | 2 | ||||
| -rw-r--r-- | examples/tablet.c | 2 | ||||
| -rw-r--r-- | examples/touch.c | 2 | ||||
| -rw-r--r-- | include/wlr/types/wlr_output.h | 9 | ||||
| -rw-r--r-- | rootston/output.c | 2 | ||||
| -rw-r--r-- | types/wlr_output.c | 82 | 
10 files changed, 74 insertions, 33 deletions
diff --git a/examples/multi-pointer.c b/examples/multi-pointer.c index 62aa1bac..d5297aef 100644 --- a/examples/multi-pointer.c +++ b/examples/multi-pointer.c @@ -62,7 +62,7 @@ static void handle_output_frame(struct output_state *output,  		sample->clear_color[2], sample->clear_color[3]);  	glClear(GL_COLOR_BUFFER_BIT); -	wlr_output_swap_buffers(wlr_output); +	wlr_output_swap_buffers(wlr_output, NULL, NULL);  }  static void handle_output_add(struct output_state *ostate) { diff --git a/examples/output-layout.c b/examples/output-layout.c index 35ed22a8..825e97d1 100644 --- a/examples/output-layout.c +++ b/examples/output-layout.c @@ -125,7 +125,7 @@ static void handle_output_frame(struct output_state *output,  	}  	wlr_renderer_end(sample->renderer); -	wlr_output_swap_buffers(wlr_output); +	wlr_output_swap_buffers(wlr_output, NULL, NULL);  }  static void handle_output_add(struct output_state *ostate) { diff --git a/examples/pointer.c b/examples/pointer.c index 9894e311..8b0993e5 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -91,7 +91,7 @@ static void handle_output_frame(struct output_state *output,  		sample->clear_color[2], sample->clear_color[3]);  	glClear(GL_COLOR_BUFFER_BIT); -	wlr_output_swap_buffers(wlr_output); +	wlr_output_swap_buffers(wlr_output, NULL, NULL);  }  static void handle_output_add(struct output_state *ostate) { diff --git a/examples/rotation.c b/examples/rotation.c index 1d974025..6fa06dcc 100644 --- a/examples/rotation.c +++ b/examples/rotation.c @@ -56,7 +56,7 @@ static void handle_output_frame(struct output_state *output, struct timespec *ts  	}  	wlr_renderer_end(sample->renderer); -	wlr_output_swap_buffers(wlr_output); +	wlr_output_swap_buffers(wlr_output, NULL, NULL);  	long ms = (ts->tv_sec - output->last_frame.tv_sec) * 1000 +  		(ts->tv_nsec - output->last_frame.tv_nsec) / 1000000; diff --git a/examples/simple.c b/examples/simple.c index 95c056c8..f788618d 100644 --- a/examples/simple.c +++ b/examples/simple.c @@ -40,7 +40,7 @@ void handle_output_frame(struct output_state *output, struct timespec *ts) {  	glClearColor(sample->color[0], sample->color[1], sample->color[2], 1.0);  	glClear(GL_COLOR_BUFFER_BIT); -	wlr_output_swap_buffers(output->output); +	wlr_output_swap_buffers(output->output, NULL, NULL);  }  int main() { diff --git a/examples/tablet.c b/examples/tablet.c index f3cd5339..5498c9ff 100644 --- a/examples/tablet.c +++ b/examples/tablet.c @@ -76,7 +76,7 @@ static void handle_output_frame(struct output_state *output, struct timespec *ts  	}  	wlr_renderer_end(sample->renderer); -	wlr_output_swap_buffers(wlr_output); +	wlr_output_swap_buffers(wlr_output, NULL, NULL);  }  static void handle_tool_axis(struct tablet_tool_state *tstate, diff --git a/examples/touch.c b/examples/touch.c index 4c1f97b6..5c778743 100644 --- a/examples/touch.c +++ b/examples/touch.c @@ -56,7 +56,7 @@ static void handle_output_frame(struct output_state *output, struct timespec *ts  	}  	wlr_renderer_end(sample->renderer); -	wlr_output_swap_buffers(wlr_output); +	wlr_output_swap_buffers(wlr_output, NULL, NULL);  }  static void handle_touch_down(struct touch_state *tstate, int32_t touch_id, diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 2c28e82f..1091ee62 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -2,6 +2,7 @@  #define WLR_TYPES_WLR_OUTPUT_H  #include <stdbool.h> +#include <time.h>  #include <pixman.h>  #include <wayland-util.h>  #include <wayland-server.h> @@ -103,7 +104,13 @@ void wlr_output_destroy(struct wlr_output *output);  void wlr_output_effective_resolution(struct wlr_output *output,  	int *width, int *height);  void wlr_output_make_current(struct wlr_output *output); -void wlr_output_swap_buffers(struct wlr_output *output); +/** + * Swaps the output buffers. If the time of the frame isn't known, set `when` to + * NULL. If the compositor doesn't support damage tracking, set `damage` to + * NULL. + */ +void wlr_output_swap_buffers(struct wlr_output *output, struct timespec *when, +	pixman_region32_t *damage);  void wlr_output_set_gamma(struct wlr_output *output,  	uint32_t size, uint16_t *r, uint16_t *g, uint16_t *b);  uint32_t wlr_output_get_gamma_size(struct wlr_output *output); diff --git a/rootston/output.c b/rootston/output.c index a1448917..93d74703 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -374,7 +374,7 @@ static void render_output(struct roots_output *output) {  renderer_end:  	glDisable(GL_SCISSOR_TEST);  	wlr_renderer_end(server->renderer); -	wlr_output_swap_buffers(wlr_output); +	wlr_output_swap_buffers(wlr_output, &now, &damage);  	output->frame_scheduled = true;  	pixman_region32_copy(&output->previous_damage, &output->damage);  	pixman_region32_clear(&output->damage); diff --git a/types/wlr_output.c b/types/wlr_output.c index bf02967c..55ee1cb3 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -408,7 +408,7 @@ static void output_cursor_get_box(struct wlr_output_cursor *cursor,  }  static void output_cursor_render(struct wlr_output_cursor *cursor, -		const struct timespec *when) { +		const struct timespec *when, pixman_region32_t *damage) {  	struct wlr_texture *texture = cursor->texture;  	struct wlr_renderer *renderer = cursor->renderer;  	if (cursor->surface != NULL) { @@ -420,13 +420,22 @@ static void output_cursor_render(struct wlr_output_cursor *cursor,  		return;  	} +	struct wlr_box box; +	output_cursor_get_box(cursor, &box); + +	pixman_region32_t surface_damage; +	pixman_region32_init(&surface_damage); +	pixman_region32_union_rect(&surface_damage, &surface_damage, box.x, box.y, +		box.width, box.height); +	pixman_region32_intersect(&surface_damage, &surface_damage, damage); +	if (!pixman_region32_not_empty(&surface_damage)) { +		goto surface_damage_finish; +	} +  	glViewport(0, 0, cursor->output->width, cursor->output->height);  	glEnable(GL_BLEND);  	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -	struct wlr_box box; -	output_cursor_get_box(cursor, &box); -  	float translate[16];  	wlr_matrix_translate(&translate, box.x, box.y, 0); @@ -439,43 +448,68 @@ static void output_cursor_render(struct wlr_output_cursor *cursor,  	wlr_render_with_matrix(renderer, texture, &matrix); +	int nrects; +	pixman_box32_t *rects = pixman_region32_rectangles(&surface_damage, &nrects); +	glEnable(GL_SCISSOR_TEST); +	for (int i = 0; i < nrects; ++i) { +		glScissor(rects[i].x1, cursor->output->height - rects[i].y2, +			rects[i].x2 - rects[i].x1, rects[i].y2 - rects[i].y1); +		wlr_render_with_matrix(renderer, texture, &matrix); +	} +	glDisable(GL_SCISSOR_TEST); +  	if (cursor->surface != NULL) {  		wlr_surface_send_frame_done(cursor->surface, when);  	} + +surface_damage_finish: +	pixman_region32_fini(&surface_damage);  } -void wlr_output_swap_buffers(struct wlr_output *output) { -	wl_signal_emit(&output->events.swap_buffers, &output); +void wlr_output_swap_buffers(struct wlr_output *output, struct timespec *when, +		pixman_region32_t *damage) { +	wl_signal_emit(&output->events.swap_buffers, damage); -	struct timespec now; -	clock_gettime(CLOCK_MONOTONIC, &now); +	pixman_region32_t *render_damage = damage; +	if (damage == NULL) { +		pixman_region32_t output_damage; +		pixman_region32_init(&output_damage); +		pixman_region32_copy(&output_damage, &output->damage); +		pixman_region32_union(&output_damage, &output_damage, +			&output->previous_damage); +		render_damage = &output_damage; +	} -	if (output->fullscreen_surface != NULL) { -		pixman_region32_t damage; -		pixman_region32_init(&damage); -		pixman_region32_copy(&damage, &output->damage); -		pixman_region32_union(&damage, &damage, &output->previous_damage); +	if (when == NULL) { +		struct timespec now; +		clock_gettime(CLOCK_MONOTONIC, &now); +		when = &now; +	} -		if (pixman_region32_not_empty(&damage)) { +	if (pixman_region32_not_empty(render_damage)) { +		if (output->fullscreen_surface != NULL) {  			output_fullscreen_surface_render(output, output->fullscreen_surface, -				&now, &damage); +				when, render_damage);  		} -		pixman_region32_fini(&damage); -	} - -	struct wlr_output_cursor *cursor; -	wl_list_for_each(cursor, &output->cursors, link) { -		if (!cursor->enabled || !cursor->visible || -				output->hardware_cursor == cursor) { -			continue; +		struct wlr_output_cursor *cursor; +		wl_list_for_each(cursor, &output->cursors, link) { +			if (!cursor->enabled || !cursor->visible || +					output->hardware_cursor == cursor) { +				continue; +			} +			output_cursor_render(cursor, when, render_damage);  		} -		output_cursor_render(cursor, &now);  	} +	// TODO: provide `damage` (not `render_damage`) to backend  	output->impl->swap_buffers(output);  	pixman_region32_copy(&output->previous_damage, &output->damage);  	pixman_region32_clear(&output->damage); + +	if (damage == NULL) { +		pixman_region32_fini(render_damage); +	}  }  void wlr_output_set_gamma(struct wlr_output *output,  | 
