summaryrefslogtreecommitdiffstats
path: root/minuitwrp
diff options
context:
space:
mode:
authorEthan Yonker <dees_troy@teamw.in>2015-12-28 21:54:50 +0100
committerEthan Yonker <dees_troy@teamw.in>2016-01-27 17:53:13 +0100
commitfbb4353a247157d32208f8f133cd1ee42f4fbc49 (patch)
tree6f819fbdd21f2adef4f7ba4a5b4d02054cc02f29 /minuitwrp
parentAdopted Storage support (diff)
downloadandroid_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 '')
-rw-r--r--minuitwrp/Android.mk44
-rw-r--r--minuitwrp/events.cpp (renamed from minuitwrp/events.c)2
-rw-r--r--minuitwrp/graphics.c754
-rw-r--r--minuitwrp/graphics.cpp416
-rw-r--r--minuitwrp/graphics.h44
-rw-r--r--minuitwrp/graphics_adf.cpp285
-rw-r--r--minuitwrp/graphics_drm.cpp492
-rw-r--r--minuitwrp/graphics_fbdev.cpp281
-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.h24
-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);