refactor / simplify EventThread

Change-Id: I3981c6fba93b7b985174b2a7045e24db2c0b4428
This commit is contained in:
Mathias Agopian 2012-04-03 17:48:03 -07:00
parent 9b71221171
commit cb9732a951
7 changed files with 102 additions and 214 deletions

View File

@ -11,7 +11,6 @@ LOCAL_SRC_FILES:= \
DisplayHardware/DisplayHardwareBase.cpp \ DisplayHardware/DisplayHardwareBase.cpp \
DisplayHardware/HWComposer.cpp \ DisplayHardware/HWComposer.cpp \
DisplayHardware/VSyncBarrier.cpp \ DisplayHardware/VSyncBarrier.cpp \
DisplayEventConnection.cpp \
GLExtensions.cpp \ GLExtensions.cpp \
MessageQueue.cpp \ MessageQueue.cpp \
SurfaceFlinger.cpp \ SurfaceFlinger.cpp \

View File

@ -1,71 +0,0 @@
/*
* Copyright (C) 2011 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 <stdint.h>
#include <sys/types.h>
#include <gui/IDisplayEventConnection.h>
#include <gui/BitTube.h>
#include <gui/DisplayEventReceiver.h>
#include <utils/Errors.h>
#include "SurfaceFlinger.h"
#include "DisplayEventConnection.h"
#include "EventThread.h"
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
DisplayEventConnection::DisplayEventConnection(
const sp<EventThread>& eventThread)
: mEventThread(eventThread), mChannel(new BitTube())
{
}
DisplayEventConnection::~DisplayEventConnection() {
mEventThread->unregisterDisplayEventConnection(this);
}
void DisplayEventConnection::onFirstRef() {
// NOTE: mEventThread doesn't hold a strong reference on us
mEventThread->registerDisplayEventConnection(this);
}
sp<BitTube> DisplayEventConnection::getDataChannel() const {
return mChannel;
}
void DisplayEventConnection::setVsyncRate(uint32_t count) {
mEventThread->setVsyncRate(count, this);
}
void DisplayEventConnection::requestNextVsync() {
mEventThread->requestNextVsync(this);
}
status_t DisplayEventConnection::postEvent(
const DisplayEventReceiver::Event& event) {
ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1);
return size < 0 ? status_t(size) : status_t(NO_ERROR);
}
// ---------------------------------------------------------------------------
}; // namespace android

View File

@ -1,62 +0,0 @@
/*
* Copyright (C) 2011 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_SURFACE_FLINGER_DISPLAY_EVENT_CONNECTION_H
#define ANDROID_SURFACE_FLINGER_DISPLAY_EVENT_CONNECTION_H
#include <stdint.h>
#include <sys/types.h>
#include <gui/IDisplayEventConnection.h>
#include <utils/Errors.h>
#include <gui/DisplayEventReceiver.h>
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
class BitTube;
class EventThread;
// ---------------------------------------------------------------------------
class DisplayEventConnection : public BnDisplayEventConnection {
public:
DisplayEventConnection(const sp<EventThread>& flinger);
status_t postEvent(const DisplayEventReceiver::Event& event);
private:
virtual ~DisplayEventConnection();
virtual void onFirstRef();
virtual sp<BitTube> getDataChannel() const;
virtual void setVsyncRate(uint32_t count);
virtual void requestNextVsync(); // asynchronous
sp<EventThread> const mEventThread;
sp<BitTube> const mChannel;
};
// ---------------------------------------------------------------------------
}; // namespace android
// ---------------------------------------------------------------------------
#endif /* ANDROID_SURFACE_FLINGER_DISPLAY_EVENT_CONNECTION_H */

View File

