Rick,
I've attached the source code for some framebuffer experimentation I did.
You'll see circle, line and filled triangle code. Should be self
explanatory.
To compile :-
gcc frame.c -o frame
Best regards,
Mark
On 18 December 2014 at 22:12, Rick Mann <[email protected]> wrote:
>
>
> > On Dec 18, 2014, at 00:29 , [email protected] wrote:
> >
> > Have you tried writing direct to the Video Frame Buffer, I have.
>
> I wrote an app that used SDL, but it had to use (I think) a software frame
> buffer, something about there not being support in the kernel for some
> hardware frame buffer? I'm not sure what it was. But I'd love to be able to
> use SDL to take over the entire display, and not use any kind of desktop or
> window manager (that's just buckets of more code that slow boot/launch
> times).
>
> For my app, fast update wasn't necessary (it was a process automation
> controller-type thing), but it would be nice to be able to draw as fast as
> possible with SDL.
>
> Does this work now?
>
> Thanks!
>
> --
> Rick Mann
> [email protected]
>
>
> --
> For more options, visit http://beagleboard.org/discuss
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "BeagleBoard" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/beagleboard/3zwXeVcTXtM/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> [email protected].
> For more options, visit https://groups.google.com/d/optout.
>
--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups
"BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <math.h>
/* This program grabs a pointer to the framebuffer and plots some pixels */
/* Macro definitions */
#ifndef PI
#define PI 3.141592654
#endif
#define sign(_x) (_x<0?-1:1)
#define ASPECT 1
#define ROUND(value) ((int)((value) + 0.5))
#define A2X(angle,radius) ROUND(ASPECT * radius * sin(angle))
#define A2Y(angle,radius) ROUND(radius * cos(angle))
#define RANDBETWEEN(min,max) (rand()%(max-min))+min
/* value constants */
const int TIMES2 = 2;
/* Global pointer to the framebuffer */
char *fbp = 0;
long int screensize = 0;
/* structures to hold video capability data */
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
typedef struct _RGB16 {
unsigned short int b:5;
unsigned short int g:6;
unsigned short int r:5;
} RGB16, *ptrRGB16;
typedef struct _Point2d {
int x;
int y;
} Point2d, *ptrPoint2d;
typedef struct _Point3d {
int x;
int y;
int z;
} Point3d, *ptrPoint3d;
typedef struct _Triangle {
Point2d A;
Point2d B;
Point2d C;
char r;
char g;
char b;
} Triangle, *ptrTriangle;
typedef struct _Rectangle {
Triangle TA;
Triangle TB;
} Rectangle, *ptrRectangle;
typedef struct _Hexagon {
Triangle Ta;
Triangle Tb;
Triangle Tc;
Triangle Td;
Triangle Te;
Triangle Tf;
} Hexagon, *ptrHexagon;
/* function declaration area */
void clearScreen();
void drawBase();
inline void SwapPoints( ptrPoint2d *A, ptrPoint2d *B );
void createRectangle( int x1, int y1, int x2, int y2, char r, char g, char b, ptrRectangle Rect );
void createTriangle( int x1, int y1, int x2, int y2, int x3, int y3, char r, char g, char b, ptrTriangle Tri );
void createHexagon( int x, int y, int Radius, char r, char g, char b, ptrHexagon Hex );
/* Drawing code */
void getLineXYPoints( int startY, Point2d *ptrA, Point2d *ptrB, Point2d results[] );
void drawTile( int x, int y, int h, char r, char g, char b );
void dline( int from_x, int from_y, int x2, int y2, char r, char g, char b );
void rasterCircle(int x0, int y0, int radius, char r, char g, char b );
void fillCircle(int x0, int y0, int radius, char r, char g, char b );
void fillTriangle( ptrTriangle myTri );
void rasterTriangle( ptrTriangle myTri );
void rasterRectangle( ptrRectangle myRect );
void fillRectangle( ptrRectangle myRect );
void rasterHexagon( ptrHexagon myHex );
void fillHexagon( ptrHexagon myHex );
/* Pointers to Functions */
void (*plotPixel)( int x, int y, char r, char g, char b );
void (*hline)( int x_from, int y_from, int x2, char r, char g, char b );
void (*vline)( int x_from, int y_from, int y2, char r, char g, char b );
/* Colour depth specific primitives */
void plotPixel16( int x, int y, char r, char g, char b );
void plotPixel32( int x, int y, char r, char g, char b );
void hline16( int x_from, int y_from, int x2, char r, char g, char b );
void hline32( int x_from, int y_from, int x2, char r, char g, char b );
void vline16( int x_from, int y_from, int y2, char r, char g, char b );
void vline32( int x_from, int y_from, int y2, char r, char g, char b );
int main()
{
int fbfd = 0;
// Open the file for reading and writing
fbfd = open("/dev/fb0", O_RDWR);
if (!fbfd)
{
printf("Error: cannot open framebuffer device.\n");
return(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");
return(2);
}
// Get variable screen information
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))
{
printf("Error reading variable information.\n");
return(3);
}
// Figure out the size of the screen in bytes
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
/* determine which plot and draw functions we're going to use */
if ( vinfo.bits_per_pixel == 32 )
{
plotPixel = &plotPixel32;
hline = &hline32;
vline = &vline32;
}
else
{ //assume 16bpp
plotPixel = &plotPixel16;
hline = &hline16;
vline = &vline16;
}
// Map the device to memory
fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,
fbfd, 0);
/* ensure that we got a valid pointer */
if ((int)fbp == -1)
{
printf("Error: failed to map framebuffer device to memory.\n");
return(4);
}
/****************************************************/
/* Do not do anything graphical above this comment! */
/****************************************************/
while( 1 )
{
Hexagon myHex;
int Radius = RANDBETWEEN( 5, 100 ) * 2;
createHexagon( RANDBETWEEN( Radius, vinfo.xres - Radius ), RANDBETWEEN( Radius, vinfo.yres - Radius ), Radius, RANDBETWEEN( 0, 31 ), RANDBETWEEN( 0, 63 ), RANDBETWEEN( 0, 31 ), &myHex );
myHex.Ta.r = myHex.Tb.r = RANDBETWEEN( 0, 31 );
myHex.Ta.g = myHex.Tb.g = RANDBETWEEN( 0, 63 );
myHex.Ta.b = myHex.Tb.b = RANDBETWEEN( 0, 31 );
myHex.Tc.r = myHex.Td.r = RANDBETWEEN( 0, 31 );
myHex.Tc.g = myHex.Td.g = RANDBETWEEN( 0, 63 );
myHex.Tc.b = myHex.Td.b = RANDBETWEEN( 0, 31 );
fillHexagon( &myHex );
}
printf("The framebuffer device was mapped to memory successfully.\n");
printf(" The framebuffer starts at %0x\n", fbp);
printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel );
printf("Line length is %d bytes\n", finfo.line_length );
munmap(fbp, screensize);
close(fbfd);
return 0;
}
inline void SwapPoints( ptrPoint2d *A, ptrPoint2d *B )
{
Point2d *ptrWork;
ptrWork = *A;
*A = *B;
*B = ptrWork;
}
/* function to plot a pixel defined by rgb at location x,y */
void plotPixel16( int x, int y, char r, char g, char b )
{
long int location = 0;
RGB16 colour;
/* set the colour value */
colour.r = r;
colour.g = g;
colour.b = b;
location = (x+vinfo.xoffset) * 2 +
(y+vinfo.yoffset) * finfo.line_length;
*((unsigned short int*)(fbp + location)) = *(unsigned short int*)&colour;
}
void plotPixel32( int x, int y, char r, char g, char b )
{
long int location = 0;
location = (x+vinfo.xoffset) * 4 +
(y+vinfo.yoffset) * finfo.line_length;
*(fbp + location) = b;
*(fbp + location + 1) = g;
*(fbp + location + 2) = r;
*(fbp + location + 3) = 0; // No transparency
}
/* Draw a diagonal(arbitrary) line using Bresenham's alogrithm. */
void dline( int from_x, int from_y, int x2, int y2, char r, char g, char b )
{
int dx, dy;
int ax, ay;
int sx, sy;
int x, y;
int d;
/* safety check to see if we can do a vertical or horizontal optimised line */
if( from_x == x2 )
{
/* it's a vertical line */
vline( from_x, from_y, y2, r, g, b );
return;
}
if( from_y == y2 )
{
/* it's a horizontal line */
hline( from_x, from_y, x2, r, g, b );
return;
}
dx = x2 - from_x;
dy = y2 - from_y;
ax = abs(dx * 2);
ay = abs(dy * 2);
sx = sign(dx);
sy = sign(dy);
x = from_x;
y = from_y;
if (ax > ay)
{
d = ay - (ax / 2);
while (1)
{
plotPixel( x, y, r, g, b);
if (x == x2)
{
return;
}
if (d >= 0)
{
y += sy;
d -= ax;
}
x += sx;
d += ay;
}
}
else
{
d = ax - (ay / 2);
while (1)
{
plotPixel( x, y, r, g, b);
if (y == y2)
{
return;
}
if (d >= 0)
{
x += sx;
d -= ay;
}
y += sy;
d += ax;
}
}
} /* end of function dline */
/* optimised horizontal line drawing function */
void hline16( int x_from, int y_from, int x2, char r, char g, char b )
{
long int location = 0;
unsigned int iCount;
int iWork;
RGB16 colour;
/* set the colour value */
colour.r = r;
colour.g = g;
colour.b = b;
if( x_from > x2 )
{
iWork = x_from;
x_from = x2;
x2 = iWork;
}
/* determine the start location */
location = (x_from + vinfo.xoffset) * 2 +
(y_from + vinfo.yoffset) * finfo.line_length;
for( iCount = x_from; iCount <= x2; iCount++ )
{
*((unsigned short int*)(fbp + location)) = *(unsigned short int*)&colour;
location++;
location++;
}
}
void hline32( int x_from, int y_from, int x2, char r, char g, char b )
{
}
void vline16( int x_from, int y_from, int y2, char r, char g, char b )
{
long int location = 0;
int iCount;
RGB16 colour;
/* set the colour value */
colour.r = r;
colour.g = g;
colour.b = b;
/* safety first, we draw our linrs from the top of the screen downwards */
if( y_from > y2 )
{
iCount = y_from;
y_from = y2;
y2 = iCount;
}
/* calculate the start point */
location = (x_from + vinfo.xoffset) * 2 +
(y_from + vinfo.yoffset) * finfo.line_length;
for( iCount = y_from; iCount <= y2; iCount++ )
{
*((unsigned short int*)(fbp + location)) = *(unsigned short int*)&colour;
location += finfo.line_length;
}
}
void vline32( int x_from, int y_from, int y2, char r, char g, char b )
{
}
/* draw an outline circle */
void rasterCircle(int x0, int y0, int radius, char r, char g, char b )
{
int f = 1 - radius;
int ddF_x = 1;
int ddF_y = -2 * radius;
int x = 0;
int y = radius;
plotPixel(x0, y0 + radius, r, g, b );
plotPixel(x0, y0 - radius, r, g, b );
plotPixel(x0 + radius, y0, r, g, b );
plotPixel(x0 - radius, y0, r, g, b );
while(x < y)
{
if(f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
plotPixel(x0 + x, y0 + y, r, g, b);
plotPixel(x0 - x, y0 + y, r, g, b);
plotPixel(x0 + x, y0 - y, r, g, b);
plotPixel(x0 - x, y0 - y, r, g, b);
plotPixel(x0 + y, y0 + x, r, g, b);
plotPixel(x0 - y, y0 + x, r, g, b);
plotPixel(x0 + y, y0 - x, r, g, b);
plotPixel(x0 - y, y0 - x, r, g, b);
}
}
/* draw a filled circle using optimised horizontal line function */
void fillCircle(int x0, int y0, int radius, char r, char g, char b )
{
int f;
int ddF_x;
int ddF_y;
int x;
int y;
/* initialise the working variables */
f = 1 - radius;
ddF_x = 1;
ddF_y = -2 * radius;
x = 0;
y = radius;
/* draw the middle line */
hline( x0 - radius, y0, x0 + radius, r, g, b);
while(x < y)
{
if( f >= 0 )
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
/* draw the four sections */
hline( x0 - x, y0 + y, x0 + x, r, g, b);
hline( x0 - x, y0 - y, x0 + x, r, g, b);
hline( x0 - y, y0 + x, x0 + y, r, g, b);
hline( x0 - y, y0 - x, x0 + y, r, g, b);
}
}
/* function to clear the screen */
void clearScreen()
{
long int location = 0;
memset( (unsigned short int*)(fbp + location), 0, screensize );
}
#define T_Height 30
#define T_Width 40
/* draw a single diamond shaped "isometric" tile. */
void drawTile( int x, int y, int h, char r, char g, char b )
{
int iHeight;
int iWidth;
iHeight = T_Height;
iWidth = T_Width;
dline( x, y - iHeight, x + iWidth, y, r, g, b );
dline( x, y - iHeight, x - iWidth, y, r, g, b );
dline( x + iWidth, y, x, y + iHeight, r, g, b );
dline( x - iWidth, y, x, y + iHeight, r, g, b );
}
#define BASEOFFSET 10
/* build a "base" from a number of "Tiles" */
void drawBase()
{
int x_start = T_Height + BASEOFFSET;
int y_start = T_Height + BASEOFFSET;
int xCount;
int yCount;
for( xCount = 0; xCount < 8; xCount++ )
{
for( yCount = 0; yCount < 8; yCount++)
{
char g = RANDBETWEEN(0,63);
drawTile( x_start, y_start, 10, 0, g, 0 );
if( g > 15 )
{
fillCircle( x_start, y_start, 10, RANDBETWEEN(0,31), RANDBETWEEN(0,31), RANDBETWEEN(0,31) );
}
else
{
fillCircle( x_start, y_start, 10, 0, 0, 0 );
}
y_start += (T_Height * 2);
}
x_start += (T_Width * 2);
y_start = T_Height + BASEOFFSET;
}
}
void rasterTriangle( ptrTriangle Tri )
{
dline( Tri->A.x, Tri->A.y, Tri->B.x, Tri->B.y, Tri->r, Tri->g, Tri->b );
dline( Tri->A.x, Tri->A.y, Tri->C.x, Tri->C.y, Tri->r, Tri->g, Tri->b );
dline( Tri->B.x, Tri->B.y, Tri->C.x, Tri->C.y, Tri->r, Tri->g, Tri->b );
}
/* ********************************************** */
/* getLineXYPoints */
/* ********************************************** */
/* populate a preallocated array with the */
/* Point values required to create a line between */
/* ptrA and ptrB. */
/* startY = offset from the top of the screen of */
/* the start of the line */
/* ********************************************** */
inline void getLineXYPoints( int startY, Point2d *ptrA, Point2d *ptrB, Point2d results[] )
{
int dx, dy;
int ax, ay;
int sx, sy;
int x, y;
int d;
dx = ptrB->x - ptrA->x;
dy = ptrB->y - ptrA->y;
ax = abs(dx * 2);
ay = abs(dy * 2);
sx = sign(dx);
sy = sign(dy);
x = ptrA->x;
y = ptrA->y;
if (ax > ay)
{
d = ay - (ax / 2);
while( 1 )
{
results[ y - startY ].x = x;
results[ y - startY ].y = y;
if( x == ptrB->x )
{
return;
}
if (d >= 0)
{
y += sy;
d -= ax;
}
x += sx;
d += ay;
}
}
else
{
d = ax - (ay / 2);
while (1)
{
results[ y - startY ].x = x;
results[ y - startY ].y = y;
if( y == ptrB->y )
{
return;
}
if (d >= 0)
{
x += sx;
d -= ay;
}
y += sy;
d += ax;
}
}
} /* end of function getLineXYPoints */
/* ********************************************** */
/* fillTriangle */
/* ********************************************** */
/* Draw a filled Triangle of Points A, B, C */
/* of colour r,g,b */
/* Triangle is drawn by means of Horizontal Lines */
/* calculated A->B, A->C, C->B */
/* ********************************************** */
inline void fillTriangle( ptrTriangle Tri )
{
char r,g,b;
int iNumA, iNumB, iNumC;
int iNumLines;
Point2d *ptrA,*ptrB,*ptrC, *ptrWork;
Point2d *leftmost,*rightmost;
/* obtain the points of the triangle */
ptrA = &Tri->A;
ptrB = &Tri->B;
ptrC = &Tri->C;
/* obtain the colour */
r = Tri->r;
g = Tri->g;
b = Tri->b;
/* Find the top-most point of the triangle */
if( ptrA->y > ptrB->y )
{
SwapPoints( &ptrA, &ptrB );
}
if( ptrB->y > ptrC->y )
{
SwapPoints( &ptrB, &ptrC );
}
if( ptrA->y > ptrB->y )
{
SwapPoints( &ptrA, &ptrB );
}
/* get the line lengths */
iNumA = abs( ptrA->y - ptrB->y );
iNumB = abs( ptrB->y - ptrC->y );
iNumC = abs( ptrA->y - ptrC->y );
/* determine the longest "Y" line */
/* we don't have to worry about "line B" as this will always have a lower "Y" value */
iNumLines = iNumA;
if( iNumA < iNumC )
{
iNumLines = iNumC;
}
/* Allocate memory for side Line start and end points */
leftmost = (Point2d *)calloc( iNumLines + 1, sizeof( Point2d ) );
rightmost = (Point2d *)calloc( iNumLines + 1, sizeof( Point2d ) );
/* Points for line A */
getLineXYPoints( ptrA->y, ptrA, ptrB, rightmost );
/* Points for line C */
getLineXYPoints( ptrA->y, ptrA, ptrC, leftmost );
/* calculate which Line B to use */
if( iNumA < iNumC )
{
getLineXYPoints( ptrA->y, ptrC, ptrB, rightmost );
}
else
{
getLineXYPoints( ptrA->y, ptrC, ptrB, leftmost );
}
register int count1;
for( count1 = 0; count1 < iNumLines; count1++ )
{
hline( leftmost[count1].x, leftmost[count1].y, rightmost[count1].x, r, g, b );
}
free( leftmost );
free( rightmost );
} /* end of function fillTriangle */
void createRectangle( int x1, int y1, int x2, int y2, char r, char g, char b, ptrRectangle Rect )
{
createTriangle( x1, y1, x2, y1, x1, y2, r, g, b, &(Rect->TA) );
createTriangle( x2, y2, x2, y1, x1, y2, r, g, b, &(Rect->TB) );
}
void createTriangle( int x1, int y1, int x2, int y2, int x3, int y3, char r, char g, char b, ptrTriangle Tri )
{
Tri->A.x = x1;
Tri->A.y = y1;
Tri->B.x = x2;
Tri->B.y = y2;
Tri->C.x = x3;
Tri->C.y = y3;
/* Set the colour */
Tri->r = r;
Tri->g = g;
Tri->b = b;
} /* end of function createTriangle */
void createHexagon( int x, int y, int Radius, char r, char g, char b, ptrHexagon Hex )
{
/* set the central coordinate */
Hex->Ta.C.x = Hex->Tb.C.x = Hex->Tc.C.x = Hex->Td.C.x = Hex->Te.C.x = Hex->Tf.C.x = x;
Hex->Ta.C.y = Hex->Tb.C.y = Hex->Tc.C.y = Hex->Td.C.y = Hex->Te.C.y = Hex->Tf.C.y = y;
Hex->Te.A.y = Hex->Tf.A.y = Hex->Tb.B.y = Hex->Tc.B.y = y;
Hex->Te.A.x = Hex->Tf.A.x = ( x - Radius );
Hex->Tc.B.x = Hex->Tb.B.x = ( x + Radius );
Hex->Ta.B.x = Hex->Tf.B.x = Hex->Te.B.x = Hex->Td.B.x = x - ( Radius/2 );
Hex->Ta.A.x = Hex->Tb.A.x = Hex->Tc.A.x = Hex->Td.A.x = x + ( Radius/2 );
Hex->Tf.B.y = Hex->Ta.B.y = Hex->Ta.A.y = Hex->Tb.A.y = (y - Radius);
Hex->Te.B.y = Hex->Td.B.y = Hex->Td.A.y = Hex->Tc.A.y = (y + Radius);
Hex->Ta.r = Hex->Tb.r = Hex->Tc.r = Hex->Td.r = Hex->Te.r = Hex->Tf.r = r;
Hex->Ta.g = Hex->Tb.g = Hex->Tc.g = Hex->Td.g = Hex->Te.g = Hex->Tf.g = g;
Hex->Ta.b = Hex->Tb.b = Hex->Tc.b = Hex->Td.b = Hex->Te.b = Hex->Tf.b = b;
} /* end of function create hexagon */
void rasterHexagon( ptrHexagon Hex )
{
dline( Hex->Ta.B.x, Hex->Ta.B.y, Hex->Ta.A.x, Hex->Ta.B.y, Hex->Ta.r, Hex->Ta.g, Hex->Ta.b );
dline( Hex->Tb.A.x, Hex->Tb.A.y, Hex->Tb.B.x, Hex->Tb.B.y, Hex->Tb.r, Hex->Tb.g, Hex->Tb.b );
dline( Hex->Tc.B.x, Hex->Tc.B.y, Hex->Tc.A.x, Hex->Tc.A.y, Hex->Tc.r, Hex->Tc.g, Hex->Tc.b );
dline( Hex->Td.A.x, Hex->Td.A.y, Hex->Td.B.x, Hex->Td.B.y, Hex->Td.r, Hex->Td.g, Hex->Td.b );
dline( Hex->Te.B.x, Hex->Te.B.y, Hex->Te.A.x, Hex->Te.A.y, Hex->Te.r, Hex->Te.g, Hex->Te.b );
dline( Hex->Tf.A.x, Hex->Tf.A.y, Hex->Tf.B.x, Hex->Tf.B.y, Hex->Tf.r, Hex->Tf.g, Hex->Tf.b );
}
void fillHexagon( ptrHexagon myHex )
{
fillTriangle( &myHex->Tf );
fillTriangle( &myHex->Ta );
fillTriangle( &myHex->Tb );
fillTriangle( &myHex->Te );
fillTriangle( &myHex->Td );
fillTriangle( &myHex->Tc );
}
void rasterRectangle( ptrRectangle my_rect )
{
/* first draw the horizontal lines */
dline( my_rect->TA.A.x, my_rect->TA.A.y, my_rect->TA.B.x, my_rect->TA.B.y, my_rect->TA.r, my_rect->TA.g, my_rect->TA.b );
dline( my_rect->TB.C.x, my_rect->TB.C.y, my_rect->TB.A.x, my_rect->TB.A.y, my_rect->TA.r, my_rect->TA.g, my_rect->TA.b );
/* now vertical */
dline( my_rect->TA.A.x, my_rect->TA.A.y, my_rect->TA.C.x, my_rect->TA.C.y, my_rect->TA.r, my_rect->TA.g, my_rect->TA.b );
dline( my_rect->TA.B.x, my_rect->TA.B.y, my_rect->TB.A.x, my_rect->TB.A.y, my_rect->TA.r, my_rect->TA.g, my_rect->TA.b );
} /* end of function rasterRectangle */
void fillRectangle( ptrRectangle my_rect )
{
fillTriangle( &my_rect->TA );
fillTriangle( &my_rect->TB );
} /* end of function fillRectangle */
/* end of source file frame.c */