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 \
|
||||
DisplayDevice.cpp \
|
||||
DispSync.cpp \
|
||||
EventControlThread.cpp \
|
||||
EventThread.cpp \
|
||||
FrameTracker.cpp \
|
||||
Layer.cpp \
|
||||
|
59
services/surfaceflinger/EventControlThread.cpp
Normal file
59
services/surfaceflinger/EventControlThread.cpp
Normal 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
|
48
services/surfaceflinger/EventControlThread.h
Normal file
48
services/surfaceflinger/EventControlThread.h
Normal 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
|
@ -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) {
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user