aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/multi-pointer.c2
-rw-r--r--examples/output-layout.c2
-rw-r--r--examples/pointer.c2
-rw-r--r--examples/rotation.c2
-rw-r--r--examples/simple.c2
-rw-r--r--examples/tablet.c2
-rw-r--r--examples/touch.c2
-rw-r--r--include/wlr/types/wlr_output.h9
-rw-r--r--rootston/output.c2
-rw-r--r--types/wlr_output.c82
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,