From 4ee5ad751feb91fdc29b78e2025c1b6a775d8e92 Mon Sep 17 00:00:00 2001 From: Ethan Yonker Date: Tue, 18 Feb 2014 18:41:17 -0600 Subject: Support Qualcomm overlay graphics in recovery Change-Id: Ia75c34ab1a45b7c8802c902906198517aa3437d5 --- minuitwrp/graphics.c | 160 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 130 insertions(+), 30 deletions(-) (limited to 'minuitwrp/graphics.c') diff --git a/minuitwrp/graphics.c b/minuitwrp/graphics.c index 3a35c587c..bd611b380 100644 --- a/minuitwrp/graphics.c +++ b/minuitwrp/graphics.c @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -52,6 +53,7 @@ #endif #define NUM_BUFFERS 2 +#define MAX_DISPLAY_DIM 2048 // #define PRINT_SCREENINFO 1 // Enables printing of screen info to log @@ -77,6 +79,17 @@ static int gr_vt_fd = -1; static struct fb_var_screeninfo vi; static struct fb_fix_screeninfo fi; +static bool has_overlay = false; +static int leftSplit = 0; +static int rightSplit = 0; + +bool target_has_overlay(char *version); +int free_ion_mem(void); +int alloc_ion_mem(unsigned int size); +int allocate_overlay(int fd, GGLSurface gr_fb[]); +int free_overlay(int fd); +int overlay_display_frame(int fd, GGLubyte* data, size_t size); + #ifdef PRINT_SCREENINFO static void print_fb_var_screeninfo() { @@ -91,6 +104,62 @@ static void print_fb_var_screeninfo() } #endif +#ifdef MSM_BSP +int getLeftSplit(void) { + //Default even split for all displays with high res + int lSplit = vi.xres / 2; + + //Override if split published by driver + if (leftSplit) + lSplit = leftSplit; + + return lSplit; +} + +int getRightSplit(void) { + return rightSplit; +} + + +void setDisplaySplit(void) { + char split[64] = {0}; + FILE* fp = fopen("/sys/class/graphics/fb0/msm_fb_split", "r"); + if (fp) { + //Format "left right" space as delimiter + if(fread(split, sizeof(char), 64, fp)) { + leftSplit = atoi(split); + printf("Left Split=%d\n",leftSplit); + char *rght = strpbrk(split, " "); + if (rght) + rightSplit = atoi(rght + 1); + printf("Right Split=%d\n", rightSplit); + } + } else { + printf("Failed to open mdss_fb_split node\n"); + } + if (fp) + fclose(fp); +} + +bool isDisplaySplit(void) { + if (vi.xres > MAX_DISPLAY_DIM) + return true; + //check if right split is set by driver + if (getRightSplit()) + return true; + + return false; +} + +int getFbXres(void) { + return vi.xres; +} + +int getFbYres (void) { + return vi.yres; +} +#endif // MSM_BSP + static int get_framebuffer(GGLSurface *fb) { int fd; @@ -177,11 +246,23 @@ static int get_framebuffer(GGLSurface *fb) return -1; } - bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (bits == MAP_FAILED) { - perror("failed to mmap framebuffer"); - close(fd); - return -1; + has_overlay = target_has_overlay(fi.id); + +#ifdef MSM_BSP + if (isTargetMdp5()) + setDisplaySplit(); +#endif + + if (!has_overlay) { + printf("Not using qualcomm overlay, '%s'\n", fi.id); + bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (bits == MAP_FAILED) { + perror("failed to mmap framebuffer"); + close(fd); + return -1; + } + } else { + printf("Using qualcomm overlay\n"); } #ifdef RECOVERY_GRAPHICS_USE_LINELENGTH @@ -197,9 +278,11 @@ static int get_framebuffer(GGLSurface *fb) #else fb->stride = vi.xres_virtual; #endif - fb->data = bits; fb->format = PIXEL_FORMAT; - memset(fb->data, 0, vi.yres * fb->stride * PIXEL_SIZE); + if (!has_overlay) { + fb->data = bits; + memset(fb->data, 0, vi.yres * fb->stride * PIXEL_SIZE); + } fb++; @@ -220,7 +303,9 @@ static int get_framebuffer(GGLSurface *fb) fb->data = (void*) (((unsigned) bits) + vi.yres * fb->stride * PIXEL_SIZE); #endif fb->format = PIXEL_FORMAT; - memset(fb->data, 0, vi.yres * fb->stride * PIXEL_SIZE); + if (!has_overlay) { + memset(fb->data, 0, vi.yres * fb->stride * PIXEL_SIZE); + } #ifdef PRINT_SCREENINFO print_fb_var_screeninfo(); @@ -251,33 +336,36 @@ static void set_active_framebuffer(unsigned n) void gr_flip(void) { - GGLContext *gl = gr_context; + if (-EINVAL == overlay_display_frame(gr_fb_fd, gr_mem_surface.data, + (fi.line_length * vi.yres))) { + GGLContext *gl = gr_context; - /* swap front and back buffers */ - if (double_buffering) - gr_active_fb = (gr_active_fb + 1) & 1; + /* swap front and back buffers */ + if (double_buffering) + gr_active_fb = (gr_active_fb + 1) & 1; #ifdef BOARD_HAS_FLIPPED_SCREEN - /* flip buffer 180 degrees for devices with physicaly inverted screens */ - unsigned int i; - unsigned int j; - uint8_t tmp; - for (i = 0; i < ((vi.xres_virtual * vi.yres)/2); i++) { - for (j = 0; j < PIXEL_SIZE; j++) { - tmp = gr_mem_surface.data[i * PIXEL_SIZE + j]; - gr_mem_surface.data[i * PIXEL_SIZE + j] = gr_mem_surface.data[(vi.xres_virtual * vi.yres * PIXEL_SIZE) - ((i+1) * PIXEL_SIZE) + j]; - gr_mem_surface.data[(vi.xres_virtual * vi.yres * PIXEL_SIZE) - ((i+1) * PIXEL_SIZE) + j] = tmp; - } - } + /* flip buffer 180 degrees for devices with physicaly inverted screens */ + unsigned int i; + unsigned int j; + uint8_t tmp; + for (i = 0; i < ((vi.xres_virtual * vi.yres)/2); i++) { + for (j = 0; j < PIXEL_SIZE; j++) { + tmp = gr_mem_surface.data[i * PIXEL_SIZE + j]; + gr_mem_surface.data[i * PIXEL_SIZE + j] = gr_mem_surface.data[(vi.xres_virtual * vi.yres * PIXEL_SIZE) - ((i+1) * PIXEL_SIZE) + j]; + gr_mem_surface.data[(vi.xres_virtual * vi.yres * PIXEL_SIZE) - ((i+1) * PIXEL_SIZE) + j] = tmp; + } + } #endif - /* copy data from the in-memory surface to the buffer we're about - * to make active. */ - memcpy(gr_framebuffer[gr_active_fb].data, gr_mem_surface.data, - vi.xres_virtual * vi.yres * PIXEL_SIZE); + /* copy data from the in-memory surface to the buffer we're about + * to make active. */ + memcpy(gr_framebuffer[gr_active_fb].data, gr_mem_surface.data, + vi.xres_virtual * vi.yres * PIXEL_SIZE); - /* inform the display driver */ - set_active_framebuffer(gr_active_fb); + /* inform the display driver */ + set_active_framebuffer(gr_active_fb); + } } void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a) @@ -691,7 +779,8 @@ int gr_init(void) /* start with 0 as front (displayed) and 1 as back (drawing) */ gr_active_fb = 0; - set_active_framebuffer(0); + if (!has_overlay) + set_active_framebuffer(0); gl->colorBuffer(gl, &gr_mem_surface); gl->activeTexture(gl, 0); @@ -701,11 +790,17 @@ int gr_init(void) // gr_fb_blank(true); // gr_fb_blank(false); + if (!alloc_ion_mem(fi.line_length * vi.yres)) + allocate_overlay(gr_fb_fd, gr_framebuffer); + return 0; } void gr_exit(void) { + free_overlay(gr_fb_fd); + free_ion_mem(); + close(gr_fb_fd); gr_fb_fd = -1; @@ -734,10 +829,15 @@ gr_pixel *gr_fb_data(void) int gr_fb_blank(int blank) { int ret; + if (blank) + free_overlay(gr_fb_fd); ret = ioctl(gr_fb_fd, FBIOBLANK, blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK); if (ret < 0) perror("ioctl(): blank"); + + if (!blank) + allocate_overlay(gr_fb_fd, gr_framebuffer); return ret; } -- cgit v1.2.3