summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/BufferStateLayer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/surfaceflinger/BufferStateLayer.cpp')
-rw-r--r--services/surfaceflinger/BufferStateLayer.cpp1086
1 files changed, 0 insertions, 1086 deletions
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
deleted file mode 100644
index e06f3c4d42..0000000000
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ /dev/null
@@ -1,1086 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#undef LOG_TAG
-#define LOG_TAG "BufferStateLayer"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include "BufferStateLayer.h"
-
-#include <limits>
-
-#include <FrameTimeline/FrameTimeline.h>
-#include <compositionengine/LayerFECompositionState.h>
-#include <gui/BufferQueue.h>
-#include <private/gui/SyncFeatures.h>
-#include <renderengine/Image.h>
-#include "TunnelModeEnabledReporter.h"
-
-#include "EffectLayer.h"
-#include "FrameTracer/FrameTracer.h"
-#include "TimeStats/TimeStats.h"
-
-#define EARLY_RELEASE_ENABLED false
-
-namespace android {
-
-using PresentState = frametimeline::SurfaceFrame::PresentState;
-namespace {
-void callReleaseBufferCallback(const sp<ITransactionCompletedListener>& listener,
- const sp<GraphicBuffer>& buffer, uint64_t framenumber,
- const sp<Fence>& releaseFence,
- uint32_t currentMaxAcquiredBufferCount) {
- if (!listener) {
- return;
- }
- listener->onReleaseBuffer({buffer->getId(), framenumber},
- releaseFence ? releaseFence : Fence::NO_FENCE,
- currentMaxAcquiredBufferCount);
-}
-} // namespace
-
-BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args)
- : BufferLayer(args), mHwcSlotGenerator(new HwcSlotGenerator()) {
- mDrawingState.dataspace = ui::Dataspace::V0_SRGB;
-}
-
-BufferStateLayer::~BufferStateLayer() {
- // The original layer and the clone layer share the same texture and buffer. Therefore, only
- // one of the layers, in this case the original layer, needs to handle the deletion. The
- // original layer and the clone should be removed at the same time so there shouldn't be any
- // issue with the clone layer trying to use the texture.
- if (mBufferInfo.mBuffer != nullptr) {
- callReleaseBufferCallback(mDrawingState.releaseBufferListener,
- mBufferInfo.mBuffer->getBuffer(), mBufferInfo.mFrameNumber,
- mBufferInfo.mFence,
- mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(
- mOwnerUid));
- }
-}
-
-// -----------------------------------------------------------------------
-// Interface implementation for Layer
-// -----------------------------------------------------------------------
-void BufferStateLayer::onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFenceResult) {
- // If we are displayed on multiple displays in a single composition cycle then we would
- // need to do careful tracking to enable the use of the mLastClientCompositionFence.
- // For example we can only use it if all the displays are client comp, and we need
- // to merge all the client comp fences. We could do this, but for now we just
- // disable the optimization when a layer is composed on multiple displays.
- if (mClearClientCompositionFenceOnLayerDisplayed) {
- mLastClientCompositionFence = nullptr;
- } else {
- mClearClientCompositionFenceOnLayerDisplayed = true;
- }
-
- // The previous release fence notifies the client that SurfaceFlinger is done with the previous
- // buffer that was presented on this layer. The first transaction that came in this frame that
- // replaced the previous buffer on this layer needs this release fence, because the fence will
- // let the client know when that previous buffer is removed from the screen.
- //
- // Every other transaction on this layer does not need a release fence because no other
- // Transactions that were set on this layer this frame are going to have their preceeding buffer
- // removed from the display this frame.
- //
- // For example, if we have 3 transactions this frame. The first transaction doesn't contain a
- // buffer so it doesn't need a previous release fence because the layer still needs the previous
- // buffer. The second transaction contains a buffer so it needs a previous release fence because
- // the previous buffer will be released this frame. The third transaction also contains a
- // buffer. It replaces the buffer in the second transaction. The buffer in the second
- // transaction will now no longer be presented so it is released immediately and the third
- // transaction doesn't need a previous release fence.
- sp<CallbackHandle> ch;
- for (auto& handle : mDrawingState.callbackHandles) {
- if (handle->releasePreviousBuffer &&
- mDrawingState.releaseBufferEndpoint == handle->listener) {
- ch = handle;
- break;
- }
- }
-
- // Prevent tracing the same release multiple times.
- if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) {
- mPreviousReleasedFrameNumber = mPreviousFrameNumber;
- }
-
- if (ch != nullptr) {
- ch->previousReleaseCallbackId = mPreviousReleaseCallbackId;
- ch->previousReleaseFences.emplace_back(std::move(futureFenceResult));
- ch->name = mName;
- }
-}
-
-void BufferStateLayer::onSurfaceFrameCreated(
- const std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame) {
- while (mPendingJankClassifications.size() >= kPendingClassificationMaxSurfaceFrames) {
- // Too many SurfaceFrames pending classification. The front of the deque is probably not
- // tracked by FrameTimeline and will never be presented. This will only result in a memory
- // leak.
- ALOGW("Removing the front of pending jank deque from layer - %s to prevent memory leak",
- mName.c_str());
- std::string miniDump = mPendingJankClassifications.front()->miniDump();
- ALOGD("Head SurfaceFrame mini dump\n%s", miniDump.c_str());
- mPendingJankClassifications.pop_front();
- }
- mPendingJankClassifications.emplace_back(surfaceFrame);
-}
-
-void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
- for (const auto& handle : mDrawingState.callbackHandles) {
- handle->transformHint = mTransformHint;
- handle->dequeueReadyTime = dequeueReadyTime;
- handle->currentMaxAcquiredBufferCount =
- mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mOwnerUid);
- }
-
- for (auto& handle : mDrawingState.callbackHandles) {
- if (handle->releasePreviousBuffer &&
- mDrawingState.releaseBufferEndpoint == handle->listener) {
- handle->previousReleaseCallbackId = mPreviousReleaseCallbackId;
- break;
- }
- }
-
- std::vector<JankData> jankData;
- jankData.reserve(mPendingJankClassifications.size());
- while (!mPendingJankClassifications.empty()
- && mPendingJankClassifications.front()->getJankType()) {
- std::shared_ptr<frametimeline::SurfaceFrame> surfaceFrame =
- mPendingJankClassifications.front();
- mPendingJankClassifications.pop_front();
- jankData.emplace_back(
- JankData(surfaceFrame->getToken(), surfaceFrame->getJankType().value()));
- }
-
- mFlinger->getTransactionCallbackInvoker().addCallbackHandles(
- mDrawingState.callbackHandles, jankData);
-
- sp<Fence> releaseFence = Fence::NO_FENCE;
- for (auto& handle : mDrawingState.callbackHandles) {
- if (handle->releasePreviousBuffer &&
- mDrawingState.releaseBufferEndpoint == handle->listener) {
- releaseFence =
- handle->previousReleaseFence ? handle->previousReleaseFence : Fence::NO_FENCE;
- break;
- }
- }
-
- mDrawingState.callbackHandles = {};
-}
-
-void BufferStateLayer::finalizeFrameEventHistory(const std::shared_ptr<FenceTime>& glDoneFence,
- const CompositorTiming& compositorTiming) {
- for (const auto& handle : mDrawingState.callbackHandles) {
- handle->gpuCompositionDoneFence = glDoneFence;
- handle->compositorTiming = compositorTiming;
- }
-}
-
-bool BufferStateLayer::willPresentCurrentTransaction() const {
- // Returns true if the most recent Transaction applied to CurrentState will be presented.
- return (getSidebandStreamChanged() || getAutoRefresh() ||
- (mDrawingState.modified &&
- (mDrawingState.buffer != nullptr || mDrawingState.bgColorLayer != nullptr)));
-}
-
-Rect BufferStateLayer::getCrop(const Layer::State& s) const {
- return s.crop;
-}
-
-bool BufferStateLayer::setTransform(uint32_t transform) {
- if (mDrawingState.bufferTransform == transform) return false;
- mDrawingState.bufferTransform = transform;
- mDrawingState.modified = true;
- setTransactionFlags(eTransactionNeeded);
- return true;
-}
-
-bool BufferStateLayer::setTransformToDisplayInverse(bool transformToDisplayInverse) {
- if (mDrawingState.transformToDisplayInverse == transformToDisplayInverse) return false;
- mDrawingState.sequence++;
- mDrawingState.transformToDisplayInverse = transformToDisplayInverse;
- mDrawingState.modified = true;
- setTransactionFlags(eTransactionNeeded);
- return true;
-}
-
-bool BufferStateLayer::setCrop(const Rect& crop) {
- if (mDrawingState.crop == crop) return false;
- mDrawingState.sequence++;
- mDrawingState.crop = crop;
-
- mDrawingState.modified = true;
- setTransactionFlags(eTransactionNeeded);
- return true;
-}
-
-bool BufferStateLayer::setBufferCrop(const Rect& bufferCrop) {
- if (mDrawingState.bufferCrop == bufferCrop) return false;
-
- mDrawingState.sequence++;
- mDrawingState.bufferCrop = bufferCrop;
-
- mDrawingState.modified = true;
- setTransactionFlags(eTransactionNeeded);
- return true;
-}
-
-bool BufferStateLayer::setDestinationFrame(const Rect& destinationFrame) {
- if (mDrawingState.destinationFrame == destinationFrame) return false;
-
- mDrawingState.sequence++;
- mDrawingState.destinationFrame = destinationFrame;
-
- mDrawingState.modified = true;
- setTransactionFlags(eTransactionNeeded);
- return true;
-}
-
-static bool assignTransform(ui::Transform* dst, ui::Transform& from) {
- if (*dst == from) {
- return false;
- }
- *dst = from;
- return true;
-}
-
-// Translate destination frame into scale and position. If a destination frame is not set, use the
-// provided scale and position
-bool BufferStateLayer::updateGeometry() {
- if ((mDrawingState.flags & layer_state_t::eIgnoreDestinationFrame) ||
- mDrawingState.destinationFrame.isEmpty()) {
- // If destination frame is not set, use the requested transform set via
- // BufferStateLayer::setPosition and BufferStateLayer::setMatrix.
- return assignTransform(&mDrawingState.transform, mRequestedTransform);
- }
-
- Rect destRect = mDrawingState.destinationFrame;
- int32_t destW = destRect.width();
- int32_t destH = destRect.height();
- if (destRect.left < 0) {
- destRect.left = 0;
- destRect.right = destW;
- }
- if (destRect.top < 0) {
- destRect.top = 0;
- destRect.bottom = destH;
- }
-
- if (!mDrawingState.buffer) {
- ui::Transform t;
- t.set(destRect.left, destRect.top);
- return assignTransform(&mDrawingState.transform, t);
- }
-
- uint32_t bufferWidth = mDrawingState.buffer->getWidth();
- uint32_t bufferHeight = mDrawingState.buffer->getHeight();
- // Undo any transformations on the buffer.
- if (mDrawingState.bufferTransform & ui::Transform::ROT_90) {
- std::swap(bufferWidth, bufferHeight);
- }
- uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags();
- if (mDrawingState.transformToDisplayInverse) {
- if (invTransform & ui::Transform::ROT_90) {
- std::swap(bufferWidth, bufferHeight);
- }
- }
-
- float sx = destW / static_cast<float>(bufferWidth);
- float sy = destH / static_cast<float>(bufferHeight);
- ui::Transform t;
- t.set(sx, 0, 0, sy);
- t.set(destRect.left, destRect.top);
- return assignTransform(&mDrawingState.transform, t);
-}
-
-bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix) {
- if (mRequestedTransform.dsdx() == matrix.dsdx && mRequestedTransform.dtdy() == matrix.dtdy &&
- mRequestedTransform.dtdx() == matrix.dtdx && mRequestedTransform.dsdy() == matrix.dsdy) {
- return false;
- }
-
- ui::Transform t;
- t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
-
- mRequestedTransform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
-
- mDrawingState.sequence++;
- mDrawingState.modified = true;
- setTransactionFlags(eTransactionNeeded);
-
- return true;
-}
-
-bool BufferStateLayer::setPosition(float x, float y) {
- if (mRequestedTransform.tx() == x && mRequestedTransform.ty() == y) {
- return false;
- }
-
- mRequestedTransform.set(x, y);
-
- mDrawingState.sequence++;
- mDrawingState.modified = true;
- setTransactionFlags(eTransactionNeeded);
-
- return true;
-}
-
-bool BufferStateLayer::setBuffer(std::shared_ptr<renderengine::ExternalTexture>& buffer,
- const BufferData& bufferData, nsecs_t postTime,
- nsecs_t desiredPresentTime, bool isAutoTimestamp,
- std::optional<nsecs_t> dequeueTime,
- const FrameTimelineInfo& info) {
- ATRACE_CALL();
-
- if (!buffer) {
- return false;
- }
-
- const bool frameNumberChanged =
- bufferData.flags.test(BufferData::BufferDataChange::frameNumberChanged);
- const uint64_t frameNumber =
- frameNumberChanged ? bufferData.frameNumber : mDrawingState.frameNumber + 1;
-
- if (mDrawingState.buffer) {
- mReleasePreviousBuffer = true;
- if (!mBufferInfo.mBuffer ||
- (!mDrawingState.buffer->hasSameBuffer(*mBufferInfo.mBuffer) ||
- mDrawingState.frameNumber != mBufferInfo.mFrameNumber)) {
- // If mDrawingState has a buffer, and we are about to update again
- // before swapping to drawing state, then the first buffer will be
- // dropped and we should decrement the pending buffer count and
- // call any release buffer callbacks if set.
- callReleaseBufferCallback(mDrawingState.releaseBufferListener,
- mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber,
- mDrawingState.acquireFence,
- mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(
- mOwnerUid));
- decrementPendingBufferCount();
- if (mDrawingState.bufferSurfaceFrameTX != nullptr &&
- mDrawingState.bufferSurfaceFrameTX->getPresentState() != PresentState::Presented) {
- addSurfaceFrameDroppedForBuffer(mDrawingState.bufferSurfaceFrameTX);
- mDrawingState.bufferSurfaceFrameTX.reset();
- }
- } else if (EARLY_RELEASE_ENABLED && mLastClientCompositionFence != nullptr) {
- callReleaseBufferCallback(mDrawingState.releaseBufferListener,
- mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber,
- mLastClientCompositionFence,
- mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(
- mOwnerUid));
- mLastClientCompositionFence = nullptr;
- }
- }
-
- mDrawingState.frameNumber = frameNumber;
- mDrawingState.releaseBufferListener = bufferData.releaseBufferListener;
- mDrawingState.buffer = std::move(buffer);
- mDrawingState.clientCacheId = bufferData.cachedBuffer;
-
- mDrawingState.acquireFence = bufferData.flags.test(BufferData::BufferDataChange::fenceChanged)
- ? bufferData.acquireFence
- : Fence::NO_FENCE;
- mDrawingState.acquireFenceTime = std::make_unique<FenceTime>(mDrawingState.acquireFence);
- if (mDrawingState.acquireFenceTime->getSignalTime() == Fence::SIGNAL_TIME_PENDING) {
- // We latched this buffer unsiganled, so we need to pass the acquire fence
- // on the callback instead of just the acquire time, since it's unknown at
- // this point.
- mCallbackHandleAcquireTimeOrFence = mDrawingState.acquireFence;
- } else {
- mCallbackHandleAcquireTimeOrFence = mDrawingState.acquireFenceTime->getSignalTime();
- }
-
- mDrawingState.modified = true;
- setTransactionFlags(eTransactionNeeded);
-
- const int32_t layerId = getSequence();
- mFlinger->mTimeStats->setPostTime(layerId, mDrawingState.frameNumber, getName().c_str(),
- mOwnerUid, postTime, getGameMode());
- mDrawingState.desiredPresentTime = desiredPresentTime;
- mDrawingState.isAutoTimestamp = isAutoTimestamp;
-
- const nsecs_t presentTime = [&] {
- if (!isAutoTimestamp) return desiredPresentTime;
-
- const auto prediction =
- mFlinger->mFrameTimeline->getTokenManager()->getPredictionsForToken(info.vsyncId);
- if (prediction.has_value()) return prediction->presentTime;
-
- return static_cast<nsecs_t>(0);
- }();
-
- using LayerUpdateType = scheduler::LayerHistory::LayerUpdateType;
- mFlinger->mScheduler->recordLayerHistory(this, presentTime, LayerUpdateType::Buffer);
-
- setFrameTimelineVsyncForBufferTransaction(info, postTime);
-
- if (dequeueTime && *dequeueTime != 0) {
- const uint64_t bufferId = mDrawingState.buffer->getId();
- mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str());
- mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, frameNumber, *dequeueTime,
- FrameTracer::FrameEvent::DEQUEUE);
- mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, frameNumber, postTime,
- FrameTracer::FrameEvent::QUEUE);
- }
-
- mDrawingState.width = mDrawingState.buffer->getWidth();
- mDrawingState.height = mDrawingState.buffer->getHeight();
- mDrawingState.releaseBufferEndpoint = bufferData.releaseBufferEndpoint;
- return true;
-}
-
-bool BufferStateLayer::setDataspace(ui::Dataspace dataspace) {
- if (mDrawingState.dataspace == dataspace) return false;
- mDrawingState.dataspace = dataspace;
- mDrawingState.modified = true;
- setTransactionFlags(eTransactionNeeded);
- return true;
-}
-
-bool BufferStateLayer::setHdrMetadata(const HdrMetadata& hdrMetadata) {
- if (mDrawingState.hdrMetadata == hdrMetadata) return false;
- mDrawingState.hdrMetadata = hdrMetadata;
- mDrawingState.modified = true;
- setTransactionFlags(eTransactionNeeded);
- return true;
-}
-
-bool BufferStateLayer::setSurfaceDamageRegion(const Region& surfaceDamage) {
- if (mDrawingState.surfaceDamageRegion.hasSameRects(surfaceDamage)) return false;
- mDrawingState.surfaceDamageRegion = surfaceDamage;
- mDrawingState.modified = true;
- setTransactionFlags(eTransactionNeeded);
- return true;
-}
-
-bool BufferStateLayer::setApi(int32_t api) {
- if (mDrawingState.api == api) return false;
- mDrawingState.api = api;
- mDrawingState.modified = true;
- setTransactionFlags(eTransactionNeeded);
- return true;
-}
-
-bool BufferStateLayer::setSidebandStream(const sp<NativeHandle>& sidebandStream) {
- if (mDrawingState.sidebandStream == sidebandStream) return false;
-
- if (mDrawingState.sidebandStream != nullptr && sidebandStream == nullptr) {
- mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount();
- } else if (sidebandStream != nullptr) {
- mFlinger->mTunnelModeEnabledReporter->incrementTunnelModeCount();
- }
-
- mDrawingState.sidebandStream = sidebandStream;
- mDrawingState.modified = true;
- setTransactionFlags(eTransactionNeeded);
- if (!mSidebandStreamChanged.exchange(true)) {
- // mSidebandStreamChanged was false
- mFlinger->onLayerUpdate();
- }
- return true;
-}
-
-bool BufferStateLayer::setTransactionCompletedListeners(
- const std::vector<sp<CallbackHandle>>& handles) {
- // If there is no handle, we will not send a callback so reset mReleasePreviousBuffer and return
- if (handles.empty()) {
- mReleasePreviousBuffer = false;
- return false;
- }
-
- const bool willPresent = willPresentCurrentTransaction();
-
- for (const auto& handle : handles) {
- // If this transaction set a buffer on this layer, release its previous buffer
- handle->releasePreviousBuffer = mReleasePreviousBuffer;
-
- // If this layer will be presented in this frame
- if (willPresent) {
- // If this transaction set an acquire fence on this layer, set its acquire time
- handle->acquireTimeOrFence = mCallbackHandleAcquireTimeOrFence;
- handle->frameNumber = mDrawingState.frameNumber;
-
- // Store so latched time and release fence can be set
- mDrawingState.callbackHandles.push_back(handle);
-
- } else { // If this layer will NOT need to be relatched and presented this frame
- // Notify the transaction completed thread this handle is done
- mFlinger->getTransactionCallbackInvoker().registerUnpresentedCallbackHandle(handle);
- }
- }
-
- mReleasePreviousBuffer = false;
- mCallbackHandleAcquireTimeOrFence = -1;
-
- return willPresent;
-}
-
-bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) {
- mDrawingState.sequence++;
- mDrawingState.transparentRegionHint = transparent;
- mDrawingState.modified = true;
- setTransactionFlags(eTransactionNeeded);
- return true;
-}
-
-Rect BufferStateLayer::getBufferSize(const State& /*s*/) const {
- // for buffer state layers we use the display frame size as the buffer size.
-
- if (mBufferInfo.mBuffer == nullptr) {
- return Rect::INVALID_RECT;
- }
-
- uint32_t bufWidth = mBufferInfo.mBuffer->getWidth();
- uint32_t bufHeight = mBufferInfo.mBuffer->getHeight();
-
- // Undo any transformations on the buffer and return the result.
- if (mBufferInfo.mTransform & ui::Transform::ROT_90) {
- std::swap(bufWidth, bufHeight);
- }
-
- if (getTransformToDisplayInverse()) {
- uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags();
- if (invTransform & ui::Transform::ROT_90) {
- std::swap(bufWidth, bufHeight);
- }
- }
-
- return Rect(0, 0, static_cast<int32_t>(bufWidth), static_cast<int32_t>(bufHeight));
-}
-
-FloatRect BufferStateLayer::computeSourceBounds(const FloatRect& parentBounds) const {
- if (mBufferInfo.mBuffer == nullptr) {
- return parentBounds;
- }
-
- return getBufferSize(getDrawingState()).toFloatRect();
-}
-
-// -----------------------------------------------------------------------
-
-// -----------------------------------------------------------------------
-// Interface implementation for BufferLayer
-// -----------------------------------------------------------------------
-bool BufferStateLayer::fenceHasSignaled() const {
- if (SurfaceFlinger::enableLatchUnsignaledConfig != LatchUnsignaledConfig::Disabled) {
- return true;
- }
-
- const bool fenceSignaled =
- getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled;
- if (!fenceSignaled) {
- mFlinger->mTimeStats->incrementLatchSkipped(getSequence(),
- TimeStats::LatchSkipReason::LateAcquire);
- }
-
- return fenceSignaled;
-}
-
-bool BufferStateLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const {
- if (!hasFrameUpdate() || isRemovedFromCurrentState()) {
- return true;
- }
-
- return mDrawingState.isAutoTimestamp || mDrawingState.desiredPresentTime <= expectedPresentTime;
-}
-
-bool BufferStateLayer::onPreComposition(nsecs_t refreshStartTime) {
- for (const auto& handle : mDrawingState.callbackHandles) {
- handle->refreshStartTime = refreshStartTime;
- }
- return BufferLayer::onPreComposition(refreshStartTime);
-}
-
-void BufferStateLayer::setAutoRefresh(bool autoRefresh) {
- mDrawingState.autoRefresh = autoRefresh;
-}
-
-bool BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) {
- // We need to update the sideband stream if the layer has both a buffer and a sideband stream.
- editCompositionState()->sidebandStreamHasFrame = hasFrameUpdate() && mSidebandStream.get();
-
- if (mSidebandStreamChanged.exchange(false)) {
- const State& s(getDrawingState());
- // mSidebandStreamChanged was true
- mSidebandStream = s.sidebandStream;
- editCompositionState()->sidebandStream = mSidebandStream;
- if (mSidebandStream != nullptr) {
- setTransactionFlags(eTransactionNeeded);
- mFlinger->setTransactionFlags(eTraversalNeeded);
- }
- recomputeVisibleRegions = true;
-
- return true;
- }
- return false;
-}
-
-bool BufferStateLayer::hasFrameUpdate() const {
- const State& c(getDrawingState());
- return (mDrawingStateModified || mDrawingState.modified) && (c.buffer != nullptr || c.bgColorLayer != nullptr);
-}
-
-status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime,
- nsecs_t /*expectedPresentTime*/) {
- const State& s(getDrawingState());
-
- if (!s.buffer) {
- if (s.bgColorLayer) {
- for (auto& handle : mDrawingState.callbackHandles) {
- handle->latchTime = latchTime;
- }
- }
- return NO_ERROR;
- }
-
- for (auto& handle : mDrawingState.callbackHandles) {
- if (handle->frameNumber == mDrawingState.frameNumber) {
- handle->latchTime = latchTime;
- }
- }
-
- const int32_t layerId = getSequence();
- const uint64_t bufferId = mDrawingState.buffer->getId();
- const uint64_t frameNumber = mDrawingState.frameNumber;
- const auto acquireFence = std::make_shared<FenceTime>(mDrawingState.acquireFence);
- mFlinger->mTimeStats->setAcquireFence(layerId, frameNumber, acquireFence);
- mFlinger->mTimeStats->setLatchTime(layerId, frameNumber, latchTime);
-
- mFlinger->mFrameTracer->traceFence(layerId, bufferId, frameNumber, acquireFence,
- FrameTracer::FrameEvent::ACQUIRE_FENCE);
- mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, frameNumber, latchTime,
- FrameTracer::FrameEvent::LATCH);
-
- auto& bufferSurfaceFrame = mDrawingState.bufferSurfaceFrameTX;
- if (bufferSurfaceFrame != nullptr &&
- bufferSurfaceFrame->getPresentState() != PresentState::Presented) {
- // Update only if the bufferSurfaceFrame wasn't already presented. A Presented
- // bufferSurfaceFrame could be seen here if a pending state was applied successfully and we
- // are processing the next state.
- addSurfaceFramePresentedForBuffer(bufferSurfaceFrame,
- mDrawingState.acquireFenceTime->getSignalTime(),
- latchTime);
- mDrawingState.bufferSurfaceFrameTX.reset();
- }
-
- std::deque<sp<CallbackHandle>> remainingHandles;
- mFlinger->getTransactionCallbackInvoker()
- .addOnCommitCallbackHandles(mDrawingState.callbackHandles, remainingHandles);
- mDrawingState.callbackHandles = remainingHandles;
-
- mDrawingStateModified = false;
-
- return NO_ERROR;
-}
-
-status_t BufferStateLayer::updateActiveBuffer() {
- const State& s(getDrawingState());
-
- if (s.buffer == nullptr) {
- return BAD_VALUE;
- }
-
- if (!mBufferInfo.mBuffer || !s.buffer->hasSameBuffer(*mBufferInfo.mBuffer)) {
- decrementPendingBufferCount();
- }
-
- mPreviousReleaseCallbackId = {getCurrentBufferId(), mBufferInfo.mFrameNumber};
- mBufferInfo.mBuffer = s.buffer;
- mBufferInfo.mFence = s.acquireFence;
- mBufferInfo.mFrameNumber = s.frameNumber;
-
- return NO_ERROR;
-}
-
-status_t BufferStateLayer::updateFrameNumber() {
- // TODO(marissaw): support frame history events
- mPreviousFrameNumber = mCurrentFrameNumber;
- mCurrentFrameNumber = mDrawingState.frameNumber;
- return NO_ERROR;
-}
-
-void BufferStateLayer::HwcSlotGenerator::bufferErased(const client_cache_t& clientCacheId) {
- std::lock_guard lock(mMutex);
- if (!clientCacheId.isValid()) {
- ALOGE("invalid process, failed to erase buffer");
- return;
- }
- eraseBufferLocked(clientCacheId);
-}
-
-int BufferStateLayer::HwcSlotGenerator::getHwcCacheSlot(const client_cache_t& clientCacheId) {
- std::lock_guard<std::mutex> lock(mMutex);
- auto itr = mCachedBuffers.find(clientCacheId);
- if (itr == mCachedBuffers.end()) {
- return addCachedBuffer(clientCacheId);
- }
- auto& [hwcCacheSlot, counter] = itr->second;
- counter = mCounter++;
- return hwcCacheSlot;
-}
-
-int BufferStateLayer::HwcSlotGenerator::addCachedBuffer(const client_cache_t& clientCacheId)
- REQUIRES(mMutex) {
- if (!clientCacheId.isValid()) {
- ALOGE("invalid process, returning invalid slot");
- return BufferQueue::INVALID_BUFFER_SLOT;
- }
-
- ClientCache::getInstance().registerErasedRecipient(clientCacheId, wp<ErasedRecipient>(this));
-
- int hwcCacheSlot = getFreeHwcCacheSlot();
- mCachedBuffers[clientCacheId] = {hwcCacheSlot, mCounter++};
- return hwcCacheSlot;
-}
-
-int BufferStateLayer::HwcSlotGenerator::getFreeHwcCacheSlot() REQUIRES(mMutex) {
- if (mFreeHwcCacheSlots.empty()) {
- evictLeastRecentlyUsed();
- }
-
- int hwcCacheSlot = mFreeHwcCacheSlots.top();
- mFreeHwcCacheSlots.pop();
- return hwcCacheSlot;
-}
-
-void BufferStateLayer::HwcSlotGenerator::evictLeastRecentlyUsed() REQUIRES(mMutex) {
- uint64_t minCounter = UINT_MAX;
- client_cache_t minClientCacheId = {};
- for (const auto& [clientCacheId, slotCounter] : mCachedBuffers) {
- const auto& [hwcCacheSlot, counter] = slotCounter;
- if (counter < minCounter) {
- minCounter = counter;
- minClientCacheId = clientCacheId;
- }
- }
- eraseBufferLocked(minClientCacheId);
-
- ClientCache::getInstance().unregisterErasedRecipient(minClientCacheId, this);
-}
-
-void BufferStateLayer::HwcSlotGenerator::eraseBufferLocked(const client_cache_t& clientCacheId)
- REQUIRES(mMutex) {
- auto itr = mCachedBuffers.find(clientCacheId);
- if (itr == mCachedBuffers.end()) {
- return;
- }
- auto& [hwcCacheSlot, counter] = itr->second;
-
- // TODO send to hwc cache and resources
-
- mFreeHwcCacheSlots.push(hwcCacheSlot);
- mCachedBuffers.erase(clientCacheId);
-}
-
-void BufferStateLayer::gatherBufferInfo() {
- BufferLayer::gatherBufferInfo();
-
- const State& s(getDrawingState());
- mBufferInfo.mDesiredPresentTime = s.desiredPresentTime;
- mBufferInfo.mFenceTime = std::make_shared<FenceTime>(s.acquireFence);
- mBufferInfo.mFence = s.acquireFence;
- mBufferInfo.mTransform = s.bufferTransform;
- auto lastDataspace = mBufferInfo.mDataspace;
- mBufferInfo.mDataspace = translateDataspace(s.dataspace);
- if (lastDataspace != mBufferInfo.mDataspace) {
- mFlinger->mSomeDataspaceChanged = true;
- }
- mBufferInfo.mCrop = computeBufferCrop(s);
- mBufferInfo.mScaleMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
- mBufferInfo.mSurfaceDamage = s.surfaceDamageRegion;
- mBufferInfo.mHdrMetadata = s.hdrMetadata;
- mBufferInfo.mApi = s.api;
- mBufferInfo.mTransformToDisplayInverse = s.transformToDisplayInverse;
- mBufferInfo.mBufferSlot = mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId);
-}
-
-uint32_t BufferStateLayer::getEffectiveScalingMode() const {
- return NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
-}
-
-Rect BufferStateLayer::computeBufferCrop(const State& s) {
- if (s.buffer && !s.bufferCrop.isEmpty()) {
- Rect bufferCrop;
- s.buffer->getBounds().intersect(s.bufferCrop, &bufferCrop);
- return bufferCrop;
- } else if (s.buffer) {
- return s.buffer->getBounds();
- } else {
- return s.bufferCrop;
- }
-}
-
-sp<Layer> BufferStateLayer::createClone() {
- LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, LayerMetadata());
- args.textureName = mTextureName;
- sp<BufferStateLayer> layer = mFlinger->getFactory().createBufferStateLayer(args);
- layer->mHwcSlotGenerator = mHwcSlotGenerator;
- layer->setInitialValuesForClone(this);
- return layer;
-}
-
-bool BufferStateLayer::bufferNeedsFiltering() const {
- const State& s(getDrawingState());
- if (!s.buffer) {
- return false;
- }
-
- int32_t bufferWidth = static_cast<int32_t>(s.buffer->getWidth());
- int32_t bufferHeight = static_cast<int32_t>(s.buffer->getHeight());
-
- // Undo any transformations on the buffer and return the result.
- if (s.bufferTransform & ui::Transform::ROT_90) {
- std::swap(bufferWidth, bufferHeight);
- }
-
- if (s.transformToDisplayInverse) {
- uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags();
- if (invTransform & ui::Transform::ROT_90) {
- std::swap(bufferWidth, bufferHeight);
- }
- }
-
- const Rect layerSize{getBounds()};
- return layerSize.width() != bufferWidth || layerSize.height() != bufferHeight;
-}
-
-void BufferStateLayer::decrementPendingBufferCount() {
- int32_t pendingBuffers = --mPendingBufferTransactions;
- tracePendingBufferCount(pendingBuffers);
-}
-
-void BufferStateLayer::tracePendingBufferCount(int32_t pendingBuffers) {
- ATRACE_INT(mBlastTransactionName.c_str(), pendingBuffers);
-}
-
-
-/*
- * We don't want to send the layer's transform to input, but rather the
- * parent's transform. This is because BufferStateLayer's transform is
- * information about how the buffer is placed on screen. The parent's
- * transform makes more sense to send since it's information about how the
- * layer is placed on screen. This transform is used by input to determine
- * how to go from screen space back to window space.
- */
-ui::Transform BufferStateLayer::getInputTransform() const {
- sp<Layer> parent = mDrawingParent.promote();
- if (parent == nullptr) {
- return ui::Transform();
- }
-
- return parent->getTransform();
-}
-
-/**
- * Similar to getInputTransform, we need to update the bounds to include the transform.
- * This is because bounds for BSL doesn't include buffer transform, where the input assumes
- * that's already included.
- */
-Rect BufferStateLayer::getInputBounds() const {
- Rect bufferBounds = getCroppedBufferSize(getDrawingState());
- if (mDrawingState.transform.getType() == ui::Transform::IDENTITY || !bufferBounds.isValid()) {
- return bufferBounds;
- }
- return mDrawingState.transform.transform(bufferBounds);
-}
-
-bool BufferStateLayer::simpleBufferUpdate(const layer_state_t& s) const {
- const uint64_t requiredFlags = layer_state_t::eBufferChanged;
-
- const uint64_t deniedFlags = layer_state_t::eProducerDisconnect | layer_state_t::eLayerChanged |
- layer_state_t::eRelativeLayerChanged | layer_state_t::eTransparentRegionChanged |
- layer_state_t::eFlagsChanged | layer_state_t::eBlurRegionsChanged |
- layer_state_t::eLayerStackChanged | layer_state_t::eAutoRefreshChanged |
- layer_state_t::eReparent;
-
- const uint64_t allowedFlags = layer_state_t::eHasListenerCallbacksChanged |
- layer_state_t::eFrameRateSelectionPriority | layer_state_t::eFrameRateChanged |
- layer_state_t::eSurfaceDamageRegionChanged | layer_state_t::eApiChanged |
- layer_state_t::eMetadataChanged | layer_state_t::eDropInputModeChanged |
- layer_state_t::eInputInfoChanged;
-
- if ((s.what & requiredFlags) != requiredFlags) {
- ALOGV("%s: false [missing required flags 0x%" PRIx64 "]", __func__,
- (s.what | requiredFlags) & ~s.what);
- return false;
- }
-
- if (s.what & deniedFlags) {
- ALOGV("%s: false [has denied flags 0x%" PRIx64 "]", __func__, s.what & deniedFlags);
- return false;
- }
-
- if (s.what & allowedFlags) {
- ALOGV("%s: [has allowed flags 0x%" PRIx64 "]", __func__, s.what & allowedFlags);
- }
-
- if (s.what & layer_state_t::ePositionChanged) {
- if (mRequestedTransform.tx() != s.x || mRequestedTransform.ty() != s.y) {
- ALOGV("%s: false [ePositionChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eAlphaChanged) {
- if (mDrawingState.color.a != s.alpha) {
- ALOGV("%s: false [eAlphaChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eColorTransformChanged) {
- if (mDrawingState.colorTransform != s.colorTransform) {
- ALOGV("%s: false [eColorTransformChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eBackgroundColorChanged) {
- if (mDrawingState.bgColorLayer || s.bgColorAlpha != 0) {
- ALOGV("%s: false [eBackgroundColorChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eMatrixChanged) {
- if (mRequestedTransform.dsdx() != s.matrix.dsdx ||
- mRequestedTransform.dtdy() != s.matrix.dtdy ||
- mRequestedTransform.dtdx() != s.matrix.dtdx ||
- mRequestedTransform.dsdy() != s.matrix.dsdy) {
- ALOGV("%s: false [eMatrixChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eCornerRadiusChanged) {
- if (mDrawingState.cornerRadius != s.cornerRadius) {
- ALOGV("%s: false [eCornerRadiusChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eBackgroundBlurRadiusChanged) {
- if (mDrawingState.backgroundBlurRadius != static_cast<int>(s.backgroundBlurRadius)) {
- ALOGV("%s: false [eBackgroundBlurRadiusChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eTransformChanged) {
- if (mDrawingState.bufferTransform != s.transform) {
- ALOGV("%s: false [eTransformChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eTransformToDisplayInverseChanged) {
- if (mDrawingState.transformToDisplayInverse != s.transformToDisplayInverse) {
- ALOGV("%s: false [eTransformToDisplayInverseChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eCropChanged) {
- if (mDrawingState.crop != s.crop) {
- ALOGV("%s: false [eCropChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eDataspaceChanged) {
- if (mDrawingState.dataspace != s.dataspace) {
- ALOGV("%s: false [eDataspaceChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eHdrMetadataChanged) {
- if (mDrawingState.hdrMetadata != s.hdrMetadata) {
- ALOGV("%s: false [eHdrMetadataChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eSidebandStreamChanged) {
- if (mDrawingState.sidebandStream != s.sidebandStream) {
- ALOGV("%s: false [eSidebandStreamChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eColorSpaceAgnosticChanged) {
- if (mDrawingState.colorSpaceAgnostic != s.colorSpaceAgnostic) {
- ALOGV("%s: false [eColorSpaceAgnosticChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eShadowRadiusChanged) {
- if (mDrawingState.shadowRadius != s.shadowRadius) {
- ALOGV("%s: false [eShadowRadiusChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eFixedTransformHintChanged) {
- if (mDrawingState.fixedTransformHint != s.fixedTransformHint) {
- ALOGV("%s: false [eFixedTransformHintChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eTrustedOverlayChanged) {
- if (mDrawingState.isTrustedOverlay != s.isTrustedOverlay) {
- ALOGV("%s: false [eTrustedOverlayChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eStretchChanged) {
- StretchEffect temp = s.stretchEffect;
- temp.sanitize();
- if (mDrawingState.stretchEffect != temp) {
- ALOGV("%s: false [eStretchChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eBufferCropChanged) {
- if (mDrawingState.bufferCrop != s.bufferCrop) {
- ALOGV("%s: false [eBufferCropChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eDestinationFrameChanged) {
- if (mDrawingState.destinationFrame != s.destinationFrame) {
- ALOGV("%s: false [eDestinationFrameChanged changed]", __func__);
- return false;
- }
- }
-
- if (s.what & layer_state_t::eDimmingEnabledChanged) {
- if (mDrawingState.dimmingEnabled != s.dimmingEnabled) {
- ALOGV("%s: false [eDimmingEnabledChanged changed]", __func__);
- return false;
- }
- }
-
- ALOGV("%s: true", __func__);
- return true;
-}
-
-} // namespace android