Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Feb 2008 11:16:51 -0800
From:      Marcel Moolenaar <xcllnt@mac.com>
To:        freebsd-hackers@FreeBSD.ORG
Subject:   Re: /boot/loader graphics support & extensibility
Message-ID:  <754FD289-9E26-4368-9AB4-64F3ECB6CDFC@mac.com>
In-Reply-To: <200802211009.m1LA9HZw040772@lurza.secnetix.de>
References:  <200802211009.m1LA9HZw040772@lurza.secnetix.de>

next in thread | previous in thread | raw e-mail | index | archive | help
On Feb 21, 2008, at 2:09 AM, Oliver Fromme wrote:

>>>
>>> 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 think they may fundamentally be the same thing. The bitblt
I refer to is Bit Block Transfer. While the bitblt API could
support bit-wise operations while it's copying, it's main
purpose is to move a bit-array (tile/sprite) from RAM to VRAM,
or possibly between VRAM locations. Everything that needs to
be done can be done with a bitblt. It also happens to be the
operation that was first accelerated...

The abstraction is in the details of how a bit-mask or image
map needs to be written to VRAM to have it appear as a char.
or an image on the screen.

>> 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.

The higher lever TTY code simply calls bitblt with a
bit mask of the glyph to be printed and doesn't need to
know about the details of the display. As such, simple
console output works at any resolution and with any
color depth.

At the same time the VGA driver is abstracted from any
high-level details, like fonts or character sets. This
means that it's easy to write an accelerated driver for
some graphics hardware. You simply implement mode
setting and bitblt and you're good to go.

> 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?

You bitblt the 4 edges. I didn't say it was the most
performance optimal thing to do. I only said that it
can be abstracted that way.

Rectangles are better abstracted with a linedraw
primitive, but unless you really want generic line
drawing capabilities in the loader, it's probably not
worth implementing it....

>>>> 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.

Yes. My vtc(4) driver, which puts graphics support in the
kernel, is having the same problems with bitmaps. I have
a nice logo (the 4.4 daemon: see
http://www.mckusick.com/beastie/shirts/source.html), but
I only have it for the standard VGA 4-bit color mode. I need
a separate one for 16-bit and/or 256-bit colors...


>>> 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.

Yeah. Something along those lines should do it.

> 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?

I think that sounds good. I do have another datapoint.
I leave it up to you whether that's something that needs
to be considered or not:

EFI supports multiple consoles. In other words, the
EFI console can be both the display and the serial
line at the same time. Clearly, graphics mode is
something that you generally cannot  duplicate over
the serial line. However, modulo the logo and
background, if the graphics console is like a text
console or serial console, then you can still have
them both. The serial console simply doesn't get
copied the logo and background, but since everything
else is text anyway, this should not be a problem.

My ia64 machines use serial consoles, because
syscons hasn't been ported (and I'm not planning to
yet). However, it would be great if we could get the
EFI loader working in graphics mode already and
it would be especially great if that doesn't break the
dual console setting in EFI.

The question before us is: worth a try or not worth
it...

> 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.

Agreed. This also works on powerpc or sparc64, where
the firmware sets the graphics mode and all we have to
do is make use of it. It's all part of the vtc(4) driver effort
too: we don't have to have a driver that knows how to set
the mode. All that suffices is a driver that can figure out
the mode in which the hardware is, and knows how to
use the mode.

>> 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.

If we're going to use the loader to set the graphics mode
for the kernel, then obviously it becomes more important
for the loader to be able to switch to modes the user likes
best...


>> ell, 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?

Yes and no. I can image that the user wants control over
the desktop. Power to the people. But here we're talking
about the boot process. For Joe User nothing more than
a waiting period. What does it matter, really, that a nice
logo is a bit distorted? Would it be nicer if we could avoid
the scaling? Yes, definitely. But it's not the first priority.

The graphics world is one with many pitfalls, obstacles
and controversies. I think it's best to get something basic
off the ground first. I think performance is not a concern.
Once you have the basic functionality, you'll also have a
wishlist of things you want to do better; performance one
of them in all likelyhood.

The apparently simple problem of avoiding the scaling
means that you need to understand much more of the
graphics hardware and need to support DDC so that you
know the capabilities and restrictions of the system.
My Sony Vaio doesn't scale for example. It always has
the resolution set to the native of 1024x768 and simply
shows a 640x480 image in the center. Ideally you use
the native resolution, but if you avoid borders and
backgrounds and only use a simple logo in the center,
then you won't even notice...

Anyway: those are just my views. Not at all important
in the grand scheme of things, because in the end we
probably all want the same thing. It's just the getting
there where we differ on :-)

>>> 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.

You're right. I was thinking too much about Open Firmware.
On PCs the user typically has no way to set a graphics mode,
so the loader is the place to do it. Sorry for the confusion.

> 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

Another great image. I think we're finally moving into the 20th
century :-)

-- 
Marcel Moolenaar
xcllnt@mac.com





Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?754FD289-9E26-4368-9AB4-64F3ECB6CDFC>