#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <linux/kd.h>
#include <stdint.h>
#include <errno.h>
typedef struct __box
{
int x;
int y;
int dx;
int dy;
uint32_t c;
} Box;
int frame_buffer_handle;
long lastms;
struct fb_var_screeninfo varinfo;
struct fb_fix_screeninfo fixinfo;
void draw_pixel(uint32_t *video_buffer, int y, int x, uint32_t c);
void fill_screen(uint32_t *video_buffer, uint32_t c);
void draw_rect(uint32_t *video_buffer, int dy, int dx, int w, int h, uint32_t c);
int msleep(long);
long msnow();
long msnow()
{
struct timespec _t;
clock_gettime(CLOCK_REALTIME, &_t);
return _t.tv_sec * 1000 + _t.tv_nsec / 1000000;
}
int msleep(long msec)
{
struct timespec ts;
int res;
if (msec < 0)
{
errno = EINVAL;
return -1;
}
ts.tv_sec = msec / 1000;
ts.tv_nsec = (msec % 1000) * 1000000;
do
{
res = nanosleep(&ts, &ts);
} while (res && errno == EINTR);
return res;
}
void draw_rect(uint32_t *video_buffer, int dy, int dx, int w, int h, uint32_t c)
{
for (int y = dy; y < dy + h; y++)
for (int x = dx; x < dx + w; x++)
draw_pixel(video_buffer, y, x, c);
}
void fill_screen(uint32_t *video_buffer, uint32_t c)
{
for (int y = 0; y < varinfo.yres; y++)
for (int x = 0; x < varinfo.xres; x++)
draw_pixel(video_buffer, y, x, c);
}
void draw_pixel(uint32_t *video_buffer, int y, int x, uint32_t c)
{
uint32_t offset = varinfo.yoffset == 0 ? varinfo.yres : 0;
uint32_t *addr = video_buffer + ((y + offset) * (fixinfo.line_length >> 2)) + x;
*addr = c;
}
void refresh_screen(int delay)
{
uint32_t offset = varinfo.yoffset == 0 ? varinfo.yres : 0;
varinfo.yoffset = offset;
int ret = ioctl(frame_buffer_handle, FBIOPAN_DISPLAY, &varinfo);
if (delay == 1)
{
long now = msnow();
if (now - lastms < 40)
{
msleep(40 - (now - lastms));
}
lastms = msnow();
}
}
int main()
{
lastms = msnow();
int tty_fd = open("/dev/tty0", O_RDWR);
ioctl(tty_fd, KDSETMODE, KD_GRAPHICS);
srand(time(NULL));
frame_buffer_handle = open("/dev/fb0", O_RDWR);
ioctl(frame_buffer_handle, FBIOGET_FSCREENINFO, &fixinfo);
printf("id: %s\n", fixinfo.id);
printf("smem_start: %ld\n", fixinfo.smem_start);
printf("smem_len: %d\n", fixinfo.smem_len);
printf("line_lenth: %d\n", fixinfo.line_length);
ioctl(frame_buffer_handle, FBIOGET_VSCREENINFO, &varinfo);
printf("resx:%d,resy:%d\n", varinfo.xres, varinfo.yres);
printf("x_virtual:%d,y_virtual:%d\n", varinfo.xres_virtual, varinfo.yres_virtual);
printf("x_offset:%d,y_offset:%d\n", varinfo.xoffset, varinfo.yoffset);
printf("bits_per_pixel:%d\n", varinfo.bits_per_pixel);
size_t len = fixinfo.line_length * varinfo.yres;
uint32_t *video_buffer = mmap(NULL, len * 2, PROT_READ | PROT_WRITE, MAP_SHARED, frame_buffer_handle, 0);
fill_screen(video_buffer, 0xff0000ff);
int box_count = 500;
Box box[box_count];
for (int i = 0; i < box_count; i++)
{
box[i].x = rand() % 380 * 2;
box[i].dx = rand() % 380 * 2;
box[i].y = rand() % 280 * 2;
box[i].dy = rand() % 280 * 2;
box[i].c = ((rand() % 256) << 24) + ((rand() % 256) << 16) + ((rand() % 256) << 8) + rand() % 256;
}
int msstart = msnow();
printf("start at:%ld\n", msstart);
for (int r = 0; r < 500; r++)
{
for (int i = 0; i < box_count; i++)
{
if (box[i].x == box[i].dx && box[i].y == box[i].dy)
{
box[i].dy = rand() % 280 * 2;
box[i].dx = rand() % 380 * 2;
}
else
{
if (box[i].x != box[i].dx)
{
box[i].x += box[i].x > box[i].dx ? -2 : 2;
}
if (box[i].y != box[i].dy)
{
box[i].y += box[i].y > box[i].dy ? -2 : 2;
}
}
}
fill_screen(video_buffer, 0xff0000ff);
for (int i = 0; i < box_count; i++)
{
draw_rect(video_buffer, box[i].y, box[i].x, 32, 32, box[i].c);
}
refresh_screen(1);
}
int msstop = msnow();
printf("stop at:%ld\n", msstop);
printf("fps:%d\n", (500 * 1000) / (msstop - msstart));
ioctl(tty_fd, KDSETMODE, KD_TEXT);
printf("\n");
return 0;
}
framebuffer graphic example
最新推荐文章于 2024-07-13 18:32:53 发布