2003-01-04 09:29:46

by Antonino A. Daplas

[permalink] [raw]
Subject: [PATCH][FBDEV]: fb_putcs() and fb_setfont() methods

Attached is a patch against 2.5.54 in an attempt to add putcs() and
setfont() methods for fbdev drivers that require them:

...
struct fb_char {
__u32 dx; /* where to place chars, in pixels */
__u32 dy; /* where to place chars, in scanline */
__u32 len; /* number of characters */
__u32 fg_color;
__u32 bg_color;
__u32 *data; /* array of indices to fontdata */
};

struct fb_fontdata {
__u32 width; /* font width */
__u32 height; /* font height */
__u32 len; /* number of characters */
__u8 *data; /* character map */
};

...

/* upload character map */
int (*fb_setfont)(struct fb_info *info, const struct fb_fontdata
*font);
/* write characters */
int (*fb_putcs)(struct fb_info *info, const struct fb_char *chars);

fb_setfont() uploads the character map to fbdev and makes it the current
map

fb_putcs() writes characters to display

I also did some rudimentary testing by adding test hooks to various
fbdev drivers but haven't examined its full effects (ie, different
character maps per console).

Tony

diff -Naur linux-2.5.54/drivers/video/console/fbcon.c linux/drivers/video/console/fbcon.c
--- linux-2.5.54/drivers/video/console/fbcon.c 2003-01-04 09:01:10.000000000 +0000
+++ linux/drivers/video/console/fbcon.c 2003-01-04 09:00:04.000000000 +0000
@@ -378,61 +378,97 @@
info->fbops->fb_fillrect(info, &region);
}

