分类: LINUX
2010-05-24 22:02:39
This is a quick document I produced while figuring out how to use
the framebuffer device to produce graphics on the Linux console. I don't
claim to be an expert in this area, but when I looked for a general
guide to doing this, I found absolutely nothing, except the header file
Therefore, this is meant to be a jump-start guide for those who want to begin using graphics in the linux console. Hopefully someone out there will write a decent graphical browser, so I don't have to start up X every time I want to surf!
As always, no warranty, express or implied...etc. Give me a break, I
took my first look at this device less than 24 hours ago! Any
corrections, money, gifts, etc. (I wish!), just
You may
freely distribute this document, as long as you do not change it in any
way, and credit me as author. In particular, I encourage Linux
distributions to include this in their packages, as I feel there isn't
half as much programming information in most distributions as there
ought to be. Copyright James Dabell, May 1999.
This document was
last updated June 11th, 1999. (Corrections from Joerg Beyer & Ian
Thompson-Bell)
Part One:
First of all, configure your system for the framebuffer console device. It may come in handy. Note that the device is only available for graphics cards that implement VESA 2.0. Fortunately, virtually all recent cards out there do this.
When you have got high-res textmodes, then you can start experimenting. You will have a device /dev/fb0 that you can look at like any normal file. To take a screenshot, all you have to do is
cat /dev/fb0 > ~/sshot
And you will have a pretty big file with the contents of your graphics card's memory inside. Now, if you clear the screen, and type
cat ~/sshot > /dev/fb0
You should have a display that looks exactly like before. Of course, the second you start typing the display reverts to normal.
Part Two:
So now, we can move on to using the device in a C program. Take a look at the following code:
#include
#include
#include
int main()
{
int fbfd = 0;
fbfd = open("/dev/fb0", O_RDWR);
if (!fbfd) {
printf("Error: cannot open framebuffer device.\n");
exit(1);
}
printf("The framebuffer device was opened successfully.\n");
close(fbfd);
return 0;
}
All in all, a pretty simple program. We open the framebuffer device
file using the low-level open(), because the buffered, higher level
fopen() is unsuitable for our needs.
Next, we test the file
descriptor to make sure that we were successful, and print a message out
that tells the user what happened.
Note that if you #include
Finally, we clean up by closing the file descriptor and
returning.
Part Three:
Using the newly created file descriptor, we can perform operations on the framebuffer with the ioctl() function. This function is used to talk to special device files in ways that are particular to that device. In this case, we can use it to obtain information on the video card. We can also use the file descriptor to map the file into memory, and use a pointer to access it, which is more efficient and easier on us. This is done using the mmap() function. If you haven't used this before, here is some sample code:
#include
#include
#include
#include
#include
int main()
{
int fbfd = 0;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
long int screensize = 0;
char *fbp = 0;
fbfd = open("/dev/fb0", O_RDWR);
if (!fbfd) {
printf("Error: cannot open framebuffer device.\n");
exit(1);
}
printf("The framebuffer device was opened successfully.\n");
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {
printf("Error reading fixed information.\n");
exit(2);
}
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
printf("Error reading variable information.\n");
exit(3);
}
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
if ((int)fbp == -1) {
printf("Error: failed to map framebuffer device to memory.\n");
exit(4);
}
printf("The framebuffer device was mapped to memory successfully.\n");
munmap(fbp, screensize);
close(fbfd);
return 0;
}
As you can see, we have to #include an extra header file to deal with
mmap(). We use the information returned by the ioctl()s to figure out
how much memory to map. The members of fb_var_screeninfo that are used
are xres, yres, and bits_per_pixel.
Note that there is also what is
known as the virtual screen size, which can be utilised for scrolling,
etc, but that is beyond the scope of this document. However, if you are
planning on using scrolling, you will probably want to use xres_virtual
and yres_virtual to calculate how much memory to map.
Finally,
remember to munmap() the memory you have mapped for use with the
framebuffer.
Part Four:
In this section we finally get to plot a pixel on the screen. First of all, we need to know in what format we should put the data. As it is the most common, and also the only type I have access to, I will be talking about the type of framebuffer that utilises packed pixels. All that is necessary to put a pixel on the screen, is to put bytes corresponding to the colours blue, green, red and transparency, in that order, at the correct location in memory, starting at 0 for x = 0, y = 0, and increasing by four bytes for every x, and y * the length of the line in bytes for every y. Standard graphics stuff; people used to the good ol' days back in mode 13h programming in DOS will catch on quickly. Anyway, here's the code:
#include
#include
#include
#include
#include
int main()
{
int fbfd = 0;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
long int screensize = 0;
char *fbp = 0;
int x = 0, y = 0;
long int location = 0;
/* Open the file for reading and writing */
fbfd = open("/dev/fb0", O_RDWR);
if (!fbfd) {
printf("Error: cannot open framebuffer device.\n");
exit(1);
}
printf("The framebuffer device was opened successfully.\n");
/* Get fixed screen information */
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {
printf("Error reading fixed information.\n");
exit(2);
}
/* Get variable screen information */
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
printf("Error reading variable information.\n");
exit(3);
}
/* Figure out the size of the screen in bytes */
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
/* Map the device to memory */
fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,
fbfd, 0);
if ((int)fbp == -1) { printf("Error: failed to map
framebuffer device to memory.\n"); exit(4);
}
printf("The framebuffer device was mapped to memory successfully.\n");
x = 100; y = 100; /* Where we are going to put the pixel */
/* Figure out where in memory to put the pixel */
location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +
(y+vinfo.yoffset) * finfo.line_length;
*(fbp + location) = 100; /* Some blue */
*(fbp + location + 1) = 15; /* A little green */
*(fbp + location + 2) = 200; /* A lot of red */
*(fbp + location + 3) = 0; /* No transparency */
munmap(fbp, screensize);
close(fbfd);
return 0;
}
Now that you know how to plot a pixel, it becomes a trivial matter to write functions to draw lines, boxes, windows, etc. Hopefully, by now you are well on your way to writing that web browser for me - consider it payment for this tutorial ;).
Talking of payment, I get paid every time
somebody buys a book this way. Sorry, but I'm a poor student, and let's
face it, if you are reading this page, then you will probably be
interested in them, if you don't have them already. I have personally
read each of these, and can say with all honesty that they are great
books.
Beginning Linux Programming:
This book really has it all for getting to grips with Linux
programming. If you can already program in C, and want to know how to
use some of the more specific Linux stuff, then get this book. It covers
all sorts, from shell programming, through socket programming in C, to X
programming using tcl/tk.
C: The Complete Reference:
This is the only book you should consider getting if you
want to learn C. This was all I needed to get programming in C, and
since it also doubles as a reference book, you will keep coming back to
it again and again. It's by Herbert Schildt, one of the best authors on
the planet when it comes to C. Forget the "learn C in 14 days" cons, get
this. Now.
Genetic Algorithms in C++:
This is all you need to understand the theory behind, and implement
Genetic Algorithms. Genetic Algorithms model themselves on nature, by
"evolving" solutions based upon how well they perform in an environment
(your program). It sounds complex, but I assure you that it is *really*
easy to get into.
One thing though. All of the sample code is
targetted at MS Windows, so if you are the kind of person who relies on
the code in a book to get through it, and you are developing for Linux,
then this book may not be for you. Personally, I didn't even need to
look at the code before implementing my own stuff, the text is more than
sufficient.
Internet Programming With Python
This book is co-authored by Guido Van Rossum, the guy who wrote the
Python language. It also comes with a CD containing Python for many
different platforms, as well as sample code. It covers CGI programs
written in Python, and also a couple of subjects not usually mentioned
in books of this kind, namely generating HTML (in a *very* nice way) and
extending the language. It also covers the basics in a way that makes
this book also good for learning the language from scratch.