diff options
-rw-r--r-- | services/surfaceflinger/Android.mk | 6 | ||||
-rw-r--r-- | services/surfaceflinger/EventThread.cpp | 29 | ||||
-rw-r--r-- | services/surfaceflinger/EventThread.h | 8 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 5 | ||||
-rw-r--r-- | services/surfaceflinger/MessageQueue.cpp | 61 | ||||
-rw-r--r-- | services/surfaceflinger/MessageQueue.h | 16 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 5 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceTextureLayer.cpp | 4 |
8 files changed, 120 insertions, 14 deletions
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 95d651a..732af53 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -23,18 +23,22 @@ LOCAL_SRC_FILES:= \ LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES +ifeq ($(TARGET_HAS_WAITFORVSYNC), true) + LOCAL_CFLAGS += -DHAS_WAITFORVSYNC +endif + ifeq ($(TARGET_BOARD_PLATFORM), omap3) LOCAL_CFLAGS += -DNO_RGBX_8888 endif ifeq ($(TARGET_BOARD_PLATFORM), omap4) LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY + LOCAL_CFLAGS += -DUSE_TRIPLE_BUFFERING=1 endif ifeq ($(TARGET_BOARD_PLATFORM), s5pc110) LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -DNEVER_DEFAULT_TO_ASYNC_MODE LOCAL_CFLAGS += -DREFRESH_RATE=56 endif - LOCAL_SHARED_LIBRARIES := \ libcutils \ libhardware \ diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp index 6796d7d..92d4266 100644 --- a/services/surfaceflinger/EventThread.cpp +++ b/services/surfaceflinger/EventThread.cpp @@ -36,6 +36,7 @@ namespace android { EventThread::EventThread(const sp<SurfaceFlinger>& flinger) : mFlinger(flinger), mHw(flinger->graphicPlane(0).displayHardware()), + mLastVSyncTimestamp(0), mDeliveredEvents(0) { } @@ -44,6 +45,20 @@ void EventThread::onFirstRef() { run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); } +sp<DisplayEventConnection> EventThread::createEventConnection() const { + return new DisplayEventConnection(const_cast<EventThread*>(this)); +} + +nsecs_t EventThread::getLastVSyncTimestamp() const { + Mutex::Autolock _l(mLock); + return mLastVSyncTimestamp; +} + +nsecs_t EventThread::getVSyncPeriod() const { + return mHw.getRefreshPeriod(); + +} + status_t EventThread::registerDisplayEventConnection( const sp<DisplayEventConnection>& connection) { Mutex::Autolock _l(mLock); @@ -80,8 +95,11 @@ void EventThread::setVsyncRate(uint32_t count, Mutex::Autolock _l(mLock); ConnectionInfo* info = getConnectionInfoLocked(connection); if (info) { - info->count = (count == 0) ? -1 : count; - mCondition.signal(); + const int32_t new_count = (count == 0) ? -1 : count; + if (info->count != new_count) { + info->count = new_count; + mCondition.signal(); + } } } } @@ -90,10 +108,8 @@ void EventThread::requestNextVsync( const wp<DisplayEventConnection>& connection) { Mutex::Autolock _l(mLock); ConnectionInfo* info = getConnectionInfoLocked(connection); - if (info) { - if (info->count < 0) { - info->count = 0; - } + if (info && info->count < 0) { + info->count = 0; mCondition.signal(); } } @@ -132,6 +148,7 @@ bool EventThread::threadLoop() { timestamp = mHw.waitForRefresh(); mLock.lock(); mDeliveredEvents++; + mLastVSyncTimestamp = timestamp; // now see if we still need to report this VSYNC event bool reportVsync = false; diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h index 35bd299..3a3071e 100644 --- a/services/surfaceflinger/EventThread.h +++ b/services/surfaceflinger/EventThread.h @@ -36,6 +36,7 @@ namespace android { class SurfaceFlinger; class DisplayHardware; +class DisplayEventConnection; // --------------------------------------------------------------------------- @@ -45,6 +46,8 @@ class EventThread : public Thread { public: EventThread(const sp<SurfaceFlinger>& flinger); + sp<DisplayEventConnection> createEventConnection() const; + status_t registerDisplayEventConnection( const sp<DisplayEventConnection>& connection); @@ -56,6 +59,10 @@ public: void requestNextVsync(const wp<DisplayEventConnection>& connection); + nsecs_t getLastVSyncTimestamp() const; + + nsecs_t getVSyncPeriod() const; + void dump(String8& result, char* buffer, size_t SIZE) const; private: @@ -88,6 +95,7 @@ private: // protected by mLock KeyedVector< wp<DisplayEventConnection>, ConnectionInfo > mDisplayEventConnections; + nsecs_t mLastVSyncTimestamp; // main thread only size_t mDeliveredEvents; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 8e87b88..9c04d59 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -97,7 +97,12 @@ void Layer::onFirstRef() mSurfaceTexture = new SurfaceTextureLayer(mTextureName, this); mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this)); mSurfaceTexture->setSynchronousMode(true); +#ifdef USE_TRIPLE_BUFFERING +#warning "using triple buffering" + mSurfaceTexture->setBufferCountServer(3); +#else mSurfaceTexture->setBufferCountServer(2); +#endif } Layer::~Layer() diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp index cbd530c..70711e7 100644 --- a/services/surfaceflinger/MessageQueue.cpp +++ b/services/surfaceflinger/MessageQueue.cpp @@ -18,12 +18,17 @@ #include <errno.h> #include <sys/types.h> +#include <binder/IPCThreadState.h> + #include <utils/threads.h> #include <utils/Timers.h> #include <utils/Log.h> -#include <binder/IPCThreadState.h> + +#include <gui/IDisplayEventConnection.h> +#include <gui/BitTube.h> #include "MessageQueue.h" +#include "EventThread.h" namespace android { @@ -51,6 +56,15 @@ MessageQueue::MessageQueue() MessageQueue::~MessageQueue() { } +void MessageQueue::setEventThread(const sp<EventThread>& eventThread) +{ + mEventThread = eventThread; + mEvents = eventThread->createEventConnection(); + mEventTube = mEvents->getDataChannel(); + mLooper->addFd(mEventTube->getFd(), 0, ALOOPER_EVENT_INPUT, + MessageQueue::cb_eventReceiver, this); +} + void MessageQueue::waitMessage() { do { IPCThreadState::self()->flushCommands(); @@ -93,13 +107,54 @@ status_t MessageQueue::postMessage( return NO_ERROR; } -status_t MessageQueue::invalidate() { +void MessageQueue::scheduleWorkASAP() { if (android_atomic_or(1, &mWorkPending) == 0) { mLooper->wake(); - } + } +} + +status_t MessageQueue::invalidate() { + mEvents->requestNextVsync(); return NO_ERROR; } +int MessageQueue::cb_eventReceiver(int fd, int events, void* data) { + MessageQueue* queue = reinterpret_cast<MessageQueue *>(data); + return queue->eventReceiver(fd, events); +} + +int MessageQueue::eventReceiver(int fd, int events) { + ssize_t n; + DisplayEventReceiver::Event buffer[8]; + while ((n = getEvents(buffer, 8)) > 0) { + for (int i=0 ; i<n ; i++) { + if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { + scheduleWorkASAP(); + break; + } + } + } + return 1; +} + +ssize_t MessageQueue::getEvents( + DisplayEventReceiver::Event* events, size_t count) +{ + ssize_t size = mEventTube->read(events, sizeof(events[0])*count); + ALOGE_IF(size<0, "MessageQueue::getEvents error (%s)", strerror(-size)); + if (size >= 0) { + // Note: if (size % sizeof(events[0])) != 0, we've got a + // partial read. This can happen if the queue filed up (ie: if we + // didn't pull from it fast enough). + // We discard the partial event and rely on the sender to + // re-send the event if appropriate (some events, like VSYNC + // can be lost forever). + // returns number of events read + size /= sizeof(events[0]); + } + return size; +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h index 2317d81..5ea197d 100644 --- a/services/surfaceflinger/MessageQueue.h +++ b/services/surfaceflinger/MessageQueue.h @@ -25,10 +25,15 @@ #include <utils/Timers.h> #include <utils/Looper.h> +#include <gui/DisplayEventReceiver.h> + #include "Barrier.h" namespace android { +class IDisplayEventConnection; +class EventThread; + // --------------------------------------------------------------------------- class MessageBase : public MessageHandler @@ -55,11 +60,20 @@ private: class MessageQueue { sp<Looper> mLooper; - volatile int32_t mWorkPending; + sp<EventThread> mEventThread; + sp<IDisplayEventConnection> mEvents; + sp<BitTube> mEventTube; + int32_t mWorkPending; + + static int cb_eventReceiver(int fd, int events, void* data); + int eventReceiver(int fd, int events); + ssize_t getEvents(DisplayEventReceiver::Event* events, size_t count); + void scheduleWorkASAP(); public: MessageQueue(); ~MessageQueue(); + void setEventThread(const sp<EventThread>& events); void waitMessage(); status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 887aee7..ff70ec3 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -296,6 +296,7 @@ status_t SurfaceFlinger::readyToRun() // start the EventThread mEventThread = new EventThread(this); + mEventQueue.setEventThread(mEventThread); /* * We're now ready to accept clients... @@ -383,8 +384,7 @@ bool SurfaceFlinger::authenticateSurfaceTexture( // ---------------------------------------------------------------------------- sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() { - sp<DisplayEventConnection> result(new DisplayEventConnection(mEventThread)); - return result; + return mEventThread->createEventConnection(); } // ---------------------------------------------------------------------------- @@ -432,7 +432,6 @@ bool SurfaceFlinger::threadLoop() } else { // pretend we did the post hw.compositionComplete(); - hw.waitForRefresh(); } return true; } diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp index 259b937..49e8e63 100644 --- a/services/surfaceflinger/SurfaceTextureLayer.cpp +++ b/services/surfaceflinger/SurfaceTextureLayer.cpp @@ -94,6 +94,10 @@ status_t SurfaceTextureLayer::connect(int api, *outTransform = orientation; } switch(api) { + case NATIVE_WINDOW_API_CPU: + // SurfaceTextureClient supports only 2 buffers for CPU connections + this->setBufferCountServer(2); + break; case NATIVE_WINDOW_API_MEDIA: case NATIVE_WINDOW_API_CAMERA: // Camera preview and videos are rate-limited on the producer |