+#define FB_PIXMAPSIZE 8192
void accel_putcs(struct vc_data *vc, struct display *p,
const unsigned short *s, int count, int yy, int xx)
{
+ static u8 pixmap[FB_PIXMAPSIZE];
struct fb_info *info = p->fb_info;
unsigned short charmask = p->charmask;
unsigned int width = ((vc->vc_font.width + 7)/8);
- unsigned int cellsize = vc->vc_font.height * width;
- struct fb_image image;
+ unsigned int cnt, i, j, k;
+ unsigned int maxcnt;
u16 c = scr_readw(s);
- static u8 pixmap[8192];
+
+ if (info->fbops->fb_putcs) {
+ struct fb_char chars;
+
+ maxcnt = FB_PIXMAPSIZE/4;
+ chars.dx = xx * vc->vc_font.width;
+ chars.dy = yy * vc->vc_font.height;
+ chars.fg_color = attr_fgcol(p, c);
+ chars.bg_color = attr_bgcol(p, c);
+ chars.data = (u32 *) pixmap;
+
+ while (count) {
+ if (count > maxcnt)
+ cnt = maxcnt;
+ else
+ cnt = count;
+ chars.len = cnt;
+ for (i = 0; i < cnt; i++)
+ ((u32 *)pixmap)[i] = (u32) (scr_readw(s++) &
+ charmask);
+
+ info->fbops->fb_putcs(info, &chars);
+ chars.dx += cnt * vc->vc_font.width;
+ count -= cnt;
+ }
+ }
+ else {
+ unsigned int cellsize = vc->vc_font.height * width;
+ struct fb_image image;

- image.fg_color = attr_fgcol(p, c);
- image.bg_color = attr_bgcol(p, c);
- image.dx = xx * vc->vc_font.width;
- image.dy = yy * vc->vc_font.height;
- image.height = vc->vc_font.height;
- image.depth = 1;
-
-/* pixmap = kmalloc((info->var.bits_per_pixel + 7) >> 3 *
- vc->vc_font.height, GFP_KERNEL);
-*/
+ image.fg_color = attr_fgcol(p, c);
+ image.bg_color = attr_bgcol(p, c);
+ image.dx = xx * vc->vc_font.width;
+ image.dy = yy * vc->vc_font.height;
+ image.height = vc->vc_font.height;
+ image.depth = 1;
+
+ if (!(vc->vc_font.width & 7)) {
+ unsigned int pitch;
+ char *src, *dst, *dst0;
+
+ maxcnt = FB_PIXMAPSIZE/(vc->vc_font.height * width);
+ image.data = pixmap;
+ while (count) {
+ if (count > maxcnt)
+ cnt = k = maxcnt;
+ else
+ cnt = k = count;

- if (!(vc->vc_font.width & 7) && pixmap != NULL) {
- unsigned int pitch = width * count, i, j;
- char *src, *dst, *dst0;
-
- dst0 = pixmap;
- image.width = vc->vc_font.width * count;
- image.data = pixmap;
- while (count--) {
- src = p->fontdata + (scr_readw(s++) & charmask) * cellsize;
- dst = dst0;
- for (i = image.height; i--; ) {
- for (j = 0; j < width; j++)
- dst[j] = *src++;
- dst += pitch;
+ dst0 = pixmap;
+ pitch = width * cnt;
+ image.width = vc->vc_font.width * cnt;
+ while (k--) {
+ src = p->fontdata +
+ (scr_readw(s++)&charmask) *
+ cellsize;
+ dst = dst0;
+ for (i = image.height; i--; ) {
+ for (j = 0; j < width; j++)
+ dst[j] = *src++;
+ dst += pitch;
+ }
+ dst0 += width;
+ }
+
+ info->fbops->fb_imageblit(info, &image);
+ image.dx += cnt * vc->vc_font.width;
+ count -= cnt;
}
- dst0 += width;
+ } else {
+ image.width = vc->vc_font.width;
+ while (count--) {
+ image.data = p->fontdata +
+ (scr_readw(s++) & charmask) *
+ vc->vc_font.height * width;
+ info->fbops->fb_imageblit(info, &image);
+ image.dx += vc->vc_font.width;
+ }
}
- info->fbops->fb_imageblit(info, &image);
- if (info->fbops->fb_sync)
- info->fbops->fb_sync(info);
- } else {
- image.width = vc->vc_font.width;
- while (count--) {
- image.data = p->fontdata +
- (scr_readw(s++) & charmask) * vc->vc_font.height * width;
- info->fbops->fb_imageblit(info, &image);
- image.dx += vc->vc_font.width;
- }
}
- /*
- if (pixmap);
- kfree(pixmap);
- */
}

void accel_clear_margins(struct vc_data *vc, struct display *p,
@@ -1144,8 +1180,6 @@
struct display *p = &fb_display[vc->vc_num];
struct fb_info *info = p->fb_info;
unsigned short charmask = p->charmask;
- unsigned int width = ((vc->vc_font.width + 7) >> 3);
- struct fb_image image;
int redraw_cursor = 0;

if (!p->can_soft_blank && console_blanked)
@@ -1158,18 +1192,35 @@
cursor_undrawn();
redraw_cursor = 1;
}
+
+ if (info->fbops->fb_putcs) {
+ struct fb_char chars;
+ u32 font = c & charmask;
+
+ chars.dx = xpos * vc->vc_font.width;
+ chars.dy = real_y(p, ypos) * vc->vc_font.height;
+ chars.len = 1;
+ chars.fg_color = attr_fgcol(p, c);
+ chars.bg_color = attr_bgcol(p, c);
+ chars.data = &font;

- image.fg_color = attr_fgcol(p, c);
- image.bg_color = attr_bgcol(p, c);
- image.dx = xpos * vc->vc_font.width;
- image.dy = real_y(p, ypos) * vc->vc_font.height;
- image.width = vc->vc_font.width;
- image.height = vc->vc_font.height;
- image.depth = 1;
- image.data = p->fontdata + (c & charmask) * vc->vc_font.height * width;
-
- info->fbops->fb_imageblit(info, &image);
-
+ info->fbops->fb_putcs(info, &chars);
+ }
+ else {
+ struct fb_image image;
+ unsigned int width = ((vc->vc_font.width + 7) >> 3);
+
+ image.fg_color = attr_fgcol(p, c);
+ image.bg_color = attr_bgcol(p, c);
+ image.dx = xpos * vc->vc_font.width;
+ image.dy = real_y(p, ypos) * vc->vc_font.height;
+ image.width = vc->vc_font.width;
+ image.height = vc->vc_font.height;
+ image.depth = 1;
+ image.data = p->fontdata + (c & charmask) * vc->vc_font.height * width;
+
+ info->fbops->fb_imageblit(info, &image);
+ }
if (redraw_cursor)
vbl_cursor_cnt = CURSOR_DRAW_DELAY;
}
@@ -1271,16 +1322,9 @@

int update_var(int con, struct fb_info *info)
{
- int err;
+ if (con == info->currcon)
+ return fb_pan_display(&info->var, info);

- if (con == info->currcon) {
- if (info->fbops->fb_pan_display) {
- if ((err =
- info->fbops->fb_pan_display(&info->var,
- info)))
- return err;
- }
- }
return 0;
}

@@ -1918,6 +1962,18 @@
scrollback_max = 0;
scrollback_current = 0;

+ if (info->fbops->fb_setfont) {
+ struct fb_fontdata font;
+
+ font.width = vc->vc_font.width;
+ font.height = vc->vc_font.height;
+ font.len = FNTCHARCNT(p->fontdata);
+ font.data = p->fontdata;
+
+ if (info->fbops->fb_setfont(info, &font))
+ return 0;
+ }
+
info->currcon = unit;

update_var(unit, info);
@@ -2133,6 +2189,18 @@

}

+ if (info->fbops->fb_setfont) {
+ struct fb_fontdata font;
+
+ font.width = vc->vc_font.width;
+ font.height = vc->vc_font.height;
+ font.len = cnt;
+ font.data = p->fontdata;
+
+ if (info->fbops->fb_setfont(info, &font))
+ return 1;
+ }
+
if (resize) {
/* reset wrap/pan */
info->var.xoffset = info->var.yoffset = p->yscroll = 0;
diff -Naur linux-2.5.54/include/linux/fb.h linux/include/linux/fb.h
--- linux-2.5.54/include/linux/fb.h 2003-01-04 09:01:31.000000000 +0000
+++ linux/include/linux/fb.h 2003-01-04 09:00:35.000000000 +0000
@@ -295,6 +295,23 @@
struct fb_cmap cmap; /* color map info */
};

+struct fb_char {
+ __u32 dx; /* where to place chars, in pixels */
+ __u32 dy; /* where to place chars, in scanline */
+ __u32 len; /* number of characters */
+ __u32 fg_color;
+ __u32 bg_color;
+ __u32 *data; /* array of indices to fontdata */
+};
+
+struct fb_fontdata {
+ __u32 width; /* font width */
+ __u32 height; /* font height */
+ __u32 len; /* number of characters */
+ __u8 *data; /* character map */
+};
+
+
/*
* hardware cursor control
*/
@@ -375,6 +392,10 @@
unsigned long arg, struct fb_info *info);
/* perform fb specific mmap */
int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma);
+ /* upload character map */
+ int (*fb_setfont)(struct fb_info *info, const struct fb_fontdata *font);
+ /* write characters */
+ int (*fb_putcs)(struct fb_info *info, const struct fb_char *chars);
};

