Skip to content

Commit

Permalink
fbcon: Add option to enable legacy hardware acceleration
Browse files Browse the repository at this point in the history
commit a3f781a upstream.

Add a config option CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION to
enable bitblt and fillrect hardware acceleration in the framebuffer
console. If disabled, such acceleration will not be used, even if it is
supported by the graphics hardware driver.

If you plan to use DRM as your main graphics output system, you should
disable this option since it will prevent compiling in code which isn't
used later on when DRM takes over.

For all other configurations, e.g. if none of your graphic cards support
DRM (yet), DRM isn't available for your architecture, or you can't be
sure that the graphic card in the target system will support DRM, you
most likely want to enable this option.

In the non-accelerated case (e.g. when DRM is used), the inlined
fb_scrollmode() function is hardcoded to return SCROLL_REDRAW and as such the
compiler is able to optimize much unneccesary code away.

In this v3 patch version I additionally changed the GETVYRES() and GETVXRES()
macros to take a pointer to the fbcon_display struct. This fixes the build when
console rotation is enabled and helps the compiler again to optimize out code.

Signed-off-by: Helge Deller <deller@gmx.de>
Cc: stable@vger.kernel.org # v5.10+
Signed-off-by: Helge Deller <deller@gmx.de>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20220202135531.92183-4-deller@gmx.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
hdeller authored and gregkh committed Feb 8, 2022
1 parent 2a2629d commit 778283d
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 34 deletions.
20 changes: 20 additions & 0 deletions drivers/video/console/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,26 @@ config FRAMEBUFFER_CONSOLE
help
Low-level framebuffer-based console driver.

config FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
bool "Enable legacy fbcon hardware acceleration code"
depends on FRAMEBUFFER_CONSOLE
default y if PARISC
default n
help
This option enables the fbcon (framebuffer text-based) hardware
acceleration for graphics drivers which were written for the fbdev
graphics interface.

On modern machines, on mainstream machines (like x86-64) or when
using a modern Linux distribution those fbdev drivers usually aren't used.
So enabling this option wouldn't have any effect, which is why you want
to disable this option on such newer machines.

If you compile this kernel for older machines which still require the
fbdev drivers, you may want to say Y.

If unsure, select n.

config FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
bool "Map the console to the primary display device"
depends on FRAMEBUFFER_CONSOLE
Expand Down
39 changes: 28 additions & 11 deletions drivers/video/fbdev/core/fbcon.c
Original file line number Diff line number Diff line change
Expand Up @@ -1136,11 +1136,13 @@ static void fbcon_init(struct vc_data *vc, int init)

ops->graphics = 0;

#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
if ((cap & FBINFO_HWACCEL_COPYAREA) &&
!(cap & FBINFO_HWACCEL_DISABLED))
p->scrollmode = SCROLL_MOVE;
else /* default to something safe */
p->scrollmode = SCROLL_REDRAW;
#endif

/*
* ++guenther: console.c:vc_allocate() relies on initializing
Expand Down Expand Up @@ -1705,7 +1707,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
count = vc->vc_rows;
if (logo_shown >= 0)
goto redraw_up;
switch (p->scrollmode) {
switch (fb_scrollmode(p)) {
case SCROLL_MOVE:
fbcon_redraw_blit(vc, info, p, t, b - t - count,
count);
Expand Down Expand Up @@ -1795,7 +1797,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
count = vc->vc_rows;
if (logo_shown >= 0)
goto redraw_down;
switch (p->scrollmode) {
switch (fb_scrollmode(p)) {
case SCROLL_MOVE:
fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
-count);
Expand Down Expand Up @@ -1946,12 +1948,12 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy,
height, width);
}

static void updatescrollmode(struct fbcon_display *p,
static void updatescrollmode_accel(struct fbcon_display *p,
struct fb_info *info,
struct vc_data *vc)
{
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
struct fbcon_ops *ops = info->fbcon_par;
int fh = vc->vc_font.height;
int cap = info->flags;
u16 t = 0;
int ypan = FBCON_SWAP(ops->rotate, info->fix.ypanstep,
Expand All @@ -1972,12 +1974,6 @@ static void updatescrollmode(struct fbcon_display *p,
int fast_imageblit = (cap & FBINFO_HWACCEL_IMAGEBLIT) &&
!(cap & FBINFO_HWACCEL_DISABLED);

p->vrows = vyres/fh;
if (yres > (fh * (vc->vc_rows + 1)))
p->vrows -= (yres - (fh * vc->vc_rows)) / fh;
if ((yres % fh) && (vyres % fh < yres % fh))
p->vrows--;

if (good_wrap || good_pan) {
if (reading_fast || fast_copyarea)
p->scrollmode = good_wrap ?
Expand All @@ -1991,6 +1987,27 @@ static void updatescrollmode(struct fbcon_display *p,
else
p->scrollmode = SCROLL_REDRAW;
}
#endif
}

static void updatescrollmode(struct fbcon_display *p,
struct fb_info *info,
struct vc_data *vc)
{
struct fbcon_ops *ops = info->fbcon_par;
int fh = vc->vc_font.height;
int yres = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual,
info->var.xres_virtual);

p->vrows = vyres/fh;
if (yres > (fh * (vc->vc_rows + 1)))
p->vrows -= (yres - (fh * vc->vc_rows)) / fh;
if ((yres % fh) && (vyres % fh < yres % fh))
p->vrows--;

/* update scrollmode in case hardware acceleration is used */
updatescrollmode_accel(p, info, vc);
}