@ -19,6 +19,7 @@
#include <stdint.h> #include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include <gui/BitTube.h>
#include <gui/IDisplayEventConnection.h> #include <gui/IDisplayEventConnection.h>
#include <gui/DisplayEventReceiver.h> #include <gui/DisplayEventReceiver.h>
@ -26,7 +27,6 @@
#include <utils/Trace.h> #include <utils/Trace.h>
#include "DisplayHardware/DisplayHardware.h" #include "DisplayHardware/DisplayHardware.h"
#include "DisplayEventConnection.h"
#include "EventThread.h" #include "EventThread.h"
#include "SurfaceFlinger.h" #include "SurfaceFlinger.h"
@ -48,8 +48,8 @@ void EventThread::onFirstRef() {
run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
} }
sp<DisplayEventConnection> EventThread::createEventConnection() const { sp<EventThread::Connection> EventThread::createEventConnection() const {
return new DisplayEventConnection(const_cast<EventThread*>(this)); return new Connection(const_cast<EventThread*>(this));
} }
nsecs_t EventThread::getLastVSyncTimestamp() const { nsecs_t EventThread::getLastVSyncTimestamp() const {
@ -63,56 +63,44 @@ nsecs_t EventThread::getVSyncPeriod() const {
} }
status_t EventThread::registerDisplayEventConnection( status_t EventThread::registerDisplayEventConnection(
const sp<DisplayEventConnection>& connection) { const sp<EventThread::Connection>& connection) {
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
ConnectionInfo info; mDisplayEventConnections.add(connection);
mDisplayEventConnections.add(connection, info);
mCondition.signal(); mCondition.signal();
return NO_ERROR; return NO_ERROR;
} }
status_t EventThread::unregisterDisplayEventConnection( status_t EventThread::unregisterDisplayEventConnection(
const wp<DisplayEventConnection>& connection) { const wp<EventThread::Connection>& connection) {
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
mDisplayEventConnections.removeItem(connection); mDisplayEventConnections.remove(connection);
mCondition.signal(); mCondition.signal();
return NO_ERROR; return NO_ERROR;
} }
void EventThread::removeDisplayEventConnection( void EventThread::removeDisplayEventConnection(
const wp<DisplayEventConnection>& connection) { const wp<EventThread::Connection>& connection) {
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
mDisplayEventConnections.removeItem(connection); mDisplayEventConnections.remove(connection);
}
EventThread::ConnectionInfo* EventThread::getConnectionInfoLocked(
const wp<DisplayEventConnection>& connection) {
ssize_t index = mDisplayEventConnections.indexOfKey(connection);
if (index < 0) return NULL;
return &mDisplayEventConnections.editValueAt(index);
} }
void EventThread::setVsyncRate(uint32_t count, void EventThread::setVsyncRate(uint32_t count,
const wp<DisplayEventConnection>& connection) { const sp<EventThread::Connection>& connection) {
if (int32_t(count) >= 0) { // server must protect against bad params if (int32_t(count) >= 0) { // server must protect against bad params
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
ConnectionInfo* info = getConnectionInfoLocked(connection); const int32_t new_count = (count == 0) ? -1 : count;
if (info) { if (connection->count != new_count) {
const int32_t new_count = (count == 0) ? -1 : count; connection->count = new_count;
if (info->count != new_count) { mCondition.signal();
info->count = new_count;
mCondition.signal();
}
} }
} }
} }
void EventThread::requestNextVsync( void EventThread::requestNextVsync(
const wp<DisplayEventConnection>& connection) { const sp<EventThread::Connection>& connection) {
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
ConnectionInfo* info = getConnectionInfoLocked(connection); if (connection->count < 0) {
if (info && info->count < 0) { connection->count = 0;
info->count = 0;
mCondition.signal(); mCondition.signal();
} }
} }
@ -121,7 +109,7 @@ bool EventThread::threadLoop() {
nsecs_t timestamp; nsecs_t timestamp;
DisplayEventReceiver::Event vsync; DisplayEventReceiver::Event vsync;
Vector< wp<DisplayEventConnection> > displayEventConnections; Vector< wp<EventThread::Connection> > displayEventConnections;
{ // scope for the lock { // scope for the lock
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
@ -131,9 +119,9 @@ bool EventThread::threadLoop() {
bool waitForNextVsync = false; bool waitForNextVsync = false;
size_t count = mDisplayEventConnections.size(); size_t count = mDisplayEventConnections.size();
for (size_t i=0 ; i<count ; i++) { for (size_t i=0 ; i<count ; i++) {
const ConnectionInfo& info( sp<Connection> connection =
mDisplayEventConnections.valueAt(i)); mDisplayEventConnections.itemAt(i).promote();
if (info.count >= 0) { if (connection!=0 && connection->count >= 0) {
// at least one continuous mode or active one-shot event // at least one continuous mode or active one-shot event
waitForNextVsync = true; waitForNextVsync = true;
break; break;
@ -158,24 +146,26 @@ bool EventThread::threadLoop() {
const size_t count = mDisplayEventConnections.size(); const size_t count = mDisplayEventConnections.size();
for (size_t i=0 ; i<count ; i++) { for (size_t i=0 ; i<count ; i++) {
bool reportVsync = false; bool reportVsync = false;
const ConnectionInfo& info( sp<Connection> connection =
mDisplayEventConnections.valueAt(i)); mDisplayEventConnections.itemAt(i).promote();
if (info.count >= 1) { if (connection == 0)
if (info.count==1 || (mDeliveredEvents % info.count) == 0) { continue;
const int32_t count = connection->count;
if (count >= 1) {
if (count==1 || (mDeliveredEvents % count) == 0) {
// continuous event, and time to report it // continuous event, and time to report it
reportVsync = true; reportVsync = true;
} }
} else if (info.count >= -1) { } else if (count >= -1) {
ConnectionInfo& info( if (count == 0) {
mDisplayEventConnections.editValueAt(i));
if (info.count == 0) {
// fired this time around // fired this time around
reportVsync = true; reportVsync = true;
} }
info.count--; connection->count--;
} }
if (reportVsync) { if (reportVsync) {
displayEventConnections.add(mDisplayEventConnections.keyAt(i)); displayEventConnections.add(connection);
} }
} }
} while (!displayEventConnections.size()); } while (!displayEventConnections.size());
@ -188,7 +178,7 @@ bool EventThread::threadLoop() {
const size_t count = displayEventConnections.size(); const size_t count = displayEventConnections.size();
for (size_t i=0 ; i<count ; i++) { for (size_t i=0 ; i<count ; i++) {
sp<DisplayEventConnection> conn(displayEventConnections[i].promote()); sp<Connection> conn(displayEventConnections[i].promote());
// make sure the connection didn't die // make sure the connection didn't die
if (conn != NULL) { if (conn != NULL) {
status_t err = conn->postEvent(vsync); status_t err = conn->postEvent(vsync);
@ -232,4 +222,39 @@ void EventThread::dump(String8& result, char* buffer, size_t SIZE) const {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
EventThread::Connection::Connection(
const sp<EventThread>& eventThread)
: count(-1), mEventThread(eventThread), mChannel(new BitTube())
{
}
EventThread::Connection::~Connection() {
mEventThread->unregisterDisplayEventConnection(this);
}
void EventThread::Connection::onFirstRef() {
// NOTE: mEventThread doesn't hold a strong reference on us
mEventThread->registerDisplayEventConnection(this);
}
sp<BitTube> EventThread::Connection::getDataChannel() const {
return mChannel;
}
void EventThread::Connection::setVsyncRate(uint32_t count) {
mEventThread->setVsyncRate(count, this);
}
void EventThread::Connection::requestNextVsync() {
mEventThread->requestNextVsync(this);
}
status_t EventThread::Connection::postEvent(
const DisplayEventReceiver::Event& event) {
ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1);
return size < 0 ? status_t(size) : status_t(NO_ERROR);
}
// ---------------------------------------------------------------------------
}; // namespace android }; // namespace android

View File

@ -20,13 +20,12 @@
#include <stdint.h> #include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include <gui/DisplayEventReceiver.h>
#include <gui/IDisplayEventConnection.h> #include <gui/IDisplayEventConnection.h>
#include <utils/Errors.h> #include <utils/Errors.h>
#include <utils/threads.h> #include <utils/threads.h>
#include <utils/KeyedVector.h> #include <utils/SortedVector.h>
#include "DisplayEventConnection.h"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -36,31 +35,43 @@ namespace android {
class SurfaceFlinger; class SurfaceFlinger;
class DisplayHardware; class DisplayHardware;
class DisplayEventConnection;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
class EventThread : public Thread { class EventThread : public Thread {
friend class DisplayEventConnection; class Connection : public BnDisplayEventConnection {
public:
Connection(const sp<EventThread>& eventThread);
status_t postEvent(const DisplayEventReceiver::Event& event);
// count >= 1 : continuous event. count is the vsync rate
// count == 0 : one-shot event that has not fired
// count ==-1 : one-shot event that fired this round / disabled
// count ==-2 : one-shot event that fired the round before
int32_t count;
private:
virtual ~Connection();
virtual void onFirstRef();
virtual sp<BitTube> getDataChannel() const;
virtual void setVsyncRate(uint32_t count);
virtual void requestNextVsync(); // asynchronous
sp<EventThread> const mEventThread;
sp<BitTube> const mChannel;
};
public: public:
EventThread(const sp<SurfaceFlinger>& flinger); EventThread(const sp<SurfaceFlinger>& flinger);
sp<DisplayEventConnection> createEventConnection() const; sp<Connection> createEventConnection() const;
status_t registerDisplayEventConnection(const sp<Connection>& connection);
status_t unregisterDisplayEventConnection(const wp<Connection>& connection);
status_t registerDisplayEventConnection( void setVsyncRate(uint32_t count, const sp<Connection>& connection);
const sp<DisplayEventConnection>& connection); void requestNextVsync(const sp<Connection>& connection);
status_t unregisterDisplayEventConnection(
const wp<DisplayEventConnection>& connection);
void setVsyncRate(uint32_t count,
const wp<DisplayEventConnection>& connection);
void requestNextVsync(const wp<DisplayEventConnection>& connection);
nsecs_t getLastVSyncTimestamp() const; nsecs_t getLastVSyncTimestamp() const;
nsecs_t getVSyncPeriod() const; nsecs_t getVSyncPeriod() const;
void dump(String8& result, char* buffer, size_t SIZE) const; void dump(String8& result, char* buffer, size_t SIZE) const;
@ -70,21 +81,7 @@ private:
virtual status_t readyToRun(); virtual status_t readyToRun();
virtual void onFirstRef(); virtual void onFirstRef();
struct ConnectionInfo { void removeDisplayEventConnection(const wp<Connection>& connection);
ConnectionInfo() : count(-1) { }
// count >= 1 : continuous event. count is the vsync rate
// count == 0 : one-shot event that has not fired
// count ==-1 : one-shot event that fired this round / disabled
// count ==-2 : one-shot event that fired the round before
int32_t count;
};
void removeDisplayEventConnection(
const wp<DisplayEventConnection>& connection);
ConnectionInfo* getConnectionInfoLocked(
const wp<DisplayEventConnection>& connection);
// constants // constants
sp<SurfaceFlinger> mFlinger; sp<SurfaceFlinger> mFlinger;
@ -94,7 +91,7 @@ private:
mutable Condition mCondition; mutable Condition mCondition;
// protected by mLock // protected by mLock
KeyedVector< wp<DisplayEventConnection>, ConnectionInfo > mDisplayEventConnections; SortedVector< wp<Connection> > mDisplayEventConnections;
nsecs_t mLastVSyncTimestamp; nsecs_t mLastVSyncTimestamp;
// main thread only // main thread only

View File

@ -50,7 +50,6 @@
#include "clz.h" #include "clz.h"
#include "DdmConnection.h" #include "DdmConnection.h"
#include "DisplayEventConnection.h"
#include "EventThread.h" #include "EventThread.h"
#include "GLExtensions.h" #include "GLExtensions.h"
#include "Layer.h" #include "Layer.h"

View File

@ -270,8 +270,9 @@ private:
}; };
struct State { struct State {
State() { State()
orientation = ISurfaceComposer::eOrientationDefault; : orientation(ISurfaceComposer::eOrientationDefault),
orientationFlags(0) {
} }
LayerVector layersSortedByZ; LayerVector layersSortedByZ;
uint8_t orientation; uint8_t orientation;