Drawing In a Linear Framebuffer: Difference between revisions

m
Bot: Replace deprecated source tag with syntaxhighlight
[unchecked revision][unchecked revision]
(Graphics Modes: reword and explain the difference between VGA and VBE/GOP.)
m (Bot: Replace deprecated source tag with syntaxhighlight)
 
(One intermediate revision by the same user not shown)
Line 119:
 
Pitch and pixel width are usually announced by VESA mode info. Once you know them, you can calculate the place where you plot your pixel as:
<sourcesyntaxhighlight lang="c">unsigned char *pixel = vram + y*pitch + x*pixelwidth;</sourcesyntaxhighlight>
 
=== Color ===
Line 130:
 
So a full "putpixel" function for VGA would be
<sourcesyntaxhighlight lang="c">
/* example for 320x200 VGA */
void putpixel(int pos_x, int pos_y, unsigned char VGA_COLOR)
Line 137:
*location = VGA_COLOR;
}
</syntaxhighlight>
</source>
 
Finally, in VESA and GOP modes, you usually have truecolor or hicolor, and in both of them, you have to give independent red, green and blue values for each pixel. modeinfo will (again) instruct you of how the RGB components are organized in the pixel bits. E.g. you will have <tt>0xRRRRRGGGGGBBBBB</tt> for 15-bits mode, meaning that #ff0000 red is there <tt>0x7800</tt>, and #808080 grey is <tt>0x4210</tt> (pickup pencil, draw the bits and see by yourself)
<sourcesyntaxhighlight lang="c">
static void putpixel(unsigned char* screen, int x,int y, int color) {
unsigned where = x*pixelwidth + y*pitch;
Line 147:
screen[where + 2] = (color >> 16) & 255; // RED
}
</syntaxhighlight>
</source>
 
=== Optimizations ===
 
It can be tempting from here to write other drawing functions from calls to putpixel... Don't. Drawing a filled rectangle means you access successive pixels and then advance by "pitch - rect_width" to fill the next line. If you do a "for(y=100;y<200;y++) for(x=100;x<200;x++) putpixel (screen,x,y,RED);" loop, you'll recompute 'where' about 10,000 times, as well as make an excessive amount of function calls. Even if the compiler has optimized y*pitch into adds and shifts instead of multiplication, it's silly to waste CPU time while you could do
<sourcesyntaxhighlight lang="c">
static void fillrect(unsigned char *vram, unsigned char r, unsigned char g, unsigned char b, unsigned char w, unsigned char h) {
unsigned char *where = vram;
Line 167:
}
}
</syntaxhighlight>
</source>
That should be enough to get you started coding (or googling for) a decent video library.
 
Line 174:
 
Once in graphic mode, you no longer have the BIOS or the hardware to draw fonts for you. The basic idea is to have font data for each character and use it to plot (or not to plot) pixels. There are plenty of ways to store those fonts depending on whether they have multiple colors or not, alpha channel or not etc. What you will basically have, however, is:
<sourcesyntaxhighlight lang="c">
// holding what you need for every character of the set
font_char* font_data[CHARS];
Line 202:
}
}
</syntaxhighlight>
</source>
 
== Drawing Icons ==
Line 208:
 
For a GUI, you'll probably want to display icons. It's as simple as
<sourcesyntaxhighlight lang="c">
void draw_icon(x, y, w, h, pixels) {
for (l = j = 0; l < h; l++) {
Line 216:
}
}
</syntaxhighlight>
</source>
The difficulty is, icons aren't stored as width, height and pixels array on disk. First you have to [[Loading Icons|decode an image file]] to get that information.