diff options
author | Mathias Agopian <mathias@google.com> | 2012-01-31 18:24:27 -0800 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2012-02-01 20:43:06 -0800 |
commit | 99ce5cdeb383216dee95af4d90e47406b0948ea1 (patch) | |
tree | 4f96f44e8e55a6c72b4e640704868f23a5e7c72b | |
parent | 93bfeedd3768e25c783e22ed88103c2c409894a4 (diff) | |
download | frameworks_native-99ce5cdeb383216dee95af4d90e47406b0948ea1.zip frameworks_native-99ce5cdeb383216dee95af4d90e47406b0948ea1.tar.gz frameworks_native-99ce5cdeb383216dee95af4d90e47406b0948ea1.tar.bz2 |
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
-rw-r--r-- | include/gui/DisplayEventReceiver.h | 2 | ||||
-rw-r--r-- | libs/gui/DisplayEventReceiver.cpp | 8 | ||||
-rw-r--r-- | services/surfaceflinger/Android.mk | 1 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 39 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 4 | ||||
-rw-r--r-- | services/surfaceflinger/LayerBase.cpp | 19 | ||||
-rw-r--r-- | services/surfaceflinger/LayerBase.h | 17 | ||||
-rw-r--r-- | services/surfaceflinger/MessageQueue.cpp | 80 | ||||
-rw-r--r-- | services/surfaceflinger/MessageQueue.h | 32 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 219 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 8 |
11 files changed, 257 insertions, 172 deletions
diff --git a/include/gui/DisplayEventReceiver.h b/include/gui/DisplayEventReceiver.h index a281377..7bca8d6 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<BitTube>& 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 3b3ccaa..6a4763d 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<BitTube>& 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 fc211e5..8b4c074 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 9c04d59..64f72d5 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<GraphicBuffer> 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 2dd4da1..bf30608 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -80,6 +80,7 @@ public: virtual wp<IBinder> getSurfaceTextureBinder() const; virtual void onLayerDisplayed(); + virtual bool onPreComposition(); // only for debugging inline const sp<GraphicBuffer>& 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 d32fcdd..44aafdf 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 6b62c9d..b8f7680 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<LayerBaseClient> getLayerBaseClient() const { return 0; } virtual sp<Layer> 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 70711e7..1ff3567 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<SurfaceFlinger>& flinger) +{ + mFlinger = flinger; + mLooper = new Looper(true); + mHandler = new Handler(*this); +} + void MessageQueue::setEventThread(const sp<EventThread>& eventThread) { mEventThread = eventThread; @@ -68,25 +102,16 @@ void MessageQueue::setEventThread(const sp<EventThread>& 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_TIMEOUT: - // timeout (should not happen) - continue; - case ALOOPER_POLL_ERROR: ALOGE("ALOOPER_POLL_ERROR"); + case ALOOPER_POLL_TIMEOUT: + // timeout (should not happen) 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 ; i<n ; i++) { if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { - scheduleWorkASAP(); + mHandler->signalRefresh(); 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 5ea197d..ea29e7e 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<SurfaceFlinger> mFlinger; sp<Looper> mLooper; sp<EventThread> mEventThread; sp<IDisplayEventConnection> mEvents; sp<BitTube> mEventTube; - int32_t mWorkPending; + sp<Handler> 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<SurfaceFlinger>& flinger); void setEventThread(const sp<EventThread>& events); void waitMessage(); status_t postMessage(const sp<MessageBase>& 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 ff70ec3..870235b 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<IBinder>& who) +{ + // the window manager died on us. prepare its eulogy. + + // reset screen orientation + Vector<ComposerState> state; + setTransactionState(state, eOrientationDefault, 0); + + // restart the boot-animation + property_set("ctl.start", "bootanim"); +} + sp<IMemoryHeap> SurfaceFlinger::getCblk() const { return mServerHeap; @@ -183,26 +206,6 @@ void SurfaceFlinger::bootFinished() property_set("ctl.stop", "bootanim"); } -void SurfaceFlinger::binderDied(const wp<IBinder>& who) -{ - // the window manager died on us. prepare its eulogy. - - // reset screen orientation - Vector<ComposerState> 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; } @@ -311,34 +314,6 @@ status_t SurfaceFlinger::readyToRun() } // ---------------------------------------------------------------------------- -#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<MessageBase>& msg, - nsecs_t reltime, uint32_t flags) { - return mEventQueue.postMessage(msg, reltime); -} - -status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& 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( const sp<ISurfaceTexture>& surfaceTexture) const { @@ -388,52 +363,91 @@ sp<IDisplayEventConnection> 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<MessageBase>& msg, + nsecs_t reltime, uint32_t flags) { + return mEventQueue.postMessage(msg, reltime); +} + +status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& 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(); + return true; +} - // check for transactions - if (CC_UNLIKELY(mConsoleSignals)) { - handleConsoleEvents(); - } +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); - } + // 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(); + // post surfaces (if needed) + handlePageFlip(); - if (mDirtyRegion.isEmpty()) { - // nothing new to do. - return true; - } + if (!mDirtyRegion.isEmpty()) { + signalRefresh(); + } + } break; - if (CC_UNLIKELY(mHwWorkListDirty)) { - // build the h/w work list - handleWorkList(); - } + 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_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(); + 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; } - return true; } void SurfaceFlinger::postFramebuffer() @@ -717,13 +731,13 @@ void SurfaceFlinger::commitTransaction() void SurfaceFlinger::handlePageFlip() { - bool visibleRegions = mVisibleRegionsDirty; + const DisplayHardware& hw = graphicPlane(0).displayHardware(); + const Region screenRegion(hw.bounds()); + const LayerVector& currentLayers(mDrawingState.layersSortedByZ); - visibleRegions |= lockPageFlip(currentLayers); + const bool visibleRegions = lockPageFlip(currentLayers); - const DisplayHardware& hw = graphicPlane(0).displayHardware(); - const Region screenRegion(hw.bounds()); - if (visibleRegions) { + 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<LayerBase> const* layers = currentLayers.array(); for (size_t i=0 ; i<count ; i++) { const sp<LayerBase>& 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<count ; i++) { + const sp<LayerBase>& 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<String16>& 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 c24a9de..fcd9361 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<MessageBase>& 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(); |