SF: Factor out expected present time computation
Compute expected present time once and pass it to traversed layers
instead of calling back into SF for each layer. This will simplify
synchronization for per-display refresh.
Also, recompute on Binder transaction, since the cached value computed
on invalidate may be stale.
Bug: 130554049
Bug: 123715322
Test: go/wm-smoke
Change-Id: I7153a728360e789dc4f97d2c39c4bdaa14183624
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index f51fbb4..4cf37a4 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -395,7 +395,8 @@
return true;
}
-bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) {
+bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ nsecs_t expectedPresentTime) {
ATRACE_CALL();
bool refreshRequired = latchSidebandStream(recomputeVisibleRegions);
@@ -430,12 +431,12 @@
const bool oldOpacity = isOpaque(s);
sp<GraphicBuffer> oldBuffer = mActiveBuffer;
- if (!allTransactionsSignaled()) {
+ if (!allTransactionsSignaled(expectedPresentTime)) {
mFlinger->setTransactionFlags(eTraversalNeeded);
return false;
}
- status_t err = updateTexImage(recomputeVisibleRegions, latchTime);
+ status_t err = updateTexImage(recomputeVisibleRegions, latchTime, expectedPresentTime);
if (err != NO_ERROR) {
return false;
}
@@ -540,10 +541,10 @@
}
// transaction
-void BufferLayer::notifyAvailableFrames() {
- const auto headFrameNumber = getHeadFrameNumber();
+void BufferLayer::notifyAvailableFrames(nsecs_t expectedPresentTime) {
+ const auto headFrameNumber = getHeadFrameNumber(expectedPresentTime);
const bool headFenceSignaled = fenceHasSignaled();
- const bool presentTimeIsCurrent = framePresentTimeIsCurrent();
+ const bool presentTimeIsCurrent = framePresentTimeIsCurrent(expectedPresentTime);
Mutex::Autolock lock(mLocalSyncPointMutex);
for (auto& point : mLocalSyncPoints) {
if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled &&
@@ -591,8 +592,8 @@
}
// h/w composer set-up
-bool BufferLayer::allTransactionsSignaled() {
- auto headFrameNumber = getHeadFrameNumber();
+bool BufferLayer::allTransactionsSignaled(nsecs_t expectedPresentTime) {
+ const auto headFrameNumber = getHeadFrameNumber(expectedPresentTime);
bool matchingFramesFound = false;
bool allTransactionsApplied = true;
Mutex::Autolock lock(mLocalSyncPointMutex);
@@ -658,9 +659,9 @@
sourceCrop.getWidth() != displayFrame.getWidth();
}
-uint64_t BufferLayer::getHeadFrameNumber() const {
+uint64_t BufferLayer::getHeadFrameNumber(nsecs_t expectedPresentTime) const {
if (hasFrameUpdate()) {
- return getFrameNumber();
+ return getFrameNumber(expectedPresentTime);
} else {
return mCurrentFrameNumber;
}
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index b679380..c793550 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -96,11 +96,12 @@
// the visible regions need to be recomputed (this is a fairly heavy
// operation, so this should be set only if needed). Typically this is used
// to figure out if the content or size of a surface has changed.
- bool latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
+ bool latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ nsecs_t expectedPresentTime) override;
bool isBufferLatched() const override { return mRefreshPending; }
- void notifyAvailableFrames() override;
+ void notifyAvailableFrames(nsecs_t expectedPresentTime) override;
bool hasReadyFrame() const override;
@@ -114,7 +115,7 @@
// -----------------------------------------------------------------------
private:
virtual bool fenceHasSignaled() const = 0;
- virtual bool framePresentTimeIsCurrent() const = 0;
+ virtual bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const = 0;
virtual nsecs_t getDesiredPresentTime() = 0;
virtual std::shared_ptr<FenceTime> getCurrentFenceTime() const = 0;
@@ -129,7 +130,7 @@
virtual int getDrawingApi() const = 0;
virtual PixelFormat getPixelFormat() const = 0;
- virtual uint64_t getFrameNumber() const = 0;
+ virtual uint64_t getFrameNumber(nsecs_t expectedPresentTime) const = 0;
virtual bool getAutoRefresh() const = 0;
virtual bool getSidebandStreamChanged() const = 0;
@@ -142,7 +143,8 @@
virtual void setFilteringEnabled(bool enabled) = 0;
virtual status_t bindTextureImage() = 0;
- virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) = 0;
+ virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ nsecs_t expectedPresentTime) = 0;
virtual status_t updateActiveBuffer() = 0;
virtual status_t updateFrameNumber(nsecs_t latchTime) = 0;
@@ -156,7 +158,7 @@
// Check all of the local sync points to ensure that all transactions
// which need to have been applied prior to the frame which is about to
// be latched have signaled
- bool allTransactionsSignaled();
+ bool allTransactionsSignaled(nsecs_t expectedPresentTime);
static bool getOpacityForFormat(uint32_t format);
@@ -175,7 +177,7 @@
// Returns true if this layer requires filtering
bool needsFiltering(const sp<const DisplayDevice>& displayDevice) const;
- uint64_t getHeadFrameNumber() const;
+ uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const;
uint32_t mCurrentScalingMode{NATIVE_WINDOW_SCALING_MODE_FREEZE};
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index d685366..fe9edfe 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -137,13 +137,13 @@
return mQueueItems[0].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
}
-bool BufferQueueLayer::framePresentTimeIsCurrent() const {
+bool BufferQueueLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const {
if (!hasFrameUpdate() || isRemovedFromCurrentState()) {
return true;
}
Mutex::Autolock lock(mQueueItemLock);
- return mQueueItems[0].mTimestamp <= mFlinger->getExpectedPresentTime();
+ return mQueueItems[0].mTimestamp <= expectedPresentTime;
}
nsecs_t BufferQueueLayer::getDesiredPresentTime() {
@@ -196,13 +196,11 @@
return mFormat;
}
-uint64_t BufferQueueLayer::getFrameNumber() const {
+uint64_t BufferQueueLayer::getFrameNumber(nsecs_t expectedPresentTime) const {
Mutex::Autolock lock(mQueueItemLock);
uint64_t frameNumber = mQueueItems[0].mFrameNumber;
// The head of the queue will be dropped if there are signaled and timely frames behind it
- nsecs_t expectedPresentTime = mFlinger->getExpectedPresentTime();
-
if (isRemovedFromCurrentState()) {
expectedPresentTime = 0;
}
@@ -268,7 +266,8 @@
return mConsumer->bindTextureImage();
}
-status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) {
+status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ nsecs_t expectedPresentTime) {
// This boolean is used to make sure that SurfaceFlinger's shadow copy
// of the buffer queue isn't modified when the buffer queue is returning
// BufferItem's that weren't actually queued. This can happen in shared
@@ -279,8 +278,6 @@
getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode,
getTransformToDisplayInverse(), mFreezeGeometryUpdates);
- nsecs_t expectedPresentTime = mFlinger->getExpectedPresentTime();
-
if (isRemovedFromCurrentState()) {
expectedPresentTime = 0;
}
@@ -432,7 +429,7 @@
void BufferQueueLayer::fakeVsync() {
mRefreshPending = false;
bool ignored = false;
- latchBuffer(ignored, systemTime());
+ latchBuffer(ignored, systemTime(), 0 /* expectedPresentTime */);
usleep(16000);
releasePendingBuffer(systemTime());
}
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index 7def33a..e60a083 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -61,7 +61,7 @@
// -----------------------------------------------------------------------
public:
bool fenceHasSignaled() const override;
- bool framePresentTimeIsCurrent() const override;
+ bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override;
private:
nsecs_t getDesiredPresentTime() override;
@@ -77,7 +77,7 @@
int getDrawingApi() const override;
PixelFormat getPixelFormat() const override;
- uint64_t getFrameNumber() const override;
+ uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override;
bool getAutoRefresh() const override;
bool getSidebandStreamChanged() const override;
@@ -89,7 +89,8 @@
void setFilteringEnabled(bool enabled) override;
status_t bindTextureImage() override;
- status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
+ status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ nsecs_t expectedPresentTime) override;
status_t updateActiveBuffer() override;
status_t updateFrameNumber(nsecs_t latchTime) override;
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 4b01301..06b2364 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -216,7 +216,7 @@
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
- mFlinger->mTimeStats->setPostTime(getSequence(), getFrameNumber(), getName().c_str(), postTime);
+ mFlinger->mTimeStats->setPostTime(getSequence(), mFrameNumber, getName().c_str(), postTime);
mDesiredPresentTime = desiredPresentTime;
if (mFlinger->mUseSmart90ForVideo) {
@@ -369,12 +369,12 @@
return getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled;
}
-bool BufferStateLayer::framePresentTimeIsCurrent() const {
+bool BufferStateLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const {
if (!hasFrameUpdate() || isRemovedFromCurrentState()) {
return true;
}
- return mDesiredPresentTime <= mFlinger->getExpectedPresentTime();
+ return mDesiredPresentTime <= expectedPresentTime;
}
nsecs_t BufferStateLayer::getDesiredPresentTime() {
@@ -446,7 +446,7 @@
return mActiveBuffer->format;
}
-uint64_t BufferStateLayer::getFrameNumber() const {
+uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const {
return mFrameNumber;
}
@@ -494,7 +494,8 @@
return engine.bindExternalTextureBuffer(mTextureName, s.buffer, s.acquireFence);
}
-status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime) {
+status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime,
+ nsecs_t /*expectedPresentTime*/) {
const State& s(getDrawingState());
if (!s.buffer) {
@@ -528,7 +529,7 @@
ALOGE("[%s] rejecting buffer: "
"bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}",
mName.string(), bufferWidth, bufferHeight, s.active.w, s.active.h);
- mFlinger->mTimeStats->removeTimeRecord(layerID, getFrameNumber());
+ mFlinger->mTimeStats->removeTimeRecord(layerID, mFrameNumber);
return BAD_VALUE;
}
@@ -550,8 +551,8 @@
}
}
- mFlinger->mTimeStats->setAcquireFence(layerID, getFrameNumber(), getCurrentFenceTime());
- mFlinger->mTimeStats->setLatchTime(layerID, getFrameNumber(), latchTime);
+ mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, getCurrentFenceTime());
+ mFlinger->mTimeStats->setLatchTime(layerID, mFrameNumber, latchTime);
mCurrentStateModified = false;
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index db8ae0d..18e8cfa 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -100,7 +100,7 @@
// Interface implementation for BufferLayer
// -----------------------------------------------------------------------
bool fenceHasSignaled() const override;
- bool framePresentTimeIsCurrent() const override;
+ bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override;
// Inherit from ClientCache::ErasedRecipient
void bufferErased(const client_cache_t& clientCacheId) override;
@@ -119,7 +119,7 @@
int getDrawingApi() const override;
PixelFormat getPixelFormat() const override;
- uint64_t getFrameNumber() const override;
+ uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override;
bool getAutoRefresh() const override;
bool getSidebandStreamChanged() const override;
@@ -131,7 +131,8 @@
void setFilteringEnabled(bool enabled) override;
status_t bindTextureImage() override;
- status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
+ status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ nsecs_t expectedPresentTime) override;
status_t updateActiveBuffer() override;
status_t updateFrameNumber(nsecs_t latchTime) override;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index b693a47..f7e188f 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -561,8 +561,9 @@
* operation, so this should be set only if needed). Typically this is used
* to figure out if the content or size of a surface has changed.
*/
- virtual bool latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/) {
- return {};
+ virtual bool latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/,
+ nsecs_t /*expectedPresentTime*/) {
+ return false;
}
virtual bool isBufferLatched() const { return false; }
@@ -812,7 +813,7 @@
// this to be called once.
sp<IBinder> getHandle();
const String8& getName() const;
- virtual void notifyAvailableFrames() {}
+ virtual void notifyAvailableFrames(nsecs_t /*expectedPresentTime*/) {}
virtual PixelFormat getPixelFormat() const { return PIXEL_FORMAT_NONE; }
bool getPremultipledAlpha() const;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 99440a6..cd80f2b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1693,15 +1693,15 @@
return fence != Fence::NO_FENCE && (fence->getStatus() == Fence::Status::Unsignaled);
}
-void SurfaceFlinger::populateExpectedPresentTime() NO_THREAD_SAFETY_ANALYSIS {
+void SurfaceFlinger::populateExpectedPresentTime() {
DisplayStatInfo stats;
mScheduler->getDisplayStatInfo(&stats);
const nsecs_t presentTime = mScheduler->getDispSyncExpectedPresentTime();
// Inflate the expected present time if we're targetting the next vsync.
- mExpectedPresentTime =
- mVsyncModulator.getOffsets().sf < mPhaseOffsets->getOffsetThresholdForNextVsync()
- ? presentTime
- : presentTime + stats.vsyncPeriod;
+ mExpectedPresentTime.store(mVsyncModulator.getOffsets().sf <
+ mPhaseOffsets->getOffsetThresholdForNextVsync()
+ ? presentTime
+ : presentTime + stats.vsyncPeriod);
}
void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS {
@@ -2856,9 +2856,11 @@
void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
+ const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
+
// Notify all layers of available frames
- mCurrentState.traverseInZOrder([](Layer* layer) {
- layer->notifyAvailableFrames();
+ mCurrentState.traverseInZOrder([expectedPresentTime](Layer* layer) {
+ layer->notifyAvailableFrames(expectedPresentTime);
});
/*
@@ -3057,7 +3059,7 @@
void SurfaceFlinger::latchAndReleaseBuffer(const sp<Layer>& layer) {
if (layer->hasReadyFrame()) {
bool ignored = false;
- layer->latchBuffer(ignored, systemTime());
+ layer->latchBuffer(ignored, systemTime(), 0 /* expectedPresentTime */);
}
layer->releasePendingBuffer(systemTime());
}
@@ -3305,6 +3307,8 @@
bool frameQueued = false;
bool newDataLatched = false;
+ const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
+
// 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.
// Example: Two producers share the same command stream and:
@@ -3317,7 +3321,6 @@
mDrawingState.traverseInZOrder([&](Layer* layer) {
if (layer->hasReadyFrame()) {
frameQueued = true;
- const nsecs_t expectedPresentTime = getExpectedPresentTime();
if (layer->shouldPresentNow(expectedPresentTime)) {
mLayersWithQueuedFrames.push_back(layer);
} else {
@@ -3335,7 +3338,7 @@
Mutex::Autolock lock(mStateLock);
for (auto& layer : mLayersWithQueuedFrames) {
- if (layer->latchBuffer(visibleRegions, latchTime)) {
+ if (layer->latchBuffer(visibleRegions, latchTime, expectedPresentTime)) {
mLayersPendingRefresh.push_back(layer);
}
layer->useSurfaceDamage();
@@ -3656,6 +3659,7 @@
while (!transactionQueue.empty()) {
const auto& transaction = transactionQueue.front();
if (!transactionIsReadyToBeApplied(transaction.desiredPresentTime,
+ true /* useCachedExpectedPresentTime */,
transaction.states)) {
setTransactionFlags(eTransactionFlushNeeded);
break;
@@ -3708,8 +3712,12 @@
}
bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime,
+ bool useCachedExpectedPresentTime,
const Vector<ComposerState>& states) {
- nsecs_t expectedPresentTime = getExpectedPresentTime();
+ if (!useCachedExpectedPresentTime)
+ populateExpectedPresentTime();
+
+ const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
// Do not present if the desiredPresentTime has not passed unless it is more than one second
// in the future. We ignore timestamps more than 1 second in the future for stability reasons.
if (desiredPresentTime >= 0 && desiredPresentTime >= expectedPresentTime &&
@@ -3764,8 +3772,10 @@
itr = mTransactionQueues.find(applyToken);
}
}
- if (itr != mTransactionQueues.end() ||
- !transactionIsReadyToBeApplied(desiredPresentTime, states)) {
+
+ // Expected present time is computed and cached on invalidate, so it may be stale.
+ if (itr != mTransactionQueues.end() || !transactionIsReadyToBeApplied(
+ desiredPresentTime, false /* useCachedExpectedPresentTime */, states)) {
mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime,
uncacheBuffer, listenerCallbacks, postTime,
privileged);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 0e6eacf..099ba72 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -295,18 +295,13 @@
// main thread function to enable/disable h/w composer event
void setPrimaryVsyncEnabledInternal(bool enabled);
+ void setVsyncEnabledInHWC(DisplayId displayId, HWC2::Vsync enabled);
// called on the main thread by MessageQueue when an internal message
// is received
// TODO: this should be made accessible only to MessageQueue
void onMessageReceived(int32_t what);
- // populates the expected present time for this frame.
- // When we are in negative offsets, we perform a correction so that the
- // predicted vsync for the *next* frame is used instead.
- void populateExpectedPresentTime();
- nsecs_t getExpectedPresentTime() const { return mExpectedPresentTime; }
-
// for debugging only
// TODO: this should be made accessible only to HWComposer
const Vector<sp<Layer>>& getLayerSortedByZForHwcDisplay(DisplayId displayId);
@@ -585,6 +580,7 @@
void commitOffscreenLayers();
bool containsAnyInvalidClientState(const Vector<ComposerState>& states);
bool transactionIsReadyToBeApplied(int64_t desiredPresentTime,
+ bool useCachedExpectedPresentTime,
const Vector<ComposerState>& states);
uint32_t setClientStateLocked(const ComposerState& composerState, int64_t desiredPresentTime,
const std::vector<ListenerCallbacks>& listenerCallbacks,
@@ -816,6 +812,12 @@
bool isDisplayConfigAllowed(int32_t configId) const REQUIRES(mStateLock);
+ bool previousFrameMissed();
+
+ // Populates the expected present time for this frame. For negative offsets, performs a
+ // correction using the predicted vsync for the next frame instead.
+ void populateExpectedPresentTime();
+
/*
* Display identification
*/
@@ -844,9 +846,6 @@
return hwcDisplayId ? getHwComposer().toPhysicalDisplayId(*hwcDisplayId) : std::nullopt;
}
- bool previousFrameMissed();
- void setVsyncEnabledInHWC(DisplayId displayId, HWC2::Vsync enabled);
-
/*
* Debugging & dumpsys
*/
@@ -1135,6 +1134,8 @@
scheduler::RefreshRateConfigs mRefreshRateConfigs;
scheduler::RefreshRateStats mRefreshRateStats{mRefreshRateConfigs, *mTimeStats};
+ std::atomic<nsecs_t> mExpectedPresentTime = 0;
+
// All configs are allowed if the set is empty.
using DisplayConfigs = std::set<int32_t>;
DisplayConfigs mAllowedDisplayConfigs GUARDED_BY(mStateLock);
@@ -1188,8 +1189,6 @@
// Flags to capture the state of Vsync in HWC
HWC2::Vsync mHWCVsyncState = HWC2::Vsync::Disable;
HWC2::Vsync mHWCVsyncPendingState = HWC2::Vsync::Disable;
-
- nsecs_t mExpectedPresentTime;
};
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index e6211c4..ce67a19 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -502,7 +502,7 @@
EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true));
bool ignoredRecomputeVisibleRegions;
- layer->latchBuffer(ignoredRecomputeVisibleRegions, 0);
+ layer->latchBuffer(ignoredRecomputeVisibleRegions, 0, 0);
Mock::VerifyAndClear(test->mRenderEngine);
}