struct fb_info {





2003-01-04 13:52:54

by jurriaan

[permalink] [raw]
Subject: Re: [PATCH][FBDEV]: fb_putcs() and fb_setfont() methods

From: Antonino Daplas <[email protected]>
Date: Sat, Jan 04, 2003 at 05:25:14PM +0800
> Attached is a patch against 2.5.54 in an attempt to add putcs() and
> setfont() methods for fbdev drivers that require them:
>
And those drivers would be the matrox framebuffer drivers, for example?

That would be really great!

Thanks,
Jurriaan
--
Me I'm just like you
I don't have a clue
Shotgun Messiah - Nobody's Home
GNU/Linux 2.5.53 SMP/ReiserFS 2x2752 bogomips 7 users load av: 2.24 1.99 1.56

2003-01-04 20:33:41

by Petr Vandrovec

[permalink] [raw]
Subject: Re: [PATCH][FBDEV]: fb_putcs() and fb_setfont() methods

On Sat, Jan 04, 2003 at 05:25:14PM +0800, Antonino Daplas wrote:
> Attached is a patch against 2.5.54 in an attempt to add putcs() and
> setfont() methods for fbdev drivers that require them:

Looks good.

> ...
> struct fb_char {
> __u32 dx; /* where to place chars, in pixels */
> __u32 dy; /* where to place chars, in scanline */

These two are questionable. I do not know what DaveM will need, but
I'll be happier with character coordinates for text mode. So for me it is
just question whether I'll do divide by width/height stored from setfont
in text mode, or multiply when in graphics mode. So I must remember
character cell size in any case. But having multiply in matroxfb could
save multiply here in generic code.

I have strong feeling that doing multiply in generic code, and then divide
in fbdev driver is waste of time, but if Dave is happier with pixel
coordinates, I can definitely live with it.

> __u32 len; /* number of characters */
> __u32 fg_color;
> __u32 bg_color;
> __u32 *data; /* array of indices to fontdata */
> };
>
> struct fb_fontdata {
> __u32 width; /* font width */
> __u32 height; /* font height */
> __u32 len; /* number of characters */
> __u8 *data; /* character map */
> };
>
> ...
>
> /* upload character map */
> int (*fb_setfont)(struct fb_info *info, const struct fb_fontdata
> *font);
> /* write characters */
> int (*fb_putcs)(struct fb_info *info, const struct fb_char *chars);
>

It would be nice to have old accel_putcs() available for modules, so driver
could decide on case-by-case basis whether it will use its own code or
generic without touching pointer (without modifying potentially constant
fb_ops structure common to all fbdev instances).
Thanks,
Petr Vandrovec
[email protected]

2003-01-04 20:59:00

by James Simmons

[permalink] [raw]
Subject: Re: [Linux-fbdev-devel] [PATCH][FBDEV]: fb_putcs() and fb_setfont() methods


Rejected. I have put thought into it and the whole point was to not allow
the fbdev layer to touch console data. I stand firm on this!!! The reason
being is the core console layer is going to change the next development
cycle. We have to change to deal with things like the PC9800 type hardware
that support more than 512 fonts. Do we realy want to break every fbdev
driver again. This way the breakage is once and for all. Its is also a
pandoras box. If we place these hooks in we end up with the same crappy
driver problem we had before. I never heard anyone every say the old api
we clean.

2003-01-04 21:00:17

by James Simmons

[permalink] [raw]
Subject: Re: [PATCH][FBDEV]: fb_putcs() and fb_setfont() methods


> > Attached is a patch against 2.5.54 in an attempt to add putcs() and
> > setfont() methods for fbdev drivers that require them:
> >
> And those drivers would be the matrox framebuffer drivers, for example?
>
> That would be really great!

I'm porting this driver to the new api. I'm alomst finished with the
nvidia driver. Once I'm done on that the matrox driver is next. Sorry it
is taking so long but I have alot of drivers to deal with.

2003-01-04 21:03:54

by James Simmons

[permalink] [raw]
Subject: Re: [PATCH][FBDEV]: fb_putcs() and fb_setfont() methods


> I'll be happier with character coordinates for text mode.

Yuck!! Using fbcon for text modes is just bloat. For hardware text mode it
is much better to write a nice small console driver like newport_con.c

> could decide on case-by-case basis whether it will use its own code or
> generic without touching pointer (without modifying potentially constant
> fb_ops structure common to all fbdev instances).

The patch was rejected. I working on your driver. I can throw in a text
mode driver as well.

2003-01-04 22:10:36

by Antonino A. Daplas

[permalink] [raw]
Subject: Re: [Linux-fbdev-devel] [PATCH][FBDEV]: fb_putcs() and fb_setfont() methods

On Sun, 2003-01-05 at 05:07, James Simmons wrote:
>
> Rejected. I have put thought into it and the whole point was to not allow

Personally, that's fine by me since I have no need for those 2
extensions. But please apply the accel_putcs() buffer overrun patch.

BTW, attached is another patch that will change the resolution of the
console via tty ioctl TIOCSWINSZ. I'm not sure if this is the correct
solution, but it's the only one I can think of without really adding a
lot of extra code. This is implemented by adding a con_resize() hook to
fbcon, so the window size can be changed such as by using:

stty cols 128 rows 48 (1024x768 with font 8x16)

The new window size should also be preserved per console. Still, there
are other fb parameters that can screw up the console (such as changing
yres_virtual and bits_per_pixel) but the window size is the most
important.

Tony

diff -Naur linux-2.5.54/drivers/video/console/fbcon.c linux/drivers/video/console/fbcon.c
--- linux-2.5.54/drivers/video/console/fbcon.c 2003-01-04 21:58:47.000000000 +0000
+++ linux/drivers/video/console/fbcon.c 2003-01-04 21:58:24.000000000 +0000
@@ -1871,6 +1871,25 @@
}


+static int fbcon_resize(struct vc_data *vc, unsigned int width,
+ unsigned int height)
+{
+ struct display *p = &fb_display[vc->vc_num];
+ struct fb_info *info = p->fb_info;
+ struct fb_var_screeninfo var = info->var;
+ int err;
+
+ var.xres = width * vc->vc_font.width;
+ var.yres = height * vc->vc_font.height;
+ var.activate = FB_ACTIVATE_NOW;
+
+ err = fb_set_var(&var, info);
+ return (err || var.xres != info->var.xres ||
+ var.yres != info->var.yres) ?
+ -EINVAL : 0;
+
+}
+
static int fbcon_switch(struct vc_data *vc)
{
int unit = vc->vc_num;
@@ -1920,6 +1939,7 @@

info->currcon = unit;

+ fbcon_resize(vc, vc->vc_cols, vc->vc_rows);
update_var(unit, info);

if (vt_cons[unit]->vc_mode == KD_TEXT)
@@ -2537,6 +2557,7 @@
.con_invert_region = fbcon_invert_region,
.con_screen_pos = fbcon_screen_pos,
.con_getxy = fbcon_getxy,
+ .con_resize = fbcon_resize,
};

