Commit 0db7bc7e authored by David Eger's avatar David Eger Committed by Linus Torvalds

[PATCH] fb accel capabilities

Baseline patch to make framebuffer/fbcon interaction more sane by basing the
fbcon heuristics on capabilities advertized by underlying framebuffer via the
fb_info.flags field.

This patch updates fbcon, fb.h, and skeletonfb.c.  It does *not* yet update
the drivers themselves.  They should compile and work, but their hinting is
not correct yet, meaning most fb drivers will be slow until I set the flags to
the right hinting driver-by-driver
Signed-off-by: default avatarDavid Eger <eger@havoc.gtf.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent e4cb7f8c
...@@ -601,8 +601,9 @@ static void fbcon_init(struct vc_data *vc, int init) ...@@ -601,8 +601,9 @@ static void fbcon_init(struct vc_data *vc, int init)
int display_fg = (*default_mode)->vc_num; int display_fg = (*default_mode)->vc_num;
int logo = 1, rows, cols, charcnt = 256; int logo = 1, rows, cols, charcnt = 256;
unsigned short *save = NULL, *r, *q; unsigned short *save = NULL, *r, *q;
int cap = info->flags;
if (vc->vc_num != display_fg || (info->flags & FBINFO_FLAG_MODULE) || if (vc->vc_num != display_fg || (info->flags & FBINFO_MODULE) ||
(info->fix.type == FB_TYPE_TEXT)) (info->fix.type == FB_TYPE_TEXT))
logo = 0; logo = 0;
...@@ -635,10 +636,10 @@ static void fbcon_init(struct vc_data *vc, int init) ...@@ -635,10 +636,10 @@ static void fbcon_init(struct vc_data *vc, int init)
rows = info->var.yres / vc->vc_font.height; rows = info->var.yres / vc->vc_font.height;
vc_resize(vc->vc_num, cols, rows); vc_resize(vc->vc_num, cols, rows);
if (info->var.accel_flags) if ((cap & FBINFO_HWACCEL_COPYAREA) && !(cap & FBINFO_HWACCEL_DISABLED))
p->scrollmode = SCROLL_YNOMOVE; p->scrollmode = SCROLL_ACCEL;
else else /* default to something safe */
p->scrollmode = SCROLL_YREDRAW; p->scrollmode = SCROLL_REDRAW;
/* /*
* ++guenther: console.c:vc_allocate() relies on initializing * ++guenther: console.c:vc_allocate() relies on initializing
...@@ -1245,7 +1246,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, ...@@ -1245,7 +1246,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
{ {
struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]]; struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
struct display *p = &fb_display[vc->vc_num]; struct display *p = &fb_display[vc->vc_num];
int scroll_partial = !(p->scrollmode & __SCROLL_YNOPARTIAL); int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK;
if (!info->fbops->fb_blank && console_blanked) if (!info->fbops->fb_blank && console_blanked)
return 0; return 0;
...@@ -1269,15 +1270,15 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, ...@@ -1269,15 +1270,15 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
fbcon_softback_note(vc, t, count); fbcon_softback_note(vc, t, count);
if (logo_shown >= 0) if (logo_shown >= 0)
goto redraw_up; goto redraw_up;
switch (p->scrollmode & __SCROLL_YMASK) { switch (p->scrollmode) {
case __SCROLL_YMOVE: case SCROLL_ACCEL:
accel_bmove(vc, info, t + count, 0, t, 0, accel_bmove(vc, info, t + count, 0, t, 0,
b - t - count, vc->vc_cols); b - t - count, vc->vc_cols);
accel_clear(vc, info, b - count, 0, count, accel_clear(vc, info, b - count, 0, count,
vc->vc_cols); vc->vc_cols);
break; break;
case __SCROLL_YWRAP: case SCROLL_WRAP:
if (b - t - count > 3 * vc->vc_rows >> 2) { if (b - t - count > 3 * vc->vc_rows >> 2) {
if (t > 0) if (t > 0)
fbcon_bmove(vc, 0, 0, count, 0, t, fbcon_bmove(vc, 0, 0, count, 0, t,
...@@ -1287,15 +1288,15 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, ...@@ -1287,15 +1288,15 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
fbcon_bmove(vc, b - count, 0, b, 0, fbcon_bmove(vc, b - count, 0, b, 0,
vc->vc_rows - b, vc->vc_rows - b,
vc->vc_cols); vc->vc_cols);
} else if (p->scrollmode & __SCROLL_YPANREDRAW) } else if (info->flags & FBINFO_READS_FAST)
goto redraw_up;
else
fbcon_bmove(vc, t + count, 0, t, 0, fbcon_bmove(vc, t + count, 0, t, 0,
b - t - count, vc->vc_cols); b - t - count, vc->vc_cols);
else
goto redraw_up;
fbcon_clear(vc, b - count, 0, count, vc->vc_cols); fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
break; break;
case __SCROLL_YPAN: case SCROLL_PAN:
if ((p->yscroll + count <= if ((p->yscroll + count <=
2 * (p->vrows - vc->vc_rows)) 2 * (p->vrows - vc->vc_rows))
&& ((!scroll_partial && (b - t == vc->vc_rows)) && ((!scroll_partial && (b - t == vc->vc_rows))
...@@ -1310,15 +1311,15 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, ...@@ -1310,15 +1311,15 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
fbcon_bmove(vc, b - count, 0, b, 0, fbcon_bmove(vc, b - count, 0, b, 0,
vc->vc_rows - b, vc->vc_rows - b,
vc->vc_cols); vc->vc_cols);
} else if (p->scrollmode & __SCROLL_YPANREDRAW) } else if (info->flags & FBINFO_READS_FAST)
goto redraw_up;
else
fbcon_bmove(vc, t + count, 0, t, 0, fbcon_bmove(vc, t + count, 0, t, 0,
b - t - count, vc->vc_cols); b - t - count, vc->vc_cols);
else
goto redraw_up;
fbcon_clear(vc, b - count, 0, count, vc->vc_cols); fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
break; break;
case __SCROLL_YREDRAW: case SCROLL_REDRAW:
redraw_up: redraw_up:
fbcon_redraw(vc, p, t, b - t - count, fbcon_redraw(vc, p, t, b - t - count,
count * vc->vc_cols); count * vc->vc_cols);
...@@ -1336,14 +1337,14 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, ...@@ -1336,14 +1337,14 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
case SM_DOWN: case SM_DOWN:
if (count > vc->vc_rows) /* Maximum realistic size */ if (count > vc->vc_rows) /* Maximum realistic size */
count = vc->vc_rows; count = vc->vc_rows;
switch (p->scrollmode & __SCROLL_YMASK) { switch (p->scrollmode) {
case __SCROLL_YMOVE: case SCROLL_ACCEL:
accel_bmove(vc, info, t, 0, t + count, 0, accel_bmove(vc, info, t, 0, t + count, 0,
b - t - count, vc->vc_cols); b - t - count, vc->vc_cols);
accel_clear(vc, info, t, 0, count, vc->vc_cols); accel_clear(vc, info, t, 0, count, vc->vc_cols);
break; break;
case __SCROLL_YWRAP: case SCROLL_WRAP:
if (b - t - count > 3 * vc->vc_rows >> 2) { if (b - t - count > 3 * vc->vc_rows >> 2) {
if (vc->vc_rows - b > 0) if (vc->vc_rows - b > 0)
fbcon_bmove(vc, b, 0, b - count, 0, fbcon_bmove(vc, b, 0, b - count, 0,
...@@ -1353,15 +1354,15 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, ...@@ -1353,15 +1354,15 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
if (t > 0) if (t > 0)
fbcon_bmove(vc, count, 0, 0, 0, t, fbcon_bmove(vc, count, 0, 0, 0, t,
vc->vc_cols); vc->vc_cols);
} else if (p->scrollmode & __SCROLL_YPANREDRAW) } else if (info->flags & FBINFO_READS_FAST)
goto redraw_down;
else
fbcon_bmove(vc, t, 0, t + count, 0, fbcon_bmove(vc, t, 0, t + count, 0,
b - t - count, vc->vc_cols); b - t - count, vc->vc_cols);
else
goto redraw_down;
fbcon_clear(vc, t, 0, count, vc->vc_cols); fbcon_clear(vc, t, 0, count, vc->vc_cols);
break; break;
case __SCROLL_YPAN: case SCROLL_PAN:
if ((count - p->yscroll <= p->vrows - vc->vc_rows) if ((count - p->yscroll <= p->vrows - vc->vc_rows)
&& ((!scroll_partial && (b - t == vc->vc_rows)) && ((!scroll_partial && (b - t == vc->vc_rows))
|| (scroll_partial || (scroll_partial
...@@ -1375,15 +1376,15 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, ...@@ -1375,15 +1376,15 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
if (t > 0) if (t > 0)
fbcon_bmove(vc, count, 0, 0, 0, t, fbcon_bmove(vc, count, 0, 0, 0, t,
vc->vc_cols); vc->vc_cols);
} else if (p->scrollmode & __SCROLL_YPANREDRAW) } else if (info->flags & FBINFO_READS_FAST)
goto redraw_down;
else
fbcon_bmove(vc, t, 0, t + count, 0, fbcon_bmove(vc, t, 0, t + count, 0,
b - t - count, vc->vc_cols); b - t - count, vc->vc_cols);
else
goto redraw_down;
fbcon_clear(vc, t, 0, count, vc->vc_cols); fbcon_clear(vc, t, 0, count, vc->vc_cols);
break; break;
case __SCROLL_YREDRAW: case SCROLL_REDRAW:
redraw_down: redraw_down:
fbcon_redraw(vc, p, b - 1, b - t - count, fbcon_redraw(vc, p, b - 1, b - t - count,
-count * vc->vc_cols); -count * vc->vc_cols);
...@@ -1467,21 +1468,23 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int s ...@@ -1467,21 +1468,23 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int s
static __inline__ void updatescrollmode(struct display *p, struct fb_info *info, struct vc_data *vc) static __inline__ void updatescrollmode(struct display *p, struct fb_info *info, struct vc_data *vc)
{ {
int m; int cap = info->flags;
if (p->scrollmode & __SCROLL_YFIXED) if ((cap & FBINFO_HWACCEL_COPYAREA) && !(cap & FBINFO_HWACCEL_DISABLED))
return; p->scrollmode = SCROLL_ACCEL;
if (divides(info->fix.ywrapstep, vc->vc_font.height) && else if ((cap & FBINFO_HWACCEL_YWRAP) &&
divides(info->fix.ywrapstep, vc->vc_font.height) &&
divides(vc->vc_font.height, info->var.yres_virtual)) divides(vc->vc_font.height, info->var.yres_virtual))
m = __SCROLL_YWRAP; p->scrollmode = SCROLL_WRAP;
else if (divides(info->fix.ypanstep, vc->vc_font.height) && else if ((cap & FBINFO_HWACCEL_YPAN) &&
divides(info->fix.ypanstep, vc->vc_font.height) &&
info->var.yres_virtual >= info->var.yres + vc->vc_font.height) info->var.yres_virtual >= info->var.yres + vc->vc_font.height)
m = __SCROLL_YPAN; p->scrollmode = SCROLL_PAN;
else if (p->scrollmode & __SCROLL_YNOMOVE) else if (cap & FBINFO_READS_FAST)
m = __SCROLL_YREDRAW; /* okay, we'll use software version of accel funcs... */
p->scrollmode = SCROLL_ACCEL;
else else
m = __SCROLL_YMOVE; p->scrollmode = SCROLL_REDRAW;
p->scrollmode = (p->scrollmode & ~__SCROLL_YMASK) | m;
} }
static int fbcon_resize(struct vc_data *vc, unsigned int width, static int fbcon_resize(struct vc_data *vc, unsigned int width,
...@@ -1556,11 +1559,11 @@ static int fbcon_switch(struct vc_data *vc) ...@@ -1556,11 +1559,11 @@ static int fbcon_switch(struct vc_data *vc)
if (info) if (info)
info->var.yoffset = p->yscroll = 0; info->var.yoffset = p->yscroll = 0;
fbcon_resize(vc, vc->vc_cols, vc->vc_rows); fbcon_resize(vc, vc->vc_cols, vc->vc_rows);
switch (p->scrollmode & __SCROLL_YMASK) { switch (p->scrollmode) {
case __SCROLL_YWRAP: case SCROLL_WRAP:
scrollback_phys_max = p->vrows - vc->vc_rows; scrollback_phys_max = p->vrows - vc->vc_rows;
break; break;
case __SCROLL_YPAN: case SCROLL_PAN:
scrollback_phys_max = p->vrows - 2 * vc->vc_rows; scrollback_phys_max = p->vrows - 2 * vc->vc_rows;
if (scrollback_phys_max < 0) if (scrollback_phys_max < 0)
scrollback_phys_max = 0; scrollback_phys_max = 0;
...@@ -2133,11 +2136,11 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines) ...@@ -2133,11 +2136,11 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines)
offset = p->yscroll - scrollback_current; offset = p->yscroll - scrollback_current;
limit = p->vrows; limit = p->vrows;
switch (p->scrollmode && __SCROLL_YMASK) { switch (p->scrollmode) {
case __SCROLL_YWRAP: case SCROLL_WRAP:
info->var.vmode |= FB_VMODE_YWRAP; info->var.vmode |= FB_VMODE_YWRAP;
break; break;
case __SCROLL_YPAN: case SCROLL_PAN:
limit -= vc->vc_rows; limit -= vc->vc_rows;
info->var.vmode &= ~FB_VMODE_YWRAP; info->var.vmode &= ~FB_VMODE_YWRAP;
break; break;
......
...@@ -67,40 +67,27 @@ extern int set_con2fb_map(int unit, int newidx); ...@@ -67,40 +67,27 @@ extern int set_con2fb_map(int unit, int newidx);
* Scroll Method * Scroll Method
*/ */
/* Internal flags */ /* There are several methods fbcon can use to move text around the screen:
#define __SCROLL_YPAN 0x001 *
#define __SCROLL_YWRAP 0x002 * + use the hardware engine to move the text
#define __SCROLL_YMOVE 0x003 * (hw-accelerated copyarea() and fillrect())
#define __SCROLL_YREDRAW 0x004 * + use hardware-supported panning on a large virtual screen
#define __SCROLL_YMASK 0x00f * + amifb can not only pan, but also wrap the display by N lines
#define __SCROLL_YFIXED 0x010 * (i.e. visible line i = physical line (i+N) % yres).
#define __SCROLL_YNOMOVE 0x020 * + read what's already rendered on the screen and
#define __SCROLL_YPANREDRAW 0x040 * write it in a different place (this is cfb_copyarea())
#define __SCROLL_YNOPARTIAL 0x080 * + re-render the text to the screen
*
/* Only these should be used by the drivers */ * Whether to use wrapping or panning can only be figured out at
/* Which one should you use? If you have a fast card and slow bus, * runtime (when we know whether our font height is a multiple
then probably just 0 to indicate fbcon should choose between * of the pan/wrap step)
YWRAP/YPAN+MOVE/YMOVE. On the other side, if you have a fast bus *
and even better if your card can do fonting (1->8/32bit painting),
you should consider either SCROLL_YREDRAW (if your card is
able to do neither YPAN/YWRAP), or SCROLL_YNOMOVE.
The best is to test it with some real life scrolling (usually, not
all lines on the screen are filled completely with non-space characters,
and REDRAW performs much better on such lines, so don't cat a file
with every line covering all screen columns, it would not be the right
benchmark).
*/ */
#define SCROLL_YREDRAW (__SCROLL_YFIXED|__SCROLL_YREDRAW)
#define SCROLL_YNOMOVE (__SCROLL_YNOMOVE|__SCROLL_YPANREDRAW)
/* SCROLL_YNOPARTIAL, used in combination with the above, is for video #define SCROLL_ACCEL 0x001
cards which can not handle using panning to scroll a portion of the #define SCROLL_PAN 0x002
screen without excessive flicker. Panning will only be used for #define SCROLL_WRAP 0x003
whole screens. #define SCROLL_REDRAW 0x004
*/
/* Namespace consistency */
#define SCROLL_YNOPARTIAL __SCROLL_YNOPARTIAL
extern int fb_console_init(void); extern int fb_console_init(void);
......
...@@ -539,7 +539,13 @@ int __init xxxfb_init(void) ...@@ -539,7 +539,13 @@ int __init xxxfb_init(void)
info.fbops = &xxxfb_ops; info.fbops = &xxxfb_ops;
info.fix = xxxfb_fix; info.fix = xxxfb_fix;
info.pseudo_palette = pseudo_palette; info.pseudo_palette = pseudo_palette;
info.flags = FBINFO_FLAG_DEFAULT;
/*
* Set up flags to indicate what sort of acceleration your
* driver can provide (pan/wrap/copyarea/etc.) and whether it
* is a module -- see FBINFO_* in include/linux/fb.h
*/
info.flags = FBINFO_DEFAULT;
info.par = current_par; info.par = current_par;
/* /*
......
...@@ -125,7 +125,8 @@ struct fb_fix_screeninfo { ...@@ -125,7 +125,8 @@ struct fb_fix_screeninfo {
unsigned long mmio_start; /* Start of Memory Mapped I/O */ unsigned long mmio_start; /* Start of Memory Mapped I/O */
/* (physical address) */ /* (physical address) */
__u32 mmio_len; /* Length of Memory Mapped I/O */ __u32 mmio_len; /* Length of Memory Mapped I/O */
__u32 accel; /* Type of acceleration available */ __u32 accel; /* Indicate to driver which */
/* specific chip/card we have */
__u16 reserved[3]; /* Reserved for future compatibility */ __u16 reserved[3]; /* Reserved for future compatibility */
}; };
...@@ -154,7 +155,7 @@ struct fb_bitfield { ...@@ -154,7 +155,7 @@ struct fb_bitfield {
#define FB_ACTIVATE_ALL 64 /* change all VCs on this fb */ #define FB_ACTIVATE_ALL 64 /* change all VCs on this fb */
#define FB_ACTIVATE_FORCE 128 /* force apply even when no change*/ #define FB_ACTIVATE_FORCE 128 /* force apply even when no change*/
#define FB_ACCELF_TEXT 1 /* text mode acceleration */ #define FB_ACCELF_TEXT 1 /* (OBSOLETE) see fb_info.flags and vc_mode */
#define FB_SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */ #define FB_SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */
#define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */ #define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */
...@@ -200,7 +201,7 @@ struct fb_var_screeninfo { ...@@ -200,7 +201,7 @@ struct fb_var_screeninfo {
__u32 height; /* height of picture in mm */ __u32 height; /* height of picture in mm */
__u32 width; /* width of picture in mm */ __u32 width; /* width of picture in mm */
__u32 accel_flags; /* acceleration flags (hints) */ __u32 accel_flags; /* (OBSOLETE) see fb_info.flags */
/* Timing: All values in pixclocks, except pixclock (of course) */ /* Timing: All values in pixclocks, except pixclock (of course) */
__u32 pixclock; /* pixel clock in ps (pico seconds) */ __u32 pixclock; /* pixel clock in ps (pico seconds) */
...@@ -502,10 +503,37 @@ struct fb_ops { ...@@ -502,10 +503,37 @@ struct fb_ops {
int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma); int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma);
}; };
/* FBINFO_* = fb_info.flags bit flags */
#define FBINFO_MODULE 0x0001 /* Low-level driver is a module */
#define FBINFO_HWACCEL_DISABLED 0x0002
/* When FBINFO_HWACCEL_DISABLED is set:
* Hardware acceleration is turned off. Software implementations
* of required functions (copyarea(), fillrect(), and imageblit())
* takes over; acceleration engine should be in a quiescent state */
/* hints */
#define FBINFO_PARTIAL_PAN_OK 0x0040 /* otw use pan only for double-buffering */
#define FBINFO_READS_FAST 0x0080 /* soft-copy faster than rendering */
/* hardware supported ops */
/* semantics: when a bit is set, it indicates that the operation is
* accelerated by hardware.
* required functions will still work even if the bit is not set.
* optional functions may not even exist if the flag bit is not set.
*/
#define FBINFO_HWACCEL_NONE 0x0000
#define FBINFO_HWACCEL_COPYAREA 0x0100 /* required */
#define FBINFO_HWACCEL_FILLRECT 0x0200 /* required */
#define FBINFO_HWACCEL_IMAGEBLIT 0x0400 /* required */
#define FBINFO_HWACCEL_ROTATE 0x0800 /* optional */
#define FBINFO_HWACCEL_XPAN 0x1000 /* optional */
#define FBINFO_HWACCEL_YPAN 0x2000 /* optional */
#define FBINFO_HWACCEL_YWRAP 0x4000 /* optional */
struct fb_info { struct fb_info {
int node; int node;
int flags; int flags;
#define FBINFO_FLAG_MODULE 1 /* Low-level driver is a module */
struct fb_var_screeninfo var; /* Current var */ struct fb_var_screeninfo var; /* Current var */
struct fb_fix_screeninfo fix; /* Current fix */ struct fb_fix_screeninfo fix; /* Current fix */
struct fb_monspecs monspecs; /* Current Monitor specs */ struct fb_monspecs monspecs; /* Current Monitor specs */
...@@ -527,11 +555,23 @@ struct fb_info { ...@@ -527,11 +555,23 @@ struct fb_info {
}; };
#ifdef MODULE #ifdef MODULE
#define FBINFO_FLAG_DEFAULT FBINFO_FLAG_MODULE #define FBINFO_DEFAULT FBINFO_MODULE
#else #else
#define FBINFO_FLAG_DEFAULT 0 #define FBINFO_DEFAULT 0
#endif #endif
// This will go away
#define FBINFO_FLAG_MODULE FBINFO_MODULE
#define FBINFO_FLAG_DEFAULT FBINFO_DEFAULT
/* This will go away
* fbset currently hacks in FB_ACCELF_TEXT into var.accel_flags
* when it wants to turn the acceleration engine on. This is
* really a separate operation, and should be modified via sysfs.
* But for now, we leave it broken with the following define
*/
#define STUPID_ACCELF_TEXT_SHIT
// This will go away // This will go away
#if defined(__sparc__) #if defined(__sparc__)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment