summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/BufferStateLayer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/surfaceflinger/BufferStateLayer.cpp')
-rw-r--r--services/surfaceflinger/BufferStateLayer.cpp382
1 files changed, 230 insertions, 152 deletions
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index de5d6225d9..790f2ece77 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -14,24 +14,25 @@
* 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 "BufferStateLayer"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#include "BufferStateLayer.h"
+
#include <limits>
-#include <compositionengine/Display.h>
-#include <compositionengine/Layer.h>
-#include <compositionengine/OutputLayer.h>
-#include <compositionengine/impl/LayerCompositionState.h>
-#include <compositionengine/impl/OutputLayerCompositionState.h>
+#include <compositionengine/LayerFECompositionState.h>
#include <gui/BufferQueue.h>
#include <private/gui/SyncFeatures.h>
#include <renderengine/Image.h>
-#include "BufferStateLayer.h"
-#include "ColorLayer.h"
+#include "EffectLayer.h"
#include "TimeStats/TimeStats.h"
namespace android {
@@ -52,12 +53,16 @@ BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args)
}
BufferStateLayer::~BufferStateLayer() {
- if (mActiveBuffer != nullptr) {
- // Ensure that mActiveBuffer is uncached from RenderEngine here, as
+ // The original layer and the clone layer share the same texture and buffer. Therefore, only
+ // one of the layers, in this case the original layer, needs to handle the deletion. The
+ // original layer and the clone should be removed at the same time so there shouldn't be any
+ // issue with the clone layer trying to use the texture.
+ if (mBufferInfo.mBuffer != nullptr && !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(mActiveBuffer->getId());
+ engine.unbindExternalTextureBuffer(mBufferInfo.mBuffer->getId());
}
}
@@ -87,18 +92,43 @@ void BufferStateLayer::onLayerDisplayed(const sp<Fence>& releaseFence) {
break;
}
}
-}
-void BufferStateLayer::setTransformHint(uint32_t /*orientation*/) const {
- // TODO(marissaw): send the transform hint to buffer owner
- return;
+ mPreviousReleaseFence = releaseFence;
+
+ // Prevent tracing the same release multiple times.
+ if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) {
+ mPreviousReleasedFrameNumber = mPreviousFrameNumber;
+ }
}
-void BufferStateLayer::releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) {
- mFlinger->getTransactionCompletedThread().addPresentedCallbackHandles(
+void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
+ for (const auto& handle : mDrawingState.callbackHandles) {
+ handle->transformHint = mTransformHint;
+ handle->dequeueReadyTime = dequeueReadyTime;
+ }
+
+ mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles(
mDrawingState.callbackHandles);
mDrawingState.callbackHandles = {};
+
+ const sp<Fence>& releaseFence(mPreviousReleaseFence);
+ std::shared_ptr<FenceTime> releaseFenceTime = std::make_shared<FenceTime>(releaseFence);
+ {
+ Mutex::Autolock lock(mFrameEventHistoryMutex);
+ if (mPreviousFrameNumber != 0) {
+ mFrameEventHistory.addRelease(mPreviousFrameNumber, dequeueReadyTime,
+ std::move(releaseFenceTime));
+ }
+ }
+}
+
+void BufferStateLayer::finalizeFrameEventHistory(const std::shared_ptr<FenceTime>& glDoneFence,
+ const CompositorTiming& compositorTiming) {
+ for (const auto& handle : mDrawingState.callbackHandles) {
+ handle->gpuCompositionDoneFence = glDoneFence;
+ handle->compositorTiming = compositorTiming;
+ }
}
bool BufferStateLayer::shouldPresentNow(nsecs_t /*expectedPresentTime*/) const {
@@ -111,29 +141,27 @@ bool BufferStateLayer::shouldPresentNow(nsecs_t /*expectedPresentTime*/) const {
bool BufferStateLayer::willPresentCurrentTransaction() const {
// Returns true if the most recent Transaction applied to CurrentState will be presented.
- return getSidebandStreamChanged() || getAutoRefresh() ||
+ return (getSidebandStreamChanged() || getAutoRefresh() ||
(mCurrentState.modified &&
- (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr));
-}
-
-bool BufferStateLayer::getTransformToDisplayInverse() const {
- return mCurrentState.transformToDisplayInverse;
+ (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr))) &&
+ !mLayerDetached;
}
+/* TODO: vhau uncomment once deferred transaction migration complete in
+ * WindowManager
void BufferStateLayer::pushPendingState() {
if (!mCurrentState.modified) {
return;
}
mPendingStates.push_back(mCurrentState);
- ATRACE_INT(mTransactionName.string(), mPendingStates.size());
+ ATRACE_INT(mTransactionName.c_str(), mPendingStates.size());
}
+*/
bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) {
- const bool stateUpdateAvailable = !mPendingStates.empty();
- while (!mPendingStates.empty()) {
- popPendingState(stateToCommit);
- }
- mCurrentStateModified = stateUpdateAvailable && mCurrentState.modified;
+ mCurrentStateModified = mCurrentState.modified;
+ bool stateUpdateAvailable = Layer::applyPendingStates(stateToCommit);
+ mCurrentStateModified = stateUpdateAvailable && mCurrentStateModified;
mCurrentState.modified = false;
return stateUpdateAvailable;
}
@@ -215,26 +243,43 @@ bool BufferStateLayer::setFrame(const Rect& frame) {
return true;
}
-bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer, nsecs_t postTime,
- nsecs_t desiredPresentTime, const client_cache_t& clientCacheId) {
+bool BufferStateLayer::addFrameEvent(const sp<Fence>& acquireFence, nsecs_t postedTime,
+ nsecs_t desiredPresentTime) {
+ Mutex::Autolock lock(mFrameEventHistoryMutex);
+ mAcquireTimeline.updateSignalTimes();
+ std::shared_ptr<FenceTime> acquireFenceTime =
+ std::make_shared<FenceTime>((acquireFence ? acquireFence : Fence::NO_FENCE));
+ NewFrameEventsEntry newTimestamps = {mCurrentState.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) {
mReleasePreviousBuffer = true;
}
+ mCurrentState.frameNumber++;
+
mCurrentState.buffer = buffer;
mCurrentState.clientCacheId = clientCacheId;
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
- mFlinger->mTimeStats->setPostTime(getSequence(), getFrameNumber(), getName().c_str(), postTime);
- mDesiredPresentTime = desiredPresentTime;
+ const int32_t layerId = getSequence();
+ mFlinger->mTimeStats->setPostTime(layerId, mCurrentState.frameNumber, getName().c_str(),
+ postTime);
+ desiredPresentTime = desiredPresentTime <= 0 ? 0 : desiredPresentTime;
+ mCurrentState.desiredPresentTime = desiredPresentTime;
- if (mFlinger->mUseSmart90ForVideo) {
- const nsecs_t presentTime = (mDesiredPresentTime == -1) ? 0 : mDesiredPresentTime;
- mFlinger->mScheduler->addLayerPresentTimeAndHDR(mSchedulerLayerHandle, presentTime,
- mCurrentState.hdrMetadata.validTypes != 0);
- }
+ mFlinger->mScheduler->recordLayerHistory(this, desiredPresentTime,
+ LayerHistory::LayerUpdateType::Buffer);
+ addFrameEvent(acquireFence, postTime, desiredPresentTime);
return true;
}
@@ -320,7 +365,7 @@ bool BufferStateLayer::setTransactionCompletedListeners(
} 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().addUnpresentedCallbackHandle(handle);
+ mFlinger->getTransactionCompletedThread().registerUnpresentedCallbackHandle(handle);
}
}
@@ -330,6 +375,11 @@ 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;
@@ -376,81 +426,59 @@ bool BufferStateLayer::fenceHasSignaled() const {
return true;
}
- return getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled;
+ const bool fenceSignaled =
+ getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled;
+ if (!fenceSignaled) {
+ mFlinger->mTimeStats->incrementLatchSkipped(getSequence(),
+ TimeStats::LatchSkipReason::LateAcquire);
+ }
+
+ return fenceSignaled;
}
-bool BufferStateLayer::framePresentTimeIsCurrent() const {
+bool BufferStateLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const {
if (!hasFrameUpdate() || isRemovedFromCurrentState()) {
return true;
}
- return mDesiredPresentTime <= mFlinger->getExpectedPresentTime();
-}
-
-nsecs_t BufferStateLayer::getDesiredPresentTime() {
- return mDesiredPresentTime;
+ return mCurrentState.desiredPresentTime <= expectedPresentTime;
}
-std::shared_ptr<FenceTime> BufferStateLayer::getCurrentFenceTime() const {
- return std::make_shared<FenceTime>(getDrawingState().acquireFence);
-}
-
-void BufferStateLayer::getDrawingTransformMatrix(float *matrix) {
- std::copy(std::begin(mTransformMatrix), std::end(mTransformMatrix), matrix);
-}
-
-uint32_t BufferStateLayer::getDrawingTransform() const {
- return getDrawingState().transform;
-}
-
-ui::Dataspace BufferStateLayer::getDrawingDataSpace() const {
- return getDrawingState().dataspace;
-}
-
-// Crop that applies to the buffer
-Rect BufferStateLayer::getDrawingCrop() const {
- const State& s(getDrawingState());
-
- if (s.crop.isEmpty() && s.buffer) {
- return s.buffer->getBounds();
- } 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;
+bool BufferStateLayer::onPreComposition(nsecs_t refreshStartTime) {
+ for (const auto& handle : mDrawingState.callbackHandles) {
+ handle->refreshStartTime = refreshStartTime;
}
- return s.crop;
+ return BufferLayer::onPreComposition(refreshStartTime);
}
-uint32_t BufferStateLayer::getDrawingScalingMode() const {
- return NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
+uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const {
+ return mDrawingState.frameNumber;
}
-Region BufferStateLayer::getDrawingSurfaceDamage() const {
- return getDrawingState().surfaceDamageRegion;
-}
-
-const HdrMetadata& BufferStateLayer::getDrawingHdrMetadata() const {
- return getDrawingState().hdrMetadata;
-}
-
-int BufferStateLayer::getDrawingApi() const {
- return getDrawingState().api;
-}
-
-uint64_t BufferStateLayer::getFrameNumber() const {
- return mFrameNumber;
+/**
+ * This is the frameNumber used for deferred transaction signalling. We need to use this because
+ * of cases where we defer a transaction for a surface to itself. In the BLAST world this
+ * may not make a huge amount of sense (Why not just merge the Buffer transaction with the
+ * deferred transaction?) but this is an important legacy use case, for example moving
+ * a window at the same time it draws makes use of this kind of technique. So anyway
+ * imagine we have something like this:
+ *
+ * Transaction { // containing
+ * Buffer -> frameNumber = 2
+ * DeferTransactionUntil -> frameNumber = 2
+ * Random other stuff
+ * }
+ * Now imagine getHeadFrameNumber returned mDrawingState.mFrameNumber (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
+ * 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
+ * we can see we need to return the frame number for the buffer we are about
+ * to apply.
+ */
+uint64_t BufferStateLayer::getHeadFrameNumber(nsecs_t /* expectedPresentTime */) const {
+ return mCurrentState.frameNumber;
}
bool BufferStateLayer::getAutoRefresh() const {
@@ -466,9 +494,8 @@ bool BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) {
if (mSidebandStreamChanged.exchange(false)) {
const State& s(getDrawingState());
// mSidebandStreamChanged was true
- LOG_ALWAYS_FATAL_IF(!getCompositionLayer());
mSidebandStream = s.sidebandStream;
- getCompositionLayer()->editState().frontEnd.sidebandStream = mSidebandStream;
+ editCompositionState()->sidebandStream = mSidebandStream;
if (mSidebandStream != nullptr) {
setTransactionFlags(eTransactionNeeded);
mFlinger->setTransactionFlags(eTraversalNeeded);
@@ -485,11 +512,6 @@ bool BufferStateLayer::hasFrameUpdate() const {
return mCurrentStateModified && (c.buffer != nullptr || c.bgColorLayer != nullptr);
}
-void BufferStateLayer::setFilteringEnabled(bool enabled) {
- GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mActiveBuffer, mCurrentCrop,
- mCurrentTransform, enabled);
-}
-
status_t BufferStateLayer::bindTextureImage() {
const State& s(getDrawingState());
auto& engine(mFlinger->getRenderEngine());
@@ -497,7 +519,8 @@ status_t BufferStateLayer::bindTextureImage() {
return engine.bindExternalTextureBuffer(mTextureName, s.buffer, s.acquireFence);
}
-status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime) {
+status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime,
+ nsecs_t /*expectedPresentTime*/) {
const State& s(getDrawingState());
if (!s.buffer) {
@@ -509,7 +532,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse
return NO_ERROR;
}
- const int32_t layerID = getSequence();
+ const int32_t layerId = getSequence();
// Reject if the layer is invalid
uint32_t bufferWidth = s.buffer->width;
@@ -520,7 +543,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse
}
if (s.transformToDisplayInverse) {
- uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform();
+ uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags();
if (invTransform & ui::Transform::ROT_90) {
std::swap(bufferWidth, bufferHeight);
}
@@ -530,13 +553,14 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse
(s.active.w != bufferWidth || s.active.h != bufferHeight)) {
ALOGE("[%s] rejecting buffer: "
"bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}",
- mName.string(), bufferWidth, bufferHeight, s.active.w, s.active.h);
- mFlinger->mTimeStats->removeTimeRecord(layerID, getFrameNumber());
+ 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()) {
@@ -548,13 +572,14 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse
// a GL-composited layer) not at all.
status_t err = bindTextureImage();
if (err != NO_ERROR) {
- mFlinger->mTimeStats->onDestroy(layerID);
+ mFlinger->mTimeStats->onDestroy(layerId);
return BAD_VALUE;
}
}
- mFlinger->mTimeStats->setAcquireFence(layerID, getFrameNumber(), getCurrentFenceTime());
- mFlinger->mTimeStats->setLatchTime(layerID, getFrameNumber(), latchTime);
+ mFlinger->mTimeStats->setAcquireFence(layerId, mDrawingState.frameNumber,
+ std::make_shared<FenceTime>(mDrawingState.acquireFence));
+ mFlinger->mTimeStats->setLatchTime(layerId, mDrawingState.frameNumber, latchTime);
mCurrentStateModified = false;
@@ -568,49 +593,22 @@ status_t BufferStateLayer::updateActiveBuffer() {
return BAD_VALUE;
}
- mActiveBuffer = s.buffer;
- mActiveBufferFence = s.acquireFence;
- auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
- layerCompositionState.buffer = mActiveBuffer;
- layerCompositionState.bufferSlot = 0;
+ mPreviousBufferId = getCurrentBufferId();
+ mBufferInfo.mBuffer = s.buffer;
+ mBufferInfo.mFence = s.acquireFence;
return NO_ERROR;
}
-status_t BufferStateLayer::updateFrameNumber(nsecs_t /*latchTime*/) {
+status_t BufferStateLayer::updateFrameNumber(nsecs_t latchTime) {
// TODO(marissaw): support frame history events
- mCurrentFrameNumber = mFrameNumber;
- return NO_ERROR;
-}
-
-void BufferStateLayer::setHwcLayerBuffer(const sp<const DisplayDevice>& display) {
- const auto outputLayer = findOutputLayerForDisplay(display);
- LOG_FATAL_IF(!outputLayer || !outputLayer->getState().hwc);
- auto& hwcInfo = *outputLayer->editState().hwc;
- auto& hwcLayer = hwcInfo.hwcLayer;
-
- const State& s(getDrawingState());
-
- uint32_t hwcSlot;
- sp<GraphicBuffer> buffer;
- hwcInfo.hwcBufferCache.getHwcBuffer(mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId),
- s.buffer, &hwcSlot, &buffer);
-
- auto error = hwcLayer->setBuffer(hwcSlot, buffer, s.acquireFence);
- if (error != HWC2::Error::None) {
- ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(),
- s.buffer->handle, to_string(error).c_str(), static_cast<int32_t>(error));
- }
-
- mFrameNumber++;
-}
-
-void BufferStateLayer::onFirstRef() {
- BufferLayer::onFirstRef();
-
- if (const auto display = mFlinger->getDefaultDisplayDevice()) {
- updateTransformHint(display);
+ mPreviousFrameNumber = mCurrentFrameNumber;
+ mCurrentFrameNumber = mDrawingState.frameNumber;
+ {
+ Mutex::Autolock lock(mFrameEventHistoryMutex);
+ mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime);
}
+ return NO_ERROR;
}
void BufferStateLayer::HwcSlotGenerator::bufferErased(const client_cache_t& clientCacheId) {
@@ -685,4 +683,84 @@ void BufferStateLayer::HwcSlotGenerator::eraseBufferLocked(const client_cache_t&
mFreeHwcCacheSlots.push(hwcCacheSlot);
mCachedBuffers.erase(clientCacheId);
}
+
+void BufferStateLayer::gatherBufferInfo() {
+ BufferLayer::gatherBufferInfo();
+
+ const State& s(getDrawingState());
+ mBufferInfo.mDesiredPresentTime = s.desiredPresentTime;
+ mBufferInfo.mFenceTime = std::make_shared<FenceTime>(s.acquireFence);
+ mBufferInfo.mFence = s.acquireFence;
+ mBufferInfo.mTransform = s.transform;
+ mBufferInfo.mDataspace = translateDataspace(s.dataspace);
+ mBufferInfo.mCrop = computeCrop(s);
+ mBufferInfo.mScaleMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
+ mBufferInfo.mSurfaceDamage = s.surfaceDamageRegion;
+ mBufferInfo.mHdrMetadata = s.hdrMetadata;
+ mBufferInfo.mApi = s.api;
+ mBufferInfo.mTransformToDisplayInverse = s.transformToDisplayInverse;
+ mBufferInfo.mBufferSlot = mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId);
+}
+
+Rect BufferStateLayer::computeCrop(const State& s) {
+ if (s.crop.isEmpty() && s.buffer) {
+ return s.buffer->getBounds();
+ } 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.crop;
+}
+
+sp<Layer> BufferStateLayer::createClone() {
+ LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, LayerMetadata());
+ args.textureName = mTextureName;
+ sp<BufferStateLayer> layer = mFlinger->getFactory().createBufferStateLayer(args);
+ layer->mHwcSlotGenerator = mHwcSlotGenerator;
+ layer->setInitialValuesForClone(this);
+ 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;
+ }
+ }
+ const float radius = getDrawingState().cornerRadius;
+ const State& s(getDrawingState());
+ if (radius <= 0 || (getActiveWidth(s) == UINT32_MAX && getActiveHeight(s) == UINT32_MAX))
+ return RoundedCornerState();
+ return RoundedCornerState(FloatRect(static_cast<float>(s.active.transform.tx()),
+ static_cast<float>(s.active.transform.ty()),
+ static_cast<float>(s.active.transform.tx() + s.active.w),
+ static_cast<float>(s.active.transform.ty() + s.active.h)),
+ radius);
+}
} // namespace android
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic pop // ignored "-Wconversion"