int __init fb_console_init(void)

2003-01-04 23:09:39

by Petr Vandrovec

[permalink] [raw]
Subject: Re: [PATCH][FBDEV]: fb_putcs() and fb_setfont() methods

On Sat, Jan 04, 2003 at 09:12:24PM +0000, James Simmons wrote:
>
> > I'll be happier with character coordinates for text mode.
>
> Yuck!! Using fbcon for text modes is just bloat. For hardware text mode it
> is much better to write a nice small console driver like newport_con.c

When I said before christmas that I'll have to write matroxcon to get
reasonable functionality, you laughed... Now, it is clear that there is
no other way...

> > could decide on case-by-case basis whether it will use its own code or
> > generic without touching pointer (without modifying potentially constant
> > fb_ops structure common to all fbdev instances).
>
> The patch was rejected. I working on your driver. I can throw in a text
> mode driver as well.

You can throw anything in and out, of course... It is GPL, after all.
Only question left is whether I'll be satisfied with functionality you
offer.
Best regards,
Petr Vandrovec
[email protected]

2003-01-04 23:22:14

by Petr Vandrovec

[permalink] [raw]
Subject: Re: [Linux-fbdev-devel] [PATCH][FBDEV]: fb_putcs() and fb_setfont() methods

On Sat, Jan 04, 2003 at 09:07:29PM +0000, James Simmons wrote:
>
> Rejected. I have put thought into it and the whole point was to not allow
> the fbdev layer to touch console data. I stand firm on this!!! The reason
> being is the core console layer is going to change the next development
> cycle. We have to change to deal with things like the PC9800 type hardware
> that support more than 512 fonts. Do we realy want to break every fbdev
> driver again. This way the breakage is once and for all. Its is also a

Why? (a) only those which will use putcs, and (b) I see no 512 chars limit
anywhere in new code. And in old code it is there only because of passed
data are only 16bit, not 32bit wide... With simple search&replace you can
extend it to any size you want, as long as you'll not use sparse font
bitmap.

> pandoras box. If we place these hooks in we end up with the same crappy
> driver problem we had before. I never heard anyone every say the old api
> we clean.

I believe that I repeatedly said that I see no problem with old API which
cannot be solved by incremental updates and without removing functionality.

It is like with modules - some believe in evolution, and some in revolution...
Fortunately modules situation finally settled down and it is enough just install
new app to handle module loading/unloading. With current fbdev even trivial
console resizing does not do anything useful (thanks, Antonio).
Best regards,
Petr Vandrovec
[email protected]

2003-01-07 21:35:35

by James Simmons

[permalink] [raw]
Subject: Re: [Linux-fbdev-devel] [PATCH][FBDEV]: fb_putcs() and fb_setfont() methods


> Personally, that's fine by me since I have no need for those 2
> extensions. But please apply the accel_putcs() buffer overrun patch.

Applied.

> BTW, attached is another patch that will change the resolution of the
> console via tty ioctl TIOCSWINSZ. I'm not sure if this is the correct
> solution, but it's the only one I can think of without really adding a
> lot of extra code. This is implemented by adding a con_resize() hook to
> fbcon, so the window size can be changed such as by using:
>
> stty cols 128 rows 48 (1024x768 with font 8x16)

Yes this is the correct approach.

> The new window size should also be preserved per console. Still, there
> are other fb parameters that can screw up the console (such as changing
> yres_virtual and bits_per_pixel) but the window size is the most
> important.

Updatevar in fbcon.c should handle yres_virtual properly. The scrolling
code needs alot of work. It is a mess. Bits_per_pixel will be trickier to
handle.

2003-01-07 21:38:52

by James Simmons

[permalink] [raw]
Subject: Re: [Linux-fbdev-devel] Re: [PATCH][FBDEV]: fb_putcs() and fb_setfont() methods


> > > I'll be happier with character coordinates for text mode.
> >
> > Yuck!! Using fbcon for text modes is just bloat. For hardware text mode it
> > is much better to write a nice small console driver like newport_con.c
>
> When I said before christmas that I'll have to write matroxcon to get
> reasonable functionality, you laughed... Now, it is clear that there is
> no other way...

No I didn't laugh. I didn't like the idea of another fbcon like system
being developed just to support this text mode. I have no problem with
a matroxcon.

> You can throw anything in and out, of course... It is GPL, after all.
> Only question left is whether I'll be satisfied with functionality you
> offer.

:-) I'm working on your driver the latest few days. I managed to shrink
most of the accel code into one common base.I still have alot to go tho.
You have a matroxfb_check_var which makes my life much easier.


2003-01-07 21:44:21

by James Simmons

[permalink] [raw]
Subject: Re: [Linux-fbdev-devel] [PATCH][FBDEV]: fb_putcs() and fb_setfont() methods


> Why? (a) only those which will use putcs, and (b) I see no 512 chars limit
> anywhere in new code. And in old code it is there only because of passed
> data are only 16bit, not 32bit wide... With simple search&replace you can
> extend it to any size you want, as long as you'll not use sparse font
> bitmap.

