[PATCH 2/4] FB accel capabilities (core update)

David Eger
2004-05-20T15:59:28Z

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.

diff -Nru a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
--- a/drivers/video/console/fbcon.c Sat May 15 22:53:10 2004
+++ b/drivers/video/console/fbcon.c Sat May 15 22:53:10 2004
@@ -599,15 +599,14 @@
static void fbcon_init(struct vc_data *vc, int init)
{
int unit = vc->vc_num;
- struct fb_info *info;

- /* on which frame buffer will we open this console? */
- info = registered_fb[(int) con2fb_map[unit]];
+ /* get the frame buffer capabilities for the fb we are opening */
+ int cap = registered_fb[(int) con2fb_map[unit]]->flags;

- if (info->var.accel_flags)
- fb_display[unit].scrollmode = SCROLL_YNOMOVE;
- else
- fb_display[unit].scrollmode = SCROLL_YREDRAW;
+ if ((cap & FBINFO_HWACCEL_COPYAREA) && !(cap & FBINFO_HWACCEL_DISABLED))
+ fb_display[unit].scrollmode = SCROLL_ACCEL;
+ else /* default to something safe */
+ fb_display[unit].scrollmode = SCROLL_REDRAW;
con_set_default_unimap(unit);
fbcon_set_display(vc, init, !init);
}
@@ -622,21 +621,23 @@
static __inline__ void updatescrollmode(struct display *p, struct vc_data *vc)
{
struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+ int cap = info->flags;

- int m;
- if (p->scrollmode & __SCROLL_YFIXED)
- return;
- if (divides(info->fix.ywrapstep, vc->vc_font.height) &&
- divides(vc->vc_font.height, info->var.yres_virtual))
- m = __SCROLL_YWRAP;
- else if (divides(info->fix.ypanstep, vc->vc_font.height) &&
+ if ((cap & FBINFO_HWACCEL_COPYAREA) && !(cap & FBINFO_HWACCEL_DISABLED))
+ p->scrollmode = SCROLL_ACCEL;
+ else if ((cap & FBINFO_HWACCEL_YWRAP) &&
+ divides(info->fix.ywrapstep, vc->vc_font.height) &&
+ divides(vc->vc_font.height, info->var.yres_virtual))
+ p->scrollmode = SCROLL_WRAP;
+ 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)
- m = __SCROLL_YPAN;
- else if (p->scrollmode & __SCROLL_YNOMOVE)
- m = __SCROLL_YREDRAW;
+ p->scrollmode = SCROLL_PAN;
+ else if (cap & FBINFO_READS_FAST)
+ /* okay, we'll use software version of accel funcs... */
+ p->scrollmode = SCROLL_ACCEL;
else
- m = __SCROLL_YMOVE;
- p->scrollmode = (p->scrollmode & ~__SCROLL_YMASK) | m;
+ p->scrollmode = SCROLL_REDRAW;
}

static void fbcon_set_display(struct vc_data *vc, int init, int logo)
@@ -647,7 +648,7 @@
unsigned short *save = NULL, *r, *q;
struct font_desc *font;

