/boot/loader graphics support & extensibility

Oliver Fromme olli at lurza.secnetix.de
Sat Feb 23 21:46:26 UTC 2008


Marcel Moolenaar wrote:
 > On Feb 22, 2008, at 12:39 PM, Oliver Fromme wrote:
 > > Yes, that'll work well for putting characters on the
 > > screen.  But I don't think it is suitable for generic
 > > graphics operations, even (and especially) for drawing
 > > single pixels.
 > 
 > True. What do you envision? How generic do you think
 > we should make it?
 > 
 > For me the difference between an abstraction solely
 > based on bitblt and an abstraction that includes a
 > couple more primitives is minimal. The key aspect is
 > that we should not have to duplicate 1000 lines of
 > code, of which less than 10% deals with the hardware.
 > This, for example, is a problem with syscons and the
 > keyboard- and video switch interfaces. The keyboard
 > switch interface alone has 18 functions???? That's a
 > bad abstraction, nothing else.

Yes, I'm aware of the problem.

All the screenshots that I've made so far use only three
functions:  Displaying PCX images, printing characters,
and drawing filled rectangles (e.g. to clear the screen
or parts of it).  That's not really much.  I'm inclined
to implement specialized versions of these functions for
each of the bitmap formats, which is currently just two:
4bit planar (16 colors) and 8bit linear (256 colors).

Currently I also have implemented several other functions
such as line drawing, filled triangles, circles etc.,
but I'm not sure if it's worth keeping them.  I'll have
to think about it a bit more.

At the moment I don't plan to support modes with more
than 8 bits (but of course if someone else wants to do
it, that would be fine with me).  Typically you can
dither truecolor images to 8 bit at very good quality
(with gimp, imagemagick, netpbm, whatever), so there's
no need for hicolor or truecolor modes.  It should also
be pointed out that there are a lot of variants of
bitmap formats, and different graphics hardware supports
different subset of these:  15 bit hicolor (5-5-5),
16 bit hicolor (5-6-5), 24 bit truecolor, 32 bit true-
color, and each of these with different component orders
(RGB or BGR), resulting in at least eight different
formats.  You have to support them all, which is somewhat
complicated (although not difficult).

The situation might be completely different on non-VGA
hardware, of course.

 > > I'm sorry, I should have been clearer, that gfx_rect()
 > > function draws a filled rectangle.
 > 
 > I see. In that case it's a single bitblt operation :-)

But how would it work in reality?  I guess you have
something like this in mind; please correct me if I'm
wrong:

 - The Forth code calls the rectangle function.
 - The hardware-independend gfx_rect function allocates
   a sufficiently large temporary memory buffer, then
   draws the rectangle into it.
 - Then it calls the hardware-dependent bitblt function,
   which copies the contents from the temporary buffer
   to the graphics frame buffer.

There are two problems that I can see with that approach
(not mentioning performance):

First, what will be the bitmap format of the temporary
memory buffer?  The first possibility would be to make
it the same as the graphics frame buffer, so the bitblt
function would just have to shovel bits (except that it
might have to shift bits if the buffer's contents don't
happen to have the right alignment already).  But then
we need multiple rectangle functions, one for every
bitmap format supported, so the abstraction doesn't
really buy us much.

The second possibility is to make the temporary buffer
independent from the bitmap format of the graphics mode,
i.e. use a fixed format.  In order to be able to support
truecolor modes, that fixed format would have to be a
truecolor format, too.  So then the rectangle function
would draw a 24bit or 32bit truecolor rectangle (even
if the graphics mode is only 4 bit), and the bitblt
function would have to convert it back to the actual
bitmap format of the graphics mode, possibly having to
do palette lookups.  That is horribly inefficient, and
there's no easy way for optimizations.

The second problem is that some graphics functions need
to work with masks.  For example, the function that
prints a character is supposed to overlay the background,
i.e. _not_ clear the rectangular area that the character
occupies (this is to allow things such as ligatures,
accent characters, shadow, bold and outline effects etc).
So the bitblt function would have to take two input
bitmaps (one being the pixel source and one being the
mask) and perform the neccessary logical operations, in
addition to the shifting (which also applies to the mask),
format conversion, palette lookup, ...

Sure, all of that could be implemented, but I fear that
it would be much more complicated and bloated in the end.

The current rectangle function for 4bit planar modes is
about 15 lines of C code (not counting comments).  The
PCX display function is basically a straight-forward
loop of about 20 lines of C code.  That's not really a
huge amount.  And I have to confess that I don't think
it's too bad that I'll have to write another 15 lines
for an 8bit rectangle function, and another 20 lines for
the 8bit PCX display loop.  Probably less, because the
8bit linear modes are much simpler than the 4bit planar
modes.

On the other hand, writing bitblt functions that do all
of the things that I explained above would cost several
hundred lines of code.  And in the end it would be slower
by an order of magnitude.

These are just my thoughts.  I certainly don't want to
dismiss the idea of bitblt completely, but I think the
disadvantages outweigh the benefits in this case.

 > Agreed. Be aware of making the mistake to separate and
 > distinguish between variations of a single operation at
 > too high a level.

Yes, I know what you mean.  I try to keep it in mind.

 > For example: it's much more costly to
 > separate vertical line drawing from horizontal line
 > drawing from any other kind of line drawing at the MI
 > layer, than it is at the hardware level. The hardware
 > level needs to check the parameters anyway and unless
 > there's hardware acceleration it'll perform separate
 > code paths most of the time. The upshot of a single line
 > drawing primitive is that you don't have to worry about
 > the coordinates and which API function you must call.
 > This is important when the coordinates are parameters
 > to some function and you'll find yourself coding like:
 > 
 >         if (isvertical(x1,y1,x2,y2))
 >                 drawline_vertical(...)
 >         elif (ishorizontal(x1,y1,x2,y2))
 >                 drawline_horizontal(...)
 >         else
 >                 drawline_generic(...)
 > 
 > With hardware acceleration you may not have to care at
 > all and when you need to draw the line in software,
 > you need to test the coordinates anyway and split the
 > work based on angle even. In that case you also split
 > horizontal and vertical.

I do have a generic line drawing function (using the
well-known Bresenham algorithm) as well as specialized
functions for vertical and horizontal lines.  However,
there is no code like the one above.

The hline and vline functions are rather intended to be
used for cases where the Forth programmer knows in advance
that the line will be horizontal or vertical, e.g. when
underlining a word, drawing a frame and similar things.

For random lines the generic line function should be used,
even if the line happens to be vertical or horizontal.
It's not worth making a distinction for that case.

 > Anyway: that's enough out of me. I think what you're
 > doing is great and I can't wait to see it realized...

Thank you very much for taking part in this discussion,
it helps a lot.  I even learned a little bit about EFI. :)

My next steps:
 - Find a spare box and install 8-current (so far I'm
   using RELENG_7 for development and testing).
 - Continue cleaning up and committing to Perforce.
 - If I have something that works, I'll prepare diffs for
   review and a tarball for people to test and play.

Beware, I'm not working full-time of this, so it might
take a little while (I have a full-time job, a wife,
other hobbies, so my time is a bit limited).

Best regards
   Oliver

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

"With sufficient thrust, pigs fly just fine.  However, this
is not necessarily a good idea.  It is hard to be sure where
they are going to land, and it could be dangerous sitting
under them as they fly overhead." -- RFC 1925


More information about the freebsd-hackers mailing list