From 01adad0cc7699e9e6d4c6a590ea8f7ecbcb5eaed Mon Sep 17 00:00:00 2001 From: Kunhoon Baik Date: Mon, 24 Jul 2017 23:12:00 +0900 Subject: [PATCH] Fix Second Framebuffer's position calculation System recovery uses double framebuffer when frame buffer backend is enabled. The second framebuffer should be correctly calcualted with fix.line_length because it is real size of row buffer. Thus, for correct calculation, this patch get fixed screen from kernel with FBIOGET_FSCREENINFO ioctl. Change-Id: I3f4640ec60e2db24724a551e1b5f510c2d2791db --- src/librui/fbdev.h | 11 +++--- src/librui/graphics-fbdev-common.c | 5 +++ src/librui/graphics-fbdev.c | 80 +++++++++++++++++++++----------------- 3 files changed, 55 insertions(+), 41 deletions(-) diff --git a/src/librui/fbdev.h b/src/librui/fbdev.h index 0b19be1..2949820 100644 --- a/src/librui/fbdev.h +++ b/src/librui/fbdev.h @@ -30,11 +30,12 @@ extern "C" { #endif typedef struct { - int fd, - displayed_buffer; - gr_surface gr_draw; - GRSurface gr_framebuffer[2]; - struct fb_var_screeninfo vi; + int fd, + displayed_buffer; + gr_surface gr_draw; + GRSurface gr_framebuffer[2]; + struct fb_var_screeninfo vi; + struct fb_fix_screeninfo fi; } fbdev_common; bool fbdev_init_common(gr_backend *backend); diff --git a/src/librui/graphics-fbdev-common.c b/src/librui/graphics-fbdev-common.c index e0255d2..2c4077d 100644 --- a/src/librui/graphics-fbdev-common.c +++ b/src/librui/graphics-fbdev-common.c @@ -47,6 +47,11 @@ bool fbdev_init_common(gr_backend *backend) { return false; } + if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb->fi) < 0) { + printf("Failed to get fb0 fix info"); + return false; + } + /* If you have a device that has other BPP patches welcome... */ if (fb->vi.bits_per_pixel != 32) { printf("Non-32-bit framebuffers not supported yet. Sorry.\n"); diff --git a/src/librui/graphics-fbdev.c b/src/librui/graphics-fbdev.c index 323a447..b37aaca 100644 --- a/src/librui/graphics-fbdev.c +++ b/src/librui/graphics-fbdev.c @@ -71,12 +71,11 @@ static void set_displayed_framebuffer(fbdev_common *fb, unsigned int n) { if (n > 1) return; - if ((signed int)fb->vi.yres_virtual < - fb->gr_framebuffer[0].height * 2) - fb->vi.yres_virtual = fb->gr_framebuffer[0].height * 2; + if(n == 0) + fb->vi.yoffset = 0; + else + fb->vi.yoffset = fb->vi.yres; - fb->vi.yoffset = n * fb->gr_framebuffer[0].height; - fb->vi.bits_per_pixel = fb->gr_framebuffer[0].pixel_bytes * 8; if (ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi) < 0) perror("Active fb swap failed"); @@ -84,37 +83,46 @@ static void set_displayed_framebuffer(fbdev_common *fb, unsigned int n) { } static gr_surface fbdev_init(gr_backend *backend) { - size_t bufsize; - fbdev_common *fb = (fbdev_common *)backend->data; - - if (!fbdev_init_common(backend)) - return NULL; - - bufsize = fb->vi.xres * fb->vi.yres * fb->vi.bits_per_pixel / 8; - - /* Double buffer allocated as single piece of memory */ - fb->gr_framebuffer[0].data = mmap(0, bufsize * 2, - PROT_READ | PROT_WRITE, MAP_SHARED, - fb->fd, 0); - - if (fb->gr_framebuffer[0].data == MAP_FAILED) { - perror("Failed to mmap video memory"); - fbdev_exit(backend); - return NULL; - } - - fb->gr_framebuffer[1].data = fb->gr_framebuffer[0].data + bufsize; - gr_fill_alpha(&fb->gr_framebuffer[0]); - memcpy(fb->gr_framebuffer[1].data, fb->gr_framebuffer[0].data, - bufsize); - set_displayed_framebuffer(fb, 0); - - printf("Framebuffer: %dx%d, %d BPP\n", fb->gr_draw->width, - fb->gr_draw->height, fb->vi.bits_per_pixel); - - fbdev_blank(backend, true); - fbdev_blank(backend, false); - return fb->gr_draw; + size_t bufsize; + size_t bufsize_for_mmap; + int nr_buffer; + + fbdev_common *fb = (fbdev_common *)backend->data; + + if (!fbdev_init_common(backend)) + return NULL; + + nr_buffer = fb->vi.yres_virtual / fb->vi.yres; + printf("Frame buffer nr = %d\n", nr_buffer); + + bufsize = fb->fi.line_length * fb->vi.yres; + //TODO : Based on Kernel code, following code is right. + // : However, it is strange because of bufsize > bufsize_for_mmap + // : It should be re-checked later with other kernel's framebuffer. + bufsize_for_mmap = fb->vi.xres * fb->vi.yres * fb->vi.bits_per_pixel / 8; + + fb->gr_framebuffer[0].data = mmap(0, bufsize_for_mmap * nr_buffer, + PROT_READ | PROT_WRITE, MAP_SHARED, + fb->fd, 0); + + if (fb->gr_framebuffer[0].data == MAP_FAILED) { + perror("Failed to mmap video memory"); + fbdev_exit(backend); + return NULL; + } + + fb->gr_framebuffer[1].data = fb->gr_framebuffer[0].data + bufsize; + gr_fill_alpha(&fb->gr_framebuffer[0]); + memcpy(fb->gr_framebuffer[1].data, fb->gr_framebuffer[0].data, + bufsize); + set_displayed_framebuffer(fb, 0); + + printf("Framebuffer: %dx%d, %d BPP\n", fb->gr_draw->width, + fb->gr_draw->height, fb->vi.bits_per_pixel); + + fbdev_blank(backend, true); + fbdev_blank(backend, false); + return fb->gr_draw; } static gr_surface fbdev_flip(gr_backend *backend) { -- 2.7.4