am 686c5be4: am 6b9454d1: SurfaceFlinger: Do less work when using PTS

* commit '686c5be4722dce02ae8e5580d6677f1eeea22464':
  SurfaceFlinger: Do less work when using PTS
This commit is contained in:
Dan Stoza 2014-11-18 20:18:27 +00:00 committed by Android Git Automerger
commit e8e23c8b79
5 changed files with 90 additions and 24 deletions

View File

@ -34,6 +34,7 @@
#include <ui/GraphicBuffer.h> #include <ui/GraphicBuffer.h>
#include <ui/PixelFormat.h> #include <ui/PixelFormat.h>
#include <gui/BufferItem.h>
#include <gui/Surface.h> #include <gui/Surface.h>
#include "clz.h" #include "clz.h"
@ -158,11 +159,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); android_atomic_inc(&mQueuedFrames);
mFlinger->signalLayerUpdate(); 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() { void Layer::onSidebandStreamChanged() {
if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) { if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) {
// mSidebandStreamChanged was false // mSidebandStreamChanged was false
@ -1012,6 +1028,14 @@ bool Layer::setLayerStack(uint32_t layerStack) {
// pageflip handling... // 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() { bool Layer::onPreComposition() {
mRefreshPending = false; mRefreshPending = false;
return mQueuedFrames > 0 || mSidebandStreamChanged; return mQueuedFrames > 0 || mSidebandStreamChanged;
@ -1201,6 +1225,12 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
return outDirtyRegion; 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 // Decrement the queued-frames count. Signal another event if we
// have more frames pending. // have more frames pending.
if (android_atomic_dec(&mQueuedFrames) > 1) { if (android_atomic_dec(&mQueuedFrames) > 1) {

View File

@ -210,6 +210,8 @@ public:
void onLayerDisplayed(const sp<const DisplayDevice>& hw, void onLayerDisplayed(const sp<const DisplayDevice>& hw,
HWComposer::HWCLayerInterface* layer); HWComposer::HWCLayerInterface* layer);
bool shouldPresentNow(const DispSync& dispSync) const;
/* /*
* called before composition. * called before composition.
* returns true if the layer has pending updates. * returns true if the layer has pending updates.
@ -331,6 +333,7 @@ protected:
private: private:
// Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener // Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener
virtual void onFrameAvailable(const BufferItem& item); virtual void onFrameAvailable(const BufferItem& item);
virtual void onFrameReplaced(const BufferItem& item);
virtual void onSidebandStreamChanged(); virtual void onSidebandStreamChanged();
void commitTransaction(); void commitTransaction();
@ -403,6 +406,10 @@ private:
// This layer can be a cursor on some displays. // This layer can be a cursor on some displays.
bool mPotentialCursor; bool mPotentialCursor;
// Local copy of the queued contents of the incoming BufferQueue
mutable Mutex mQueueItemLock;
Vector<BufferItem> mQueueItems;
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -828,30 +828,39 @@ void SurfaceFlinger::eventControl(int disp, int event, int enabled) {
void SurfaceFlinger::onMessageReceived(int32_t what) { void SurfaceFlinger::onMessageReceived(int32_t what) {
ATRACE_CALL(); ATRACE_CALL();
switch (what) { switch (what) {
case MessageQueue::TRANSACTION: case MessageQueue::TRANSACTION: {
handleMessageTransaction(); handleMessageTransaction();
break; break;
case MessageQueue::INVALIDATE: }
handleMessageTransaction(); case MessageQueue::INVALIDATE: {
handleMessageInvalidate(); bool refreshNeeded = handleMessageTransaction();
signalRefresh(); refreshNeeded |= handleMessageInvalidate();
break; if (refreshNeeded) {
case MessageQueue::REFRESH: // Signal a refresh if a transaction modified the window state or if
handleMessageRefresh(); // a new buffer was latched
break; signalRefresh();
}
break;
}
case MessageQueue::REFRESH: {
handleMessageRefresh();
break;
}
} }
} }
void SurfaceFlinger::handleMessageTransaction() { bool SurfaceFlinger::handleMessageTransaction() {
uint32_t transactionFlags = peekTransactionFlags(eTransactionMask); uint32_t transactionFlags = peekTransactionFlags(eTransactionMask);
if (transactionFlags) { if (transactionFlags) {
handleTransaction(transactionFlags); handleTransaction(transactionFlags);
return true;
} }
return false;
} }
void SurfaceFlinger::handleMessageInvalidate() { bool SurfaceFlinger::handleMessageInvalidate() {
ATRACE_CALL(); ATRACE_CALL();
handlePageFlip(); return handlePageFlip();
} }
void SurfaceFlinger::handleMessageRefresh() { void SurfaceFlinger::handleMessageRefresh() {
@ -1686,12 +1695,13 @@ void SurfaceFlinger::invalidateLayerStack(uint32_t layerStack,
} }
} }
void SurfaceFlinger::handlePageFlip() bool SurfaceFlinger::handlePageFlip()
{ {
Region dirtyRegion; Region dirtyRegion;
bool visibleRegions = false; bool visibleRegions = false;
const LayerVector& layers(mDrawingState.layersSortedByZ); const LayerVector& layers(mDrawingState.layersSortedByZ);
bool frameQueued = false;
// Store the set of layers that need updates. This set must not change as // 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. // buffers are being latched, as this could result in a deadlock.
@ -1705,8 +1715,12 @@ void SurfaceFlinger::handlePageFlip()
Vector<Layer*> layersWithQueuedFrames; Vector<Layer*> layersWithQueuedFrames;
for (size_t i = 0, count = layers.size(); i<count ; i++) { for (size_t i = 0, count = layers.size(); i<count ; i++) {
const sp<Layer>& layer(layers[i]); const sp<Layer>& layer(layers[i]);
if (layer->hasQueuedFrame()) if (layer->hasQueuedFrame()) {
layersWithQueuedFrames.push_back(layer.get()); frameQueued = true;
if (layer->shouldPresentNow(mPrimaryDispSync)) {
layersWithQueuedFrames.push_back(layer.get());
}
}
} }
for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) { for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) {
Layer* layer = layersWithQueuedFrames[i]; Layer* layer = layersWithQueuedFrames[i];
@ -1716,6 +1730,16 @@ void SurfaceFlinger::handlePageFlip()
} }
mVisibleRegionsDirty |= visibleRegions; 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() void SurfaceFlinger::invalidateHwcGeometry()

View File

@ -247,8 +247,12 @@ private:
// called on the main thread in response to setPowerMode() // called on the main thread in response to setPowerMode()
void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode); void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode);
void handleMessageTransaction(); // Returns whether the transaction actually modified any state
void handleMessageInvalidate(); bool handleMessageTransaction();
// Returns whether a new buffer has been latched (see handlePageFlip())
bool handleMessageInvalidate();
void handleMessageRefresh(); void handleMessageRefresh();
void handleTransaction(uint32_t transactionFlags); void handleTransaction(uint32_t transactionFlags);
@ -256,10 +260,11 @@ private:
void updateCursorAsync(); void updateCursorAsync();
/* handlePageFilp: this is were we latch a new buffer /* handlePageFlip - latch a new buffer if available and compute the dirty
* if available and compute the dirty region. * 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 * Transactions

View File

@ -67,9 +67,9 @@ public:
sp<NativeHandle> getSidebandStream() const; sp<NativeHandle> getSidebandStream() const;
private:
nsecs_t computeExpectedPresent(const DispSync& dispSync); nsecs_t computeExpectedPresent(const DispSync& dispSync);
private:
virtual void onSidebandStreamChanged(); virtual void onSidebandStreamChanged();
wp<ContentsChangedListener> mContentsChangedListener; wp<ContentsChangedListener> mContentsChangedListener;