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:
+58
-44
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user