diff options
Diffstat (limited to 'services')
-rw-r--r-- | services/surfaceflinger/Android.mk | 7 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/DisplayHardware.cpp | 15 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/DisplayHardware.h | 5 | ||||
-rw-r--r-- | services/surfaceflinger/EventThread.cpp | 41 | ||||
-rw-r--r-- | services/surfaceflinger/EventThread.h | 8 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 46 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 18 | ||||
-rw-r--r-- | services/surfaceflinger/LayerBase.cpp | 11 | ||||
-rw-r--r-- | services/surfaceflinger/LayerBase.h | 6 | ||||
-rw-r--r-- | services/surfaceflinger/MessageQueue.cpp | 61 | ||||
-rw-r--r-- | services/surfaceflinger/MessageQueue.h | 16 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 314 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 8 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceTextureLayer.cpp | 4 | ||||
-rw-r--r-- | services/surfaceflinger/tests/vsync/vsync.cpp | 2 |
15 files changed, 408 insertions, 154 deletions
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 95d651a..fc211e5 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -23,18 +23,21 @@ 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/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp index 438a6da..986aec5 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -350,15 +350,28 @@ uint32_t DisplayHardware::getPageFlipCount() const { } // this needs to be thread safe -nsecs_t DisplayHardware::waitForVSync() const { +nsecs_t DisplayHardware::waitForRefresh() const { nsecs_t timestamp; if (mVSync.wait(×tamp) < 0) { // vsync not supported! usleep( getDelayToNextVSyncUs(×tamp) ); } + mLastHwVSync = timestamp; // FIXME: Not thread safe return timestamp; } +nsecs_t DisplayHardware::getRefreshTimestamp() const { + // this returns the last refresh timestamp. + // if the last one is not available, we estimate it based on + // the refresh period and whatever closest timestamp we have. + nsecs_t now = systemTime(); + return now - ((now - mLastHwVSync) % mRefreshPeriod); +} + +nsecs_t DisplayHardware::getRefreshPeriod() const { + return mRefreshPeriod; +} + int32_t DisplayHardware::getDelayToNextVSyncUs(nsecs_t* timestamp) const { Mutex::Autolock _l(mFakeVSyncMutex); const nsecs_t period = mRefreshPeriod; diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h index 77da272..02be4dc 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardware.h +++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h @@ -76,7 +76,9 @@ public: uint32_t getMaxViewportDims() const; // waits for the next vsync and returns the timestamp of when it happened - nsecs_t waitForVSync() const; + nsecs_t waitForRefresh() const; + nsecs_t getRefreshPeriod() const; + nsecs_t getRefreshTimestamp() const; uint32_t getPageFlipCount() const; EGLDisplay getEGLDisplay() const { return mDisplay; } @@ -119,6 +121,7 @@ private: mutable Mutex mFakeVSyncMutex; mutable nsecs_t mNextFakeVSync; nsecs_t mRefreshPeriod; + mutable nsecs_t mLastHwVSync; HWComposer* mHwc; diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp index 80ab519..af0da0b 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(); } } @@ -129,14 +145,15 @@ bool EventThread::threadLoop() { // at least one listener requested VSYNC mLock.unlock(); - timestamp = mHw.waitForVSync(); + timestamp = mHw.waitForRefresh(); mLock.lock(); mDeliveredEvents++; + mLastVSyncTimestamp = timestamp; // now see if we still need to report this VSYNC event - bool reportVsync = false; - size_t count = mDisplayEventConnections.size(); + const size_t count = mDisplayEventConnections.size(); for (size_t i=0 ; i<count ; i++) { + bool reportVsync = false; const ConnectionInfo& info( mDisplayEventConnections.valueAt(i)); if (info.count >= 1) { @@ -157,11 +174,7 @@ bool EventThread::threadLoop() { displayEventConnections.add(mDisplayEventConnections.keyAt(i)); } } - - if (reportVsync) { - break; - } - } while (true); + } while (!displayEventConnections.size()); // dispatch vsync events to listeners... vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; 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 d4c4b1f..9c04d59 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -38,6 +38,7 @@ #include "Layer.h" #include "SurfaceFlinger.h" #include "SurfaceTextureLayer.h" +#include <math.h> #define DEBUG_RESIZE 0 @@ -54,6 +55,8 @@ Layer::Layer(SurfaceFlinger* flinger, mCurrentTransform(0), mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), mCurrentOpacity(true), + mFrameLatencyNeeded(false), + mFrameLatencyOffset(0), mFormat(PIXEL_FORMAT_NONE), mGLExtensions(GLExtensions::getInstance()), mOpaqueLayer(true), @@ -65,6 +68,17 @@ Layer::Layer(SurfaceFlinger* flinger, glGenTextures(1, &mTextureName); } +void Layer::onLayerDisplayed() { + if (mFrameLatencyNeeded) { + const DisplayHardware& hw(graphicPlane(0).displayHardware()); + mFrameStats[mFrameLatencyOffset].timestamp = mSurfaceTexture->getTimestamp(); + mFrameStats[mFrameLatencyOffset].set = systemTime(); + mFrameStats[mFrameLatencyOffset].vsync = hw.getRefreshTimestamp(); + mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128; + mFrameLatencyNeeded = false; + } +} + void Layer::onFirstRef() { LayerBaseClient::onFirstRef(); @@ -83,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() @@ -408,6 +427,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) // update the active buffer mActiveBuffer = mSurfaceTexture->getCurrentBuffer(); + mFrameLatencyNeeded = true; const Rect crop(mSurfaceTexture->getCurrentCrop()); const uint32_t transform(mSurfaceTexture->getCurrentTransform()); @@ -543,6 +563,32 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const } } +void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const +{ + LayerBaseClient::dumpStats(result, buffer, SIZE); + const size_t o = mFrameLatencyOffset; + const DisplayHardware& hw(graphicPlane(0).displayHardware()); + const nsecs_t period = hw.getRefreshPeriod(); + result.appendFormat("%lld\n", period); + for (size_t i=0 ; i<128 ; i++) { + const size_t index = (o+i) % 128; + const nsecs_t time_app = mFrameStats[index].timestamp; + const nsecs_t time_set = mFrameStats[index].set; + const nsecs_t time_vsync = mFrameStats[index].vsync; + result.appendFormat("%lld\t%lld\t%lld\n", + time_app, + time_vsync, + time_set); + } + result.append("\n"); +} + +void Layer::clearStats() +{ + LayerBaseClient::clearStats(); + memset(mFrameStats, 0, sizeof(mFrameStats)); +} + uint32_t Layer::getEffectiveUsage(uint32_t usage) const { // TODO: should we do something special if mSecure is set? diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 2b9471b..2dd4da1 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -34,6 +34,7 @@ #include "LayerBase.h" #include "SurfaceTextureLayer.h" #include "Transform.h" +#include <utils/Timers.h> namespace android { @@ -78,12 +79,16 @@ public: // LayerBaseClient interface virtual wp<IBinder> getSurfaceTextureBinder() const; + virtual void onLayerDisplayed(); + // only for debugging inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; } protected: virtual void onFirstRef(); virtual void dump(String8& result, char* scratch, size_t size) const; + virtual void dumpStats(String8& result, char* buffer, size_t SIZE) const; + virtual void clearStats(); private: friend class SurfaceTextureLayer; @@ -110,6 +115,16 @@ private: uint32_t mCurrentTransform; uint32_t mCurrentScalingMode; bool mCurrentOpacity; + bool mFrameLatencyNeeded; + int mFrameLatencyOffset; + struct Statistics { + Statistics() : timestamp(0), set(0), vsync(0) { } + nsecs_t timestamp; // buffer timestamp + nsecs_t set; // buffer displayed timestamp + nsecs_t vsync; // vsync immediately before set + }; + // protected by mLock + Statistics mFrameStats[128]; // constants PixelFormat mFormat; @@ -121,9 +136,6 @@ private: bool mSecure; // no screenshots bool mProtectedByApp; // application requires protected path to external sink Region mPostedDirtyRegion; - - // binder thread, transaction thread - mutable Mutex mLock; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index 37879f1..d32fcdd 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -471,6 +471,9 @@ void LayerBase::drawWithOpenGL(const Region& clip) const void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const { const Layer::State& s(drawingState()); + s.transparentRegion.dump(result, "transparentRegion"); + transparentRegionScreen.dump(result, "transparentRegionScreen"); + visibleRegionScreen.dump(result, "visibleRegionScreen"); snprintf(buffer, SIZE, "+ %s %p (%s)\n" " " @@ -486,11 +489,15 @@ void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const result.append(buffer); } -void LayerBase::shortDump(String8& result, char* scratch, size_t size) const -{ +void LayerBase::shortDump(String8& result, char* scratch, size_t size) const { LayerBase::dump(result, scratch, size); } +void LayerBase::dumpStats(String8& result, char* scratch, size_t SIZE) const { +} + +void LayerBase::clearStats() { +} // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h index 7f62145..6b62c9d 100644 --- a/services/surfaceflinger/LayerBase.h +++ b/services/surfaceflinger/LayerBase.h @@ -205,10 +205,14 @@ public: /** called with the state lock when the surface is removed from the * current list */ virtual void onRemoved() { }; - + + virtual void onLayerDisplayed() { }; + /** always call base class first */ virtual void dump(String8& result, char* scratch, size_t size) const; virtual void shortDump(String8& result, char* scratch, size_t size) const; + virtual void dumpStats(String8& result, char* buffer, size_t SIZE) const; + virtual void clearStats(); enum { // flags for doTransaction() 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 af47402..ff70ec3 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -188,7 +188,8 @@ void SurfaceFlinger::binderDied(const wp<IBinder>& who) // the window manager died on us. prepare its eulogy. // reset screen orientation - setOrientation(0, eOrientationDefault, 0); + Vector<ComposerState> state; + setTransactionState(state, eOrientationDefault, 0); // restart the boot-animation property_set("ctl.start", "bootanim"); @@ -295,6 +296,7 @@ status_t SurfaceFlinger::readyToRun() // start the EventThread mEventThread = new EventThread(this); + mEventQueue.setEventThread(mEventThread); /* * We're now ready to accept clients... @@ -382,8 +384,7 @@ bool SurfaceFlinger::authenticateSurfaceTexture( // ---------------------------------------------------------------------------- sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() { - sp<DisplayEventConnection> result(new DisplayEventConnection(mEventThread)); - return result; + return mEventThread->createEventConnection(); } // ---------------------------------------------------------------------------- @@ -431,7 +432,6 @@ bool SurfaceFlinger::threadLoop() } else { // pretend we did the post hw.compositionComplete(); - hw.waitForVSync(); } return true; } @@ -445,6 +445,12 @@ void SurfaceFlinger::postFramebuffer() const nsecs_t now = systemTime(); mDebugInSwapBuffers = now; hw.flip(mSwapRegion); + + size_t numLayers = mVisibleLayersSortedByZ.size(); + for (size_t i = 0; i < numLayers; i++) { + mVisibleLayersSortedByZ[i]->onLayerDisplayed(); + } + mLastSwapBufferTime = systemTime() - now; mDebugInSwapBuffers = 0; mSwapRegion.clear(); @@ -1219,26 +1225,6 @@ void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& state, } } -int SurfaceFlinger::setOrientation(DisplayID dpy, - int orientation, uint32_t flags) -{ - if (CC_UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT)) - return BAD_VALUE; - - Mutex::Autolock _l(mStateLock); - if (mCurrentState.orientation != orientation) { - if (uint32_t(orientation)<=eOrientation270 || orientation==42) { - mCurrentState.orientationFlags = flags; - mCurrentState.orientation = orientation; - setTransactionFlags(eTransactionNeeded); - mTransactionCV.wait(mStateLock); - } else { - orientation = BAD_VALUE; - } - } - return orientation; -} - sp<ISurface> SurfaceFlinger::createSurface( ISurfaceComposerClient::surface_data_t* params, const String8& name, @@ -1463,14 +1449,6 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) IPCThreadState::self()->getCallingUid()); result.append(buffer); } else { - - // figure out if we're stuck somewhere - const nsecs_t now = systemTime(); - const nsecs_t inSwapBuffers(mDebugInSwapBuffers); - const nsecs_t inTransaction(mDebugInTransaction); - nsecs_t inSwapBuffersDuration = (inSwapBuffers) ? now-inSwapBuffers : 0; - nsecs_t inTransactionDuration = (inTransaction) ? now-inTransaction : 0; - // Try to get the main lock, but don't insist if we can't // (this would indicate SF is stuck, but we want to be able to // print something in dumpsys). @@ -1486,117 +1464,203 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) result.append(buffer); } - /* - * Dump the visible layer list - */ - const LayerVector& currentLayers = mCurrentState.layersSortedByZ; - const size_t count = currentLayers.size(); - snprintf(buffer, SIZE, "Visible layers (count = %d)\n", count); - result.append(buffer); - for (size_t i=0 ; i<count ; i++) { - const sp<LayerBase>& layer(currentLayers[i]); - layer->dump(result, buffer, SIZE); - const Layer::State& s(layer->drawingState()); - s.transparentRegion.dump(result, "transparentRegion"); - layer->transparentRegionScreen.dump(result, "transparentRegionScreen"); - layer->visibleRegionScreen.dump(result, "visibleRegionScreen"); - } + bool dumpAll = true; + size_t index = 0; + size_t numArgs = args.size(); + if (numArgs) { + dumpAll = false; - /* - * Dump the layers in the purgatory - */ - - const size_t purgatorySize = mLayerPurgatory.size(); - snprintf(buffer, SIZE, "Purgatory state (%d entries)\n", purgatorySize); - result.append(buffer); - for (size_t i=0 ; i<purgatorySize ; i++) { - const sp<LayerBase>& layer(mLayerPurgatory.itemAt(i)); - layer->shortDump(result, buffer, SIZE); - } + if ((index < numArgs) && + (args[index] == String16("--list"))) { + index++; + listLayersLocked(args, index, result, buffer, SIZE); + } - /* - * Dump SurfaceFlinger global state - */ + if ((index < numArgs) && + (args[index] == String16("--latency"))) { + index++; + dumpStatsLocked(args, index, result, buffer, SIZE); + } - snprintf(buffer, SIZE, "SurfaceFlinger global state:\n"); - result.append(buffer); + if ((index < numArgs) && + (args[index] == String16("--latency-clear"))) { + index++; + clearStatsLocked(args, index, result, buffer, SIZE); + } + } - const GLExtensions& extensions(GLExtensions::getInstance()); - snprintf(buffer, SIZE, "GLES: %s, %s, %s\n", - extensions.getVendor(), - extensions.getRenderer(), - extensions.getVersion()); - result.append(buffer); + if (dumpAll) { + dumpAllLocked(result, buffer, SIZE); + } - snprintf(buffer, SIZE, "EGL : %s\n", - eglQueryString(graphicPlane(0).getEGLDisplay(), - EGL_VERSION_HW_ANDROID)); - result.append(buffer); + if (locked) { + mStateLock.unlock(); + } + } + write(fd, result.string(), result.size()); + return NO_ERROR; +} - snprintf(buffer, SIZE, "EXTS: %s\n", extensions.getExtension()); +void SurfaceFlinger::listLayersLocked(const Vector<String16>& args, size_t& index, + String8& result, char* buffer, size_t SIZE) const +{ + const LayerVector& currentLayers = mCurrentState.layersSortedByZ; + const size_t count = currentLayers.size(); + for (size_t i=0 ; i<count ; i++) { + const sp<LayerBase>& layer(currentLayers[i]); + snprintf(buffer, SIZE, "%s\n", layer->getName().string()); result.append(buffer); + } +} - mWormholeRegion.dump(result, "WormholeRegion"); - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - snprintf(buffer, SIZE, - " orientation=%d, canDraw=%d\n", - mCurrentState.orientation, hw.canDraw()); - result.append(buffer); - snprintf(buffer, SIZE, - " last eglSwapBuffers() time: %f us\n" - " last transaction time : %f us\n" - " refresh-rate : %f fps\n" - " x-dpi : %f\n" - " y-dpi : %f\n", - mLastSwapBufferTime/1000.0, - mLastTransactionTime/1000.0, - hw.getRefreshRate(), - hw.getDpiX(), - hw.getDpiY()); - result.append(buffer); +void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index, + String8& result, char* buffer, size_t SIZE) const +{ + String8 name; + if (index < args.size()) { + name = String8(args[index]); + index++; + } - if (inSwapBuffersDuration || !locked) { - snprintf(buffer, SIZE, " eglSwapBuffers time: %f us\n", - inSwapBuffersDuration/1000.0); + const LayerVector& currentLayers = mCurrentState.layersSortedByZ; + const size_t count = currentLayers.size(); + for (size_t i=0 ; i<count ; i++) { + const sp<LayerBase>& layer(currentLayers[i]); + if (name.isEmpty()) { + snprintf(buffer, SIZE, "%s\n", layer->getName().string()); result.append(buffer); } + if (name.isEmpty() || (name == layer->getName())) { + layer->dumpStats(result, buffer, SIZE); + } + } +} - if (inTransactionDuration || !locked) { - snprintf(buffer, SIZE, " transaction time: %f us\n", - inTransactionDuration/1000.0); - result.append(buffer); +void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& index, + String8& result, char* buffer, size_t SIZE) const +{ + String8 name; + if (index < args.size()) { + name = String8(args[index]); + index++; + } + + const LayerVector& currentLayers = mCurrentState.layersSortedByZ; + const size_t count = currentLayers.size(); + for (size_t i=0 ; i<count ; i++) { + const sp<LayerBase>& layer(currentLayers[i]); + if (name.isEmpty() || (name == layer->getName())) { + layer->clearStats(); } + } +} - /* - * VSYNC state - */ - mEventThread->dump(result, buffer, SIZE); +void SurfaceFlinger::dumpAllLocked( + String8& result, char* buffer, size_t SIZE) const +{ + // figure out if we're stuck somewhere + const nsecs_t now = systemTime(); + const nsecs_t inSwapBuffers(mDebugInSwapBuffers); + const nsecs_t inTransaction(mDebugInTransaction); + nsecs_t inSwapBuffersDuration = (inSwapBuffers) ? now-inSwapBuffers : 0; + nsecs_t inTransactionDuration = (inTransaction) ? now-inTransaction : 0; - /* - * Dump HWComposer state - */ - HWComposer& hwc(hw.getHwComposer()); - snprintf(buffer, SIZE, "h/w composer state:\n"); - result.append(buffer); - snprintf(buffer, SIZE, " h/w composer %s and %s\n", - hwc.initCheck()==NO_ERROR ? "present" : "not present", - (mDebugDisableHWC || mDebugRegion) ? "disabled" : "enabled"); - result.append(buffer); - hwc.dump(result, buffer, SIZE, mVisibleLayersSortedByZ); + /* + * Dump the visible layer list + */ + const LayerVector& currentLayers = mCurrentState.layersSortedByZ; + const size_t count = currentLayers.size(); + snprintf(buffer, SIZE, "Visible layers (count = %d)\n", count); + result.append(buffer); + for (size_t i=0 ; i<count ; i++) { + const sp<LayerBase>& layer(currentLayers[i]); + layer->dump(result, buffer, SIZE); + } - /* - * Dump gralloc state - */ - const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get()); - alloc.dump(result); - hw.dump(result); + /* + * Dump the layers in the purgatory + */ - if (locked) { - mStateLock.unlock(); - } + const size_t purgatorySize = mLayerPurgatory.size(); + snprintf(buffer, SIZE, "Purgatory state (%d entries)\n", purgatorySize); + result.append(buffer); + for (size_t i=0 ; i<purgatorySize ; i++) { + const sp<LayerBase>& layer(mLayerPurgatory.itemAt(i)); + layer->shortDump(result, buffer, SIZE); } - write(fd, result.string(), result.size()); - return NO_ERROR; + + /* + * Dump SurfaceFlinger global state + */ + + snprintf(buffer, SIZE, "SurfaceFlinger global state:\n"); + result.append(buffer); + + const GLExtensions& extensions(GLExtensions::getInstance()); + snprintf(buffer, SIZE, "GLES: %s, %s, %s\n", + extensions.getVendor(), + extensions.getRenderer(), + extensions.getVersion()); + result.append(buffer); + + snprintf(buffer, SIZE, "EGL : %s\n", + eglQueryString(graphicPlane(0).getEGLDisplay(), + EGL_VERSION_HW_ANDROID)); + result.append(buffer); + + snprintf(buffer, SIZE, "EXTS: %s\n", extensions.getExtension()); + result.append(buffer); + + mWormholeRegion.dump(result, "WormholeRegion"); + const DisplayHardware& hw(graphicPlane(0).displayHardware()); + snprintf(buffer, SIZE, + " orientation=%d, canDraw=%d\n", + mCurrentState.orientation, hw.canDraw()); + result.append(buffer); + snprintf(buffer, SIZE, + " last eglSwapBuffers() time: %f us\n" + " last transaction time : %f us\n" + " refresh-rate : %f fps\n" + " x-dpi : %f\n" + " y-dpi : %f\n", + mLastSwapBufferTime/1000.0, + mLastTransactionTime/1000.0, + hw.getRefreshRate(), + hw.getDpiX(), + hw.getDpiY()); + result.append(buffer); + + snprintf(buffer, SIZE, " eglSwapBuffers time: %f us\n", + inSwapBuffersDuration/1000.0); + result.append(buffer); + + snprintf(buffer, SIZE, " transaction time: %f us\n", + inTransactionDuration/1000.0); + result.append(buffer); + + /* + * VSYNC state + */ + mEventThread->dump(result, buffer, SIZE); + + /* + * Dump HWComposer state + */ + HWComposer& hwc(hw.getHwComposer()); + snprintf(buffer, SIZE, "h/w composer state:\n"); + result.append(buffer); + snprintf(buffer, SIZE, " h/w composer %s and %s\n", + hwc.initCheck()==NO_ERROR ? "present" : "not present", + (mDebugDisableHWC || mDebugRegion) ? "disabled" : "enabled"); + result.append(buffer); + hwc.dump(result, buffer, SIZE, mVisibleLayersSortedByZ); + + /* + * Dump gralloc state + */ + const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get()); + alloc.dump(result); + hw.dump(result); } status_t SurfaceFlinger::onTransact( diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 7f6c90c..c24a9de 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -170,7 +170,6 @@ public: virtual void bootFinished(); virtual void setTransactionState(const Vector<ComposerState>& state, int orientation, uint32_t flags); - virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags); virtual bool authenticateSurfaceTexture(const sp<ISurfaceTexture>& surface) const; virtual sp<IDisplayEventConnection> createDisplayEventConnection(); @@ -337,6 +336,13 @@ private: void debugFlashRegions(); void drawWormhole() const; + void listLayersLocked(const Vector<String16>& args, size_t& index, + String8& result, char* buffer, size_t SIZE) const; + void dumpStatsLocked(const Vector<String16>& args, size_t& index, + String8& result, char* buffer, size_t SIZE) const; + void clearStatsLocked(const Vector<String16>& args, size_t& index, + String8& result, char* buffer, size_t SIZE) const; + void dumpAllLocked(String8& result, char* buffer, size_t SIZE) const; mutable MessageQueue mEventQueue; 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 diff --git a/services/surfaceflinger/tests/vsync/vsync.cpp b/services/surfaceflinger/tests/vsync/vsync.cpp index 4f79080..b0d54c4 100644 --- a/services/surfaceflinger/tests/vsync/vsync.cpp +++ b/services/surfaceflinger/tests/vsync/vsync.cpp @@ -55,6 +55,8 @@ int main(int argc, char** argv) loop->addFd(myDisplayEvent.getFd(), 0, ALOOPER_EVENT_INPUT, receiver, &myDisplayEvent); + myDisplayEvent.setVsyncRate(1); + do { //printf("about to poll...\n"); int32_t ret = loop->pollOnce(-1); |