The current "core" console code screen_buf layout is designed after VGA
text mode. 16 bits which only 8 bits are used to represent a character, 9
if you have high_fonts flag set. The other 8,7 bits are for attributes.
This is very limiting and it does effect fbcon.c :-( I like to the console
system remove these awful limitation in the future. This why I like to see
fbdev drivers avoid touching strings from the console layer.


2003-01-08 10:44:50

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [Linux-fbdev-devel] [PATCH][FBDEV]: fb_putcs() and fb_setfont() methods

On Tue, 7 Jan 2003, James Simmons wrote:
> > Why? (a) only those which will use putcs, and (b) I see no 512 chars limit
> > anywhere in new code. And in old code it is there only because of passed
> > data are only 16bit, not 32bit wide... With simple search&replace you can
> > extend it to any size you want, as long as you'll not use sparse font
> > bitmap.
>
> The current "core" console code screen_buf layout is designed after VGA
> text mode. 16 bits which only 8 bits are used to represent a character, 9
> if you have high_fonts flag set. The other 8,7 bits are for attributes.
> This is very limiting and it does effect fbcon.c :-( I like to the console
> system remove these awful limitation in the future. This why I like to see
> fbdev drivers avoid touching strings from the console layer.

Please note that Tony's new accel_putcs() code uses __u32 to pass the character
indices. So it's not limited to 256/512 characters per font. Fonts can be as
large as you want. Sparse fonts can be handled as well, if accel_putcs() takes
care of the conversion from sparse character indices to dense character
indices.

His code can be viewed as a way to do multiple monochrome to color expansions
with one single call, using a predefined table of patterns. Quite generic,
unless you want to have multi-color fonts later :-)

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

2003-01-08 18:22:57

by Antonino A. Daplas

[permalink] [raw]
Subject: Re: [Linux-fbdev-devel] [PATCH][FBDEV]: fb_putcs() and fb_setfont() methods

On Wed, 2003-01-08 at 18:47, Geert Uytterhoeven wrote:
> On Tue, 7 Jan 2003, James Simmons wrote:
> > > Why? (a) only those which will use putcs, and (b) I see no 512 chars limit
> > > anywhere in new code. And in old code it is there only because of passed
> > > data are only 16bit, not 32bit wide... With simple search&replace you can
> > > extend it to any size you want, as long as you'll not use sparse font
> > > bitmap.
> >
> > The current "core" console code screen_buf layout is designed after VGA
> > text mode. 16 bits which only 8 bits are used to represent a character, 9
> > if you have high_fonts flag set. The other 8,7 bits are for attributes.
> > This is very limiting and it does effect fbcon.c :-( I like to the console
> > system remove these awful limitation in the future. This why I like to see
> > fbdev drivers avoid touching strings from the console layer.
>
> Please note that Tony's new accel_putcs() code uses __u32 to pass the character
> indices. So it's not limited to 256/512 characters per font. Fonts can be as
> large as you want. Sparse fonts can be handled as well, if accel_putcs() takes
> care of the conversion from sparse character indices to dense character
> indices.
>
> His code can be viewed as a way to do multiple monochrome to color expansions
> with one single call, using a predefined table of patterns. Quite generic,
> unless you want to have multi-color fonts later :-)
>
:-) I did not want prolong the discussion, but...

Geert is correct that the functions are generic. The fb_putcs() and
fb_setfont() can be compared to Tile blitting. Tile blitting is a
common operation in some games such as Warcraft, Starcraft, and most
RPG's. I'm think there is Tile Blitting support in DirectFB.

In a tile-based game, the basic unit is a Tile which is just a bitmap
with a predefined width and height. The game has several tiles stored in
memory each with it's own unique id. To draw the background/layer, a
TileMap is constructed which is basically another array. Its format is
something like this - TileMap[x] = y which means draw Tile y at screen
position x.

In the fbcon perspective, we can think of each character as a Tile, and
fontdata as the collection of tiles. fb_char.data is basically a
TileMap. Of course, tile blitting in games is more complicated than
this, since games have multiple layers for the background, so layer
position, transparency, etc has to be considered.

So maybe if we can rename fb_putcs() to fb_tileblit(), fb_setfont() to
fb_loadtiles(), struct fb_chars to struct fb_tilemap and struct
fb_fontdata to struct fb_tiledata, maybe it will be more acceptable?

It can be even be expanded by including fb_tiledata.depth
fb_tiledata.cmap so we can support multi-colored tiled blitting.

Tony




2003-01-09 18:01:26

by James Simmons

[permalink] [raw]
Subject: Re: [Linux-fbdev-devel] [PATCH][FBDEV]: fb_putcs() and fb_setfont() methods


> :-) I did not want prolong the discussion, but...
>
> Geert is correct that the functions are generic. The fb_putcs() and
> fb_setfont() can be compared to Tile blitting. Tile blitting is a
> common operation in some games such as Warcraft, Starcraft, and most
> RPG's. I'm think there is Tile Blitting support in DirectFB.
>
> In a tile-based game, the basic unit is a Tile which is just a bitmap
> with a predefined width and height. The game has several tiles stored in
> memory each with it's own unique id. To draw the background/layer, a
> TileMap is constructed which is basically another array. Its format is
> something like this - TileMap[x] = y which means draw Tile y at screen
> position x.
>
> In the fbcon perspective, we can think of each character as a Tile, and
> fontdata as the collection of tiles. fb_char.data is basically a
> TileMap. Of course, tile blitting in games is more complicated than
> this, since games have multiple layers for the background, so layer
> position, transparency, etc has to be considered.
>
> So maybe if we can rename fb_putcs() to fb_tileblit(), fb_setfont() to
> fb_loadtiles(), struct fb_chars to struct fb_tilemap and struct
> fb_fontdata to struct fb_tiledata, maybe it will be more acceptable?
>
> It can be even be expanded by including fb_tiledata.depth
> fb_tiledata.cmap so we can support multi-colored tiled blitting.

This I have no problem with. I'm willing to accept this. As long as data
from the console layer is not touched. As for loadtiles one thing I like
to address is memory allocation. It probable is good idea to do things
like place the tile data in buffers allocated by pci_alloc_consistent.
The other fear is it will only support so many tiles.



