Programación do FrameBuffer

De Wiki do Ciclo ASIR do IES de Rodeira

A seguinte libraría de funcións ilustra como se pode programar o modo gráfico de consola framebuffer.

Ficheiro de Cabeceira

#ifndef __GRAFICOSH__
#define __GRAFICOSH__
 
#define NEGRO    0
#define BLANCO   1
#define GRIS     2
#define ROJO     3
#define VERDE    4
#define AZUL     5
#define AMARILLO 6
#define NARANJA  7
#define MORADO   8
 
typedef struct tagPALETA {
  unsigned char r;
  unsigned char b;
  unsigned char g;
} PALETA;
 
void setcolor(int idx,int r,int g,int b);
int addcolor(int r,int g,int b);
PALETA *getcolor(int idx);
void initcolors(void);
int sizex(void);
int sizey(void);
 
void lineaH(int y,int x,int sz,int color);
void lineaV(int y,int x,int sz,int color);
void putpixel(int y,int x,int r,int g,int b);
void setpixel(int y,int x,int color);
void clrscr(void);
void putsprite(int y,int x,int *sprite);
char *initgraphics (int *resy, int *resx);
 
#endif

Libraría

#include <linux/fb.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
 
#include <math.h>
 
#include "graficos.h"
 
char *__memvid;
int __resx;
int __resy;
int __Bpp;
int __sizevid;
 
PALETA __paleta[2048];
int __maxcolor=0;
 
int sizex(void)
{
  return __resx;
}
 
int sizey(void)
{
  return __resy;
}
 
void initcolors(void)
{
  addcolor(0,0,0);
  addcolor(255,255,255);
  addcolor(128,128,128);
  addcolor(255,0,0);
  addcolor(0,255,0);
  addcolor(0,0,255);
  addcolor(246,243,24);
  addcolor(249,143,4);
  addcolor(249,4,196);
}
 
void setcolor(int idx,int r,int g,int b)
{
   __paleta[idx].r=r;
   __paleta[idx].g=g;
   __paleta[idx].b=b;
}
 
int addcolor(int r,int g,int b)
{
   int ret=-1;
 
   if (__maxcolor<2048)
   {
      ret=__maxcolor;
      __paleta[__maxcolor].r=r;
      __paleta[__maxcolor].g=g;
      __paleta[__maxcolor].b=b;
      __maxcolor++;
   }
   return ret;
}
 
PALETA *getcolor(int idx)
{
   return &__paleta[idx];
}
 
void clrscr()
{
  memset(__memvid,0,__sizevid);
  system("clear");
}
 
void putsprite(int y, int x, int *dibujo)
{
  int sy=*dibujo;
  int sx=*(dibujo+1);
  int i,j;
 
  dibujo+=2;
  for (i=0;i<sy;i++)
  {
    for (j=0;j<sx;j++)
    {
       //printf("%d",*dibujo);
       setpixel(y+i,x+j,*dibujo);
       dibujo++;
    }
    //printf("\n");
  }
}
                                                                                                                                                                                                                                                                                                                             void setpixel(int y,int x,int color)
{
 putpixel(y,x,__paleta[color].r,__paleta[color].g,__paleta[color].b);
}
 
void lineaH(int y,int x,int sz,int color)
{
  int i;
 
  for(i=x;i<x+sz;i++) setpixel(y,i,color);
}
 
void lineaV(int y,int x,int sz,int color)
{
  int i;
 
  for(i=y;i<y+sz;i++) setpixel(i,x,color);
}
 
void putpixel(int y,int x,int r,int g,int b)
{
   char *pos;
   unsigned char col;
 
   if ((y>__resy-1)||(x>__resx-1)||(y<0)||(x<0)) return;
   pos=__memvid+y*__resx*__Bpp+x*__Bpp;
   switch(__Bpp)
   {
      case 2: r=r>>3;
              g=g>>3;
              b=b>>3;
              col=(r<<3)+(g>>2);
              *(pos+1)=col;
              col=((g&0x03)<<6)+(b>>1);
              *(pos)=col;
              break;
      case 3: *pos=b;
              *(pos+1)=g;
              *(pos+2)=r;
              break;
      case 4: *pos=b;
              *(pos+1)=g;
              *(pos+2)=r;
              *(pos+3)=0;
              break;
   }
}
 
char *initgraphics (int *resy, int *resx)
{
        int framebuffer_device;
        int line_size, buffer_size, i;
        struct fb_var_screeninfo var_info;
 
        framebuffer_device = open ("/dev/fb0", O_RDWR);
        ioctl (framebuffer_device, FBIOGET_VSCREENINFO, &var_info);
        __Bpp=var_info.bits_per_pixel/8;
 
        line_size = var_info.xres * __Bpp;
        __sizevid = line_size * var_info.yres;
 
        var_info.xoffset = 0;
        var_info.yoffset = 0;
        ioctl (framebuffer_device, FBIOPAN_DISPLAY, &var_info); // == -1);
 
        __memvid = (char *) mmap (NULL, __sizevid, PROT_READ | PROT_WRITE, MAP_SHARED, framebuffer_device, 0);
 
        *resx=__resx=var_info.xres;
        *resy=__resy=var_info.yres;
        return __memvid;
}