OSDN Git Service

SurfaceFlinger: Add EventControlThread
authorJamie Gennis <jgennis@google.com>
Mon, 14 Oct 2013 19:22:52 +0000 (12:22 -0700)
committerJamie Gennis <jgennis@google.com>
Tue, 15 Oct 2013 21:31:41 +0000 (14:31 -0700)
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

services/surfaceflinger/Android.mk
services/surfaceflinger/EventControlThread.cpp [new file with mode: 0644]
services/surfaceflinger/EventControlThread.h [new file with mode: 0644]
services/surfaceflinger/SurfaceFlinger.cpp
services/surfaceflinger/SurfaceFlinger.h

index bd89bd5..36ad741 100644 (file)
@@ -5,6 +5,7 @@ LOCAL_SRC_FILES:= \
     Client.cpp \
     DisplayDevice.cpp \
     DispSync.cpp \
+    EventControlThread.cpp \
     EventThread.cpp \
     FrameTracker.cpp \
     Layer.cpp \
diff --git a/services/surfaceflinger/EventControlThread.cpp b/services/surfaceflinger/EventControlThread.cpp
new file mode 100644 (file)
index 0000000..6504091
--- /dev/null
@@ -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
diff --git a/services/surfaceflinger/EventControlThread.h b/services/surfaceflinger/EventControlThread.h
new file mode 100644 (file)
index 0000000..be6c53a
--- /dev/null
@@ -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
index bc8cfb8..8ef4d6f 100644 (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) {
index 353e7ba..03c4ba3 100644 (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