Display设备管理
DisplayDevice介绍
DisplayDevice描述了一个显示设备,是Android显示设备的抽象类。Android系统中定义了三种Device
DISPLAY_PRIMARY = HWC_DISPLAY_PRIMARY,
DISPLAY_EXTERNAL = HWC_DISPLAY_EXTERNAL,
DISPLAY_VIRTUAL = HWC_DISPLAY_VIRTUAL,
1:DISPLAY_PRIMARY Android 手机主显示屏
2:DISPLAY_EXTERNAL 一般为外接显示设备
3:DISPLAY_VIRTUAL 虚拟显示设备,用于WiFi投屏
第一种类型是基本的设备,基本所有设备都有自带显示屏, 其他两种则需要其他硬件来支持
SurfaceFlinger中需要显示的图层(layer)将通过DisplayDevice对象传递到OpenGLES中进行合成,因为如果同时有多个显示屏的情况下,不同的Layer可能会显示在不同的屏幕上。合成之后的图像再通过HWComposer对象传递到Framebuffer中显示。DisplayDevice对象中的成员变量mVisibleLayersSortedByZ保存了所有需要显示在本显示设备中显示的Layer对象,同时DisplayDevice对象也保存了和显示设备相关的显示方向、显示区域坐标等信息。
SurfaceFlinger的init函数中会初始化Display设备,代码如下:
//先检查硬件设备是否连接,或者是否是主显示屏
if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
// All non-virtual displays are currently considered secure.
bool isSecure = true;
//给显示设备分配一个Token,并且创建一个DisplayDeviceState对象,保存在SurfaceFlinger的mCurrentState.display列表中
createBuiltinDisplayLocked(type);
wp<IBinder> token = mBuiltinDisplays[i];
//为当前设备创建一个Buffer队列,初始化一个生产者和一个消费者,消费者有FrameBufferSurface封装,生产者交由DisplayDevice持有
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer,
new GraphicBufferAlloc());
//
sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
consumer);
//为甚分配一个ID
int32_t hwcId = allocateHwcDisplayId(type);
//根据相关信息,创建DisplayDevice对象
sp<DisplayDevice> hw = new DisplayDevice(this,
type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
fbs, producer,
mRenderEngine->getEGLConfig());
if (i > DisplayDevice::DISPLAY_PRIMARY) {
// FIXME: currently we don't get blank/unblank requests
// for displays other than the main display, so we always
// assume a connected display is unblanked.
ALOGD("marking display %zu as acquired/unblanked", i);
hw->setPowerMode(HWC_POWER_MODE_NORMAL);
}
//将DiplayDevice保存到SurfaceFlinger的mDisplays中。
mDisplays.add(token, hw);
}
}
getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
1:调用了HWComposer的isConnected来检查显示设备是否已连接,只有连接的硬件设备才会创建对应的DisplayDevice。主设备除外,无论是否连接都会创建一个DisplayDevice。
2:为当前显示设备创建一个BBinder类型的Token,并且创建一个DisplayDeviceState对象,保存在SurfaceFlinger的mCurrentState.display列表中
3:为当前显示设备创建一个Buffer队列,初始化一个生产者和一个消费者,消费者有FrameBufferSurface封装,生产者交由DisplayDevice持有
4:创建DisplayDevice对象,传入Buffer队列的producer,DisplayDevice的构造函数中,会创建一个Surface对象传递给底层的OpenGL ES使用,而这个Surface是一个生产者。在OpenGl ES中合成好了图像之后会将图像数据写到Surface对象中,这将触发consumer对象的onFrameAvailable函数被调用,然后FramebufferSurface调用HWComposer对象mHwc的fbPost函数输出到FB中。
5:将DiplayDevice保存到SurfaceFlinger的mDisplays中。
6:调用主显示屏的makeCurrent,绑定DisplayDevice的上下文
DisplayDevice构造方法如下:
mNativeWindow = new Surface(producer, false);
ANativeWindow* const window = mNativeWindow.get();
/*
* Create our display's surface
*/
EGLSurface surface;
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (config == EGL_NO_CONFIG) {
config = RenderEngine::chooseEglConfig(display, format);
}
surface = eglCreateWindowSurface(display, config, window, NULL);
eglQuerySurface(display, surface, EGL_WIDTH, &mDisplayWidth);
eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
window->setSwapInterval(window, 0);
mConfig = config;
mDisplay = display;
mSurface = surface;
mFormat = format;
mPageFlipCount = 0;
mViewport.makeInvalid();
mFrame.makeInvalid();
setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
创建OpenGL的EGL环境,我们在前面已经解释过,初始化过后,openGL就可以想Surface中绘制了,绘制完成调用eglswapBuffer来将绘制完成的Buffer发送到Buffer队列,这样FrameBufferSurface就可收到onFrameAvaliable通知了。
接着看下DisplayDevice的swapBuffer函数
void DisplayDevice::swapBuffers(HWComposer& hwc) const {
// 调用eglSwapBuffers()函数的条件:
// (1) 没有HWComposer硬件
// (2) 这一帧我们需要使用GLES来合成(包括两种情况)
// (a) we have framebuffer target support (not present on legacy
// devices, where HWComposer::commit() handles things); or
// (b) 虚拟显示设备
if (hwc.initCheck() != NO_ERROR ||
(hwc.hasGlesComposition(mHwcDisplayId) &&
(hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) {
//调用eglSwapBuffers更新队列
EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
......
}
}
swapBuffers用于将Display合成的图像渲染到FB设备的图像缓冲区,一般只有在不支持HWComposer情况下才会调用。
当DisplayDevice调用swapBuffer函数后,消费者收到onFrameAvailable通知。再来看下FrameBufferSurface的onFrameAvailale函数。
// Overrides ConsumerBase::onFrameAvailable(), does not call base class impl.
void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {
sp<GraphicBuffer> buf;
sp<Fence> acquireFence;
//调用NextBuffer从Buffer队列中获取新的Buffer
status_t err = nextBuffer(buf, acquireFence);
if (err != NO_ERROR) {
ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",
strerror(-err), err);
return;
}
//调用gralloc模块的FB设备的函数fbPost将graphicBuffer图像缓冲区渲染到FB显示缓冲区中.
err = mHwc.fbPost(mDisplayType, acquireFence, buf);
if (err != NO_ERROR) {
ALOGE("error posting framebuffer: %d", err);
}
}