From 9a9dbd5921b6c138673eea206a1a067a01928cb5 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 31 Jan 2012 18:24:27 -0800 Subject: [PATCH] separate transactions from updates with this changes, SF transactions are handled as soon as possible but do not trigger updates. the update is delayed until the next vsync. this allows us to work much better without requiring triple-buffering. Change-Id: I1fa10794d0cf742129f0877698b7b1e1f2ec7401 --- include/gui/DisplayEventReceiver.h | 2 + libs/gui/DisplayEventReceiver.cpp | 8 +- services/surfaceflinger/Android.mk | 1 - services/surfaceflinger/Layer.cpp | 39 +++- services/surfaceflinger/Layer.h | 4 + services/surfaceflinger/LayerBase.cpp | 19 +- services/surfaceflinger/LayerBase.h | 17 +- services/surfaceflinger/MessageQueue.cpp | 80 +++---- services/surfaceflinger/MessageQueue.h | 32 ++- services/surfaceflinger/SurfaceFlinger.cpp | 233 ++++++++++++--------- services/surfaceflinger/SurfaceFlinger.h | 8 +- 11 files changed, 264 insertions(+), 179 deletions(-) diff --git a/include/gui/DisplayEventReceiver.h b/include/gui/DisplayEventReceiver.h index a28137785e9ab..7bca8d6ea8926 100644 --- a/include/gui/DisplayEventReceiver.h +++ b/include/gui/DisplayEventReceiver.h @@ -95,6 +95,8 @@ public: * should be destroyed and getEvents() shouldn't be called again. */ ssize_t getEvents(Event* events, size_t count); + static ssize_t getEvents(const sp& dataChannel, + Event* events, size_t count); /* * setVsyncRate() sets the Event::VSync delivery rate. A value of diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp index 3b3ccaaf74c5e..6a4763d5a72b2 100644 --- a/libs/gui/DisplayEventReceiver.cpp +++ b/libs/gui/DisplayEventReceiver.cpp @@ -80,7 +80,13 @@ status_t DisplayEventReceiver::requestNextVsync() { ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events, size_t count) { - ssize_t size = mDataChannel->read(events, sizeof(events[0])*count); + return DisplayEventReceiver::getEvents(mDataChannel, events, count); +} + +ssize_t DisplayEventReceiver::getEvents(const sp& dataChannel, + Event* events, size_t count) +{ + ssize_t size = dataChannel->read(events, sizeof(events[0])*count); ALOGE_IF(size<0, "DisplayEventReceiver::getEvents error (%s)", strerror(-size)); diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index fc211e56b91c8..8b4c0744b7c2e 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -32,7 +32,6 @@ ifeq ($(TARGET_BOARD_PLATFORM), omap3) 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 diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 9c04d597205c5..64f72d5c87142 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -55,6 +55,7 @@ Layer::Layer(SurfaceFlinger* flinger, mCurrentTransform(0), mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), mCurrentOpacity(true), + mRefreshPending(0), mFrameLatencyNeeded(false), mFrameLatencyOffset(0), mFormat(PIXEL_FORMAT_NONE), @@ -97,12 +98,7 @@ 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() @@ -113,7 +109,7 @@ Layer::~Layer() void Layer::onFrameQueued() { android_atomic_inc(&mQueuedFrames); - mFlinger->signalEvent(); + mFlinger->signalLayerUpdate(); } // called with SurfaceFlinger::mStateLock as soon as the layer is entered @@ -407,16 +403,37 @@ bool Layer::isCropped() const { // pageflip handling... // ---------------------------------------------------------------------------- +bool Layer::onPreComposition() +{ + // if there was more than one pending update, request a refresh + if (mRefreshPending >= 2) { + mRefreshPending = 0; + return true; + } + mRefreshPending = 0; + return false; +} + void Layer::lockPageFlip(bool& recomputeVisibleRegions) { if (mQueuedFrames > 0) { + + // if we've already called updateTexImage() without going through + // a composition step, we have to skip this layer at this point + // because we cannot call updateTeximage() without a corresponding + // compositionComplete() call. + // we'll trigger an update in onPreComposition(). + if (mRefreshPending++) { + return; + } + // Capture the old state of the layer for comparisons later const bool oldOpacity = isOpaque(); sp oldActiveBuffer = mActiveBuffer; // signal another event if we have more frames pending if (android_atomic_dec(&mQueuedFrames) > 1) { - mFlinger->signalEvent(); + mFlinger->signalLayerUpdate(); } if (mSurfaceTexture->updateTexImage() < NO_ERROR) { @@ -519,6 +536,10 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) void Layer::unlockPageFlip( const Transform& planeTransform, Region& outDirtyRegion) { + if (mRefreshPending >= 2) { + return; + } + Region dirtyRegion(mPostedDirtyRegion); if (!dirtyRegion.isEmpty()) { mPostedDirtyRegion.clear(); @@ -552,9 +573,9 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const snprintf(buffer, SIZE, " " "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X]," - " transform-hint=0x%02x, queued-frames=%d\n", + " transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n", mFormat, w0, h0, s0,f0, - getTransformHint(), mQueuedFrames); + getTransformHint(), mQueuedFrames, mRefreshPending); result.append(buffer); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 2dd4da130dcfc..bf30608c97131 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -80,6 +80,7 @@ public: virtual wp getSurfaceTextureBinder() const; virtual void onLayerDisplayed(); + virtual bool onPreComposition(); // only for debugging inline const sp& getActiveBuffer() const { return mActiveBuffer; } @@ -115,14 +116,17 @@ private: uint32_t mCurrentTransform; uint32_t mCurrentScalingMode; bool mCurrentOpacity; + size_t mRefreshPending; 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]; diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index d32fcdd62528a..44aafdf8c871e 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -47,8 +47,7 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display) mOrientation(0), mPlaneOrientation(0), mTransactionFlags(0), - mPremultipliedAlpha(true), mName("unnamed"), mDebug(false), - mInvalidate(0) + mPremultipliedAlpha(true), mName("unnamed"), mDebug(false) { const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware()); mFlags = hw.getFlags(); @@ -262,23 +261,11 @@ void LayerBase::validateVisibility(const Transform& planeTransform) mTransformedBounds = tr.makeBounds(w, h); } -void LayerBase::lockPageFlip(bool& recomputeVisibleRegions) -{ +void LayerBase::lockPageFlip(bool& recomputeVisibleRegions) { } void LayerBase::unlockPageFlip( - const Transform& planeTransform, Region& outDirtyRegion) -{ - if ((android_atomic_and(~1, &mInvalidate)&1) == 1) { - outDirtyRegion.orSelf(visibleRegionScreen); - } -} - -void LayerBase::invalidate() -{ - if ((android_atomic_or(1, &mInvalidate)&1) == 0) { - mFlinger->signalEvent(); - } + const Transform& planeTransform, Region& outDirtyRegion) { } void LayerBase::drawRegion(const Region& reg) const diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h index 6b62c9db7836e..b8f7680b2b253 100644 --- a/services/surfaceflinger/LayerBase.h +++ b/services/surfaceflinger/LayerBase.h @@ -103,8 +103,6 @@ public: Rect visibleBounds() const; void drawRegion(const Region& reg) const; - void invalidate(); - virtual sp getLayerBaseClient() const { return 0; } virtual sp getLayer() const { return 0; } @@ -204,9 +202,16 @@ public: /** called with the state lock when the surface is removed from the * current list */ - virtual void onRemoved() { }; + virtual void onRemoved() { } - virtual void onLayerDisplayed() { }; + /** called after page-flip + */ + virtual void onLayerDisplayed() { } + + /** called before composition. + * returns true if the layer has pending updates. + */ + virtual bool onPreComposition() { return false; } /** always call base class first */ virtual void dump(String8& result, char* scratch, size_t size) const; @@ -275,10 +280,6 @@ protected: mutable bool mDebug; - // atomic - volatile int32_t mInvalidate; - - public: // called from class SurfaceFlinger virtual ~LayerBase(); diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp index 70711e73ee46b..1ff3567f4df6e 100644 --- a/services/surfaceflinger/MessageQueue.cpp +++ b/services/surfaceflinger/MessageQueue.cpp @@ -29,6 +29,7 @@ #include "MessageQueue.h" #include "EventThread.h" +#include "SurfaceFlinger.h" namespace android { @@ -48,14 +49,47 @@ void MessageBase::handleMessage(const Message&) { // --------------------------------------------------------------------------- +void MessageQueue::Handler::signalRefresh() { + if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) { + mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH)); + } +} + +void MessageQueue::Handler::signalInvalidate() { + if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) { + mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE)); + } +} + +void MessageQueue::Handler::handleMessage(const Message& message) { + switch (message.what) { + case INVALIDATE: + android_atomic_and(~eventMaskInvalidate, &mEventMask); + mQueue.mFlinger->onMessageReceived(message.what); + break; + case REFRESH: + android_atomic_and(~eventMaskRefresh, &mEventMask); + mQueue.mFlinger->onMessageReceived(message.what); + break; + } +} + +// --------------------------------------------------------------------------- + MessageQueue::MessageQueue() - : mLooper(new Looper(true)), mWorkPending(0) { } MessageQueue::~MessageQueue() { } +void MessageQueue::init(const sp& flinger) +{ + mFlinger = flinger; + mLooper = new Looper(true); + mHandler = new Handler(*this); +} + void MessageQueue::setEventThread(const sp& eventThread) { mEventThread = eventThread; @@ -68,25 +102,16 @@ void MessageQueue::setEventThread(const sp& eventThread) void MessageQueue::waitMessage() { do { IPCThreadState::self()->flushCommands(); - int32_t ret = mLooper->pollOnce(-1); switch (ret) { case ALOOPER_POLL_WAKE: case ALOOPER_POLL_CALLBACK: - // callback and/or wake - if (android_atomic_and(0, &mWorkPending)) { - return; - } continue; - + case ALOOPER_POLL_ERROR: + ALOGE("ALOOPER_POLL_ERROR"); case ALOOPER_POLL_TIMEOUT: // timeout (should not happen) continue; - - case ALOOPER_POLL_ERROR: - ALOGE("ALOOPER_POLL_ERROR"); - continue; - default: // should not happen ALOGE("Looper::pollOnce() returned unknown status %d", ret); @@ -107,15 +132,12 @@ status_t MessageQueue::postMessage( return NO_ERROR; } -void MessageQueue::scheduleWorkASAP() { - if (android_atomic_or(1, &mWorkPending) == 0) { - mLooper->wake(); - } +void MessageQueue::invalidate() { + mHandler->signalInvalidate(); } -status_t MessageQueue::invalidate() { +void MessageQueue::refresh() { mEvents->requestNextVsync(); - return NO_ERROR; } int MessageQueue::cb_eventReceiver(int fd, int events, void* data) { @@ -126,10 +148,10 @@ int MessageQueue::cb_eventReceiver(int fd, int events, void* data) { int MessageQueue::eventReceiver(int fd, int events) { ssize_t n; DisplayEventReceiver::Event buffer[8]; - while ((n = getEvents(buffer, 8)) > 0) { + while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) { for (int i=0 ; isignalRefresh(); break; } } @@ -137,24 +159,6 @@ int MessageQueue::eventReceiver(int fd, int events) { 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 5ea197dc70c95..ea29e7ef729ca 100644 --- a/services/surfaceflinger/MessageQueue.h +++ b/services/surfaceflinger/MessageQueue.h @@ -33,6 +33,7 @@ namespace android { class IDisplayEventConnection; class EventThread; +class SurfaceFlinger; // --------------------------------------------------------------------------- @@ -59,25 +60,48 @@ private: // --------------------------------------------------------------------------- class MessageQueue { + class Handler : public MessageHandler { + enum { + eventMaskInvalidate = 0x1, + eventMaskRefresh = 0x2 + }; + MessageQueue& mQueue; + int32_t mEventMask; + public: + Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) { } + virtual void handleMessage(const Message& message); + void signalRefresh(); + void signalInvalidate(); + }; + + friend class Handler; + + sp mFlinger; sp mLooper; sp mEventThread; sp mEvents; sp mEventTube; - int32_t mWorkPending; + sp mHandler; + 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: + enum { + INVALIDATE = 0, + REFRESH = 1, + }; + MessageQueue(); ~MessageQueue(); + void init(const sp& flinger); void setEventThread(const sp& events); void waitMessage(); status_t postMessage(const sp& message, nsecs_t reltime=0); - status_t invalidate(); + void invalidate(); + void refresh(); }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index ff70ec327eb33..870235bffa1b5 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -125,11 +125,34 @@ void SurfaceFlinger::init() ALOGI_IF(mDebugDDMS, "DDMS debugging enabled"); } +void SurfaceFlinger::onFirstRef() +{ + mEventQueue.init(this); + + run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY); + + // Wait for the main thread to be done with its initialization + mReadyToRunBarrier.wait(); +} + + SurfaceFlinger::~SurfaceFlinger() { glDeleteTextures(1, &mWormholeTexName); } +void SurfaceFlinger::binderDied(const wp& who) +{ + // the window manager died on us. prepare its eulogy. + + // reset screen orientation + Vector state; + setTransactionState(state, eOrientationDefault, 0); + + // restart the boot-animation + property_set("ctl.start", "bootanim"); +} + sp SurfaceFlinger::getCblk() const { return mServerHeap; @@ -183,26 +206,6 @@ void SurfaceFlinger::bootFinished() property_set("ctl.stop", "bootanim"); } -void SurfaceFlinger::binderDied(const wp& who) -{ - // the window manager died on us. prepare its eulogy. - - // reset screen orientation - Vector state; - setTransactionState(state, eOrientationDefault, 0); - - // restart the boot-animation - property_set("ctl.start", "bootanim"); -} - -void SurfaceFlinger::onFirstRef() -{ - run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY); - - // Wait for the main thread to be done with its initialization - mReadyToRunBarrier.wait(); -} - static inline uint16_t pack565(int r, int g, int b) { return (r<<11)|(g<<5)|b; } @@ -310,34 +313,6 @@ status_t SurfaceFlinger::readyToRun() return NO_ERROR; } -// ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark Events Handler -#endif - -void SurfaceFlinger::waitForEvent() { - mEventQueue.waitMessage(); -} - -void SurfaceFlinger::signalEvent() { - mEventQueue.invalidate(); -} - -status_t SurfaceFlinger::postMessageAsync(const sp& msg, - nsecs_t reltime, uint32_t flags) { - return mEventQueue.postMessage(msg, reltime); -} - -status_t SurfaceFlinger::postMessageSync(const sp& msg, - nsecs_t reltime, uint32_t flags) { - status_t res = mEventQueue.postMessage(msg, reltime); - if (res == NO_ERROR) { - msg->wait(); - } - return res; -} - // ---------------------------------------------------------------------------- bool SurfaceFlinger::authenticateSurfaceTexture( @@ -388,54 +363,93 @@ sp SurfaceFlinger::createDisplayEventConnection() { } // ---------------------------------------------------------------------------- -#if 0 -#pragma mark - -#pragma mark Main loop -#endif + +void SurfaceFlinger::waitForEvent() { + mEventQueue.waitMessage(); +} + +void SurfaceFlinger::signalTransaction() { + mEventQueue.invalidate(); +} + +void SurfaceFlinger::signalLayerUpdate() { + mEventQueue.invalidate(); +} + +void SurfaceFlinger::signalRefresh() { + mEventQueue.refresh(); +} + +status_t SurfaceFlinger::postMessageAsync(const sp& msg, + nsecs_t reltime, uint32_t flags) { + return mEventQueue.postMessage(msg, reltime); +} + +status_t SurfaceFlinger::postMessageSync(const sp& msg, + nsecs_t reltime, uint32_t flags) { + status_t res = mEventQueue.postMessage(msg, reltime); + if (res == NO_ERROR) { + msg->wait(); + } + return res; +} bool SurfaceFlinger::threadLoop() { waitForEvent(); - - // check for transactions - if (CC_UNLIKELY(mConsoleSignals)) { - handleConsoleEvents(); - } - - // if we're in a global transaction, don't do anything. - const uint32_t mask = eTransactionNeeded | eTraversalNeeded; - uint32_t transactionFlags = peekTransactionFlags(mask); - if (CC_UNLIKELY(transactionFlags)) { - handleTransaction(transactionFlags); - } - - // post surfaces (if needed) - handlePageFlip(); - - if (mDirtyRegion.isEmpty()) { - // nothing new to do. - return true; - } - - if (CC_UNLIKELY(mHwWorkListDirty)) { - // build the h/w work list - handleWorkList(); - } - - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - if (CC_LIKELY(hw.canDraw())) { - // repaint the framebuffer (if needed) - handleRepaint(); - // inform the h/w that we're done compositing - hw.compositionComplete(); - postFramebuffer(); - } else { - // pretend we did the post - hw.compositionComplete(); - } return true; } +void SurfaceFlinger::onMessageReceived(int32_t what) +{ + switch (what) { + case MessageQueue::INVALIDATE: { + // check for transactions + if (CC_UNLIKELY(mConsoleSignals)) { + handleConsoleEvents(); + } + + // if we're in a global transaction, don't do anything. + const uint32_t mask = eTransactionNeeded | eTraversalNeeded; + uint32_t transactionFlags = peekTransactionFlags(mask); + if (CC_UNLIKELY(transactionFlags)) { + handleTransaction(transactionFlags); + } + + // post surfaces (if needed) + handlePageFlip(); + + if (!mDirtyRegion.isEmpty()) { + signalRefresh(); + } + } break; + + case MessageQueue::REFRESH: { + if (!mDirtyRegion.isEmpty()) { + // NOTE: it is mandatory to call hw.compositionComplete() + // after handleRefresh() + handleRefresh(); + + const DisplayHardware& hw(graphicPlane(0).displayHardware()); + if (CC_UNLIKELY(mHwWorkListDirty)) { + // build the h/w work list + handleWorkList(); + } + if (CC_LIKELY(hw.canDraw())) { + // repaint the framebuffer (if needed) + handleRepaint(); + // inform the h/w that we're done compositing + hw.compositionComplete(); + postFramebuffer(); + } else { + // pretend we did the post + hw.compositionComplete(); + } + } + } break; + } +} + void SurfaceFlinger::postFramebuffer() { // this should never happen. we do the flip anyways so we don't @@ -717,13 +731,13 @@ void SurfaceFlinger::commitTransaction() void SurfaceFlinger::handlePageFlip() { - bool visibleRegions = mVisibleRegionsDirty; - const LayerVector& currentLayers(mDrawingState.layersSortedByZ); - visibleRegions |= lockPageFlip(currentLayers); + const DisplayHardware& hw = graphicPlane(0).displayHardware(); + const Region screenRegion(hw.bounds()); - const DisplayHardware& hw = graphicPlane(0).displayHardware(); - const Region screenRegion(hw.bounds()); - if (visibleRegions) { + const LayerVector& currentLayers(mDrawingState.layersSortedByZ); + const bool visibleRegions = lockPageFlip(currentLayers); + + if (visibleRegions || mVisibleRegionsDirty) { Region opaqueRegion; computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion); @@ -770,7 +784,7 @@ void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers) { const GraphicPlane& plane(graphicPlane(0)); const Transform& planeTransform(plane.transform()); - size_t count = currentLayers.size(); + const size_t count = currentLayers.size(); sp const* layers = currentLayers.array(); for (size_t i=0 ; i& layer(layers[i]); @@ -778,6 +792,23 @@ void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers) } } +void SurfaceFlinger::handleRefresh() +{ + bool needInvalidate = false; + const LayerVector& currentLayers(mDrawingState.layersSortedByZ); + const size_t count = currentLayers.size(); + for (size_t i=0 ; i& layer(currentLayers[i]); + if (layer->onPreComposition()) { + needInvalidate = true; + } + } + if (needInvalidate) { + signalLayerUpdate(); + } +} + + void SurfaceFlinger::handleWorkList() { mHwWorkListDirty = false; @@ -1175,7 +1206,7 @@ uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) { uint32_t old = android_atomic_or(flags, &mTransactionFlags); if ((old & flags)==0) { // wake the server up - signalEvent(); + signalTransaction(); } return old; } @@ -1426,14 +1457,14 @@ void SurfaceFlinger::screenReleased(int dpy) { // this may be called by a signal handler, we can't do too much in here android_atomic_or(eConsoleReleased, &mConsoleSignals); - signalEvent(); + signalTransaction(); } void SurfaceFlinger::screenAcquired(int dpy) { // this may be called by a signal handler, we can't do too much in here android_atomic_or(eConsoleAcquired, &mConsoleSignals); - signalEvent(); + signalTransaction(); } status_t SurfaceFlinger::dump(int fd, const Vector& args) @@ -1769,7 +1800,7 @@ void SurfaceFlinger::repaintEverything() { const DisplayHardware& hw(graphicPlane(0).displayHardware()); const Rect bounds(hw.getBounds()); setInvalidateRegion(Region(bounds)); - signalEvent(); + signalTransaction(); } void SurfaceFlinger::setInvalidateRegion(const Region& reg) { @@ -2245,7 +2276,7 @@ status_t SurfaceFlinger::turnElectronBeamOnImplLocked(int32_t mode) // make sure to redraw the whole screen when the animation is done mDirtyRegion.set(hw.bounds()); - signalEvent(); + signalTransaction(); return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c24a9de45a597..fcd93615ff1a8 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -190,6 +190,8 @@ public: status_t renderScreenToTextureLocked(DisplayID dpy, GLuint* textureName, GLfloat* uOut, GLfloat* vOut); + void onMessageReceived(int32_t what); + status_t postMessageAsync(const sp& msg, nsecs_t reltime=0, uint32_t flags = 0); @@ -283,7 +285,10 @@ private: public: // hack to work around gcc 4.0.3 bug const GraphicPlane& graphicPlane(int dpy) const; GraphicPlane& graphicPlane(int dpy); - void signalEvent(); + + void signalTransaction(); + void signalLayerUpdate(); + void signalRefresh(); void repaintEverything(); private: @@ -300,6 +305,7 @@ private: void handlePageFlip(); bool lockPageFlip(const LayerVector& currentLayers); void unlockPageFlip(const LayerVector& currentLayers); + void handleRefresh(); void handleWorkList(); void handleRepaint(); void postFramebuffer();