zoukankan      html  css  js  c++  java
  • MTK Recovery 模式横屏修改(适用于6.0 + 8.1)

    在这里插入图片描述

    修改前

    在这里插入图片描述

    修改后

    6.0 Recovery 模式横屏修改方法

    修改相关文件
    bootable ecoveryminuiAndroid.mk
    bootable ecoveryminuimt_graphic_rotate.cpp
    bootable ecoveryminuimt_graphic_rotate.h
    bootable ecoveryminuigraphics_fbdev.cpp
    bootable ecoveryminuiminui.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 "
    ",
            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
    ", 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
    ");
            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):
    "
               "  vi.bits_per_pixel = %d
    "
               "  vi.red.offset   = %3d   .length = %3d
    "
               "  vi.green.offset = %3d   .length = %3d
    "
               "  vi.blue.offset  = %3d   .length = %3d
    ",
               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
    ",
            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
    ");
    
            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
    ");
            // 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)
    ", 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.hmt_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):
    "
          "  vi.bits_per_pixel = %d
    "
          "  vi.red.offset   = %3d   .length = %3d
    "
          "  vi.green.offset = %3d   .length = %3d
    "
          "  vi.blue.offset  = %3d   .length = %3d
    ",
          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)
    ", 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.

  • 相关阅读:
    Linux Systemcall By INT 0x80、Llinux Kernel Debug Based On Sourcecode
    ELF(Executable and Linkable Format)
    Linux文件权限;ACL;Setuid、Setgid、Stick bit特殊权限;sudo提权
    Linux System Calls Hooking Method Summary
    GCC、Makefile编程学习
    Linux Process/Thread Creation、Linux Process Principle、sys_fork、sys_execve、glibc fork/execve api sourcecode
    Linux中断技术、门描述符、IDT(中断描述符表)、异常控制技术总结归类
    浅议SNMP安全、SNMP协议、网络管理学习
    DNS安全浅议、域名A记录(ANAME),MX记录,CNAME记录
    RIP、OSPF、BGP、动态路由选路协议、自治域AS
  • 原文地址:https://www.cnblogs.com/cczheng-666/p/11528773.html
Copyright © 2011-2022 走看看