diff options
23 files changed, 136 insertions, 89 deletions
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h index 109e28b9dc..d9a0253781 100644 --- a/libs/gui/include/gui/DisplayEventReceiver.h +++ b/libs/gui/include/gui/DisplayEventReceiver.h @@ -65,6 +65,7 @@ public: struct VSync { uint32_t count; + nsecs_t expectedVSyncTimestamp; }; struct Hotplug { diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 0a0f2f132e..2e7fbc1a78 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -116,9 +116,13 @@ sp<GraphicBuffer> RefreshRateOverlay::SevenSegmentDrawer::drawNumber(int number, sp<GraphicBuffer> buffer = new GraphicBuffer(BUFFER_WIDTH, BUFFER_HEIGHT, HAL_PIXEL_FORMAT_RGBA_8888, 1, - GRALLOC_USAGE_SW_WRITE_RARELY, "RefreshRateOverlayBuffer"); + GRALLOC_USAGE_SW_WRITE_RARELY | GRALLOC_USAGE_HW_COMPOSER | + GRALLOC_USAGE_HW_TEXTURE, + "RefreshRateOverlayBuffer"); uint8_t* pixels; buffer->lock(GRALLOC_USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&pixels)); + // Clear buffer content + drawRect(Rect(BUFFER_WIDTH, BUFFER_HEIGHT), half4(0), buffer, pixels); int left = 0; if (hundreds != 0) { drawDigit(hundreds, left, color, buffer, pixels); diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 19c204cddb..27353d8c0b 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -130,7 +130,7 @@ private: mVsyncListening = false; } - void onDispSyncEvent(nsecs_t /* when */) final { + void onDispSyncEvent(nsecs_t /*when*/, nsecs_t /*expectedVSyncTimestamp*/) final { std::unique_lock<decltype(mMutex)> lock(mMutex); if (mPhaseIntervalSetting == Phase::ZERO) { @@ -425,7 +425,8 @@ void RegionSamplingThread::captureSample() { } bool ignored; - mFlinger.captureScreenCommon(renderArea, traverseLayers, buffer, false, ignored); + mFlinger.captureScreenCommon(renderArea, traverseLayers, buffer, false /* identityTransform */, + true /* regionSampling */, ignored); std::vector<Descriptor> activeDescriptors; for (const auto& descriptor : descriptors) { diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp index fc6ccaeb6e..ff91bf7bc0 100644 --- a/services/surfaceflinger/Scheduler/DispSync.cpp +++ b/services/surfaceflinger/Scheduler/DispSync.cpp @@ -200,7 +200,8 @@ public: } } - callbackInvocations = gatherCallbackInvocationsLocked(now); + callbackInvocations = + gatherCallbackInvocationsLocked(now, computeNextRefreshLocked(0, now)); } if (callbackInvocations.size() > 0) { @@ -303,6 +304,11 @@ public: return BAD_VALUE; } + nsecs_t computeNextRefresh(int periodOffset, nsecs_t now) const { + Mutex::Autolock lock(mMutex); + return computeNextRefreshLocked(periodOffset, now); + } + private: struct EventListener { const char* mName; @@ -315,6 +321,7 @@ private: struct CallbackInvocation { DispSync::Callback* mCallback; nsecs_t mEventTime; + nsecs_t mExpectedVSyncTime; }; nsecs_t computeNextEventTimeLocked(nsecs_t now) { @@ -340,7 +347,8 @@ private: return duration < (3 * mPeriod) / 5; } - std::vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_t now) { + std::vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_t now, + nsecs_t expectedVSyncTime) { if (mTraceDetailedInfo) ATRACE_CALL(); ALOGV("[%s] gatherCallbackInvocationsLocked @ %" PRId64, mName, ns2us(now)); @@ -361,6 +369,10 @@ private: CallbackInvocation ci; ci.mCallback = eventListener.mCallback; ci.mEventTime = t; + ci.mExpectedVSyncTime = expectedVSyncTime; + if (eventListener.mPhase < 0) { + ci.mExpectedVSyncTime += mPeriod; + } ALOGV("[%s] [%s] Preparing to fire, latency: %" PRId64, mName, eventListener.mName, t - eventListener.mLastEventTime); callbackInvocations.push_back(ci); @@ -426,8 +438,17 @@ private: void fireCallbackInvocations(const std::vector<CallbackInvocation>& callbacks) { if (mTraceDetailedInfo) ATRACE_CALL(); for (size_t i = 0; i < callbacks.size(); i++) { - callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime); + callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime, + callbacks[i].mExpectedVSyncTime); + } + } + + nsecs_t computeNextRefreshLocked(int periodOffset, nsecs_t now) const { + nsecs_t phase = mReferenceTime + mPhase; + if (mPeriod == 0) { + return 0; } + return (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase; } const char* const mName; @@ -444,7 +465,7 @@ private: std::vector<EventListener> mEventListeners; - Mutex mMutex; + mutable Mutex mMutex; Condition mCond; // Flag to turn on logging in systrace. @@ -458,7 +479,7 @@ class ZeroPhaseTracer : public DispSync::Callback { public: ZeroPhaseTracer() : mParity("ZERO_PHASE_VSYNC", false) {} - virtual void onDispSyncEvent(nsecs_t /*when*/) { + virtual void onDispSyncEvent(nsecs_t /*when*/, nsecs_t /*expectedVSyncTimestamp*/) { mParity = !mParity; } @@ -845,7 +866,7 @@ nsecs_t DispSync::expectedPresentTime(nsecs_t now) { const uint32_t hwcLatency = 0; // Ask DispSync when the next refresh will be (CLOCK_MONOTONIC). - return computeNextRefresh(hwcLatency, now); + return mThread->computeNextRefresh(hwcLatency, now); } } // namespace impl diff --git a/services/surfaceflinger/Scheduler/DispSync.h b/services/surfaceflinger/Scheduler/DispSync.h index 2faa81ce41..832f08e07b 100644 --- a/services/surfaceflinger/Scheduler/DispSync.h +++ b/services/surfaceflinger/Scheduler/DispSync.h @@ -36,7 +36,7 @@ public: public: Callback() = default; virtual ~Callback(); - virtual void onDispSyncEvent(nsecs_t when) = 0; + virtual void onDispSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp) = 0; protected: Callback(Callback const&) = delete; diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp index 4e3f85f53e..8752b6600e 100644 --- a/services/surfaceflinger/Scheduler/DispSyncSource.cpp +++ b/services/surfaceflinger/Scheduler/DispSyncSource.cpp @@ -92,7 +92,7 @@ void DispSyncSource::setPhaseOffset(nsecs_t phaseOffset) { } } -void DispSyncSource::onDispSyncEvent(nsecs_t when) { +void DispSyncSource::onDispSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp) { VSyncSource::Callback* callback; { std::lock_guard lock(mCallbackMutex); @@ -104,7 +104,7 @@ void DispSyncSource::onDispSyncEvent(nsecs_t when) { } if (callback != nullptr) { - callback->onVSyncEvent(when); + callback->onVSyncEvent(when, expectedVSyncTimestamp); } } diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.h b/services/surfaceflinger/Scheduler/DispSyncSource.h index f278712407..2aee3f6321 100644 --- a/services/surfaceflinger/Scheduler/DispSyncSource.h +++ b/services/surfaceflinger/Scheduler/DispSyncSource.h @@ -40,7 +40,7 @@ public: private: // The following method is the implementation of the DispSync::Callback. - virtual void onDispSyncEvent(nsecs_t when); + void onDispSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp) override; const char* const mName; TracedOrdinal<int> mValue; diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index 8347650636..5dedb6a1e7 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -79,8 +79,9 @@ std::string toString(const DisplayEventReceiver::Event& event) { event.hotplug.connected ? "connected" : "disconnected"); case DisplayEventReceiver::DISPLAY_EVENT_VSYNC: return StringPrintf("VSync{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT - ", count=%u}", - event.header.displayId, event.vsync.count); + ", count=%u, expectedVSyncTimestamp=%" PRId64 "}", + event.header.displayId, event.vsync.count, + event.vsync.expectedVSyncTimestamp); case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED: return StringPrintf("ConfigChanged{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", configId=%u}", @@ -99,10 +100,11 @@ DisplayEventReceiver::Event makeHotplug(PhysicalDisplayId displayId, nsecs_t tim } DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t timestamp, - uint32_t count) { + uint32_t count, nsecs_t expectedVSyncTimestamp) { DisplayEventReceiver::Event event; event.header = {DisplayEventReceiver::DISPLAY_EVENT_VSYNC, displayId, timestamp}; event.vsync.count = count; + event.vsync.expectedVSyncTimestamp = expectedVSyncTimestamp; return event; } @@ -312,11 +314,12 @@ void EventThread::onScreenAcquired() { mCondition.notify_all(); } -void EventThread::onVSyncEvent(nsecs_t timestamp) { +void EventThread::onVSyncEvent(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp) { std::lock_guard<std::mutex> lock(mMutex); LOG_FATAL_IF(!mVSyncState); - mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count)); + mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count, + expectedVSyncTimestamp)); mCondition.notify_all(); } @@ -423,7 +426,8 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) { } else { // Generate a fake VSYNC after a long timeout in case the driver stalls. When the // display is off, keep feeding clients at 60 Hz. - const auto timeout = mState == State::SyntheticVSync ? 16ms : 1000ms; + const std::chrono::nanoseconds timeout = + mState == State::SyntheticVSync ? 16ms : 1000ms; if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) { if (mState == State::VSync) { ALOGW("Faking VSYNC due to driver stall for thread %s", mThreadName); @@ -439,9 +443,10 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) { } LOG_FATAL_IF(!mVSyncState); - mPendingEvents.push_back(makeVSync(mVSyncState->displayId, - systemTime(SYSTEM_TIME_MONOTONIC), - ++mVSyncState->count)); + const auto now = systemTime(SYSTEM_TIME_MONOTONIC); + const auto expectedVSyncTime = now + timeout.count(); + mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now, + ++mVSyncState->count, expectedVSyncTime)); } } } diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h index 98b1876994..9e7086eb0c 100644 --- a/services/surfaceflinger/Scheduler/EventThread.h +++ b/services/surfaceflinger/Scheduler/EventThread.h @@ -57,7 +57,7 @@ public: class Callback { public: virtual ~Callback() {} - virtual void onVSyncEvent(nsecs_t when) = 0; + virtual void onVSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp) = 0; }; virtual ~VSyncSource() {} @@ -189,7 +189,7 @@ private: REQUIRES(mMutex); // Implements VSyncSource::Callback - void onVSyncEvent(nsecs_t timestamp) override; + void onVSyncEvent(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp) override; const std::unique_ptr<VSyncSource> mVSyncSource GUARDED_BY(mMutex); diff --git a/services/surfaceflinger/Scheduler/InjectVSyncSource.h b/services/surfaceflinger/Scheduler/InjectVSyncSource.h index 31da588b72..975c9db41a 100644 --- a/services/surfaceflinger/Scheduler/InjectVSyncSource.h +++ b/services/surfaceflinger/Scheduler/InjectVSyncSource.h @@ -35,10 +35,10 @@ public: mCallback = callback; } - void onInjectSyncEvent(nsecs_t when) { + void onInjectSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp) { std::lock_guard<std::mutex> lock(mCallbackMutex); if (mCallback) { - mCallback->onVSyncEvent(when); + mCallback->onVSyncEvent(when, expectedVSyncTimestamp); } } diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp index d8a666a6de..9d6e1d864a 100644 --- a/services/surfaceflinger/Scheduler/MessageQueue.cpp +++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp @@ -62,9 +62,9 @@ void MessageQueue::Handler::dispatchRefresh() { } } -void MessageQueue::Handler::dispatchInvalidate(nsecs_t timestamp) { +void MessageQueue::Handler::dispatchInvalidate(nsecs_t expectedVSyncTimestamp) { if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) { - mLastVsyncTime = timestamp; + mExpectedVSyncTime = expectedVSyncTimestamp; mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE)); } } @@ -73,11 +73,11 @@ void MessageQueue::Handler::handleMessage(const Message& message) { switch (message.what) { case INVALIDATE: android_atomic_and(~eventMaskInvalidate, &mEventMask); - mQueue.mFlinger->onMessageReceived(message.what, mLastVsyncTime); + mQueue.mFlinger->onMessageReceived(message.what, mExpectedVSyncTime); break; case REFRESH: android_atomic_and(~eventMaskRefresh, &mEventMask); - mQueue.mFlinger->onMessageReceived(message.what, mLastVsyncTime); + mQueue.mFlinger->onMessageReceived(message.what, mExpectedVSyncTime); break; } } @@ -152,7 +152,7 @@ int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) { while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) { for (int i = 0; i < n; i++) { if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { - mHandler->dispatchInvalidate(buffer[i].header.timestamp); + mHandler->dispatchInvalidate(buffer[i].vsync.expectedVSyncTimestamp); break; } } diff --git a/services/surfaceflinger/Scheduler/MessageQueue.h b/services/surfaceflinger/Scheduler/MessageQueue.h index dbd5e96f00..ebc4315ec9 100644 --- a/services/surfaceflinger/Scheduler/MessageQueue.h +++ b/services/surfaceflinger/Scheduler/MessageQueue.h @@ -101,13 +101,13 @@ class MessageQueue final : public android::MessageQueue { enum { eventMaskInvalidate = 0x1, eventMaskRefresh = 0x2, eventMaskTransaction = 0x4 }; MessageQueue& mQueue; int32_t mEventMask; - std::atomic<nsecs_t> mLastVsyncTime; + std::atomic<nsecs_t> mExpectedVSyncTime; public: explicit Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) {} virtual void handleMessage(const Message& message); void dispatchRefresh(); - void dispatchInvalidate(nsecs_t timestamp); + void dispatchInvalidate(nsecs_t expectedVSyncTimestamp); }; friend class Handler; diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 3a84b67e93..86bb6eb7de 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -276,12 +276,12 @@ Scheduler::ConnectionHandle Scheduler::enableVSyncInjection(bool enable) { return mInjectorConnectionHandle; } -bool Scheduler::injectVSync(nsecs_t when) { +bool Scheduler::injectVSync(nsecs_t when, nsecs_t expectedVSyncTime) { if (!mInjectVSyncs || !mVSyncInjector) { return false; } - mVSyncInjector->onInjectSyncEvent(when); + mVSyncInjector->onInjectSyncEvent(when, expectedVSyncTime); return true; } diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 75c02f3134..4a0280fe1e 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -95,7 +95,7 @@ public: ConnectionHandle enableVSyncInjection(bool enable); // Returns false if injection is disabled. - bool injectVSync(nsecs_t when); + bool injectVSync(nsecs_t when, nsecs_t expectedVSyncTime); void enableHardwareVsync(); void disableHardwareVsync(bool makeUnavailable); diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp index 2f1faacba0..5f0c9ce40c 100644 --- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp +++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp @@ -128,7 +128,7 @@ private: mLastCallTime = vsynctime; } - mCallback->onDispSyncEvent(wakeupTime); + mCallback->onDispSyncEvent(wakeupTime, vsynctime); { std::lock_guard<std::mutex> lk(mMutex); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 811c660951..c5ebc540ab 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1415,7 +1415,7 @@ status_t SurfaceFlinger::enableVSyncInjections(bool enable) { status_t SurfaceFlinger::injectVSync(nsecs_t when) { Mutex::Autolock lock(mStateLock); - return mScheduler->injectVSync(when) ? NO_ERROR : BAD_VALUE; + return mScheduler->injectVSync(when, calculateExpectedPresentTime(when)) ? NO_ERROR : BAD_VALUE; } status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const @@ -1826,16 +1826,16 @@ nsecs_t SurfaceFlinger::previousFramePresentTime() NO_THREAD_SAFETY_ANALYSIS { return fence->getSignalTime(); } -void SurfaceFlinger::populateExpectedPresentTime(nsecs_t wakeupTime) { +nsecs_t SurfaceFlinger::calculateExpectedPresentTime(nsecs_t now) const { DisplayStatInfo stats; mScheduler->getDisplayStatInfo(&stats); - const nsecs_t presentTime = mScheduler->getDispSyncExpectedPresentTime(wakeupTime); + const nsecs_t presentTime = mScheduler->getDispSyncExpectedPresentTime(now); // Inflate the expected present time if we're targetting the next vsync. - mExpectedPresentTime.store( - mVSyncModulator->getOffsets().sf > 0 ? presentTime : presentTime + stats.vsyncPeriod); + return mVSyncModulator->getOffsets().sf > 0 ? presentTime : presentTime + stats.vsyncPeriod; } -void SurfaceFlinger::onMessageReceived(int32_t what, nsecs_t when) NO_THREAD_SAFETY_ANALYSIS { +void SurfaceFlinger::onMessageReceived(int32_t what, + nsecs_t expectedVSyncTime) NO_THREAD_SAFETY_ANALYSIS { ATRACE_CALL(); switch (what) { case MessageQueue::INVALIDATE: { @@ -1844,7 +1844,7 @@ void SurfaceFlinger::onMessageReceived(int32_t what, nsecs_t when) NO_THREAD_SAF // value throughout this frame to make sure all layers are // seeing this same value. const nsecs_t lastExpectedPresentTime = mExpectedPresentTime.load(); - populateExpectedPresentTime(when); + mExpectedPresentTime = expectedVSyncTime; // When Backpressure propagation is enabled we want to give a small grace period // for the present fence to fire instead of just giving up on this frame to handle cases @@ -3244,7 +3244,6 @@ bool SurfaceFlinger::flushTransactionQueues() { while (!transactionQueue.empty()) { const auto& transaction = transactionQueue.front(); if (!transactionIsReadyToBeApplied(transaction.desiredPresentTime, - true /* useCachedExpectedPresentTime */, transaction.states)) { setTransactionFlags(eTransactionFlushNeeded); break; @@ -3276,9 +3275,7 @@ bool SurfaceFlinger::transactionFlushNeeded() { bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime, - bool useCachedExpectedPresentTime, const Vector<ComposerState>& states) { - if (!useCachedExpectedPresentTime) populateExpectedPresentTime(systemTime()); const nsecs_t expectedPresentTime = mExpectedPresentTime.load(); // Do not present if the desiredPresentTime has not passed unless it is more than one second @@ -3330,9 +3327,13 @@ void SurfaceFlinger::setTransactionState( } } + const bool pendingTransactions = itr != mTransactionQueues.end(); // Expected present time is computed and cached on invalidate, so it may be stale. - if (itr != mTransactionQueues.end() || !transactionIsReadyToBeApplied( - desiredPresentTime, false /* useCachedExpectedPresentTime */, states)) { + if (!pendingTransactions) { + mExpectedPresentTime = calculateExpectedPresentTime(systemTime()); + } + + if (pendingTransactions || !transactionIsReadyToBeApplied(desiredPresentTime, states)) { mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime, uncacheBuffer, postTime, privileged, hasListenerCallbacks, listenerCallbacks); @@ -5667,13 +5668,13 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, usage, "screenshot"); return captureScreenCommon(renderArea, traverseLayers, *outBuffer, useIdentityTransform, - outCapturedSecureLayers); + false /* regionSampling */, outCapturedSecureLayers); } status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, const sp<GraphicBuffer>& buffer, - bool useIdentityTransform, + bool useIdentityTransform, bool regionSampling, bool& outCapturedSecureLayers) { // This mutex protects syncFd and captureResult for communication of the return values from the // main thread back to this Binder thread @@ -5704,7 +5705,7 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, renderArea.render([&] { result = captureScreenImplLocked(renderArea, traverseLayers, buffer.get(), useIdentityTransform, forSystem, &fd, - outCapturedSecureLayers); + regionSampling, outCapturedSecureLayers); }); } @@ -5741,7 +5742,7 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, bool useIdentityTransform, - int* outSyncFd) { + bool regionSampling, int* outSyncFd) { ATRACE_CALL(); const auto reqWidth = renderArea.getReqWidth(); @@ -5797,6 +5798,12 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, for (auto& settings : results) { settings.geometry.positionTransform = transform.asMatrix4() * settings.geometry.positionTransform; + // There's no need to process blurs when we're executing region sampling, + // we're just trying to understand what we're drawing, and doing so without + // blurs is already a pretty good approximation. + if (regionSampling) { + settings.backgroundBlurRadius = 0; + } } clientCompositionLayers.insert(clientCompositionLayers.end(), std::make_move_iterator(results.begin()), @@ -5834,7 +5841,8 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, bool useIdentityTransform, bool forSystem, - int* outSyncFd, bool& outCapturedSecureLayers) { + int* outSyncFd, bool regionSampling, + bool& outCapturedSecureLayers) { ATRACE_CALL(); traverseLayers([&](Layer* layer) { @@ -5849,7 +5857,8 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, ALOGW("FB is protected: PERMISSION_DENIED"); return PERMISSION_DENIED; } - renderScreenImplLocked(renderArea, traverseLayers, buffer, useIdentityTransform, outSyncFd); + renderScreenImplLocked(renderArea, traverseLayers, buffer, useIdentityTransform, regionSampling, + outSyncFd); return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 5a8153ef0e..8973bc92f5 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -315,7 +315,7 @@ public: // 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, nsecs_t when); + void onMessageReceived(int32_t what, nsecs_t expectedVSyncTime); renderengine::RenderEngine& getRenderEngine() const; @@ -630,7 +630,6 @@ private: void commitTransaction() REQUIRES(mStateLock); void commitOffscreenLayers(); bool transactionIsReadyToBeApplied(int64_t desiredPresentTime, - bool useCachedExpectedPresentTime, const Vector<ComposerState>& states); uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock); uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands) @@ -702,19 +701,20 @@ private: void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, bool useIdentityTransform, - int* outSyncFd); + bool regionSampling, int* outSyncFd); status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, sp<GraphicBuffer>* outBuffer, const ui::PixelFormat reqPixelFormat, bool useIdentityTransform, bool& outCapturedSecureLayers); status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers, const sp<GraphicBuffer>& buffer, bool useIdentityTransform, - bool& outCapturedSecureLayers); + bool regionSampling, bool& outCapturedSecureLayers); const sp<DisplayDevice> getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack); const sp<DisplayDevice> getDisplayByLayerStack(uint64_t layerStack); status_t captureScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, bool useIdentityTransform, - bool forSystem, int* outSyncFd, bool& outCapturedSecureLayers); + bool forSystem, int* outSyncFd, bool regionSampling, + bool& outCapturedSecureLayers); void traverseLayersInDisplay(const sp<const DisplayDevice>& display, const LayerVector::Visitor& visitor); @@ -852,9 +852,9 @@ private: // Must be called on the main thread. nsecs_t previousFramePresentTime(); - // Populates the expected present time for this frame. For negative offsets, performs a + // Calculates the expected present time for this frame. For negative offsets, performs a // correction using the predicted vsync for the next frame instead. - void populateExpectedPresentTime(nsecs_t now); + nsecs_t calculateExpectedPresentTime(nsecs_t now) const; /* * Display identification diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 0a0c9b7c51..e0dd0d9f07 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -231,6 +231,7 @@ void CompositionTest::captureScreenComposition() { const Rect sourceCrop(0, 0, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT); constexpr bool useIdentityTransform = true; constexpr bool forSystem = true; + constexpr bool regionSampling = false; DisplayRenderArea renderArea(mDisplay, sourceCrop, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT, ui::Dataspace::V0_SRGB, @@ -249,7 +250,7 @@ void CompositionTest::captureScreenComposition() { int fd = -1; status_t result = mFlinger.captureScreenImplLocked(renderArea, traverseLayers, mCaptureScreenBuffer.get(), - useIdentityTransform, forSystem, &fd); + useIdentityTransform, forSystem, &fd, regionSampling); if (fd >= 0) { close(fd); } diff --git a/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp b/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp index 2e705dad6d..afebc40aa9 100644 --- a/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp +++ b/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp @@ -43,7 +43,7 @@ protected: void createDispSync(); void createDispSyncSource(); - void onVSyncEvent(nsecs_t when) override; + void onVSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp) override; std::unique_ptr<mock::DispSync> mDispSync; std::unique_ptr<DispSyncSource> mDispSyncSource; @@ -66,7 +66,7 @@ DispSyncSourceTest::~DispSyncSourceTest() { ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); } -void DispSyncSourceTest::onVSyncEvent(nsecs_t when) { +void DispSyncSourceTest::onVSyncEvent(nsecs_t when, nsecs_t /*expectedVSyncTimestamp*/) { ALOGD("onVSyncEvent: %" PRId64, when); mVSyncEventCallRecorder.recordCall(when); diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp index ba5c0c2988..b90b566eee 100644 --- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp +++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp @@ -258,14 +258,14 @@ TEST_F(EventThreadTest, requestNextVsyncPostsASingleVSyncEventToTheConnection) { // Use the received callback to signal a first vsync event. // The interceptor should receive the event, as well as the connection. - mCallback->onVSyncEvent(123); + mCallback->onVSyncEvent(123, 456); expectInterceptCallReceived(123); expectVsyncEventReceivedByConnection(123, 1u); // Use the received callback to signal a second vsync event. // The interceptor should receive the event, but the the connection should // not as it was only interested in the first. - mCallback->onVSyncEvent(456); + mCallback->onVSyncEvent(456, 123); expectInterceptCallReceived(456); EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value()); @@ -299,7 +299,7 @@ TEST_F(EventThreadTest, setVsyncRateZeroPostsNoVSyncEventsToThatConnection) { // Send a vsync event. EventThread should then make a call to the // interceptor, and the second connection. The first connection should not // get the event. - mCallback->onVSyncEvent(123); + mCallback->onVSyncEvent(123, 456); expectInterceptCallReceived(123); EXPECT_FALSE(firstConnectionEventRecorder.waitForUnexpectedCall().has_value()); expectVsyncEventReceivedByConnection("secondConnection", secondConnectionEventRecorder, 123, @@ -314,17 +314,17 @@ TEST_F(EventThreadTest, setVsyncRateOnePostsAllEventsToThatConnection) { // Send a vsync event. EventThread should then make a call to the // interceptor, and the connection. - mCallback->onVSyncEvent(123); + mCallback->onVSyncEvent(123, 456); expectInterceptCallReceived(123); expectVsyncEventReceivedByConnection(123, 1u); // A second event should go to the same places. - mCallback->onVSyncEvent(456); + mCallback->onVSyncEvent(456, 123); expectInterceptCallReceived(456); expectVsyncEventReceivedByConnection(456, 2u); // A third event should go to the same places. - mCallback->onVSyncEvent(789); + mCallback->onVSyncEvent(789, 777); expectInterceptCallReceived(789); expectVsyncEventReceivedByConnection(789, 3u); } @@ -336,22 +336,22 @@ TEST_F(EventThreadTest, setVsyncRateTwoPostsEveryOtherEventToThatConnection) { expectVSyncSetEnabledCallReceived(true); // The first event will be seen by the interceptor, and not the connection. - mCallback->onVSyncEvent(123); + mCallback->onVSyncEvent(123, 456); expectInterceptCallReceived(123); EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value()); // The second event will be seen by the interceptor and the connection. - mCallback->onVSyncEvent(456); + mCallback->onVSyncEvent(456, 123); expectInterceptCallReceived(456); expectVsyncEventReceivedByConnection(456, 2u); // The third event will be seen by the interceptor, and not the connection. - mCallback->onVSyncEvent(789); + mCallback->onVSyncEvent(789, 777); expectInterceptCallReceived(789); EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value()); // The fourth event will be seen by the interceptor and the connection. - mCallback->onVSyncEvent(101112); + mCallback->onVSyncEvent(101112, 7847); expectInterceptCallReceived(101112); expectVsyncEventReceivedByConnection(101112, 4u); } @@ -366,7 +366,7 @@ TEST_F(EventThreadTest, connectionsRemovedIfInstanceDestroyed) { mConnection = nullptr; // The first event will be seen by the interceptor, and not the connection. - mCallback->onVSyncEvent(123); + mCallback->onVSyncEvent(123, 456); expectInterceptCallReceived(123); EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value()); @@ -386,13 +386,13 @@ TEST_F(EventThreadTest, connectionsRemovedIfEventDeliveryError) { // The first event will be seen by the interceptor, and by the connection, // which then returns an error. - mCallback->onVSyncEvent(123); + mCallback->onVSyncEvent(123, 456); expectInterceptCallReceived(123); expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u); // A subsequent event will be seen by the interceptor and not by the // connection. - mCallback->onVSyncEvent(456); + mCallback->onVSyncEvent(456, 123); expectInterceptCallReceived(456); EXPECT_FALSE(errorConnectionEventRecorder.waitForUnexpectedCall().has_value()); @@ -420,7 +420,7 @@ TEST_F(EventThreadTest, tracksEventConnections) { // The first event will be seen by the interceptor, and by the connection, // which then returns an error. - mCallback->onVSyncEvent(123); + mCallback->onVSyncEvent(123, 456); expectInterceptCallReceived(123); expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u); expectVsyncEventReceivedByConnection("successConnection", secondConnectionEventRecorder, 123, @@ -440,13 +440,13 @@ TEST_F(EventThreadTest, eventsDroppedIfNonfatalEventDeliveryError) { // The first event will be seen by the interceptor, and by the connection, // which then returns an non-fatal error. - mCallback->onVSyncEvent(123); + mCallback->onVSyncEvent(123, 456); expectInterceptCallReceived(123); expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u); // A subsequent event will be seen by the interceptor, and by the connection, // which still then returns an non-fatal error. - mCallback->onVSyncEvent(456); + mCallback->onVSyncEvent(456, 123); expectInterceptCallReceived(456); expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 456, 2u); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index ba640de419..add33270f9 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -323,13 +323,14 @@ public: auto onMessageReceived(int32_t what) { return mFlinger->onMessageReceived(what, systemTime()); } - auto captureScreenImplLocked( - const RenderArea& renderArea, SurfaceFlinger::TraverseLayersFunction traverseLayers, - ANativeWindowBuffer* buffer, bool useIdentityTransform, bool forSystem, int* outSyncFd) { + auto captureScreenImplLocked(const RenderArea& renderArea, + SurfaceFlinger::TraverseLayersFunction traverseLayers, + ANativeWindowBuffer* buffer, bool useIdentityTransform, + bool forSystem, int* outSyncFd, bool regionSampling) { bool ignored; return mFlinger->captureScreenImplLocked(renderArea, traverseLayers, buffer, useIdentityTransform, forSystem, outSyncFd, - ignored); + regionSampling, ignored); } auto traverseLayersInDisplay(const sp<const DisplayDevice>& display, diff --git a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp index 32c9045ade..3f14d652ce 100644 --- a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp @@ -135,7 +135,7 @@ std::shared_ptr<FenceTime> generateSignalledFenceWithTime(nsecs_t time) { class StubCallback : public DispSync::Callback { public: - void onDispSyncEvent(nsecs_t when) final { + void onDispSyncEvent(nsecs_t when, nsecs_t /*expectedVSyncTimestamp*/) final { std::lock_guard<std::mutex> lk(mMutex); mLastCallTime = when; } @@ -544,7 +544,9 @@ TEST_F(VSyncReactorTest, selfRemovingEventListenerStopsCallbacks) { class SelfRemovingCallback : public DispSync::Callback { public: SelfRemovingCallback(VSyncReactor& vsr) : mVsr(vsr) {} - void onDispSyncEvent(nsecs_t when) final { mVsr.removeEventListener(this, &when); } + void onDispSyncEvent(nsecs_t when, nsecs_t /*expectedVSyncTimestamp*/) final { + mVsr.removeEventListener(this, &when); + } private: VSyncReactor& mVsr; diff --git a/services/surfaceflinger/tests/unittests/mock/MockDispSync.cpp b/services/surfaceflinger/tests/unittests/mock/MockDispSync.cpp index f6c4f62022..1c8c44dca0 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockDispSync.cpp +++ b/services/surfaceflinger/tests/unittests/mock/MockDispSync.cpp @@ -17,6 +17,7 @@ #include "mock/MockDispSync.h" #include <thread> +using namespace std::chrono_literals; namespace android { namespace mock { @@ -54,8 +55,9 @@ status_t DispSync::changePhaseOffset(Callback* callback, nsecs_t phase) { void DispSync::triggerCallback() { if (mCallback.callback == nullptr) return; - mCallback.callback->onDispSyncEvent( - std::chrono::steady_clock::now().time_since_epoch().count()); + const std::chrono::nanoseconds now = std::chrono::steady_clock::now().time_since_epoch(); + const auto expectedVSyncTime = now + 16ms; + mCallback.callback->onDispSyncEvent(now.count(), expectedVSyncTime.count()); } } // namespace mock |