From fdc09b028fde9d2ec70418735f354b51c8295d0f Mon Sep 17 00:00:00 2001 From: Weifeng Liu Date: Sun, 11 May 2025 15:33:18 +0800 Subject: [PATCH] ui/gtk-gl-area: Render guest content with padding in fixed-scale mode MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit In fixed-scale mode (zoom-to-fit=false), we expect that scale should not change, meaning that if window size is larger than guest surface, padding is supposed to be added to preserve the scale. However, in OpenGL mode (gl=on), guest surface is always painted to the whole canvas without any padding. This change tries to fix this bug by adding appropriate padding when drawing surfaces. Signed-off-by: Weifeng Liu Message-ID: <20250511073337.876650-9-weifeng.liu.z@gmail.com> Acked-by: Gerd Hoffmann Acked-by: Marc-André Lureau --- ui/gtk-gl-area.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index db93cd6204..8151cc413c 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -44,7 +44,9 @@ void gd_gl_area_draw(VirtualConsole *vc) #endif int pw, ph, gs, y1, y2; int ww, wh; + int ww_surface, wh_surface; int fbw, fbh; + int wx_offset, wy_offset; if (!vc->gfx.gls) { return; @@ -61,6 +63,17 @@ void gd_gl_area_draw(VirtualConsole *vc) gd_update_scale(vc, ww, wh, fbw, fbh); + ww_surface = fbw * vc->gfx.scale_x; + wh_surface = fbh * vc->gfx.scale_y; + + wx_offset = wy_offset = 0; + if (ww > ww_surface) { + wx_offset = (ww - ww_surface) / 2; + } + if (wh > wh_surface) { + wy_offset = (wh - wh_surface) / 2; + } + if (vc->gfx.scanout_mode) { if (!vc->gfx.guest_fb.framebuffer) { return; @@ -79,11 +92,29 @@ void gd_gl_area_draw(VirtualConsole *vc) glBindFramebuffer(GL_READ_FRAMEBUFFER, vc->gfx.guest_fb.framebuffer); /* GtkGLArea sets GL_DRAW_FRAMEBUFFER for us */ + if (wx_offset > 0) { + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, wx_offset * gs, wh * gs); + glClear(GL_COLOR_BUFFER_BIT); + glScissor((ww - wx_offset) * gs, 0, wx_offset * gs, wh * gs); + glClear(GL_COLOR_BUFFER_BIT); + glDisable(GL_SCISSOR_TEST); + } + if (wy_offset > 0) { + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, ww * gs, wy_offset * gs); + glClear(GL_COLOR_BUFFER_BIT); + glScissor(0, (wh - wy_offset) * gs, ww * gs, wy_offset * gs); + glClear(GL_COLOR_BUFFER_BIT); + glDisable(GL_SCISSOR_TEST); + } + glViewport(0, 0, pw, ph); y1 = vc->gfx.y0_top ? 0 : vc->gfx.h; y2 = vc->gfx.y0_top ? vc->gfx.h : 0; glBlitFramebuffer(0, y1, vc->gfx.w, y2, - 0, 0, pw, ph, + wx_offset * gs, wy_offset * gs, + (ww - wx_offset) * gs, (wh - wy_offset) * gs, GL_COLOR_BUFFER_BIT, GL_NEAREST); #ifdef CONFIG_GBM if (dmabuf) { -- 2.39.5