Drop redundant manual popup compositing
Popup/menu surfaces are regular wlr_scene_xdg_surface nodes under their parent's tree, so wlroots' scene renderer already composites them into the output buffer like any other surface. The host-side second draw (composite_popups/popup_draw_cb + popup_tex) was a redundant double-blend that predated the scene nodes; with it removed, menus and sub-menus render correctly through the scene path. Keep the popup scene-node wiring, unconstrain, and commit/reposition/destroy listeners.
This commit is contained in:
parent
cc2ddc63c0
commit
b7e1c650dc
1 changed files with 5 additions and 77 deletions
|
|
@ -151,7 +151,6 @@ struct tabbed_host {
|
|||
GLuint gl_program;
|
||||
GLint gl_pos_loc, gl_uv_loc, gl_tex_loc;
|
||||
GLuint import_tex;
|
||||
GLuint popup_tex;
|
||||
/* Present gating: at most one buffer aimed at the host compositor at a
|
||||
time, paced by the host surface's wl_callback. */
|
||||
struct wl_callback *frame_cb;
|
||||
|
|
@ -442,14 +441,6 @@ static bool gl_setup(void) {
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glGenTextures(1, &host.popup_tex);
|
||||
glBindTexture(GL_TEXTURE_2D, host.popup_tex);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -907,17 +898,11 @@ static int app_index(struct tabbed_app *app) {
|
|||
struct tabbed_popup {
|
||||
struct wlr_xdg_surface *xdg_surface;
|
||||
struct wlr_scene_tree *scene;
|
||||
struct wl_list link;
|
||||
struct wl_listener commit;
|
||||
struct wl_listener destroy;
|
||||
struct wl_listener reposition;
|
||||
};
|
||||
|
||||
/* Popups are also drawn by us (host-side) for the presented frame, because
|
||||
wlroots' own premultiplied-alpha rendering of these ARGB menus produces
|
||||
nothing in this nested EGL pipeline. This list tracks the live ones. */
|
||||
static struct wl_list popups = { &popups, &popups };
|
||||
|
||||
/* Enough of the host window for popups to be positioned within; open menus
|
||||
may exceed the toplevel but we keep them inside the visible area. */
|
||||
static void popup_usable_box(struct wlr_box *box) {
|
||||
|
|
@ -932,10 +917,11 @@ static void popup_usable_box(struct wlr_box *box) {
|
|||
}
|
||||
}
|
||||
|
||||
/* Menu popups (e.g. galculator's) submit ARGB buffers that wlroots renders
|
||||
with premultiplied-alpha blending, which produces nothing in this nested
|
||||
EGL pipeline. We therefore draw them ourselves into the presented frame
|
||||
(see composite_popups in blit_scene_buffer). */
|
||||
/* Popups (menus, tooltips) are regular wlr_scene_xdg_surface nodes under
|
||||
their parent's tree, so wlroots' scene renderer composites them into the
|
||||
output buffer like any other surface. We only need to make sure the client
|
||||
gets its initial configure (unconstrain from the output box) and to place
|
||||
each popup under its parent's tree. */
|
||||
static void popup_handle_commit(struct wl_listener *listener, void *data) {
|
||||
(void)data;
|
||||
struct tabbed_popup *tp = wl_container_of(listener, tp, commit);
|
||||
|
|
@ -964,7 +950,6 @@ static void popup_handle_reposition(struct wl_listener *listener, void *data) {
|
|||
static void popup_handle_destroy(struct wl_listener *listener, void *data) {
|
||||
(void)data;
|
||||
struct tabbed_popup *tp = wl_container_of(listener, tp, destroy);
|
||||
wl_list_remove(&tp->link);
|
||||
wl_list_remove(&tp->commit.link);
|
||||
wl_list_remove(&tp->destroy.link);
|
||||
wl_list_remove(&tp->reposition.link);
|
||||
|
|
@ -978,7 +963,6 @@ static void create_popup(struct wlr_xdg_popup *popup,
|
|||
if (!tp) return;
|
||||
tp->xdg_surface = xdg_surface;
|
||||
tp->scene = wlr_scene_xdg_surface_create(parent_tree, xdg_surface);
|
||||
wl_list_insert(&popups, &tp->link);
|
||||
/* wlr_scene_xdg_surface_create destroys the node when the surface is
|
||||
destroyed, so we only track positioning/reposition listeners here. */
|
||||
tp->commit.notify = popup_handle_commit;
|
||||
|
|
@ -2528,60 +2512,6 @@ static bool import_scene_buffer(struct wlr_buffer *buf, GLuint tex) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Draw one popup surface buffer into the presented window at its on-screen
|
||||
position. This bypasses wlroots' scene rendering for popups, whose
|
||||
premultiplied-alpha blend paints nothing in our nested EGL pipeline.
|
||||
|
||||
Each popup surface is composited exactly once per frame. A sub-menu is a
|
||||
popup nested under its parent menu's scene tree, so it is reachable both
|
||||
from its own tree and from the parent menu's tree; the surfaces-drawn array
|
||||
prevents it being drawn twice. Position uses wlr_scene_node_coords (the
|
||||
true absolute offset, including every ancestor), because the iterator's
|
||||
sx/sy only sums offsets from its own tree root and would place a nested
|
||||
popup too high/left by the missing ancestor offsets. */
|
||||
struct popup_draw_ctx {
|
||||
int win_w, win_h;
|
||||
struct wlr_surface **drawn;
|
||||
int ndrawn;
|
||||
};
|
||||
|
||||
static void popup_draw_cb(struct wlr_scene_buffer *buffer,
|
||||
int sx, int sy, void *user_data) {
|
||||
struct popup_draw_ctx *ctx = user_data;
|
||||
if (!buffer->buffer) return;
|
||||
struct wlr_scene_surface *ss = wlr_scene_surface_try_from_buffer(buffer);
|
||||
if (!ss) return;
|
||||
for (int i = 0; i < ctx->ndrawn; i++) {
|
||||
if (ctx->drawn[i] == ss->surface) return;
|
||||
}
|
||||
ctx->drawn[ctx->ndrawn++] = ss->surface;
|
||||
(void)sx; (void)sy;
|
||||
int lx = 0, ly = 0;
|
||||
wlr_scene_node_coords(&buffer->node, &lx, &ly);
|
||||
if (!import_scene_buffer(buffer->buffer, host.popup_tex)) return;
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
draw_texture_rect(host.popup_tex, buffer->buffer->width,
|
||||
buffer->buffer->height,
|
||||
0, 0, buffer->buffer->width, buffer->buffer->height,
|
||||
lx, ly, ctx->win_w, ctx->win_h);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
static void composite_popups(void) {
|
||||
struct wlr_surface *drawn[64];
|
||||
struct popup_draw_ctx ctx = {
|
||||
.win_w = host.width,
|
||||
.win_h = host.height,
|
||||
.drawn = drawn,
|
||||
.ndrawn = 0,
|
||||
};
|
||||
struct tabbed_popup *tp;
|
||||
wl_list_for_each(tp, &popups, link)
|
||||
wlr_scene_node_for_each_buffer(&tp->scene->node,
|
||||
popup_draw_cb, &ctx);
|
||||
}
|
||||
|
||||
/* Pace presents to the host compositor: this fires after the host has shown
|
||||
the buffer we queued, so we know we may queue the next one. Any frame drawn
|
||||
while a present is still pending is coalesced into the back buffer and
|
||||
|
|
@ -2653,8 +2583,6 @@ static void blit_scene_buffer(struct wlr_buffer *buf) {
|
|||
0, 0, buf->width, buf->height, 0, 0, w, h);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
composite_popups();
|
||||
|
||||
if (dump_host_req) {
|
||||
dump_host_req = false;
|
||||
dump_host_back();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue