From f0be8d94a51d9562a9fe9958d738f427b1bdd3d4 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Fri, 3 Oct 2025 00:29:07 +0200 Subject: [PATCH] gl-renderer: Use glClear for solid opaque regions If we have a solid region which is opaque, we don't need to go through blending: we can simply emit a glClear, which has a pretty big benefit on tilers in particular. Signed-off-by: Daniel Stone --- libweston/renderer-gl/gl-renderer.c | 38 +++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c index d81f28d52..ef9b792e5 100644 --- a/libweston/renderer-gl/gl-renderer.c +++ b/libweston/renderer-gl/gl-renderer.c @@ -2011,6 +2011,37 @@ repaint_region(struct gl_renderer *gr, gr->barycentric_stream.size = 0; } +static void +clear_region(struct gl_renderer *gr, struct weston_paint_node *pnode, + pixman_region32_t *repaint) +{ + struct weston_output *output = pnode->output; + struct gl_output_state *go = get_output_state(pnode->output); + EGLint *rects; + EGLint nrects; + int i; + + pixman_region_to_egl(output, repaint, go->border_status, + &rects, &nrects); + assert(nrects > 0); + + /* We must be either fully transparent - punching a hole for an + * underlay - or fully opaque, to use clear rather than blending. */ + assert(pnode->solid.a == 0.0f || pnode->solid.a == 1.0f); + set_blend_state(gr, false); + glClearColor(pnode->solid.r, pnode->solid.g, pnode->solid.b, + pnode->solid.a); + + glEnable(GL_SCISSOR_TEST); + for (i = 0; i < nrects; i++) { + EGLint *r = &rects[i * 4]; + glScissor(r[0], r[1], r[2], r[3]); + glClear(GL_COLOR_BUFFER_BIT); + } + glDisable(GL_SCISSOR_TEST); + free(rects); +} + static void draw_paint_node(struct weston_paint_node *pnode, pixman_region32_t *damage /* in global coordinates */) @@ -2045,6 +2076,13 @@ draw_paint_node(struct weston_paint_node *pnode, goto out; } + if (!gr->debug_mode && pnode->draw_solid && pnode->is_fully_opaque && + pnode->view->alpha == 1.0f && !pnode->surf_xform.transform) { + clear_region(gr, pnode, &repaint); + gs->used_in_output_repaint = true; + goto out; + } + if (ensure_surface_buffer_is_ready(gr, gs, pnode) < 0) goto out;