DisplayDevice介紹
DisplayDevice描述了一個(gè)顯示設(shè)備,是Android顯示設(shè)備的抽象類(lèi)。Android系統(tǒng)中定義了三種Device
DISPLAY_PRIMARY = HWC_DISPLAY_PRIMARY,
DISPLAY_EXTERNAL = HWC_DISPLAY_EXTERNAL,
DISPLAY_VIRTUAL = HWC_DISPLAY_VIRTUAL,
1:DISPLAY_PRIMARY Android 手機(jī)主顯示屏
2:DISPLAY_EXTERNAL 一般為外接顯示設(shè)備
3:DISPLAY_VIRTUAL 虛擬顯示設(shè)備,用于WiFi投屏
第一種類(lèi)型是基本的設(shè)備,基本所有設(shè)備都有自帶顯示屏, 其他兩種則需要其他硬件來(lái)支持
SurfaceFlinger中需要顯示的圖層(layer)將通過(guò)DisplayDevice對(duì)象傳遞到OpenGLES中進(jìn)行合成,因?yàn)槿绻瑫r(shí)有多個(gè)顯示屏的情況下,不同的Layer可能會(huì)顯示在不同的屏幕上。合成之后的圖像再通過(guò)HWComposer對(duì)象傳遞到Framebuffer中顯示。DisplayDevice對(duì)象中的成員變量mVisibleLayersSortedByZ保存了所有需要顯示在本顯示設(shè)備中顯示的Layer對(duì)象,同時(shí)DisplayDevice對(duì)象也保存了和顯示設(shè)備相關(guān)的顯示方向、顯示區(qū)域坐標(biāo)等信息。
SurfaceFlinger的init函數(shù)中會(huì)初始化Display設(shè)備,代碼如下:
//先檢查硬件設(shè)備是否連接,或者是否是主顯示屏
if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
// All non-virtual displays are currently considered secure.
bool isSecure = true;
//給顯示設(shè)備分配一個(gè)Token,并且創(chuàng)建一個(gè)DisplayDeviceState對(duì)象,保存在SurfaceFlinger的mCurrentState.display列表中
createBuiltinDisplayLocked(type);
wp<IBinder> token = mBuiltinDisplays[i];
//為當(dāng)前設(shè)備創(chuàng)建一個(gè)Buffer隊(duì)列,初始化一個(gè)生產(chǎn)者和一個(gè)消費(fèi)者,消費(fèi)者有FrameBufferSurface封裝,生產(chǎn)者交由DisplayDevice持有
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer,
new GraphicBufferAlloc());
//
sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
consumer);
//為甚分配一個(gè)ID
int32_t hwcId = allocateHwcDisplayId(type);
//根據(jù)相關(guān)信息,創(chuàng)建DisplayDevice對(duì)象
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:調(diào)用了HWComposer的isConnected來(lái)檢查顯示設(shè)備是否已連接,只有連接的硬件設(shè)備才會(huì)創(chuàng)建對(duì)應(yīng)的DisplayDevice。主設(shè)備除外,無(wú)論是否連接都會(huì)創(chuàng)建一個(gè)DisplayDevice。
2:為當(dāng)前顯示設(shè)備創(chuàng)建一個(gè)BBinder類(lèi)型的Token,并且創(chuàng)建一個(gè)DisplayDeviceState對(duì)象,保存在SurfaceFlinger的mCurrentState.display列表中
3:為當(dāng)前顯示設(shè)備創(chuàng)建一個(gè)Buffer隊(duì)列,初始化一個(gè)生產(chǎn)者和一個(gè)消費(fèi)者,消費(fèi)者有FrameBufferSurface封裝,生產(chǎn)者交由DisplayDevice持有
4:創(chuàng)建DisplayDevice對(duì)象,傳入Buffer隊(duì)列的producer,DisplayDevice的構(gòu)造函數(shù)中,會(huì)創(chuàng)建一個(gè)Surface對(duì)象傳遞給底層的OpenGL ES使用,而這個(gè)Surface是一個(gè)生產(chǎn)者。在OpenGl ES中合成好了圖像之后會(huì)將圖像數(shù)據(jù)寫(xiě)到Surface對(duì)象中,這將觸發(fā)consumer對(duì)象的onFrameAvailable函數(shù)被調(diào)用,然后FramebufferSurface調(diào)用HWComposer對(duì)象mHwc的fbPost函數(shù)輸出到FB中。
5:將DiplayDevice保存到SurfaceFlinger的mDisplays中。
6:調(diào)用主顯示屏的makeCurrent,綁定DisplayDevice的上下文
DisplayDevice構(gòu)造方法如下:
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);
創(chuàng)建OpenGL的EGL環(huán)境,我們?cè)谇懊嬉呀?jīng)解釋過(guò),初始化過(guò)后,openGL就可以想Surface中繪制了,繪制完成調(diào)用eglswapBuffer來(lái)將繪制完成的Buffer發(fā)送到Buffer隊(duì)列,這樣FrameBufferSurface就可收到onFrameAvaliable通知了。
接著看下DisplayDevice的swapBuffer函數(shù)
void DisplayDevice::swapBuffers(HWComposer& hwc) const {
// 調(diào)用eglSwapBuffers()函數(shù)的條件:
// (1) 沒(méi)有HWComposer硬件
// (2) 這一幀我們需要使用GLES來(lái)合成(包括兩種情況)
// (a) we have framebuffer target support (not present on legacy
// devices, where HWComposer::commit() handles things); or
// (b) 虛擬顯示設(shè)備
if (hwc.initCheck() != NO_ERROR ||
(hwc.hasGlesComposition(mHwcDisplayId) &&
(hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) {
//調(diào)用eglSwapBuffers更新隊(duì)列
EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
......
}
}
swapBuffers用于將Display合成的圖像渲染到FB設(shè)備的圖像緩沖區(qū),一般只有在不支持HWComposer情況下才會(huì)調(diào)用。
當(dāng)DisplayDevice調(diào)用swapBuffer函數(shù)后,消費(fèi)者收到onFrameAvailable通知。再來(lái)看下FrameBufferSurface的onFrameAvailale函數(shù)。
// Overrides ConsumerBase::onFrameAvailable(), does not call base class impl.
void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {
sp<GraphicBuffer> buf;
sp<Fence> acquireFence;
//調(diào)用NextBuffer從Buffer隊(duì)列中獲取新的Buffer
status_t err = nextBuffer(buf, acquireFence);
if (err != NO_ERROR) {
ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",
strerror(-err), err);
return;
}
//調(diào)用gralloc模塊的FB設(shè)備的函數(shù)fbPost將graphicBuffer圖像緩沖區(qū)渲染到FB顯示緩沖區(qū)中.
err = mHwc.fbPost(mDisplayType, acquireFence, buf);
if (err != NO_ERROR) {
ALOGE("error posting framebuffer: %d", err);
}
}