2003-01-09 20:47:23

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [Linux-fbdev-devel] [PATCH][FBDEV]: fb_putcs() and fb_setfont() methods

On Thu, 9 Jan 2003, James Simmons wrote:
> > :-) I did not want prolong the discussion, but...
> >
> > Geert is correct that the functions are generic. The fb_putcs() and
> > fb_setfont() can be compared to Tile blitting. Tile blitting is a
> > common operation in some games such as Warcraft, Starcraft, and most
> > RPG's. I'm think there is Tile Blitting support in DirectFB.
> >
> > In a tile-based game, the basic unit is a Tile which is just a bitmap
> > with a predefined width and height. The game has several tiles stored in
> > memory each with it's own unique id. To draw the background/layer, a
> > TileMap is constructed which is basically another array. Its format is
> > something like this - TileMap[x] = y which means draw Tile y at screen
> > position x.
> >
> > In the fbcon perspective, we can think of each character as a Tile, and
> > fontdata as the collection of tiles. fb_char.data is basically a
> > TileMap. Of course, tile blitting in games is more complicated than
> > this, since games have multiple layers for the background, so layer
> > position, transparency, etc has to be considered.
> >
> > So maybe if we can rename fb_putcs() to fb_tileblit(), fb_setfont() to
> > fb_loadtiles(), struct fb_chars to struct fb_tilemap and struct
> > fb_fontdata to struct fb_tiledata, maybe it will be more acceptable?
> >
> > It can be even be expanded by including fb_tiledata.depth
> > fb_tiledata.cmap so we can support multi-colored tiled blitting.
>
> This I have no problem with. I'm willing to accept this. As long as data
> from the console layer is not touched. As for loadtiles one thing I like
> to address is memory allocation. It probable is good idea to do things
> like place the tile data in buffers allocated by pci_alloc_consistent.
> The other fear is it will only support so many tiles.

I think it's best to let the driver allocate it. That way the driver can put it
where it's best suited. pci_alloc_consistent() is meant for PCI only.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

2003-01-09 21:16:55

by James Simmons

[permalink] [raw]
Subject: Re: [Linux-fbdev-devel] [PATCH][FBDEV]: fb_putcs() and fb_setfont() methods


> > This I have no problem with. I'm willing to accept this. As long as data
> > from the console layer is not touched. As for loadtiles one thing I like
> > to address is memory allocation. It probable is good idea to do things
> > like place the tile data in buffers allocated by pci_alloc_consistent.
> > The other fear is it will only support so many tiles.
>
> I think it's best to let the driver allocate it. That way the driver can put it
> where it's best suited. pci_alloc_consistent() is meant for PCI only.

Sorry about the confusiing. I was meaning things like pci_alloc_consistent
of course would be handled for each driver that needed it.

2003-01-10 14:39:24

by Antonino A. Daplas

[permalink] [raw]
Subject: Re: [Linux-fbdev-devel] [PATCH][FBDEV]: fb_putcs() and fb_setfont() methods

On Fri, 2003-01-10 at 02:09, James Simmons wrote:
> >
> > So maybe if we can rename fb_putcs() to fb_tileblit(), fb_setfont() to
> > fb_loadtiles(), struct fb_chars to struct fb_tilemap and struct
> > fb_fontdata to struct fb_tiledata, maybe it will be more acceptable?
> >
> > It can be even be expanded by including fb_tiledata.depth
> > fb_tiledata.cmap so we can support multi-colored tiled blitting.
>
> This I have no problem with. I'm willing to accept this. As long as data
> from the console layer is not touched. As for loadtiles one thing I like
> to address is memory allocation. It probable is good idea to do things
> like place the tile data in buffers allocated by pci_alloc_consistent.
> The other fear is it will only support so many tiles.
>

Hmm, so you're willing to accept this... okay, attached is another
patch, made it a bit cleaner so none of the console data will be ever
touched. Also expanded it so tile blitting has an equivalent
counterpart with classic blitting.

Thinking about it, I think tile blitting may one day become useful if
ever the console supports more than 16-colors. Imagine how expensive it
would be to draw 32-bit fonts using classic blitting.

Tried it with a few test hooks, works fine except for one thing: the
font is initially scrambled at boot, but became fixed later on. I don't
know how to fix that.

Tony


diff -Naur linux-2.5.54/drivers/video/console/fbcon.c linux/drivers/video/console/fbcon.c
--- linux-2.5.54/drivers/video/console/fbcon.c 2003-01-10 11:08:04.000000000 +0000
+++ linux/drivers/video/console/fbcon.c 2003-01-10 11:04:59.000000000 +0000
@@ -350,35 +350,91 @@
{
struct fb_info *info = p->fb_info;
struct vc_data *vc = p->conp;
- struct fb_copyarea area;

- area.sx = sx * vc->vc_font.width;
- area.sy = sy * vc->vc_font.height;
- area.dx = dx * vc->vc_font.width;
- area.dy = dy * vc->vc_font.height;
- area.height = height * vc->vc_font.height;
- area.width = width * vc->vc_font.width;
+ if (info->caps & FB_CAPS_TILEBLIT && info->tileops) {
+ struct fb_tilecopy tilerect;

- info->fbops->fb_copyarea(info, &area);
+ tilerect.sx = sx;
+ tilerect.sy = sy;
+ tilerect.dx = dx;
+ tilerect.dy = dy;
+ tilerect.width = width;
+ tilerect.height = height;
+
+ info->tileops->fb_tilecopy(info, &tilerect);
+ } else {
+ struct fb_copyarea area;
+
+ area.sx = sx * vc->vc_font.width;
+ area.sy = sy * vc->vc_font.height;
+ area.dx = dx * vc->vc_font.width;
+ area.dy = dy * vc->vc_font.height;
+ area.height = height * vc->vc_font.height;
+ area.width = width * vc->vc_font.width;
+
+ info->fbops->fb_copyarea(info, &area);
+ }
}

