Applying C - Framebuffer Graphics
Written by Harry Fairhead   
Monday, 10 June 2019
Article Index
Applying C - Framebuffer Graphics
Color
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, 
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

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

Summary

  • 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

  1. C,IoT, POSIX & LINUX
  2. Kernel Mode, User Mode & Syscall
  3. Execution, Permissions & Systemd
    Extract Running Programs With Systemd
  4. Signals & Exceptions
  5. Integer Arithmetic
  6. Fixed Point
  7. Floating Point
  8. File Descriptors
  9. The Pseudo-File System
    Extract: The Pseudo File System 
  10. Graphics
    Extract: framebuffer 
  11. Sockets
  12. Threading
    Extract  Condition Variables
    Extract  Deadline Scheduling
  13. Cores Atomics & Memory Management
  14. Interupts & Polling
  15. Assembler
    Extract: Assembler ***NEW

Also see the companion book: Fundamental C

<ASIN:1871962609>

<ASIN:1871962463>

<ASIN:1871962617>

<ASIN:1871962455>

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.

Banner


Electron 8 - First Release As OpenJS Foundation Incubator
07/02/2020

At the end of last year Electron joined the OpenJS Foundation as an incubator project. The release of Electron 8, less than two months later, is an indication that it is thriving in its new home.  [ ... ]



Oracle Files Response To Google and API Copyright - We Are All Doomed
17/02/2020

The long ongoing, but not for too much longer, dispute between Oracle and Google about the use of code from the Java SDK in Android has reached a new stage. Oracle has outlined its case to the Supreme [ ... ]


More News

graphics

 



 

Comments




or email your comment to: comments@i-programmer.info

 



Last Updated ( Monday, 01 July 2019 )