- if (vc->vc_num != fg_console || (info->flags & FBINFO_FLAG_MODULE) ||
+ if (vc->vc_num != fg_console || (info->flags & FBINFO_MODULE) ||
(info->fix.type == FB_TYPE_TEXT))
logo = 0;

@@ -1311,7 +1312,7 @@
{
struct fb_info *info = registered_fb[(int) con2fb_map[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)
return 0;
@@ -1335,15 +1336,15 @@
fbcon_softback_note(vc, t, count);
if (logo_shown >= 0)
goto redraw_up;
- switch (p->scrollmode & __SCROLL_YMASK) {
- case __SCROLL_YMOVE:
+ switch (p->scrollmode) {
+ case SCROLL_ACCEL:
accel_bmove(vc, info, t + count, 0, t, 0,
b - t - count, vc->vc_cols);
accel_clear(vc, info, b - count, 0, count,
vc->vc_cols);
break;

- case __SCROLL_YWRAP:
+ case SCROLL_WRAP:
if (b - t - count > 3 * vc->vc_rows >> 2) {
if (t > 0)
fbcon_bmove(vc, 0, 0, count, 0, t,
@@ -1353,15 +1354,15 @@
fbcon_bmove(vc, b - count, 0, b, 0,
vc->vc_rows - b,
vc->vc_cols);
- } else if (p->scrollmode & __SCROLL_YPANREDRAW)
- goto redraw_up;
- else
+ } else if (info->flags & FBINFO_READS_FAST)
fbcon_bmove(vc, t + count, 0, t, 0,
b - t - count, vc->vc_cols);
+ else
+ goto redraw_up;
fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
break;

- case __SCROLL_YPAN:
+ case SCROLL_PAN:
if ((p->yscroll + count <=
2 * (p->vrows - vc->vc_rows))
&& ((!scroll_partial && (b - t == vc->vc_rows))
@@ -1376,15 +1377,15 @@
fbcon_bmove(vc, b - count, 0, b, 0,
vc->vc_rows - b,
vc->vc_cols);
- } else if (p->scrollmode & __SCROLL_YPANREDRAW)
- goto redraw_up;
- else
+ } else if (info->flags & FBINFO_READS_FAST)
fbcon_bmove(vc, t + count, 0, t, 0,
b - t - count, vc->vc_cols);
+ else
+ goto redraw_up;
fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
break;

- case __SCROLL_YREDRAW:
+ case SCROLL_REDRAW:
redraw_up:
fbcon_redraw(vc, p, t, b - t - count,
count * vc->vc_cols);
@@ -1402,14 +1403,14 @@
case SM_DOWN:
if (count > vc->vc_rows) /* Maximum realistic size */
count = vc->vc_rows;
- switch (p->scrollmode & __SCROLL_YMASK) {
- case __SCROLL_YMOVE:
+ switch (p->scrollmode) {
+ case SCROLL_ACCEL:
accel_bmove(vc, info, t, 0, t + count, 0,
b - t - count, vc->vc_cols);
accel_clear(vc, info, t, 0, count, vc->vc_cols);
break;

- case __SCROLL_YWRAP:
+ case SCROLL_WRAP:
if (b - t - count > 3 * vc->vc_rows >> 2) {
if (vc->vc_rows - b > 0)
fbcon_bmove(vc, b, 0, b - count, 0,
@@ -1419,15 +1420,15 @@
if (t > 0)
fbcon_bmove(vc, count, 0, 0, 0, t,
vc->vc_cols);
- } else if (p->scrollmode & __SCROLL_YPANREDRAW)
- goto redraw_down;
- else
+ } else if (info->flags & FBINFO_READS_FAST)
fbcon_bmove(vc, t, 0, t + count, 0,
b - t - count, vc->vc_cols);
+ else
+ goto redraw_down;
fbcon_clear(vc, t, 0, count, vc->vc_cols);
break;

- case __SCROLL_YPAN:
+ case SCROLL_PAN:
if ((count - p->yscroll <= p->vrows - vc->vc_rows)
&& ((!scroll_partial && (b - t == vc->vc_rows))
|| (scroll_partial
@@ -1441,15 +1442,15 @@
if (t > 0)
fbcon_bmove(vc, count, 0, 0, 0, t,
vc->vc_cols);
- } else if (p->scrollmode & __SCROLL_YPANREDRAW)
- goto redraw_down;
- else
+ } else if (info->flags & FBINFO_READS_FAST)
fbcon_bmove(vc, t, 0, t + count, 0,
b - t - count, vc->vc_cols);
+ else
+ goto redraw_down;
fbcon_clear(vc, t, 0, count, vc->vc_cols);
break;

- case __SCROLL_YREDRAW:
+ case SCROLL_REDRAW:
redraw_down:
fbcon_redraw(vc, p, b - 1, b - t - count,
-count * vc->vc_cols);
@@ -1594,12 +1595,12 @@
}
if (info)
info->var.yoffset = p->yscroll = 0;
- fbcon_resize(vc, vc->vc_cols, vc->vc_rows);
- switch (p->scrollmode & __SCROLL_YMASK) {
- case __SCROLL_YWRAP:
+ fbcon_resize(vc, vc->vc_cols, vc->vc_rows);
+ switch (p->scrollmode) {
+ case SCROLL_WRAP:
scrollback_phys_max = p->vrows - vc->vc_rows;
break;
- case __SCROLL_YPAN:
+ case SCROLL_PAN:
scrollback_phys_max = p->vrows - 2 * vc->vc_rows;
if (scrollback_phys_max < 0)
scrollback_phys_max = 0;
@@ -2173,11 +2174,11 @@

offset = p->yscroll - scrollback_current;
limit = p->vrows;
- switch (p->scrollmode && __SCROLL_YMASK) {
- case __SCROLL_YWRAP:
+ switch (p->scrollmode) {
+ case SCROLL_WRAP:
info->var.vmode |= FB_VMODE_YWRAP;
break;
- case __SCROLL_YPAN:
+ case SCROLL_PAN:
limit -= vc->vc_rows;
info->var.vmode &= ~FB_VMODE_YWRAP;
break;
diff -Nru a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
--- a/drivers/video/console/fbcon.h Sat May 15 22:53:10 2004
+++ b/drivers/video/console/fbcon.h Sat May 15 22:53:10 2004
@@ -68,40 +68,27 @@
* Scroll Method
*/

-/* Internal flags */
-#define __SCROLL_YPAN 0x001
-#define __SCROLL_YWRAP 0x002
-#define __SCROLL_YMOVE 0x003
-#define __SCROLL_YREDRAW 0x004
-#define __SCROLL_YMASK 0x00f
-#define __SCROLL_YFIXED 0x010
-#define __SCROLL_YNOMOVE 0x020
-#define __SCROLL_YPANREDRAW 0x040
-#define __SCROLL_YNOPARTIAL 0x080
-
-/* Only these should be used by the drivers */
-/* Which one should you use? If you have a fast card and slow bus,
- then probably just 0 to indicate fbcon should choose between
- 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).
+/* There are several methods fbcon can use to move text around the screen:
+ *
+ * + use the hardware engine to move the text
+ * (hw-accelerated copyarea() and fillrect())
+ * + use hardware-supported panning on a large virtual screen
+ * + amifb can not only pan, but also wrap the display by N lines
+ * (i.e. visible line i = physical line (i+N) % yres).
+ * + read what's already rendered on the screen and
+ * write it in a different place (this is cfb_copyarea())
+ * + re-render the text to the screen
+ *
+ * Whether to use wrapping or panning can only be figured out at
+ * runtime (when we know whether our font height is a multiple
+ * of the pan/wrap step)
+ *
*/
-#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
- cards which can not handle using panning to scroll a portion of the
- screen without excessive flicker. Panning will only be used for
- whole screens.
- */
-/* Namespace consistency */
-#define SCROLL_YNOPARTIAL __SCROLL_YNOPARTIAL
+#define SCROLL_ACCEL 0x001
+#define SCROLL_PAN 0x002
+#define SCROLL_WRAP 0x003
+#define SCROLL_REDRAW 0x004

extern int fb_console_init(void);

diff -Nru a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
--- a/drivers/video/skeletonfb.c Sat May 15 22:53:10 2004
+++ b/drivers/video/skeletonfb.c Sat May 15 22:53:10 2004
@@ -539,7 +539,13 @@
info.fbops = &xxxfb_ops;
info.fix = xxxfb_fix;
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;

/*
diff -Nru a/include/linux/fb.h b/include/linux/fb.h
--- a/include/linux/fb.h Sat May 15 22:53:10 2004
+++ b/include/linux/fb.h Sat May 15 22:53:10 2004
@@ -125,7 +125,8 @@
unsigned long mmio_start; /* Start of Memory Mapped I/O */
/* (physical address) */
__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 */
};

@@ -154,7 +155,7 @@
#define FB_ACTIVATE_ALL 64 /* change all VCs on this fb */
#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_VERT_HIGH_ACT 2 /* vertical sync high active */
@@ -200,7 +201,7 @@
__u32 height; /* height 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) */
__u32 pixclock; /* pixel clock in ps (pico seconds) */
@@ -502,10 +503,28 @@
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
+
+/* 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 */
+#define FBINFO_HWACCEL_NONE 0x0000
+#define FBINFO_HWACCEL_COPYAREA 0x0100
+#define FBINFO_HWACCEL_FILLRECT 0x0200
+#define FBINFO_HWACCEL_ROTATE 0x0400
+#define FBINFO_HWACCEL_IMAGEBLIT 0x0800
+#define FBINFO_HWACCEL_XPAN 0x1000
+#define FBINFO_HWACCEL_YPAN 0x2000
+#define FBINFO_HWACCEL_YWRAP 0x4000
+
+
struct fb_info {
int node;
int flags;
-#define FBINFO_FLAG_MODULE 1 /* Low-level driver is a module */
struct fb_var_screeninfo var; /* Current var */
struct fb_fix_screeninfo fix; /* Current fix */
struct fb_monspecs monspecs; /* Current Monitor specs */
@@ -528,9 +547,9 @@
};

#ifdef MODULE
-#define FBINFO_FLAG_DEFAULT FBINFO_FLAG_MODULE
+#define FBINFO_DEFAULT FBINFO_MODULE
#else
-#define FBINFO_FLAG_DEFAULT 0
+#define FBINFO_DEFAULT 0
#endif

// This will go away