output: fix software cursors damage tracking
This commit is contained in:
parent
b296481007
commit
e29a0df8c1
|
@ -62,7 +62,7 @@ static void handle_output_frame(struct output_state *output,
|
||||||
sample->clear_color[2], sample->clear_color[3]);
|
sample->clear_color[2], sample->clear_color[3]);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
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) {
|
static void handle_output_add(struct output_state *ostate) {
|
||||||
|
|
|
@ -125,7 +125,7 @@ static void handle_output_frame(struct output_state *output,
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_renderer_end(sample->renderer);
|
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) {
|
static void handle_output_add(struct output_state *ostate) {
|
||||||
|
|
|
@ -91,7 +91,7 @@ static void handle_output_frame(struct output_state *output,
|
||||||
sample->clear_color[2], sample->clear_color[3]);
|
sample->clear_color[2], sample->clear_color[3]);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
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) {
|
static void handle_output_add(struct output_state *ostate) {
|
||||||
|
|
|
@ -56,7 +56,7 @@ static void handle_output_frame(struct output_state *output, struct timespec *ts
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_renderer_end(sample->renderer);
|
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 +
|
long ms = (ts->tv_sec - output->last_frame.tv_sec) * 1000 +
|
||||||
(ts->tv_nsec - output->last_frame.tv_nsec) / 1000000;
|
(ts->tv_nsec - output->last_frame.tv_nsec) / 1000000;
|
||||||
|
|
|
@ -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);
|
glClearColor(sample->color[0], sample->color[1], sample->color[2], 1.0);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
wlr_output_swap_buffers(output->output);
|
wlr_output_swap_buffers(output->output, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|
|
@ -76,7 +76,7 @@ static void handle_output_frame(struct output_state *output, struct timespec *ts
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_renderer_end(sample->renderer);
|
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,
|
static void handle_tool_axis(struct tablet_tool_state *tstate,
|
||||||
|
|
|
@ -56,7 +56,7 @@ static void handle_output_frame(struct output_state *output, struct timespec *ts
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_renderer_end(sample->renderer);
|
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,
|
static void handle_touch_down(struct touch_state *tstate, int32_t touch_id,
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define WLR_TYPES_WLR_OUTPUT_H
|
#define WLR_TYPES_WLR_OUTPUT_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <time.h>
|
||||||
#include <pixman.h>
|
#include <pixman.h>
|
||||||
#include <wayland-util.h>
|
#include <wayland-util.h>
|
||||||
#include <wayland-server.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,
|
void wlr_output_effective_resolution(struct wlr_output *output,
|
||||||
int *width, int *height);
|
int *width, int *height);
|
||||||
void wlr_output_make_current(struct wlr_output *output);
|
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,
|
void wlr_output_set_gamma(struct wlr_output *output,
|
||||||
uint32_t size, uint16_t *r, uint16_t *g, uint16_t *b);
|
uint32_t size, uint16_t *r, uint16_t *g, uint16_t *b);
|
||||||
uint32_t wlr_output_get_gamma_size(struct wlr_output *output);
|
uint32_t wlr_output_get_gamma_size(struct wlr_output *output);
|
||||||
|
|
|
@ -374,7 +374,7 @@ static void render_output(struct roots_output *output) {
|
||||||
renderer_end:
|
renderer_end:
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
wlr_renderer_end(server->renderer);
|
wlr_renderer_end(server->renderer);
|
||||||
wlr_output_swap_buffers(wlr_output);
|
wlr_output_swap_buffers(wlr_output, &now, &damage);
|
||||||
output->frame_scheduled = true;
|
output->frame_scheduled = true;
|
||||||
pixman_region32_copy(&output->previous_damage, &output->damage);
|
pixman_region32_copy(&output->previous_damage, &output->damage);
|
||||||
pixman_region32_clear(&output->damage);
|
pixman_region32_clear(&output->damage);
|
||||||
|
|
|
@ -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,
|
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_texture *texture = cursor->texture;
|
||||||
struct wlr_renderer *renderer = cursor->renderer;
|
struct wlr_renderer *renderer = cursor->renderer;
|
||||||
if (cursor->surface != NULL) {
|
if (cursor->surface != NULL) {
|
||||||
|
@ -420,13 +420,22 @@ static void output_cursor_render(struct wlr_output_cursor *cursor,
|
||||||
return;
|
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);
|
glViewport(0, 0, cursor->output->width, cursor->output->height);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
struct wlr_box box;
|
|
||||||
output_cursor_get_box(cursor, &box);
|
|
||||||
|
|
||||||
float translate[16];
|
float translate[16];
|
||||||
wlr_matrix_translate(&translate, box.x, box.y, 0);
|
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);
|
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) {
|
if (cursor->surface != NULL) {
|
||||||
wlr_surface_send_frame_done(cursor->surface, when);
|
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) {
|
void wlr_output_swap_buffers(struct wlr_output *output, struct timespec *when,
|
||||||
wl_signal_emit(&output->events.swap_buffers, &output);
|
pixman_region32_t *damage) {
|
||||||
|
wl_signal_emit(&output->events.swap_buffers, damage);
|
||||||
|
|
||||||
struct timespec now;
|
pixman_region32_t *render_damage = damage;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
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) {
|
if (when == NULL) {
|
||||||
pixman_region32_t damage;
|
struct timespec now;
|
||||||
pixman_region32_init(&damage);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
pixman_region32_copy(&damage, &output->damage);
|
when = &now;
|
||||||
pixman_region32_union(&damage, &damage, &output->previous_damage);
|
}
|
||||||
|
|
||||||
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,
|
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 ||
|
||||||
struct wlr_output_cursor *cursor;
|
output->hardware_cursor == cursor) {
|
||||||
wl_list_for_each(cursor, &output->cursors, link) {
|
continue;
|
||||||
if (!cursor->enabled || !cursor->visible ||
|
}
|
||||||
output->hardware_cursor == cursor) {
|
output_cursor_render(cursor, when, render_damage);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
output_cursor_render(cursor, &now);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: provide `damage` (not `render_damage`) to backend
|
||||||
output->impl->swap_buffers(output);
|
output->impl->swap_buffers(output);
|
||||||
pixman_region32_copy(&output->previous_damage, &output->damage);
|
pixman_region32_copy(&output->previous_damage, &output->damage);
|
||||||
pixman_region32_clear(&output->damage);
|
pixman_region32_clear(&output->damage);
|
||||||
|
|
||||||
|
if (damage == NULL) {
|
||||||
|
pixman_region32_fini(render_damage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_output_set_gamma(struct wlr_output *output,
|
void wlr_output_set_gamma(struct wlr_output *output,
|
||||||
|
|
Loading…
Reference in New Issue