feat: vsync and double buffer for framebuffer

This commit is contained in:
anjingyu 2025-07-17 14:05:59 +08:00
parent 4041117faf
commit 1676583d3b
1 changed files with 40 additions and 20 deletions

View File

@ -49,6 +49,8 @@ struct swwApp
{
struct termios term;
uint8_t* fb;
int fbfd;
int xres;
int yres;
@ -68,12 +70,15 @@ struct swwWindow
{
swwImage* surface;
/* Poistion on display(framebuffer) */
uint32_t x, y;
/* common data */
swwWindowCallback callback;
void* userdata;
};
swwApp g_app = {{0}, 0, 0, 0, 0, 0, NULL, {-1}, 0, {0}, {0}};
swwApp g_app = {{0}, NULL, 0, 0, 0, 0, 0, NULL, {-1}, 0, {0}, {0}};
/* Signal Handler */
typedef enum
@ -291,8 +296,6 @@ void swwApp_Initialize()
// EnableRawMode();
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
long int screensize = 0;
char* fbp = 0;
g_app.fbfd = open("/dev/fb0", O_RDWR);
if (g_app.fbfd == -1) {
@ -315,6 +318,13 @@ void swwApp_Initialize()
exit(4);
}
g_app.fb = (uint8_t*)mmap(0, g_app.xres * g_app.yres * 4, PROT_READ | PROT_WRITE, MAP_SHARED,
g_app.fbfd, 0);
if (g_app.fb == (void*)-1) {
perror("Error: failed to map framebuffer device to memory");
exit(5);
}
g_app.xres = vinfo.xres;
g_app.yres = vinfo.yres;
@ -354,6 +364,8 @@ void swwApp_Cleanup()
close(g_app.event_source[i].fd);
}
}
munmap(g_app.fb, g_app.xres * g_app.yres * 4);
close(g_app.fbfd);
// DisableRawMode();
}
@ -391,22 +403,11 @@ swwWindow* swwWindow_Create(const char* title, uint32_t width, uint32_t height)
assert(width > 0 && height > 0 && width < g_app.xres && height < g_app.yres);
int screensize = g_app.xres * g_app.yres * 4;
uint8_t* fbp = (uint8_t*)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, g_app.fbfd, 0);
if (fbp == (void*)-1) {
perror("Error: failed to map framebuffer device to memory");
exit(5);
}
o = (swwWindow*)malloc(sizeof(swwWindow));
memset(o, 0, sizeof(swwWindow));
o->surface = swwImage_Create(10, 10, 4);
// NOTE(donkey): An guly patch, the buffer will be allocated by mmap
free(o->surface->buffer);
o->surface->buffer = fbp;
o->surface->width = g_app.xres;
o->surface->height = g_app.yres;
o->surface = swwImage_Create(width, height, 4);
o->x = (g_app.xres - width) >> 1; // divided by 2
o->y = (g_app.yres - height) >> 1; // divided by 2
g_app.window = o;
++g_app.window_count;
@ -417,15 +418,34 @@ swwWindow* swwWindow_Create(const char* title, uint32_t width, uint32_t height)
void swwWindow_Destroy(swwWindow* o)
{
if (o != NULL) {
munmap(o->surface->buffer, o->surface->width * o->surface->height * 4);
swwImage_Destroy(o->surface);
free(o);
--g_app.window_count;
g_app.window = NULL;
}
}
void swwWindow_Present(swwWindow* window)
{}
void swwWindow_Present(swwWindow* o)
{
int i = 0;
/* Start position: <fb4pixels>[y][x] */
uint8_t* start = g_app.fb + (((o->y * g_app.xres) + o->x) << 2);
uint8_t* buf = o->surface->buffer;
size_t line_size = o->o->surface->width << 2;
// VSYNC
int zero = 0;
int ret = ioctl(g_app.fbfd, FBIO_WAITFORVSYNC, &zero);
if (ret != 0) {
perror("Failed to do VSYNC!");
}
/* Copy the window buffer to framebuffer line by line */
for (; i < o->height; ++i, start += (g_app.xres << 2), buf += line_size) {
memcpy(start, buf, line_size);
}
}
uint8_t* swwWindow_LockBuffer(swwWindow* o)
{