SurfaceFlinger是Android的一個native進程,負責將圖層進行合成,圖層疊加起來就構成了咱們看到的界面。合成的方式分爲在線合成和離線合成。在線合成是指如今一塊buffer畫好全部的內容,而後直接交給linux圖像驅動framebuffer顯示出來;離線合成是指將一些圖層的buffer直接遞交HWComposer,HWComposer指的是可以處理圖像數據並組合的現實硬件模塊(有些設備上可能沒有),當須要顯示某一行的數據時,再將這些圖層的數據進行處理組合後再交給framebuffer顯示出來,合成方式有MDP,DYN,C2D等,反正不是GPU,於是減輕了GPU負擔。
SurfaceFlinger啓動的main函數在main_surfaceflinger.cpp中。最後的run函數使SurfaceFlinger進程陷入do…while循環中,不會退出。咱們重點關注SurfaceFlinger的init函數。linux
/frameworks/native/services/surfaceflinger/main_surfaceflinger.cppapp
int main(int, char**) {
// When SF is launched in its own process, limit the number of
// binder threads to 4.
ProcessState::self()->setThreadPoolMaxThreadCount(4);composer
// start the thread pool
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();async
// instantiate surfaceflinger
sp<SurfaceFlinger> flinger = new SurfaceFlinger();ide
#if defined(HAVE_PTHREADS)
setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
#endif
set_sched_policy(0, SP_FOREGROUND);函數
// initialize before clients can connect
flinger->init();post
// publish surface flinger
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);ui
// run in this thread
flinger->run();this
return 0;
}
下面介紹的狀況均以只有一個主屏幕(id爲0)爲前提,實際上Android支持三種屏幕:主屏幕,外接屏幕(HDMI等),虛擬屏幕(投屏)。init函數的主要工做有:1.初始化EGL的一些環境以及設置;2.啓動hwc;3.搜尋可用的屏幕,初始化屏幕的一些信息,新建DisplayDevice和FramebufferSurface,並分別做爲生產者和消費者;4.分別爲app端和SurfaceFlinger創建一個EventThread以響應vysnc信號;5.啓動bootanimation。線程
/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::init() {
ALOGI( "SurfaceFlinger's main thread ready to run. "
"Initializing graphics H/W...");
status_t err;
Mutex::Autolock _l(mStateLock);
// initialize EGL for the default display
//初始化EGL環境
mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(mEGLDisplay, NULL, NULL);
// Initialize the H/W composer object. There may or may not be an
// actual hardware composer underneath.
//初始化hwc
mHwc = new HWComposer(this,
*static_cast<HWComposer::EventHandler *>(this));
// get a RenderEngine for the given display / config (can't fail)
//建立RenderEngine,RenderEngine封裝了一些OpenGL的操做
mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());
// retrieve the EGL context that was selected/created
//獲取EGL上下文
mEGLContext = mRenderEngine->getEGLContext();
LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
"couldn't create EGLContext");
// initialize our non-virtual displays
for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
// set-up the displays that are already connected
//屏幕可用或者爲主屏幕
if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
// All non-virtual displays are currently considered secure.
bool isSecure = true;
//建立內置屏幕,每一個屏幕id對應一個binder對象
createBuiltinDisplayLocked(type);
wp<IBinder> token = mBuiltinDisplays[i];
//建立生產者和消費者
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer,
new GraphicBufferAlloc());
//新建FramebufferSurface做爲消費者,向framebuffer傳遞數據就靠它了
sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
consumer);
//爲屏幕建立hwc層的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);
}
//屏幕id的對應的binder對象和DisplayDevice組成鍵值對,保存在mDisplays
mDisplays.add(token, hw);
}
}
// make the GLContext current so that we can create textures when creating Layers
// (which may happens before we render something)
//DisplayDevice::makeCurrent會調用到eglMakeCurrent,libagl.so的實現裏eglMakeCurrent會dequeue一塊buffer
getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
// start the EventThread
//基於不一樣的vsync信號模型建立的EventThread,mEventThread是app端對vsync信號的處理線程,mSFEventThread是SurfaceFlinger端對vysnc信號的處理線程
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "app");
mEventThread = new EventThread(vsyncSrc);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread = new EventThread(sfVsyncSrc);
mEventQueue.setEventThread(mSFEventThread);
//mEventControlThread線程用來開關vsync
mEventControlThread = new EventControlThread(this);
mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
// set a fake vsync period if there is no HWComposer
//hwc層初始化失敗後,使用1/16666667的屏幕刷新週期
if (mHwc->initCheck() != NO_ERROR) {
mPrimaryDispSync.setPeriod(16666667);
}
// initialize our drawing state
//初始化mDrawingState
mDrawingState = mCurrentState;
// set initial conditions (e.g. unblank default device)
//初始化主屏幕的一些flag和信息
initializeDisplays();
// start boot animation
//啓動bootanimation
startBootAnim();
}
先看看hwc的初始化。vsync信號分爲兩種:1.硬件產生的vsync;2.軟件模擬的vsync。這份源碼對應的是Android 5.1,使用的hwc HAL版本是1.4,因此不會打開framebuffer設備,在有hwc設備的狀況下不會開啓軟件模擬vysnc。
並且硬件vsync一開始是出於關閉狀態的。
/frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
HWComposer::HWComposer(
const sp<SurfaceFlinger>& flinger,
EventHandler& handler)
: mFlinger(flinger),
mFbDev(0), mHwc(0), mNumDisplays(1),
mCBContext(new cb_context),
mEventHandler(handler),
mDebugForceFakeVSync(false)
{
for (size_t i =0 ; i<MAX_HWC_DISPLAYS ; i++) {
mLists[i] = 0;
}
for (size_t i=0 ; i<HWC_NUM_PHYSICAL_DISPLAY_TYPES ; i++) {
mLastHwVSync[i] = 0;
mVSyncCounts[i] = 0;
}
char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.no_hw_vsync", value, "0");
//mDebugForceFakeVSync決定咱們是否啓用硬件vsync,爲true時永久關閉硬件vsync
mDebugForceFakeVSync = atoi(value);
//表示是否須要軟件模擬vsync
bool needVSyncThread = true;
// Note: some devices may insist that the FB HAL be opened before HWC.
//加載framebuffer和hwc的HAL模塊
int fberr = loadFbHalModule();
loadHwcModule();
if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
// close FB HAL if we don't needed it.
// FIXME: this is temporary until we're not forced to open FB HAL
// before HWC.
//若是framebuffer和hwc的硬件設備都被成功加載,且hwc HAL版本大於等於1.1,關閉framebuffer硬件設備
framebuffer_close(mFbDev);
mFbDev = NULL;
}
// If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.
if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
&& !mFbDev) {
ALOGE("ERROR: failed to open framebuffer (%s), aborting",
strerror(-fberr));
abort();
}
// these display IDs are always reserved
//NUM_BUILTIN_DISPLAYS(2)之內的id已被佔用,申請hwc id須要從NUM_BUILTIN_DISPLAYS開始申請
for (size_t i=0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
mAllocatedDisplayIDs.markBit(i);
}
if (mHwc) {
ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
(hwcApiVersion(mHwc) >> 24) & 0xff,
(hwcApiVersion(mHwc) >> 16) & 0xff);
if (mHwc->registerProcs) {
//註冊hwc HAL層回調事件
mCBContext->hwc = this;
mCBContext->procs.invalidate = &hook_invalidate;
mCBContext->procs.vsync = &hook_vsync;
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
mCBContext->procs.hotplug = &hook_hotplug;
else
mCBContext->procs.hotplug = NULL;
memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
mHwc->registerProcs(mHwc, &mCBContext->procs);
}
// don't need a vsync thread if we have a hardware composer
//有hwc模塊就不須要軟件模擬vysnc了
needVSyncThread = false;
// always turn vsync off when we start
//hwc初始化時先關閉硬件vysnc
eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
// the number of displays we actually have depends on the
// hw composer version
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
// 1.3 adds support for virtual displays
mNumDisplays = MAX_HWC_DISPLAYS;
} else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
// 1.1 adds support for multiple displays
mNumDisplays = NUM_BUILTIN_DISPLAYS;
} else {
mNumDisplays = 1;
}
}
if (mFbDev) {
//hwc HAL1.1以上的版本mFbDev爲null,不會走到該分支
ALOG_ASSERT(!(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),
"should only have fbdev if no hwc or hwc is 1.0");
DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);
disp.connected = true;
disp.format = mFbDev->format;
DisplayConfig config = DisplayConfig();
config.width = mFbDev->width;
config.height = mFbDev->height;
config.xdpi = mFbDev->xdpi;
config.ydpi = mFbDev->ydpi;
config.refresh = nsecs_t(1e9 / mFbDev->fps);
disp.configs.push_back(config);
disp.currentConfig = 0;
} else if (mHwc) {
// here we're guaranteed to have at least HWC 1.1
//執行到這裏說明是hwc HAL1.1以上的版本,這裏從HAL層獲取屏幕信息填充mDisplayData成員變量
for (size_t i =0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
queryDisplayProperties(i);
}
}
if (needVSyncThread) {
// we don't have VSYNC support, we need to fake it
//不支持硬件vsyn,就開啓軟件模擬vysnc線程
mVSyncThread = new VSyncThread(*this);
}
}
再看看DisplayDevice的初始化。
/frameworks/native/services/surfaceflinger/DisplayDevice.cpp
DisplayDevice::DisplayDevice(
const sp<SurfaceFlinger>& flinger,
DisplayType type,
int32_t hwcId,
int format,
bool isSecure,
const wp<IBinder>& displayToken,
const sp<DisplaySurface>& displaySurface,
const sp<IGraphicBufferProducer>& producer,
EGLConfig config)
: lastCompositionHadVisibleLayers(false),
mFlinger(flinger),
mType(type), mHwcDisplayId(hwcId),
mDisplayToken(displayToken),
mDisplaySurface(displaySurface),
mDisplay(EGL_NO_DISPLAY),
mSurface(EGL_NO_SURFACE),
mDisplayWidth(), mDisplayHeight(), mFormat(),
mFlags(),
mPageFlipCount(),
mIsSecure(isSecure),
mSecureLayerVisible(false),
mLayerStack(NO_LAYER_STACK),
mOrientation(),
mPowerMode(HWC_POWER_MODE_OFF),
mActiveConfig(0)
{
//DisplayDevice新建一個Surface做爲生產者
mNativeWindow = new Surface(producer, false);
ANativeWindow* const window = mNativeWindow.get();
/*
* Create our display's surface
*/
EGLSurface surface;
EGLint w, h;
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (config == EGL_NO_CONFIG) {
config = RenderEngine::chooseEglConfig(display, format);
}
//建立EGLSurface
surface = eglCreateWindowSurface(display, config, window, NULL);
//獲取Surface的寬高,保存在mDisplayWidth和mDisplayHeight中,這兩個值在消費者FrameBufferSurfcae建立時從hwc HAL層得到,就是屏幕的寬高值
eglQuerySurface(display, surface, EGL_WIDTH, &mDisplayWidth);
eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
// Make sure that composition can never be stalled by a virtual display
// consumer that isn't processing buffers fast enough. We have to do this
// in two places:
// * Here, in case the display is composed entirely by HWC.
// * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
// window's swap interval in eglMakeCurrent, so they'll override the
// interval we set here.
if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
window->setSwapInterval(window, 0);
mConfig = config;
mDisplay = display;
mSurface = surface;
mFormat = format;
mPageFlipCount = 0;
mViewport.makeInvalid();
mFrame.makeInvalid();
// virtual displays are always considered enabled
//主屏幕的電源模式初始化爲關閉狀態,在SurfaceFlinger::onInitializeDisplays中,會將主屏幕的電源模式設爲HWC_POWER_MODE_NORMAL
mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ?
HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
// Name the display. The name will be replaced shortly if the display
// was created with createDisplay().
switch (mType) {
case DISPLAY_PRIMARY:
mDisplayName = "Built-in Screen";
break;
case DISPLAY_EXTERNAL:
mDisplayName = "HDMI Screen";
break;
default:
mDisplayName = "Virtual Screen"; // e.g. Overlay #n
break;
}
// initialize the display orientation transform.
//調整顯示設備視角的大小、位移、旋轉等參數,eOrientationDefault指的是默認的旋轉方向,mViewport指的是邏輯顯示區域,mFrame指的是物理顯示區域
setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
}
再看看雙EventThread的初始化。咱們能夠在基於物理vsync的基礎上添加相移,做爲獨立的vsync起始位置mPhase,再根據vsync的週期mPeriod,能夠獨立就算出一個獨立的vsync模型,供app和SurfaceFlinger兩個EventThread使用。並且還能夠在後續的過程當中動態更新這個vsync模型,這樣作可使物理vsync,app繪製下一幀,SurfaceFlinger合成圖層錯開工做,避免同一時間同時執行這三個操做,提升效率。
vsyncPhaseOffsetNs是app端的DispSyncSource使用的相移mPhase由VSYNC_EVENT_PHASE_OFFSET_NS宏指定,能夠在在mk文件加入LOCAL_CFLAGS := -DVSYNC_EVENT_PHASE_OFFSET_NS=xxx指定;而SurfaceFlinger端使用的相移SF_VSYNC_EVENT_PHASE_OFFSET_NS則由SF_VSYNC_EVENT_PHASE_OFFSET_NS指定,也能夠在mk文件中指定。而mPeriod在兩個DispSyncSource構建時爲0。
/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
// start the EventThread
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "app");
mEventThread = new EventThread(vsyncSrc);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread = new EventThread(sfVsyncSrc);
mEventQueue.setEventThread(mSFEventThread);
mPrimaryDispSync是一個DispSync對象,其在構造時會執行一個DispSyncThread線程。該線程負責在使能vync的時候執行一些回調操做,從而觸發更新圖層或者app繪製下一幀的動做。這個在之後篇幅再介紹。
/frameworks/native/services/surfaceflinger/DispSync.cpp
DispSync::DispSync() :
mRefreshSkipCount(0),
mThread(new DispSyncThread()) {
mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
reset();
beginResync();
if (kTraceDetailedInfo) {
// If we're not getting present fences then the ZeroPhaseTracer
// would prevent HW vsync event from ever being turned off.
// Even if we're just ignoring the fences, the zero-phase tracing is
// not needed because any time there is an event registered we will
// turn on the HW vsync events.
if (!kIgnorePresentFences) {
addEventListener(0, new ZeroPhaseTracer());
}
}
}
SurfaceFlinger::initializeDisplays用來初始化一些狀態。
/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::initializeDisplays() {
class MessageScreenInitialized : public MessageBase {
SurfaceFlinger* flinger;
public:
MessageScreenInitialized(SurfaceFlinger* flinger) : flinger(flinger) { }
virtual bool handler() {
flinger->onInitializeDisplays();
return true;
}
};
sp<MessageBase> msg = new MessageScreenInitialized(this);
postMessageAsync(msg); // we may be called from main thread, use async message
}
DisplayState用來記錄一個屏幕設備的狀態信息。這裏將主屏幕的變化flag設爲eDisplayProjectionChanged |eLayerStackChanged;將layerStack 設爲0(一般一個屏幕對應一個layerstack);將orientation設爲默認旋轉方向等等。這些信息都會被封裝到DisplayState中,這個DisplayState會被添加到裝載DisplayState的vector displays中,經過setTransactionState–>setDisplayStateLocked傳遞給mCurrentState的displays成員。SurfaceFlinger維持了兩個成員變量mCurrentState和mDrawingState,mCurrentState記錄了SurfaceFlinger當前屏幕的相關信息,mDrawingState記錄了上一次更新圖層時屏幕的相關信息。經過對比mCurrentState和mDrawingState,能夠知道屏幕的哪些參數發生了改變,並更新這些信息到mCurrentState中。若是發生了變化,還會觸發一次signalTransaction以更新圖層。
/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::onInitializeDisplays() {
// reset screen orientation and use primary layer stack
Vector<ComposerState> state;
Vector<DisplayState> displays;
DisplayState d;
d.what = DisplayState::eDisplayProjectionChanged |
DisplayState::eLayerStackChanged;
d.token = mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY];
d.layerStack = 0;
d.orientation = DisplayState::eOrientationDefault;
d.frame.makeInvalid();
d.viewport.makeInvalid();
d.width = 0;
d.height = 0;
displays.add(d);
setTransactionState(state, displays, 0);
setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL);
const nsecs_t period =
getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
mAnimFrameTracker.setDisplayRefreshPeriod(period);
}
/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::setTransactionState(
const Vector<ComposerState>& state,
const Vector<DisplayState>& displays,
uint32_t flags)
{
ATRACE_CALL();
Mutex::Autolock _l(mStateLock);
uint32_t transactionFlags = 0;
if (flags & eAnimation) {
// For window updates that are part of an animation we must wait for
// previous animation "frames" to be handled.
while (mAnimTransactionPending) {
status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
if (CC_UNLIKELY(err != NO_ERROR)) {
// just in case something goes wrong in SF, return to the
// caller after a few seconds.
ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out "
"waiting for previous animation frame");
mAnimTransactionPending = false;
break;
}
}
}
size_t count = displays.size();
for (size_t i=0 ; i<count ; i++) {
const DisplayState& s(displays[i]);
//更新屏幕信息到mCurrentState
transactionFlags |= setDisplayStateLocked(s);
}
count = state.size();
for (size_t i=0 ; i<count ; i++) {
const ComposerState& s(state[i]);
// Here we need to check that the interface we're given is indeed
// one of our own. A malicious client could give us a NULL
// IInterface, or one of its own or even one of our own but a
// different type. All these situations would cause us to crash.
//
// NOTE: it would be better to use RTTI as we could directly check
// that we have a Client*. however, RTTI is disabled in Android.
if (s.client != NULL) {
sp<IBinder> binder = s.client->asBinder();
if (binder != NULL) {
String16 desc(binder->getInterfaceDescriptor());
if (desc == ISurfaceComposerClient::descriptor) {
sp<Client> client( static_cast<Client *>(s.client.get()) );
transactionFlags |= setClientStateLocked(client, s.state);
}
}
}
}
if (transactionFlags) {
// this triggers the transaction
//屏幕信息發生了變化,觸發更新圖層
setTransactionFlags(transactionFlags);
// if this is a synchronous transaction, wait for it to take effect
// before returning.
if (flags & eSynchronous) {
mTransactionPending = true;
}
if (flags & eAnimation) {
mAnimTransactionPending = true;
}
while (mTransactionPending) {
status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
if (CC_UNLIKELY(err != NO_ERROR)) {
// just in case something goes wrong in SF, return to the
// called after a few seconds.
ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
mTransactionPending = false;
break;
}
}
}
}
/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s)
{
ssize_t dpyIdx = mCurrentState.displays.indexOfKey(s.token);
if (dpyIdx < 0)
return 0;
uint32_t flags = 0;
DisplayDeviceState& disp(mCurrentState.displays.editValueAt(dpyIdx));
if (disp.isValid()) {
const uint32_t what = s.what;
if (what & DisplayState::eSurfaceChanged) {
if (disp.surface->asBinder() != s.surface->asBinder()) {
disp.surface = s.surface;
flags |= eDisplayTransactionNeeded;
}
}
if (what & DisplayState::eLayerStackChanged) {
if (disp.layerStack != s.layerStack) {
disp.layerStack = s.layerStack;
flags |= eDisplayTransactionNeeded;
}
}
if (what & DisplayState::eDisplayProjectionChanged) {
if (disp.orientation != s.orientation) {
disp.orientation = s.orientation;
flags |= eDisplayTransactionNeeded;
}
if (disp.frame != s.frame) {
disp.frame = s.frame;
flags |= eDisplayTransactionNeeded;
}
if (disp.viewport != s.viewport) {
disp.viewport = s.viewport;
flags |= eDisplayTransactionNeeded;
}
}
if (what & DisplayState::eDisplaySizeChanged) {
if (disp.width != s.width) {
disp.width = s.width;
flags |= eDisplayTransactionNeeded;
}
if (disp.height != s.height) {
disp.height = s.height;
flags |= eDisplayTransactionNeeded;
}
}
}
return flags;
}
/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw,
int mode) {
ALOGD("Set power mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
this);
int32_t type = hw->getDisplayType();
int currentMode = hw->getPowerMode();
if (mode == currentMode) {
ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode);
return;
}
hw->setPowerMode(mode);
if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
ALOGW("Trying to set power mode for virtual display");
return;
}
if (currentMode == HWC_POWER_MODE_OFF) {
getHwComposer().setPowerMode(type, mode);
if (type == DisplayDevice::DISPLAY_PRIMARY) {
// FIXME: eventthread only knows about the main display right now
mEventThread->onScreenAcquired();
resyncToHardwareVsync(true);
}
mVisibleRegionsDirty = true;
repaintEverything();
} else if (mode == HWC_POWER_MODE_OFF) {
if (type == DisplayDevice::DISPLAY_PRIMARY) {
disableHardwareVsync(true); // also cancels any in-progress resync
// FIXME: eventthread only knows about the main display right now
mEventThread->onScreenReleased();
}
getHwComposer().setPowerMode(type, mode);
mVisibleRegionsDirty = true;
// from this point on, SF will stop drawing on this display
} else {
getHwComposer().setPowerMode(type, mode);
}
}
:initializeDisplays還有一步操做是設置DisplayDevice的PowerMode。主屏幕初始化時的PowerMode爲HWC_POWER_MODE_OFF,如今要更新爲HWC_POWER_MODE_NORMAL。
/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw,
int mode) {
ALOGD("Set power mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
this);
int32_t type = hw->getDisplayType();
int currentMode = hw->getPowerMode();
if (mode == currentMode) {
ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode);
return;
}
//更新DisplayDevice的PowerMode
hw->setPowerMode(mode);
if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
ALOGW("Trying to set power mode for virtual display");
return;
}
if (currentMode == HWC_POWER_MODE_OFF) {
//設置hwc的PowerMode
getHwComposer().setPowerMode(type, mode);
if (type == DisplayDevice::DISPLAY_PRIMARY) {
// FIXME: eventthread only knows about the main display right now
mEventThread->onScreenAcquired();
//須要打開硬件vsync同步
resyncToHardwareVsync(true);
}
mVisibleRegionsDirty = true;
//觸發重繪操做
repaintEverything();
} else if (mode == HWC_POWER_MODE_OFF) {
if (type == DisplayDevice::DISPLAY_PRIMARY) {
disableHardwareVsync(true); // also cancels any in-progress resync
// FIXME: eventthread only knows about the main display right now
mEventThread->onScreenReleased();
}
getHwComposer().setPowerMode(type, mode);
mVisibleRegionsDirty = true;
// from this point on, SF will stop drawing on this display
} else {
getHwComposer().setPowerMode(type, mode);
}
}
這裏會更新vysnc週期mPeriod爲hwc層的硬件Vysnc週期,通常爲1/60s,由於從滅屏狀態進入到點亮屏幕狀態須要重建vsync模型。mPrimaryHWVsyncEnabled被初始化爲false,因此經過EventControlThread::setVsyncEnabled就能夠打開硬件Vsync了,今後開始進入Vsync的世界。
/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) {
Mutex::Autolock _l(mHWVsyncLock);
if (makeAvailable) {
mHWVsyncAvailable = true;
} else if (!mHWVsyncAvailable) {
ALOGE("resyncToHardwareVsync called when HW vsync unavailable");
return;
}
const nsecs_t period =
getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
mPrimaryDispSync.reset();
mPrimaryDispSync.setPeriod(period);
if (!mPrimaryHWVsyncEnabled) { mPrimaryDispSync.beginResync(); //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true); mEventControlThread->setVsyncEnabled(true); mPrimaryHWVsyncEnabled = true; } }