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
This commit is contained in:
Aaron Kling
2020-10-19 22:08:25 +00:00
committed by bigbiff
parent bff7617e2f
commit 4eccd9a1c6
5 changed files with 109 additions and 85 deletions
+58 -44
View File
@@ -31,6 +31,7 @@
#include <time.h>
#include <cutils/properties.h>
#include <pixelflinger/pixelflinger.h>
#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;
}
+3 -3
View File
@@ -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;
+17 -2
View File
@@ -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, \
+3 -10
View File
@@ -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);
Executable → Regular
+28 -26
View File
@@ -28,6 +28,8 @@
#include <string>
#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;
}