Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d1700756 authored by Jamie Gennis's avatar Jamie Gennis
Browse files

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
parent 24742375
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ LOCAL_SRC_FILES:= \
    Client.cpp \
    DisplayDevice.cpp \
    DispSync.cpp \
    EventControlThread.cpp \
    EventThread.cpp \
    FrameTracker.cpp \
    Layer.cpp \
+59 −0
Original line number Diff line number Diff line
/*
 * 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 −0
Original line number Diff line number Diff line
/*
 * 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
+21 −9
Original line number Diff line number Diff line
@@ -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,8 +803,14 @@ void SurfaceFlinger::disableHardwareVsync(bool makeUnavailable) {
}

void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
    if (type == 0) {
        bool needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
    bool needsHwVsync = false;

    { // Scope for the lock
        Mutex::Autolock _l(mHWVsyncLock);
        if (type == 0 && mPrimaryHWVsyncEnabled) {
            needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
        }
    }

    if (needsHwVsync) {
        enableHardwareVsync();
@@ -805,7 +818,6 @@ void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
        disableHardwareVsync(false);
    }
}
}

void SurfaceFlinger::onHotplugReceived(int type, bool connected) {
    if (mEventThread == NULL) {
+2 −1
Original line number Diff line number Diff line
@@ -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