FIX: Fixed framebuffer freeze upon screenshot

This commit is contained in:
boreddevnl
2026-04-01 23:05:52 +02:00
parent d7d97b5a97
commit 9634ebb086
6 changed files with 106 additions and 87 deletions

View File

@@ -9,16 +9,38 @@
#include "stb_image_write.h"
#include <string.h>
#define GUI_CMD_GET_SCREEN_SIZE 17
#define GUI_CMD_GET_SCREENBUFFER 18
#define GUI_CMD_SHOW_NOTIFICATION 19
#define GUI_CMD_GET_DATETIME 20
#define GUI_CMD_GET_SCREEN_SIZE 50
#define GUI_CMD_GET_SCREENBUFFER 51
#define GUI_CMD_SHOW_NOTIFICATION 52
#define GUI_CMD_GET_DATETIME 53
#define PNG_WRITE_BUF_SIZE (8 * 1024 * 1024) // 8MB buffer to hold entire PNG
static uint8_t *png_output_buf = NULL;
static int png_output_idx = 0;
void png_write_func(void *context, void *data, int size) {
int fd = *(int*)context;
sys_write_fs(fd, data, size);
(void)context;
if (!png_output_buf) return;
if (png_output_idx + size < PNG_WRITE_BUF_SIZE) {
memcpy(png_output_buf + png_output_idx, data, size);
png_output_idx += size;
}
}
// Global filename for helper functions
static char g_filename[128];
void append_num(int num, int digits) {
int len = 0; while (g_filename[len]) len++;
if (digits == 4) {
g_filename[len++] = '0' + (num / 1000) % 10;
g_filename[len++] = '0' + (num / 100) % 10;
}
g_filename[len++] = '0' + (num / 10) % 10;
g_filename[len++] = '0' + (num % 10);
g_filename[len] = '\0';
}
int main(int argc, char **argv) {
(void)argc;
@@ -29,28 +51,25 @@ int main(int argc, char **argv) {
syscall3(SYS_GUI, GUI_CMD_GET_SCREEN_SIZE, (uint64_t)&w, (uint64_t)&h);
if (w == 0 || h == 0 || w > 4096 || h > 4096) {
printf("Failed to get screen size %d x %d\n", (int)w, (int)h);
return 1;
}
// 2. Allocate buffer for 0xAARRGGBB
// 2. Allocate buffers
uint32_t *pixels = (uint32_t *)malloc(w * h * sizeof(uint32_t));
if (!pixels) {
printf("Failed to allocate memory for %d x %d pixels\n", (int)w, (int)h);
uint8_t *rgb_pixels = (uint8_t *)malloc(w * h * 3);
png_output_buf = (uint8_t *)malloc(PNG_WRITE_BUF_SIZE);
if (!pixels || !rgb_pixels || !png_output_buf) {
if (pixels) free(pixels);
if (rgb_pixels) free(rgb_pixels);
if (png_output_buf) free(png_output_buf);
return 1;
}
// 3. Request screenbuffer
syscall2(SYS_GUI, GUI_CMD_GET_SCREENBUFFER, (uint64_t)pixels);
// 4. Convert 0xAARRGGBB to RGB for stb_image_write
uint8_t *rgb_pixels = (uint8_t *)malloc(w * h * 3);
if (!rgb_pixels) {
printf("Failed to allocate RGB buffer\n");
free(pixels);
return 1;
}
// 4. Convert 0xAARRGGBB to RGB
for (int y = 0; y < (int)h; y++) {
for (int x = 0; x < (int)w; x++) {
uint32_t px = pixels[y * w + x];
@@ -61,62 +80,50 @@ int main(int argc, char **argv) {
}
}
// 5. Get Datetime for filename
// 5. Get Datetime and construct filename
uint64_t dt[6] = {0};
syscall2(SYS_GUI, GUI_CMD_GET_DATETIME, (uint64_t)dt);
char filename[128] = "A:/Desktop/screenshot-";
strcpy(g_filename, "/Desktop/screenshot-");
append_num((int)dt[0], 4); // Year
append_num((int)dt[1], 2); // Month
append_num((int)dt[2], 2); // Day
// Quick helper to append 4-digit and 2-digit numbers
auto void append_num(int num, int digits);
void append_num(int num, int digits) {
int len = 0; while (filename[len]) len++;
if (digits == 4) {
filename[len++] = '0' + (num / 1000) % 10;
filename[len++] = '0' + (num / 100) % 10;
int len = strlen(g_filename);
g_filename[len++] = '-'; g_filename[len] = '\0';
append_num((int)dt[3], 2); // Hour
append_num((int)dt[4], 2); // Min
append_num((int)dt[5], 2); // Sec
strcat(g_filename, ".png");
// 6. Generate PNG in memory
png_output_idx = 0;
int res = stbi_write_png_to_func(png_write_func, NULL, (int)w, (int)h, 3, rgb_pixels, (int)w * 3);
// 7. Perform a SINGLE write to the filesystem
if (res && png_output_idx > 0) {
int fd = sys_open(g_filename, "w");
if (fd >= 0) {
sys_write_fs(fd, png_output_buf, png_output_idx);
sys_close(fd);
// Show notification
char notif[256] = "Saved ";
strcat(notif, g_filename + 9); // Skip "/Desktop/"
syscall2(SYS_GUI, GUI_CMD_SHOW_NOTIFICATION, (uint64_t)notif);
} else {
res = 0;
}
filename[len++] = '0' + (num / 10) % 10;
filename[len++] = '0' + (num % 10);
filename[len] = '\0';
}
append_num((int)dt[0], 4);
append_num((int)dt[1], 2);
append_num((int)dt[2], 2);
int len = 0; while (filename[len]) len++;
filename[len++] = '-'; filename[len] = '\0';
append_num((int)dt[3], 2);
append_num((int)dt[4], 2);
append_num((int)dt[5], 2);
len = 0; while (filename[len]) len++;
filename[len++] = '.'; filename[len++] = 'p'; filename[len++] = 'n'; filename[len++] = 'g'; filename[len] = '\0';
// 6. Write to PNG
int fd = sys_open(filename, "w"); // Open file
int res = 0;
if (fd >= 0) {
res = stbi_write_png_to_func(png_write_func, &fd, (int)w, (int)h, 3, rgb_pixels, (int)w * 3);
sys_close(fd); // Close file
if (!res) {
syscall2(SYS_GUI, GUI_CMD_SHOW_NOTIFICATION, (uint64_t)"Failed to save screenshot");
}
free(png_output_buf);
free(rgb_pixels);
free(pixels);
if (res) {
char notif[256] = "Saved ";
int nlen = 6;
int flen = 0;
while (filename[11 + flen]) {
notif[nlen + flen] = filename[11 + flen];
flen++;
}
notif[nlen + flen] = '\0';
syscall2(SYS_GUI, GUI_CMD_SHOW_NOTIFICATION, (uint64_t)notif);
} else {
syscall2(SYS_GUI, GUI_CMD_SHOW_NOTIFICATION, (uint64_t)"Failed to save screenshot");
return 1;
}
return 0;
return res ? 0 : 1;
}