android emulator虚拟设备分析第四篇之framebuffer

一、概述

framebuffer是啥就不用详细说了吧,需要注意的是android emulator的framebuffer貌似用处不大,因为我之前用android emulator运行x86镜像时,可能是分辨率选得太大了,/dev/graphics/fb0文件都没有产生,系统却可以正常跑,因为系统用的是DRM方式。

另外,GOLDFISH-VIRTUAL-HARDWARE.TXT说了

IMPORTANT NOTE: When GPU emulation is enabled, the framebuffer will typically only be used during boot.

所以,本篇可以跳过不看。


二、驱动

老规矩,先看文档

V. Goldfish framebuffer:
========================

Relevant files:
  $QEMU/hw/android/goldfish/fb.c
  $KERNEL/drivers/video/goldfish_fb.c

Device properties:
  Name: goldfish_fb
  Id: 0 to N  (only one used in practice).
  IrqCount: 0
  I/O Registers:
    0x00  GET_WIDTH       R: Read framebuffer width in pixels.
    0x04  GET_HEIGHT      R: Read framebuffer height in pixels.
    0x08  INT_STATUS
    0x0c  INT_ENABLE
    0x10  SET_BASE
    0x14  SET_ROTATION
    0x18  SET_BLANK       W: Set 'blank' flag.
    0x1c  GET_PHYS_WIDTH  R: Read framebuffer width in millimeters.
    0x20  GET_PHYS_HEIGHT R: Read framebuffer height in millimeters.
    0x24  GET_FORMAT      R: Read framebuffer pixel format.

The framebuffer device is a bit peculiar, because it uses, in addition to the
typical I/O registers and IRQs, a large area of physical memory, allocated by
the kernel, but visible to the emulator, to store a large pixel buffer.

The emulator is responsible for displaying the framebuffer content in its UI
window, which can be rotated, as instructed by the kernel.

IMPORTANT NOTE: When GPU emulation is enabled, the framebuffer will typically
only be used during boot. Note that GPU emulation doesn't rely on a specific
virtual GPU device, however, it uses the "QEMU Pipe" device described below.
For more information, please read:

  https://android.googlesource.com/platform/sdk/+/master/emulator/opengl/DESIGN

On boot, the kernel will read various properties of the framebuffer:

  IO_READ(GET_WIDTH) and IO_READ(GET_HEIGHT) return the width and height of
  the framebuffer in pixels. Note that a 'row' corresponds to consecutive bytes
  in memory, but doesn't necessarily to an horizontal line on the final display,
  due to possible rotation (see SET_ROTATION below).

  IO_READ(GET_PHYS_WIDTH) and IO_READ(GET_PHYS_HEIGHT) return the emulated
  physical width and height in millimeters, this is later used by the kernel
  and the platform to determine the device's emulated density.

  IO_READ(GET_FORMAT) returns a value matching the format of pixels in the
  framebuffer. Note that these values are specified by the Android hardware
  abstraction layer (HAL) and cannot change:

    0x01  HAL_PIXEL_FORMAT_BRGA_8888
    0x02  HAL_PIXEL_FORMAT_RGBX_8888
    0x03  HAL_PIXEL_FORMAT_RGB_888
    0x04  HAL_PIXEL_FORMAT_RGB_565
    0x05  HAL_PIXEL_FORMAT_BGRA_8888
    0x06  HAL_PIXEL_FORMAT_RGBA_5551
    0x08  HAL_PIXEL_FORMAT_RGBA_4444

  HOWEVER, the kernel driver only expects a value of HAL_PIXEL_FORMAT_RGB_565
  at the moment. Until this is fixed, the virtual device should always return
  the value 0x04 here. Rows are not padded, so the size in bytes of a single
  framebuffer will always be exactly 'width * heigth * 2'.

  Note that GPU emulation doesn't have this limitation and can use and display
  32-bit surfaces properly, because it doesn't use the framebuffer.

The device has a 'blank' flag. When set to 1, the UI should only display an
empty/blank framebuffer, ignoring the content of the framebuffer memory.
It is set with IO_WRITE(SET_BLANK, <value>), where value can be 1 or 0. This is
used when simulating suspend/resume.

IMPORTANT: The framebuffer memory is allocated by the kernel, which will send
its physical address to the device by using IO_WRITE(SET_BASE, <address>).

The kernel really allocates a memory buffer large enough to hold *two*
framebuffers, in order to implement panning / double-buffering. This also means
that calls to IO_WRITE(SET_BASE, <address>) will be frequent.

The allocation happens with dma_alloc_writecombine() on ARM, which can only
allocate a maximum of 4 MB, this limits the size of each framebuffer to 2 MB,
which may not be enough to emulate high-density devices :-(

For other architectures, dma_alloc_coherent() is used instead, and has the same
upper limit / limitation.

TODO(digit): Explain how it's possible to raise this limit by modifyinf
             CONSISTENT_DMA_SIZE and/or MAX_ORDER in the kernel configuration.

The device uses a single IRQ to notify the kernel of several events. When it
is raised, the kernel IRQ handler must IO_READ(INT_STATUS), which will return
a value containing the following bit flags:

  bit 0: Set to 1 to i
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值