Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Feb 2008 11:09:17 +0100 (CET)
From:      Oliver Fromme <olli@lurza.secnetix.de>
To:        freebsd-hackers@FreeBSD.ORG, xcllnt@mac.com
Subject:   Re: /boot/loader graphics support & extensibility
Message-ID:  <200802211009.m1LA9HZw040772@lurza.secnetix.de>
In-Reply-To: <1E2E2F4B-5169-42B4-AFFC-259B401F7F60@mac.com>

next in thread | previous in thread | raw e-mail | index | archive | help
Marcel Moolenaar wrote:
 > On Feb 20, 2008, at 12:08 PM, Oliver Fromme wrote:
 > > By the way:  Will the standard i386 /boot/loader work
 > > on an EFI machine, or does it require a different loader
 > > binary?
 > 
 > It needs a different loader. If you want to support EFI
 > the right way, it also needs a different kernel -- one
 > that respects the memory map. But that's a different
 > story :-)

OK.

 > > One final question:  What happens if you try to call a
 > > BIOS interrupt (such as the 0x10 video interrupt) on
 > > an EFI machine?  Will it crash?  Or is there a
 > > compatibility layer that returns "not supported"?
 > 
 > Assume it will crash.

OK.  That question was just out of curiosity.  I assume
such a situation will not arise in practice.

 > > > I haven't looked at the code yet, so I don't know
 > > > which graphics functions we're talking about.
 > > 
 > > Here's an excerpt from the .h file (it's not complete):
 > > 
 > > void    gfx_setcolor(int index, int color);
 > > void    gfx_setrgb(int color, int red, int green, int blue);
 > > void    gfx_usecolor(int color);
 > > void    gfx_pixel(int x, int y);
 > > void    gfx_rect(int x, int y, int width, int height);
 > > void    gfx_line(int x1, int y1, int x2, int y2);
 > > void    gfx_triangle(int x1, int y1, int x2, int y2, int x3, int y3);
 > > void    gfx_circle(int x, int y, int diameter);
 > > struct fontinfo *gfx_loadfont(char *filename);
 > > void    gfx_text(int *x, int *y, unsigned char *text, int length);
 > > unsigned char *gfx_loadpcx(char *filename);
 > > void    gfx_showpcx(unsigned char *pcx, int xstart, int ystart);
 > > 
 > > > You may want to keep in mind that EFI basically
 > > > defines a single graphics function: bitblt. If the
 > > > graphics functions are variations of bitblt, then
 > > > yes, it's very reasonable.
 > > 
 > > Actually I don't plan to use a bitblit function at all,
 > > because it's not really feasible in standard VGA modes.
 > 
 > What do you mean by that?

Maybe we have different understandings what bitblit means.
My understanding is that bitblit is a raster operation
between two bitmaps (typically "AND" and "OR" operations
for masking regions).  I've done such things on the Amiga
20 years ago (hardware-assisted by a coprocessor called
"Blitter").

I don't see how such functionality helps in this situation,
i.e. abstracting graphics functions from the hardware.

 > I implemented bitblt for VGA for vtc(4). Take a look at:
 >         http://people.freebsd.org/~marcel/vga.diff
 > 
 > [patch extracted from the tty branch in Perforce]

That's good code, but how does it help abstracting the
hardware?  I think I might just fail to see the obvious
because I haven't had enough coffee in the morning yet.

For example, lets say there's a function to draw a
rectangle (in fact there _is_ such a function in my code).
The Forth code to draw a rectangle covering the whole
screen at 640x480 would look like this:

480 640 0 0 vrect

The FICL word pops the parameters from the Forth stack
and calls a function gfx_rect().  This will go through
an abstraction switch so it calls an appropriate function
depending on the bitmap format of the current mode,
i.e. there will be gfx_planar4_rect(), gfx_linear8_rect()
and gfx_true24_rect().  Each of these functions implements
the graphics operation in the most efficient way for the
particular bitmap format.