void accel_clear(struct vc_data *vc, struct display *p, int sy,
int sx, int height, int width)
{
struct fb_info *info = p->fb_info;
- struct fb_fillrect region;
+ if (info->caps & FB_CAPS_TILEBLIT && info->tileops) {
+ struct fb_tilefill tilerect;

- region.color = attr_bgcol_ec(p, vc);
- region.dx = sx * vc->vc_font.width;
- region.dy = sy * vc->vc_font.height;
- region.width = width * vc->vc_font.width;
- region.height = height * vc->vc_font.height;
- region.rop = ROP_COPY;
+ tilerect.dx = sx;
+ tilerect.dy = sy;
+ tilerect.width = width;
+ tilerect.height = height;
+ tilerect.fg_color = attr_fgcol_ec(p, vc);
+ tilerect.bg_color = attr_bgcol_ec(p, vc);
+ tilerect.idx = vc->vc_video_erase_char & p->charmask;
+ tilerect.rop = ROP_COPY;

- info->fbops->fb_fillrect(info, &region);
-}
+ info->tileops->fb_tilefill(info, &tilerect);
+ } else {
+ struct fb_fillrect region;
+
+ region.color = attr_bgcol_ec(p, vc);
+ region.dx = sx * vc->vc_font.width;
+ region.dy = sy * vc->vc_font.height;
+ region.width = width * vc->vc_font.width;
+ region.height = height * vc->vc_font.height;
+ region.rop = ROP_COPY;
+
+ info->fbops->fb_fillrect(info, &region);
+ }
+}

#define FB_PIXMAPSIZE 8192
+static void tile_putcs(struct vc_data *vc, struct display *p, u32 *tilemap,
+ const unsigned short *s, int count, int yy, int xx)
+{
+ struct fb_info *info = p->fb_info;
+ struct fb_tileblit tilerect;
+ int maxcnt = FB_PIXMAPSIZE/4, i, cnt;
+ u16 c = scr_readw(s);
+
+ tilerect.dx = xx;
+ tilerect.dy = yy;
+ tilerect.height = 1;
+ tilerect.fg_color = attr_fgcol(p, c);
+ tilerect.bg_color = attr_bgcol(p, c);
+ tilerect.data = tilemap;
+
+ while (count) {
+ cnt = (count > maxcnt) ? maxcnt : count;
+ tilerect.width = cnt;
+ for (i = 0; i < cnt; i++)
+ tilemap[i] = (u32) (scr_readw(s++) & p->charmask);
+
+ info->tileops->fb_tileblit(info, &tilerect);
+ tilerect.dx += cnt;
+ count -= cnt;
+ }
+}
+
void accel_putcs(struct vc_data *vc, struct display *p,
const unsigned short *s, int count, int yy, int xx)
{
@@ -390,6 +446,11 @@
u16 c = scr_readw(s);
static u8 pixmap[FB_PIXMAPSIZE];

+ if (info->caps & FB_CAPS_TILEBLIT && info->tileops) {
+ tile_putcs(vc, p, (u32 *) pixmap, s, count, yy, xx);
+ return;
+ }
+
image.fg_color = attr_fgcol(p, c);
image.bg_color = attr_bgcol(p, c);
image.dx = xx * vc->vc_font.width;
@@ -452,6 +513,10 @@
unsigned int bs = info->var.yres - bh;
struct fb_fillrect region;

+ /* unneeded for tile blits */
+ if (info->caps && FB_CAPS_TILEBLIT && info->tileops)
+ return;
+
region.color = attr_bgcol_ec(p, vc);
region.rop = ROP_COPY;

@@ -1150,7 +1215,6 @@
struct fb_info *info = p->fb_info;
unsigned short charmask = p->charmask;
unsigned int width = ((vc->vc_font.width + 7) >> 3);
- struct fb_image image;
int redraw_cursor = 0;

if (!p->can_soft_blank && console_blanked)
@@ -1164,17 +1228,33 @@
redraw_cursor = 1;
}

- image.fg_color = attr_fgcol(p, c);
- image.bg_color = attr_bgcol(p, c);
- image.dx = xpos * vc->vc_font.width;
- image.dy = real_y(p, ypos) * vc->vc_font.height;
- image.width = vc->vc_font.width;
- image.height = vc->vc_font.height;
- image.depth = 1;
- image.data = p->fontdata + (c & charmask) * vc->vc_font.height * width;
+ if (info->caps & FB_CAPS_TILEBLIT && info->tileops) {
+ struct fb_tileblit tilerect;
+
+ u32 font = c & charmask;
+ tilerect.dx = xpos;
+ tilerect.dy = real_y(p, ypos);
+ tilerect.width = 1;
+ tilerect.height = 1;
+ tilerect.fg_color = attr_fgcol(p, c);
+ tilerect.bg_color = attr_bgcol(p, c);
+ tilerect.data = &font;
+
+ info->tileops->fb_tileblit(info, &tilerect);
+ } else {
+ struct fb_image image;

- info->fbops->fb_imageblit(info, &image);
+ image.fg_color = attr_fgcol(p, c);
+ image.bg_color = attr_bgcol(p, c);
+ image.dx = xpos * vc->vc_font.width;
+ image.dy = real_y(p, ypos) * vc->vc_font.height;
+ image.width = vc->vc_font.width;
+ image.height = vc->vc_font.height;
+ image.depth = 1;
+ image.data = p->fontdata + (c & charmask) * vc->vc_font.height * width;

+ info->fbops->fb_imageblit(info, &image);
+ }
if (redraw_cursor)
vbl_cursor_cnt = CURSOR_DRAW_DELAY;
}
@@ -1935,6 +2015,31 @@
scrollback_max = 0;
scrollback_current = 0;

