From 4eccd9a1c63ddcae5f7b5052f9c705a677e14d67 Mon Sep 17 00:00:00 2001 From: Aaron Kling Date: Sun, 30 Jun 2019 12:20:09 -0500 Subject: [PATCH] Choose hwrotation at runtime If the prop persist.twrp.rotation is set to 0, 90, 180, or 270, that will be used. If the prop is not set, the existing rotation board config flags will be honored. Note: This flag will only rotate graphics. If a set of devices needs differing touch rotation, that support will need added separately. Change-Id: I6996c07bc0ae7bb8555b3d480b2917a17a365eb3 --- minuitwrp/graphics.cpp | 102 +++++++++++++++++++-------------- minuitwrp/graphics_overlay.cpp | 6 +- minuitwrp/graphics_utils.cpp | 19 +++++- minuitwrp/minui.h | 13 +---- minuitwrp/truetype.cpp | 54 ++++++++--------- 5 files changed, 109 insertions(+), 85 deletions(-) mode change 100755 => 100644 minuitwrp/truetype.cpp diff --git a/minuitwrp/graphics.cpp b/minuitwrp/graphics.cpp index 8abf8eb7..35ffaebb 100755 --- a/minuitwrp/graphics.cpp +++ b/minuitwrp/graphics.cpp @@ -31,6 +31,7 @@ #include +#include #include #include "../gui/placement.h" #include "minui.h" @@ -61,6 +62,8 @@ static GGLContext *gr_context = 0; GGLSurface gr_mem_surface; static int gr_is_curr_clr_opaque = 0; +unsigned int gr_rotation = 0; + int gr_textEx_scaleW(int x, int y, const char *s, void* pFont, int max_width, int placement, int scale) { GGLContext *gl = gr_context; @@ -115,17 +118,20 @@ void gr_clip(int x, int y, int w, int h) { GGLContext *gl = gr_context; -#if TW_ROTATION == 0 - gl->scissor(gl, x, y, w, h); -#elif TW_ROTATION == 90 - gl->scissor(gl, gr_draw->width - y - h, x, h, w); -#elif TW_ROTATION == 270 - gl->scissor(gl, y, gr_draw->height - x - w, h, w); -#else - int t_disp = gr_draw->height - y - h; - int l_disp = gr_draw->width - x - w; - gl->scissor(gl, l_disp, t_disp, w, h); -#endif + switch (gr_rotation) { + case 90: + gl->scissor(gl, gr_draw->width - y - h, x, h, w); + break; + case 180: + gl->scissor(gl, gr_draw->width - x - w, gr_draw->height - y - h, w, h); + break; + case 270: + gl->scissor(gl, y, gr_draw->height - x - w, h, w); + break; + default: + gl->scissor(gl, x, y, w, h); + break; + } gl->enable(gl, GGL_SCISSOR_TEST); } @@ -143,10 +149,10 @@ void gr_line(int x0, int y0, int x1, int y1, int width) GGLContext *gl = gr_context; int x0_disp, y0_disp, x1_disp, y1_disp; - x0_disp = ROTATION_X_DISP(x0, y0, gr_draw); - y0_disp = ROTATION_Y_DISP(x0, y0, gr_draw); - x1_disp = ROTATION_X_DISP(x1, y1, gr_draw); - y1_disp = ROTATION_Y_DISP(x1, y1, gr_draw); + x0_disp = ROTATION_X_DISP(x0, y0, gr_draw->width); + y0_disp = ROTATION_Y_DISP(x0, y0, gr_draw->height); + x1_disp = ROTATION_X_DISP(x1, y1, gr_draw->width); + y1_disp = ROTATION_Y_DISP(x1, y1, gr_draw->height); if(gr_is_curr_clr_opaque) gl->disable(gl, GGL_BLEND); @@ -246,10 +252,10 @@ void gr_fill(int x, int y, int w, int h) if(gr_is_curr_clr_opaque) gl->disable(gl, GGL_BLEND); - x0_disp = ROTATION_X_DISP(x, y, gr_draw); - y0_disp = ROTATION_Y_DISP(x, y, gr_draw); - x1_disp = ROTATION_X_DISP(x + w, y + h, gr_draw); - y1_disp = ROTATION_Y_DISP(x + w, y + h, gr_draw); + x0_disp = ROTATION_X_DISP(x, y, gr_draw->width); + y0_disp = ROTATION_Y_DISP(x, y, gr_draw->height); + x1_disp = ROTATION_X_DISP(x + w, y + h, gr_draw->width); + y1_disp = ROTATION_Y_DISP(x + w, y + h, gr_draw->height); l_disp = std::min(x0_disp, x1_disp); r_disp = std::max(x0_disp, x1_disp); t_disp = std::min(y0_disp, y1_disp); @@ -276,35 +282,36 @@ void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy) int dx0_disp, dy0_disp, dx1_disp, dy1_disp; int l_disp, r_disp, t_disp, b_disp; - // Figuring out display coordinates works for TW_ROTATION == 0 too, + // Figuring out display coordinates works for gr_rotation == 0 too, // and isn't as expensive as allocating and rotating another surface, // so we do this anyway. - dx0_disp = ROTATION_X_DISP(dx, dy, gr_draw); - dy0_disp = ROTATION_Y_DISP(dx, dy, gr_draw); - dx1_disp = ROTATION_X_DISP(dx + w, dy + h, gr_draw); - dy1_disp = ROTATION_Y_DISP(dx + w, dy + h, gr_draw); + dx0_disp = ROTATION_X_DISP(dx, dy, gr_draw->width); + dy0_disp = ROTATION_Y_DISP(dx, dy, gr_draw->height); + dx1_disp = ROTATION_X_DISP(dx + w, dy + h, gr_draw->width); + dy1_disp = ROTATION_Y_DISP(dx + w, dy + h, gr_draw->height); l_disp = std::min(dx0_disp, dx1_disp); r_disp = std::max(dx0_disp, dx1_disp); t_disp = std::min(dy0_disp, dy1_disp); b_disp = std::max(dy0_disp, dy1_disp); -#if TW_ROTATION != 0 - // Do not perform relatively expensive operation if not needed GGLSurface surface_rotated; - surface_rotated.version = sizeof(surface_rotated); - // Skip the **(TW_ROTATION == 0)** || (TW_ROTATION == 180) check - // because we are under a TW_ROTATION != 0 conditional compilation statement - surface_rotated.width = (TW_ROTATION == 180) ? surface->width : surface->height; - surface_rotated.height = (TW_ROTATION == 180) ? surface->height : surface->width; - surface_rotated.stride = surface_rotated.width; - surface_rotated.format = surface->format; - surface_rotated.data = (GGLubyte*) malloc(surface_rotated.stride * surface_rotated.height * 4); - surface_ROTATION_transform((gr_surface) &surface_rotated, (const gr_surface) surface, 4); + if (gr_rotation != 0) { + // Do not perform relatively expensive operation if not needed + surface_rotated.version = sizeof(surface_rotated); + // Skip the **(gr_rotation == 0)** || (gr_rotation == 180) check + // because we are under a gr_rotation != 0 conditional compilation statement + surface_rotated.width = (gr_rotation == 180) ? surface->width : surface->height; + surface_rotated.height = (gr_rotation == 180) ? surface->height : surface->width; + surface_rotated.stride = surface_rotated.width; + surface_rotated.format = surface->format; + surface_rotated.data = (GGLubyte*) malloc(surface_rotated.stride * surface_rotated.height * 4); + surface_ROTATION_transform((gr_surface) &surface_rotated, (const gr_surface) surface, 4); + + gl->bindTexture(gl, &surface_rotated); + } else { + gl->bindTexture(gl, surface); + } - gl->bindTexture(gl, &surface_rotated); -#else - gl->bindTexture(gl, surface); -#endif 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); @@ -313,9 +320,8 @@ void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy) gl->recti(gl, l_disp, t_disp, r_disp, b_disp); gl->disable(gl, GGL_TEXTURE_2D); -#if TW_ROTATION != 0 - free(surface_rotated.data); -#endif + if (gr_rotation != 0) + free(surface_rotated.data); if(surface->format == GGL_PIXEL_FORMAT_RGBX_8888) gl->enable(gl, GGL_BLEND); @@ -356,6 +362,14 @@ int gr_init(void) { gr_draw = NULL; + char gr_rotation_string[PROPERTY_VALUE_MAX]; + char default_rotation[4]; + snprintf(default_rotation, 4, "%d", TW_ROTATION); + property_get("persist.twrp.rotation", gr_rotation_string, default_rotation); + gr_rotation = atoi(gr_rotation_string); + if (!(gr_rotation == 90 || gr_rotation == 180 || gr_rotation == 270)) + gr_rotation = 0; + #ifdef MSM_BSP gr_backend = open_overlay(); if (gr_backend) { @@ -438,14 +452,14 @@ void gr_exit(void) int gr_fb_width(void) { - return (TW_ROTATION == 0 || TW_ROTATION == 180) ? + return (gr_rotation == 0 || gr_rotation == 180) ? gr_draw->width - 2 * overscan_offset_x : gr_draw->height - 2 * overscan_offset_y; } int gr_fb_height(void) { - return (TW_ROTATION == 0 || TW_ROTATION == 180) ? + return (gr_rotation == 0 || gr_rotation == 180) ? gr_draw->height - 2 * overscan_offset_y : gr_draw->width - 2 * overscan_offset_x; } diff --git a/minuitwrp/graphics_overlay.cpp b/minuitwrp/graphics_overlay.cpp index 4dff7f4a..a53faa86 100644 --- a/minuitwrp/graphics_overlay.cpp +++ b/minuitwrp/graphics_overlay.cpp @@ -324,7 +324,7 @@ int allocate_overlay(int fd, GRSurface gr_fb) overlayL.dst_rect.h = gr_fb.height; overlayL.alpha = 0xFF; // If this worked, life would have been so much easier - //switch (TW_ROTATION) { + //switch (gr_rotation) { //case 0: overlayL.flags = MDP_ROT_NOP; break; //case 90: overlayL.flags = MDP_ROT_90; break; //case 180: overlayL.flags = MDP_ROT_180; break; @@ -368,7 +368,7 @@ int allocate_overlay(int fd, GRSurface gr_fb) overlayL.dst_rect.h = height; overlayL.alpha = 0xFF; // If this worked, life would have been so much easier - //switch (TW_ROTATION) { + //switch (gr_rotation) { //case 0: overlayL.flags = MDP_ROT_NOP; break; //case 90: overlayL.flags = MDP_ROT_90; break; //case 180: overlayL.flags = MDP_ROT_180; break; @@ -403,7 +403,7 @@ int allocate_overlay(int fd, GRSurface gr_fb) overlayR.alpha = 0xFF; overlayR.flags = MDSS_MDP_RIGHT_MIXER; // If this worked, life would have been so much easier - //switch (TW_ROTATION) { + //switch (gr_rotation) { //case 0: overlayR.flags |= MDP_ROT_NOP; break; //case 90: overlayR.flags |= MDP_ROT_90; break; //case 180: overlayR.flags |= MDP_ROT_180; break; diff --git a/minuitwrp/graphics_utils.cpp b/minuitwrp/graphics_utils.cpp index c591e539..0bc86828 100644 --- a/minuitwrp/graphics_utils.cpp +++ b/minuitwrp/graphics_utils.cpp @@ -26,6 +26,7 @@ struct fb_var_screeninfo vi; extern GGLSurface gr_mem_surface; extern GRSurface* gr_draw; +extern unsigned int gr_rotation; int gr_save_screenshot(const char *dest) { @@ -123,6 +124,20 @@ exit: return res; } +int ROTATION_X_DISP(int x, int y, int w) { + return ((gr_rotation == 0) ? (x) : + (gr_rotation == 90) ? (w - (y) - 1) : + (gr_rotation == 180) ? (w - (x) - 1) : + (gr_rotation == 270) ? (y) : -1); +} + +int ROTATION_Y_DISP(int x, int y, int h) { + return ((gr_rotation == 0) ? (y) : + (gr_rotation == 90) ? (x) : + (gr_rotation == 180) ? (h - (y) - 1) : + (gr_rotation == 270) ? (h - (x) - 1) : -1); +} + #define MATRIX_ELEMENT(matrix, row, col, row_size, elem_size) \ (((uint8_t*) (matrix)) + (((row) * (elem_size)) * (row_size)) + ((col) * (elem_size))) @@ -135,8 +150,8 @@ exit: /* input pointer from src->data */ \ const uint##bits_per_pixel##_t *ip; \ /* Display coordinates (in dst) corresponding to (x, y) in src */ \ - size_t x_disp = ROTATION_X_DISP(x, y, dst); \ - size_t y_disp = ROTATION_Y_DISP(x, y, dst); \ + size_t x_disp = ROTATION_X_DISP(x, y, dst->width); \ + size_t y_disp = ROTATION_Y_DISP(x, y, dst->height); \ \ ip = (const uint##bits_per_pixel##_t*) \ MATRIX_ELEMENT(src->data, y, x, \ diff --git a/minuitwrp/minui.h b/minuitwrp/minui.h index 2c462e75..a6c2a712 100644 --- a/minuitwrp/minui.h +++ b/minuitwrp/minui.h @@ -76,16 +76,9 @@ int gr_save_screenshot(const char *dest); // Transform minuitwrp API coordinates into display coordinates, // for panels that are hardware-mounted in a rotated manner. -#define ROTATION_X_DISP(x, y, surface) \ - ((TW_ROTATION == 0) ? (x) : \ - (TW_ROTATION == 90) ? ((surface)->width - (y) - 1) : \ - (TW_ROTATION == 180) ? ((surface)->width - (x) - 1) : \ - (TW_ROTATION == 270) ? (y) : -1) -#define ROTATION_Y_DISP(x, y, surface) \ - ((TW_ROTATION == 0) ? (y) : \ - (TW_ROTATION == 90) ? (x) : \ - (TW_ROTATION == 180) ? ((surface)->height - (y) - 1) : \ - (TW_ROTATION == 270) ? ((surface)->height - (x) - 1) : -1) +int ROTATION_X_DISP(int x, int y, int w); + +int ROTATION_Y_DISP(int x, int y, int h); void surface_ROTATION_transform(gr_surface dst_ptr, const gr_surface src_ptr, size_t num_bytes_per_pixel); diff --git a/minuitwrp/truetype.cpp b/minuitwrp/truetype.cpp old mode 100755 new mode 100644 index 86954325..9ab8c7a0 --- a/minuitwrp/truetype.cpp +++ b/minuitwrp/truetype.cpp @@ -28,6 +28,8 @@ #include #include "truetype.hpp" +extern unsigned int gr_rotation; + static FontData font_data = { .ft_library = NULL, .mutex = PTHREAD_MUTEX_INITIALIZER @@ -568,20 +570,20 @@ int twrpTruetype::gr_ttf_textExWH(void *context, int x, int y, return -1; } -#if TW_ROTATION != 0 - // Do not perform relatively expensive operation if not needed GGLSurface string_surface_rotated; - string_surface_rotated.version = sizeof(string_surface_rotated); - // Skip the **(TW_ROTATION == 0)** || (TW_ROTATION == 180) check - // because we are under a TW_ROTATION != 0 conditional compilation statement - string_surface_rotated.width = (TW_ROTATION == 180) ? e->surface.width : e->surface.height; - string_surface_rotated.height = (TW_ROTATION == 180) ? e->surface.height : e->surface.width; - string_surface_rotated.stride = string_surface_rotated.width; - string_surface_rotated.format = e->surface.format; - // e->surface.format is GGL_PIXEL_FORMAT_A_8 (grayscale) - string_surface_rotated.data = (GGLubyte*) malloc(string_surface_rotated.stride * string_surface_rotated.height * 1); - surface_ROTATION_transform((gr_surface) &string_surface_rotated, (const gr_surface) &e->surface, 1); -#endif + if (gr_rotation != 0) { + // Do not perform relatively expensive operation if not needed + string_surface_rotated.version = sizeof(string_surface_rotated); + // Skip the **(gr_rotation == 0)** || (gr_rotation == 180) check + // because we are under a gr_rotation != 0 conditional compilation statement + string_surface_rotated.width = (gr_rotation == 180) ? e->surface.width : e->surface.height; + string_surface_rotated.height = (gr_rotation == 180) ? e->surface.height : e->surface.width; + string_surface_rotated.stride = string_surface_rotated.width; + string_surface_rotated.format = e->surface.format; + // e->surface.format is GGL_PIXEL_FORMAT_A_8 (grayscale) + string_surface_rotated.data = (GGLubyte*) malloc(string_surface_rotated.stride * string_surface_rotated.height * 1); + surface_ROTATION_transform((gr_surface) &string_surface_rotated, (const gr_surface) &e->surface, 1); + } int y_bottom = y + e->surface.height; int res = e->rendered_bytes; @@ -596,26 +598,26 @@ int twrpTruetype::gr_ttf_textExWH(void *context, int x, int y, } } - // Figuring out display coordinates works for TW_ROTATION == 0 too, + // Figuring out display coordinates works for gr_rotation == 0 too, // and isn't as expensive as allocating and rotating another surface, // so we do this anyway. int x0_disp, y0_disp, x1_disp, y1_disp; int l_disp, r_disp, t_disp, b_disp; - x0_disp = ROTATION_X_DISP(x, y, gr_draw); - y0_disp = ROTATION_Y_DISP(x, y, gr_draw); - x1_disp = ROTATION_X_DISP(x + e->surface.width, y_bottom, gr_draw); - y1_disp = ROTATION_Y_DISP(x + e->surface.width, y_bottom, gr_draw); + x0_disp = ROTATION_X_DISP(x, y, gr_draw->width); + y0_disp = ROTATION_Y_DISP(x, y, gr_draw->height); + x1_disp = ROTATION_X_DISP(x + e->surface.width, y_bottom, gr_draw->width); + y1_disp = ROTATION_Y_DISP(x + e->surface.width, y_bottom, gr_draw->height); l_disp = std::min(x0_disp, x1_disp); r_disp = std::max(x0_disp, x1_disp); t_disp = std::min(y0_disp, y1_disp); b_disp = std::max(y0_disp, y1_disp); -#if TW_ROTATION != 0 - gl->bindTexture(gl, &string_surface_rotated); -#else - gl->bindTexture(gl, &e->surface); -#endif + if (gr_rotation != 0) { + gl->bindTexture(gl, &string_surface_rotated); + } else { + gl->bindTexture(gl, &e->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); @@ -625,9 +627,9 @@ int twrpTruetype::gr_ttf_textExWH(void *context, int x, int y, gl->recti(gl, l_disp, t_disp, r_disp, b_disp); gl->disable(gl, GGL_TEXTURE_2D); -#if TW_ROTATION != 0 - free(string_surface_rotated.data); -#endif + if (gr_rotation != 0) + free(string_surface_rotated.data); + pthread_mutex_unlock(&font->mutex);; return res; }