How would the above work with a bitblit function, exactly?

 > > > Why not have the platform set a suitable graphics mode?
 > > > In other words: rather than have the end-user code
 > > > determine a mode, which they can't do reliably, why
 > > > not have the mode be set for the end-user code.
 > > 
 > > So you mean that "vmode" wouldn't take any arguments
 > > at all?
 > 
 > Correct.
 > 
 > > That would be possible.  But then there will be other
 > > problems.  For example, lets say that the i386 loader
 > > decides to use 640x480 @4bit, and the sparc64 loader
 > > decides that 1152x900 @8bit is "best".
 > > 
 > > The Forth code clearly needs a way to query the resolution
 > > and bit depth that was set, so it can chose an appropriate
 > > background image.  It might also have to chose a different
 > > font.
 > 
 > Yes, that's generally the difficulty with graphics.
 > 
 > > So the bottom line is that the Forth code cannot easily
 > > be abstracted from the hardware anyway.
 > 
 > Well, it cannot be abstracted from the graphics settings,
 > but it is abstracted from the hardware.

True.  I agree.

What I meant to say was this:  The hardware dictates which
graphics settings are available.  So the Forth code depends
on the hardware indirectly.  But of course it shouldn't
have to know anything about the hardware itself.

 > > There's also a problem when VESA support is added:  It's
 > > not possible to reliable detect what resolutions the
 > > attached monitor supports, so by default we must use
 > > 640x480 anyway, even if VESA support is present and the
 > > hardware can do 1600x1200 or whatever.  Using a higher-
 > > resolution mode is a decision that needs to be made by
 > > the admin, not by the loader, so there must be a way
 > > for the Forth code to request a specific resolution.
 > 
 > This does not have to be done in Forth. If in Forth you
 > simply say "Switch to graphics" and the platform code
 > looks up an environment variable for the actual mode,
 > then the user is still control of the resolution. In
 > fact, this is much more user friendly than having the
 > user edit Forth code, which he/she may not...

You're completely right, of course.

I didn't mean to say the the user will have to edit Forth
code (I wish loader would use a different language, but
that's a different story).

My plan is that there will be a configuration snippet
(maybe in loader.conf, maybe separate, I haven't spent
many thoughts on it yet).  It will contain things such
as the file name of the background image, font, colors
for the text, position of the menu, etc.  It should
also contain the desired resolution (if not the default).
It should be fairly easy to edit.

The Forth code will only have to be edited if the user
wants to create something completely different that's
not covered by the configuration settings.

So the situation will be similar to what it is now in
regards to the text menu:  The use can select whether
he wants the ASCIII beastie or the big "FreeBSD" text,
and whether he wants it in color or b/w.  He can also
disable the menu completely.  But if he wants to make
major changes, such as adding new menu items, or changing
the ASCII logo, he'll have to dig into the Forth code.

What do you think?

By the way, all of the screenshots I've made so far
should be possible without modifying any Forth code
(I haven't implemented that yet, i.e. I _did_ have to
modify the Forth code, but this is only temporary).

 > > > It seems to me that there are 2 ways of thinking about
 > > > consoles. One is the traditional way of not assuming
 > > > too much and just use the console in a serial fashion
 > > > so that it works with dump terminals as well. The other
 > > > is the graphical way of thinking which removes any and
 > > > all levels of abstraction (other than using BIOS mode
 > > > numbers????) and demands that the user can set every
 > > > little bit that can be set.
 > > 
 > > There will be users who want exactly that, i.e. be able
 > > to set every little bit that can be set.  I already got
 > > such requests in private mail.
 > 
 > While I understand the request, it should not be forgotten
 > that it's easy to end up with nothing if you allow the user
 > control over everything. On top of that, we can't use any
 > code in the loader from the kernel, so whatever support we
 > add, we need to add to the kernel too. At least, I think
 > it's lame to support fancy graphics in the loader and then
 > not support at least the same in the kernel. If you raise
 > the bar for the loader, you also have to raise it for the
 > kernel. How else would the kernel be able to use the console?

Basically I agree that whatever graphics support is added to
the loader should be possible to add to the kernel later,
too.  In fact that might be the best way to solve the
problem that VESA modes cannot be used with FreeBSD/amd64:
Let the loader switch to the desired VESA mode and give
all information necessary to access the frame buffer to
the kernel, so the VESA BIOS is out of the way.

 > So, the question is: how important is it for the user to
 > be able to tweak it all.

If the user had no way of specifying a resolution, then
there would be no point in supporting VESA, because there
wouldn't be a way to specify a VESA mode at anything else
than 640x480.

 > Is it merely people going nuts
 > over it (like a toddler going nuts over candy) than we
 > should simply forget about it (and tell the user to grow
 > up :-). If there's an actual reason for it (say: to support
 > HD TVs) then it's something that we could keep in mind if
 > we think it's the future (I have my Mac Mini hooked up to
 > my TV, so it's real for me).

