diff options
Diffstat (limited to 'services/surfaceflinger/BufferStateLayer.cpp')
-rw-r--r-- | services/surfaceflinger/BufferStateLayer.cpp | 765 |
1 files changed, 265 insertions, 500 deletions
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 8bc51dfa5d..790f2ece77 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -17,7 +17,6 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wextra" //#define LOG_NDEBUG 0 #undef LOG_TAG @@ -28,37 +27,29 @@ #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" 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 transformHint, - uint32_t currentMaxAcquiredBufferCount) { - if (!listener) { - return; - } - listener->onReleaseBuffer({buffer->getId(), framenumber}, - releaseFence ? releaseFence : Fence::NO_FENCE, transformHint, - currentMaxAcquiredBufferCount); -} -} // namespace +// clang-format off +const std::array<float, 16> BufferStateLayer::IDENTITY_MATRIX{ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 +}; +// clang-format on BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args), mHwcSlotGenerator(new HwcSlotGenerator()) { - mDrawingState.dataspace = ui::Dataspace::V0_SRGB; + mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; + mCurrentState.dataspace = ui::Dataspace::V0_SRGB; } BufferStateLayer::~BufferStateLayer() { @@ -67,79 +58,18 @@ BufferStateLayer::~BufferStateLayer() { // 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 && !isClone()) { - callReleaseBufferCallback(mDrawingState.releaseBufferListener, - mBufferInfo.mBuffer->getBuffer(), mBufferInfo.mFrameNumber, - mBufferInfo.mFence, mTransformHint, - mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate( - mOwnerUid)); + // Ensure that mBuffer is uncached from RenderEngine here, as + // RenderEngine may have been using the buffer as an external texture + // after the client uncached the buffer. + auto& engine(mFlinger->getRenderEngine()); + engine.unbindExternalTextureBuffer(mBufferInfo.mBuffer->getId()); } } -status_t BufferStateLayer::addReleaseFence(const sp<CallbackHandle>& ch, - const sp<Fence>& fence) { - if (ch == nullptr) { - return OK; - } - ch->previousReleaseCallbackId = mPreviousReleaseCallbackId; - if (!ch->previousReleaseFence.get()) { - ch->previousReleaseFence = fence; - return OK; - } - - // Below logic is lifted from ConsumerBase.cpp: - // Check status of fences first because merging is expensive. - // Merging an invalid fence with any other fence results in an - // invalid fence. - auto currentStatus = ch->previousReleaseFence->getStatus(); - if (currentStatus == Fence::Status::Invalid) { - ALOGE("Existing fence has invalid state, layer: %s", mName.c_str()); - return BAD_VALUE; - } - - auto incomingStatus = fence->getStatus(); - if (incomingStatus == Fence::Status::Invalid) { - ALOGE("New fence has invalid state, layer: %s", mName.c_str()); - ch->previousReleaseFence = fence; - return BAD_VALUE; - } - - // If both fences are signaled or both are unsignaled, we need to merge - // them to get an accurate timestamp. - if (currentStatus == incomingStatus) { - char fenceName[32] = {}; - snprintf(fenceName, 32, "%.28s", mName.c_str()); - sp<Fence> mergedFence = Fence::merge( - fenceName, ch->previousReleaseFence, fence); - if (!mergedFence.get()) { - ALOGE("failed to merge release fences, layer: %s", mName.c_str()); - // synchronization is broken, the best we can do is hope fences - // signal in order so the new fence will act like a union - ch->previousReleaseFence = fence; - return BAD_VALUE; - } - ch->previousReleaseFence = mergedFence; - } else if (incomingStatus == Fence::Status::Unsignaled) { - // If one fence has signaled and the other hasn't, the unsignaled - // fence will approximately correspond with the correct timestamp. - // There's a small race if both fences signal at about the same time - // and their statuses are retrieved with unfortunate timing. However, - // by this point, they will have both signaled and only the timestamp - // will be slightly off; any dependencies after this point will - // already have been met. - ch->previousReleaseFence = fence; - } - // else if (currentStatus == Fence::Status::Unsignaled) is a no-op. - - return OK; -} - // ----------------------------------------------------------------------- // Interface implementation for Layer // ----------------------------------------------------------------------- void BufferStateLayer::onLayerDisplayed(const sp<Fence>& releaseFence) { - if (!releaseFence->isValid()) { - return; - } // 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 @@ -156,17 +86,12 @@ void BufferStateLayer::onLayerDisplayed(const sp<Fence>& releaseFence) { // 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) { - ch = handle; + handle->previousReleaseFence = releaseFence; break; } } - auto status = addReleaseFence(ch, releaseFence); - if (status != OK) { - ALOGE("Failed to add release fence for layer %s", getName().c_str()); - } mPreviousReleaseFence = releaseFence; @@ -176,55 +101,14 @@ void BufferStateLayer::onLayerDisplayed(const sp<Fence>& releaseFence) { } } -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); - } - - // If there are multiple transactions in this frame, set the previous id on the earliest - // transacton. We don't need to pass in the released buffer id to multiple transactions. - // The buffer id does not have to correspond to any particular transaction as long as the - // listening end point is the same but the client expects the first transaction callback that - // replaces the presented buffer to contain the release fence. This follows the same logic. - // see BufferStateLayer::onLayerDisplayed. - for (auto& handle : mDrawingState.callbackHandles) { - if (handle->releasePreviousBuffer) { - 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().finalizePendingCallbackHandles( - mDrawingState.callbackHandles, jankData); + mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles( + mDrawingState.callbackHandles); mDrawingState.callbackHandles = {}; @@ -247,158 +131,115 @@ void BufferStateLayer::finalizeFrameEventHistory(const std::shared_ptr<FenceTime } } +bool BufferStateLayer::shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { + if (getSidebandStreamChanged() || getAutoRefresh()) { + return true; + } + + return hasFrameUpdate(); +} + 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))); + (mCurrentState.modified && + (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr))) && + !mLayerDetached; } -Rect BufferStateLayer::getCrop(const Layer::State& s) const { - return s.crop; +/* TODO: vhau uncomment once deferred transaction migration complete in + * WindowManager +void BufferStateLayer::pushPendingState() { + if (!mCurrentState.modified) { + return; + } + mPendingStates.push_back(mCurrentState); + ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); } +*/ -bool BufferStateLayer::setTransform(uint32_t transform) { - if (mDrawingState.bufferTransform == transform) return false; - mDrawingState.bufferTransform = transform; - mDrawingState.modified = true; - setTransactionFlags(eTransactionNeeded); - return true; +bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) { + mCurrentStateModified = mCurrentState.modified; + bool stateUpdateAvailable = Layer::applyPendingStates(stateToCommit); + mCurrentStateModified = stateUpdateAvailable && mCurrentStateModified; + mCurrentState.modified = false; + return stateUpdateAvailable; } -bool BufferStateLayer::setTransformToDisplayInverse(bool transformToDisplayInverse) { - if (mDrawingState.transformToDisplayInverse == transformToDisplayInverse) return false; - mDrawingState.sequence++; - mDrawingState.transformToDisplayInverse = transformToDisplayInverse; - mDrawingState.modified = true; - setTransactionFlags(eTransactionNeeded); - return true; +// Crop that applies to the window +Rect BufferStateLayer::getCrop(const Layer::State& /*s*/) const { + return Rect::INVALID_RECT; } -bool BufferStateLayer::setCrop(const Rect& crop) { - if (mDrawingState.crop == crop) return false; - mDrawingState.sequence++; - mDrawingState.crop = crop; - - mDrawingState.modified = true; +bool BufferStateLayer::setTransform(uint32_t transform) { + if (mCurrentState.transform == transform) return false; + mCurrentState.transform = transform; + mCurrentState.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; +bool BufferStateLayer::setTransformToDisplayInverse(bool transformToDisplayInverse) { + if (mCurrentState.transformToDisplayInverse == transformToDisplayInverse) return false; + mCurrentState.sequence++; + mCurrentState.transformToDisplayInverse = transformToDisplayInverse; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } -bool BufferStateLayer::setDestinationFrame(const Rect& destinationFrame) { - if (mDrawingState.destinationFrame == destinationFrame) return false; - - mDrawingState.sequence++; - mDrawingState.destinationFrame = destinationFrame; +bool BufferStateLayer::setCrop(const Rect& crop) { + Rect c = crop; + if (c.left < 0) { + c.left = 0; + } + if (c.top < 0) { + c.top = 0; + } + // If the width and/or height are < 0, make it [0, 0, -1, -1] so the equality comparision below + // treats all invalid rectangles the same. + if (!c.isValid()) { + c.makeInvalid(); + } - mDrawingState.modified = true; + if (mCurrentState.crop == c) return false; + mCurrentState.crop = c; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } -static bool assignTransform(ui::Transform* dst, ui::Transform& from) { - if (*dst == from) { - return false; - } - *dst = from; - return true; -} +bool BufferStateLayer::setFrame(const Rect& frame) { + int x = frame.left; + int y = frame.top; + int w = frame.getWidth(); + int h = frame.getHeight(); -// 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.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 (x < 0) { + x = 0; + w = frame.right; } - if (!mDrawingState.buffer) { - ui::Transform t; - t.set(destRect.left, destRect.top); - return assignTransform(&mDrawingState.transform, t); + if (y < 0) { + y = 0; + h = frame.bottom; } - uint32_t bufferWidth = mDrawingState.buffer->getBuffer()->getWidth(); - uint32_t bufferHeight = mDrawingState.buffer->getBuffer()->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, - bool allowNonRectPreservingTransforms) { - if (mRequestedTransform.dsdx() == matrix.dsdx && mRequestedTransform.dtdy() == matrix.dtdy && - mRequestedTransform.dtdx() == matrix.dtdx && mRequestedTransform.dsdy() == matrix.dsdy) { + if (mCurrentState.active.transform.tx() == x && mCurrentState.active.transform.ty() == y && + mCurrentState.active.w == w && mCurrentState.active.h == h) { return false; } - ui::Transform t; - t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); - - if (!allowNonRectPreservingTransforms && !t.preserveRects()) { - ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER nor " - "ROTATE_SURFACE_FLINGER ignored"); - return false; - } - - 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; + if (!frame.isValid()) { + x = y = w = h = 0; } + mCurrentState.active.transform.set(x, y); + mCurrentState.active.w = w; + mCurrentState.active.h = h; - mRequestedTransform.set(x, y); - - mDrawingState.sequence++; - mDrawingState.modified = true; + mCurrentState.sequence++; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); - return true; } @@ -408,142 +249,87 @@ bool BufferStateLayer::addFrameEvent(const sp<Fence>& acquireFence, nsecs_t post mAcquireTimeline.updateSignalTimes(); std::shared_ptr<FenceTime> acquireFenceTime = std::make_shared<FenceTime>((acquireFence ? acquireFence : Fence::NO_FENCE)); - NewFrameEventsEntry newTimestamps = {mDrawingState.frameNumber, postedTime, desiredPresentTime, + NewFrameEventsEntry newTimestamps = {mCurrentState.frameNumber, postedTime, desiredPresentTime, acquireFenceTime}; mFrameEventHistory.setProducerWantsEvents(); mFrameEventHistory.addQueue(newTimestamps); return true; } -bool BufferStateLayer::setBuffer(const std::shared_ptr<renderengine::ExternalTexture>& buffer, - const sp<Fence>& acquireFence, nsecs_t postTime, - nsecs_t desiredPresentTime, bool isAutoTimestamp, - const client_cache_t& clientCacheId, uint64_t frameNumber, - std::optional<nsecs_t> dequeueTime, const FrameTimelineInfo& info, - const sp<ITransactionCompletedListener>& releaseBufferListener) { - ATRACE_CALL(); - - if (mDrawingState.buffer) { +bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence>& acquireFence, + nsecs_t postTime, nsecs_t desiredPresentTime, + const client_cache_t& clientCacheId) { + if (mCurrentState.buffer) { mReleasePreviousBuffer = true; - if (mDrawingState.buffer != 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, mTransformHint, - mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate( - mOwnerUid)); - decrementPendingBufferCount(); - if (mDrawingState.bufferSurfaceFrameTX != nullptr && - mDrawingState.bufferSurfaceFrameTX->getPresentState() != PresentState::Presented) { - addSurfaceFrameDroppedForBuffer(mDrawingState.bufferSurfaceFrameTX); - mDrawingState.bufferSurfaceFrameTX.reset(); - } - } } - mDrawingState.frameNumber = frameNumber; - mDrawingState.releaseBufferListener = releaseBufferListener; - mDrawingState.buffer = buffer; - mDrawingState.clientCacheId = clientCacheId; - mDrawingState.modified = true; + mCurrentState.frameNumber++; + + mCurrentState.buffer = buffer; + mCurrentState.clientCacheId = clientCacheId; + mCurrentState.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; + mFlinger->mTimeStats->setPostTime(layerId, mCurrentState.frameNumber, getName().c_str(), + postTime); + desiredPresentTime = desiredPresentTime <= 0 ? 0 : desiredPresentTime; + mCurrentState.desiredPresentTime = desiredPresentTime; - const auto prediction = - mFlinger->mFrameTimeline->getTokenManager()->getPredictionsForToken(info.vsyncId); - if (prediction.has_value()) return prediction->presentTime; - - return static_cast<nsecs_t>(0); - }(); - mFlinger->mScheduler->recordLayerHistory(this, presentTime, + mFlinger->mScheduler->recordLayerHistory(this, desiredPresentTime, LayerHistory::LayerUpdateType::Buffer); - addFrameEvent(acquireFence, postTime, isAutoTimestamp ? 0 : desiredPresentTime); - - setFrameTimelineVsyncForBufferTransaction(info, postTime); - - if (buffer && dequeueTime && *dequeueTime != 0) { - const uint64_t bufferId = buffer->getBuffer()->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->getBuffer()->getWidth(); - mDrawingState.height = mDrawingState.buffer->getBuffer()->getHeight(); - + addFrameEvent(acquireFence, postTime, desiredPresentTime); return true; } bool BufferStateLayer::setAcquireFence(const sp<Fence>& fence) { - mDrawingState.acquireFence = fence; - mDrawingState.acquireFenceTime = std::make_unique<FenceTime>(fence); - // The acquire fences of BufferStateLayers have already signaled before they are set - mCallbackHandleAcquireTime = mDrawingState.acquireFenceTime->getSignalTime(); + mCallbackHandleAcquireTime = fence->getSignalTime(); - mDrawingState.modified = true; + mCurrentState.acquireFence = fence; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool BufferStateLayer::setDataspace(ui::Dataspace dataspace) { - if (mDrawingState.dataspace == dataspace) return false; - mDrawingState.dataspace = dataspace; - mDrawingState.modified = true; + if (mCurrentState.dataspace == dataspace) return false; + mCurrentState.dataspace = dataspace; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool BufferStateLayer::setHdrMetadata(const HdrMetadata& hdrMetadata) { - if (mDrawingState.hdrMetadata == hdrMetadata) return false; - mDrawingState.hdrMetadata = hdrMetadata; - mDrawingState.modified = true; + if (mCurrentState.hdrMetadata == hdrMetadata) return false; + mCurrentState.hdrMetadata = hdrMetadata; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool BufferStateLayer::setSurfaceDamageRegion(const Region& surfaceDamage) { - mDrawingState.surfaceDamageRegion = surfaceDamage; - mDrawingState.modified = true; + mCurrentState.surfaceDamageRegion = surfaceDamage; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool BufferStateLayer::setApi(int32_t api) { - if (mDrawingState.api == api) return false; - mDrawingState.api = api; - mDrawingState.modified = true; + if (mCurrentState.api == api) return false; + mCurrentState.api = api; + mCurrentState.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; + if (mCurrentState.sidebandStream == sidebandStream) return false; + mCurrentState.sidebandStream = sidebandStream; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); + if (!mSidebandStreamChanged.exchange(true)) { // mSidebandStreamChanged was false mFlinger->signalLayerUpdate(); @@ -569,18 +355,17 @@ bool BufferStateLayer::setTransactionCompletedListeners( if (willPresent) { // If this transaction set an acquire fence on this layer, set its acquire time handle->acquireTime = mCallbackHandleAcquireTime; - handle->frameNumber = mDrawingState.frameNumber; // Notify the transaction completed thread that there is a pending latched callback // handle - mFlinger->getTransactionCallbackInvoker().registerPendingCallbackHandle(handle); + mFlinger->getTransactionCompletedThread().registerPendingCallbackHandle(handle); // Store so latched time and release fence can be set - mDrawingState.callbackHandles.push_back(handle); + mCurrentState.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); + mFlinger->getTransactionCompletedThread().registerUnpresentedCallbackHandle(handle); } } @@ -590,45 +375,45 @@ bool BufferStateLayer::setTransactionCompletedListeners( return willPresent; } +void BufferStateLayer::forceSendCallbacks() { + mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles( + mCurrentState.callbackHandles); +} + bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) { - mDrawingState.sequence++; - mDrawingState.transparentRegionHint = transparent; - mDrawingState.modified = true; + mCurrentState.transparentRegionHint = transparent; + mCurrentState.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->getBuffer()->getWidth(); - uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->getHeight(); - - // Undo any transformations on the buffer and return the result. - if (mBufferInfo.mTransform & ui::Transform::ROT_90) { - std::swap(bufWidth, bufHeight); + if (getActiveWidth(s) < UINT32_MAX && getActiveHeight(s) < UINT32_MAX) { + return Rect(getActiveWidth(s), getActiveHeight(s)); } - if (getTransformToDisplayInverse()) { - uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags(); - if (invTransform & ui::Transform::ROT_90) { - std::swap(bufWidth, bufHeight); + // if the display frame is not defined, use the parent bounds as the buffer size. + const auto& p = mDrawingParent.promote(); + if (p != nullptr) { + Rect parentBounds = Rect(p->getBounds(Region())); + if (!parentBounds.isEmpty()) { + return parentBounds; } } - return Rect(0, 0, bufWidth, bufHeight); + return Rect::INVALID_RECT; } FloatRect BufferStateLayer::computeSourceBounds(const FloatRect& parentBounds) const { - if (mBufferInfo.mBuffer == nullptr) { - return parentBounds; + const State& s(getDrawingState()); + // for buffer state layers we use the display frame size as the buffer size. + if (getActiveWidth(s) < UINT32_MAX && getActiveHeight(s) < UINT32_MAX) { + return FloatRect(0, 0, getActiveWidth(s), getActiveHeight(s)); } - return getBufferSize(getDrawingState()).toFloatRect(); + // if the display frame is not defined, use the parent bounds as the buffer size. + return parentBounds; } // ----------------------------------------------------------------------- @@ -637,7 +422,7 @@ FloatRect BufferStateLayer::computeSourceBounds(const FloatRect& parentBounds) c // Interface implementation for BufferLayer // ----------------------------------------------------------------------- bool BufferStateLayer::fenceHasSignaled() const { - if (SurfaceFlinger::enableLatchUnsignaled) { + if (latchUnsignaledBuffers()) { return true; } @@ -656,7 +441,7 @@ bool BufferStateLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) co return true; } - return mDrawingState.isAutoTimestamp || mDrawingState.desiredPresentTime <= expectedPresentTime; + return mCurrentState.desiredPresentTime <= expectedPresentTime; } bool BufferStateLayer::onPreComposition(nsecs_t refreshStartTime) { @@ -683,9 +468,9 @@ uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const * DeferTransactionUntil -> frameNumber = 2 * Random other stuff * } - * Now imagine mFrameNumber returned mDrawingState.frameNumber (or mCurrentFrameNumber). + * Now imagine getHeadFrameNumber returned mDrawingState.mFrameNumber (or mCurrentFrameNumber). * Prior to doTransaction SurfaceFlinger will call notifyAvailableFrames, but because we - * haven't swapped mDrawingState to mDrawingState yet we will think the sync point + * haven't swapped mCurrentState to mDrawingState yet we will think the sync point * is not ready. So we will return false from applyPendingState and not swap * current state to drawing state. But because we don't swap current state * to drawing state the number will never update and we will be stuck. This way @@ -693,20 +478,20 @@ uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const * to apply. */ uint64_t BufferStateLayer::getHeadFrameNumber(nsecs_t /* expectedPresentTime */) const { - return mDrawingState.frameNumber; + return mCurrentState.frameNumber; } -void BufferStateLayer::setAutoRefresh(bool autoRefresh) { - if (!mAutoRefresh.exchange(autoRefresh)) { - mFlinger->signalLayerUpdate(); - } +bool BufferStateLayer::getAutoRefresh() const { + // TODO(marissaw): support shared buffer mode + return false; } -bool BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) { - // We need to update the sideband stream if the layer has both a buffer and a sideband stream. - const bool updateSidebandStream = hasFrameUpdate() && mSidebandStream.get(); +bool BufferStateLayer::getSidebandStreamChanged() const { + return mSidebandStreamChanged.load(); +} - if (mSidebandStreamChanged.exchange(false) || updateSidebandStream) { +bool BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) { + if (mSidebandStreamChanged.exchange(false)) { const State& s(getDrawingState()); // mSidebandStreamChanged was true mSidebandStream = s.sidebandStream; @@ -723,8 +508,15 @@ bool BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) { } bool BufferStateLayer::hasFrameUpdate() const { - const State& c(getDrawingState()); - return (mDrawingStateModified || mDrawingState.modified) && (c.buffer != nullptr || c.bgColorLayer != nullptr); + const State& c(getCurrentState()); + return mCurrentStateModified && (c.buffer != nullptr || c.bgColorLayer != nullptr); +} + +status_t BufferStateLayer::bindTextureImage() { + const State& s(getDrawingState()); + auto& engine(mFlinger->getRenderEngine()); + + return engine.bindExternalTextureBuffer(mTextureName, s.buffer, s.acquireFence); } status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime, @@ -740,42 +532,56 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse return NO_ERROR; } + const int32_t layerId = getSequence(); + + // Reject if the layer is invalid + uint32_t bufferWidth = s.buffer->width; + uint32_t bufferHeight = s.buffer->height; + + if (s.transform & 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); + } + } + + if (getEffectiveScalingMode() == NATIVE_WINDOW_SCALING_MODE_FREEZE && + (s.active.w != bufferWidth || s.active.h != bufferHeight)) { + ALOGE("[%s] rejecting buffer: " + "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}", + getDebugName(), bufferWidth, bufferHeight, s.active.w, s.active.h); + mFlinger->mTimeStats->removeTimeRecord(layerId, mDrawingState.frameNumber); + return BAD_VALUE; + } + for (auto& handle : mDrawingState.callbackHandles) { - if (handle->frameNumber == mDrawingState.frameNumber) { - handle->latchTime = latchTime; + handle->latchTime = latchTime; + handle->frameNumber = mDrawingState.frameNumber; + } + + if (!SyncFeatures::getInstance().useNativeFenceSync()) { + // Bind the new buffer to the GL texture. + // + // Older devices require the "implicit" synchronization provided + // by glEGLImageTargetTexture2DOES, which this method calls. Newer + // devices will either call this in Layer::onDraw, or (if it's not + // a GL-composited layer) not at all. + status_t err = bindTextureImage(); + if (err != NO_ERROR) { + mFlinger->mTimeStats->onDestroy(layerId); + return BAD_VALUE; } } - const int32_t layerId = getSequence(); - const uint64_t bufferId = mDrawingState.buffer->getBuffer()->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() - .finalizeOnCommitCallbackHandles(mDrawingState.callbackHandles, remainingHandles); - mDrawingState.callbackHandles = remainingHandles; - - mDrawingStateModified = false; + mFlinger->mTimeStats->setAcquireFence(layerId, mDrawingState.frameNumber, + std::make_shared<FenceTime>(mDrawingState.acquireFence)); + mFlinger->mTimeStats->setLatchTime(layerId, mDrawingState.frameNumber, latchTime); + + mCurrentStateModified = false; return NO_ERROR; } @@ -787,14 +593,9 @@ status_t BufferStateLayer::updateActiveBuffer() { return BAD_VALUE; } - if (!mBufferInfo.mBuffer || s.buffer->getBuffer() != mBufferInfo.mBuffer->getBuffer()) { - decrementPendingBufferCount(); - } - - mPreviousReleaseCallbackId = {getCurrentBufferId(), mBufferInfo.mFrameNumber}; + mPreviousBufferId = getCurrentBufferId(); mBufferInfo.mBuffer = s.buffer; mBufferInfo.mFence = s.acquireFence; - mBufferInfo.mFrameNumber = s.frameNumber; return NO_ERROR; } @@ -890,13 +691,9 @@ void BufferStateLayer::gatherBufferInfo() { 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.mTransform = s.transform; mBufferInfo.mDataspace = translateDataspace(s.dataspace); - if (lastDataspace != mBufferInfo.mDataspace) { - mFlinger->mSomeDataspaceChanged = true; - } - mBufferInfo.mCrop = computeBufferCrop(s); + mBufferInfo.mCrop = computeCrop(s); mBufferInfo.mScaleMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; mBufferInfo.mSurfaceDamage = s.surfaceDamageRegion; mBufferInfo.mHdrMetadata = s.hdrMetadata; @@ -905,20 +702,27 @@ void BufferStateLayer::gatherBufferInfo() { 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->getBuffer()->getBounds().intersect(s.bufferCrop, &bufferCrop); - return bufferCrop; +Rect BufferStateLayer::computeCrop(const State& s) { + if (s.crop.isEmpty() && s.buffer) { + return s.buffer->getBounds(); } else if (s.buffer) { - return s.buffer->getBuffer()->getBounds(); - } else { - return s.bufferCrop; + Rect crop = s.crop; + crop.left = std::max(crop.left, 0); + crop.top = std::max(crop.top, 0); + uint32_t bufferWidth = s.buffer->getWidth(); + uint32_t bufferHeight = s.buffer->getHeight(); + if (bufferHeight <= std::numeric_limits<int32_t>::max() && + bufferWidth <= std::numeric_limits<int32_t>::max()) { + crop.right = std::min(crop.right, static_cast<int32_t>(bufferWidth)); + crop.bottom = std::min(crop.bottom, static_cast<int32_t>(bufferHeight)); + } + if (!crop.isValid()) { + // Crop rect is out of bounds, return whole buffer + return s.buffer->getBounds(); + } + return crop; } + return s.crop; } sp<Layer> BufferStateLayer::createClone() { @@ -930,72 +734,33 @@ sp<Layer> BufferStateLayer::createClone() { return layer; } -bool BufferStateLayer::bufferNeedsFiltering() const { - const State& s(getDrawingState()); - if (!s.buffer) { - return false; - } - - uint32_t bufferWidth = s.buffer->getBuffer()->width; - uint32_t bufferHeight = s.buffer->getBuffer()->height; - - // 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); +Layer::RoundedCornerState BufferStateLayer::getRoundedCornerState() const { + const auto& p = mDrawingParent.promote(); + if (p != nullptr) { + RoundedCornerState parentState = p->getRoundedCornerState(); + if (parentState.radius > 0) { + ui::Transform t = getActiveTransform(getDrawingState()); + t = t.inverse(); + parentState.cropRect = t.transform(parentState.cropRect); + // The rounded corners shader only accepts 1 corner radius for performance reasons, + // but a transform matrix can define horizontal and vertical scales. + // Let's take the average between both of them and pass into the shader, practically we + // never do this type of transformation on windows anyway. + parentState.radius *= (t[0][0] + t[1][1]) / 2.0f; + return parentState; } } - - 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); + const float radius = getDrawingState().cornerRadius; + const State& s(getDrawingState()); + if (radius <= 0 || (getActiveWidth(s) == UINT32_MAX && getActiveHeight(s) == UINT32_MAX)) + return RoundedCornerState(); + return RoundedCornerState(FloatRect(static_cast<float>(s.active.transform.tx()), + static_cast<float>(s.active.transform.ty()), + static_cast<float>(s.active.transform.tx() + s.active.w), + static_cast<float>(s.active.transform.ty() + s.active.h)), + radius); } - } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" +#pragma clang diagnostic pop // ignored "-Wconversion" |