Android recovery 模式下屏幕显示旋转

Android recovery 模式下屏幕显示旋转

大家在网上搜索 Android屏幕旋转,成千上万的文章,但是没有几个是写recovery 模式的。难道你们只旋转正常模式下的屏幕方向,不管recovery模式,那升级的画面岂不是有问题。

很对人使用的是MTK平台,对与MTK平台,MTK已经帮你做好了,你只用修改一下配置就行了。
MTK平台我们可以在bootable/recovery/minui/mt_graphic_rotate.cpp 清晰的看到下面的代码:

#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;
}


已经很清楚了,只需要修改 MTK_LCM_PHYSICAL_ROTATION 这个宏就可以了。这是MTK已经改造过的recovery 。
那么其他一些平台 并没有想MTK平台这样,帮你改造好了。比如RK平台,我在RK的代码里只发现了,一个旋转180度的配置,那我要旋转270度怎么办。那就需要自己去看代码了。
recovery 模式 是直接操作 dev目录下的 fb ,如果对这种操作不熟悉的同学需要去补课,不然可能会看不懂我接下来说的。
在 bootable/recovery/minui/graphics_fbdev.c 我们可以看到下面的代码。

static gr_surface fbdev_init(minui_backend* backend) {
    int fd;
    void *bits;
    int tmp = 0;

    struct fb_fix_screeninfo fi;

    fd = open("/dev/graphics/fb0", O_RDWR);
    if (fd < 0) {
        perror("cannot open fb0");
        return NULL;
    }

    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;
    }
//这里是我添加的,调换 高度 和 宽度
#ifdef RotateScreen_270
    tmp = vi.xres;
    vi.xres = vi.yres;
    vi.yres = tmp;
#endif

    vi.red.offset     = 0;
    vi.red.length     = 8;
    vi.green.offset   = 8;
    vi.green.length   = 8;
    vi.blue.offset    = 16;
    vi.blue.length    = 8;
    vi.transp.offset  = 24;
    vi.transp.length  = 8;
    vi.bits_per_pixel = 32;
    vi.nonstd = 2;

    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 = vi.xres * 4;
    gr_framebuffer[0].pixel_bytes = vi.bits_per_pixel / 8;
    gr_framebuffer[0].data = bits;
    memset(gr_framebuffer[0].data, 0, gr_framebuffer[0].height * gr_framebuffer[0].row_bytes);
}


我们看到了 “/dev/graphics/fb0”,相信很多人知道这是什么,这是video buffer,那么所有的 width、height、pixel_bytes、这些信息都来自与内核。而且用到了mmap,我们关心的屏幕相关信息都在这里。我们关心 gr_framebuffer[0].data = bits;,不了解 mmap的同学,请查看其他资料。这个文件里的很多方法,例如 fbdev_init(),fbdev_flip(),返回值都是gr_framebuffer, 其他文件都是调用这两个个方法,获取 gr_framebuffer,然后在上面作画。

那么我的方法就很简单了,我再构造一个 GRSurface,然后设置参数,在fbdev_init(),fbdev_flip(),方法里返回我自己增加的 这个GRSurface。
那么 就会在 我 增加的 这个 GRSurface 上面作画,
然后在 fbdev_flip 中 做画面的旋转,为什么要旋转呢,比如我的屏幕内核里面读出来的是 1024x768,我在fbdev_init,中调换了高和宽,fbdev_init(),fbdev_flip(),返回的 GRSurface 都是 768x1024的,其他文件也会认为屏幕就是768x1024的,所以生成的画面都是在768x1024的 GRSurface 中(也就是我新增的 GRSurface),但是这个buf是不可以直接传入内核的,为什么你们仔细想想,内核是1024x768的,这点并没有改变,所以我们要把这个画面转成内核可以使用的。

void rk_rotate_surface_90(GRSurface* surface,GRSurface* src) {
    GGLuint width = surface->width;
    GGLuint height = surface->height;
    int byt = 4; // 4 byte for ARGB_8888 (2 byte for RGB_565) 
    int length = width * height;
   

    GGLubyte* des_data = malloc(sizeof(GGLubyte)*length*byt);
    memcpy(des_data,src->data,src->height * src->row_bytes);
    memset(surface->data, 0, sizeof(GGLubyte)*length*byt);
    int i = 0;
    int j = 0;
    for(i = 0;i < width;i++){
        for(j = 0;j < height;j++) {
   
            surface->data[((width-1-i)*height +j)*byt] = des_data[(j*width + i)*byt];
            surface->data[((width-1-i)*height +j)*byt+1] = des_data[(j*width + i)*byt+1];
            surface->data[((width-1-i)*height +j)*byt+2] = des_data[(j*width + i)*byt+2];
            surface->data[((width-1-i)*height +j)*byt+3] = des_data[(j*width + i)*byt+3];
        }
    }
    free(des_data);
}


static gr_surface fbdev_flip(minui_backend* backend __unused) {
#ifdef RotateScreen_270    
            rk_rotate_surface_270(gr_draw,subx_draw);
#endif
}

static void set_displayed_framebuffer(unsigned n)
{
    int tmp;
    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;
#ifdef RotateScreen_270
    tmp = vi.xres;
    vi.xres = vi.yres;
    vi.yres = tmp;
    vi.yres_virtual = gr_framebuffer[0].width * 2;
     vi.yoffset = n * gr_framebuffer[0].width;
#endif
     if (ioctl(fb_fd, FBIOPUT_VSCREENINFO, &vi) < 0) {
        perror("active fb swap failed");
    }

    if (ioctl(fb_fd,RK_FBIOSET_CONFIG_DONE, NULL) < 0) {
        perror("set config done failed");
    }
    displayed_buffer = n;
#ifdef RotateScreen_270
        tmp = vi.xres;
        vi.xres = vi.yres;
        vi.yres = tmp;
#endif

}

最后和内核交互的时候需要 修正 参数,交互完成后再修改成我们需要的参数。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值