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:
parent
247423751f
commit
d1700756ec
|
@ -5,6 +5,7 @@ LOCAL_SRC_FILES:= \
|
||||||
Client.cpp \
|
Client.cpp \
|
||||||
DisplayDevice.cpp \
|
DisplayDevice.cpp \
|
||||||
DispSync.cpp \
|
DispSync.cpp \
|
||||||
|
EventControlThread.cpp \
|
||||||
EventThread.cpp \
|
EventThread.cpp \
|
||||||
FrameTracker.cpp \
|
FrameTracker.cpp \
|
||||||
Layer.cpp \
|
Layer.cpp \
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -60,6 +60,7 @@
|
||||||
#include "DdmConnection.h"
|
#include "DdmConnection.h"
|
||||||
#include "DisplayDevice.h"
|
#include "DisplayDevice.h"
|
||||||
#include "DispSync.h"
|
#include "DispSync.h"
|
||||||
|
#include "EventControlThread.h"
|
||||||
#include "EventThread.h"
|
#include "EventThread.h"
|
||||||
#include "Layer.h"
|
#include "Layer.h"
|
||||||
#include "LayerDim.h"
|
#include "LayerDim.h"
|
||||||
|
@ -592,6 +593,9 @@ void SurfaceFlinger::init() {
|
||||||
mEventThread = new EventThread(vsyncSrc);
|
mEventThread = new EventThread(vsyncSrc);
|
||||||
mEventQueue.setEventThread(mEventThread);
|
mEventQueue.setEventThread(mEventThread);
|
||||||
|
|
||||||
|
mEventControlThread = new EventControlThread(this);
|
||||||
|
mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
|
||||||
|
|
||||||
// set a fake vsync period if there is no HWComposer
|
// set a fake vsync period if there is no HWComposer
|
||||||
if (mHwc->initCheck() != NO_ERROR) {
|
if (mHwc->initCheck() != NO_ERROR) {
|
||||||
mPrimaryDispSync.setPeriod(16666667);
|
mPrimaryDispSync.setPeriod(16666667);
|
||||||
|
@ -755,7 +759,8 @@ void SurfaceFlinger::enableHardwareVsync() {
|
||||||
Mutex::Autolock _l(mHWVsyncLock);
|
Mutex::Autolock _l(mHWVsyncLock);
|
||||||
if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
|
if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
|
||||||
mPrimaryDispSync.beginResync();
|
mPrimaryDispSync.beginResync();
|
||||||
eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
|
//eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
|
||||||
|
mEventControlThread->setVsyncEnabled(true);
|
||||||
mPrimaryHWVsyncEnabled = true;
|
mPrimaryHWVsyncEnabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -778,7 +783,8 @@ void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) {
|
||||||
|
|
||||||
if (!mPrimaryHWVsyncEnabled) {
|
if (!mPrimaryHWVsyncEnabled) {
|
||||||
mPrimaryDispSync.beginResync();
|
mPrimaryDispSync.beginResync();
|
||||||
eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
|
//eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
|
||||||
|
mEventControlThread->setVsyncEnabled(true);
|
||||||
mPrimaryHWVsyncEnabled = true;
|
mPrimaryHWVsyncEnabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -786,7 +792,8 @@ void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) {
|
||||||
void SurfaceFlinger::disableHardwareVsync(bool makeUnavailable) {
|
void SurfaceFlinger::disableHardwareVsync(bool makeUnavailable) {
|
||||||
Mutex::Autolock _l(mHWVsyncLock);
|
Mutex::Autolock _l(mHWVsyncLock);
|
||||||
if (mPrimaryHWVsyncEnabled) {
|
if (mPrimaryHWVsyncEnabled) {
|
||||||
eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, false);
|
//eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, false);
|
||||||
|
mEventControlThread->setVsyncEnabled(false);
|
||||||
mPrimaryDispSync.endResync();
|
mPrimaryDispSync.endResync();
|
||||||
mPrimaryHWVsyncEnabled = false;
|
mPrimaryHWVsyncEnabled = false;
|
||||||
}
|
}
|
||||||
|
@ -796,15 +803,20 @@ void SurfaceFlinger::disableHardwareVsync(bool makeUnavailable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
|
void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
|
||||||
if (type == 0) {
|
bool needsHwVsync = false;
|
||||||
bool needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
|
|
||||||
|
|
||||||
if (needsHwVsync) {
|
{ // Scope for the lock
|
||||||
enableHardwareVsync();
|
Mutex::Autolock _l(mHWVsyncLock);
|
||||||
} else {
|
if (type == 0 && mPrimaryHWVsyncEnabled) {
|
||||||
disableHardwareVsync(false);
|
needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (needsHwVsync) {
|
||||||
|
enableHardwareVsync();
|
||||||
|
} else {
|
||||||
|
disableHardwareVsync(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceFlinger::onHotplugReceived(int type, bool connected) {
|
void SurfaceFlinger::onHotplugReceived(int type, bool connected) {
|
||||||
|
|
|
@ -67,6 +67,7 @@ class Layer;
|
||||||
class LayerDim;
|
class LayerDim;
|
||||||
class Surface;
|
class Surface;
|
||||||
class RenderEngine;
|
class RenderEngine;
|
||||||
|
class EventControlThread;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -427,6 +428,7 @@ private:
|
||||||
nsecs_t mBootTime;
|
nsecs_t mBootTime;
|
||||||
bool mGpuToCpuSupported;
|
bool mGpuToCpuSupported;
|
||||||
sp<EventThread> mEventThread;
|
sp<EventThread> mEventThread;
|
||||||
|
sp<EventControlThread> mEventControlThread;
|
||||||
EGLContext mEGLContext;
|
EGLContext mEGLContext;
|
||||||
EGLConfig mEGLConfig;
|
EGLConfig mEGLConfig;
|
||||||
EGLDisplay mEGLDisplay;
|
EGLDisplay mEGLDisplay;
|
||||||
|
@ -477,7 +479,6 @@ private:
|
||||||
bool mDaltonize;
|
bool mDaltonize;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
}; // namespace android
|
}; // namespace android
|
||||||
|
|
||||||
#endif // ANDROID_SURFACE_FLINGER_H
|
#endif // ANDROID_SURFACE_FLINGER_H
|
||||||
|
|
Loading…
Reference in New Issue