MTK Recovery 模式横屏修改(适用于6.0 + 8.1)
程序员文章站
2022-03-28 12:22:14
修改前 修改后 6.0 Recovery 模式横屏修改方法 修改相关文件 bootable\recovery\minui\Android.mk bootable\recovery\minui\mt_graphic_rotate.cpp bootable\recovery\minui\mt_graph ......
修改前
修改后
6.0 recovery 模式横屏修改方法
修改相关文件
bootable\recovery\minui\android.mk
bootable\recovery\minui\mt_graphic_rotate.cpp
bootable\recovery\minui\mt_graphic_rotate.h
bootable\recovery\minui\graphics_fbdev.cpp
bootable\recovery\minui\minui.h
1、在 android.mk 中增加 mt_graphic_rotate.cpp 编译项
local_src_files := \ events.cpp \ graphics.cpp \ graphics_adf.cpp \ graphics_drm.cpp \ graphics_fbdev.cpp \ resources.cpp \ #cczheng add local_src_files += mt_graphic_rotate.cpp
2、对比修改 mt_graphic_rotate.cpp,没有则直接复制以下类
/* * copyright (c) 2014 mediatek inc. * modification based on code covered by the mentioned copyright * and/or permission notice(s). */ #include <stdbool.h> #include <stdlib.h> #include <unistd.h> #include <inttypes.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" grsurface __gr_canvas; grsurface* gr_canvas = null; int rotate_index=-1; static void print_surface_info(grsurface *s, const char *name) { printf("[graphics] %s > height:%d, width:%d, pixelbytes:%d, rowbytes:%d, size:%d, data: 0x%08" prixptr "\n", name, s->height, s->width, s->pixel_bytes, s->row_bytes, s->height* s->row_bytes, (uintptr_t) s->data); } // read configuration from mtk_lcm_physical_rotation #ifndef mtk_lcm_physical_rotation #define mtk_lcm_physical_rotation "undefined" #endif static int rotate_config(grsurface *gr_draw) { if (rotate_index<0) { if (gr_draw->pixel_bytes != 4) rotate_index=0; // support 4 bytes pixel only else if (0 == strncmp(mtk_lcm_physical_rotation, "90", 2)) rotate_index=1; else if (0 == strncmp(mtk_lcm_physical_rotation, "180", 3)) rotate_index=2; else if (0 == strncmp(mtk_lcm_physical_rotation, "270", 3)) rotate_index=3; else rotate_index=0; printf("[graphics] rotate_config %d %s\n", rotate_index, mtk_lcm_physical_rotation); } return rotate_index; } #define swap(x, y, type) {type z; z=x; x=y; y=z;} // allocate and setup the canvas object void rotate_canvas_init(grsurface *gr_draw) { gr_canvas = &__gr_canvas; memcpy(gr_canvas, gr_draw, sizeof(grsurface)); // swap canvas' height and width, if the rotate angle is 90" or 270" if (rotate_config(gr_draw)%2) { swap(gr_canvas->width, gr_canvas->height, int); gr_canvas->row_bytes = gr_canvas->width * gr_canvas->pixel_bytes; } gr_canvas->data = (unsigned char*) malloc(gr_canvas->height * gr_canvas->row_bytes); if (gr_canvas->data == null) { printf("[graphics] rotate_canvas_init() malloc gr_canvas->data failed\n"); gr_canvas = null; return; } memset(gr_canvas->data, 0, gr_canvas->height * gr_canvas->row_bytes); print_surface_info(gr_draw, "gr_draw"); print_surface_info(gr_canvas, "gr_canvas"); } // cleanup the canvas void rotate_canvas_exit(void) { if (gr_canvas) { if (gr_canvas->data) free(gr_canvas->data); free(gr_canvas); } gr_canvas=null; } // return the canvas object grsurface *rotate_canvas_get(grsurface *gr_draw) { // initialize the canvas, if it was not exist. if (gr_canvas==null) rotate_canvas_init(gr_draw); return gr_canvas; } // surface rotate routines static void rotate_surface_0(grsurface *dst, grsurface *src) { memcpy(dst->data, src->data, src->height*src->row_bytes); } static void rotate_surface_270(grsurface *dst, grsurface *src) { int v, w, h; unsigned int *src_pixel; unsigned int *dst_pixel; for (h=0, v=src->width-1; h<dst->height; h++, v--) { for (w=0; w<dst->width; w++) { dst_pixel = (unsigned int *)(dst->data + dst->row_bytes*h); src_pixel = (unsigned int *)(src->data + src->row_bytes*w); *(dst_pixel+w)=*(src_pixel+v); } } } static void rotate_surface_180(grsurface *dst, grsurface *src) { int v, w, k, h; unsigned int *src_pixel; unsigned int *dst_pixel; for (h=0, k=src->height-1; h<dst->height && k>=0 ; h++, k--) { dst_pixel = (unsigned int *)(dst->data + dst->row_bytes*h); src_pixel = (unsigned int *)(src->data + src->row_bytes*k); for (w=0, v=src->width-1; w<dst->width && v>=0; w++, v--) { *(dst_pixel+w)=*(src_pixel+v); } } } static void rotate_surface_90(grsurface *dst, grsurface *src) { int w, k, h; unsigned int *src_pixel; unsigned int *dst_pixel; for (h=0; h<dst->height; h++) { for (w=0, k=src->height-1; w<dst->width; w++, k--) { dst_pixel = (unsigned int *)(dst->data + dst->row_bytes*h); src_pixel = (unsigned int *)(src->data + src->row_bytes*k); *(dst_pixel+w)=*(src_pixel+h); } } } typedef void (*rotate_surface_t) (grsurface *, grsurface *); rotate_surface_t rotate_func[4]= { rotate_surface_0, rotate_surface_90, rotate_surface_180, rotate_surface_270 }; // rotate and copy src* surface to dst surface void rotate_surface(grsurface *dst, grsurface *src) { rotate_surface_t rotate; rotate=rotate_func[rotate_config(dst)]; rotate(dst, src); }
3、对比修改 mt_graphic_rotate.h,没有则直接复制以下类
/* * copyright (c) 2014 mediatek inc. * modification based on code covered by the mentioned copyright * and/or permission notice(s). */ #ifndef mt_graphics_rotate_h_ #define mt_graphics_rotate_h_ #include "minui.h" void rotate_canvas_exit(void); void rotate_canvas_init(grsurface *gr_draw); void rotate_surface(grsurface *dst, grsurface *src); grsurface *rotate_canvas_get(grsurface *gr_draw); #endif
4、对比修改 graphics_fbdev.cpp,没有则直接复制以下类
/* * 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 "mt_graphic_rotate.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 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) { int ret; ret = ioctl(fb_fd, fbioblank, blank ? fb_blank_powerdown : fb_blank_unblank); if (ret < 0) perror("ioctl(): blank"); } 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); 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; gr_framebuffer[0].data = reinterpret_cast<uint8_t*>(bits); memset(gr_framebuffer[0].data, 0, gr_framebuffer[0].height * gr_framebuffer[0].row_bytes); /* check if we can use double buffering */ printf("[graphics] vi.yres * fi.line_length = %d * %d * 2 = %d, fi.smem_len=%d\n", vi.yres, fi.line_length, vi.yres * fi.line_length * 2, fi.smem_len); if (vi.yres * fi.line_length * 2 <= fi.smem_len) { double_buffered = true; printf("[graphics] 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; gr_draw = gr_framebuffer+1; } else { double_buffered = false; printf("[graphics] without double buffer\n"); // without double-buffering, we allocate ram for a buffer to // draw in, and then "flipping" the buffer consists of a // memcpy from the buffer we allocated to the framebuffer. gr_draw = (grsurface*) malloc(sizeof(grsurface)); memcpy(gr_draw, gr_framebuffer, sizeof(grsurface)); gr_draw->data = (unsigned char*) malloc(gr_draw->height * gr_draw->row_bytes); if (!gr_draw->data) { perror("failed to allocate in-memory surface"); return null; } } memset(gr_draw->data, 0, gr_draw->height * gr_draw->row_bytes); fb_fd = fd; set_displayed_framebuffer(0); printf("framebuffer: %d (%d x %d)\n", fb_fd, gr_draw->width, gr_draw->height); #if 0 // to avoid display blink due to display driver not disable backlight after kernel standardization, so that temp state between display suspend/resume is shown fbdev_blank(backend, true); fbdev_blank(backend, false); #endif return rotate_canvas_get(gr_draw); } static grsurface* fbdev_flip(minui_backend* backend __unused) { rotate_surface(gr_draw, rotate_canvas_get(gr_draw)); 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 // change gr_draw to point to the buffer currently displayed, // then flip the driver so we're displaying the other buffer // instead. gr_draw = gr_framebuffer + displayed_buffer; 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 rotate_canvas_get(gr_draw); } static void fbdev_exit(minui_backend* backend __unused) { close(fb_fd); fb_fd = -1; rotate_canvas_exit(); if (!double_buffered && gr_draw) { free(gr_draw->data); free(gr_draw); } gr_draw = null; }
5、对比修改 minui.h,没有则直接复制以下类
/* * 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. */ #ifndef _minui_h_ #define _minui_h_ #include <sys/types.h> #include <functional> // // graphics. // struct grsurface { int width; int height; int row_bytes; int pixel_bytes; unsigned char* data; }; int gr_init(); void gr_exit(); int gr_fb_width(); int gr_fb_height(); void gr_flip(); void gr_fb_blank(bool blank); void gr_clear(); // clear entire surface to current color void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a); void gr_fill(int x1, int y1, int x2, int y2); void gr_text(int x, int y, const char *s, bool bold); void gr_texticon(int x, int y, grsurface* icon); int gr_measure(const char *s); void gr_font_size(int *x, int *y); void gr_blit(grsurface* source, int sx, int sy, int w, int h, int dx, int dy); unsigned int gr_get_width(grsurface* surface); unsigned int gr_get_height(grsurface* surface); // // input events. // struct input_event; // todo: move these over to std::function. typedef int (*ev_callback)(int fd, uint32_t epevents, void* data); typedef int (*ev_set_key_callback)(int code, int value, void* data); int ev_init(ev_callback input_cb, void* data); void ev_exit(); int ev_add_fd(int fd, ev_callback cb, void* data); void ev_iterate_available_keys(std::function<void(int)> f); int ev_sync_key_state(ev_set_key_callback set_key_cb, void* data); // 'timeout' has the same semantics as poll(2). // 0 : don't block // < 0 : block forever // > 0 : block for 'timeout' milliseconds int ev_wait(int timeout); int ev_get_input(int fd, uint32_t epevents, input_event* ev); void ev_dispatch(); int ev_get_epollfd(); // // resources // // res_create_*_surface() functions return 0 if no error, else // negative. // // a "display" surface is one that is intended to be drawn to the // screen with gr_blit(). an "alpha" surface is a grayscale image // interpreted as an alpha mask used to render text in the current // color (with gr_text() or gr_texticon()). // // all these functions load png images from "/res/images/${name}.png". // load a single display surface from a png image. int res_create_display_surface(const char* name, grsurface** psurface); // load an array of display surfaces from a single png image. the png // should have a 'frames' text chunk whose value is the number of // frames this image represents. the pixel data itself is interlaced // by row. int res_create_multi_display_surface(const char* name, int* frames, grsurface*** psurface); // load a single alpha surface from a grayscale png image. int res_create_alpha_surface(const char* name, grsurface** psurface); // load part of a grayscale png image that is the first match for the // given locale. the image is expected to be a composite of multiple // translations of the same text, with special added rows that encode // the subimages' size and intended locale in the pixel data. see // development/tools/recovery_l10n for an app that will generate these // specialized images from android resources. int res_create_localized_alpha_surface(const char* name, const char* locale, grsurface** psurface); // free a surface allocated by any of the res_create_*_surface() // functions. void res_free_surface(grsurface* surface); #endif
8.1 recovery 模式横屏修改方法
8.1 的修改步骤和 6.0 大体差不多,前三步都一样,请参考上面的,由于 8.1 中不需要 minui.h 文件,所以 mt_graphic_rotate.h 和 mt_graphic_rotate.cpp 中 需要注释
//#include "minui.h"
4、对比修改 graphics_fbdev.cpp
/* * 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 "graphics_fbdev.h" #include <fcntl.h> #include <linux/fb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <sys/types.h> #include <unistd.h> #include "minui/minui.h" //cczheng add for rotatecanvas #include "mt_graphic_rotate.h" minuibackendfbdev::minuibackendfbdev() : gr_draw(nullptr), fb_fd(-1) {} void minuibackendfbdev::blank(bool blank) { int ret = ioctl(fb_fd, fbioblank, blank ? fb_blank_powerdown : fb_blank_unblank); if (ret < 0) perror("ioctl(): blank"); } void minuibackendfbdev::setdisplayedframebuffer(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; } grsurface* minuibackendfbdev::init() { int fd = open("/dev/graphics/fb0", o_rdwr); if (fd == -1) { perror("cannot open fb0"); return nullptr; } fb_fix_screeninfo fi; if (ioctl(fd, fbioget_fscreeninfo, &fi) < 0) { perror("failed to get fb0 info"); close(fd); return nullptr; } if (ioctl(fd, fbioget_vscreeninfo, &vi) < 0) { perror("failed to get fb0 info"); close(fd); return nullptr; } // 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 nullptr; } memset(bits, 0, fi.smem_len); 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; gr_framebuffer[0].data = static_cast<uint8_t*>(bits); memset(gr_framebuffer[0].data, 0, gr_framebuffer[0].height * gr_framebuffer[0].row_bytes); /* check if we can use double buffering */ if (vi.yres * fi.line_length * 2 <= fi.smem_len) { double_buffered = true; 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; gr_draw = gr_framebuffer + 1; } else { double_buffered = false; // without double-buffering, we allocate ram for a buffer to // draw in, and then "flipping" the buffer consists of a // memcpy from the buffer we allocated to the framebuffer. gr_draw = static_cast<grsurface*>(malloc(sizeof(grsurface))); memcpy(gr_draw, gr_framebuffer, sizeof(grsurface)); gr_draw->data = static_cast<unsigned char*>(malloc(gr_draw->height * gr_draw->row_bytes)); if (!gr_draw->data) { perror("failed to allocate in-memory surface"); return nullptr; } } memset(gr_draw->data, 0, gr_draw->height * gr_draw->row_bytes); fb_fd = fd; setdisplayedframebuffer(0); printf("framebuffer: %d (%d x %d)\n", fb_fd, gr_draw->width, gr_draw->height); #if 0 blank(true); blank(false); #endif //return gr_draw; //cczheng add for rotatecanvas return rotate_canvas_get(gr_draw); } grsurface* minuibackendfbdev::flip() { //cczheng add for rotatecanvas rotate_surface(gr_draw, rotate_canvas_get(gr_draw)); if (double_buffered) { // change gr_draw to point to the buffer currently displayed, // then flip the driver so we're displaying the other buffer // instead. gr_draw = gr_framebuffer + displayed_buffer; setdisplayedframebuffer(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; //cczheng add for rotatecanvas return rotate_canvas_get(gr_draw); } minuibackendfbdev::~minuibackendfbdev() { close(fb_fd); fb_fd = -1; //cczheng add for rotatecanvas rotate_canvas_exit(); if (!double_buffered && gr_draw) { free(gr_draw->data); free(gr_draw); } gr_draw = nullptr; }
修改旋转角度,在 mt_graphic_rotate.cpp 中的 rotate_config(grsurface gr_draw)
旋转90度就将 return rotate_index 直接改为 return 1,
依次类推转 180度, 改为 return 2, 270 度改为 return 3.
注意旋转方向为顺时针旋转
我修改的情况对应 return 3.