SurfaceFlinger: Add EventControlThread

This change adds a new thread for calling HWComposer's eventControl
asynchronously.  The DispSync-based vsync approach ends up enabling and
disabling HWComposer's vsync callbacks at arbitrary times, and some HWComposer
implementations do not have these calls optimized.

Bug: 11175503
Change-Id: I719be82bd200b391c61d40863b991c7b59acdfd6
This commit is contained in:
Jamie Gennis 2013-10-14 12:22:52 -07:00
parent 247423751f
commit d1700756ec
5 changed files with 131 additions and 10 deletions

View File

@ -5,6 +5,7 @@ LOCAL_SRC_FILES:= \
Client.cpp \
DisplayDevice.cpp \
DispSync.cpp \
EventControlThread.cpp \
EventThread.cpp \
FrameTracker.cpp \
Layer.cpp \

View File

@ -0,0 +1,59 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "EventControlThread.h"
#include "SurfaceFlinger.h"
namespace android {
EventControlThread::EventControlThread(const sp<SurfaceFlinger>& flinger):
mFlinger(flinger),
mVsyncEnabled(false) {
}
void EventControlThread::setVsyncEnabled(bool enabled) {
Mutex::Autolock lock(mMutex);
mVsyncEnabled = enabled;
mCond.signal();
}
bool EventControlThread::threadLoop() {
Mutex::Autolock lock(mMutex);
bool vsyncEnabled = mVsyncEnabled;
mFlinger->eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC,
mVsyncEnabled);
while (true) {
status_t err = mCond.wait(mMutex);
if (err != NO_ERROR) {
ALOGE("error waiting for new events: %s (%d)",
strerror(-err), err);
return false;
}
if (vsyncEnabled != mVsyncEnabled) {
mFlinger->eventControl(HWC_DISPLAY_PRIMARY,
SurfaceFlinger::EVENT_VSYNC, mVsyncEnabled);
vsyncEnabled = mVsyncEnabled;
}
}
return false;
}
} // namespace android

View File

@ -0,0 +1,48 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_EVENTCONTROLTHREAD_H
#define ANDROID_EVENTCONTROLTHREAD_H
#include <stddef.h>
#include <utils/Mutex.h>
#include <utils/Thread.h>
namespace android {
class SurfaceFlinger;
class EventControlThread: public Thread {
public:
EventControlThread(const sp<SurfaceFlinger>& flinger);
virtual ~EventControlThread() {}
void setVsyncEnabled(bool enabled);
virtual bool threadLoop();
private:
sp<SurfaceFlinger> mFlinger;
bool mVsyncEnabled;
Mutex mMutex;
Condition mCond;
};
}
#endif // ANDROID_DISPSYNC_H

View File

@ -60,6 +60,7 @@
#include "DdmConnection.h"
#include "DisplayDevice.h"
#include "DispSync.h"
#include "EventControlThread.h"
#include "EventThread.h"
#include "Layer.h"
#include "LayerDim.h"
@ -592,6 +593,9 @@ void SurfaceFlinger::init() {
mEventThread = new EventThread(vsyncSrc);
mEventQueue.setEventThread(mEventThread);
mEventControlThread = new EventControlThread(this);
mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
// set a fake vsync period if there is no HWComposer
if (mHwc->initCheck() != NO_ERROR) {
mPrimaryDispSync.setPeriod(16666667);
@ -755,7 +759,8 @@ void SurfaceFlinger::enableHardwareVsync() {
Mutex::Autolock _l(mHWVsyncLock);
if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
mPrimaryDispSync.beginResync();
eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
//eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
mEventControlThread->setVsyncEnabled(true);
mPrimaryHWVsyncEnabled = true;
}
}
@ -778,7 +783,8 @@ void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) {
if (!mPrimaryHWVsyncEnabled) {
mPrimaryDispSync.beginResync();
eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
//eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
mEventControlThread->setVsyncEnabled(true);
mPrimaryHWVsyncEnabled = true;
}
}
@ -786,7 +792,8 @@ void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) {
void SurfaceFlinger::disableHardwareVsync(bool makeUnavailable) {
Mutex::Autolock _l(mHWVsyncLock);
if (mPrimaryHWVsyncEnabled) {
eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, false);
//eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, false);
mEventControlThread->setVsyncEnabled(false);
mPrimaryDispSync.endResync();
mPrimaryHWVsyncEnabled = false;
}
@ -796,15 +803,20 @@ void SurfaceFlinger::disableHardwareVsync(bool makeUnavailable) {
}
void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
if (type == 0) {
bool needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
bool needsHwVsync = false;
if (needsHwVsync) {
enableHardwareVsync();
} else {
disableHardwareVsync(false);
{ // Scope for the lock
Mutex::Autolock _l(mHWVsyncLock);
if (type == 0 && mPrimaryHWVsyncEnabled) {
needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
}
}
if (needsHwVsync) {
enableHardwareVsync();
} else {
disableHardwareVsync(false);
}
}
void SurfaceFlinger::onHotplugReceived(int type, bool connected) {

View File

@ -67,6 +67,7 @@ class Layer;
class LayerDim;
class Surface;
class RenderEngine;
class EventControlThread;
// ---------------------------------------------------------------------------
@ -427,6 +428,7 @@ private:
nsecs_t mBootTime;
bool mGpuToCpuSupported;
sp<EventThread> mEventThread;
sp<EventControlThread> mEventControlThread;
EGLContext mEGLContext;
EGLConfig mEGLConfig;
EGLDisplay mEGLDisplay;
@ -477,7 +479,6 @@ private:
bool mDaltonize;
};
// ---------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_SURFACE_FLINGER_H