Browse Source

feat: vsync and double buffer for framebuffer

master
anjingyu 11 months ago
parent
commit
1676583d3b
1 changed files with 40 additions and 20 deletions
  1. +40
    -20
      sww/source/platform/fb.c

+ 40
- 20
sww/source/platform/fb.c 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)
{


Loading…
Cancel
Save