diff options
Diffstat (limited to 'services/surfaceflinger')
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 32 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 7 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 58 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 15 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlingerConsumer.h | 2 |
5 files changed, 90 insertions, 24 deletions
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index acc2775..c3e1a76 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -34,6 +34,7 @@ #include <ui/GraphicBuffer.h> #include <ui/PixelFormat.h> +#include <gui/BufferItem.h> #include <gui/Surface.h> #include "clz.h" @@ -159,11 +160,26 @@ void Layer::onLayerDisplayed(const sp<const DisplayDevice>& /* hw */, } } -void Layer::onFrameAvailable(const BufferItem& /* item */) { +void Layer::onFrameAvailable(const BufferItem& item) { + // Add this buffer from our internal queue tracker + { // Autolock scope + Mutex::Autolock lock(mQueueItemLock); + mQueueItems.push_back(item); + } + android_atomic_inc(&mQueuedFrames); mFlinger->signalLayerUpdate(); } +void Layer::onFrameReplaced(const BufferItem& item) { + Mutex::Autolock lock(mQueueItemLock); + if (mQueueItems.empty()) { + ALOGE("Can't replace a frame on an empty queue"); + return; + } + mQueueItems.editItemAt(0) = item; +} + void Layer::onSidebandStreamChanged() { if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) { // mSidebandStreamChanged was false @@ -1014,6 +1030,14 @@ bool Layer::setLayerStack(uint32_t layerStack) { // pageflip handling... // ---------------------------------------------------------------------------- +bool Layer::shouldPresentNow(const DispSync& dispSync) const { + Mutex::Autolock lock(mQueueItemLock); + nsecs_t expectedPresent = + mSurfaceFlingerConsumer->computeExpectedPresent(dispSync); + return mQueueItems.empty() ? + false : mQueueItems[0].mTimestamp < expectedPresent; +} + bool Layer::onPreComposition() { mRefreshPending = false; return mQueuedFrames > 0 || mSidebandStreamChanged; @@ -1203,6 +1227,12 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) return outDirtyRegion; } + // Remove this buffer from our internal queue tracker + { // Autolock scope + Mutex::Autolock lock(mQueueItemLock); + mQueueItems.removeAt(0); + } + // Decrement the queued-frames count. Signal another event if we // have more frames pending. if (android_atomic_dec(&mQueuedFrames) > 1) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index e2100fc..1d4eee7 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -210,6 +210,8 @@ public: void onLayerDisplayed(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface* layer); + bool shouldPresentNow(const DispSync& dispSync) const; + /* * called before composition. * returns true if the layer has pending updates. @@ -331,6 +333,7 @@ protected: private: // Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener virtual void onFrameAvailable(const BufferItem& item); + virtual void onFrameReplaced(const BufferItem& item); virtual void onSidebandStreamChanged(); void commitTransaction(); @@ -404,6 +407,10 @@ private: // This layer can be a cursor on some displays. bool mPotentialCursor; + + // Local copy of the queued contents of the incoming BufferQueue + mutable Mutex mQueueItemLock; + Vector<BufferItem> mQueueItems; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c469627..b8b6472 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -829,30 +829,39 @@ void SurfaceFlinger::eventControl(int disp, int event, int enabled) { void SurfaceFlinger::onMessageReceived(int32_t what) { ATRACE_CALL(); switch (what) { - case MessageQueue::TRANSACTION: - handleMessageTransaction(); - break; - case MessageQueue::INVALIDATE: - handleMessageTransaction(); - handleMessageInvalidate(); - signalRefresh(); - break; - case MessageQueue::REFRESH: - handleMessageRefresh(); - break; + case MessageQueue::TRANSACTION: { + handleMessageTransaction(); + break; + } + case MessageQueue::INVALIDATE: { + bool refreshNeeded = handleMessageTransaction(); + refreshNeeded |= handleMessageInvalidate(); + if (refreshNeeded) { + // Signal a refresh if a transaction modified the window state or if + // a new buffer was latched + signalRefresh(); + } + break; + } + case MessageQueue::REFRESH: { + handleMessageRefresh(); + break; + } } } -void SurfaceFlinger::handleMessageTransaction() { +bool SurfaceFlinger::handleMessageTransaction() { uint32_t transactionFlags = peekTransactionFlags(eTransactionMask); if (transactionFlags) { handleTransaction(transactionFlags); + return true; } + return false; } -void SurfaceFlinger::handleMessageInvalidate() { +bool SurfaceFlinger::handleMessageInvalidate() { ATRACE_CALL(); - handlePageFlip(); + return handlePageFlip(); } void SurfaceFlinger::handleMessageRefresh() { @@ -1685,12 +1694,13 @@ void SurfaceFlinger::invalidateLayerStack(uint32_t layerStack, } } -void SurfaceFlinger::handlePageFlip() +bool SurfaceFlinger::handlePageFlip() { Region dirtyRegion; bool visibleRegions = false; const LayerVector& layers(mDrawingState.layersSortedByZ); + bool frameQueued = false; // Store the set of layers that need updates. This set must not change as // buffers are being latched, as this could result in a deadlock. @@ -1704,8 +1714,12 @@ void SurfaceFlinger::handlePageFlip() Vector<Layer*> layersWithQueuedFrames; for (size_t i = 0, count = layers.size(); i<count ; i++) { const sp<Layer>& layer(layers[i]); - if (layer->hasQueuedFrame()) - layersWithQueuedFrames.push_back(layer.get()); + if (layer->hasQueuedFrame()) { + frameQueued = true; + if (layer->shouldPresentNow(mPrimaryDispSync)) { + layersWithQueuedFrames.push_back(layer.get()); + } + } } for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) { Layer* layer = layersWithQueuedFrames[i]; @@ -1715,6 +1729,16 @@ void SurfaceFlinger::handlePageFlip() } mVisibleRegionsDirty |= visibleRegions; + + // If we will need to wake up at some time in the future to deal with a + // queued frame that shouldn't be displayed during this vsync period, wake + // up during the next vsync period to check again. + if (frameQueued && layersWithQueuedFrames.empty()) { + signalLayerUpdate(); + } + + // Only continue with the refresh if there is actually new work to do + return !layersWithQueuedFrames.empty(); } void SurfaceFlinger::invalidateHwcGeometry() diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 710dac7..4deb815 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -247,8 +247,12 @@ private: // called on the main thread in response to setPowerMode() void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode); - void handleMessageTransaction(); - void handleMessageInvalidate(); + // Returns whether the transaction actually modified any state + bool handleMessageTransaction(); + + // Returns whether a new buffer has been latched (see handlePageFlip()) + bool handleMessageInvalidate(); + void handleMessageRefresh(); void handleTransaction(uint32_t transactionFlags); @@ -256,10 +260,11 @@ private: void updateCursorAsync(); - /* handlePageFilp: this is were we latch a new buffer - * if available and compute the dirty region. + /* handlePageFlip - latch a new buffer if available and compute the dirty + * region. Returns whether a new buffer has been latched, i.e., whether it + * is necessary to perform a refresh during this vsync. */ - void handlePageFlip(); + bool handlePageFlip(); /* ------------------------------------------------------------------------ * Transactions diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h index 5633980..28f2f6a 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.h +++ b/services/surfaceflinger/SurfaceFlingerConsumer.h @@ -67,9 +67,9 @@ public: sp<NativeHandle> getSidebandStream() const; -private: nsecs_t computeExpectedPresent(const DispSync& dispSync); +private: virtual void onSidebandStreamChanged(); wp<ContentsChangedListener> mContentsChangedListener; |