Applying C - Framebuffer Graphics
Written by Harry Fairhead   
Monday, 10 June 2019
Article Index
Applying C - Framebuffer Graphics
The Main Program

We also need a function to get a block of pixels and a function to restore them:

void saveBlock(uint32_t x, uint32_t y, uint32_t L,
                                    uint32_t block[]) {
  for (int i = 0; i < L; i++) {
    for (int j = 0; j < L; j++) {
      block[i+j*L] = getRawPixel(x + i, y + j);
void restoreBlock(uint32_t x, uint32_t y, uint32_t L, 
uint32_t block[]) { for (int i = 0; i < L; i++) { for (int j = 0; j < L; j++) { setRawPixel(x + i, y + j, block[i+j*L]); } } }

The pixel data is stored in a one-dimensional array simulating a two-dimensional array to avoid the problems of passing a variable size two-dimensional array.

Now we can start on the main program. First we need the includes and some data structures:

#define _POSIX_C_SOURCE  199309L
#include <stdio.h>
#include <stdlib.h>
#include <linux/fb.h>
#include <fcntl.h> 
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <inttypes.h>
#include <time.h>
#define BLOCKSIZE 10
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;
uint8_t *fbp;
uint32_t block[BLOCKSIZE*BLOCKSIZE];
struct color {
    uint32_t r;
    uint32_t g;
    uint32_t b;
    uint32_t a;

The fbp variable is a global pointer to the start of the framebuffer. First we need to set up the framebuffer:

int main(int argc, char** argv) {
    int fd = open("/dev/fb0", O_RDWR);
    ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
    ioctl(fd, FBIOGET_FSCREENINFO, &finfo);
    vinfo.grayscale = 0;
    vinfo.bits_per_pixel = 32;
    ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo);
    ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);   
    fbp = mmap(0, vinfo.yres * finfo.line_length, 

With the framebuffer set up we can write a bounce program ignoring the details of how the graphics are being created:

struct color c = {0xFF, 0x00, 0x00, 0xFF};
int x = 600;
int y = 400;
int vx = -1;
int vy = -1;
struct timespec pause;
pause.tv_sec = 0;
pause.tv_nsec = 20 * 1000*1000;
saveBlock(x, y, BLOCKSIZE,block);
for (;;) {
    restoreBlock(x, y, BLOCKSIZE, block);
    x = x + vx;
    y = y + vy;
    if (x <= 0) {
       x = 0; vx = -vx;
    if (y <= 0) {
       y = 0; vy = -vy;
    if ((x + BLOCKSIZE) >= vinfo.xres) {
       x = vinfo.xres - BLOCKSIZE - 1;
       vx = -vx;
    if ((y + BLOCKSIZE) >= vinfo.yres) {
       y = vinfo.yres - BLOCKSIZE - 1;
       vy = -vy;
    saveBlock(x, y, BLOCKSIZE, block);
    setBlock(x, y, BLOCKSIZE, c);
    nanosleep(&pause, NULL);
    return (EXIT_SUCCESS);

The if statements check to see if the ball is about to go off the screen and if it is then it is bounced by reversing the appropriate velocity and settings its position to be on the edge of the screen. The speed of the bounce can be determined by the time delay used in nanosleep. The ball will bounce around the screen, overwriting, but not destroying, anything else on the screen. There are various system "glitches" that can spoil the effect. In particular, the activation of any screensaver will result in the ball leaving a trail behind.

If you are familiar with other graphics environments, you might be wondering how to synchronize your graphics update to the screen refresh. You can try looking up the ioctl FBIO_WAITFORVSYNC call, which waits for a vertical sync to occur. The problem is that many graphics cards do not implement it.

Also included in the chapter:

  • Framebuffer Text PSF 1
  • Framebuffer Text PSF 2
  • Windowing Systems - X11
  • Device, Screen and Window
  • Graphics Functions
  • An Example
  • Color
  • Events
  • GTK - a GUI Framework
  • A First Window
  • Glade
  • Graphics Beyond GTK


  • Selecting a graphics system for Linux is difficult because there is so much choice and many different levels of operation.

  • The framebuffer gives you direct access to the graphics buffer.

  • You can use it to write directly to the screen and it doesn't take account of windows or any other part of the GUI.

  • It is possible to use font files to write text to the framebuffer.

  • The standard window system is X11 and it has a client-server architecture with the program that does the drawing as the client, and the program that does the rendering on a device as the server.

  • X11 can be used via the Xlib library.

  • X11 can also handle user input and for this you have to implement an event handling loop.

  • The GTK Framework is a complete GUI system with windows, buttons and events.

  • The structure of almost any GUI framework makes your program asynchronous and this can be confusing at first.

  • You can use GTK via function calls, but it is much easier to use the Glade drag-and-drop editor.


Now available as a paperback or ebook from Amazon.

Applying C For The IoT With Linux

  2. Kernel Mode, User Mode & Syscall
  3. Execution, Permissions & Systemd
    Extract Running Programs With Systemd
  4. Signals & Exceptions
    Extract  Signals
  5. Integer Arithmetic
    Extract: Basic Arithmetic As Bit Operations
  6. Fixed Point
    Extract: Simple Fixed Point Arithmetic
  7. Floating Point
  8. File Descriptors
    Extract: Simple File Descriptors 
    Extract: Pipes 
  9. The Pseudo-File System
    Extract: The Pseudo File System
  10. Graphics
    Extract: framebuffer
  11. Sockets
    Extract: Sockets The Client
    Extract: Socket Server
  12. Threading
    Extract:  Pthreads ***NEW
    Extract:  Condition Variables
    Extract:  Deadline Scheduling
  13. Cores Atomics & Memory Management
    Extract: Applying C - Cores 
  14. Interupts & Polling
    Extract: Interrupts & Polling 
  15. Assembler
    Extract: Assembler

Also see the companion book: Fundamental C





Related Articles

Remote C/C++ Development With NetBeans

Raspberry Pi And The IoT In C

Getting Started With C/C++ On The Micro:bit

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.


Spatial Data Management For GIS and Data Scientists

Videos of the lectures taught in Fall 2023 at the University of Tennessee are now available as a YouTube playlist. They provide a complete overview of the concepts of GeoSpatial science using&nbs [ ... ]

PHP 8.3 Released

PHP 8.3 has been released with improvements including explicit typing of class constants, deep cloning of readonly properties, and additions to randomness functionality.

More News




or email your comment to:


Last Updated ( Monday, 01 July 2019 )