+ if (info->caps & FB_CAPS_TILEBLIT && info->tileops) {
+ struct fb_tiledata tile;
+ int err, cnt = FNTCHARCNT(p->fontdata);
+ int size = (vc->vc_font.height * vc->vc_font.width)/8 * cnt;
+ u8 *tiledata;
+
+ /*
+ * make sure we don't allow drivers to mangle
+ * console fontdata
+ */
+ tiledata = kmalloc(size, GFP_KERNEL);
+ if (tiledata == NULL)
+ return 0;
+ memcpy(tiledata, p->fontdata, size);
+ tile.tile.width = vc->vc_font.width;
+ tile.tile.height = vc->vc_font.height;
+ tile.tile.depth = 1;
+ tile.len = cnt;
+ tile.data = tiledata;
+ err = info->tileops->fb_loadtiles(info, &tile);
+ kfree(tiledata);
+
+ if (err) return 0;
+ }
+
info->currcon = unit;

fbcon_resize(vc, vc->vc_cols, vc->vc_rows);
@@ -2152,6 +2257,27 @@

}

+ if (info->caps & FB_CAPS_TILEBLIT && info->tileops) {
+ struct fb_tiledata tile;
+ int size = (vc->vc_font.height * vc->vc_font.width)/8 * cnt;
+ int err;
+ u8 *tiledata;
+
+ tiledata = kmalloc(size, GFP_KERNEL);
+ if (tiledata == NULL)
+ return 1;
+ memcpy(tiledata, p->fontdata, size);
+ tile.tile.width = vc->vc_font.width;
+ tile.tile.height = vc->vc_font.height;
+ tile.tile.depth = 1;
+ tile.len = cnt;
+ tile.data = tiledata;
+
+ err = info->tileops->fb_loadtiles(info, &tile);
+ kfree(tiledata);
+ if (err) return err;
+ }
+
if (resize) {
/* reset wrap/pan */
info->var.xoffset = info->var.yoffset = p->yscroll = 0;
diff -Naur linux-2.5.54/include/linux/fb.h linux/include/linux/fb.h
--- linux-2.5.54/include/linux/fb.h 2003-01-10 11:08:19.000000000 +0000
+++ linux/include/linux/fb.h 2003-01-10 11:21:27.000000000 +0000
@@ -173,6 +173,10 @@
#define FB_VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */
#define FB_VMODE_CONUPDATE 512 /* don't update x/yoffset */

+/* Driver Capability */
+#define FB_CAPS_CLIPPING 1 /* hardware can do clipping */
+#define FB_CAPS_TILEBLIT 2 /* hardware can do tileblits */
+
#define PICOS2KHZ(a) (1000000000UL/(a))
#define KHZ2PICOS(a) (1000000000UL/(a))

@@ -377,6 +381,77 @@
int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma);
};

+/*
+ * Tile Blitting Support
+ *
+ * In Tile Blitting, the basic unit is a Tile which is a bitmap with
+ * a predefined width and height, and optionally, other properties
+ * such as color depth, spacing, transparency, etc. For now, we'll
+ * just support width, height, and color depth.
+ *
+ * All operations are analogous to classic blitting operations which
+ * use pixels as the basic unit. Instead of pixels, it will use tiles,
+ * instead of info->pseudo_palette, it will use tiledata, etc.
+ */
+
+struct fb_tile {
+ __u32 width; /* tile width in pixels */
+ __u32 height; /* tile height in scanlines */
+ __u32 depth; /* pixel depth */
+};
+
+struct fb_tiledata {
+ struct fb_tile tile; /* tile properties */
+ __u32 len; /* number of tiles in the map */
+ __u8 *data; /* packed tile data */
+};
+
+struct fb_tileblit {
+ __u32 dx; /* destination x origin, in tiles */
+ __u32 dy; /* destination y origin, in tiles */
+ __u32 width; /* destination window width, in tiles */
+ __u32 height; /* destination window height, in tiles */
+ __u32 fg_color; /* fg_color if monochrome */
+ __u32 bg_color; /* bg_color if monochrome */
+ __u32 *data; /* tile map - array of indices to tiledata */
+};
+
+struct fb_tilecopy {
+ __u32 dx; /* destination window origin... */
+ __u32 dy; /* in tiles */
+ __u32 width; /* destination width, in tiles */
+ __u32 height; /* destination height, in tiles */
+ __u32 sx; /* source window origin ... */
+ __u32 sy; /* in tiles */
+};
+
+struct fb_tilefill {
+ __u32 dx; /* destination window origin ... */
+ __u32 dy; /* in tiles */
+ __u32 width; /* destination width in tiles */
+ __u32 height; /* destination height in tiles */
+ __u32 fg_color; /* fg_color if monochrome */
+ __u32 bg_color; /* bg_color if monochrome */
+ __u32 rop; /* rop operation */
+ __u32 idx; /* index to current tiledata */
+};
+
+struct fb_tileops {
+ /* upload tile data to driver and make it current... the driver
+ * must copy the contents of tiledata.data, not just the pointer to it */
+ int (*fb_loadtiles)(struct fb_info *info,
+ const struct fb_tiledata *tile);
+ /* blit tiles to destination from a tilemap */
+ void (*fb_tileblit)(struct fb_info *info,
+ const struct fb_tileblit *tilemap);
+ /* copy tiles from one region of fb memory to another */
+ void (*fb_tilecopy)(struct fb_info *info, const struct fb_tilecopy *area);
+ /* fill a region of fb memory with a tile */
+ void (*fb_tilefill)(struct fb_info *info,
+ const struct fb_tilefill *region);
+ /* If driver is to support tile blitting, all hooks above are required */
+};
+
struct fb_info {
kdev_t node;
int flags;
@@ -388,6 +463,7 @@
struct fb_cursor cursor; /* Current cursor */
struct fb_cmap cmap; /* Current cmap */
struct fb_ops *fbops;
+ struct fb_tileops *tileops /* Tile blitting */
char *screen_base; /* Virtual address */
struct vc_data *display_fg; /* Console visible on this display */
int currcon; /* Current VC. */