SF: merge BufferLayer and BufferStateLayer
Test: builds and boots
Bug: 238781169
Change-Id: If4b22aea96ba9c0c52df16a0af5fad648afc4cf1
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index eb17995..f1457bf 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -141,7 +141,6 @@
name: "libsurfaceflinger_sources",
srcs: [
"BackgroundExecutor.cpp",
- "BufferLayer.cpp",
"BufferStateLayer.cpp",
"ClientCache.cpp",
"Client.cpp",
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
deleted file mode 100644
index dd918c5..0000000
--- a/services/surfaceflinger/BufferLayer.cpp
+++ /dev/null
@@ -1,819 +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.
- */
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
-//#define LOG_NDEBUG 0
-#undef LOG_TAG
-#define LOG_TAG "BufferLayer"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include "BufferLayer.h"
-
-#include <compositionengine/CompositionEngine.h>
-#include <compositionengine/LayerFECompositionState.h>
-#include <compositionengine/OutputLayer.h>
-#include <compositionengine/impl/OutputLayerCompositionState.h>
-#include <cutils/compiler.h>
-#include <cutils/native_handle.h>
-#include <cutils/properties.h>
-#include <gui/BufferItem.h>
-#include <gui/BufferQueue.h>
-#include <gui/GLConsumer.h>
-#include <gui/LayerDebugInfo.h>
-#include <gui/Surface.h>
-#include <gui/TraceUtils.h>
-#include <renderengine/RenderEngine.h>
-#include <ui/DebugUtils.h>
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <utils/NativeHandle.h>
-#include <utils/StopWatch.h>
-#include <utils/Trace.h>
-
-#include <cmath>
-#include <cstdlib>
-#include <mutex>
-#include <sstream>
-
-#include "Colorizer.h"
-#include "DisplayDevice.h"
-#include "FrameTracer/FrameTracer.h"
-#include "TimeStats/TimeStats.h"
-
-namespace android {
-
-using gui::WindowInfo;
-
-static constexpr float defaultMaxLuminance = 1000.0;
-
-BufferLayer::BufferLayer(const LayerCreationArgs& args)
- : Layer(args),
- mTextureName(args.textureName),
- mCompositionState{mFlinger->getCompositionEngine().createLayerFECompositionState()} {
- ALOGV("Creating Layer %s", getDebugName());
-
- mPremultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied);
-
- mPotentialCursor = args.flags & ISurfaceComposerClient::eCursorWindow;
- mProtectedByApp = args.flags & ISurfaceComposerClient::eProtectedByApp;
-}
-
-BufferLayer::~BufferLayer() {
- if (!isClone()) {
- // The original layer and the clone layer share the same texture. 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 deleted texture.
- mFlinger->deleteTextureAsync(mTextureName);
- }
- const int32_t layerId = getSequence();
- mFlinger->mTimeStats->onDestroy(layerId);
- mFlinger->mFrameTracer->onDestroy(layerId);
-}
-
-void BufferLayer::useSurfaceDamage() {
- if (mFlinger->mForceFullDamage) {
- surfaceDamageRegion = Region::INVALID_REGION;
- } else {
- surfaceDamageRegion = mBufferInfo.mSurfaceDamage;
- }
-}
-
-void BufferLayer::useEmptyDamage() {
- surfaceDamageRegion.clear();
-}
-
-bool BufferLayer::isOpaque(const Layer::State& s) const {
- // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the
- // layer's opaque flag.
- if ((mSidebandStream == nullptr) && (mBufferInfo.mBuffer == nullptr)) {
- return false;
- }
-
- // if the layer has the opaque flag, then we're always opaque,
- // otherwise we use the current buffer's format.
- return ((s.flags & layer_state_t::eLayerOpaque) != 0) || getOpacityForFormat(getPixelFormat());
-}
-
-bool BufferLayer::canReceiveInput() const {
- return !isHiddenByPolicy() && (mBufferInfo.mBuffer == nullptr || getAlpha() > 0.0f);
-}
-
-bool BufferLayer::isVisible() const {
- return !isHiddenByPolicy() && getAlpha() > 0.0f &&
- (mBufferInfo.mBuffer != nullptr || mSidebandStream != nullptr);
-}
-
-bool BufferLayer::isFixedSize() const {
- return getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE;
-}
-
-bool BufferLayer::usesSourceCrop() const {
- return true;
-}
-
-static constexpr mat4 inverseOrientation(uint32_t transform) {
- const mat4 flipH(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
- const mat4 flipV(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1);
- const mat4 rot90(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
- mat4 tr;
-
- if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- tr = tr * rot90;
- }
- if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
- tr = tr * flipH;
- }
- if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
- tr = tr * flipV;
- }
- return inverse(tr);
-}
-
-std::optional<compositionengine::LayerFE::LayerSettings> BufferLayer::prepareClientComposition(
- compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) {
- ATRACE_CALL();
-
- std::optional<compositionengine::LayerFE::LayerSettings> result =
- Layer::prepareClientComposition(targetSettings);
- if (!result) {
- return result;
- }
-
- if (CC_UNLIKELY(mBufferInfo.mBuffer == 0) && mSidebandStream != nullptr) {
- // For surfaceview of tv sideband, there is no activeBuffer
- // in bufferqueue, we need return LayerSettings.
- return result;
- }
- const bool blackOutLayer = (isProtected() && !targetSettings.supportsProtectedContent) ||
- ((isSecure() || isProtected()) && !targetSettings.isSecure);
- const bool bufferCanBeUsedAsHwTexture =
- mBufferInfo.mBuffer->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE;
- compositionengine::LayerFE::LayerSettings& layer = *result;
- if (blackOutLayer || !bufferCanBeUsedAsHwTexture) {
- ALOGE_IF(!bufferCanBeUsedAsHwTexture, "%s is blacked out as buffer is not gpu readable",
- mName.c_str());
- prepareClearClientComposition(layer, true /* blackout */);
- return layer;
- }
-
- const State& s(getDrawingState());
- layer.source.buffer.buffer = mBufferInfo.mBuffer;
- layer.source.buffer.isOpaque = isOpaque(s);
- layer.source.buffer.fence = mBufferInfo.mFence;
- layer.source.buffer.textureName = mTextureName;
- layer.source.buffer.usePremultipliedAlpha = getPremultipledAlpha();
- layer.source.buffer.isY410BT2020 = isHdrY410();
- bool hasSmpte2086 = mBufferInfo.mHdrMetadata.validTypes & HdrMetadata::SMPTE2086;
- bool hasCta861_3 = mBufferInfo.mHdrMetadata.validTypes & HdrMetadata::CTA861_3;
- float maxLuminance = 0.f;
- if (hasSmpte2086 && hasCta861_3) {
- maxLuminance = std::min(mBufferInfo.mHdrMetadata.smpte2086.maxLuminance,
- mBufferInfo.mHdrMetadata.cta8613.maxContentLightLevel);
- } else if (hasSmpte2086) {
- maxLuminance = mBufferInfo.mHdrMetadata.smpte2086.maxLuminance;
- } else if (hasCta861_3) {
- maxLuminance = mBufferInfo.mHdrMetadata.cta8613.maxContentLightLevel;
- } else {
- switch (layer.sourceDataspace & HAL_DATASPACE_TRANSFER_MASK) {
- case HAL_DATASPACE_TRANSFER_ST2084:
- case HAL_DATASPACE_TRANSFER_HLG:
- // Behavior-match previous releases for HDR content
- maxLuminance = defaultMaxLuminance;
- break;
- }
- }
- layer.source.buffer.maxLuminanceNits = maxLuminance;
- layer.frameNumber = mCurrentFrameNumber;
- layer.bufferId = mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getId() : 0;
-
- const bool useFiltering =
- targetSettings.needsFiltering || mNeedsFiltering || bufferNeedsFiltering();
-
- // Query the texture matrix given our current filtering mode.
- float textureMatrix[16];
- getDrawingTransformMatrix(useFiltering, textureMatrix);
-
- if (getTransformToDisplayInverse()) {
- /*
- * the code below applies the primary display's inverse transform to
- * the texture transform
- */
- uint32_t transform = DisplayDevice::getPrimaryDisplayRotationFlags();
- mat4 tr = inverseOrientation(transform);
-
- /**
- * TODO(b/36727915): This is basically a hack.
- *
- * Ensure that regardless of the parent transformation,
- * this buffer is always transformed from native display
- * orientation to display orientation. For example, in the case
- * of a camera where the buffer remains in native orientation,
- * we want the pixels to always be upright.
- */
- sp<Layer> p = mDrawingParent.promote();
- if (p != nullptr) {
- const auto parentTransform = p->getTransform();
- tr = tr * inverseOrientation(parentTransform.getOrientation());
- }
-
- // and finally apply it to the original texture matrix
- const mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr);
- memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));
- }
-
- const Rect win{getBounds()};
- float bufferWidth = getBufferSize(s).getWidth();
- float bufferHeight = getBufferSize(s).getHeight();
-
- // BufferStateLayers can have a "buffer size" of [0, 0, -1, -1] when no display frame has
- // been set and there is no parent layer bounds. In that case, the scale is meaningless so
- // ignore them.
- if (!getBufferSize(s).isValid()) {
- bufferWidth = float(win.right) - float(win.left);
- bufferHeight = float(win.bottom) - float(win.top);
- }
-
- const float scaleHeight = (float(win.bottom) - float(win.top)) / bufferHeight;
- const float scaleWidth = (float(win.right) - float(win.left)) / bufferWidth;
- const float translateY = float(win.top) / bufferHeight;
- const float translateX = float(win.left) / bufferWidth;
-
- // Flip y-coordinates because GLConsumer expects OpenGL convention.
- mat4 tr = mat4::translate(vec4(.5, .5, 0, 1)) * mat4::scale(vec4(1, -1, 1, 1)) *
- mat4::translate(vec4(-.5, -.5, 0, 1)) *
- mat4::translate(vec4(translateX, translateY, 0, 1)) *
- mat4::scale(vec4(scaleWidth, scaleHeight, 1.0, 1.0));
-
- layer.source.buffer.useTextureFiltering = useFiltering;
- layer.source.buffer.textureTransform = mat4(static_cast<const float*>(textureMatrix)) * tr;
-
- return layer;
-}
-
-bool BufferLayer::isHdrY410() const {
- // pixel format is HDR Y410 masquerading as RGBA_1010102
- return (mBufferInfo.mDataspace == ui::Dataspace::BT2020_ITU_PQ &&
- mBufferInfo.mApi == NATIVE_WINDOW_API_MEDIA &&
- mBufferInfo.mPixelFormat == HAL_PIXEL_FORMAT_RGBA_1010102);
-}
-
-sp<compositionengine::LayerFE> BufferLayer::getCompositionEngineLayerFE() const {
- return asLayerFE();
-}
-
-compositionengine::LayerFECompositionState* BufferLayer::editCompositionState() {
- return mCompositionState.get();
-}
-
-const compositionengine::LayerFECompositionState* BufferLayer::getCompositionState() const {
- return mCompositionState.get();
-}
-
-void BufferLayer::preparePerFrameCompositionState() {
- Layer::preparePerFrameCompositionState();
-
- // Sideband layers
- auto* compositionState = editCompositionState();
- if (compositionState->sidebandStream.get() && !compositionState->sidebandStreamHasFrame) {
- compositionState->compositionType =
- aidl::android::hardware::graphics::composer3::Composition::SIDEBAND;
- return;
- } else if ((mDrawingState.flags & layer_state_t::eLayerIsDisplayDecoration) != 0) {
- compositionState->compositionType =
- aidl::android::hardware::graphics::composer3::Composition::DISPLAY_DECORATION;
- } else {
- // Normal buffer layers
- compositionState->hdrMetadata = mBufferInfo.mHdrMetadata;
- compositionState->compositionType = mPotentialCursor
- ? aidl::android::hardware::graphics::composer3::Composition::CURSOR
- : aidl::android::hardware::graphics::composer3::Composition::DEVICE;
- }
-
- compositionState->buffer = getBuffer();
- compositionState->bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT)
- ? 0
- : mBufferInfo.mBufferSlot;
- compositionState->acquireFence = mBufferInfo.mFence;
- compositionState->frameNumber = mBufferInfo.mFrameNumber;
- compositionState->sidebandStreamHasFrame = false;
-}
-
-bool BufferLayer::onPreComposition(nsecs_t) {
- return hasReadyFrame();
-}
-namespace {
-TimeStats::SetFrameRateVote frameRateToSetFrameRateVotePayload(Layer::FrameRate frameRate) {
- using FrameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility;
- using Seamlessness = TimeStats::SetFrameRateVote::Seamlessness;
- const auto frameRateCompatibility = [frameRate] {
- switch (frameRate.type) {
- case Layer::FrameRateCompatibility::Default:
- return FrameRateCompatibility::Default;
- case Layer::FrameRateCompatibility::ExactOrMultiple:
- return FrameRateCompatibility::ExactOrMultiple;
- default:
- return FrameRateCompatibility::Undefined;
- }
- }();
-
- const auto seamlessness = [frameRate] {
- switch (frameRate.seamlessness) {
- case scheduler::Seamlessness::OnlySeamless:
- return Seamlessness::ShouldBeSeamless;
- case scheduler::Seamlessness::SeamedAndSeamless:
- return Seamlessness::NotRequired;
- default:
- return Seamlessness::Undefined;
- }
- }();
-
- return TimeStats::SetFrameRateVote{.frameRate = frameRate.rate.getValue(),
- .frameRateCompatibility = frameRateCompatibility,
- .seamlessness = seamlessness};
-}
-} // namespace
-
-void BufferLayer::onPostComposition(const DisplayDevice* display,
- const std::shared_ptr<FenceTime>& glDoneFence,
- const std::shared_ptr<FenceTime>& presentFence,
- const CompositorTiming& compositorTiming) {
- // mFrameLatencyNeeded is true when a new frame was latched for the
- // composition.
- if (!mBufferInfo.mFrameLatencyNeeded) return;
-
- // Update mFrameEventHistory.
- finalizeFrameEventHistory(glDoneFence, compositorTiming);
-
- // Update mFrameTracker.
- nsecs_t desiredPresentTime = mBufferInfo.mDesiredPresentTime;
- mFrameTracker.setDesiredPresentTime(desiredPresentTime);
-
- const int32_t layerId = getSequence();
- mFlinger->mTimeStats->setDesiredTime(layerId, mCurrentFrameNumber, desiredPresentTime);
-
- const auto outputLayer = findOutputLayerForDisplay(display);
- if (outputLayer && outputLayer->requiresClientComposition()) {
- nsecs_t clientCompositionTimestamp = outputLayer->getState().clientCompositionTimestamp;
- mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber,
- clientCompositionTimestamp,
- FrameTracer::FrameEvent::FALLBACK_COMPOSITION);
- // Update the SurfaceFrames in the drawing state
- if (mDrawingState.bufferSurfaceFrameTX) {
- mDrawingState.bufferSurfaceFrameTX->setGpuComposition();
- }
- for (auto& [token, surfaceFrame] : mDrawingState.bufferlessSurfaceFramesTX) {
- surfaceFrame->setGpuComposition();
- }
- }
-
- std::shared_ptr<FenceTime> frameReadyFence = mBufferInfo.mFenceTime;
- if (frameReadyFence->isValid()) {
- mFrameTracker.setFrameReadyFence(std::move(frameReadyFence));
- } else {
- // There was no fence for this frame, so assume that it was ready
- // to be presented at the desired present time.
- mFrameTracker.setFrameReadyTime(desiredPresentTime);
- }
-
- if (display) {
- const Fps refreshRate = display->refreshRateConfigs().getActiveMode()->getFps();
- const std::optional<Fps> renderRate =
- mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());
-
- const auto vote = frameRateToSetFrameRateVotePayload(mDrawingState.frameRate);
- const auto gameMode = getGameMode();
-
- if (presentFence->isValid()) {
- mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence,
- refreshRate, renderRate, vote, gameMode);
- mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber,
- presentFence,
- FrameTracer::FrameEvent::PRESENT_FENCE);
- mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
- } else if (const auto displayId = PhysicalDisplayId::tryCast(display->getId());
- displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
- // The HWC doesn't support present fences, so use the refresh
- // timestamp instead.
- const nsecs_t actualPresentTime = display->getRefreshTimestamp();
- mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime,
- refreshRate, renderRate, vote, gameMode);
- mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(),
- mCurrentFrameNumber, actualPresentTime,
- FrameTracer::FrameEvent::PRESENT_FENCE);
- mFrameTracker.setActualPresentTime(actualPresentTime);
- }
- }
-
- mFrameTracker.advanceFrame();
- mBufferInfo.mFrameLatencyNeeded = false;
-}
-
-void BufferLayer::gatherBufferInfo() {
- mBufferInfo.mPixelFormat =
- !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->getPixelFormat();
- mBufferInfo.mFrameLatencyNeeded = true;
-}
-
-bool BufferLayer::shouldPresentNow(nsecs_t expectedPresentTime) const {
- // If this is not a valid vsync for the layer's uid, return and try again later
- const bool isVsyncValidForUid =
- mFlinger->mScheduler->isVsyncValid(expectedPresentTime, mOwnerUid);
- if (!isVsyncValidForUid) {
- ATRACE_NAME("!isVsyncValidForUid");
- return false;
- }
-
- // AutoRefresh layers and sideband streams should always be presented
- if (getSidebandStreamChanged() || getAutoRefresh()) {
- return true;
- }
-
- // If this layer doesn't have a frame is shouldn't be presented
- if (!hasFrameUpdate()) {
- return false;
- }
-
- // Defer to the derived class to decide whether the next buffer is due for
- // presentation.
- return isBufferDue(expectedPresentTime);
-}
-
-bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
- nsecs_t expectedPresentTime) {
- ATRACE_FORMAT_INSTANT("latchBuffer %s - %" PRIu64, getDebugName(),
- getDrawingState().frameNumber);
-
- bool refreshRequired = latchSidebandStream(recomputeVisibleRegions);
-
- if (refreshRequired) {
- return refreshRequired;
- }
-
- // If the head buffer's acquire fence hasn't signaled yet, return and
- // try again later
- if (!fenceHasSignaled()) {
- ATRACE_NAME("!fenceHasSignaled()");
- mFlinger->onLayerUpdate();
- return false;
- }
-
- // Capture the old state of the layer for comparisons later
- const State& s(getDrawingState());
- const bool oldOpacity = isOpaque(s);
-
- BufferInfo oldBufferInfo = mBufferInfo;
-
- status_t err = updateTexImage(recomputeVisibleRegions, latchTime, expectedPresentTime);
- if (err != NO_ERROR) {
- return false;
- }
-
- err = updateActiveBuffer();
- if (err != NO_ERROR) {
- return false;
- }
-
- err = updateFrameNumber();
- if (err != NO_ERROR) {
- return false;
- }
-
- gatherBufferInfo();
-
- if (oldBufferInfo.mBuffer == nullptr) {
- // the first time we receive a buffer, we need to trigger a
- // geometry invalidation.
- recomputeVisibleRegions = true;
- }
-
- if ((mBufferInfo.mCrop != oldBufferInfo.mCrop) ||
- (mBufferInfo.mTransform != oldBufferInfo.mTransform) ||
- (mBufferInfo.mScaleMode != oldBufferInfo.mScaleMode) ||
- (mBufferInfo.mTransformToDisplayInverse != oldBufferInfo.mTransformToDisplayInverse)) {
- recomputeVisibleRegions = true;
- }
-
- if (oldBufferInfo.mBuffer != nullptr) {
- uint32_t bufWidth = mBufferInfo.mBuffer->getWidth();
- uint32_t bufHeight = mBufferInfo.mBuffer->getHeight();
- if (bufWidth != oldBufferInfo.mBuffer->getWidth() ||
- bufHeight != oldBufferInfo.mBuffer->getHeight()) {
- recomputeVisibleRegions = true;
- }
- }
-
- if (oldOpacity != isOpaque(s)) {
- recomputeVisibleRegions = true;
- }
-
- return true;
-}
-
-bool BufferLayer::hasReadyFrame() const {
- return hasFrameUpdate() || getSidebandStreamChanged() || getAutoRefresh();
-}
-
-uint32_t BufferLayer::getEffectiveScalingMode() const {
- return mBufferInfo.mScaleMode;
-}
-
-bool BufferLayer::isProtected() const {
- return (mBufferInfo.mBuffer != nullptr) &&
- (mBufferInfo.mBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
-}
-
-// As documented in libhardware header, formats in the range
-// 0x100 - 0x1FF are specific to the HAL implementation, and
-// are known to have no alpha channel
-// TODO: move definition for device-specific range into
-// hardware.h, instead of using hard-coded values here.
-#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
-
-bool BufferLayer::getOpacityForFormat(PixelFormat format) {
- if (HARDWARE_IS_DEVICE_FORMAT(format)) {
- return true;
- }
- switch (format) {
- case PIXEL_FORMAT_RGBA_8888:
- case PIXEL_FORMAT_BGRA_8888:
- case PIXEL_FORMAT_RGBA_FP16:
- case PIXEL_FORMAT_RGBA_1010102:
- case PIXEL_FORMAT_R_8:
- return false;
- }
- // in all other case, we have no blending (also for unknown formats)
- return true;
-}
-
-bool BufferLayer::needsFiltering(const DisplayDevice* display) const {
- const auto outputLayer = findOutputLayerForDisplay(display);
- if (outputLayer == nullptr) {
- return false;
- }
-
- // We need filtering if the sourceCrop rectangle size does not match the
- // displayframe rectangle size (not a 1:1 render)
- const auto& compositionState = outputLayer->getState();
- const auto displayFrame = compositionState.displayFrame;
- const auto sourceCrop = compositionState.sourceCrop;
- return sourceCrop.getHeight() != displayFrame.getHeight() ||
- sourceCrop.getWidth() != displayFrame.getWidth();
-}
-
-bool BufferLayer::needsFilteringForScreenshots(const DisplayDevice* display,
- const ui::Transform& inverseParentTransform) const {
- const auto outputLayer = findOutputLayerForDisplay(display);
- if (outputLayer == nullptr) {
- return false;
- }
-
- // We need filtering if the sourceCrop rectangle size does not match the
- // viewport rectangle size (not a 1:1 render)
- const auto& compositionState = outputLayer->getState();
- const ui::Transform& displayTransform = display->getTransform();
- const ui::Transform inverseTransform = inverseParentTransform * displayTransform.inverse();
- // Undo the transformation of the displayFrame so that we're back into
- // layer-stack space.
- const Rect frame = inverseTransform.transform(compositionState.displayFrame);
- const FloatRect sourceCrop = compositionState.sourceCrop;
-
- int32_t frameHeight = frame.getHeight();
- int32_t frameWidth = frame.getWidth();
- // If the display transform had a rotational component then undo the
- // rotation so that the orientation matches the source crop.
- if (displayTransform.getOrientation() & ui::Transform::ROT_90) {
- std::swap(frameHeight, frameWidth);
- }
- return sourceCrop.getHeight() != frameHeight || sourceCrop.getWidth() != frameWidth;
-}
-
-Rect BufferLayer::getBufferSize(const State& s) const {
- // If we have a sideband stream, or we are scaling the buffer then return the layer size since
- // we cannot determine the buffer size.
- if ((s.sidebandStream != nullptr) ||
- (getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE)) {
- return Rect(getActiveWidth(s), getActiveHeight(s));
- }
-
- 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(bufWidth, bufHeight);
-}
-
-FloatRect BufferLayer::computeSourceBounds(const FloatRect& parentBounds) const {
- const State& s(getDrawingState());
-
- // If we have a sideband stream, or we are scaling the buffer then return the layer size since
- // we cannot determine the buffer size.
- if ((s.sidebandStream != nullptr) ||
- (getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE)) {
- return FloatRect(0, 0, getActiveWidth(s), getActiveHeight(s));
- }
-
- if (mBufferInfo.mBuffer == nullptr) {
- return parentBounds;
- }
-
- 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 FloatRect(0, 0, bufWidth, bufHeight);
-}
-
-void BufferLayer::latchAndReleaseBuffer() {
- if (hasReadyFrame()) {
- bool ignored = false;
- latchBuffer(ignored, systemTime(), 0 /* expectedPresentTime */);
- }
- releasePendingBuffer(systemTime());
-}
-
-PixelFormat BufferLayer::getPixelFormat() const {
- return mBufferInfo.mPixelFormat;
-}
-
-bool BufferLayer::getTransformToDisplayInverse() const {
- return mBufferInfo.mTransformToDisplayInverse;
-}
-
-Rect BufferLayer::getBufferCrop() const {
- // this is the crop rectangle that applies to the buffer
- // itself (as opposed to the window)
- if (!mBufferInfo.mCrop.isEmpty()) {
- // if the buffer crop is defined, we use that
- return mBufferInfo.mCrop;
- } else if (mBufferInfo.mBuffer != nullptr) {
- // otherwise we use the whole buffer
- return mBufferInfo.mBuffer->getBounds();
- } else {
- // if we don't have a buffer yet, we use an empty/invalid crop
- return Rect();
- }
-}
-
-uint32_t BufferLayer::getBufferTransform() const {
- return mBufferInfo.mTransform;
-}
-
-ui::Dataspace BufferLayer::getDataSpace() const {
- return mBufferInfo.mDataspace;
-}
-
-ui::Dataspace BufferLayer::translateDataspace(ui::Dataspace dataspace) {
- ui::Dataspace updatedDataspace = dataspace;
- // translate legacy dataspaces to modern dataspaces
- switch (dataspace) {
- case ui::Dataspace::SRGB:
- updatedDataspace = ui::Dataspace::V0_SRGB;
- break;
- case ui::Dataspace::SRGB_LINEAR:
- updatedDataspace = ui::Dataspace::V0_SRGB_LINEAR;
- break;
- case ui::Dataspace::JFIF:
- updatedDataspace = ui::Dataspace::V0_JFIF;
- break;
- case ui::Dataspace::BT601_625:
- updatedDataspace = ui::Dataspace::V0_BT601_625;
- break;
- case ui::Dataspace::BT601_525:
- updatedDataspace = ui::Dataspace::V0_BT601_525;
- break;
- case ui::Dataspace::BT709:
- updatedDataspace = ui::Dataspace::V0_BT709;
- break;
- default:
- break;
- }
-
- return updatedDataspace;
-}
-
-sp<GraphicBuffer> BufferLayer::getBuffer() const {
- return mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer() : nullptr;
-}
-
-void BufferLayer::getDrawingTransformMatrix(bool filteringEnabled, float outMatrix[16]) {
- sp<GraphicBuffer> buffer = getBuffer();
- if (!buffer) {
- ALOGE("Buffer should not be null!");
- return;
- }
- GLConsumer::computeTransformMatrix(outMatrix, buffer->getWidth(), buffer->getHeight(),
- buffer->getPixelFormat(), mBufferInfo.mCrop,
- mBufferInfo.mTransform, filteringEnabled);
-}
-
-void BufferLayer::setInitialValuesForClone(const sp<Layer>& clonedFrom) {
- Layer::setInitialValuesForClone(clonedFrom);
-
- sp<BufferLayer> bufferClonedFrom = static_cast<BufferLayer*>(clonedFrom.get());
- mPremultipliedAlpha = bufferClonedFrom->mPremultipliedAlpha;
- mPotentialCursor = bufferClonedFrom->mPotentialCursor;
- mProtectedByApp = bufferClonedFrom->mProtectedByApp;
-
- updateCloneBufferInfo();
-}
-
-void BufferLayer::updateCloneBufferInfo() {
- if (!isClone() || !isClonedFromAlive()) {
- return;
- }
-
- sp<BufferLayer> clonedFrom = static_cast<BufferLayer*>(getClonedFrom().get());
- mBufferInfo = clonedFrom->mBufferInfo;
- mSidebandStream = clonedFrom->mSidebandStream;
- surfaceDamageRegion = clonedFrom->surfaceDamageRegion;
- mCurrentFrameNumber = clonedFrom->mCurrentFrameNumber.load();
- mPreviousFrameNumber = clonedFrom->mPreviousFrameNumber;
-
- // After buffer info is updated, the drawingState from the real layer needs to be copied into
- // the cloned. This is because some properties of drawingState can change when latchBuffer is
- // called. However, copying the drawingState would also overwrite the cloned layer's relatives
- // and touchableRegionCrop. Therefore, temporarily store the relatives so they can be set in
- // the cloned drawingState again.
- wp<Layer> tmpZOrderRelativeOf = mDrawingState.zOrderRelativeOf;
- SortedVector<wp<Layer>> tmpZOrderRelatives = mDrawingState.zOrderRelatives;
- wp<Layer> tmpTouchableRegionCrop = mDrawingState.touchableRegionCrop;
- WindowInfo tmpInputInfo = mDrawingState.inputInfo;
-
- cloneDrawingState(clonedFrom.get());
-
- mDrawingState.touchableRegionCrop = tmpTouchableRegionCrop;
- mDrawingState.zOrderRelativeOf = tmpZOrderRelativeOf;
- mDrawingState.zOrderRelatives = tmpZOrderRelatives;
- mDrawingState.inputInfo = tmpInputInfo;
-}
-
-void BufferLayer::setTransformHint(ui::Transform::RotationFlags displayTransformHint) {
- mTransformHint = getFixedTransformHint();
- if (mTransformHint == ui::Transform::ROT_INVALID) {
- mTransformHint = displayTransformHint;
- }
-}
-
-bool BufferLayer::bufferNeedsFiltering() const {
- return isFixedSize();
-}
-
-const std::shared_ptr<renderengine::ExternalTexture>& BufferLayer::getExternalTexture() const {
- return mBufferInfo.mBuffer;
-}
-
-} // namespace android
-
-#if defined(__gl_h_)
-#error "don't include gl/gl.h in this file"
-#endif
-
-#if defined(__gl2_h_)
-#error "don't include gl2/gl2.h in this file"
-#endif
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
deleted file mode 100644
index 7cc67a2..0000000
--- a/services/surfaceflinger/BufferLayer.h
+++ /dev/null
@@ -1,220 +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.
- */
-
-#pragma once
-
-#include <sys/types.h>
-#include <cstdint>
-#include <list>
-
-#include <android/gui/ISurfaceComposerClient.h>
-#include <gui/LayerState.h>
-#include <renderengine/Image.h>
-#include <renderengine/Mesh.h>
-#include <renderengine/Texture.h>
-#include <system/window.h> // For NATIVE_WINDOW_SCALING_MODE_FREEZE
-#include <ui/FrameStats.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/PixelFormat.h>
-#include <ui/Region.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <utils/Timers.h>
-
-#include "Client.h"
-#include "DisplayHardware/HWComposer.h"
-#include "FrameTimeline.h"
-#include "FrameTracker.h"
-#include "Layer.h"
-#include "LayerVector.h"
-#include "SurfaceFlinger.h"
-
-namespace android {
-
-class BufferLayer : public Layer {
-public:
- explicit BufferLayer(const LayerCreationArgs& args);
- virtual ~BufferLayer() override;
-
- // Implements Layer.
- sp<compositionengine::LayerFE> getCompositionEngineLayerFE() const override;
- compositionengine::LayerFECompositionState* editCompositionState() override;
-
- // If we have received a new buffer this frame, we will pass its surface
- // damage down to hardware composer. Otherwise, we must send a region with
- // one empty rect.
- void useSurfaceDamage() override;
- void useEmptyDamage() override;
-
- bool isOpaque(const Layer::State& s) const override;
- bool canReceiveInput() const override;
-
- // isVisible - true if this layer is visible, false otherwise
- bool isVisible() const override;
-
- // isProtected - true if the layer may contain protected content in the
- // GRALLOC_USAGE_PROTECTED sense.
- bool isProtected() const override;
-
- // isFixedSize - true if content has a fixed size
- bool isFixedSize() const override;
-
- bool usesSourceCrop() const override;
-
- bool isHdrY410() const override;
-
- void onPostComposition(const DisplayDevice*, const std::shared_ptr<FenceTime>& glDoneFence,
- const std::shared_ptr<FenceTime>& presentFence,
- const CompositorTiming&) override;
-
- // latchBuffer - called each time the screen is redrawn and returns whether
- // the visible regions need to be recomputed (this is a fairly heavy
- // operation, so this should be set only if needed). Typically this is used
- // to figure out if the content or size of a surface has changed.
- bool latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
- nsecs_t expectedPresentTime) override;
- bool hasReadyFrame() const override;
-
- // Returns the current scaling mode
- uint32_t getEffectiveScalingMode() const override;
-
- // Calls latchBuffer if the buffer has a frame queued and then releases the buffer.
- // This is used if the buffer is just latched and releases to free up the buffer
- // and will not be shown on screen.
- // Should only be called on the main thread.
- void latchAndReleaseBuffer() override;
-
- bool getTransformToDisplayInverse() const override;
-
- Rect getBufferCrop() const override;
-
- uint32_t getBufferTransform() const override;
-
- ui::Dataspace getDataSpace() const override;
-
- sp<GraphicBuffer> getBuffer() const override;
- const std::shared_ptr<renderengine::ExternalTexture>& getExternalTexture() const override;
-
- ui::Transform::RotationFlags getTransformHint() const override { return mTransformHint; }
-
- // Returns true if the transformed buffer size does not match the layer size and we need
- // to apply filtering.
- virtual bool bufferNeedsFiltering() const;
-
-protected:
- struct BufferInfo {
- nsecs_t mDesiredPresentTime;
- std::shared_ptr<FenceTime> mFenceTime;
- sp<Fence> mFence;
- uint32_t mTransform{0};
- ui::Dataspace mDataspace{ui::Dataspace::UNKNOWN};
- Rect mCrop;
- uint32_t mScaleMode{NATIVE_WINDOW_SCALING_MODE_FREEZE};
- Region mSurfaceDamage;
- HdrMetadata mHdrMetadata;
- int mApi;
- PixelFormat mPixelFormat{PIXEL_FORMAT_NONE};
- bool mTransformToDisplayInverse{false};
-
- std::shared_ptr<renderengine::ExternalTexture> mBuffer;
- uint64_t mFrameNumber;
- int mBufferSlot{BufferQueue::INVALID_BUFFER_SLOT};
-
- bool mFrameLatencyNeeded{false};
- };
-
- BufferInfo mBufferInfo;
- virtual void gatherBufferInfo() = 0;
-
- std::optional<compositionengine::LayerFE::LayerSettings> prepareClientComposition(
- compositionengine::LayerFE::ClientCompositionTargetSettings&) override;
-
- /*
- * compositionengine::LayerFE overrides
- */
- const compositionengine::LayerFECompositionState* getCompositionState() const override;
- bool onPreComposition(nsecs_t) override;
- void preparePerFrameCompositionState() override;
-
- static bool getOpacityForFormat(PixelFormat format);
-
- // from graphics API
- const uint32_t mTextureName;
- ui::Dataspace translateDataspace(ui::Dataspace dataspace);
- void setInitialValuesForClone(const sp<Layer>& clonedFrom);
- void updateCloneBufferInfo() override;
- uint64_t mPreviousFrameNumber = 0;
-
- void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override;
-
- // Transform hint provided to the producer. This must be accessed holding
- // the mStateLock.
- ui::Transform::RotationFlags mTransformHint = ui::Transform::ROT_0;
-
- bool getAutoRefresh() const { return mDrawingState.autoRefresh; }
- bool getSidebandStreamChanged() const { return mSidebandStreamChanged; }
-
- // Returns true if the next buffer should be presented at the expected present time
- bool shouldPresentNow(nsecs_t expectedPresentTime) const;
-
- // Returns true if the next buffer should be presented at the expected present time,
- // overridden by BufferStateLayer and BufferQueueLayer for implementation
- // specific logic
- virtual bool isBufferDue(nsecs_t /*expectedPresentTime*/) const = 0;
-
- std::atomic<bool> mSidebandStreamChanged{false};
-
-private:
- virtual bool fenceHasSignaled() const = 0;
- virtual bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const = 0;
-
- // Latch sideband stream and returns true if the dirty region should be updated.
- virtual bool latchSidebandStream(bool& recomputeVisibleRegions) = 0;
-
- virtual bool hasFrameUpdate() const = 0;
-
- virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
- nsecs_t expectedPresentTime) = 0;
-
- virtual status_t updateActiveBuffer() = 0;
- virtual status_t updateFrameNumber() = 0;
-
- // We generate InputWindowHandles for all non-cursor buffered layers regardless of whether they
- // have an InputChannel. This is to enable the InputDispatcher to do PID based occlusion
- // detection.
- bool needsInputInfo() const override { return !mPotentialCursor; }
-
- // Returns true if this layer requires filtering
- bool needsFiltering(const DisplayDevice*) const override;
- bool needsFilteringForScreenshots(const DisplayDevice*,
- const ui::Transform& inverseParentTransform) const override;
-
- // BufferStateLayers can return Rect::INVALID_RECT if the layer does not have a display frame
- // and its parent layer is not bounded
- Rect getBufferSize(const State& s) const override;
-
- PixelFormat getPixelFormat() const;
-
- // Computes the transform matrix using the setFilteringEnabled to determine whether the
- // transform matrix should be computed for use with bilinear filtering.
- void getDrawingTransformMatrix(bool filteringEnabled, float outMatrix[16]);
-
- std::unique_ptr<compositionengine::LayerFECompositionState> mCompositionState;
-
- FloatRect computeSourceBounds(const FloatRect& parentBounds) const override;
-};
-
-} // namespace android
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 574e2f5..59e2d18 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -24,6 +24,7 @@
#include <limits>
#include <FrameTimeline/FrameTimeline.h>
+#include <compositionengine/CompositionEngine.h>
#include <compositionengine/LayerFECompositionState.h>
#include <gui/BufferQueue.h>
#include <private/gui/SyncFeatures.h>
@@ -37,10 +38,39 @@
#define EARLY_RELEASE_ENABLED false
+#include <compositionengine/LayerFECompositionState.h>
+#include <compositionengine/OutputLayer.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
+#include <cutils/compiler.h>
+#include <cutils/native_handle.h>
+#include <cutils/properties.h>
+#include <gui/BufferItem.h>
+#include <gui/BufferQueue.h>
+#include <gui/GLConsumer.h>
+#include <gui/LayerDebugInfo.h>
+#include <gui/Surface.h>
+#include <renderengine/RenderEngine.h>
+#include <ui/DebugUtils.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/NativeHandle.h>
+#include <utils/StopWatch.h>
+#include <utils/Trace.h>
+
+#include <cmath>
+#include <cstdlib>
+#include <mutex>
+#include <sstream>
+
+#include "Colorizer.h"
+#include "DisplayDevice.h"
+#include "FrameTracer/FrameTracer.h"
+#include "TimeStats/TimeStats.h"
+
namespace android {
using PresentState = frametimeline::SurfaceFrame::PresentState;
-
+using gui::WindowInfo;
void BufferStateLayer::callReleaseBufferCallback(const sp<ITransactionCompletedListener>& listener,
const sp<GraphicBuffer>& buffer,
uint64_t framenumber,
@@ -55,8 +85,21 @@
currentMaxAcquiredBufferCount);
}
+namespace {
+static constexpr float defaultMaxLuminance = 1000.0;
+} // namespace
+
BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args)
- : BufferLayer(args), mHwcSlotGenerator(new HwcSlotGenerator()) {
+ : Layer(args),
+ mTextureName(args.textureName),
+ mCompositionState{mFlinger->getCompositionEngine().createLayerFECompositionState()},
+ mHwcSlotGenerator(new HwcSlotGenerator()) {
+ ALOGV("Creating Layer %s", getDebugName());
+
+ mPremultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied);
+
+ mPotentialCursor = args.flags & ISurfaceComposerClient::eCursorWindow;
+ mProtectedByApp = args.flags & ISurfaceComposerClient::eProtectedByApp;
mDrawingState.dataspace = ui::Dataspace::V0_SRGB;
}
@@ -72,6 +115,16 @@
mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(
mOwnerUid));
}
+ if (!isClone()) {
+ // The original layer and the clone layer share the same texture. 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 deleted texture.
+ mFlinger->deleteTextureAsync(mTextureName);
+ }
+ const int32_t layerId = getSequence();
+ mFlinger->mTimeStats->onDestroy(layerId);
+ mFlinger->mFrameTracer->onDestroy(layerId);
}
// -----------------------------------------------------------------------
@@ -573,10 +626,6 @@
}
// -----------------------------------------------------------------------
-
-// -----------------------------------------------------------------------
-// Interface implementation for BufferLayer
-// -----------------------------------------------------------------------
bool BufferStateLayer::fenceHasSignaled() const {
if (SurfaceFlinger::enableLatchUnsignaledConfig != LatchUnsignaledConfig::Disabled) {
return true;
@@ -604,7 +653,7 @@
for (const auto& handle : mDrawingState.callbackHandles) {
handle->refreshStartTime = refreshStartTime;
}
- return BufferLayer::onPreComposition(refreshStartTime);
+ return hasReadyFrame();
}
void BufferStateLayer::setAutoRefresh(bool autoRefresh) {
@@ -789,7 +838,9 @@
}
void BufferStateLayer::gatherBufferInfo() {
- BufferLayer::gatherBufferInfo();
+ mBufferInfo.mPixelFormat =
+ !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->getPixelFormat();
+ mBufferInfo.mFrameLatencyNeeded = true;
const State& s(getDrawingState());
mBufferInfo.mDesiredPresentTime = s.desiredPresentTime;
@@ -1094,4 +1145,619 @@
return true;
}
+void BufferStateLayer::useSurfaceDamage() {
+ if (mFlinger->mForceFullDamage) {
+ surfaceDamageRegion = Region::INVALID_REGION;
+ } else {
+ surfaceDamageRegion = mBufferInfo.mSurfaceDamage;
+ }
+}
+
+void BufferStateLayer::useEmptyDamage() {
+ surfaceDamageRegion.clear();
+}
+
+bool BufferStateLayer::isOpaque(const Layer::State& s) const {
+ // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the
+ // layer's opaque flag.
+ if ((mSidebandStream == nullptr) && (mBufferInfo.mBuffer == nullptr)) {
+ return false;
+ }
+
+ // if the layer has the opaque flag, then we're always opaque,
+ // otherwise we use the current buffer's format.
+ return ((s.flags & layer_state_t::eLayerOpaque) != 0) || getOpacityForFormat(getPixelFormat());
+}
+
+bool BufferStateLayer::canReceiveInput() const {
+ return !isHiddenByPolicy() && (mBufferInfo.mBuffer == nullptr || getAlpha() > 0.0f);
+}
+
+bool BufferStateLayer::isVisible() const {
+ return !isHiddenByPolicy() && getAlpha() > 0.0f &&
+ (mBufferInfo.mBuffer != nullptr || mSidebandStream != nullptr);
+}
+
+bool BufferStateLayer::isFixedSize() const {
+ return true;
+}
+
+bool BufferStateLayer::usesSourceCrop() const {
+ return true;
+}
+
+static constexpr mat4 inverseOrientation(uint32_t transform) {
+ const mat4 flipH(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
+ const mat4 flipV(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1);
+ const mat4 rot90(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
+ mat4 tr;
+
+ if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+ tr = tr * rot90;
+ }
+ if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
+ tr = tr * flipH;
+ }
+ if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
+ tr = tr * flipV;
+ }
+ return inverse(tr);
+}
+
+std::optional<compositionengine::LayerFE::LayerSettings> BufferStateLayer::prepareClientComposition(
+ compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) {
+ ATRACE_CALL();
+
+ std::optional<compositionengine::LayerFE::LayerSettings> result =
+ Layer::prepareClientComposition(targetSettings);
+ if (!result) {
+ return result;
+ }
+
+ if (CC_UNLIKELY(mBufferInfo.mBuffer == 0) && mSidebandStream != nullptr) {
+ // For surfaceview of tv sideband, there is no activeBuffer
+ // in bufferqueue, we need return LayerSettings.
+ return result;
+ }
+ const bool blackOutLayer = (isProtected() && !targetSettings.supportsProtectedContent) ||
+ ((isSecure() || isProtected()) && !targetSettings.isSecure);
+ const bool bufferCanBeUsedAsHwTexture =
+ mBufferInfo.mBuffer->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE;
+ compositionengine::LayerFE::LayerSettings& layer = *result;
+ if (blackOutLayer || !bufferCanBeUsedAsHwTexture) {
+ ALOGE_IF(!bufferCanBeUsedAsHwTexture, "%s is blacked out as buffer is not gpu readable",
+ mName.c_str());
+ prepareClearClientComposition(layer, true /* blackout */);
+ return layer;
+ }
+
+ const State& s(getDrawingState());
+ layer.source.buffer.buffer = mBufferInfo.mBuffer;
+ layer.source.buffer.isOpaque = isOpaque(s);
+ layer.source.buffer.fence = mBufferInfo.mFence;
+ layer.source.buffer.textureName = mTextureName;
+ layer.source.buffer.usePremultipliedAlpha = getPremultipledAlpha();
+ layer.source.buffer.isY410BT2020 = isHdrY410();
+ bool hasSmpte2086 = mBufferInfo.mHdrMetadata.validTypes & HdrMetadata::SMPTE2086;
+ bool hasCta861_3 = mBufferInfo.mHdrMetadata.validTypes & HdrMetadata::CTA861_3;
+ float maxLuminance = 0.f;
+ if (hasSmpte2086 && hasCta861_3) {
+ maxLuminance = std::min(mBufferInfo.mHdrMetadata.smpte2086.maxLuminance,
+ mBufferInfo.mHdrMetadata.cta8613.maxContentLightLevel);
+ } else if (hasSmpte2086) {
+ maxLuminance = mBufferInfo.mHdrMetadata.smpte2086.maxLuminance;
+ } else if (hasCta861_3) {
+ maxLuminance = mBufferInfo.mHdrMetadata.cta8613.maxContentLightLevel;
+ } else {
+ switch (layer.sourceDataspace & HAL_DATASPACE_TRANSFER_MASK) {
+ case HAL_DATASPACE_TRANSFER_ST2084:
+ case HAL_DATASPACE_TRANSFER_HLG:
+ // Behavior-match previous releases for HDR content
+ maxLuminance = defaultMaxLuminance;
+ break;
+ }
+ }
+ layer.source.buffer.maxLuminanceNits = maxLuminance;
+ layer.frameNumber = mCurrentFrameNumber;
+ layer.bufferId = mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getId() : 0;
+
+ const bool useFiltering =
+ targetSettings.needsFiltering || mNeedsFiltering || bufferNeedsFiltering();
+
+ // Query the texture matrix given our current filtering mode.
+ float textureMatrix[16];
+ getDrawingTransformMatrix(useFiltering, textureMatrix);
+
+ if (getTransformToDisplayInverse()) {
+ /*
+ * the code below applies the primary display's inverse transform to
+ * the texture transform
+ */
+ uint32_t transform = DisplayDevice::getPrimaryDisplayRotationFlags();
+ mat4 tr = inverseOrientation(transform);
+
+ /**
+ * TODO(b/36727915): This is basically a hack.
+ *
+ * Ensure that regardless of the parent transformation,
+ * this buffer is always transformed from native display
+ * orientation to display orientation. For example, in the case
+ * of a camera where the buffer remains in native orientation,
+ * we want the pixels to always be upright.
+ */
+ sp<Layer> p = mDrawingParent.promote();
+ if (p != nullptr) {
+ const auto parentTransform = p->getTransform();
+ tr = tr * inverseOrientation(parentTransform.getOrientation());
+ }
+
+ // and finally apply it to the original texture matrix
+ const mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr);
+ memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));
+ }
+
+ const Rect win{getBounds()};
+ float bufferWidth = getBufferSize(s).getWidth();
+ float bufferHeight = getBufferSize(s).getHeight();
+
+ // BufferStateLayers can have a "buffer size" of [0, 0, -1, -1] when no display frame has
+ // been set and there is no parent layer bounds. In that case, the scale is meaningless so
+ // ignore them.
+ if (!getBufferSize(s).isValid()) {
+ bufferWidth = float(win.right) - float(win.left);
+ bufferHeight = float(win.bottom) - float(win.top);
+ }
+
+ const float scaleHeight = (float(win.bottom) - float(win.top)) / bufferHeight;
+ const float scaleWidth = (float(win.right) - float(win.left)) / bufferWidth;
+ const float translateY = float(win.top) / bufferHeight;
+ const float translateX = float(win.left) / bufferWidth;
+
+ // Flip y-coordinates because GLConsumer expects OpenGL convention.
+ mat4 tr = mat4::translate(vec4(.5f, .5f, 0.f, 1.f)) * mat4::scale(vec4(1.f, -1.f, 1.f, 1.f)) *
+ mat4::translate(vec4(-.5f, -.5f, 0.f, 1.f)) *
+ mat4::translate(vec4(translateX, translateY, 0.f, 1.f)) *
+ mat4::scale(vec4(scaleWidth, scaleHeight, 1.0f, 1.0f));
+
+ layer.source.buffer.useTextureFiltering = useFiltering;
+ layer.source.buffer.textureTransform = mat4(static_cast<const float*>(textureMatrix)) * tr;
+
+ return layer;
+}
+
+bool BufferStateLayer::isHdrY410() const {
+ // pixel format is HDR Y410 masquerading as RGBA_1010102
+ return (mBufferInfo.mDataspace == ui::Dataspace::BT2020_ITU_PQ &&
+ mBufferInfo.mApi == NATIVE_WINDOW_API_MEDIA &&
+ mBufferInfo.mPixelFormat == HAL_PIXEL_FORMAT_RGBA_1010102);
+}
+
+sp<compositionengine::LayerFE> BufferStateLayer::getCompositionEngineLayerFE() const {
+ return asLayerFE();
+}
+
+compositionengine::LayerFECompositionState* BufferStateLayer::editCompositionState() {
+ return mCompositionState.get();
+}
+
+const compositionengine::LayerFECompositionState* BufferStateLayer::getCompositionState() const {
+ return mCompositionState.get();
+}
+
+void BufferStateLayer::preparePerFrameCompositionState() {
+ Layer::preparePerFrameCompositionState();
+
+ // Sideband layers
+ auto* compositionState = editCompositionState();
+ if (compositionState->sidebandStream.get() && !compositionState->sidebandStreamHasFrame) {
+ compositionState->compositionType =
+ aidl::android::hardware::graphics::composer3::Composition::SIDEBAND;
+ return;
+ } else if ((mDrawingState.flags & layer_state_t::eLayerIsDisplayDecoration) != 0) {
+ compositionState->compositionType =
+ aidl::android::hardware::graphics::composer3::Composition::DISPLAY_DECORATION;
+ } else {
+ // Normal buffer layers
+ compositionState->hdrMetadata = mBufferInfo.mHdrMetadata;
+ compositionState->compositionType = mPotentialCursor
+ ? aidl::android::hardware::graphics::composer3::Composition::CURSOR
+ : aidl::android::hardware::graphics::composer3::Composition::DEVICE;
+ }
+
+ compositionState->buffer = getBuffer();
+ compositionState->bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT)
+ ? 0
+ : mBufferInfo.mBufferSlot;
+ compositionState->acquireFence = mBufferInfo.mFence;
+ compositionState->frameNumber = mBufferInfo.mFrameNumber;
+ compositionState->sidebandStreamHasFrame = false;
+}
+
+namespace {
+TimeStats::SetFrameRateVote frameRateToSetFrameRateVotePayload(Layer::FrameRate frameRate) {
+ using FrameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility;
+ using Seamlessness = TimeStats::SetFrameRateVote::Seamlessness;
+ const auto frameRateCompatibility = [frameRate] {
+ switch (frameRate.type) {
+ case Layer::FrameRateCompatibility::Default:
+ return FrameRateCompatibility::Default;
+ case Layer::FrameRateCompatibility::ExactOrMultiple:
+ return FrameRateCompatibility::ExactOrMultiple;
+ default:
+ return FrameRateCompatibility::Undefined;
+ }
+ }();
+
+ const auto seamlessness = [frameRate] {
+ switch (frameRate.seamlessness) {
+ case scheduler::Seamlessness::OnlySeamless:
+ return Seamlessness::ShouldBeSeamless;
+ case scheduler::Seamlessness::SeamedAndSeamless:
+ return Seamlessness::NotRequired;
+ default:
+ return Seamlessness::Undefined;
+ }
+ }();
+
+ return TimeStats::SetFrameRateVote{.frameRate = frameRate.rate.getValue(),
+ .frameRateCompatibility = frameRateCompatibility,
+ .seamlessness = seamlessness};
+}
+} // namespace
+
+void BufferStateLayer::onPostComposition(const DisplayDevice* display,
+ const std::shared_ptr<FenceTime>& glDoneFence,
+ const std::shared_ptr<FenceTime>& presentFence,
+ const CompositorTiming& compositorTiming) {
+ // mFrameLatencyNeeded is true when a new frame was latched for the
+ // composition.
+ if (!mBufferInfo.mFrameLatencyNeeded) return;
+
+ // Update mFrameEventHistory.
+ finalizeFrameEventHistory(glDoneFence, compositorTiming);
+
+ // Update mFrameTracker.
+ nsecs_t desiredPresentTime = mBufferInfo.mDesiredPresentTime;
+ mFrameTracker.setDesiredPresentTime(desiredPresentTime);
+
+ const int32_t layerId = getSequence();
+ mFlinger->mTimeStats->setDesiredTime(layerId, mCurrentFrameNumber, desiredPresentTime);
+
+ const auto outputLayer = findOutputLayerForDisplay(display);
+ if (outputLayer && outputLayer->requiresClientComposition()) {
+ nsecs_t clientCompositionTimestamp = outputLayer->getState().clientCompositionTimestamp;
+ mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber,
+ clientCompositionTimestamp,
+ FrameTracer::FrameEvent::FALLBACK_COMPOSITION);
+ // Update the SurfaceFrames in the drawing state
+ if (mDrawingState.bufferSurfaceFrameTX) {
+ mDrawingState.bufferSurfaceFrameTX->setGpuComposition();
+ }
+ for (auto& [token, surfaceFrame] : mDrawingState.bufferlessSurfaceFramesTX) {
+ surfaceFrame->setGpuComposition();
+ }
+ }
+
+ std::shared_ptr<FenceTime> frameReadyFence = mBufferInfo.mFenceTime;
+ if (frameReadyFence->isValid()) {
+ mFrameTracker.setFrameReadyFence(std::move(frameReadyFence));
+ } else {
+ // There was no fence for this frame, so assume that it was ready
+ // to be presented at the desired present time.
+ mFrameTracker.setFrameReadyTime(desiredPresentTime);
+ }
+
+ if (display) {
+ const Fps refreshRate = display->refreshRateConfigs().getActiveMode()->getFps();
+ const std::optional<Fps> renderRate =
+ mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());
+
+ const auto vote = frameRateToSetFrameRateVotePayload(mDrawingState.frameRate);
+ const auto gameMode = getGameMode();
+
+ if (presentFence->isValid()) {
+ mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence,
+ refreshRate, renderRate, vote, gameMode);
+ mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber,
+ presentFence,
+ FrameTracer::FrameEvent::PRESENT_FENCE);
+ mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
+ } else if (const auto displayId = PhysicalDisplayId::tryCast(display->getId());
+ displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
+ // The HWC doesn't support present fences, so use the refresh
+ // timestamp instead.
+ const nsecs_t actualPresentTime = display->getRefreshTimestamp();
+ mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime,
+ refreshRate, renderRate, vote, gameMode);
+ mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(),
+ mCurrentFrameNumber, actualPresentTime,
+ FrameTracer::FrameEvent::PRESENT_FENCE);
+ mFrameTracker.setActualPresentTime(actualPresentTime);
+ }
+ }
+
+ mFrameTracker.advanceFrame();
+ mBufferInfo.mFrameLatencyNeeded = false;
+}
+
+bool BufferStateLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ nsecs_t expectedPresentTime) {
+ ATRACE_FORMAT_INSTANT("latchBuffer %s - %" PRIu64, getDebugName(),
+ getDrawingState().frameNumber);
+
+ bool refreshRequired = latchSidebandStream(recomputeVisibleRegions);
+
+ if (refreshRequired) {
+ return refreshRequired;
+ }
+
+ // If the head buffer's acquire fence hasn't signaled yet, return and
+ // try again later
+ if (!fenceHasSignaled()) {
+ ATRACE_NAME("!fenceHasSignaled()");
+ mFlinger->onLayerUpdate();
+ return false;
+ }
+
+ // Capture the old state of the layer for comparisons later
+ const State& s(getDrawingState());
+ const bool oldOpacity = isOpaque(s);
+
+ BufferInfo oldBufferInfo = mBufferInfo;
+
+ status_t err = updateTexImage(recomputeVisibleRegions, latchTime, expectedPresentTime);
+ if (err != NO_ERROR) {
+ return false;
+ }
+
+ err = updateActiveBuffer();
+ if (err != NO_ERROR) {
+ return false;
+ }
+
+ err = updateFrameNumber();
+ if (err != NO_ERROR) {
+ return false;
+ }
+
+ gatherBufferInfo();
+
+ if (oldBufferInfo.mBuffer == nullptr) {
+ // the first time we receive a buffer, we need to trigger a
+ // geometry invalidation.
+ recomputeVisibleRegions = true;
+ }
+
+ if ((mBufferInfo.mCrop != oldBufferInfo.mCrop) ||
+ (mBufferInfo.mTransform != oldBufferInfo.mTransform) ||
+ (mBufferInfo.mScaleMode != oldBufferInfo.mScaleMode) ||
+ (mBufferInfo.mTransformToDisplayInverse != oldBufferInfo.mTransformToDisplayInverse)) {
+ recomputeVisibleRegions = true;
+ }
+
+ if (oldBufferInfo.mBuffer != nullptr) {
+ uint32_t bufWidth = mBufferInfo.mBuffer->getWidth();
+ uint32_t bufHeight = mBufferInfo.mBuffer->getHeight();
+ if (bufWidth != oldBufferInfo.mBuffer->getWidth() ||
+ bufHeight != oldBufferInfo.mBuffer->getHeight()) {
+ recomputeVisibleRegions = true;
+ }
+ }
+
+ if (oldOpacity != isOpaque(s)) {
+ recomputeVisibleRegions = true;
+ }
+
+ return true;
+}
+
+bool BufferStateLayer::hasReadyFrame() const {
+ return hasFrameUpdate() || getSidebandStreamChanged() || getAutoRefresh();
+}
+
+bool BufferStateLayer::isProtected() const {
+ return (mBufferInfo.mBuffer != nullptr) &&
+ (mBufferInfo.mBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
+}
+
+// As documented in libhardware header, formats in the range
+// 0x100 - 0x1FF are specific to the HAL implementation, and
+// are known to have no alpha channel
+// TODO: move definition for device-specific range into
+// hardware.h, instead of using hard-coded values here.
+#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
+
+bool BufferStateLayer::getOpacityForFormat(PixelFormat format) {
+ if (HARDWARE_IS_DEVICE_FORMAT(format)) {
+ return true;
+ }
+ switch (format) {
+ case PIXEL_FORMAT_RGBA_8888:
+ case PIXEL_FORMAT_BGRA_8888:
+ case PIXEL_FORMAT_RGBA_FP16:
+ case PIXEL_FORMAT_RGBA_1010102:
+ case PIXEL_FORMAT_R_8:
+ return false;
+ }
+ // in all other case, we have no blending (also for unknown formats)
+ return true;
+}
+
+bool BufferStateLayer::needsFiltering(const DisplayDevice* display) const {
+ const auto outputLayer = findOutputLayerForDisplay(display);
+ if (outputLayer == nullptr) {
+ return false;
+ }
+
+ // We need filtering if the sourceCrop rectangle size does not match the
+ // displayframe rectangle size (not a 1:1 render)
+ const auto& compositionState = outputLayer->getState();
+ const auto displayFrame = compositionState.displayFrame;
+ const auto sourceCrop = compositionState.sourceCrop;
+ return sourceCrop.getHeight() != displayFrame.getHeight() ||
+ sourceCrop.getWidth() != displayFrame.getWidth();
+}
+
+bool BufferStateLayer::needsFilteringForScreenshots(
+ const DisplayDevice* display, const ui::Transform& inverseParentTransform) const {
+ const auto outputLayer = findOutputLayerForDisplay(display);
+ if (outputLayer == nullptr) {
+ return false;
+ }
+
+ // We need filtering if the sourceCrop rectangle size does not match the
+ // viewport rectangle size (not a 1:1 render)
+ const auto& compositionState = outputLayer->getState();
+ const ui::Transform& displayTransform = display->getTransform();
+ const ui::Transform inverseTransform = inverseParentTransform * displayTransform.inverse();
+ // Undo the transformation of the displayFrame so that we're back into
+ // layer-stack space.
+ const Rect frame = inverseTransform.transform(compositionState.displayFrame);
+ const FloatRect sourceCrop = compositionState.sourceCrop;
+
+ int32_t frameHeight = frame.getHeight();
+ int32_t frameWidth = frame.getWidth();
+ // If the display transform had a rotational component then undo the
+ // rotation so that the orientation matches the source crop.
+ if (displayTransform.getOrientation() & ui::Transform::ROT_90) {
+ std::swap(frameHeight, frameWidth);
+ }
+ return sourceCrop.getHeight() != frameHeight || sourceCrop.getWidth() != frameWidth;
+}
+
+void BufferStateLayer::latchAndReleaseBuffer() {
+ if (hasReadyFrame()) {
+ bool ignored = false;
+ latchBuffer(ignored, systemTime(), 0 /* expectedPresentTime */);
+ }
+ releasePendingBuffer(systemTime());
+}
+
+PixelFormat BufferStateLayer::getPixelFormat() const {
+ return mBufferInfo.mPixelFormat;
+}
+
+bool BufferStateLayer::getTransformToDisplayInverse() const {
+ return mBufferInfo.mTransformToDisplayInverse;
+}
+
+Rect BufferStateLayer::getBufferCrop() const {
+ // this is the crop rectangle that applies to the buffer
+ // itself (as opposed to the window)
+ if (!mBufferInfo.mCrop.isEmpty()) {
+ // if the buffer crop is defined, we use that
+ return mBufferInfo.mCrop;
+ } else if (mBufferInfo.mBuffer != nullptr) {
+ // otherwise we use the whole buffer
+ return mBufferInfo.mBuffer->getBounds();
+ } else {
+ // if we don't have a buffer yet, we use an empty/invalid crop
+ return Rect();
+ }
+}
+
+uint32_t BufferStateLayer::getBufferTransform() const {
+ return mBufferInfo.mTransform;
+}
+
+ui::Dataspace BufferStateLayer::getDataSpace() const {
+ return mBufferInfo.mDataspace;
+}
+
+ui::Dataspace BufferStateLayer::translateDataspace(ui::Dataspace dataspace) {
+ ui::Dataspace updatedDataspace = dataspace;
+ // translate legacy dataspaces to modern dataspaces
+ switch (dataspace) {
+ case ui::Dataspace::SRGB:
+ updatedDataspace = ui::Dataspace::V0_SRGB;
+ break;
+ case ui::Dataspace::SRGB_LINEAR:
+ updatedDataspace = ui::Dataspace::V0_SRGB_LINEAR;
+ break;
+ case ui::Dataspace::JFIF:
+ updatedDataspace = ui::Dataspace::V0_JFIF;
+ break;
+ case ui::Dataspace::BT601_625:
+ updatedDataspace = ui::Dataspace::V0_BT601_625;
+ break;
+ case ui::Dataspace::BT601_525:
+ updatedDataspace = ui::Dataspace::V0_BT601_525;
+ break;
+ case ui::Dataspace::BT709:
+ updatedDataspace = ui::Dataspace::V0_BT709;
+ break;
+ default:
+ break;
+ }
+
+ return updatedDataspace;
+}
+
+sp<GraphicBuffer> BufferStateLayer::getBuffer() const {
+ return mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer() : nullptr;
+}
+
+void BufferStateLayer::getDrawingTransformMatrix(bool filteringEnabled, float outMatrix[16]) {
+ sp<GraphicBuffer> buffer = getBuffer();
+ if (!buffer) {
+ ALOGE("Buffer should not be null!");
+ return;
+ }
+ GLConsumer::computeTransformMatrix(outMatrix, buffer->getWidth(), buffer->getHeight(),
+ buffer->getPixelFormat(), mBufferInfo.mCrop,
+ mBufferInfo.mTransform, filteringEnabled);
+}
+
+void BufferStateLayer::setInitialValuesForClone(const sp<Layer>& clonedFrom) {
+ Layer::setInitialValuesForClone(clonedFrom);
+
+ sp<BufferStateLayer> bufferClonedFrom = static_cast<BufferStateLayer*>(clonedFrom.get());
+ mPremultipliedAlpha = bufferClonedFrom->mPremultipliedAlpha;
+ mPotentialCursor = bufferClonedFrom->mPotentialCursor;
+ mProtectedByApp = bufferClonedFrom->mProtectedByApp;
+
+ updateCloneBufferInfo();
+}
+
+void BufferStateLayer::updateCloneBufferInfo() {
+ if (!isClone() || !isClonedFromAlive()) {
+ return;
+ }
+
+ sp<BufferStateLayer> clonedFrom = static_cast<BufferStateLayer*>(getClonedFrom().get());
+ mBufferInfo = clonedFrom->mBufferInfo;
+ mSidebandStream = clonedFrom->mSidebandStream;
+ surfaceDamageRegion = clonedFrom->surfaceDamageRegion;
+ mCurrentFrameNumber = clonedFrom->mCurrentFrameNumber.load();
+ mPreviousFrameNumber = clonedFrom->mPreviousFrameNumber;
+
+ // After buffer info is updated, the drawingState from the real layer needs to be copied into
+ // the cloned. This is because some properties of drawingState can change when latchBuffer is
+ // called. However, copying the drawingState would also overwrite the cloned layer's relatives
+ // and touchableRegionCrop. Therefore, temporarily store the relatives so they can be set in
+ // the cloned drawingState again.
+ wp<Layer> tmpZOrderRelativeOf = mDrawingState.zOrderRelativeOf;
+ SortedVector<wp<Layer>> tmpZOrderRelatives = mDrawingState.zOrderRelatives;
+ wp<Layer> tmpTouchableRegionCrop = mDrawingState.touchableRegionCrop;
+ WindowInfo tmpInputInfo = mDrawingState.inputInfo;
+
+ cloneDrawingState(clonedFrom.get());
+
+ mDrawingState.touchableRegionCrop = tmpTouchableRegionCrop;
+ mDrawingState.zOrderRelativeOf = tmpZOrderRelativeOf;
+ mDrawingState.zOrderRelatives = tmpZOrderRelatives;
+ mDrawingState.inputInfo = tmpInputInfo;
+}
+
+void BufferStateLayer::setTransformHint(ui::Transform::RotationFlags displayTransformHint) {
+ mTransformHint = getFixedTransformHint();
+ if (mTransformHint == ui::Transform::ROT_INVALID) {
+ mTransformHint = displayTransformHint;
+ }
+}
+
+const std::shared_ptr<renderengine::ExternalTexture>& BufferStateLayer::getExternalTexture() const {
+ return mBufferInfo.mBuffer;
+}
+
} // namespace android
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index bf98a27..df7ae61 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -16,27 +16,106 @@
#pragma once
-#include "BufferLayer.h"
-#include "Layer.h"
-
-#include <renderengine/Image.h>
-#include <renderengine/RenderEngine.h>
-#include <system/window.h>
-#include <utils/String8.h>
-
+#include <sys/types.h>
+#include <cstdint>
+#include <list>
#include <stack>
+#include <android/gui/ISurfaceComposerClient.h>
+#include <gui/LayerState.h>
+#include <renderengine/Image.h>
+#include <renderengine/Mesh.h>
+#include <renderengine/RenderEngine.h>
+#include <renderengine/Texture.h>
+#include <system/window.h> // For NATIVE_WINDOW_SCALING_MODE_FREEZE
+#include <ui/FrameStats.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/PixelFormat.h>
+#include <ui/Region.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/Timers.h>
+
+#include "Client.h"
+#include "DisplayHardware/HWComposer.h"
+#include "FrameTimeline.h"
+#include "FrameTracker.h"
+#include "Layer.h"
+#include "LayerVector.h"
+#include "SurfaceFlinger.h"
+
namespace android {
class SlotGenerationTest;
-class BufferStateLayer : public BufferLayer {
+class BufferStateLayer : public Layer {
public:
explicit BufferStateLayer(const LayerCreationArgs&);
~BufferStateLayer() override;
// Implements Layer.
+ sp<compositionengine::LayerFE> getCompositionEngineLayerFE() const override;
+ compositionengine::LayerFECompositionState* editCompositionState() override;
+
+ // If we have received a new buffer this frame, we will pass its surface
+ // damage down to hardware composer. Otherwise, we must send a region with
+ // one empty rect.
+ void useSurfaceDamage() override;
+ void useEmptyDamage() override;
+
+ bool isOpaque(const Layer::State& s) const override;
+ bool canReceiveInput() const override;
+
+ // isVisible - true if this layer is visible, false otherwise
+ bool isVisible() const override;
+
+ // isProtected - true if the layer may contain protected content in the
+ // GRALLOC_USAGE_PROTECTED sense.
+ bool isProtected() const override;
+
+ // isFixedSize - true if content has a fixed size
+ bool isFixedSize() const override;
+
+ bool usesSourceCrop() const override;
+
+ bool isHdrY410() const override;
+
+ void onPostComposition(const DisplayDevice*, const std::shared_ptr<FenceTime>& glDoneFence,
+ const std::shared_ptr<FenceTime>& presentFence,
+ const CompositorTiming&) override;
+
+ // latchBuffer - called each time the screen is redrawn and returns whether
+ // the visible regions need to be recomputed (this is a fairly heavy
+ // operation, so this should be set only if needed). Typically this is used
+ // to figure out if the content or size of a surface has changed.
+ bool latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ nsecs_t expectedPresentTime) override;
+ bool hasReadyFrame() const override;
+
+ // Returns the current scaling mode
+ uint32_t getEffectiveScalingMode() const override;
+
+ // Calls latchBuffer if the buffer has a frame queued and then releases the buffer.
+ // This is used if the buffer is just latched and releases to free up the buffer
+ // and will not be shown on screen.
+ // Should only be called on the main thread.
+ void latchAndReleaseBuffer() override;
+
+ bool getTransformToDisplayInverse() const override;
+
+ Rect getBufferCrop() const override;
+
+ uint32_t getBufferTransform() const override;
+
+ ui::Dataspace getDataSpace() const override;
+
+ sp<GraphicBuffer> getBuffer() const override;
+ const std::shared_ptr<renderengine::ExternalTexture>& getExternalTexture() const override;
+
+ ui::Transform::RotationFlags getTransformHint() const override { return mTransformHint; }
+
+ // Implements Layer.
const char* getType() const override { return "BufferStateLayer"; }
void onLayerDisplayed(ftl::SharedFuture<FenceResult>) override;
@@ -46,7 +125,10 @@
void finalizeFrameEventHistory(const std::shared_ptr<FenceTime>& glDoneFence,
const CompositorTiming& compositorTiming) override;
- bool isBufferDue(nsecs_t /*expectedPresentTime*/) const override { return true; }
+ // Returns true if the next buffer should be presented at the expected present time,
+ // overridden by BufferStateLayer and BufferQueueLayer for implementation
+ // specific logic
+ bool isBufferDue(nsecs_t /*expectedPresentTime*/) const { return true; }
Region getActiveTransparentRegion(const Layer::State& s) const override {
return s.transparentRegionHint;
@@ -73,6 +155,8 @@
bool setSize(uint32_t /*w*/, uint32_t /*h*/) override { return false; }
bool setTransparentRegionHint(const Region& transparent) override;
+ // BufferStateLayers can return Rect::INVALID_RECT if the layer does not have a display frame
+ // and its parent layer is not bounded
Rect getBufferSize(const State& s) const override;
FloatRect computeSourceBounds(const FloatRect& parentBounds) const override;
void setAutoRefresh(bool autoRefresh) override;
@@ -81,48 +165,114 @@
bool setDestinationFrame(const Rect& destinationFrame) override;
bool updateGeometry() override;
- // -----------------------------------------------------------------------
-
- // -----------------------------------------------------------------------
- // Interface implementation for BufferLayer
- // -----------------------------------------------------------------------
- bool fenceHasSignaled() const override;
- bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override;
- bool onPreComposition(nsecs_t refreshStartTime) override;
- uint32_t getEffectiveScalingMode() const override;
+ bool fenceHasSignaled() const;
+ bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const;
+ bool onPreComposition(nsecs_t) override;
// See mPendingBufferTransactions
void decrementPendingBufferCount();
std::atomic<int32_t>* getPendingBufferCounter() override { return &mPendingBufferTransactions; }
std::string getPendingBufferCounterName() override { return mBlastTransactionName; }
+ // Returns true if the next buffer should be presented at the expected present time
bool shouldPresentNow(nsecs_t /*expectedPresentTime*/) const override { return true; }
protected:
- void gatherBufferInfo() override;
+ void gatherBufferInfo();
void onSurfaceFrameCreated(const std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame);
ui::Transform getInputTransform() const override;
Rect getInputBounds() const override;
+ struct BufferInfo {
+ nsecs_t mDesiredPresentTime;
+ std::shared_ptr<FenceTime> mFenceTime;
+ sp<Fence> mFence;
+ uint32_t mTransform{0};
+ ui::Dataspace mDataspace{ui::Dataspace::UNKNOWN};
+ Rect mCrop;
+ uint32_t mScaleMode{NATIVE_WINDOW_SCALING_MODE_FREEZE};
+ Region mSurfaceDamage;
+ HdrMetadata mHdrMetadata;
+ int mApi;
+ PixelFormat mPixelFormat{PIXEL_FORMAT_NONE};
+ bool mTransformToDisplayInverse{false};
+
+ std::shared_ptr<renderengine::ExternalTexture> mBuffer;
+ uint64_t mFrameNumber;
+ int mBufferSlot{BufferQueue::INVALID_BUFFER_SLOT};
+
+ bool mFrameLatencyNeeded{false};
+ };
+
+ BufferInfo mBufferInfo;
+
+ std::optional<compositionengine::LayerFE::LayerSettings> prepareClientComposition(
+ compositionengine::LayerFE::ClientCompositionTargetSettings&) override;
+
+ /*
+ * compositionengine::LayerFE overrides
+ */
+ const compositionengine::LayerFECompositionState* getCompositionState() const override;
+ void preparePerFrameCompositionState() override;
+
+ static bool getOpacityForFormat(PixelFormat format);
+
+ // from graphics API
+ const uint32_t mTextureName;
+ ui::Dataspace translateDataspace(ui::Dataspace dataspace);
+ void setInitialValuesForClone(const sp<Layer>& clonedFrom);
+ void updateCloneBufferInfo() override;
+ uint64_t mPreviousFrameNumber = 0;
+
+ void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override;
+
+ // Transform hint provided to the producer. This must be accessed holding
+ // the mStateLock.
+ ui::Transform::RotationFlags mTransformHint = ui::Transform::ROT_0;
+
+ bool getAutoRefresh() const { return mDrawingState.autoRefresh; }
+ bool getSidebandStreamChanged() const { return mSidebandStreamChanged; }
+
+ std::atomic<bool> mSidebandStreamChanged{false};
+
private:
friend class SlotGenerationTest;
friend class TransactionFrameTracerTest;
friend class TransactionSurfaceFrameTest;
+ // We generate InputWindowHandles for all non-cursor buffered layers regardless of whether they
+ // have an InputChannel. This is to enable the InputDispatcher to do PID based occlusion
+ // detection.
+ bool needsInputInfo() const override { return !mPotentialCursor; }
+
+ // Returns true if this layer requires filtering
+ bool needsFiltering(const DisplayDevice*) const override;
+ bool needsFilteringForScreenshots(const DisplayDevice*,
+ const ui::Transform& inverseParentTransform) const override;
+
+ PixelFormat getPixelFormat() const;
+
+ // Computes the transform matrix using the setFilteringEnabled to determine whether the
+ // transform matrix should be computed for use with bilinear filtering.
+ void getDrawingTransformMatrix(bool filteringEnabled, float outMatrix[16]);
+
+ std::unique_ptr<compositionengine::LayerFECompositionState> mCompositionState;
+
inline void tracePendingBufferCount(int32_t pendingBuffers);
bool updateFrameEventHistory(const sp<Fence>& acquireFence, nsecs_t postedTime,
nsecs_t requestedPresentTime);
- bool latchSidebandStream(bool& recomputeVisibleRegions) override;
+ // Latch sideband stream and returns true if the dirty region should be updated.
+ bool latchSidebandStream(bool& recomputeVisibleRegions);
- bool hasFrameUpdate() const override;
+ bool hasFrameUpdate() const;
status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
- nsecs_t expectedPresentTime) override;
+ nsecs_t expectedPresentTime);
- status_t updateActiveBuffer() override;
- status_t updateFrameNumber() override;
+ status_t updateActiveBuffer();
+ status_t updateFrameNumber();
sp<Layer> createClone() override;
@@ -131,7 +281,9 @@
bool willPresentCurrentTransaction() const;
- bool bufferNeedsFiltering() const override;
+ // Returns true if the transformed buffer size does not match the layer size and we need
+ // to apply filtering.
+ bool bufferNeedsFiltering() const;
bool simpleBufferUpdate(const layer_state_t& s) const override;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index cabadb7..ba3cb51 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -62,7 +62,6 @@
#include <mutex>
#include <sstream>
-#include "BufferLayer.h"
#include "Colorizer.h"
#include "DisplayDevice.h"
#include "DisplayHardware/HWComposer.h"
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 2beb946..3874371 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -105,7 +105,6 @@
#include <ui/DisplayIdentification.h>
#include "BackgroundExecutor.h"
-#include "BufferLayer.h"
#include "BufferStateLayer.h"
#include "Client.h"
#include "Colorizer.h"