#define PITCH(w) (((w) + 7) >> 3)
Expand Down Expand Up @@ -2148,7 +2165,7 @@ static int fbcon_switch(struct vc_data *vc)

updatescrollmode(p, info, vc);

switch (p->scrollmode) {
switch (fb_scrollmode(p)) {
case SCROLL_WRAP_MOVE:
scrollback_phys_max = p->vrows - vc->vc_rows;
break;
Expand Down
15 changes: 14 additions & 1 deletion drivers/video/fbdev/core/fbcon.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ struct fbcon_display {
/* Filled in by the low-level console driver */
const u_char *fontdata;
int userfont; /* != 0 if fontdata kmalloc()ed */
u_short scrollmode; /* Scroll Method */
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
u_short scrollmode; /* Scroll Method, use fb_scrollmode() */
#endif
u_short inverse; /* != 0 text black on white as default */
short yscroll; /* Hardware scrolling */
int vrows; /* number of virtual rows */
Expand Down Expand Up @@ -208,6 +210,17 @@ static inline int attr_col_ec(int shift, struct vc_data *vc,
#define SCROLL_REDRAW 0x004
#define SCROLL_PAN_REDRAW 0x005

static inline u_short fb_scrollmode(struct fbcon_display *fb)
{
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
return fb->scrollmode;
#else
/* hardcoded to SCROLL_REDRAW if acceleration was disabled. */
return SCROLL_REDRAW;
#endif
}


#ifdef CONFIG_FB_TILEBLITTING
extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
#endif
Expand Down
10 changes: 5 additions & 5 deletions drivers/video/fbdev/core/fbcon_ccw.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy,
{
struct fbcon_ops *ops = info->fbcon_par;
struct fb_copyarea area;
u32 vyres = GETVYRES(ops->p->scrollmode, info);
u32 vyres = GETVYRES(ops->p, info);

area.sx = sy * vc->vc_font.height;
area.sy = vyres - ((sx + width) * vc->vc_font.width);
Expand All @@ -83,7 +83,7 @@ static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy,
struct fbcon_ops *ops = info->fbcon_par;
struct fb_fillrect region;
int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
u32 vyres = GETVYRES(ops->p->scrollmode, info);
u32 vyres = GETVYRES(ops->p, info);

region.color = attr_bgcol_ec(bgshift,vc,info);
region.dx = sy * vc->vc_font.height;
Expand Down Expand Up @@ -140,7 +140,7 @@ static void ccw_putcs(struct vc_data *vc, struct fb_info *info,
u32 cnt, pitch, size;
u32 attribute = get_attribute(info, scr_readw(s));
u8 *dst, *buf = NULL;
u32 vyres = GETVYRES(ops->p->scrollmode, info);
u32 vyres = GETVYRES(ops->p, info);

if (!ops->fontbuffer)
return;
Expand Down Expand Up @@ -229,7 +229,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1, dx, dy;
char *src;
u32 vyres = GETVYRES(ops->p->scrollmode, info);
u32 vyres = GETVYRES(ops->p, info);

if (!ops->fontbuffer)
return;
Expand Down Expand Up @@ -387,7 +387,7 @@ static int ccw_update_start(struct fb_info *info)
{
struct fbcon_ops *ops = info->fbcon_par;
u32 yoffset;
u32 vyres = GETVYRES(ops->p->scrollmode, info);
u32 vyres = GETVYRES(ops->p, info);
int err;

yoffset = (vyres - info->var.yres) - ops->var.xoffset;
Expand Down
10 changes: 5 additions & 5 deletions drivers/video/fbdev/core/fbcon_cw.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy,
{
struct fbcon_ops *ops = info->fbcon_par;
struct fb_copyarea area;
u32 vxres = GETVXRES(ops->p->scrollmode, info);
u32 vxres = GETVXRES(ops->p, info);

area.sx = vxres - ((sy + height) * vc->vc_font.height);
area.sy = sx * vc->vc_font.width;
Expand All @@ -68,7 +68,7 @@ static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy,
struct fbcon_ops *ops = info->fbcon_par;
struct fb_fillrect region;
int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
u32 vxres = GETVXRES(ops->p->scrollmode, info);
u32 vxres = GETVXRES(ops->p, info);

region.color = attr_bgcol_ec(bgshift,vc,info);
region.dx = vxres - ((sy + height) * vc->vc_font.height);
Expand Down Expand Up @@ -125,7 +125,7 @@ static void cw_putcs(struct vc_data *vc, struct fb_info *info,
u32 cnt, pitch, size;
u32 attribute = get_attribute(info, scr_readw(s));
u8 *dst, *buf = NULL;
u32 vxres = GETVXRES(ops->p->scrollmode, info);
u32 vxres = GETVXRES(ops->p, info);

if (!ops->fontbuffer)
return;
Expand Down Expand Up @@ -212,7 +212,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1, dx, dy;
char *src;
u32 vxres = GETVXRES(ops->p->scrollmode, info);
u32 vxres = GETVXRES(ops->p, info);

if (!ops->fontbuffer)
return;
Expand Down Expand Up @@ -369,7 +369,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
static int cw_update_start(struct fb_info *info)
{
struct fbcon_ops *ops = info->fbcon_par;
u32 vxres = GETVXRES(ops->p->scrollmode, info);
u32 vxres = GETVXRES(ops->p, info);
u32 xoffset;
int err;

Expand Down
4 changes: 2 additions & 2 deletions drivers/video/fbdev/core/fbcon_rotate.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
#define _FBCON_ROTATE_H

#define GETVYRES(s,i) ({ \
(s == SCROLL_REDRAW || s == SCROLL_MOVE) ? \
(fb_scrollmode(s) == SCROLL_REDRAW || fb_scrollmode(s) == SCROLL_MOVE) ? \
(i)->var.yres : (i)->var.yres_virtual; })

#define GETVXRES(s,i) ({ \
(s == SCROLL_REDRAW || s == SCROLL_MOVE || !(i)->fix.xpanstep) ? \
(fb_scrollmode(s) == SCROLL_REDRAW || fb_scrollmode(s) == SCROLL_MOVE || !(i)->fix.xpanstep) ? \
(i)->var.xres : (i)->var.xres_virtual; })


Expand Down
20 changes: 10 additions & 10 deletions drivers/video/fbdev/core/fbcon_ud.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy,
{
struct fbcon_ops *ops = info->fbcon_par;
struct fb_copyarea area;
u32 vyres = GETVYRES(ops->p->scrollmode, info);
u32 vxres = GETVXRES(ops->p->scrollmode, info);
u32 vyres = GETVYRES(ops->p, info);
u32 vxres = GETVXRES(ops->p, info);

area.sy = vyres - ((sy + height) * vc->vc_font.height);
area.sx = vxres - ((sx + width) * vc->vc_font.width);
Expand All @@ -69,8 +69,8 @@ static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy,
struct fbcon_ops *ops = info->fbcon_par;
struct fb_fillrect region;
int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
u32 vyres = GETVYRES(ops->p->scrollmode, info);
u32 vxres = GETVXRES(ops->p->scrollmode, info);
u32 vyres = GETVYRES(ops->p, info);
u32 vxres = GETVXRES(ops->p, info);

region.color = attr_bgcol_ec(bgshift,vc,info);
region.dy = vyres - ((sy + height) * vc->vc_font.height);
Expand Down Expand Up @@ -162,8 +162,8 @@ static void ud_putcs(struct vc_data *vc, struct fb_info *info,
u32 mod = vc->vc_font.width % 8, cnt, pitch, size;
u32 attribute = get_attribute(info, scr_readw(s));
u8 *dst, *buf = NULL;
u32 vyres = GETVYRES(ops->p->scrollmode, info);
u32 vxres = GETVXRES(ops->p->scrollmode, info);
u32 vyres = GETVYRES(ops->p, info);
u32 vxres = GETVXRES(ops->p, info);

if (!ops->fontbuffer)
return;
Expand Down Expand Up @@ -259,8 +259,8 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1, dx, dy;
char *src;
u32 vyres = GETVYRES(ops->p->scrollmode, info);
u32 vxres = GETVXRES(ops->p->scrollmode, info);
u32 vyres = GETVYRES(ops->p, info);
u32 vxres = GETVXRES(ops->p, info);

if (!ops->fontbuffer)
return;
Expand Down Expand Up @@ -410,8 +410,8 @@ static int ud_update_start(struct fb_info *info)
{
struct fbcon_ops *ops = info->fbcon_par;
int xoffset, yoffset;
u32 vyres = GETVYRES(ops->p->scrollmode, info);
u32 vxres = GETVXRES(ops->p->scrollmode, info);
u32 vyres = GETVYRES(ops->p, info);
u32 vxres = GETVXRES(ops->p, info);
int err;

xoffset = vxres - info->var.xres - ops->var.xoffset;
Expand Down

0 comments on commit 778283d

Please sign in to comment.