diff --git a/blitbuffer.c b/blitbuffer.c index 106a8b286..aef8bab72 100644 --- a/blitbuffer.c +++ b/blitbuffer.c @@ -92,7 +92,7 @@ static int blitFullToBuffer(lua_State *L) { BlitBuffer *dst = (BlitBuffer*) luaL_checkudata(L, 1, "blitbuffer"); BlitBuffer *src = (BlitBuffer*) luaL_checkudata(L, 2, "blitbuffer"); - if(src->w != dst->w || src->h != dst->h) { + if(src->w != dst->w || src->h != dst->h || src->pitch != dst->pitch) { return luaL_error(L, "blitbuffer size must be framebuffer size!"); } diff --git a/einkfb.c b/einkfb.c index b7784e592..a4b995e71 100644 --- a/einkfb.c +++ b/einkfb.c @@ -26,6 +26,7 @@ static int openFrameBuffer(lua_State *L) { const char *fb_device = luaL_checkstring(L, 1); FBInfo *fb = (FBInfo*) lua_newuserdata(L, sizeof(FBInfo)); + uint8_t *fb_map_address = NULL; luaL_getmetatable(L, "einkfb"); @@ -73,13 +74,38 @@ static int openFrameBuffer(lua_State *L) { } /* mmap the framebuffer */ - fb->buf->data = mmap(0, fb->finfo.smem_len, + fb->buf->pitch = fb->finfo.line_length; + fb_map_address = mmap(0, fb->finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fb->fd, 0); if(fb->buf->data == MAP_FAILED) { return luaL_error(L, "cannot mmap framebuffer"); } - memset(fb->buf->data, 0, fb->finfo.smem_len); - fb->buf->pitch = fb->finfo.line_length; + if (fb->vinfo.bits_per_pixel != 4) { + /* for 8bpp K4, we create a shadow 4bpp blitbuffer + * K4 uses 16 scale 8bpp framebuffer, so we still cheat it as 4bpp */ + fb->buf->pitch = fb->buf->pitch / 2; + + fb->buf->data = malloc(fb->buf->pitch * fb->vinfo.yres); + if (!fb->buf->data) { + return luaL_error(L, "failed to allocate memory for framebuffer's shadow blitbuffer!"); + } + fb->buf->allocated = 1; + + fb->real_buf = (BlitBuffer *)malloc(sizeof(BlitBuffer)); + if (!fb->buf->data) { + return luaL_error(L, "failed to allocate memory for framebuffer's blitbuffer!"); + } + fb->real_buf->pitch = fb->finfo.line_length; + fb->real_buf->w = fb->vinfo.xres; + fb->real_buf->h = fb->vinfo.yres; + fb->real_buf->allocated = 0; + fb->real_buf->data = fb_map_address; + } else { + /* for K2, K3 and DXG, we map framebuffer to fb->buf->data directly */ + fb->real_buf = NULL; + fb->buf->data = fb_map_address; + } + memset(fb->buf->data, 0, fb->buf->pitch * fb->buf->h); #else if(SDL_Init(SDL_INIT_VIDEO) < 0) { return luaL_error(L, "cannot initialize SDL."); @@ -118,6 +144,9 @@ static int closeFrameBuffer(lua_State *L) { close(fb->fd); #else free(fb->buf->data); + if (fb->vinfo.bits_per_pixel != 4) { + free(fb->real_buf->data); + } #endif fb->buf->data = NULL; // the blitbuffer in fb->buf should be freed @@ -133,24 +162,25 @@ static int einkUpdate(lua_State *L) { // for Kindle e-ink display int fxtype = luaL_optint(L, 2, 0); #ifndef EMULATE_READER - int i = 0, j = 0, h = 0, w = 0; + int i = 0, j = 0, h = 0, w = 0, pitch = 0; uint8_t *fb_buf = NULL; - /* dulplicate 4bpp to 8bpp */ + /* copy bitmap from 4bpp shadow blitbuffer to framebuffer */ if (fb->vinfo.bits_per_pixel != 4) { fb_buf = fb->buf->data; h = fb->buf->h; w = fb->buf->w; + pitch = fb->buf->pitch; for (i = (h-1); i > 0; i--) { for (j = (w-1)/2; j > 0; j--) { - fb_buf[i*w + j*2] = fb_buf[i*w + j]; - fb_buf[i*w + j*2] &= 0xF0; - fb_buf[i*w + j*2] |= fb_buf[i*w + j*2]>>4 & 0x0F; + fb->real_buf->data[i*w + j*2] = fb_buf[i*pitch + j]; + fb->real_buf->data[i*w + j*2] &= 0xF0; + fb->real_buf->data[i*w + j*2] |= fb_buf[i*pitch + j]>>4 & 0x0F; - fb_buf[i*w + j*2 + 1] = fb_buf[i*w + j]; - fb_buf[i*w + j*2 + 1] &= 0x0F; - fb_buf[i*w + j*2 + 1] |= fb_buf[i*w + j*2 + 1]<<4 & 0xF0; + fb->real_buf->data[i*w + j*2 + 1] = fb_buf[i*pitch + j]; + fb->real_buf->data[i*w + j*2 + 1] &= 0x0F; + fb->real_buf->data[i*w + j*2 + 1] |= fb_buf[i*pitch + j]<<4 & 0xF0; } } } @@ -163,15 +193,6 @@ static int einkUpdate(lua_State *L) { myarea.buffer = NULL; myarea.which_fx = fxtype ? fx_update_partial : fx_update_full; ioctl(fb->fd, FBIO_EINK_UPDATE_DISPLAY_AREA, &myarea); - - /* revert 8bpp to 4bpp */ - if (fb->vinfo.bits_per_pixel != 4) { - for (i = 0; i < h; i++) { - for (j = 0; j < w/2; j++) { - fb_buf[i*w + j] = (fb_buf[i*w + j*2] & 0xF0) | (fb_buf[i*w + j*2 + 1] & 0x0F); - } - } - } #else // for now, we only do fullscreen blits in emulation mode if (fxtype == 0) { diff --git a/einkfb.h b/einkfb.h index d3c0ca933..f7d3c019f 100644 --- a/einkfb.h +++ b/einkfb.h @@ -38,6 +38,7 @@ struct fb_var_screeninfo { typedef struct FBInfo { int fd; BlitBuffer *buf; + BlitBuffer *real_buf; #ifdef EMULATE_READER SDL_Surface *screen; #else