diff options
author | Ethan Yonker <dees_troy@teamw.in> | 2015-12-28 21:54:50 +0100 |
---|---|---|
committer | Ethan Yonker <dees_troy@teamw.in> | 2016-01-27 17:53:13 +0100 |
commit | fbb4353a247157d32208f8f133cd1ee42f4fbc49 (patch) | |
tree | 6f819fbdd21f2adef4f7ba4a5b4d02054cc02f29 /minuitwrp | |
parent | Adopted Storage support (diff) | |
download | android_bootable_recovery-fbb4353a247157d32208f8f133cd1ee42f4fbc49.tar android_bootable_recovery-fbb4353a247157d32208f8f133cd1ee42f4fbc49.tar.gz android_bootable_recovery-fbb4353a247157d32208f8f133cd1ee42f4fbc49.tar.bz2 android_bootable_recovery-fbb4353a247157d32208f8f133cd1ee42f4fbc49.tar.lz android_bootable_recovery-fbb4353a247157d32208f8f133cd1ee42f4fbc49.tar.xz android_bootable_recovery-fbb4353a247157d32208f8f133cd1ee42f4fbc49.tar.zst android_bootable_recovery-fbb4353a247157d32208f8f133cd1ee42f4fbc49.zip |
Diffstat (limited to 'minuitwrp')
-rw-r--r-- | minuitwrp/Android.mk | 44 | ||||
-rw-r--r-- | minuitwrp/events.cpp (renamed from minuitwrp/events.c) | 2 | ||||
-rw-r--r-- | minuitwrp/graphics.c | 754 | ||||
-rw-r--r-- | minuitwrp/graphics.cpp | 416 | ||||
-rw-r--r-- | minuitwrp/graphics.h | 44 | ||||
-rw-r--r-- | minuitwrp/graphics_adf.cpp | 285 | ||||
-rw-r--r-- | minuitwrp/graphics_drm.cpp | 492 | ||||
-rw-r--r-- | minuitwrp/graphics_fbdev.cpp | 281 | ||||
-rw-r--r-- | minuitwrp/graphics_overlay.cpp (renamed from minuitwrp/graphics_overlay.c) | 492 | ||||
-rw-r--r-- | minuitwrp/graphics_utils.cpp (renamed from minuitwrp/graphics_utils.c) | 9 | ||||
-rw-r--r-- | minuitwrp/minui.h | 24 | ||||
-rw-r--r-- | minuitwrp/resources.cpp (renamed from minuitwrp/resources.c) | 84 | ||||
-rw-r--r-- | minuitwrp/truetype.cpp (renamed from minuitwrp/truetype.c) | 91 |
13 files changed, 2005 insertions, 1013 deletions
diff --git a/minuitwrp/Android.mk b/minuitwrp/Android.mk index 01225c32e..39c61c40e 100644 --- a/minuitwrp/Android.mk +++ b/minuitwrp/Android.mk @@ -2,12 +2,20 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -LOCAL_SRC_FILES := events.c resources.c graphics_overlay.c graphics_utils.c truetype.c +LOCAL_SRC_FILES := \ + graphics.cpp \ + graphics_fbdev.cpp \ + resources.cpp \ + graphics_overlay.cpp \ + truetype.cpp \ + graphics_utils.cpp \ + events.cpp ifneq ($(TW_BOARD_CUSTOM_GRAPHICS),) - LOCAL_SRC_FILES += $(TW_BOARD_CUSTOM_GRAPHICS) -else - LOCAL_SRC_FILES += graphics.c + $(warning ****************************************************************************) + $(warning * TW_BOARD_CUSTOM_GRAPHICS support has been deprecated in TWRP. *) + $(warning ****************************************************************************) + $(error stopping) endif ifeq ($(TW_TARGET_USES_QCOM_BSP), true) @@ -17,25 +25,39 @@ ifeq ($(TW_TARGET_USES_QCOM_BSP), true) LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include else ifeq ($(TARGET_CUSTOM_KERNEL_HEADERS),) - LOCAL_C_INCLUDES += $(commands_recovery_local_path)/minuitwrp/include + LOCAL_C_INCLUDES += $(commands_recovery_local_path)/minui/include else LOCAL_C_INCLUDES += $(TARGET_CUSTOM_KERNEL_HEADERS) endif endif else - LOCAL_C_INCLUDES += $(commands_recovery_local_path)/minuitwrp/include + LOCAL_C_INCLUDES += $(commands_recovery_local_path)/minui/include + # The header files required for adf graphics can cause compile errors + # with adf graphics. + ifneq ($(wildcard system/core/adf/Android.mk),) + LOCAL_CFLAGS += -DHAS_ADF + LOCAL_SRC_FILES += graphics_adf.cpp + LOCAL_WHOLE_STATIC_LIBRARIES += libadf + endif endif ifeq ($(TW_NEW_ION_HEAP), true) LOCAL_CFLAGS += -DNEW_ION_HEAP endif +ifneq ($(wildcard external/libdrm/Android.mk),) + LOCAL_CFLAGS += -DHAS_DRM + LOCAL_SRC_FILES += graphics_drm.cpp + LOCAL_WHOLE_STATIC_LIBRARIES += libdrm +endif + LOCAL_C_INCLUDES += \ external/libpng \ external/zlib \ system/core/include \ external/jpeg \ - external/freetype/include + external/freetype/include \ + external/libcxx/include ifeq ($(RECOVERY_TOUCHSCREEN_SWAP_XY), true) LOCAL_CFLAGS += -DRECOVERY_TOUCHSCREEN_SWAP_XY @@ -76,6 +98,12 @@ ifeq ($(subst ",,$(TARGET_RECOVERY_PIXEL_FORMAT)),RGB_565) LOCAL_CFLAGS += -DRECOVERY_RGB_565 endif +ifneq ($(TARGET_RECOVERY_OVERSCAN_PERCENT),) + LOCAL_CFLAGS += -DOVERSCAN_PERCENT=$(TARGET_RECOVERY_OVERSCAN_PERCENT) +else + LOCAL_CFLAGS += -DOVERSCAN_PERCENT=0 +endif + ifeq ($(TARGET_RECOVERY_PIXEL_FORMAT),"RGBX_8888") LOCAL_CFLAGS += -DRECOVERY_RGBX endif @@ -120,6 +148,8 @@ ifeq ($(TW_DISABLE_TTF), true) $(error stopping) endif +LOCAL_CLANG := true + LOCAL_CFLAGS += -DTWRES=\"$(TWRES_PATH)\" LOCAL_SHARED_LIBRARIES += libft2 libz libc libcutils libjpeg libpng libutils LOCAL_STATIC_LIBRARIES += libpixelflinger_twrp diff --git a/minuitwrp/events.c b/minuitwrp/events.cpp index 4e10e72fd..d4ca0abbc 100644 --- a/minuitwrp/events.c +++ b/minuitwrp/events.cpp @@ -243,7 +243,7 @@ static int vk_init(struct ev *e) printf("EV: MT minX: %d maxX: %d minY: %d maxY: %d\n", e->mt_p.xi.minimum, e->mt_p.xi.maximum, e->mt_p.yi.minimum, e->mt_p.yi.maximum); #endif - e->vks = malloc(sizeof(*e->vks) * e->vk_count); + e->vks = (virtualkey *)malloc(sizeof(*e->vks) * e->vk_count); for (i = 0; i < e->vk_count; ++i) { char *token[6]; diff --git a/minuitwrp/graphics.c b/minuitwrp/graphics.c deleted file mode 100644 index fb86c1450..000000000 --- a/minuitwrp/graphics.c +++ /dev/null @@ -1,754 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdbool.h> -#include <stdlib.h> -#include <unistd.h> - -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <string.h> - -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <sys/types.h> - -#include <linux/fb.h> -#include <linux/kd.h> - -#include <pixelflinger/pixelflinger.h> - -#include "minui.h" -#include "../gui/placement.h" - -#ifdef RECOVERY_BGRA -#define PIXEL_FORMAT GGL_PIXEL_FORMAT_BGRA_8888 -#define PIXEL_SIZE 4 -#endif -#ifdef RECOVERY_RGBA -#define PIXEL_FORMAT GGL_PIXEL_FORMAT_RGBA_8888 -#define PIXEL_SIZE 4 -#endif -#ifdef RECOVERY_RGBX -#define PIXEL_FORMAT GGL_PIXEL_FORMAT_RGBX_8888 -#define PIXEL_SIZE 4 -#endif -#ifndef PIXEL_FORMAT -#define PIXEL_FORMAT GGL_PIXEL_FORMAT_RGB_565 -#define PIXEL_SIZE 2 -#endif - -#define NUM_BUFFERS 2 -#define MAX_DISPLAY_DIM 2048 - -// #define PRINT_SCREENINFO 1 // Enables printing of screen info to log - -typedef struct { - int type; - GGLSurface texture; - unsigned offset[97]; - unsigned cheight; - unsigned ascent; -} GRFont; - -static GRFont *gr_font = 0; -static GGLContext *gr_context = 0; -static GGLSurface gr_font_texture; -static GGLSurface gr_framebuffer[NUM_BUFFERS]; -GGLSurface gr_mem_surface; -static unsigned gr_active_fb = 0; -static unsigned double_buffering = 0; -static int gr_is_curr_clr_opaque = 0; - -static int gr_fb_fd = -1; -static int gr_vt_fd = -1; - -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() -{ - printf("vi.xres: %d\n", vi.xres); - printf("vi.yres: %d\n", vi.yres); - printf("vi.xres_virtual: %d\n", vi.xres_virtual); - printf("vi.yres_virtual: %d\n", vi.yres_virtual); - printf("vi.xoffset: %d\n", vi.xoffset); - printf("vi.yoffset: %d\n", vi.yoffset); - printf("vi.bits_per_pixel: %d\n", vi.bits_per_pixel); - printf("vi.grayscale: %d\n", vi.grayscale); -} -#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, index = 0; - void *bits; - - fd = open("/dev/graphics/fb0", O_RDWR); - - while (fd < 0 && index < 30) { - usleep(1000); - fd = open("/dev/graphics/fb0", O_RDWR); - index++; - } - if (fd < 0) { - perror("cannot open fb0\n"); - return -1; - } - - if (ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) { - perror("failed to get fb0 info"); - close(fd); - return -1; - } - - fprintf(stderr, "Pixel format: %dx%d @ %dbpp\n", vi.xres, vi.yres, vi.bits_per_pixel); - - vi.bits_per_pixel = PIXEL_SIZE * 8; - if (PIXEL_FORMAT == GGL_PIXEL_FORMAT_BGRA_8888) { - fprintf(stderr, "Pixel format: BGRA_8888\n"); - if (PIXEL_SIZE != 4) fprintf(stderr, "E: Pixel Size mismatch!\n"); - vi.red.offset = 8; - vi.red.length = 8; - vi.green.offset = 16; - vi.green.length = 8; - vi.blue.offset = 24; - vi.blue.length = 8; - vi.transp.offset = 0; - vi.transp.length = 8; - } else if (PIXEL_FORMAT == GGL_PIXEL_FORMAT_RGBA_8888) { - fprintf(stderr, "Pixel format: RGBA_8888\n"); - if (PIXEL_SIZE != 4) fprintf(stderr, "E: Pixel Size mismatch!\n"); - vi.red.offset = 0; - vi.red.length = 8; - vi.green.offset = 8; - vi.green.length = 8; - vi.blue.offset = 16; - vi.blue.length = 8; - vi.transp.offset = 24; - vi.transp.length = 8; - } else if (PIXEL_FORMAT == GGL_PIXEL_FORMAT_RGBX_8888) { - fprintf(stderr, "Pixel format: RGBX_8888\n"); - if (PIXEL_SIZE != 4) fprintf(stderr, "E: Pixel Size mismatch!\n"); - vi.red.offset = 24; - vi.red.length = 8; - vi.green.offset = 16; - vi.green.length = 8; - vi.blue.offset = 8; - vi.blue.length = 8; - vi.transp.offset = 0; - vi.transp.length = 8; - } else if (PIXEL_FORMAT == GGL_PIXEL_FORMAT_RGB_565) { -#ifdef RECOVERY_RGB_565 - fprintf(stderr, "Pixel format: RGB_565\n"); - vi.blue.offset = 0; - vi.green.offset = 5; - vi.red.offset = 11; -#else - fprintf(stderr, "Pixel format: BGR_565\n"); - vi.blue.offset = 11; - vi.green.offset = 5; - vi.red.offset = 0; -#endif - if (PIXEL_SIZE != 2) fprintf(stderr, "E: Pixel Size mismatch!\n"); - vi.blue.length = 5; - vi.green.length = 6; - vi.red.length = 5; - vi.blue.msb_right = 0; - vi.green.msb_right = 0; - vi.red.msb_right = 0; - vi.transp.offset = 0; - vi.transp.length = 0; - } - else - { - perror("unknown pixel format"); - close(fd); - return -1; - } - - vi.vmode = FB_VMODE_NONINTERLACED; - vi.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; - - if (ioctl(fd, FBIOPUT_VSCREENINFO, &vi) < 0) { - perror("failed to put fb0 info"); - close(fd); - return -1; - } - - if (ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) { - perror("failed to get fb0 info"); - close(fd); - return -1; - } - -#ifdef MSM_BSP - has_overlay = target_has_overlay(fi.id); - - if (isTargetMdp5()) - setDisplaySplit(); -#else - has_overlay = false; -#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 - vi.xres_virtual = fi.line_length / PIXEL_SIZE; -#endif - - fb->version = sizeof(*fb); - fb->width = vi.xres; - fb->height = vi.yres; -#ifdef BOARD_HAS_JANKY_BACKBUFFER - printf("setting JANKY BACKBUFFER\n"); - fb->stride = fi.line_length/2; -#else - fb->stride = vi.xres_virtual; -#endif - fb->format = PIXEL_FORMAT; - if (!has_overlay) { - fb->data = bits; - memset(fb->data, 0, vi.yres * fb->stride * PIXEL_SIZE); - } - - fb++; - -#ifndef TW_DISABLE_DOUBLE_BUFFERING - /* check if we can use double buffering */ - if (vi.yres * fi.line_length * 2 > fi.smem_len) -#else - printf("TW_DISABLE_DOUBLE_BUFFERING := true\n"); -#endif - return fd; - - double_buffering = 1; - - fb->version = sizeof(*fb); - fb->width = vi.xres; - fb->height = vi.yres; -#ifdef BOARD_HAS_JANKY_BACKBUFFER - fb->stride = fi.line_length/2; - fb->data = (GGLubyte*) (((unsigned long) bits) + vi.yres * fi.line_length); -#else - fb->stride = vi.xres_virtual; - fb->data = (GGLubyte*) (((unsigned long) bits) + vi.yres * fb->stride * PIXEL_SIZE); -#endif - fb->format = PIXEL_FORMAT; - if (!has_overlay) { - memset(fb->data, 0, vi.yres * fb->stride * PIXEL_SIZE); - } - -#ifdef PRINT_SCREENINFO - print_fb_var_screeninfo(); -#endif - - return fd; -} - -static void get_memory_surface(GGLSurface* ms) { - ms->version = sizeof(*ms); - ms->width = vi.xres; - ms->height = vi.yres; - ms->stride = vi.xres_virtual; - ms->data = malloc(vi.xres_virtual * vi.yres * PIXEL_SIZE); - ms->format = PIXEL_FORMAT; -} - -static void set_active_framebuffer(unsigned n) -{ - if (n > 1 || !double_buffering) return; - vi.yres_virtual = vi.yres * NUM_BUFFERS; - vi.yoffset = n * vi.yres; -// vi.bits_per_pixel = PIXEL_SIZE * 8; - if (ioctl(gr_fb_fd, FBIOPUT_VSCREENINFO, &vi) < 0) { - perror("active fb swap failed"); - } -} - -void gr_flip(void) -{ - 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; - -#ifdef BOARD_HAS_FLIPPED_SCREEN - /* flip buffer 180 degrees for devices with physicaly inverted screens */ - unsigned int i; - unsigned int j; - for (i = 0; i < vi.yres; i++) { - for (j = 0; j < vi.xres; j++) { - memcpy(gr_framebuffer[gr_active_fb].data + (i * vi.xres_virtual + j) * PIXEL_SIZE, - gr_mem_surface.data + ((vi.yres - i - 1) * vi.xres_virtual + vi.xres - j - 1) * PIXEL_SIZE, PIXEL_SIZE); - } - } -#else - /* 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); -#endif - - /* 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) -{ - GGLContext *gl = gr_context; - GGLint color[4]; - color[0] = ((r << 8) | r) + 1; - color[1] = ((g << 8) | g) + 1; - color[2] = ((b << 8) | b) + 1; - color[3] = ((a << 8) | a) + 1; - gl->color4xv(gl, color); - - gr_is_curr_clr_opaque = (a == 255); -} - -int gr_measureEx(const char *s, void* font) -{ - GRFont* fnt = (GRFont*) font; - - if (!fnt) - return 0; - - return gr_ttf_measureEx(s, font); -} - -int gr_maxExW(const char *s, void* font, int max_width) -{ - GRFont* fnt = (GRFont*) font; - - if (!fnt) - return 0; - - return gr_ttf_maxExW(s, font, max_width); -} - -int gr_textEx(int x, int y, const char *s, void* pFont) -{ - GGLContext *gl = gr_context; - GRFont *font = (GRFont*) pFont; - - if (!font) - return 0; - - return gr_ttf_textExWH(gl, x, y, s, pFont, -1, -1); -} - -int gr_textEx_scaleW(int x, int y, const char *s, void* pFont, int max_width, int placement, int scale) -{ - GGLContext *gl = gr_context; - void* vfont = pFont; - GRFont *font = (GRFont*) pFont; - unsigned off; - unsigned cwidth; - int y_scale = 0, measured_width, measured_height, ret, new_height; - - if (!s || strlen(s) == 0 || !font) - return 0; - - measured_height = gr_ttf_getMaxFontHeight(font); - - if (scale) { - measured_width = gr_ttf_measureEx(s, vfont); - if (measured_width > max_width) { - // Adjust font size down until the text fits - void *new_font = gr_ttf_scaleFont(vfont, max_width, measured_width); - if (!new_font) { - printf("gr_textEx_scaleW new_font is NULL\n"); - return 0; - } - measured_width = gr_ttf_measureEx(s, new_font); - // These next 2 lines adjust the y point based on the new font's height - new_height = gr_ttf_getMaxFontHeight(new_font); - y_scale = (measured_height - new_height) / 2; - vfont = new_font; - } - } else - measured_width = gr_ttf_measureEx(s, vfont); - - int x_adj = measured_width; - if (measured_width > max_width) - x_adj = max_width; - - if (placement != TOP_LEFT && placement != BOTTOM_LEFT && placement != TEXT_ONLY_RIGHT) { - if (placement == CENTER || placement == CENTER_X_ONLY) - x -= (x_adj / 2); - else - x -= x_adj; - } - - if (placement != TOP_LEFT && placement != TOP_RIGHT) { - if (placement == CENTER || placement == TEXT_ONLY_RIGHT) - y -= (measured_height / 2); - else if (placement == BOTTOM_LEFT || placement == BOTTOM_RIGHT) - y -= measured_height; - } - return gr_ttf_textExWH(gl, x, y + y_scale, s, vfont, measured_width + x, -1); -} - -int gr_textExW(int x, int y, const char *s, void* pFont, int max_width) -{ - GGLContext *gl = gr_context; - GRFont *font = (GRFont*) pFont; - - if (!font) - return 0; - - return gr_ttf_textExWH(gl, x, y, s, pFont, max_width, -1); -} - -int gr_textExWH(int x, int y, const char *s, void* pFont, int max_width, int max_height) -{ - GGLContext *gl = gr_context; - GRFont *font = (GRFont*) pFont; - - if (!font) - return 0; - - return gr_ttf_textExWH(gl, x, y, s, pFont, max_width, max_height); -} - -void gr_clip(int x, int y, int w, int h) -{ - GGLContext *gl = gr_context; - gl->scissor(gl, x, y, w, h); - gl->enable(gl, GGL_SCISSOR_TEST); -} - -void gr_noclip() -{ - GGLContext *gl = gr_context; - gl->scissor(gl, 0, 0, gr_fb_width(), gr_fb_height()); - gl->disable(gl, GGL_SCISSOR_TEST); -} - -void gr_fill(int x, int y, int w, int h) -{ - GGLContext *gl = gr_context; - - if(gr_is_curr_clr_opaque) - gl->disable(gl, GGL_BLEND); - - gl->recti(gl, x, y, x + w, y + h); - - if(gr_is_curr_clr_opaque) - gl->enable(gl, GGL_BLEND); -} - -void gr_line(int x0, int y0, int x1, int y1, int width) -{ - GGLContext *gl = gr_context; - - if(gr_is_curr_clr_opaque) - gl->disable(gl, GGL_BLEND); - - const int coords0[2] = { x0 << 4, y0 << 4 }; - const int coords1[2] = { x1 << 4, y1 << 4 }; - gl->linex(gl, coords0, coords1, width << 4); - - if(gr_is_curr_clr_opaque) - gl->enable(gl, GGL_BLEND); -} - -gr_surface gr_render_circle(int radius, unsigned char r, unsigned char g, unsigned char b, unsigned char a) -{ - int rx, ry; - GGLSurface *surface; - const int diameter = radius*2 + 1; - const int radius_check = radius*radius + radius*0.8; - const uint32_t px = (a << 24) | (b << 16) | (g << 8) | r; - uint32_t *data; - - surface = malloc(sizeof(GGLSurface)); - memset(surface, 0, sizeof(GGLSurface)); - - data = malloc(diameter * diameter * 4); - memset(data, 0, diameter * diameter * 4); - - surface->version = sizeof(surface); - surface->width = diameter; - surface->height = diameter; - surface->stride = diameter; - surface->data = (GGLubyte*)data; - surface->format = GGL_PIXEL_FORMAT_RGBA_8888; - - for(ry = -radius; ry <= radius; ++ry) - for(rx = -radius; rx <= radius; ++rx) - if(rx*rx+ry*ry <= radius_check) - *(data + diameter*(radius + ry) + (radius+rx)) = px; - - return surface; -} - -void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy) { - if (gr_context == NULL) { - return; - } - - GGLContext *gl = gr_context; - GGLSurface *surface = (GGLSurface*)source; - - if(surface->format == GGL_PIXEL_FORMAT_RGBX_8888) - gl->disable(gl, GGL_BLEND); - - gl->bindTexture(gl, surface); - gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE); - gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); - gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); - gl->enable(gl, GGL_TEXTURE_2D); - gl->texCoord2i(gl, sx - dx, sy - dy); - gl->recti(gl, dx, dy, dx + w, dy + h); - gl->disable(gl, GGL_TEXTURE_2D); - - if(surface->format == GGL_PIXEL_FORMAT_RGBX_8888) - gl->enable(gl, GGL_BLEND); -} - -unsigned int gr_get_width(gr_surface surface) { - if (surface == NULL) { - return 0; - } - return ((GGLSurface*) surface)->width; -} - -unsigned int gr_get_height(gr_surface surface) { - if (surface == NULL) { - return 0; - } - return ((GGLSurface*) surface)->height; -} - -int gr_getMaxFontHeight(void *font) -{ - GRFont *fnt = (GRFont*) font; - - if (!fnt) - return -1; - - return gr_ttf_getMaxFontHeight(font); -} - -int gr_init(void) -{ - gglInit(&gr_context); - GGLContext *gl = gr_context; - - gr_vt_fd = open("/dev/tty0", O_RDWR | O_SYNC); - if (gr_vt_fd < 0) { - // This is non-fatal; post-Cupcake kernels don't have tty0. - } else if (ioctl(gr_vt_fd, KDSETMODE, (void*) KD_GRAPHICS)) { - // However, if we do open tty0, we expect the ioctl to work. - perror("failed KDSETMODE to KD_GRAPHICS on tty0"); - gr_exit(); - return -1; - } - - gr_fb_fd = get_framebuffer(gr_framebuffer); - if (gr_fb_fd < 0) { - perror("Unable to get framebuffer.\n"); - gr_exit(); - return -1; - } - - get_memory_surface(&gr_mem_surface); - - fprintf(stderr, "framebuffer: fd %d (%d x %d)\n", - gr_fb_fd, gr_framebuffer[0].width, gr_framebuffer[0].height); - - /* start with 0 as front (displayed) and 1 as back (drawing) */ - gr_active_fb = 0; - if (!has_overlay) - set_active_framebuffer(0); - gl->colorBuffer(gl, &gr_mem_surface); - - gl->activeTexture(gl, 0); - gl->enable(gl, GGL_BLEND); - gl->blendFunc(gl, GGL_SRC_ALPHA, GGL_ONE_MINUS_SRC_ALPHA); - -#ifdef TW_SCREEN_BLANK_ON_BOOT - printf("TW_SCREEN_BLANK_ON_BOOT := true\n"); - gr_fb_blank(true); - gr_fb_blank(false); -#endif - - 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; - - free(gr_mem_surface.data); - - ioctl(gr_vt_fd, KDSETMODE, (void*) KD_TEXT); - close(gr_vt_fd); - gr_vt_fd = -1; -} - -int gr_fb_width(void) -{ - return gr_framebuffer[0].width; -} - -int gr_fb_height(void) -{ - return gr_framebuffer[0].height; -} - -gr_pixel *gr_fb_data(void) -{ - return (unsigned short *) gr_mem_surface.data; -} - -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; -} - -int gr_get_surface(gr_surface* surface) -{ - GGLSurface* ms = malloc(sizeof(GGLSurface)); - if (!ms) return -1; - - // Allocate the data - get_memory_surface(ms); - - // Now, copy the data - memcpy(ms->data, gr_mem_surface.data, vi.xres * vi.yres * vi.bits_per_pixel / 8); - - *surface = (gr_surface*) ms; - return 0; -} - -int gr_free_surface(gr_surface surface) -{ - if (!surface) - return -1; - - GGLSurface* ms = (GGLSurface*) surface; - free(ms->data); - free(ms); - return 0; -} - -void gr_write_frame_to_file(int fd) -{ - write(fd, gr_mem_surface.data, vi.xres * vi.yres * vi.bits_per_pixel / 8); -} diff --git a/minuitwrp/graphics.cpp b/minuitwrp/graphics.cpp new file mode 100644 index 000000000..47325d01e --- /dev/null +++ b/minuitwrp/graphics.cpp @@ -0,0 +1,416 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <fcntl.h> +#include <stdio.h> + +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/types.h> + +#include <linux/fb.h> +#include <linux/kd.h> + +#include <time.h> + +#include <pixelflinger/pixelflinger.h> +#include "../gui/placement.h" +#include "minui.h" +#include "graphics.h" + +struct GRFont { + GRSurface* texture; + int cwidth; + int cheight; +}; + +static GRFont* gr_font = NULL; +static minui_backend* gr_backend = NULL; + +static int overscan_percent = OVERSCAN_PERCENT; +static int overscan_offset_x = 0; +static int overscan_offset_y = 0; + +static unsigned char gr_current_r = 255; +static unsigned char gr_current_g = 255; +static unsigned char gr_current_b = 255; +static unsigned char gr_current_a = 255; +static unsigned char rgb_555[2]; +static unsigned char gr_current_r5 = 31; +static unsigned char gr_current_g5 = 63; +static unsigned char gr_current_b5 = 31; + +GRSurface* gr_draw = NULL; + +static GGLContext *gr_context = 0; +GGLSurface gr_mem_surface; +static int gr_is_curr_clr_opaque = 0; + +static bool outside(int x, int y) +{ + return x < 0 || x >= gr_draw->width || y < 0 || y >= gr_draw->height; +} + +int gr_textEx_scaleW(int x, int y, const char *s, void* pFont, int max_width, int placement, int scale) +{ + GGLContext *gl = gr_context; + void* vfont = pFont; + GRFont *font = (GRFont*) pFont; + unsigned off; + unsigned cwidth; + int y_scale = 0, measured_width, measured_height, ret, new_height; + + if (!s || strlen(s) == 0 || !font) + return 0; + + measured_height = gr_ttf_getMaxFontHeight(font); + + if (scale) { + measured_width = gr_ttf_measureEx(s, vfont); + if (measured_width > max_width) { + // Adjust font size down until the text fits + void *new_font = gr_ttf_scaleFont(vfont, max_width, measured_width); + if (!new_font) { + printf("gr_textEx_scaleW new_font is NULL\n"); + return 0; + } + measured_width = gr_ttf_measureEx(s, new_font); + // These next 2 lines adjust the y point based on the new font's height + new_height = gr_ttf_getMaxFontHeight(new_font); + y_scale = (measured_height - new_height) / 2; + vfont = new_font; + } + } else + measured_width = gr_ttf_measureEx(s, vfont); + + int x_adj = measured_width; + if (measured_width > max_width) + x_adj = max_width; + + if (placement != TOP_LEFT && placement != BOTTOM_LEFT && placement != TEXT_ONLY_RIGHT) { + if (placement == CENTER || placement == CENTER_X_ONLY) + x -= (x_adj / 2); + else + x -= x_adj; + } + + if (placement != TOP_LEFT && placement != TOP_RIGHT) { + if (placement == CENTER || placement == TEXT_ONLY_RIGHT) + y -= (measured_height / 2); + else if (placement == BOTTOM_LEFT || placement == BOTTOM_RIGHT) + y -= measured_height; + } + return gr_ttf_textExWH(gl, x, y + y_scale, s, vfont, measured_width + x, -1); +} + +void gr_clip(int x, int y, int w, int h) +{ + GGLContext *gl = gr_context; + gl->scissor(gl, x, y, w, h); + gl->enable(gl, GGL_SCISSOR_TEST); +} + +void gr_noclip() +{ + GGLContext *gl = gr_context; + gl->scissor(gl, 0, 0, gr_fb_width(), gr_fb_height()); + gl->disable(gl, GGL_SCISSOR_TEST); +} + +void gr_line(int x0, int y0, int x1, int y1, int width) +{ + GGLContext *gl = gr_context; + + if(gr_is_curr_clr_opaque) + gl->disable(gl, GGL_BLEND); + + const int coords0[2] = { x0 << 4, y0 << 4 }; + const int coords1[2] = { x1 << 4, y1 << 4 }; + gl->linex(gl, coords0, coords1, width << 4); + + if(gr_is_curr_clr_opaque) + gl->enable(gl, GGL_BLEND); +} + +gr_surface gr_render_circle(int radius, unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + int rx, ry; + GGLSurface *surface; + const int diameter = radius*2 + 1; + const int radius_check = radius*radius + radius*0.8; + const uint32_t px = (a << 24) | (b << 16) | (g << 8) | r; + uint32_t *data; + + surface = (GGLSurface *)malloc(sizeof(GGLSurface)); + memset(surface, 0, sizeof(GGLSurface)); + + data = (uint32_t *)malloc(diameter * diameter * 4); + memset(data, 0, diameter * diameter * 4); + + surface->version = sizeof(surface); + surface->width = diameter; + surface->height = diameter; + surface->stride = diameter; + surface->data = (GGLubyte*)data; + surface->format = GGL_PIXEL_FORMAT_RGBA_8888; + + for(ry = -radius; ry <= radius; ++ry) + for(rx = -radius; rx <= radius; ++rx) + if(rx*rx+ry*ry <= radius_check) + *(data + diameter*(radius + ry) + (radius+rx)) = px; + + return (gr_surface)surface; +} + +void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + GGLContext *gl = gr_context; + GGLint color[4]; +#if defined(RECOVERY_ABGR) || defined(RECOVERY_BGRA) + color[0] = ((b << 8) | r) + 1; + color[1] = ((g << 8) | g) + 1; + color[2] = ((r << 8) | b) + 1; + color[3] = ((a << 8) | a) + 1; +#else + color[0] = ((r << 8) | r) + 1; + color[1] = ((g << 8) | g) + 1; + color[2] = ((b << 8) | b) + 1; + color[3] = ((a << 8) | a) + 1; +#endif + gl->color4xv(gl, color); + + gr_is_curr_clr_opaque = (a == 255); +} + +void gr_clear() +{ + if (gr_draw->pixel_bytes == 2) { + gr_fill(0, 0, gr_fb_width(), gr_fb_height()); + return; + } + + // This code only works on 32bpp devices + if (gr_current_r == gr_current_g && gr_current_r == gr_current_b) { + memset(gr_draw->data, gr_current_r, gr_draw->height * gr_draw->row_bytes); + } else { + unsigned char* px = gr_draw->data; + for (int y = 0; y < gr_draw->height; ++y) { + for (int x = 0; x < gr_draw->width; ++x) { + *px++ = gr_current_r; + *px++ = gr_current_g; + *px++ = gr_current_b; + px++; + } + px += gr_draw->row_bytes - (gr_draw->width * gr_draw->pixel_bytes); + } + } +} + +void gr_fill(int x, int y, int w, int h) +{ + GGLContext *gl = gr_context; + + if(gr_is_curr_clr_opaque) + gl->disable(gl, GGL_BLEND); + + gl->recti(gl, x, y, x + w, y + h); + + if(gr_is_curr_clr_opaque) + gl->enable(gl, GGL_BLEND); +} + +void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy) { + if (gr_context == NULL) { + return; + } + + GGLContext *gl = gr_context; + GGLSurface *surface = (GGLSurface*)source; + + if(surface->format == GGL_PIXEL_FORMAT_RGBX_8888) + gl->disable(gl, GGL_BLEND); + + gl->bindTexture(gl, surface); + gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE); + gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); + gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); + gl->enable(gl, GGL_TEXTURE_2D); + gl->texCoord2i(gl, sx - dx, sy - dy); + gl->recti(gl, dx, dy, dx + w, dy + h); + gl->disable(gl, GGL_TEXTURE_2D); + + if(surface->format == GGL_PIXEL_FORMAT_RGBX_8888) + gl->enable(gl, GGL_BLEND); +} + +unsigned int gr_get_width(gr_surface surface) { + if (surface == NULL) { + return 0; + } + return ((GGLSurface*) surface)->width; +} + +unsigned int gr_get_height(gr_surface surface) { + if (surface == NULL) { + return 0; + } + return ((GGLSurface*) surface)->height; +} + +void gr_flip() { + gr_draw = gr_backend->flip(gr_backend); + // On double buffered back ends, when we flip, we need to tell + // pixel flinger to draw to the other buffer + gr_mem_surface.data = (GGLubyte*)gr_draw->data; + gr_context->colorBuffer(gr_context, &gr_mem_surface); +} + +static void get_memory_surface(GGLSurface* ms) { + ms->version = sizeof(*ms); + ms->width = gr_draw->width; + ms->height = gr_draw->height; + ms->stride = gr_draw->row_bytes / gr_draw->pixel_bytes; + ms->data = (GGLubyte*)gr_draw->data; + ms->format = gr_draw->format; +} + +int gr_init(void) +{ + gr_draw = NULL; + + gr_backend = open_overlay(); + if (gr_backend) { + gr_draw = gr_backend->init(gr_backend); + if (!gr_draw) { + gr_backend->exit(gr_backend); + } else + printf("Using overlay graphics.\n"); + } + +#ifdef HAS_ADF + if (!gr_draw) { + gr_backend = open_adf(); + if (gr_backend) { + gr_draw = gr_backend->init(gr_backend); + if (!gr_draw) { + gr_backend->exit(gr_backend); + } else + printf("Using adf graphics.\n"); + } + } +#else +#ifdef MSM_BSP + printf("Skipping adf graphics because TW_TARGET_USES_QCOM_BSP := true\n"); +#else + printf("Skipping adf graphics -- not present in build tree\n"); +#endif +#endif + +#ifdef HAS_DRM + if (!gr_draw) { + gr_backend = open_drm(); + gr_draw = gr_backend->init(gr_backend); + if (gr_draw) + printf("Using drm graphics.\n"); + } +#else + printf("Skipping drm graphics -- not present in build tree\n"); +#endif + + if (!gr_draw) { + gr_backend = open_fbdev(); + gr_draw = gr_backend->init(gr_backend); + if (gr_draw == NULL) { + return -1; + } else + printf("Using fbdev graphics.\n"); + } + + overscan_offset_x = gr_draw->width * overscan_percent / 100; + overscan_offset_y = gr_draw->height * overscan_percent / 100; + + // Set up pixelflinger + get_memory_surface(&gr_mem_surface); + gglInit(&gr_context); + GGLContext *gl = gr_context; + gl->colorBuffer(gl, &gr_mem_surface); + + gl->activeTexture(gl, 0); + gl->enable(gl, GGL_BLEND); + gl->blendFunc(gl, GGL_SRC_ALPHA, GGL_ONE_MINUS_SRC_ALPHA); + + gr_flip(); + gr_flip(); + + return 0; +} + +void gr_exit(void) +{ + gr_backend->exit(gr_backend); +} + +int gr_fb_width(void) +{ + return gr_draw->width - 2*overscan_offset_x; +} + +int gr_fb_height(void) +{ + return gr_draw->height - 2*overscan_offset_y; +} + +void gr_fb_blank(bool blank) +{ + gr_backend->blank(gr_backend, blank); +} + +int gr_get_surface(gr_surface* surface) +{ + GGLSurface* ms = (GGLSurface*)malloc(sizeof(GGLSurface)); + if (!ms) return -1; + + // Allocate the data + get_memory_surface(ms); + ms->data = (GGLubyte*)malloc(ms->stride * ms->height * gr_draw->pixel_bytes); + + // Now, copy the data + memcpy(ms->data, gr_mem_surface.data, gr_draw->width * gr_draw->height * gr_draw->pixel_bytes / 8); + + *surface = (gr_surface*) ms; + return 0; +} + +int gr_free_surface(gr_surface surface) +{ + if (!surface) + return -1; + + GGLSurface* ms = (GGLSurface*) surface; + free(ms->data); + free(ms); + return 0; +} + +void gr_write_frame_to_file(int fd) +{ + write(fd, gr_mem_surface.data, gr_draw->width * gr_draw->height * gr_draw->pixel_bytes / 8); +} diff --git a/minuitwrp/graphics.h b/minuitwrp/graphics.h new file mode 100644 index 000000000..a4115fd50 --- /dev/null +++ b/minuitwrp/graphics.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _GRAPHICS_H_ +#define _GRAPHICS_H_ + +#include "minui.h" + +// TODO: lose the function pointers. +struct minui_backend { + // Initializes the backend and returns a GRSurface* to draw into. + GRSurface* (*init)(minui_backend*); + + // Causes the current drawing surface (returned by the most recent + // call to flip() or init()) to be displayed, and returns a new + // drawing surface. + GRSurface* (*flip)(minui_backend*); + + // Blank (or unblank) the screen. + void (*blank)(minui_backend*, bool); + + // Device cleanup when drawing is done. + void (*exit)(minui_backend*); +}; + +minui_backend* open_fbdev(); +minui_backend* open_adf(); +minui_backend* open_drm(); +minui_backend* open_overlay(); + +#endif diff --git a/minuitwrp/graphics_adf.cpp b/minuitwrp/graphics_adf.cpp new file mode 100644 index 000000000..b71bed2a8 --- /dev/null +++ b/minuitwrp/graphics_adf.cpp @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sys/cdefs.h> +#include <sys/mman.h> + +#include <adf/adf.h> + +#include "graphics.h" +#include <pixelflinger/pixelflinger.h> + +struct adf_surface_pdata { + GRSurface base; + int fd; + __u32 offset; + __u32 pitch; + unsigned char* adf_data; +}; + +struct adf_pdata { + minui_backend base; + int intf_fd; + adf_id_t eng_id; + __u32 format; + + unsigned int current_surface; + unsigned int n_surfaces; + adf_surface_pdata surfaces[2]; +}; + +static GRSurface* adf_flip(minui_backend *backend); +static void adf_blank(minui_backend *backend, bool blank); + +static int adf_surface_init(adf_pdata *pdata, drm_mode_modeinfo *mode, adf_surface_pdata *surf) { + memset(surf, 0, sizeof(*surf)); + + surf->fd = adf_interface_simple_buffer_alloc(pdata->intf_fd, mode->hdisplay, + mode->vdisplay, pdata->format, &surf->offset, &surf->pitch); + if (surf->fd < 0) + return surf->fd; + + surf->base.width = mode->hdisplay; + surf->base.height = mode->vdisplay; + surf->base.row_bytes = surf->pitch; + surf->base.pixel_bytes = (pdata->format == DRM_FORMAT_RGB565) ? 2 : 4; + if (pdata->format == DRM_FORMAT_ABGR8888) + surf->base.format = GGL_PIXEL_FORMAT_BGRA_8888; + else if (pdata->format == DRM_FORMAT_BGRA8888) + surf->base.format = GGL_PIXEL_FORMAT_BGRA_8888; + else if (pdata->format == DRM_FORMAT_RGBA8888) + surf->base.format = GGL_PIXEL_FORMAT_RGBA_8888; + else if (pdata->format == DRM_FORMAT_RGBX8888) + surf->base.format = GGL_PIXEL_FORMAT_RGBX_8888; + else + surf->base.format = GGL_PIXEL_FORMAT_RGB_565; + + surf->adf_data = reinterpret_cast<uint8_t*>(mmap(NULL, + surf->pitch * surf->base.height, PROT_WRITE, + MAP_SHARED, surf->fd, surf->offset)); + if (surf->adf_data == MAP_FAILED) { + close(surf->fd); + return -errno; + } + + return 0; +} + +static int adf_interface_init(adf_pdata *pdata) +{ + adf_interface_data intf_data; + int ret = 0; + int err; + unsigned char* framebuffer_data = NULL; + + err = adf_get_interface_data(pdata->intf_fd, &intf_data); + if (err < 0) + return err; + + err = adf_surface_init(pdata, &intf_data.current_mode, &pdata->surfaces[0]); + if (err < 0) { + fprintf(stderr, "allocating surface 0 failed: %s\n", strerror(-err)); + ret = err; + goto done; + } + + /* Allocate a single buffer for drawing. graphics.cpp will draw to + * this buffer which will later be copied to the mmapped adf buffer. + * Using a regular memory buffer improves performance by about 10x. */ + framebuffer_data = (unsigned char*)calloc(pdata->surfaces[0].pitch * pdata->surfaces[0].base.height, 1); + if (framebuffer_data == NULL) { + printf("failed to calloc surface data\n"); + close(pdata->surfaces[0].fd); + munmap(pdata->surfaces[0].adf_data, pdata->surfaces[0].pitch * pdata->surfaces[0].base.height); + ret = -1; + goto done; + } + pdata->surfaces[0].base.data = framebuffer_data; + + err = adf_surface_init(pdata, &intf_data.current_mode, + &pdata->surfaces[1]); + if (err < 0) { + fprintf(stderr, "allocating surface 1 failed: %s\n", strerror(-err)); + memset(&pdata->surfaces[1], 0, sizeof(pdata->surfaces[1])); + pdata->n_surfaces = 1; + } else { + pdata->n_surfaces = 2; + pdata->surfaces[1].base.data = framebuffer_data; + } + +done: + adf_free_interface_data(&intf_data); + return ret; +} + +static int adf_device_init(adf_pdata *pdata, adf_device *dev) +{ + adf_id_t intf_id; + int intf_fd; + int err; + + err = adf_find_simple_post_configuration(dev, &pdata->format, 1, &intf_id, + &pdata->eng_id); + if (err < 0) + return err; + + err = adf_device_attach(dev, pdata->eng_id, intf_id); + if (err < 0 && err != -EALREADY) + return err; + + pdata->intf_fd = adf_interface_open(dev, intf_id, O_RDWR); + if (pdata->intf_fd < 0) + return pdata->intf_fd; + + err = adf_interface_init(pdata); + if (err < 0) { + close(pdata->intf_fd); + pdata->intf_fd = -1; + } + + return err; +} + +static GRSurface* adf_init(minui_backend *backend) +{ + adf_pdata *pdata = (adf_pdata *)backend; + adf_id_t *dev_ids = NULL; + ssize_t n_dev_ids, i; + GRSurface* ret; + +#if defined(RECOVERY_ABGR) + pdata->format = DRM_FORMAT_ABGR8888; + printf("setting DRM_FORMAT_ABGR8888 and GGL_PIXEL_FORMAT_BGRA_8888, GGL_PIXEL_FORMAT may not match!\n"); +#elif defined(RECOVERY_BGRA) + pdata->format = DRM_FORMAT_BGRA8888; + printf("setting DRM_FORMAT_BGRA8888 and GGL_PIXEL_FORMAT_BGRA_8888\n"); +#elif defined(RECOVERY_RGBA) + pdata->format = DRM_FORMAT_RGBA8888; + printf("setting DRM_FORMAT_RGBA8888 and GGL_PIXEL_FORMAT_RGBA_8888\n"); +#elif defined(RECOVERY_RGBX) + pdata->format = DRM_FORMAT_RGBX8888; + printf("setting DRM_FORMAT_RGBX8888 and GGL_PIXEL_FORMAT_RGBX_8888\n"); +#else + pdata->format = DRM_FORMAT_RGB565; + printf("setting DRM_FORMAT_RGB565 and GGL_PIXEL_FORMAT_RGB_565\n"); +#endif + + n_dev_ids = adf_devices(&dev_ids); + if (n_dev_ids == 0) { + return NULL; + } else if (n_dev_ids < 0) { + fprintf(stderr, "enumerating adf devices failed: %s\n", + strerror(-n_dev_ids)); + return NULL; + } + + pdata->intf_fd = -1; + + for (i = 0; i < n_dev_ids && pdata->intf_fd < 0; i++) { + adf_device dev; + + int err = adf_device_open(dev_ids[i], O_RDWR, &dev); + if (err < 0) { + fprintf(stderr, "opening adf device %u failed: %s\n", dev_ids[i], + strerror(-err)); + continue; + } + + err = adf_device_init(pdata, &dev); + if (err < 0) + fprintf(stderr, "initializing adf device %u failed: %s\n", + dev_ids[i], strerror(-err)); + + adf_device_close(&dev); + } + + free(dev_ids); + + if (pdata->intf_fd < 0) + return NULL; + + ret = adf_flip(backend); + + adf_blank(backend, true); + adf_blank(backend, false); + + return ret; +} + +static GRSurface* adf_flip(minui_backend *backend) +{ + adf_pdata *pdata = (adf_pdata *)backend; + adf_surface_pdata *surf = &pdata->surfaces[pdata->current_surface]; + + memcpy(surf->adf_data, surf->base.data, surf->pitch * surf->base.height); + int fence_fd = adf_interface_simple_post(pdata->intf_fd, pdata->eng_id, + surf->base.width, surf->base.height, pdata->format, surf->fd, + surf->offset, surf->pitch, -1); + if (fence_fd >= 0) + close(fence_fd); + + pdata->current_surface = (pdata->current_surface + 1) % pdata->n_surfaces; + return &pdata->surfaces[pdata->current_surface].base; +} + +static void adf_blank(minui_backend *backend, bool blank) +{ + adf_pdata *pdata = (adf_pdata *)backend; + adf_interface_blank(pdata->intf_fd, + blank ? DRM_MODE_DPMS_OFF : DRM_MODE_DPMS_ON); +} + +static void adf_surface_destroy(adf_surface_pdata *surf) +{ + munmap(surf->adf_data, surf->pitch * surf->base.height); + close(surf->fd); +} + +static void adf_exit(minui_backend *backend) +{ + adf_pdata *pdata = (adf_pdata *)backend; + unsigned int i; + + free(pdata->surfaces[0].base.data); + for (i = 0; i < pdata->n_surfaces; i++) + adf_surface_destroy(&pdata->surfaces[i]); + if (pdata->intf_fd >= 0) + close(pdata->intf_fd); + free(pdata); +} + +minui_backend *open_adf() +{ + adf_pdata* pdata = reinterpret_cast<adf_pdata*>(calloc(1, sizeof(*pdata))); + if (!pdata) { + perror("allocating adf backend failed"); + return NULL; + } + + pdata->base.init = adf_init; + pdata->base.flip = adf_flip; + pdata->base.blank = adf_blank; + pdata->base.exit = adf_exit; + return &pdata->base; +} diff --git a/minuitwrp/graphics_drm.cpp b/minuitwrp/graphics_drm.cpp new file mode 100644 index 000000000..9bbf7e98f --- /dev/null +++ b/minuitwrp/graphics_drm.cpp @@ -0,0 +1,492 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <drm_fourcc.h> +#include <fcntl.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/cdefs.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <unistd.h> +#include <xf86drm.h> +#include <xf86drmMode.h> + +#include "minui.h" +#include "graphics.h" +#include <pixelflinger/pixelflinger.h> + +#define ARRAY_SIZE(A) (sizeof(A)/sizeof(*(A))) + +struct drm_surface { + GRSurface base; + uint32_t fb_id; + uint32_t handle; +}; + +static drm_surface *drm_surfaces[2]; +static int current_buffer; + +static drmModeCrtc *main_monitor_crtc; +static drmModeConnector *main_monitor_connector; + +static int drm_fd = -1; + +static void drm_disable_crtc(int drm_fd, drmModeCrtc *crtc) { + if (crtc) { + drmModeSetCrtc(drm_fd, crtc->crtc_id, + 0, // fb_id + 0, 0, // x,y + NULL, // connectors + 0, // connector_count + NULL); // mode + } +} + +static void drm_enable_crtc(int drm_fd, drmModeCrtc *crtc, + struct drm_surface *surface) { + int32_t ret; + + ret = drmModeSetCrtc(drm_fd, crtc->crtc_id, + surface->fb_id, + 0, 0, // x,y + &main_monitor_connector->connector_id, + 1, // connector_count + &main_monitor_crtc->mode); + + if (ret) + printf("drmModeSetCrtc failed ret=%d\n", ret); +} + +static void drm_blank(minui_backend* backend __unused, bool blank) { + if (blank) + drm_disable_crtc(drm_fd, main_monitor_crtc); + else + drm_enable_crtc(drm_fd, main_monitor_crtc, + drm_surfaces[current_buffer]); +} + +static void drm_destroy_surface(struct drm_surface *surface) { + struct drm_gem_close gem_close; + int ret; + + if(!surface) + return; + + if (surface->base.data) + munmap(surface->base.data, + surface->base.row_bytes * surface->base.height); + + if (surface->fb_id) { + ret = drmModeRmFB(drm_fd, surface->fb_id); + if (ret) + printf("drmModeRmFB failed ret=%d\n", ret); + } + + if (surface->handle) { + memset(&gem_close, 0, sizeof(gem_close)); + gem_close.handle = surface->handle; + + ret = drmIoctl(drm_fd, DRM_IOCTL_GEM_CLOSE, &gem_close); + if (ret) + printf("DRM_IOCTL_GEM_CLOSE failed ret=%d\n", ret); + } + + free(surface); +} + +static int drm_format_to_bpp(uint32_t format) { + switch(format) { + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_BGRA8888: + case DRM_FORMAT_RGBX8888: + case DRM_FORMAT_BGRX8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XRGB8888: + return 32; + case DRM_FORMAT_RGB565: + return 16; + default: + printf("Unknown format %d\n", format); + return 32; + } +} + +static drm_surface *drm_create_surface(int width, int height) { + struct drm_surface *surface; + struct drm_mode_create_dumb create_dumb; + uint32_t format; + __u32 base_format; + int ret; + + surface = (struct drm_surface*)calloc(1, sizeof(*surface)); + if (!surface) { + printf("Can't allocate memory\n"); + return NULL; + } + +#if defined(RECOVERY_ABGR) + format = DRM_FORMAT_RGBA8888; + base_format = GGL_PIXEL_FORMAT_RGBA_8888; + printf("setting DRM_FORMAT_RGBA8888 and GGL_PIXEL_FORMAT_RGBA_8888\n"); +#elif defined(RECOVERY_BGRA) + format = DRM_FORMAT_ARGB8888; + base_format = GGL_PIXEL_FORMAT_BGRA_8888; + printf("setting DRM_FORMAT_ARGB8888 and GGL_PIXEL_FORMAT_BGRA_8888, GGL_PIXEL_FORMAT may not match!\n"); +#elif defined(RECOVERY_RGBA) + format = DRM_FORMAT_ABGR8888; + base_format = GGL_PIXEL_FORMAT_BGRA_8888; + printf("setting DRM_FORMAT_ABGR8888 and GGL_PIXEL_FORMAT_BGRA_8888, GGL_PIXEL_FORMAT may not match!\n"); +#elif defined(RECOVERY_RGBX) + format = DRM_FORMAT_XBGR8888; + base_format = GGL_PIXEL_FORMAT_BGRA_8888; + printf("setting DRM_FORMAT_XBGR8888 and GGL_PIXEL_FORMAT_BGRA_8888, GGL_PIXEL_FORMAT may not match!\n"); +#else + format = DRM_FORMAT_RGB565; + base_format = GGL_PIXEL_FORMAT_BGRA_8888; + printf("setting DRM_FORMAT_RGB565 and GGL_PIXEL_FORMAT_RGB_565\n"); +#endif + + memset(&create_dumb, 0, sizeof(create_dumb)); + create_dumb.height = height; + create_dumb.width = width; + create_dumb.bpp = drm_format_to_bpp(format); + create_dumb.flags = 0; + + ret = drmIoctl(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb); + if (ret) { + printf("DRM_IOCTL_MODE_CREATE_DUMB failed ret=%d\n",ret); + drm_destroy_surface(surface); + return NULL; + } + surface->handle = create_dumb.handle; + + uint32_t handles[4], pitches[4], offsets[4]; + + handles[0] = surface->handle; + pitches[0] = create_dumb.pitch; + offsets[0] = 0; + + ret = drmModeAddFB2(drm_fd, width, height, + format, handles, pitches, offsets, + &(surface->fb_id), 0); + if (ret) { + printf("drmModeAddFB2 failed ret=%d\n", ret); + drm_destroy_surface(surface); + return NULL; + } + + struct drm_mode_map_dumb map_dumb; + memset(&map_dumb, 0, sizeof(map_dumb)); + map_dumb.handle = create_dumb.handle; + ret = drmIoctl(drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb); + if (ret) { + printf("DRM_IOCTL_MODE_MAP_DUMB failed ret=%d\n",ret); + drm_destroy_surface(surface); + return NULL;; + } + + surface->base.height = height; + surface->base.width = width; + surface->base.row_bytes = create_dumb.pitch; + surface->base.pixel_bytes = create_dumb.bpp / 8; + surface->base.format = base_format; + surface->base.data = (unsigned char*) + mmap(NULL, + surface->base.height * surface->base.row_bytes, + PROT_READ | PROT_WRITE, MAP_SHARED, + drm_fd, map_dumb.offset); + if (surface->base.data == MAP_FAILED) { + perror("mmap() failed"); + drm_destroy_surface(surface); + return NULL; + } + + return surface; +} + +static drmModeCrtc *find_crtc_for_connector(int fd, + drmModeRes *resources, + drmModeConnector *connector) { + int i, j; + drmModeEncoder *encoder; + int32_t crtc; + + /* + * Find the encoder. If we already have one, just use it. + */ + if (connector->encoder_id) + encoder = drmModeGetEncoder(fd, connector->encoder_id); + else + encoder = NULL; + + if (encoder && encoder->crtc_id) { + crtc = encoder->crtc_id; + drmModeFreeEncoder(encoder); + return drmModeGetCrtc(fd, crtc); + } + + /* + * Didn't find anything, try to find a crtc and encoder combo. + */ + crtc = -1; + for (i = 0; i < connector->count_encoders; i++) { + encoder = drmModeGetEncoder(fd, connector->encoders[i]); + + if (encoder) { + for (j = 0; j < resources->count_crtcs; j++) { + if (!(encoder->possible_crtcs & (1 << j))) + continue; + crtc = resources->crtcs[j]; + break; + } + if (crtc >= 0) { + drmModeFreeEncoder(encoder); + return drmModeGetCrtc(fd, crtc); + } + } + } + + return NULL; +} + +static drmModeConnector *find_used_connector_by_type(int fd, + drmModeRes *resources, + unsigned type) { + int i; + for (i = 0; i < resources->count_connectors; i++) { + drmModeConnector *connector; + + connector = drmModeGetConnector(fd, resources->connectors[i]); + if (connector) { + if ((connector->connector_type == type) && + (connector->connection == DRM_MODE_CONNECTED) && + (connector->count_modes > 0)) + return connector; + + drmModeFreeConnector(connector); + } + } + return NULL; +} + +static drmModeConnector *find_first_connected_connector(int fd, + drmModeRes *resources) { + int i; + for (i = 0; i < resources->count_connectors; i++) { + drmModeConnector *connector; + + connector = drmModeGetConnector(fd, resources->connectors[i]); + if (connector) { + if ((connector->count_modes > 0) && + (connector->connection == DRM_MODE_CONNECTED)) + return connector; + + drmModeFreeConnector(connector); + } + } + return NULL; +} + +static drmModeConnector *find_main_monitor(int fd, drmModeRes *resources, + uint32_t *mode_index) { + unsigned i = 0; + int modes; + /* Look for LVDS/eDP/DSI connectors. Those are the main screens. */ + unsigned kConnectorPriority[] = { + DRM_MODE_CONNECTOR_LVDS, + DRM_MODE_CONNECTOR_eDP, + DRM_MODE_CONNECTOR_DSI, + }; + + drmModeConnector *main_monitor_connector = NULL; + do { + main_monitor_connector = find_used_connector_by_type(fd, + resources, + kConnectorPriority[i]); + i++; + } while (!main_monitor_connector && i < ARRAY_SIZE(kConnectorPriority)); + + /* If we didn't find a connector, grab the first one that is connected. */ + if (!main_monitor_connector) + main_monitor_connector = + find_first_connected_connector(fd, resources); + + /* If we still didn't find a connector, give up and return. */ + if (!main_monitor_connector) + return NULL; + + *mode_index = 0; + for (modes = 0; modes < main_monitor_connector->count_modes; modes++) { + if (main_monitor_connector->modes[modes].type & + DRM_MODE_TYPE_PREFERRED) { + *mode_index = modes; + break; + } + } + + return main_monitor_connector; +} + +static void disable_non_main_crtcs(int fd, + drmModeRes *resources, + drmModeCrtc* main_crtc) { + int i; + drmModeCrtc* crtc; + + for (i = 0; i < resources->count_connectors; i++) { + drmModeConnector *connector; + + connector = drmModeGetConnector(fd, resources->connectors[i]); + crtc = find_crtc_for_connector(fd, resources, connector); + if (crtc->crtc_id != main_crtc->crtc_id) + drm_disable_crtc(fd, crtc); + drmModeFreeCrtc(crtc); + } +} + +static GRSurface* drm_init(minui_backend* backend __unused) { + drmModeRes *res = NULL; + uint32_t selected_mode; + char *dev_name; + int width, height; + int ret, i; + + /* Consider DRM devices in order. */ + for (i = 0; i < DRM_MAX_MINOR; i++) { + uint64_t cap = 0; + + ret = asprintf(&dev_name, DRM_DEV_NAME, DRM_DIR_NAME, i); + if (ret < 0) + continue; + + drm_fd = open(dev_name, O_RDWR, 0); + free(dev_name); + if (drm_fd < 0) + continue; + + /* We need dumb buffers. */ + ret = drmGetCap(drm_fd, DRM_CAP_DUMB_BUFFER, &cap); + if (ret || cap == 0) { + close(drm_fd); + continue; + } + + res = drmModeGetResources(drm_fd); + if (!res) { + close(drm_fd); + continue; + } + + /* Use this device if it has at least one connected monitor. */ + if (res->count_crtcs > 0 && res->count_connectors > 0) + if (find_first_connected_connector(drm_fd, res)) + break; + + drmModeFreeResources(res); + close(drm_fd); + res = NULL; + } + + if (drm_fd < 0 || res == NULL) { + perror("cannot find/open a drm device"); + return NULL; + } + + main_monitor_connector = find_main_monitor(drm_fd, + res, &selected_mode); + + if (!main_monitor_connector) { + printf("main_monitor_connector not found\n"); + drmModeFreeResources(res); + close(drm_fd); + return NULL; + } + + main_monitor_crtc = find_crtc_for_connector(drm_fd, res, + main_monitor_connector); + + if (!main_monitor_crtc) { + printf("main_monitor_crtc not found\n"); + drmModeFreeResources(res); + close(drm_fd); + return NULL; + } + + disable_non_main_crtcs(drm_fd, + res, main_monitor_crtc); + + main_monitor_crtc->mode = main_monitor_connector->modes[selected_mode]; + + width = main_monitor_crtc->mode.hdisplay; + height = main_monitor_crtc->mode.vdisplay; + + drmModeFreeResources(res); + + drm_surfaces[0] = drm_create_surface(width, height); + drm_surfaces[1] = drm_create_surface(width, height); + if (!drm_surfaces[0] || !drm_surfaces[1]) { + drm_destroy_surface(drm_surfaces[0]); + drm_destroy_surface(drm_surfaces[1]); + drmModeFreeResources(res); + close(drm_fd); + return NULL; + } + + current_buffer = 0; + + drm_enable_crtc(drm_fd, main_monitor_crtc, drm_surfaces[1]); + + return &(drm_surfaces[0]->base); +} + +static GRSurface* drm_flip(minui_backend* backend __unused) { + int ret; + + ret = drmModePageFlip(drm_fd, main_monitor_crtc->crtc_id, + drm_surfaces[current_buffer]->fb_id, 0, NULL); + if (ret < 0) { + printf("drmModePageFlip failed ret=%d\n", ret); + return NULL; + } + current_buffer = 1 - current_buffer; + return &(drm_surfaces[current_buffer]->base); +} + +static void drm_exit(minui_backend* backend __unused) { + drm_disable_crtc(drm_fd, main_monitor_crtc); + drm_destroy_surface(drm_surfaces[0]); + drm_destroy_surface(drm_surfaces[1]); + drmModeFreeCrtc(main_monitor_crtc); + drmModeFreeConnector(main_monitor_connector); + close(drm_fd); + drm_fd = -1; +} + +static minui_backend drm_backend = { + .init = drm_init, + .flip = drm_flip, + .blank = drm_blank, + .exit = drm_exit, +}; + +minui_backend* open_drm() { + return &drm_backend; +} diff --git a/minuitwrp/graphics_fbdev.cpp b/minuitwrp/graphics_fbdev.cpp new file mode 100644 index 000000000..10ef4fec2 --- /dev/null +++ b/minuitwrp/graphics_fbdev.cpp @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <fcntl.h> +#include <stdio.h> + +#include <sys/cdefs.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/types.h> + +#include <linux/fb.h> +#include <linux/kd.h> + +#include "minui.h" +#include "graphics.h" +#include <pixelflinger/pixelflinger.h> + +static GRSurface* fbdev_init(minui_backend*); +static GRSurface* fbdev_flip(minui_backend*); +static void fbdev_blank(minui_backend*, bool); +static void fbdev_exit(minui_backend*); + +static GRSurface gr_framebuffer[2]; +static bool double_buffered; +static GRSurface* gr_draw = NULL; +static int displayed_buffer; + +static fb_var_screeninfo vi; +static int fb_fd = -1; +static __u32 smem_len; + +static minui_backend my_backend = { + .init = fbdev_init, + .flip = fbdev_flip, + .blank = fbdev_blank, + .exit = fbdev_exit, +}; + +minui_backend* open_fbdev() { + return &my_backend; +} + +static void fbdev_blank(minui_backend* backend __unused, bool blank) +{ +#if defined(TW_NO_SCREEN_BLANK) && defined(TW_BRIGHTNESS_PATH) && defined(TW_MAX_BRIGHTNESS) + int fd; + char brightness[4]; + snprintf(brightness, 4, "%03d", TW_MAX_BRIGHTNESS/2); + + fd = open(TW_BRIGHTNESS_PATH, O_RDWR); + if (fd < 0) { + perror("cannot open LCD backlight"); + return; + } + write(fd, blank ? "000" : brightness, 3); + close(fd); +#else +#ifndef TW_NO_SCREEN_BLANK + int ret; + + ret = ioctl(fb_fd, FBIOBLANK, blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK); + if (ret < 0) + perror("ioctl(): blank"); +#endif +#endif +} + +static void set_displayed_framebuffer(unsigned n) +{ + if (n > 1 || !double_buffered) return; + + vi.yres_virtual = gr_framebuffer[0].height * 2; + vi.yoffset = n * gr_framebuffer[0].height; + vi.bits_per_pixel = gr_framebuffer[0].pixel_bytes * 8; + if (ioctl(fb_fd, FBIOPUT_VSCREENINFO, &vi) < 0) { + perror("active fb swap failed"); + } + displayed_buffer = n; +} + +static GRSurface* fbdev_init(minui_backend* backend) { + int fd = open("/dev/graphics/fb0", O_RDWR); + if (fd == -1) { + perror("cannot open fb0"); + return NULL; + } + + fb_fix_screeninfo fi; + if (ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) { + perror("failed to get fb0 info"); + close(fd); + return NULL; + } + + if (ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) { + perror("failed to get fb0 info"); + close(fd); + return NULL; + } + + // We print this out for informational purposes only, but + // throughout we assume that the framebuffer device uses an RGBX + // pixel format. This is the case for every development device I + // have access to. For some of those devices (eg, hammerhead aka + // Nexus 5), FBIOGET_VSCREENINFO *reports* that it wants a + // different format (XBGR) but actually produces the correct + // results on the display when you write RGBX. + // + // If you have a device that actually *needs* another pixel format + // (ie, BGRX, or 565), patches welcome... + + printf("fb0 reports (possibly inaccurate):\n" + " vi.bits_per_pixel = %d\n" + " vi.red.offset = %3d .length = %3d\n" + " vi.green.offset = %3d .length = %3d\n" + " vi.blue.offset = %3d .length = %3d\n", + vi.bits_per_pixel, + vi.red.offset, vi.red.length, + vi.green.offset, vi.green.length, + vi.blue.offset, vi.blue.length); + + void* 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 NULL; + } + + memset(bits, 0, fi.smem_len); + +#ifdef RECOVERY_RGB_565 + printf("Forcing pixel format: RGB_565\n"); + vi.blue.offset = 0; + vi.green.offset = 5; + vi.red.offset = 11; + vi.blue.length = 5; + vi.green.length = 6; + vi.red.length = 5; + vi.blue.msb_right = 0; + vi.green.msb_right = 0; + vi.red.msb_right = 0; + vi.transp.offset = 0; + vi.transp.length = 0; + vi.bits_per_pixel = 16; +#endif + + gr_framebuffer[0].width = vi.xres; + gr_framebuffer[0].height = vi.yres; + gr_framebuffer[0].row_bytes = fi.line_length; + gr_framebuffer[0].pixel_bytes = vi.bits_per_pixel / 8; +#ifdef RECOVERY_GRAPHICS_USE_LINELENGTH + vi.xres_virtual = fi.line_length / gr_framebuffer[0].pixel_bytes; +#endif + gr_framebuffer[0].data = reinterpret_cast<uint8_t*>(bits); + if (vi.bits_per_pixel == 16) { + printf("setting GGL_PIXEL_FORMAT_RGB_565\n"); + gr_framebuffer[0].format = GGL_PIXEL_FORMAT_RGB_565; + } else if (vi.red.offset == 8) { + printf("setting GGL_PIXEL_FORMAT_BGRA_8888\n"); + gr_framebuffer[0].format = GGL_PIXEL_FORMAT_BGRA_8888; + } else if (vi.red.offset == 0) { + printf("setting GGL_PIXEL_FORMAT_RGBA_8888\n"); + gr_framebuffer[0].format = GGL_PIXEL_FORMAT_RGBA_8888; + } else if (vi.red.offset == 24) { + printf("setting GGL_PIXEL_FORMAT_RGBX_8888\n"); + gr_framebuffer[0].format = GGL_PIXEL_FORMAT_RGBX_8888; + } else { + if (vi.red.length == 8) { + printf("No valid pixel format detected, trying GGL_PIXEL_FORMAT_RGBX_8888\n"); + gr_framebuffer[0].format = GGL_PIXEL_FORMAT_RGBX_8888; + } else { + printf("No valid pixel format detected, trying GGL_PIXEL_FORMAT_RGB_565\n"); + gr_framebuffer[0].format = GGL_PIXEL_FORMAT_RGB_565; + } + } + + // Drawing directly to the framebuffer takes about 5 times longer. + // Instead, we will allocate some memory and draw to that, then + // memcpy the data into the framebuffer later. + gr_draw = (GRSurface*) malloc(sizeof(GRSurface)); + if (!gr_draw) { + perror("failed to allocate gr_draw"); + close(fd); + munmap(bits, fi.smem_len); + return NULL; + } + memcpy(gr_draw, gr_framebuffer, sizeof(GRSurface)); + gr_draw->data = (unsigned char*) calloc(gr_draw->height * gr_draw->row_bytes, 1); + if (!gr_draw->data) { + perror("failed to allocate in-memory surface"); + close(fd); + free(gr_draw); + munmap(bits, fi.smem_len); + return NULL; + } + + /* check if we can use double buffering */ + if (vi.yres * fi.line_length * 2 <= fi.smem_len) { + double_buffered = true; + printf("double buffered\n"); + + memcpy(gr_framebuffer+1, gr_framebuffer, sizeof(GRSurface)); + gr_framebuffer[1].data = gr_framebuffer[0].data + + gr_framebuffer[0].height * gr_framebuffer[0].row_bytes; + + } else { + double_buffered = false; + printf("single buffered\n"); + } +#if defined(RECOVERY_BGRA) + printf("RECOVERY_BGRA\n"); +#endif + fb_fd = fd; + set_displayed_framebuffer(0); + + printf("framebuffer: %d (%d x %d)\n", fb_fd, gr_draw->width, gr_draw->height); + + fbdev_blank(backend, true); + fbdev_blank(backend, false); + + smem_len = fi.smem_len; + + return gr_draw; +} + +static GRSurface* fbdev_flip(minui_backend* backend __unused) { + if (double_buffered) { +#if defined(RECOVERY_BGRA) + // In case of BGRA, do some byte swapping + unsigned int idx; + unsigned char tmp; + unsigned char* ucfb_vaddr = (unsigned char*)gr_draw->data; + for (idx = 0 ; idx < (gr_draw->height * gr_draw->row_bytes); + idx += 4) { + tmp = ucfb_vaddr[idx]; + ucfb_vaddr[idx ] = ucfb_vaddr[idx + 2]; + ucfb_vaddr[idx + 2] = tmp; + } +#endif + // Copy from the in-memory surface to the framebuffer. + memcpy(gr_framebuffer[1-displayed_buffer].data, gr_draw->data, + gr_draw->height * gr_draw->row_bytes); + set_displayed_framebuffer(1-displayed_buffer); + } else { + // Copy from the in-memory surface to the framebuffer. + memcpy(gr_framebuffer[0].data, gr_draw->data, + gr_draw->height * gr_draw->row_bytes); + } + return gr_draw; +} + +static void fbdev_exit(minui_backend* backend __unused) { + close(fb_fd); + fb_fd = -1; + + if (gr_draw) { + free(gr_draw->data); + free(gr_draw); + } + gr_draw = NULL; + munmap(gr_framebuffer[0].data, smem_len); +} diff --git a/minuitwrp/graphics_overlay.c b/minuitwrp/graphics_overlay.cpp index 723ffa2d4..5445b6f62 100644 --- a/minuitwrp/graphics_overlay.c +++ b/minuitwrp/graphics_overlay.cpp @@ -1,40 +1,29 @@ /* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Copyright (C) 2014 The Android Open Source Project * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of The Linux Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #include <stdbool.h> #include <stdlib.h> +#include <string.h> #include <unistd.h> - #include <errno.h> + #include <fcntl.h> #include <stdio.h> +#include <sys/cdefs.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <sys/types.h> @@ -47,15 +36,32 @@ #include <linux/msm_ion.h> #endif -#include <pixelflinger/pixelflinger.h> - #include "minui.h" +#include "graphics.h" +#include <pixelflinger/pixelflinger.h> #define MDP_V4_0 400 +#define MAX_DISPLAY_DIM 2048 -#ifdef MSM_BSP +static GRSurface* overlay_init(minui_backend*); +static GRSurface* overlay_flip(minui_backend*); +static void overlay_blank(minui_backend*, bool); +static void overlay_exit(minui_backend*); + +static GRSurface gr_framebuffer; +static GRSurface* gr_draw = NULL; +static int displayed_buffer; + +static fb_var_screeninfo vi; +static int fb_fd = -1; +static bool isMDP5 = false; +static int leftSplit = 0; +static int rightSplit = 0; #define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1)) +static size_t frame_size = 0; + +#ifdef MSM_BSP typedef struct { unsigned char *mem_buf; int size; @@ -72,23 +78,31 @@ static memInfo mem_info; static int map_mdp_pixel_format() { - int format = MDP_RGB_565; -#if defined(RECOVERY_BGRA) - format = MDP_BGRA_8888; -#elif defined(RECOVERY_RGBA) - format = MDP_RGBA_8888; -#elif defined(RECOVERY_RGBX) - format = MDP_RGBA_8888; -#endif - return format; + if (gr_framebuffer.format == GGL_PIXEL_FORMAT_RGB_565) + return MDP_RGB_565; + else if (gr_framebuffer.format == GGL_PIXEL_FORMAT_BGRA_8888) + return MDP_BGRA_8888; + else if (gr_framebuffer.format == GGL_PIXEL_FORMAT_RGBA_8888) + return MDP_RGBA_8888; + else if (gr_framebuffer.format == GGL_PIXEL_FORMAT_RGBX_8888) + return MDP_RGBA_8888; + printf("No known pixel format for map_mdp_pixel_format, defaulting to MDP_RGB_565.\n"); + return MDP_RGB_565; } +#endif // MSM_BSP -static bool overlay_supported = false; -static bool isMDP5 = false; +static minui_backend my_backend = { + .init = overlay_init, + .flip = overlay_flip, + .blank = overlay_blank, + .exit = overlay_exit, +}; bool target_has_overlay(char *version) { + int ret; int mdp_version; + bool overlay_supported = false; if (strlen(version) >= 8) { if(!strncmp(version, "msmfb", strlen("msmfb"))) { @@ -104,22 +118,100 @@ bool target_has_overlay(char *version) isMDP5 = true; } } - if (overlay_supported) printf("Using qcomm overlay\n"); + return overlay_supported; } -bool isTargetMdp5() +minui_backend* open_overlay() { + fb_fix_screeninfo fi; + int fd; + + fd = open("/dev/graphics/fb0", O_RDWR); + if (fd < 0) { + perror("open_overlay cannot open fb0"); + return NULL; + } + + if (ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) { + perror("failed to get fb0 info"); + close(fd); + return NULL; + } + + if (target_has_overlay(fi.id)) { +#ifdef MSM_BSP + close(fd); + return &my_backend; +#else + printf("Overlay graphics may work (%s), but not enabled. Use TW_TARGET_USES_QCOM_BSP := true to enable.\n", fi.id); +#endif + } + close(fd); + return NULL; +} + +static void overlay_blank(minui_backend* backend __unused, bool blank) { - if (isMDP5) - return true; +#if defined(TW_NO_SCREEN_BLANK) && defined(TW_BRIGHTNESS_PATH) && defined(TW_MAX_BRIGHTNESS) + int fd; + char brightness[4]; + snprintf(brightness, 4, "%03d", TW_MAX_BRIGHTNESS/2); + + fd = open(TW_BRIGHTNESS_PATH, O_RDWR); + if (fd < 0) { + perror("cannot open LCD backlight"); + return; + } + write(fd, blank ? "000" : brightness, 3); + close(fd); +#else + int ret; - return false; + ret = ioctl(fb_fd, FBIOBLANK, blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK); + if (ret < 0) + perror("ioctl(): blank"); +#endif } -int free_ion_mem(void) { - if (!overlay_supported) - return -EINVAL; +#ifdef MSM_BSP +void setDisplaySplit(void) { + char split[64] = {0}; + if (!isMDP5) + return; + 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); +} + +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; +} + +int free_ion_mem(void) { int ret = 0; if (mem_info.mem_buf) @@ -144,8 +236,6 @@ int free_ion_mem(void) { int alloc_ion_mem(unsigned int size) { - if (!overlay_supported) - return -EINVAL; int result; struct ion_fd_data fd_data; struct ion_allocation_data ionAllocData; @@ -195,13 +285,20 @@ int alloc_ion_mem(unsigned int size) return 0; } -int allocate_overlay(int fd, GGLSurface gr_fb[]) +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 allocate_overlay(int fd, GRSurface gr_fb) { int ret = 0; - if (!overlay_supported) - return -EINVAL; - if (!isDisplaySplit()) { // Check if overlay is already allocated if (MSMFB_NEW_REQUEST == overlayL_id) { @@ -210,13 +307,13 @@ int allocate_overlay(int fd, GGLSurface gr_fb[]) memset(&overlayL, 0 , sizeof (struct mdp_overlay)); /* Fill Overlay Data */ - overlayL.src.width = ALIGN(gr_fb[0].width, 32); - overlayL.src.height = gr_fb[0].height; + overlayL.src.width = ALIGN(gr_fb.width, 32); + overlayL.src.height = gr_fb.height; overlayL.src.format = map_mdp_pixel_format(); - overlayL.src_rect.w = gr_fb[0].width; - overlayL.src_rect.h = gr_fb[0].height; - overlayL.dst_rect.w = gr_fb[0].width; - overlayL.dst_rect.h = gr_fb[0].height; + overlayL.src_rect.w = gr_fb.width; + overlayL.src_rect.h = gr_fb.height; + overlayL.dst_rect.w = gr_fb.width; + overlayL.dst_rect.h = gr_fb.height; overlayL.alpha = 0xFF; overlayL.transp_mask = MDP_TRANSP_NOP; overlayL.id = MSMFB_NEW_REQUEST; @@ -228,13 +325,13 @@ int allocate_overlay(int fd, GGLSurface gr_fb[]) overlayL_id = overlayL.id; } } else { - float xres = getFbXres(); + float xres = vi.xres; int lSplit = getLeftSplit(); float lSplitRatio = lSplit / xres; - float lCropWidth = gr_fb[0].width * lSplitRatio; + float lCropWidth = gr_fb.width * lSplitRatio; int lWidth = lSplit; - int rWidth = gr_fb[0].width - lSplit; - int height = gr_fb[0].height; + int rWidth = gr_fb.width - lSplit; + int height = gr_fb.height; if (MSMFB_NEW_REQUEST == overlayL_id) { @@ -243,13 +340,13 @@ int allocate_overlay(int fd, GGLSurface gr_fb[]) memset(&overlayL, 0 , sizeof (struct mdp_overlay)); /* Fill OverlayL Data */ - overlayL.src.width = ALIGN(gr_fb[0].width, 32); - overlayL.src.height = gr_fb[0].height; + overlayL.src.width = ALIGN(gr_fb.width, 32); + overlayL.src.height = gr_fb.height; overlayL.src.format = map_mdp_pixel_format(); overlayL.src_rect.x = 0; overlayL.src_rect.y = 0; overlayL.src_rect.w = lCropWidth; - overlayL.src_rect.h = gr_fb[0].height; + overlayL.src_rect.h = gr_fb.height; overlayL.dst_rect.x = 0; overlayL.dst_rect.y = 0; overlayL.dst_rect.w = lWidth; @@ -270,13 +367,13 @@ int allocate_overlay(int fd, GGLSurface gr_fb[]) memset(&overlayR, 0 , sizeof (struct mdp_overlay)); /* Fill OverlayR Data */ - overlayR.src.width = ALIGN(gr_fb[0].width, 32); - overlayR.src.height = gr_fb[0].height; + overlayR.src.width = ALIGN(gr_fb.width, 32); + overlayR.src.height = gr_fb.height; overlayR.src.format = map_mdp_pixel_format(); overlayR.src_rect.x = lCropWidth; overlayR.src_rect.y = 0; - overlayR.src_rect.w = gr_fb[0].width - lCropWidth; - overlayR.src_rect.h = gr_fb[0].height; + overlayR.src_rect.w = gr_fb.width - lCropWidth; + overlayR.src_rect.h = gr_fb.height; overlayR.dst_rect.x = 0; overlayR.dst_rect.y = 0; overlayR.dst_rect.w = rWidth; @@ -297,64 +394,8 @@ int allocate_overlay(int fd, GGLSurface gr_fb[]) return 0; } -int free_overlay(int fd) -{ - if (!overlay_supported) - return -EINVAL; - - int ret = 0; - struct mdp_display_commit ext_commit; - - if (!isDisplaySplit()) { - if (overlayL_id != MSMFB_NEW_REQUEST) { - ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayL_id); - if (ret) { - perror("Overlay Unset Failed"); - overlayL_id = MSMFB_NEW_REQUEST; - return ret; - } - } - } else { - - if (overlayL_id != MSMFB_NEW_REQUEST) { - ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayL_id); - if (ret) { - perror("OverlayL Unset Failed"); - overlayL_id = MSMFB_NEW_REQUEST; - return ret; - } - } - - if (overlayR_id != MSMFB_NEW_REQUEST) { - ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayR_id); - if (ret) { - perror("OverlayR Unset Failed"); - overlayR_id = MSMFB_NEW_REQUEST; - return ret; - } - } - } - memset(&ext_commit, 0, sizeof(struct mdp_display_commit)); - ext_commit.flags = MDP_DISPLAY_COMMIT_OVERLAY; - ext_commit.wait_for_finish = 1; - ret = ioctl(fd, MSMFB_DISPLAY_COMMIT, &ext_commit); - if (ret < 0) { - perror("ERROR: Clear MSMFB_DISPLAY_COMMIT failed!"); - overlayL_id = MSMFB_NEW_REQUEST; - overlayR_id = MSMFB_NEW_REQUEST; - return ret; - } - overlayL_id = MSMFB_NEW_REQUEST; - overlayR_id = MSMFB_NEW_REQUEST; - - return 0; -} - -int overlay_display_frame(int fd, GGLubyte* data, size_t size) +int overlay_display_frame(int fd, void* data, size_t size) { - if (!overlay_supported) - return -EINVAL; - int ret = 0; struct msmfb_overlay_data ovdataL, ovdataR; struct mdp_display_commit ext_commit; @@ -376,6 +417,7 @@ int overlay_display_frame(int fd, GGLubyte* data, size_t size) ret = ioctl(fd, MSMFB_OVERLAY_PLAY, &ovdataL); if (ret < 0) { perror("overlay_display_frame failed, overlay play Failed\n"); + printf("%i, %i, %i, %i\n", ret, fb_fd, fd, errno); return ret; } } else { @@ -426,38 +468,186 @@ int overlay_display_frame(int fd, GGLubyte* data, size_t size) return ret; } -#else - -bool target_has_overlay(char *version) { - return false; +static GRSurface* overlay_flip(minui_backend* backend __unused) { +#if defined(RECOVERY_BGRA) + // In case of BGRA, do some byte swapping + unsigned int idx; + unsigned char tmp; + unsigned char* ucfb_vaddr = (unsigned char*)gr_draw->data; + for (idx = 0 ; idx < (gr_draw->height * gr_draw->row_bytes); + idx += 4) { + tmp = ucfb_vaddr[idx]; + ucfb_vaddr[idx ] = ucfb_vaddr[idx + 2]; + ucfb_vaddr[idx + 2] = tmp; + } +#endif + // Copy from the in-memory surface to the framebuffer. + overlay_display_frame(fb_fd, gr_draw->data, frame_size); + return gr_draw; } -bool isTargetMdp5() { - return false; -} +int free_overlay(int fd) +{ + int ret = 0; + struct mdp_display_commit ext_commit; -int free_ion_mem(void) { - return -EINVAL; -} + if (!isDisplaySplit()) { + if (overlayL_id != MSMFB_NEW_REQUEST) { + ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayL_id); + if (ret) { + perror("Overlay Unset Failed"); + overlayL_id = MSMFB_NEW_REQUEST; + return ret; + } + } + } else { -int alloc_ion_mem(unsigned int size) -{ - return -EINVAL; + if (overlayL_id != MSMFB_NEW_REQUEST) { + ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayL_id); + if (ret) { + perror("OverlayL Unset Failed"); + } + } + + if (overlayR_id != MSMFB_NEW_REQUEST) { + ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayR_id); + if (ret) { + perror("OverlayR Unset Failed"); + overlayR_id = MSMFB_NEW_REQUEST; + return ret; + } + } + } + memset(&ext_commit, 0, sizeof(struct mdp_display_commit)); + ext_commit.flags = MDP_DISPLAY_COMMIT_OVERLAY; + ext_commit.wait_for_finish = 1; + ret = ioctl(fd, MSMFB_DISPLAY_COMMIT, &ext_commit); + if (ret < 0) { + perror("ERROR: Clear MSMFB_DISPLAY_COMMIT failed!"); + overlayL_id = MSMFB_NEW_REQUEST; + overlayR_id = MSMFB_NEW_REQUEST; + return ret; + } + overlayL_id = MSMFB_NEW_REQUEST; + overlayR_id = MSMFB_NEW_REQUEST; + + return 0; } -int allocate_overlay(int fd, GGLSurface gr_fb[]) -{ - return -EINVAL; +static GRSurface* overlay_init(minui_backend* backend) { + int fd = open("/dev/graphics/fb0", O_RDWR); + if (fd == -1) { + perror("cannot open fb0"); + return NULL; + } + + fb_fix_screeninfo fi; + if (ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) { + perror("failed to get fb0 info"); + close(fd); + return NULL; + } + + if (ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) { + perror("failed to get fb0 info"); + close(fd); + return NULL; + } + + // We print this out for informational purposes only, but + // throughout we assume that the framebuffer device uses an RGBX + // pixel format. This is the case for every development device I + // have access to. For some of those devices (eg, hammerhead aka + // Nexus 5), FBIOGET_VSCREENINFO *reports* that it wants a + // different format (XBGR) but actually produces the correct + // results on the display when you write RGBX. + // + // If you have a device that actually *needs* another pixel format + // (ie, BGRX, or 565), patches welcome... + + printf("fb0 reports (possibly inaccurate):\n" + " vi.bits_per_pixel = %d\n" + " vi.red.offset = %3d .length = %3d\n" + " vi.green.offset = %3d .length = %3d\n" + " vi.blue.offset = %3d .length = %3d\n", + vi.bits_per_pixel, + vi.red.offset, vi.red.length, + vi.green.offset, vi.green.length, + vi.blue.offset, vi.blue.length); + + gr_framebuffer.width = vi.xres; + gr_framebuffer.height = vi.yres; + gr_framebuffer.row_bytes = fi.line_length; + gr_framebuffer.pixel_bytes = vi.bits_per_pixel / 8; + //gr_framebuffer.data = reinterpret_cast<uint8_t*>(bits); + if (vi.bits_per_pixel == 16) { + printf("setting GGL_PIXEL_FORMAT_RGB_565\n"); + gr_framebuffer.format = GGL_PIXEL_FORMAT_RGB_565; + } else if (vi.red.offset == 8) { + printf("setting GGL_PIXEL_FORMAT_BGRA_8888\n"); + gr_framebuffer.format = GGL_PIXEL_FORMAT_BGRA_8888; + } else if (vi.red.offset == 0) { + printf("setting GGL_PIXEL_FORMAT_RGBA_8888\n"); + gr_framebuffer.format = GGL_PIXEL_FORMAT_RGBA_8888; + } else if (vi.red.offset == 24) { + printf("setting GGL_PIXEL_FORMAT_RGBX_8888\n"); + gr_framebuffer.format = GGL_PIXEL_FORMAT_RGBX_8888; + } else { + if (vi.red.length == 8) { + printf("No valid pixel format detected, trying GGL_PIXEL_FORMAT_RGBX_8888\n"); + gr_framebuffer.format = GGL_PIXEL_FORMAT_RGBX_8888; + } else { + printf("No valid pixel format detected, trying GGL_PIXEL_FORMAT_RGB_565\n"); + gr_framebuffer.format = GGL_PIXEL_FORMAT_RGB_565; + } + } + + frame_size = fi.line_length * vi.yres; + + gr_framebuffer.data = reinterpret_cast<uint8_t*>(calloc(frame_size, 1)); + if (gr_framebuffer.data == NULL) { + perror("failed to calloc framebuffer"); + close(fd); + return NULL; + } + + gr_draw = &gr_framebuffer; + fb_fd = fd; + + printf("framebuffer: %d (%d x %d)\n", fb_fd, gr_draw->width, gr_draw->height); + + overlay_blank(backend, true); + overlay_blank(backend, false); + + if (!alloc_ion_mem(frame_size)) + allocate_overlay(fb_fd, gr_framebuffer); + + return gr_draw; } -int free_overlay(int fd) -{ - return -EINVAL; +static void overlay_exit(minui_backend* backend __unused) { + free_overlay(fb_fd); + free_ion_mem(); + + close(fb_fd); + fb_fd = -1; + + if (gr_draw) { + free(gr_draw->data); + free(gr_draw); + } + gr_draw = NULL; +} +#else // MSM_BSP +static GRSurface* overlay_flip(minui_backend* backend __unused) { + return NULL; } -int overlay_display_frame(int fd, GGLubyte* data, size_t size) -{ - return -EINVAL; +static GRSurface* overlay_init(minui_backend* backend __unused) { + return NULL; } -#endif //#ifdef MSM_BSP +static void overlay_exit(minui_backend* backend __unused) { + return; +} +#endif // MSM_BSP diff --git a/minuitwrp/graphics_utils.c b/minuitwrp/graphics_utils.cpp index ea1182dd9..6ce570484 100644 --- a/minuitwrp/graphics_utils.c +++ b/minuitwrp/graphics_utils.cpp @@ -23,7 +23,8 @@ #include "minui.h" struct fb_var_screeninfo vi; -GGLSurface gr_mem_surface; +extern GGLSurface gr_mem_surface; +extern GRSurface* gr_draw; int gr_save_screenshot(const char *dest) { @@ -41,7 +42,11 @@ int gr_save_screenshot(const char *dest) if(!fp) goto exit; - img_data = malloc(gr_mem_surface.stride * vi.yres * 4); + img_data = (uint8_t *)malloc(gr_mem_surface.stride * gr_mem_surface.height * gr_draw->pixel_bytes); + if (!img_data) { + printf("gr_save_screenshot failed to malloc img_data\n"); + goto exit; + } surface.version = sizeof(surface); surface.width = gr_mem_surface.width; surface.height = gr_mem_surface.height; diff --git a/minuitwrp/minui.h b/minuitwrp/minui.h index 25a785a5b..018f3274f 100644 --- a/minuitwrp/minui.h +++ b/minuitwrp/minui.h @@ -18,6 +18,16 @@ #define _MINUI_H_ #include "../gui/placement.h" +#include <stdbool.h> + +struct GRSurface { + int width; + int height; + int row_bytes; + int pixel_bytes; + unsigned char* data; + __u32 format; +}; typedef void* gr_surface; typedef unsigned short gr_pixel; @@ -32,7 +42,7 @@ int gr_fb_width(void); int gr_fb_height(void); gr_pixel *gr_fb_data(void); void gr_flip(void); -int gr_fb_blank(int blank); +void gr_fb_blank(bool blank); void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a); void gr_clip(int x, int y, int w, int h); @@ -41,14 +51,7 @@ void gr_fill(int x, int y, int w, int h); void gr_line(int x0, int y0, int x1, int y1, int width); gr_surface gr_render_circle(int radius, unsigned char r, unsigned char g, unsigned char b, unsigned char a); -int gr_textEx(int x, int y, const char *s, void* font); int gr_textEx_scaleW(int x, int y, const char *s, void* pFont, int max_width, int placement, int scale); -int gr_textExW(int x, int y, const char *s, void* font, int max_width); -int gr_textExWH(int x, int y, const char *s, void* pFont, int max_width, int max_height); -static inline int gr_text(int x, int y, const char *s) { return gr_textEx(x, y, s, NULL); } -int gr_measureEx(const char *s, void* font); -static inline int gr_measure(const char *s) { return gr_measureEx(s, NULL); } -int gr_maxExW(const char *s, void* font, int max_width); int gr_getMaxFontHeight(void *font); @@ -86,11 +89,6 @@ int res_create_surface(const char* name, gr_surface* pSurface); void res_free_surface(gr_surface surface); int res_scale_surface(gr_surface source, gr_surface* destination, float scale_w, float scale_h); -// Needed for AOSP: -int ev_wait(int timeout); -void ev_dispatch(void); -int ev_get_input(int fd, short revents, struct input_event *ev); - int vibrate(int timeout_ms); #endif diff --git a/minuitwrp/resources.c b/minuitwrp/resources.cpp index 0e124608e..781df2b06 100644 --- a/minuitwrp/resources.c +++ b/minuitwrp/resources.cpp @@ -15,6 +15,7 @@ */ #include <stdlib.h> +#include <string.h> #include <unistd.h> #include <fcntl.h> @@ -23,32 +24,25 @@ #include <sys/ioctl.h> #include <sys/mman.h> #include <sys/types.h> -#include <string.h> #include <linux/fb.h> #include <linux/kd.h> -#include <pixelflinger/pixelflinger.h> - #include <png.h> -#include "jpeglib.h" - -#include "minui.h" -// libpng gives "undefined reference to 'pow'" errors, and I have no -// idea how to convince the build system to link with -lm. We don't -// need this functionality (it's used for gamma adjustment) so provide -// a dummy implementation to satisfy the linker. -double pow(double x, double y) { - return x; +#include <pixelflinger/pixelflinger.h> +extern "C" { +#include "jpeglib.h" } +#include "minui.h" #define SURFACE_DATA_ALIGNMENT 8 static GGLSurface* malloc_surface(size_t data_size) { - unsigned char* temp = malloc(sizeof(GGLSurface) + data_size + SURFACE_DATA_ALIGNMENT); + size_t size = sizeof(GGLSurface) + data_size + SURFACE_DATA_ALIGNMENT; + unsigned char* temp = reinterpret_cast<unsigned char*>(malloc(size)); if (temp == NULL) return NULL; - GGLSurface* surface = (GGLSurface*) temp; + GGLSurface* surface = reinterpret_cast<GGLSurface*>(temp); surface->data = temp + sizeof(GGLSurface) + (SURFACE_DATA_ALIGNMENT - (sizeof(GGLSurface) % SURFACE_DATA_ALIGNMENT)); return surface; @@ -59,9 +53,10 @@ static int open_png(const char* name, png_structp* png_ptr, png_infop* info_ptr, char resPath[256]; unsigned char header[8]; int result = 0; + int color_type, bit_depth; + size_t bytesRead; snprintf(resPath, sizeof(resPath)-1, TWRES "images/%s.png", name); - printf("open_png %s\n", resPath); resPath[sizeof(resPath)-1] = '\0'; FILE* fp = fopen(resPath, "rb"); if (fp == NULL) { @@ -72,7 +67,7 @@ static int open_png(const char* name, png_structp* png_ptr, png_infop* info_ptr, } } - size_t bytesRead = fread(header, 1, sizeof(header), fp); + bytesRead = fread(header, 1, sizeof(header), fp); if (bytesRead != sizeof(header)) { result = -2; goto exit; @@ -104,13 +99,12 @@ static int open_png(const char* name, png_structp* png_ptr, png_infop* info_ptr, png_set_sig_bytes(*png_ptr, sizeof(header)); png_read_info(*png_ptr, *info_ptr); - int color_type, bit_depth; png_get_IHDR(*png_ptr, *info_ptr, width, height, &bit_depth, &color_type, NULL, NULL, NULL); *channels = png_get_channels(*png_ptr, *info_ptr); - /*if (bit_depth == 8 && *channels == 3 && color_type == PNG_COLOR_TYPE_RGB) { + if (bit_depth == 8 && *channels == 3 && color_type == PNG_COLOR_TYPE_RGB) { // 8-bit RGB images: great, nothing to do. } else if (bit_depth <= 8 && *channels == 1 && color_type == PNG_COLOR_TYPE_GRAY) { // 1-, 2-, 4-, or 8-bit gray images: expand to 8-bit gray. @@ -122,14 +116,8 @@ static int open_png(const char* name, png_structp* png_ptr, png_infop* info_ptr, // general. png_set_palette_to_rgb(*png_ptr); *channels = 3; - } else { - fprintf(stderr, "minui doesn't support PNG depth %d channels %d color_type %d\n", - bit_depth, *channels, color_type); - result = -7; - goto exit; - }*/ - if (color_type == PNG_COLOR_TYPE_PALETTE) { - png_set_palette_to_rgb(png_ptr); + } else if (color_type == PNG_COLOR_TYPE_PALETTE) { + png_set_palette_to_rgb(*png_ptr); } *fpp = fp; @@ -153,12 +141,10 @@ static int open_png(const char* name, png_structp* png_ptr, png_infop* info_ptr, // framebuffer pixel format; they need to be modified if the // framebuffer format changes (but nothing else should). -// Allocate and return a gr_surface sufficient for storing an image of +// Allocate and return a GRSurface* sufficient for storing an image of // the indicated size in the framebuffer pixel format. static GGLSurface* init_display_surface(png_uint_32 width, png_uint_32 height) { - GGLSurface* surface; - - surface = (GGLSurface*) malloc_surface(width * height * 4); + GGLSurface* surface = malloc_surface(width * height * 4); if (surface == NULL) return NULL; surface->version = sizeof(GGLSurface); @@ -222,6 +208,8 @@ int res_create_surface_png(const char* name, gr_surface* pSurface) { png_uint_32 width, height; png_byte channels; FILE* fp; + unsigned char* p_row; + unsigned int y; *pSurface = NULL; @@ -234,8 +222,15 @@ int res_create_surface_png(const char* name, gr_surface* pSurface) { goto exit; } - unsigned char* p_row = malloc(width * 4); - unsigned int y; +#if defined(RECOVERY_ABGR) || defined(RECOVERY_BGRA) + png_set_bgr(png_ptr); +#endif + + p_row = reinterpret_cast<unsigned char*>(malloc(width * 4)); + if (p_row == NULL) { + result = -9; + goto exit; + } for (y = 0; y < height; ++y) { png_read_row(png_ptr, p_row, NULL); transform_rgb_to_draw(p_row, surface->data + y * width * 4, channels, width); @@ -258,9 +253,11 @@ int res_create_surface_png(const char* name, gr_surface* pSurface) { int res_create_surface_jpg(const char* name, gr_surface* pSurface) { GGLSurface* surface = NULL; - int result = 0; + int result = 0, y; struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; + unsigned char* pData; + size_t width, height, stride, pixelSize; FILE* fp = fopen(name, "rb"); if (fp == NULL) { @@ -288,18 +285,19 @@ int res_create_surface_jpg(const char* name, gr_surface* pSurface) { /* Start decompressor */ (void) jpeg_start_decompress(&cinfo); - size_t width = cinfo.image_width; - size_t height = cinfo.image_height; - size_t stride = 4 * width; - size_t pixelSize = stride * height; + width = cinfo.image_width; + height = cinfo.image_height; + stride = 4 * width; + pixelSize = stride * height; - surface = malloc(sizeof(GGLSurface) + pixelSize); + surface = reinterpret_cast<GGLSurface*>(malloc(sizeof(GGLSurface) + pixelSize)); + //p_row = reinterpret_cast<unsigned char*>(malloc(width * 4)); if (surface == NULL) { result = -8; goto exit; } - unsigned char* pData = (unsigned char*) (surface + 1); + pData = (unsigned char*) (surface + 1); surface->version = sizeof(GGLSurface); surface->width = width; surface->height = height; @@ -307,7 +305,6 @@ int res_create_surface_jpg(const char* name, gr_surface* pSurface) { surface->data = pData; surface->format = GGL_PIXEL_FORMAT_RGBX_8888; - int y; for (y = 0; y < (int) height; ++y) { unsigned char* pRow = pData + y * stride; jpeg_read_scanlines(&cinfo, &pRow, 1); @@ -320,10 +317,17 @@ int res_create_surface_jpg(const char* name, gr_surface* pSurface) { unsigned char g = pRow[sx + 1]; unsigned char b = pRow[sx + 2]; unsigned char a = 0xff; +#if defined(RECOVERY_ABGR) || defined(RECOVERY_BGRA) + pRow[dx ] = b; // r + pRow[dx + 1] = g; // g + pRow[dx + 2] = r; // b + pRow[dx + 3] = a; +#else pRow[dx ] = r; // r pRow[dx + 1] = g; // g pRow[dx + 2] = b; // b pRow[dx + 3] = a; +#endif } } *pSurface = (gr_surface) surface; diff --git a/minuitwrp/truetype.c b/minuitwrp/truetype.cpp index d9ed0198b..18635a886 100644 --- a/minuitwrp/truetype.c +++ b/minuitwrp/truetype.cpp @@ -88,8 +88,8 @@ static const uint32_t offset_basis = 2166136261U; static uint32_t fnv_hash(void *data, uint32_t len) { - uint8_t *d8 = data; - uint32_t *d32 = data; + uint8_t *d8 = (uint8_t *)data; + uint32_t *d32 = (uint32_t *)data; uint32_t i, max; uint32_t hash = offset_basis; @@ -118,12 +118,12 @@ static inline uint32_t fnv_hash_add(uint32_t cur_hash, uint32_t word) return cur_hash; } -int utf8_to_unicode(unsigned char* pIn, unsigned int *pOut) +int utf8_to_unicode(const char* pIn, unsigned int *pOut) { int utf_bytes = 1; unsigned int unicode = 0; unsigned char tmp; - tmp = *pIn++; + tmp = (unsigned char)*pIn++; if (tmp < 0x80) { *pOut = tmp; @@ -157,27 +157,27 @@ int utf8_to_unicode(unsigned char* pIn, unsigned int *pOut) static bool gr_ttf_string_cache_equals(void *keyA, void *keyB) { - StringCacheKey *a = keyA; - StringCacheKey *b = keyB; + StringCacheKey *a = (StringCacheKey *)keyA; + StringCacheKey *b = (StringCacheKey *)keyB; return a->max_width == b->max_width && strcmp(a->text, b->text) == 0; } static int gr_ttf_string_cache_hash(void *key) { - StringCacheKey *k = key; + StringCacheKey *k = (StringCacheKey *)key; return fnv_hash(k->text, strlen(k->text)); } static bool gr_ttf_font_cache_equals(void *keyA, void *keyB) { - TrueTypeFontKey *a = keyA; - TrueTypeFontKey *b = keyB; + TrueTypeFontKey *a = (TrueTypeFontKey *)keyA; + TrueTypeFontKey *b = (TrueTypeFontKey *)keyB; return (a->size == b->size) && (a->dpi == b->dpi) && !strcmp(a->path, b->path); } static int gr_ttf_font_cache_hash(void *key) { - TrueTypeFontKey *k = key; + TrueTypeFontKey *k = (TrueTypeFontKey *)key; uint32_t hash = fnv_hash(k->path, strlen(k->path)); hash = fnv_hash_add(hash, k->size); @@ -189,6 +189,7 @@ void *gr_ttf_loadFont(const char *filename, int size, int dpi) { int error; TrueTypeFont *res = NULL; + TrueTypeFontKey *key = NULL; pthread_mutex_lock(&font_data.mutex); @@ -200,7 +201,7 @@ void *gr_ttf_loadFont(const char *filename, int size, int dpi) .path = (char*)filename }; - res = hashmapGet(font_data.fonts, &k); + res = (TrueTypeFont *)hashmapGet(font_data.fonts, &k); if(res) { ++res->refcount; @@ -234,7 +235,7 @@ void *gr_ttf_loadFont(const char *filename, int size, int dpi) goto exit; } - res = malloc(sizeof(TrueTypeFont)); + res = (TrueTypeFont *)malloc(sizeof(TrueTypeFont)); memset(res, 0, sizeof(TrueTypeFont)); res->type = FONT_TYPE_TTF; res->size = size; @@ -250,7 +251,7 @@ void *gr_ttf_loadFont(const char *filename, int size, int dpi) if(!font_data.fonts) font_data.fonts = hashmapCreate(4, gr_ttf_font_cache_hash, gr_ttf_font_cache_equals); - TrueTypeFontKey *key = malloc(sizeof(TrueTypeFontKey)); + key = (TrueTypeFontKey *)malloc(sizeof(TrueTypeFontKey)); memset(key, 0, sizeof(TrueTypeFontKey)); key->path = strdup(filename); key->size = size; @@ -270,7 +271,7 @@ void *gr_ttf_scaleFont(void *font, int max_width, int measured_width) if (!font) return NULL; - TrueTypeFont *f = font; + TrueTypeFont *f = (TrueTypeFont *)font; float scale_value = (float)(max_width) / (float)(measured_width); int new_size = ((int)((float)f->size * scale_value)) - 1; if (new_size < 1) @@ -280,22 +281,22 @@ void *gr_ttf_scaleFont(void *font, int max_width, int measured_width) return gr_ttf_loadFont(file, new_size, dpi); } -static bool gr_ttf_freeFontCache(void *key, void *value, void *context) +static bool gr_ttf_freeFontCache(void *key, void *value, void *context __unused) { - TrueTypeCacheEntry *e = value; + TrueTypeCacheEntry *e = (TrueTypeCacheEntry *)value; FT_Done_Glyph((FT_Glyph)e->glyph); free(e); free(key); return true; } -static bool gr_ttf_freeStringCache(void *key, void *value, void *context) +static bool gr_ttf_freeStringCache(void *key, void *value, void *context __unused) { - StringCacheKey *k = key; + StringCacheKey *k = (StringCacheKey *)key; free(k->text); free(k); - StringCacheEntry *e = value; + StringCacheEntry *e = (StringCacheEntry *)value; free(e->surface.data); free(e); return true; @@ -305,7 +306,7 @@ void gr_ttf_freeFont(void *font) { pthread_mutex_lock(&font_data.mutex); - TrueTypeFont *d = font; + TrueTypeFont *d = (TrueTypeFont *)font; if(--d->refcount == 0) { @@ -334,12 +335,12 @@ void gr_ttf_freeFont(void *font) static TrueTypeCacheEntry *gr_ttf_glyph_cache_peek(TrueTypeFont *font, int char_index) { - return hashmapGet(font->glyph_cache, &char_index); + return (TrueTypeCacheEntry *)hashmapGet(font->glyph_cache, &char_index); } static TrueTypeCacheEntry *gr_ttf_glyph_cache_get(TrueTypeFont *font, int char_index) { - TrueTypeCacheEntry *res = hashmapGet(font->glyph_cache, &char_index); + TrueTypeCacheEntry *res = (TrueTypeCacheEntry *)hashmapGet(font->glyph_cache, &char_index); if(!res) { int error = FT_Load_Glyph(font->face, char_index, FT_LOAD_RENDER); @@ -357,12 +358,12 @@ static TrueTypeCacheEntry *gr_ttf_glyph_cache_get(TrueTypeFont *font, int char_i return NULL; } - res = malloc(sizeof(TrueTypeCacheEntry)); + res = (TrueTypeCacheEntry *)malloc(sizeof(TrueTypeCacheEntry)); memset(res, 0, sizeof(TrueTypeCacheEntry)); res->glyph = glyph; FT_Glyph_Get_CBox((FT_Glyph)glyph, FT_GLYPH_BBOX_PIXELS, &res->bbox); - int *key = malloc(sizeof(int)); + int *key = (int *)malloc(sizeof(int)); *key = char_index; hashmapPut(font->glyph_cache, key, res); @@ -373,7 +374,7 @@ static TrueTypeCacheEntry *gr_ttf_glyph_cache_get(TrueTypeFont *font, int char_i static int gr_ttf_copy_glyph_to_surface(GGLSurface *dest, FT_BitmapGlyph glyph, int offX, int offY, int base) { - int y; + unsigned y; uint8_t *src_itr = glyph->bitmap.buffer; uint8_t *dest_itr = dest->data; @@ -467,7 +468,7 @@ static int gr_ttf_render_text(TrueTypeFont *font, GGLSurface *surface, const cha int *char_idxs; int char_idxs_len = 0; - char_idxs = malloc(strlen(text) * sizeof(int)); + char_idxs = (int *)malloc(strlen(text) * sizeof(int)); while(*text_itr) { @@ -509,7 +510,7 @@ static int gr_ttf_render_text(TrueTypeFont *font, GGLSurface *surface, const cha height = font->max_height; - data = malloc(total_w*height); + data = (uint8_t *)malloc(total_w*height); memset(data, 0, total_w*height); x = 0; prev_idx = 0; @@ -518,7 +519,7 @@ static int gr_ttf_render_text(TrueTypeFont *font, GGLSurface *surface, const cha surface->width = total_w; surface->height = height; surface->stride = total_w; - surface->data = (void*)data; + surface->data = (GGLubyte*)data; surface->format = GGL_PIXEL_FORMAT_A_8; for(i = 0; i < char_idxs_len; ++i) @@ -552,7 +553,7 @@ static StringCacheEntry *gr_ttf_string_cache_peek(TrueTypeFont *font, const char .max_width = max_width }; - return hashmapGet(font->string_cache, &k); + return (StringCacheEntry *)hashmapGet(font->string_cache, &k); } static StringCacheEntry *gr_ttf_string_cache_get(TrueTypeFont *font, const char *text, int max_width) @@ -563,10 +564,10 @@ static StringCacheEntry *gr_ttf_string_cache_get(TrueTypeFont *font, const char .max_width = max_width }; - res = hashmapGet(font->string_cache, &k); + res = (StringCacheEntry *)hashmapGet(font->string_cache, &k); if(!res) { - res = malloc(sizeof(StringCacheEntry)); + res = (StringCacheEntry *)malloc(sizeof(StringCacheEntry)); memset(res, 0, sizeof(StringCacheEntry)); res->rendered_bytes = gr_ttf_render_text(font, &res->surface, text, max_width); if(res->rendered_bytes < 0) @@ -575,7 +576,7 @@ static StringCacheEntry *gr_ttf_string_cache_get(TrueTypeFont *font, const char return NULL; } - StringCacheKey *new_key = malloc(sizeof(StringCacheKey)); + StringCacheKey *new_key = (StringCacheKey *)malloc(sizeof(StringCacheKey)); memset(new_key, 0, sizeof(StringCacheKey)); new_key->max_width = max_width; new_key->text = strdup(text); @@ -633,11 +634,11 @@ static StringCacheEntry *gr_ttf_string_cache_get(TrueTypeFont *font, const char int gr_ttf_measureEx(const char *s, void *font) { - TrueTypeFont *f = font; + TrueTypeFont *f = (TrueTypeFont *)font; int res = -1; pthread_mutex_lock(&f->mutex); - StringCacheEntry *e = gr_ttf_string_cache_get(font, s, -1); + StringCacheEntry *e = gr_ttf_string_cache_get(f, s, -1); if(e) res = e->surface.width; pthread_mutex_unlock(&f->mutex); @@ -647,7 +648,7 @@ int gr_ttf_measureEx(const char *s, void *font) int gr_ttf_maxExW(const char *s, void *font, int max_width) { - TrueTypeFont *f = font; + TrueTypeFont *f = (TrueTypeFont *)font; TrueTypeCacheEntry *ent; int max_bytes = 0, total_w = 0; int utf_bytes, prev_utf_bytes = 0; @@ -658,7 +659,7 @@ int gr_ttf_maxExW(const char *s, void *font, int max_width) pthread_mutex_lock(&f->mutex); - e = gr_ttf_string_cache_peek(font, s, max_width); + e = gr_ttf_string_cache_peek(f, s, max_width); if(e) { max_bytes = e->rendered_bytes; @@ -699,8 +700,8 @@ int gr_ttf_maxExW(const char *s, void *font, int max_width) int gr_ttf_textExWH(void *context, int x, int y, const char *s, void *pFont, int max_width, int max_height) { - GGLContext *gl = context; - TrueTypeFont *font = pFont; + GGLContext *gl = (GGLContext *)context; + TrueTypeFont *font = (TrueTypeFont *)pFont; // not actualy max width, but max_width + x if(max_width != -1) @@ -749,7 +750,7 @@ int gr_ttf_textExWH(void *context, int x, int y, const char *s, void *pFont, int int gr_ttf_getMaxFontHeight(void *font) { int res; - TrueTypeFont *f = font; + TrueTypeFont *f = (TrueTypeFont *)font; pthread_mutex_lock(&f->mutex); @@ -761,19 +762,19 @@ int gr_ttf_getMaxFontHeight(void *font) return res; } -static bool gr_ttf_dump_stats_count_string_cache(void *key, void *value, void *context) +static bool gr_ttf_dump_stats_count_string_cache(void *key __unused, void *value, void *context) { - int *string_cache_size = context; - StringCacheEntry *e = value; + int *string_cache_size = (int *)context; + StringCacheEntry *e = (StringCacheEntry *)value; *string_cache_size += e->surface.height*e->surface.width + sizeof(StringCacheEntry); return true; } static bool gr_ttf_dump_stats_font(void *key, void *value, void *context) { - TrueTypeFontKey *k = key; - TrueTypeFont *f = value; - int *total_string_cache_size = context; + TrueTypeFontKey *k = (TrueTypeFontKey *)key; + TrueTypeFont *f = (TrueTypeFont *)value; + int *total_string_cache_size = (int *)context; int string_cache_size = 0; pthread_mutex_lock(&f->mutex); |