Date: Sat, 23 Feb 2008 22:46:22 +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: <200802232146.m1NLkMNR089426@lurza.secnetix.de> In-Reply-To: <073CCEB2-3124-4631-A034-6A23544A6177@mac.com>
next in thread | previous in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200802232146.m1NLkMNR089426>