Well, personally I would also like to be able to use the
capabilities of my hardware.  My main "workstation" at home
is a notebook.  When using the default VGA resolution of
640x480, the hardware scales it up to the TFT resolution,
and it doesn't do a particularly good job at it ...  It's
butt ugly and distorted.  As a user, I would certainly
welcome an option (in loader.conf or whatever) that enables
me to select a better resolution.

Is that like a toddler going nuts over candy?

 > > Of course, it would be pretty easy to implement both.
 > > So you have one function that simply set the mode that
 > > the driver thinks is best (that would be a 640x480 mode
 > > in the i386 case).  And a second function that takes
 > > resolution and depth as parameters, in order to switch
 > > to a specific mode.  There could be a special depth
 > > value (0 or -1) indicating "I don't care, just give
 > > me whatever you can at this resolution".
 > 
 > Yes. If common code doesn't care about the setting, then
 > it's easy enough to allow the user to pick the setting
 > of choice...

Right.  My goal is that it should work that way.

 > > > There's an in-between. The loader exists only to load
 > > > a kernel. We want it to look nice, but there's no
 > > > reason to tweak resolutions so that you can see the
 > > > kernel being loader in HD. The platform, which
 > > > includes the firmware, knows best which resolutions
 > > > look good.
 > > 
 > > I bet there will be people who disagree with the firmware
 > > about which resolution looks good.
 > 
 > True. But in that case you want to change the setting in
 > the firmware, not in the loader. If you want to depend on
 > the firmware/BIOS for mode setting then you also have to
 > depend on the Firmware/BIOS to allow the user to select
 > a setting of choice. Here too the loader then pretty much
 > as to work with whatever it gets thrown at it.

Hm.  I'm not sure I understand.

Lets take an example:  By default the loader decides to
use 640x480 @4bit (or maybe @8bit if VESA support present).
Now some user wants to use VESA mode 1024x768 instead.
And yet another user would prefer Mode-X 360x480 @8bit
with his own 256-color background image.  How are these
users supposed to do that?  There's no way in the BIOS
to tune anything.  I think the most appropriate way would
be a setting in loader.conf or another configuration file.

 > > My goal is that the Forth code should not have to care
 > > about the graphics hardware at all, as long as the
 > > underlying driver supports a resolution that the Forth
 > > code is prepared to deal with.
 > 
 > Agreed. Even if that's standard VGA for now...

OK.

 > > It's not feasible to define a hardware-specific setpixel
 > > function and let all other functions use it.  That would
 > > make all functions slower.  A _lot_ slower.  Orders of
 > > magnitude slower.  In VGA planar modes, you have to
 > > select each of the four bitplanes, one after another
 > > (using inb + mask + outb to the ISA registers), in order
 > > to set a single pixel.  Doing that for every single pixel
 > > in a character string or PCX image would be prohibitively
 > > inefficient.  These functions need to deal with the bits
 > > directly, and only switch planes if necessary.
 > 
 > That's why there's bitblt. See the URL above...

I don't see how it helps for all the graphics functions.
See my paragraph above about bitblit.

Best regards
   Oliver

PS:  I just took a few minutes to make yet another screen
design, it's based on the design of the www.freebsd.og
web pages.  It includes both the logo and the daemon
mascot:

http://www.secnetix.de/olli/FreeBSD/vloader/screenshot5.png

-- 
Oliver Fromme, secnetix GmbH & Co. KG, Marktplatz 29, 85567 Grafing b. M.
Handelsregister: Registergericht Muenchen, HRA 74606,  Geschäftsfuehrung:
secnetix Verwaltungsgesellsch. mbH, Handelsregister: Registergericht Mün-
chen, HRB 125758,  Geschäftsführer: Maik Bachmann, Olaf Erb, Ralf Gebhart

FreeBSD-Dienstleistungen, -Produkte und mehr:  http://www.secnetix.de/bsd

"Software gets slower faster than hardware gets faster."
        -- Niklaus Wirth



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200802211009.m1LA9HZw040772>