diff options
Diffstat (limited to 'services/surfaceflinger/BufferStateLayer.cpp')
| -rw-r--r-- | services/surfaceflinger/BufferStateLayer.cpp | 697 | 
1 files changed, 433 insertions, 264 deletions
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index d94347a237..8bc51dfa5d 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -17,6 +17,7 @@  // 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 @@ -27,29 +28,37 @@  #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 { -// 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 +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  BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args)        : BufferLayer(args), mHwcSlotGenerator(new HwcSlotGenerator()) { -    mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; -    mCurrentState.dataspace = ui::Dataspace::V0_SRGB; +    mDrawingState.dataspace = ui::Dataspace::V0_SRGB;  }  BufferStateLayer::~BufferStateLayer() { @@ -58,11 +67,11 @@ 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()) { -        // 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()); +        callReleaseBufferCallback(mDrawingState.releaseBufferListener, +                                  mBufferInfo.mBuffer->getBuffer(), mBufferInfo.mFrameNumber, +                                  mBufferInfo.mFence, mTransformHint, +                                  mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate( +                                          mOwnerUid));      }  } @@ -71,6 +80,7 @@ status_t BufferStateLayer::addReleaseFence(const sp<CallbackHandle>& ch,      if (ch == nullptr) {          return OK;      } +    ch->previousReleaseCallbackId = mPreviousReleaseCallbackId;      if (!ch->previousReleaseFence.get()) {          ch->previousReleaseFence = fence;          return OK; @@ -166,14 +176,55 @@ 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);      } -    mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles( -            mDrawingState.callbackHandles); +    // 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);      mDrawingState.callbackHandles = {}; @@ -196,115 +247,158 @@ 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() || -            (mCurrentState.modified && -             (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr))) && -        !mLayerDetached; +            (mDrawingState.modified && +             (mDrawingState.buffer != nullptr || mDrawingState.bgColorLayer != nullptr)));  } -/* 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()); +Rect BufferStateLayer::getCrop(const Layer::State& s) const { +    return s.crop;  } -*/ -bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) { -    mCurrentStateModified = mCurrentState.modified; -    bool stateUpdateAvailable = Layer::applyPendingStates(stateToCommit); -    mCurrentStateModified = stateUpdateAvailable && mCurrentStateModified; -    mCurrentState.modified = false; -    return stateUpdateAvailable; +bool BufferStateLayer::setTransform(uint32_t transform) { +    if (mDrawingState.bufferTransform == transform) return false; +    mDrawingState.bufferTransform = transform; +    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::setTransformToDisplayInverse(bool transformToDisplayInverse) { +    if (mDrawingState.transformToDisplayInverse == transformToDisplayInverse) return false; +    mDrawingState.sequence++; +    mDrawingState.transformToDisplayInverse = transformToDisplayInverse; +    mDrawingState.modified = true; +    setTransactionFlags(eTransactionNeeded); +    return true;  } -bool BufferStateLayer::setTransform(uint32_t transform) { -    if (mCurrentState.transform == transform) return false; -    mCurrentState.transform = transform; -    mCurrentState.modified = 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::setTransformToDisplayInverse(bool transformToDisplayInverse) { -    if (mCurrentState.transformToDisplayInverse == transformToDisplayInverse) return false; -    mCurrentState.sequence++; -    mCurrentState.transformToDisplayInverse = transformToDisplayInverse; -    mCurrentState.modified = 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::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(); -    } +bool BufferStateLayer::setDestinationFrame(const Rect& destinationFrame) { +    if (mDrawingState.destinationFrame == destinationFrame) return false; + +    mDrawingState.sequence++; +    mDrawingState.destinationFrame = destinationFrame; -    if (mCurrentState.crop == c) return false; -    mCurrentState.crop = c; -    mCurrentState.modified = true; +    mDrawingState.modified = true;      setTransactionFlags(eTransactionNeeded);      return true;  } -bool BufferStateLayer::setFrame(const Rect& frame) { -    int x = frame.left; -    int y = frame.top; -    int w = frame.getWidth(); -    int h = frame.getHeight(); +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.destinationFrame.isEmpty()) { +        // If destination frame is not set, use the requested transform set via +        // BufferStateLayer::setPosition and BufferStateLayer::setMatrix. +        return assignTransform(&mDrawingState.transform, mRequestedTransform); +    } -    if (x < 0) { -        x = 0; -        w = frame.right; +    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 (y < 0) { -        y = 0; -        h = frame.bottom; +    if (!mDrawingState.buffer) { +        ui::Transform t; +        t.set(destRect.left, destRect.top); +        return assignTransform(&mDrawingState.transform, t);      } -    if (mCurrentState.active.transform.tx() == x && mCurrentState.active.transform.ty() == y && -        mCurrentState.active.w == w && mCurrentState.active.h == h) { +    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) {          return false;      } -    if (!frame.isValid()) { -        x = y = w = h = 0; +    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;      } -    mCurrentState.active.transform.set(x, y); -    mCurrentState.active.w = w; -    mCurrentState.active.h = h; -    mCurrentState.sequence++; -    mCurrentState.modified = true; +    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;  } @@ -314,87 +408,142 @@ 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 = {mCurrentState.frameNumber, postedTime, desiredPresentTime, +    NewFrameEventsEntry newTimestamps = {mDrawingState.frameNumber, postedTime, desiredPresentTime,                                           acquireFenceTime};      mFrameEventHistory.setProducerWantsEvents();      mFrameEventHistory.addQueue(newTimestamps);      return true;  } -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) { +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) {          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(); +            } +        }      } -    mCurrentState.frameNumber++; - -    mCurrentState.buffer = buffer; -    mCurrentState.clientCacheId = clientCacheId; -    mCurrentState.modified = true; +    mDrawingState.frameNumber = frameNumber; +    mDrawingState.releaseBufferListener = releaseBufferListener; +    mDrawingState.buffer = buffer; +    mDrawingState.clientCacheId = clientCacheId; +    mDrawingState.modified = true;      setTransactionFlags(eTransactionNeeded);      const int32_t layerId = getSequence(); -    mFlinger->mTimeStats->setPostTime(layerId, mCurrentState.frameNumber, getName().c_str(), -                                      postTime); -    desiredPresentTime = desiredPresentTime <= 0 ? 0 : desiredPresentTime; -    mCurrentState.desiredPresentTime = desiredPresentTime; +    mFlinger->mTimeStats->setPostTime(layerId, mDrawingState.frameNumber, getName().c_str(), +                                      mOwnerUid, postTime, getGameMode()); +    mDrawingState.desiredPresentTime = desiredPresentTime; +    mDrawingState.isAutoTimestamp = isAutoTimestamp; -    mFlinger->mScheduler->recordLayerHistory(this, desiredPresentTime, +    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); +    }(); +    mFlinger->mScheduler->recordLayerHistory(this, presentTime,                                               LayerHistory::LayerUpdateType::Buffer); -    addFrameEvent(acquireFence, postTime, desiredPresentTime); +    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(); +      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 = fence->getSignalTime(); +    mCallbackHandleAcquireTime = mDrawingState.acquireFenceTime->getSignalTime(); -    mCurrentState.acquireFence = fence; -    mCurrentState.modified = true; +    mDrawingState.modified = true;      setTransactionFlags(eTransactionNeeded);      return true;  }  bool BufferStateLayer::setDataspace(ui::Dataspace dataspace) { -    if (mCurrentState.dataspace == dataspace) return false; -    mCurrentState.dataspace = dataspace; -    mCurrentState.modified = true; +    if (mDrawingState.dataspace == dataspace) return false; +    mDrawingState.dataspace = dataspace; +    mDrawingState.modified = true;      setTransactionFlags(eTransactionNeeded);      return true;  }  bool BufferStateLayer::setHdrMetadata(const HdrMetadata& hdrMetadata) { -    if (mCurrentState.hdrMetadata == hdrMetadata) return false; -    mCurrentState.hdrMetadata = hdrMetadata; -    mCurrentState.modified = true; +    if (mDrawingState.hdrMetadata == hdrMetadata) return false; +    mDrawingState.hdrMetadata = hdrMetadata; +    mDrawingState.modified = true;      setTransactionFlags(eTransactionNeeded);      return true;  }  bool BufferStateLayer::setSurfaceDamageRegion(const Region& surfaceDamage) { -    mCurrentState.surfaceDamageRegion = surfaceDamage; -    mCurrentState.modified = true; +    mDrawingState.surfaceDamageRegion = surfaceDamage; +    mDrawingState.modified = true;      setTransactionFlags(eTransactionNeeded);      return true;  }  bool BufferStateLayer::setApi(int32_t api) { -    if (mCurrentState.api == api) return false; -    mCurrentState.api = api; -    mCurrentState.modified = true; +    if (mDrawingState.api == api) return false; +    mDrawingState.api = api; +    mDrawingState.modified = true;      setTransactionFlags(eTransactionNeeded);      return true;  }  bool BufferStateLayer::setSidebandStream(const sp<NativeHandle>& sidebandStream) { -    if (mCurrentState.sidebandStream == sidebandStream) return false; -    mCurrentState.sidebandStream = sidebandStream; -    mCurrentState.modified = true; -    setTransactionFlags(eTransactionNeeded); +    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->signalLayerUpdate(); @@ -420,17 +569,18 @@ 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->getTransactionCompletedThread().registerPendingCallbackHandle(handle); +            mFlinger->getTransactionCallbackInvoker().registerPendingCallbackHandle(handle);              // Store so latched time and release fence can be set -            mCurrentState.callbackHandles.push_back(handle); +            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->getTransactionCompletedThread().registerUnpresentedCallbackHandle(handle); +            mFlinger->getTransactionCallbackInvoker().registerUnpresentedCallbackHandle(handle);          }      } @@ -440,45 +590,45 @@ bool BufferStateLayer::setTransactionCompletedListeners(      return willPresent;  } -void BufferStateLayer::forceSendCallbacks() { -    mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles( -            mCurrentState.callbackHandles); -} -  bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) { -    mCurrentState.transparentRegionHint = transparent; -    mCurrentState.modified = true; +    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 (getActiveWidth(s) < UINT32_MAX && getActiveHeight(s) < UINT32_MAX) { -        return Rect(getActiveWidth(s), getActiveHeight(s)); + +    if (mBufferInfo.mBuffer == nullptr) { +        return Rect::INVALID_RECT;      } -    // 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; +    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 (getTransformToDisplayInverse()) { +        uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags(); +        if (invTransform & ui::Transform::ROT_90) { +            std::swap(bufWidth, bufHeight);          }      } -    return Rect::INVALID_RECT; +    return Rect(0, 0, bufWidth, bufHeight);  }  FloatRect BufferStateLayer::computeSourceBounds(const FloatRect& parentBounds) const { -    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)); +    if (mBufferInfo.mBuffer == nullptr) { +        return parentBounds;      } -    // if the display frame is not defined, use the parent bounds as the buffer size. -    return parentBounds; +    return getBufferSize(getDrawingState()).toFloatRect();  }  // ----------------------------------------------------------------------- @@ -487,7 +637,7 @@ FloatRect BufferStateLayer::computeSourceBounds(const FloatRect& parentBounds) c  // Interface implementation for BufferLayer  // -----------------------------------------------------------------------  bool BufferStateLayer::fenceHasSignaled() const { -    if (latchUnsignaledBuffers()) { +    if (SurfaceFlinger::enableLatchUnsignaled) {          return true;      } @@ -506,7 +656,7 @@ bool BufferStateLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) co          return true;      } -    return mCurrentState.desiredPresentTime <= expectedPresentTime; +    return mDrawingState.isAutoTimestamp || mDrawingState.desiredPresentTime <= expectedPresentTime;  }  bool BufferStateLayer::onPreComposition(nsecs_t refreshStartTime) { @@ -533,9 +683,9 @@ uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const   *     DeferTransactionUntil -> frameNumber = 2   *     Random other stuff   *  } - * Now imagine getHeadFrameNumber returned mDrawingState.mFrameNumber (or mCurrentFrameNumber). + * Now imagine mFrameNumber returned mDrawingState.frameNumber (or mCurrentFrameNumber).   * Prior to doTransaction SurfaceFlinger will call notifyAvailableFrames, but because we - * haven't swapped mCurrentState to mDrawingState yet we will think the sync point + * haven't swapped mDrawingState 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 @@ -543,20 +693,20 @@ uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const   * to apply.   */  uint64_t BufferStateLayer::getHeadFrameNumber(nsecs_t /* expectedPresentTime */) const { -    return mCurrentState.frameNumber; -} - -bool BufferStateLayer::getAutoRefresh() const { -    // TODO(marissaw): support shared buffer mode -    return false; +    return mDrawingState.frameNumber;  } -bool BufferStateLayer::getSidebandStreamChanged() const { -    return mSidebandStreamChanged.load(); +void BufferStateLayer::setAutoRefresh(bool autoRefresh) { +    if (!mAutoRefresh.exchange(autoRefresh)) { +        mFlinger->signalLayerUpdate(); +    }  }  bool BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) { -    if (mSidebandStreamChanged.exchange(false)) { +    // We need to update the sideband stream if the layer has both a buffer and a sideband stream. +    const bool updateSidebandStream = hasFrameUpdate() && mSidebandStream.get(); + +    if (mSidebandStreamChanged.exchange(false) || updateSidebandStream) {          const State& s(getDrawingState());          // mSidebandStreamChanged was true          mSidebandStream = s.sidebandStream; @@ -573,15 +723,8 @@ bool BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) {  }  bool BufferStateLayer::hasFrameUpdate() const { -    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); +    const State& c(getDrawingState()); +    return (mDrawingStateModified || mDrawingState.modified) && (c.buffer != nullptr || c.bgColorLayer != nullptr);  }  status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime, @@ -597,56 +740,42 @@ 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) { -        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; +        if (handle->frameNumber == mDrawingState.frameNumber) { +            handle->latchTime = latchTime;          }      } -    mFlinger->mTimeStats->setAcquireFence(layerId, mDrawingState.frameNumber, -                                          std::make_shared<FenceTime>(mDrawingState.acquireFence)); -    mFlinger->mTimeStats->setLatchTime(layerId, mDrawingState.frameNumber, latchTime); - -    mCurrentStateModified = false; +    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;      return NO_ERROR;  } @@ -658,9 +787,14 @@ status_t BufferStateLayer::updateActiveBuffer() {          return BAD_VALUE;      } -    mPreviousBufferId = getCurrentBufferId(); +    if (!mBufferInfo.mBuffer || s.buffer->getBuffer() != mBufferInfo.mBuffer->getBuffer()) { +        decrementPendingBufferCount(); +    } + +    mPreviousReleaseCallbackId = {getCurrentBufferId(), mBufferInfo.mFrameNumber};      mBufferInfo.mBuffer = s.buffer;      mBufferInfo.mFence = s.acquireFence; +    mBufferInfo.mFrameNumber = s.frameNumber;      return NO_ERROR;  } @@ -756,9 +890,13 @@ void BufferStateLayer::gatherBufferInfo() {      mBufferInfo.mDesiredPresentTime = s.desiredPresentTime;      mBufferInfo.mFenceTime = std::make_shared<FenceTime>(s.acquireFence);      mBufferInfo.mFence = s.acquireFence; -    mBufferInfo.mTransform = s.transform; +    mBufferInfo.mTransform = s.bufferTransform; +    auto lastDataspace = mBufferInfo.mDataspace;      mBufferInfo.mDataspace = translateDataspace(s.dataspace); -    mBufferInfo.mCrop = computeCrop(s); +    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; @@ -767,27 +905,20 @@ void BufferStateLayer::gatherBufferInfo() {      mBufferInfo.mBufferSlot = mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId);  } -Rect BufferStateLayer::computeCrop(const State& s) { -    if (s.crop.isEmpty() && s.buffer) { -        return s.buffer->getBounds(); +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;      } else if (s.buffer) { -        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.buffer->getBuffer()->getBounds(); +    } else { +        return s.bufferCrop;      } -    return s.crop;  }  sp<Layer> BufferStateLayer::createClone() { @@ -799,34 +930,72 @@ sp<Layer> BufferStateLayer::createClone() {      return layer;  } -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; +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);          }      } -    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); + +    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);  }  } // namespace android  // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"  |