Restructure subsurface handling

Subsurfaces have been handled somewhat incorrectly. With the release of Firefox
87 this happens to trigger a couple of rendering bugs. Damage is not tracked
properly for those subsurfaces.
This commit is contained in:
raichoo 2021-03-28 15:05:08 +00:00
parent 5153eac0d3
commit 0e0ccfbffc
6 changed files with 92 additions and 71 deletions

View File

@ -16,7 +16,6 @@ struct hikari_renderer {
struct wlr_renderer *wlr_renderer;
pixman_region32_t *damage;
struct wlr_box *geometry;
struct timespec *when;
};
void

View File

@ -57,6 +57,7 @@ struct hikari_view {
struct wl_list group_views;
struct wl_list visible_group_views;
struct wl_list visible_server_views;
struct wl_list children;
struct hikari_operation pending_operation;
@ -73,9 +74,13 @@ struct hikari_view {
void (*activate)(struct hikari_view *, bool);
void (*quit)(struct hikari_view *);
void (*constraints)(struct hikari_view *, int *, int *, int *, int *);
struct wl_listener new_subsurface;
};
struct hikari_view_child {
struct wl_list link;
struct wlr_surface *surface;
struct hikari_view *parent;

View File

@ -19,7 +19,6 @@ struct hikari_xdg_view {
struct wl_listener destroy;
struct wl_listener commit;
struct wl_listener new_popup;
struct wl_listener new_subsurface;
struct wl_listener set_title;
struct wl_listener request_fullscreen;
};

View File

@ -484,18 +484,15 @@ render_overlay(struct hikari_renderer *renderer)
#endif
static inline void
render_output(struct hikari_output *output,
pixman_region32_t *damage,
struct timespec *now)
render_output(struct hikari_output *output, pixman_region32_t *damage)
{
struct wlr_output *wlr_output = output->wlr_output;
struct wlr_renderer *wlr_renderer =
wlr_backend_get_renderer(wlr_output->backend);
struct hikari_renderer renderer = { .wlr_output = wlr_output,
.wlr_renderer = wlr_renderer,
.when = now,
.damage = damage };
struct hikari_renderer renderer = {
.wlr_output = wlr_output, .wlr_renderer = wlr_renderer, .damage = damage
};
wlr_renderer_begin(wlr_renderer, wlr_output->width, wlr_output->height);
@ -531,12 +528,15 @@ send_frame_done(struct wlr_surface *surface, int sx, int sy, void *data)
}
static inline void
frame_done(struct hikari_output *output, struct timespec *now)
frame_done(struct hikari_output *output)
{
struct hikari_view *view;
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
wl_list_for_each_reverse (view, &output->views, output_views) {
hikari_node_for_each_surface(
(struct hikari_node *)view, send_frame_done, now);
(struct hikari_node *)view, send_frame_done, &now);
}
#ifdef HAVE_XWAYLAND
@ -545,13 +545,13 @@ frame_done(struct hikari_output *output, struct timespec *now)
&output->unmanaged_xwayland_views,
unmanaged_output_views) {
wlr_surface_for_each_surface(
xwayland_unmanaged_view->surface->surface, send_frame_done, now);
xwayland_unmanaged_view->surface->surface, send_frame_done, &now);
}
#endif
#ifdef HAVE_LAYERSHELL
for (int i = 0; i < 4; i++) {
layer_for_each(&output->layers[i], send_frame_done, now);
layer_for_each(&output->layers[i], send_frame_done, &now);
}
#endif
}
@ -559,25 +559,29 @@ frame_done(struct hikari_output *output, struct timespec *now)
void
hikari_renderer_damage_frame_handler(struct wl_listener *listener, void *data)
{
bool needs_frame;
struct timespec now;
struct hikari_output *output =
wl_container_of(listener, output, damage_frame);
pixman_region32_t buffer_damage;
pixman_region32_init(&buffer_damage);
clock_gettime(CLOCK_MONOTONIC, &now);
if (wlr_output_damage_attach_render(
output->damage, &needs_frame, &buffer_damage) &&
needs_frame) {
render_output(output, &buffer_damage, &now);
bool needs_frame;
if (!wlr_output_damage_attach_render(
output->damage, &needs_frame, &buffer_damage)) {
goto render_done;
}
if (!needs_frame) {
wlr_output_rollback(output->wlr_output);
goto render_done;
}
render_output(output, &buffer_damage);
render_done:
pixman_region32_fini(&buffer_damage);
frame_done(output, &now);
frame_done(output);
}
static inline void

View File

@ -431,6 +431,8 @@ hikari_view_init(
hikari_view_unset_dirty(view);
view->pending_operation.tile = NULL;
wl_list_init(&view->children);
}
void
@ -773,6 +775,19 @@ MOVE(top_middle)
MOVE(top_right)
#undef MOVE
static void
new_subsurface_handler(struct wl_listener *listener, void *data)
{
struct hikari_view *view = wl_container_of(listener, view, new_subsurface);
struct wlr_subsurface *wlr_subsurface = data;
struct hikari_view_subsurface *view_subsurface =
hikari_malloc(sizeof(struct hikari_view_subsurface));
hikari_view_subsurface_init(view_subsurface, view, wlr_subsurface);
}
void
hikari_view_map(struct hikari_view *view, struct wlr_surface *surface)
{
@ -788,6 +803,19 @@ hikari_view_map(struct hikari_view *view, struct wlr_surface *surface)
struct hikari_view_config *view_config =
hikari_configuration_resolve_view_config(hikari_configuration, view->id);
view->surface = surface;
view->new_subsurface.notify = new_subsurface_handler;
wl_signal_add(&surface->events.new_subsurface, &view->new_subsurface);
struct wlr_subsurface *wlr_subsurface;
wl_list_for_each (wlr_subsurface, &surface->subsurfaces, parent_link) {
struct hikari_view_subsurface *subsurface =
(struct hikari_view_subsurface *)malloc(
sizeof(struct hikari_view_subsurface));
hikari_view_subsurface_init(subsurface, view, wlr_subsurface);
}
if (view_config != NULL) {
struct hikari_mark *mark;
struct hikari_view_properties *properties =
@ -809,7 +837,6 @@ hikari_view_map(struct hikari_view *view, struct wlr_surface *surface)
}
view->group = group;
view->surface = surface;
wl_list_insert(&sheet->views, &view->sheet_views);
wl_list_insert(&group->views, &view->group_views);
@ -836,6 +863,16 @@ hikari_view_unmap(struct hikari_view *view)
assert(!hikari_view_is_unmanaged(view));
assert(hikari_view_is_mapped(view));
wl_list_remove(&view->new_subsurface.link);
struct hikari_view_child *child, *child_temp;
wl_list_for_each_safe (child, child_temp, &view->children, link) {
struct hikari_view_subsurface *subsurface =
(struct hikari_view_subsurface *)child;
hikari_view_subsurface_fini(subsurface);
hikari_free(subsurface);
}
if (hikari_view_is_forced(view)) {
if (hikari_view_is_hidden(view)) {
hide(view);
@ -1561,6 +1598,7 @@ hikari_view_subsurface_init(struct hikari_view_subsurface *view_subsurface,
void
hikari_view_child_fini(struct hikari_view_child *view_child)
{
wl_list_remove(&view_child->link);
wl_list_remove(&view_child->commit.link);
wl_list_remove(&view_child->new_subsurface.link);
}
@ -1572,25 +1610,11 @@ hikari_view_subsurface_fini(struct hikari_view_subsurface *view_subsurface)
wl_list_remove(&view_subsurface->destroy.link);
}
static void
new_subsurface_handler(struct wl_listener *listener, void *data)
{
struct hikari_view_child *view_child =
wl_container_of(listener, view_child, new_subsurface);
struct wlr_subsurface *wlr_subsurface = data;
struct hikari_view_subsurface *view_subsurface =
hikari_malloc(sizeof(struct hikari_view_subsurface));
hikari_view_subsurface_init(
view_subsurface, view_child->parent, wlr_subsurface);
}
static void
damage_surface(struct wlr_surface *surface, int sx, int sy, void *data)
{
struct hikari_damage_data *damage_data = data;
struct hikari_output *output = damage_data->output;
if (damage_data->whole) {
damage_whole_surface(surface, sx, sy, data);
@ -1618,18 +1642,32 @@ damage_single_surface(struct wlr_surface *surface, int sx, int sy, void *data)
}
static void
commit_view_child_handler(struct wl_listener *listener, void *data)
commit_child_handler(struct wl_listener *listener, void *data)
{
struct hikari_view_child *view_child =
wl_container_of(listener, view_child, commit);
struct hikari_view *parent = view_child->parent;
assert(!hikari_view_is_hidden(parent));
if (!hikari_view_is_hidden(parent)) {
struct wlr_surface *surface = view_child->surface;
struct wlr_surface *surface = view_child->surface;
hikari_view_damage_surface(parent, surface, false);
}
hikari_view_damage_surface(parent, surface, false);
}
static void
new_subsurface_child_handler(struct wl_listener *listener, void *data)
{
struct hikari_view_child *view_child =
wl_container_of(listener, view_child, new_subsurface);
struct wlr_subsurface *wlr_subsurface = data;
struct hikari_view_subsurface *view_subsurface =
hikari_malloc(sizeof(struct hikari_view_subsurface));
hikari_view_subsurface_init(
view_subsurface, view_child->parent, wlr_subsurface);
}
void
@ -1640,11 +1678,13 @@ hikari_view_child_init(struct hikari_view_child *view_child,
view_child->parent = parent;
view_child->surface = surface;
view_child->new_subsurface.notify = new_subsurface_handler;
view_child->new_subsurface.notify = new_subsurface_child_handler;
wl_signal_add(&surface->events.new_subsurface, &view_child->new_subsurface);
view_child->commit.notify = commit_view_child_handler;
view_child->commit.notify = commit_child_handler;
wl_signal_add(&surface->events.commit, &view_child->commit);
wl_list_insert(&parent->children, &view_child->link);
}
void

View File

@ -26,9 +26,6 @@
static void
new_popup_handler(struct wl_listener *listener, void *data);
static void
new_subsurface_handler(struct wl_listener *listener, void *data);
static void
request_fullscreen_handler(struct wl_listener *listener, void *data);
@ -186,10 +183,6 @@ map(struct hikari_view *view, bool focus)
xdg_view->new_popup.notify = new_popup_handler;
wl_signal_add(&xdg_surface->events.new_popup, &xdg_view->new_popup);
xdg_view->new_subsurface.notify = new_subsurface_handler;
wl_signal_add(
&xdg_surface->surface->events.new_subsurface, &xdg_view->new_subsurface);
xdg_view->commit.notify = commit_handler;
wl_signal_add(&xdg_view->surface->surface->events.commit, &xdg_view->commit);
@ -227,7 +220,6 @@ unmap(struct hikari_view *view)
wl_list_remove(&xdg_view->set_title.link);
wl_list_remove(&xdg_view->request_fullscreen.link);
wl_list_remove(&xdg_view->new_popup.link);
wl_list_remove(&xdg_view->new_subsurface.link);
wl_list_remove(&xdg_view->commit.link);
}
@ -435,24 +427,6 @@ xdg_popup_create(struct wlr_xdg_popup *wlr_popup, struct hikari_view *parent)
popup_unconstrain(popup);
}
static void
new_subsurface_handler(struct wl_listener *listener, void *data)
{
struct hikari_xdg_view *xdg_view =
wl_container_of(listener, xdg_view, new_subsurface);
struct wlr_subsurface *subsurface = data;
struct hikari_view_subsurface *view_subsurface =
hikari_malloc(sizeof(struct hikari_view_subsurface));
hikari_view_subsurface_init(view_subsurface, &xdg_view->view, subsurface);
#if !defined(NDEBUG)
printf("SUBSURFACE\n");
#endif
}
static void
request_fullscreen_handler(struct wl_listener *listener, void *data)
{