[PATCH] drm/fb-helper: Fix xres and yres to reflect reality
Jouni Högander
jouni.hogander at intel.com
Thu Jul 11 07:44:41 UTC 2024
When multiple CRTCs with different modes exists fb-helper is setting fbdev
width and height to match with smallest mode. This is causing problems with
panning: Information provided towards user space is stating xres and yres
are smaller than what they are in CRTC with larger resolution -> User space
may try panning such that it is out of area in CRTC with larger mode.
Fix this by setting xres and yres to match CRTC with largest
resolution. Ensure fdev drawing area is fully visible in CRTC with smallest
mode as well by setting info->var.*_margin.
Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4435
Signed-off-by: Jouni Högander <jouni.hogander at intel.com>
---
drivers/gpu/drm/drm_fb_helper.c | 23 ++++++++++++++++-------
include/drm/drm_fb_helper.h | 2 ++
2 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 18565ec684517..105b34174b09c 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1196,8 +1196,10 @@ static void __fill_var(struct fb_var_screeninfo *var, struct fb_info *info,
var->height = info->var.height;
var->width = info->var.width;
- var->left_margin = var->right_margin = 0;
- var->upper_margin = var->lower_margin = 0;
+ var->left_margin = info->var.left_margin;
+ var->right_margin = info->var.right_margin;
+ var->upper_margin = info->var.upper_margin;
+ var->lower_margin = info->var.lower_margin;
var->hsync_len = var->vsync_len = 0;
var->sync = var->vmode = 0;
var->rotate = 0;
@@ -1629,6 +1631,9 @@ static int drm_fb_helper_find_sizes(struct drm_fb_helper *fb_helper,
if (ret)
return ret;
+ sizes->visible_width = sizes->surface_width;
+ sizes->visible_height = sizes->surface_height;
+
/* Handle our overallocation */
sizes->surface_height *= drm_fbdev_overalloc;
sizes->surface_height /= 100;
@@ -1693,7 +1698,7 @@ static void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
static void drm_fb_helper_fill_var(struct fb_info *info,
struct drm_fb_helper *fb_helper,
- uint32_t fb_width, uint32_t fb_height)
+ struct drm_fb_helper_surface_size *sizes)
{
struct drm_framebuffer *fb = fb_helper->fb;
const struct drm_format_info *format = fb->format;
@@ -1714,13 +1719,18 @@ static void drm_fb_helper_fill_var(struct fb_info *info,
info->pseudo_palette = fb_helper->pseudo_palette;
info->var.xoffset = 0;
info->var.yoffset = 0;
+ info->var.upper_margin = 0;
+ info->var.left_margin = 0;
+ info->var.right_margin = sizes->visible_width - sizes->fb_width;
+ info->var.lower_margin = sizes->visible_height - sizes->fb_height;
+
__fill_var(&info->var, info, fb);
info->var.activate = FB_ACTIVATE_NOW;
drm_fb_helper_fill_pixel_fmt(&info->var, format);
- info->var.xres = fb_width;
- info->var.yres = fb_height;
+ info->var.xres = sizes->visible_width;
+ info->var.yres = sizes->visible_height;
}
/**
@@ -1744,8 +1754,7 @@ void drm_fb_helper_fill_info(struct fb_info *info,
drm_fb_helper_fill_fix(info, fb->pitches[0],
fb->format->is_color_indexed);
- drm_fb_helper_fill_var(info, fb_helper,
- sizes->fb_width, sizes->fb_height);
+ drm_fb_helper_fill_var(info, fb_helper, sizes);
info->par = fb_helper;
/*
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index 375737fd6c36e..5697a442f1b8b 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -59,6 +59,8 @@ struct drm_fb_helper_surface_size {
u32 fb_height;
u32 surface_width;
u32 surface_height;
+ u32 visible_width;
+ u32 visible_height;
u32 surface_bpp;
u32 surface_depth;
};
--
2.34.1
More information about the Intel-gfx-trybot
mailing list