#include #include #include #include #include #include #include #include #include #include #define MAGICKCORE_QUANTUM_DEPTH 8 #define MAGICKCORE_HDRI_ENABLE 0 #include #include "fb.h" #include "gpio.h" #define WAVEFORM_MODE_INIT 0x0 /* Screen goes to white (clears) */ #define WAVEFORM_MODE_DU 0x1 /* Grey->white/grey->black */ #define WAVEFORM_MODE_GC16 0x2 /* High fidelity (flashing) */ #define WAVEFORM_MODE_GC4 0x3 /* Lower fidelity */ #define WAVEFORM_MODE_A2 0x4 /* Fast black/white animation */ static struct { int fd; unsigned char *addr; struct fb_fix_screeninfo fsi; struct fb_var_screeninfo vsi; size_t size; } fb; static void fb_update(int x, int y, int w, int h) { static int marker = 0; marker++; struct mxcfb_update_data data = { .update_mode = UPDATE_MODE_PARTIAL, .waveform_mode = WAVEFORM_MODE_AUTO, .update_region.left = x, .update_region.top = y, .update_region.width = w, .update_region.height = h, .update_marker = marker, .temp = TEMP_USE_AMBIENT, .flags = 0, }; printf("SEND_UPDATE: "); fflush(NULL); sync(); int r = ioctl(fb.fd, MXCFB_SEND_UPDATE, &data); printf("%d\n", r); fflush(NULL); sync(); struct mxcfb_update_marker_data md = { .update_marker = marker, }; printf("WAIT_FOR_UPDATE_COMPLETE: "); fflush(NULL); sync(); r = ioctl(fb.fd, MXCFB_WAIT_FOR_UPDATE_COMPLETE, &md); printf("%d\n", r); fflush(NULL); sync(); } void fb_blank(void) { memset(fb.addr, 0xff, fb.size); fb_update(0, 0, fb.vsi.xres_virtual, fb.vsi.yres_virtual); } void fb_loadimage(int screen, const char *path) { printf("loading image %s\n", path); fflush(NULL); sync(); ExceptionInfo *exception = AcquireExceptionInfo(); printf("reading original image\n"); ImageInfo *info = CloneImageInfo((ImageInfo*)NULL); strcpy(info->filename, path); Image *images = ReadImage(info, exception); printf("resizing\n"); Image *original = RemoveFirstImageFromList(&images); Image *resized = ResizeImage(original, fb.vsi.xres, fb.vsi.yres, LanczosFilter, exception); DestroyImage(original); printf("rotating\n"); Image *rotated = IntegralRotateImage(resized, 3, exception); DestroyImage(rotated); printf("writing grayscale\n"); AppendImageToList(&images, rotated); strcpy(info->filename, "/tmp/converted.gray"); WriteImage(info, images, exception); printf("cleaning up\n"); DestroyImageList(images); DestroyImage(rotated); DestroyImageInfo(info); DestroyExceptionInfo(exception); int fd = open("/tmp/converted.gray", O_RDONLY); if (fd == -1) { printf("not found\n"); fflush(NULL); sync(); return; } struct stat st; fstat(fd, &st); char *img = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (img == MAP_FAILED) { printf("map failed\n"); fflush(NULL); sync(); return; } printf("copying image..."); fflush(NULL); sync(); unsigned char *buffer = fb.addr + (screen * fb.size / 2); memcpy(buffer, img, st.st_size < fb.size ? st.st_size : fb.size); printf("done\n"); fflush(NULL); sync(); munmap(img, st.st_size); close(fd); fb_update(0, (screen * fb.vsi.yres_virtual / 2), fb.vsi.xres_virtual, fb.vsi.yres_virtual / 2); } void fb_init(void) { MagickCoreGenesis(NULL, MagickFalse); fb.fd = open("/dev/fb0", O_RDWR); ioctl(fb.fd, FBIOGET_FSCREENINFO, &fb.fsi); ioctl(fb.fd, FBIOGET_VSCREENINFO, &fb.vsi); fb.vsi.bits_per_pixel = 8; fb.vsi.grayscale = GRAYSCALE_8BIT; fb.vsi.activate = FB_ACTIVATE_FORCE; ioctl(fb.fd, FBIOPUT_VSCREENINFO, &fb.vsi); fb.size = fb.vsi.xres_virtual * fb.vsi.yres_virtual; fb.addr = mmap(NULL, fb.size, PROT_READ | PROT_WRITE, MAP_SHARED, fb.fd, 0); fb_update(0, 0, fb.vsi.xres_virtual, fb.vsi.yres_virtual); }