diff options
author | 2018-06-08 15:11:57 -0700 | |
---|---|---|
committer | 2018-06-08 15:11:57 -0700 | |
commit | f11e2bd016d886a333345dea853ebda23a408d5c (patch) | |
tree | 905bd4d25d6ab2b046620ff459777d8dcfa5d7de /services/surfaceflinger/Layer.cpp | |
parent | aabd6b7fa343654cd85b3b2da392e424d037d15a (diff) | |
parent | 5c947cdf72270fd1f766b2248d526ebc8c7227f6 (diff) |
Merge pi-dev-plus-aosp-without-vendor into stage-aosp-master
Bug: 79597307
Change-Id: I6d6bee71b9424eb478780bbfc06b830eb8ded342
Diffstat (limited to 'services/surfaceflinger/Layer.cpp')
-rw-r--r--[-rwxr-xr-x] | services/surfaceflinger/Layer.cpp | 1981 |
1 files changed, 590 insertions, 1391 deletions
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 97c56b3542..2595ec1a05 100755..100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -19,10 +19,11 @@ #define LOG_TAG "Layer" #define ATRACE_TAG ATRACE_TAG_GRAPHICS -#include <stdlib.h> +#include <math.h> #include <stdint.h> +#include <stdlib.h> #include <sys/types.h> -#include <math.h> +#include <algorithm> #include <cutils/compiler.h> #include <cutils/native_handle.h> @@ -39,41 +40,43 @@ #include <ui/PixelFormat.h> #include <gui/BufferItem.h> -#include <gui/BufferQueue.h> #include <gui/LayerDebugInfo.h> #include <gui/Surface.h> -#include "clz.h" +#include "BufferLayer.h" #include "Colorizer.h" #include "DisplayDevice.h" #include "Layer.h" #include "LayerRejecter.h" #include "MonitoredProducer.h" #include "SurfaceFlinger.h" +#include "clz.h" #include "DisplayHardware/HWComposer.h" #include "RenderEngine/RenderEngine.h" #include <mutex> +#include "LayerProtoHelper.h" -#define DEBUG_RESIZE 0 +#define DEBUG_RESIZE 0 namespace android { -// --------------------------------------------------------------------------- +LayerBE::LayerBE() + : mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) { +} + int32_t Layer::sSequence = 1; -Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, - const String8& name, uint32_t w, uint32_t h, uint32_t flags) - : contentDirty(false), +Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w, + uint32_t h, uint32_t flags) + : contentDirty(false), sequence(uint32_t(android_atomic_inc(&sSequence))), mFlinger(flinger), - mTextureName(UINT32_MAX), mPremultipliedAlpha(true), - mName("unnamed"), - mFormat(PIXEL_FORMAT_NONE), + mName(name), mTransactionFlags(0), mPendingStateMutex(), mPendingStates(), @@ -81,86 +84,55 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, mSidebandStreamChanged(false), mActiveBufferSlot(BufferQueue::INVALID_BUFFER_SLOT), mCurrentTransform(0), - mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), mOverrideScalingMode(-1), mCurrentOpacity(true), - mBufferLatched(false), mCurrentFrameNumber(0), - mPreviousFrameNumber(0), - mRefreshPending(false), mFrameLatencyNeeded(false), mFiltering(false), mNeedsFiltering(false), - mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2), -#ifndef USE_HWC2 - mIsGlesComposition(false), -#endif mProtectedByApp(false), - mHasSurface(false), mClientRef(client), mPotentialCursor(false), mQueueItemLock(), mQueueItemCondition(), mQueueItems(), mLastFrameNumberReceived(0), - mUpdateTexImageFailed(false), mAutoRefresh(false), - mFreezeGeometryUpdates(false) -{ -#ifdef USE_HWC2 - ALOGV("Creating Layer %s", name.string()); -#endif - + mFreezeGeometryUpdates(false), + mCurrentChildren(LayerVector::StateSet::Current), + mDrawingChildren(LayerVector::StateSet::Drawing) { mCurrentCrop.makeInvalid(); - mFlinger->getRenderEngine().genTextures(1, &mTextureName); - mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName); uint32_t layerFlags = 0; - if (flags & ISurfaceComposerClient::eHidden) - layerFlags |= layer_state_t::eLayerHidden; - if (flags & ISurfaceComposerClient::eOpaque) - layerFlags |= layer_state_t::eLayerOpaque; - if (flags & ISurfaceComposerClient::eSecure) - layerFlags |= layer_state_t::eLayerSecure; - - if (flags & ISurfaceComposerClient::eNonPremultiplied) - mPremultipliedAlpha = false; + if (flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden; + if (flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque; + if (flags & ISurfaceComposerClient::eSecure) layerFlags |= layer_state_t::eLayerSecure; mName = name; mTransactionName = String8("TX - ") + mName; mCurrentState.active.w = w; mCurrentState.active.h = h; + mCurrentState.flags = layerFlags; mCurrentState.active.transform.set(0, 0); mCurrentState.crop.makeInvalid(); mCurrentState.finalCrop.makeInvalid(); mCurrentState.requestedFinalCrop = mCurrentState.finalCrop; mCurrentState.requestedCrop = mCurrentState.crop; mCurrentState.z = 0; -#ifdef USE_HWC2 - mCurrentState.alpha = 1.0f; -#else - mCurrentState.alpha = 0xFF; -#endif + mCurrentState.color.a = 1.0f; mCurrentState.layerStack = 0; - mCurrentState.flags = layerFlags; mCurrentState.sequence = 0; mCurrentState.requested = mCurrentState.active; - mCurrentState.dataSpace = HAL_DATASPACE_UNKNOWN; mCurrentState.appId = 0; mCurrentState.type = 0; // drawing state & current state are identical mDrawingState = mCurrentState; -#ifdef USE_HWC2 const auto& hwc = flinger->getHwComposer(); const auto& activeConfig = hwc.getActiveConfig(HWC_DISPLAY_PRIMARY); nsecs_t displayPeriod = activeConfig->getVsyncPeriod(); -#else - nsecs_t displayPeriod = - flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY); -#endif mFrameTracker.setDisplayRefreshPeriod(displayPeriod); CompositorTiming compositorTiming; @@ -168,27 +140,10 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, mFrameEventHistory.initializeCompositorTiming(compositorTiming); } -void Layer::onFirstRef() { - // Creates a custom BufferQueue for SurfaceFlingerConsumer to use - sp<IGraphicBufferProducer> producer; - sp<IGraphicBufferConsumer> consumer; - BufferQueue::createBufferQueue(&producer, &consumer, true); - mProducer = new MonitoredProducer(producer, mFlinger, this); - mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName, this); - mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); - mSurfaceFlingerConsumer->setContentsChangedListener(this); - mSurfaceFlingerConsumer->setName(mName); - - if (mFlinger->isLayerTripleBufferingDisabled()) { - mProducer->setMaxDequeuedBufferCount(2); - } - - const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice()); - updateTransformHint(hw); -} +void Layer::onFirstRef() {} Layer::~Layer() { - sp<Client> c(mClientRef.promote()); + sp<Client> c(mClientRef.promote()); if (c != 0) { c->detachLayer(this); } @@ -199,103 +154,25 @@ Layer::~Layer() { for (auto& point : mLocalSyncPoints) { point->setFrameAvailable(); } - mFlinger->deleteTextureAsync(mTextureName); mFrameTracker.logAndResetStats(mName); - -#ifdef USE_HWC2 - if (!mHwcLayers.empty()) { - ALOGE("Found stale hardware composer layers when destroying " - "surface flinger layer %s", mName.string()); - destroyAllHwcLayers(); - } -#endif } // --------------------------------------------------------------------------- // callbacks // --------------------------------------------------------------------------- -#ifdef USE_HWC2 -void Layer::onLayerDisplayed(const sp<Fence>& releaseFence) { - mSurfaceFlingerConsumer->setReleaseFence(releaseFence); -} -#else -void Layer::onLayerDisplayed(const sp<const DisplayDevice>& /* hw */, - HWComposer::HWCLayerInterface* layer) { - if (layer) { - layer->onDisplayed(); - mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFence()); - } -} -#endif - -void Layer::onFrameAvailable(const BufferItem& item) { - // Add this buffer from our internal queue tracker - { // Autolock scope - Mutex::Autolock lock(mQueueItemLock); - mFlinger->mInterceptor.saveBufferUpdate(this, item.mGraphicBuffer->getWidth(), - item.mGraphicBuffer->getHeight(), item.mFrameNumber); - // Reset the frame number tracker when we receive the first buffer after - // a frame number reset - if (item.mFrameNumber == 1) { - mLastFrameNumberReceived = 0; - } - - // Ensure that callbacks are handled in order - while (item.mFrameNumber != mLastFrameNumberReceived + 1) { - status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, - ms2ns(500)); - if (result != NO_ERROR) { - ALOGE("[%s] Timed out waiting on callback", mName.string()); - } - } - - mQueueItems.push_back(item); - android_atomic_inc(&mQueuedFrames); - - // Wake up any pending callbacks - mLastFrameNumberReceived = item.mFrameNumber; - mQueueItemCondition.broadcast(); - } - - mFlinger->signalLayerUpdate(); -} - -void Layer::onFrameReplaced(const BufferItem& item) { - { // Autolock scope - Mutex::Autolock lock(mQueueItemLock); - - // Ensure that callbacks are handled in order - while (item.mFrameNumber != mLastFrameNumberReceived + 1) { - status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, - ms2ns(500)); - if (result != NO_ERROR) { - ALOGE("[%s] Timed out waiting on callback", mName.string()); - } - } - - if (mQueueItems.empty()) { - ALOGE("Can't replace a frame on an empty queue"); - return; - } - mQueueItems.editItemAt(mQueueItems.size() - 1) = item; - - // Wake up any pending callbacks - mLastFrameNumberReceived = item.mFrameNumber; - mQueueItemCondition.broadcast(); - } -} - -void Layer::onSidebandStreamChanged() { - if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) { - // mSidebandStreamChanged was false - mFlinger->signalLayerUpdate(); - } -} +/* + * onLayerDisplayed is only meaningful for BufferLayer, but, is called through + * Layer. So, the implementation is done in BufferLayer. When called on a + * ColorLayer object, it's essentially a NOP. + */ +void Layer::onLayerDisplayed(const sp<Fence>& /*releaseFence*/) {} void Layer::onRemovedFromCurrentState() { // the layer is removed from SF mCurrentState to mLayersPendingRemoval + mPendingRemoval = true; + if (mCurrentState.zOrderRelativeOf != nullptr) { sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote(); if (strongRelative != nullptr) { @@ -312,11 +189,9 @@ void Layer::onRemovedFromCurrentState() { void Layer::onRemoved() { // the layer is removed from SF mLayersPendingRemoval + abandon(); - mSurfaceFlingerConsumer->abandon(); -#ifdef USE_HWC2 destroyAllHwcLayers(); -#endif for (const auto& child : mCurrentChildren) { child->onRemoved(); @@ -331,94 +206,58 @@ const String8& Layer::getName() const { return mName; } -status_t Layer::setBuffers( uint32_t w, uint32_t h, - PixelFormat format, uint32_t flags) -{ - uint32_t const maxSurfaceDims = min( - mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims()); - - // never allow a surface larger than what our underlying GL implementation - // can handle. - if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) { - ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h)); - return BAD_VALUE; - } - - mFormat = format; - - mPotentialCursor = (flags & ISurfaceComposerClient::eCursorWindow) ? true : false; - mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false; - mCurrentOpacity = getOpacityForFormat(format); - - mSurfaceFlingerConsumer->setDefaultBufferSize(w, h); - mSurfaceFlingerConsumer->setDefaultBufferFormat(format); - mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); - - return NO_ERROR; +bool Layer::getPremultipledAlpha() const { + return mPremultipliedAlpha; } sp<IBinder> Layer::getHandle() { Mutex::Autolock _l(mLock); - - LOG_ALWAYS_FATAL_IF(mHasSurface, - "Layer::getHandle() has already been called"); - - mHasSurface = true; - return new Handle(mFlinger, this); } -sp<IGraphicBufferProducer> Layer::getProducer() const { - return mProducer; -} - // --------------------------------------------------------------------------- // h/w composer set-up // --------------------------------------------------------------------------- -#ifdef USE_HWC2 bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) { - LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0, - "Already have a layer for hwcId %d", hwcId); + LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(hwcId) != 0, + "Already have a layer for hwcId %d", hwcId); HWC2::Layer* layer = hwc->createLayer(hwcId); if (!layer) { return false; } - HWCInfo& hwcInfo = mHwcLayers[hwcId]; + LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers[hwcId]; hwcInfo.hwc = hwc; hwcInfo.layer = layer; layer->setLayerDestroyedListener( - [this, hwcId] (HWC2::Layer* /*layer*/){mHwcLayers.erase(hwcId);}); + [this, hwcId](HWC2::Layer* /*layer*/) { getBE().mHwcLayers.erase(hwcId); }); return true; } bool Layer::destroyHwcLayer(int32_t hwcId) { - if (mHwcLayers.count(hwcId) == 0) { + if (getBE().mHwcLayers.count(hwcId) == 0) { return false; } - auto& hwcInfo = mHwcLayers[hwcId]; - LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr, - "Attempt to destroy null layer"); + auto& hwcInfo = getBE().mHwcLayers[hwcId]; + LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr, "Attempt to destroy null layer"); LOG_ALWAYS_FATAL_IF(hwcInfo.hwc == nullptr, "Missing HWComposer"); hwcInfo.hwc->destroyLayer(hwcId, hwcInfo.layer); // The layer destroyed listener should have cleared the entry from // mHwcLayers. Verify that. - LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0, - "Stale layer entry in mHwcLayers"); - + LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(hwcId) != 0, + "Stale layer entry in getBE().mHwcLayers"); return true; } void Layer::destroyAllHwcLayers() { - size_t numLayers = mHwcLayers.size(); + size_t numLayers = getBE().mHwcLayers.size(); for (size_t i = 0; i < numLayers; ++i) { - LOG_ALWAYS_FATAL_IF(mHwcLayers.empty(), "destroyAllHwcLayers failed"); - destroyHwcLayer(mHwcLayers.begin()->first); + LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.empty(), "destroyAllHwcLayers failed"); + destroyHwcLayer(getBE().mHwcLayers.begin()->first); } - LOG_ALWAYS_FATAL_IF(!mHwcLayers.empty(), - "All hardware composer layers should have been destroyed"); + LOG_ALWAYS_FATAL_IF(!getBE().mHwcLayers.empty(), + "All hardware composer layers should have been destroyed"); } -#endif Rect Layer::getContentCrop() const { // this is the crop rectangle that applies to the buffer @@ -427,9 +266,9 @@ Rect Layer::getContentCrop() const { if (!mCurrentCrop.isEmpty()) { // if the buffer crop is defined, we use that crop = mCurrentCrop; - } else if (mActiveBuffer != NULL) { + } else if (getBE().compositionInfo.mBuffer != nullptr) { // otherwise we use the whole buffer - crop = mActiveBuffer->getBounds(); + crop = getBE().compositionInfo.mBuffer->getBounds(); } else { // if we don't have a buffer yet, we use an empty/invalid crop crop.makeInvalid(); @@ -550,10 +389,17 @@ Rect Layer::computeInitialCrop(const sp<const DisplayDevice>& hw) const { activeCrop.clear(); } if (!s.finalCrop.isEmpty()) { - if(!activeCrop.intersect(s.finalCrop, &activeCrop)) { + if (!activeCrop.intersect(s.finalCrop, &activeCrop)) { activeCrop.clear(); } } + + const auto& p = mDrawingParent.promote(); + if (p != nullptr) { + auto parentCrop = p->computeInitialCrop(hw); + activeCrop.intersect(parentCrop, &activeCrop); + } + return activeCrop; } @@ -567,11 +413,6 @@ FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { // Screen space to make reduction to parent crop clearer. Rect activeCrop = computeInitialCrop(hw); - const auto& p = mDrawingParent.promote(); - if (p != nullptr) { - auto parentCrop = p->computeInitialCrop(hw); - activeCrop.intersect(parentCrop, &activeCrop); - } Transform t = getTransform(); // Back to layer space to work with the content crop. activeCrop = t.inverse().transform(activeCrop); @@ -598,16 +439,13 @@ FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { * the code below applies the primary display's inverse transform to the * buffer */ - uint32_t invTransformOrient = - DisplayDevice::getPrimaryDisplayOrientationTransform(); + uint32_t invTransformOrient = DisplayDevice::getPrimaryDisplayOrientationTransform(); // calculate the inverse transform if (invTransformOrient & NATIVE_WINDOW_TRANSFORM_ROT_90) { - invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | - NATIVE_WINDOW_TRANSFORM_FLIP_H; + invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H; } // and apply to the current transform - invTransform = (Transform(invTransformOrient) * Transform(invTransform)) - .getOrientation(); + invTransform = (Transform(invTransformOrient) * Transform(invTransform)).getOrientation(); } int winWidth = s.active.w; @@ -621,49 +459,36 @@ FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { bool is_h_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0; bool is_v_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0; if (is_h_flipped == is_v_flipped) { - invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | - NATIVE_WINDOW_TRANSFORM_FLIP_H; + invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H; } winWidth = s.active.h; winHeight = s.active.w; } - const Rect winCrop = activeCrop.transform( - invTransform, s.active.w, s.active.h); + const Rect winCrop = activeCrop.transform(invTransform, s.active.w, s.active.h); // below, crop is intersected with winCrop expressed in crop's coordinate space - float xScale = crop.getWidth() / float(winWidth); + float xScale = crop.getWidth() / float(winWidth); float yScale = crop.getHeight() / float(winHeight); - float insetL = winCrop.left * xScale; - float insetT = winCrop.top * yScale; - float insetR = (winWidth - winCrop.right ) * xScale; + float insetL = winCrop.left * xScale; + float insetT = winCrop.top * yScale; + float insetR = (winWidth - winCrop.right) * xScale; float insetB = (winHeight - winCrop.bottom) * yScale; - crop.left += insetL; - crop.top += insetT; - crop.right -= insetR; + crop.left += insetL; + crop.top += insetT; + crop.right -= insetR; crop.bottom -= insetB; return crop; } -#ifdef USE_HWC2 void Layer::setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z) -#else -void Layer::setGeometry( - const sp<const DisplayDevice>& hw, - HWComposer::HWCLayerInterface& layer) -#endif { -#ifdef USE_HWC2 const auto hwcId = displayDevice->getHwcDisplayId(); - auto& hwcInfo = mHwcLayers[hwcId]; -#else - layer.setDefaultState(); -#endif + auto& hwcInfo = getBE().mHwcLayers[hwcId]; // enable this layer -#ifdef USE_HWC2 hwcInfo.forceClientComposition = false; if (isSecure() && !displayDevice->isSecure()) { @@ -671,33 +496,20 @@ void Layer::setGeometry( } auto& hwcLayer = hwcInfo.layer; -#else - layer.setSkip(false); - - if (isSecure() && !hw->isSecure()) { - layer.setSkip(true); - } -#endif // this gives us only the "orientation" component of the transform const State& s(getDrawingState()); -#ifdef USE_HWC2 auto blendMode = HWC2::BlendMode::None; if (!isOpaque(s) || getAlpha() != 1.0f) { - blendMode = mPremultipliedAlpha ? - HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage; + blendMode = + mPremultipliedAlpha ? HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage; } auto error = hwcLayer->setBlendMode(blendMode); - ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set blend mode %s:" - " %s (%d)", mName.string(), to_string(blendMode).c_str(), - to_string(error).c_str(), static_cast<int32_t>(error)); -#else - if (!isOpaque(s) || getAlpha() != 0xFF) { - layer.setBlending(mPremultipliedAlpha ? - HWC_BLENDING_PREMULT : - HWC_BLENDING_COVERAGE); - } -#endif + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set blend mode %s:" + " %s (%d)", + mName.string(), to_string(blendMode).c_str(), to_string(error).c_str(), + static_cast<int32_t>(error)); // apply the layer's transform, followed by the display's global transform // here we're guaranteed that the layer's transform preserves rects @@ -706,11 +518,7 @@ void Layer::setGeometry( if (!s.crop.isEmpty()) { Rect activeCrop(s.crop); activeCrop = t.transform(activeCrop); -#ifdef USE_HWC2 - if(!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) { -#else - if(!activeCrop.intersect(hw->getViewport(), &activeCrop)) { -#endif + if (!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) { activeCrop.clear(); } activeCrop = t.inverse().transform(activeCrop, true); @@ -720,28 +528,25 @@ void Layer::setGeometry( // transform.inverse().transform(transform.transform(Rect)) != Rect // in which case we need to make sure the final rect is clipped to the // display bounds. - if(!activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop)) { + if (!activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop)) { activeCrop.clear(); } // mark regions outside the crop as transparent activeTransparentRegion.orSelf(Rect(0, 0, s.active.w, activeCrop.top)); - activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom, - s.active.w, s.active.h)); - activeTransparentRegion.orSelf(Rect(0, activeCrop.top, - activeCrop.left, activeCrop.bottom)); - activeTransparentRegion.orSelf(Rect(activeCrop.right, activeCrop.top, - s.active.w, activeCrop.bottom)); + activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom, s.active.w, s.active.h)); + activeTransparentRegion.orSelf(Rect(0, activeCrop.top, activeCrop.left, activeCrop.bottom)); + activeTransparentRegion.orSelf( + Rect(activeCrop.right, activeCrop.top, s.active.w, activeCrop.bottom)); } // computeBounds returns a FloatRect to provide more accuracy during the // transformation. We then round upon constructing 'frame'. Rect frame{t.transform(computeBounds(activeTransparentRegion))}; if (!s.finalCrop.isEmpty()) { - if(!frame.intersect(s.finalCrop, &frame)) { + if (!frame.intersect(s.finalCrop, &frame)) { frame.clear(); } } -#ifdef USE_HWC2 if (!frame.intersect(displayDevice->getViewport(), &frame)) { frame.clear(); } @@ -749,10 +554,9 @@ void Layer::setGeometry( Rect transformedFrame = tr.transform(frame); error = hwcLayer->setDisplayFrame(transformedFrame); if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)", - mName.string(), transformedFrame.left, transformedFrame.top, - transformedFrame.right, transformedFrame.bottom, - to_string(error).c_str(), static_cast<int32_t>(error)); + ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)", mName.string(), + transformedFrame.left, transformedFrame.top, transformedFrame.right, + transformedFrame.bottom, to_string(error).c_str(), static_cast<int32_t>(error)); } else { hwcInfo.displayFrame = transformedFrame; } @@ -761,45 +565,38 @@ void Layer::setGeometry( error = hwcLayer->setSourceCrop(sourceCrop); if (error != HWC2::Error::None) { ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: " - "%s (%d)", mName.string(), sourceCrop.left, sourceCrop.top, - sourceCrop.right, sourceCrop.bottom, to_string(error).c_str(), - static_cast<int32_t>(error)); + "%s (%d)", + mName.string(), sourceCrop.left, sourceCrop.top, sourceCrop.right, sourceCrop.bottom, + to_string(error).c_str(), static_cast<int32_t>(error)); } else { hwcInfo.sourceCrop = sourceCrop; } - float alpha = getAlpha(); + float alpha = static_cast<float>(getAlpha()); error = hwcLayer->setPlaneAlpha(alpha); - ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set plane alpha %.3f: " - "%s (%d)", mName.string(), alpha, to_string(error).c_str(), - static_cast<int32_t>(error)); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set plane alpha %.3f: " + "%s (%d)", + mName.string(), alpha, to_string(error).c_str(), static_cast<int32_t>(error)); error = hwcLayer->setZOrder(z); - ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set Z %u: %s (%d)", - mName.string(), z, to_string(error).c_str(), - static_cast<int32_t>(error)); + ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set Z %u: %s (%d)", mName.string(), z, + to_string(error).c_str(), static_cast<int32_t>(error)); int type = s.type; int appId = s.appId; sp<Layer> parent = mDrawingParent.promote(); if (parent.get()) { auto& parentState = parent->getDrawingState(); - type = parentState.type; - appId = parentState.appId; + if (parentState.type >= 0 || parentState.appId >= 0) { + type = parentState.type; + appId = parentState.appId; + } } error = hwcLayer->setInfo(type, appId); - ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", - mName.string(), static_cast<int32_t>(error)); -#else - if (!frame.intersect(hw->getViewport(), &frame)) { - frame.clear(); - } - const Transform& tr(hw->getTransform()); - layer.setFrame(tr.transform(frame)); - layer.setCrop(computeCrop(hw)); - layer.setPlaneAlpha(getAlpha()); -#endif + ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", mName.string(), + static_cast<int32_t>(error)); /* * Transformations are applied in this order: @@ -817,12 +614,10 @@ void Layer::setGeometry( * the code below applies the primary display's inverse transform to the * buffer */ - uint32_t invTransform = - DisplayDevice::getPrimaryDisplayOrientationTransform(); + uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); // calculate the inverse transform if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { - invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | - NATIVE_WINDOW_TRANSFORM_FLIP_H; + invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H; } /* @@ -836,163 +631,43 @@ void Layer::setGeometry( // this gives us only the "orientation" component of the transform const uint32_t orientation = transform.getOrientation(); -#ifdef USE_HWC2 if (orientation & Transform::ROT_INVALID) { // we can only handle simple transformation hwcInfo.forceClientComposition = true; } else { auto transform = static_cast<HWC2::Transform>(orientation); + hwcInfo.transform = transform; auto error = hwcLayer->setTransform(transform); - ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set transform %s: " - "%s (%d)", mName.string(), to_string(transform).c_str(), - to_string(error).c_str(), static_cast<int32_t>(error)); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set transform %s: " + "%s (%d)", + mName.string(), to_string(transform).c_str(), to_string(error).c_str(), + static_cast<int32_t>(error)); } -#else - if (orientation & Transform::ROT_INVALID) { - // we can only handle simple transformation - layer.setSkip(true); - } else { - layer.setTransform(orientation); - } -#endif } -#ifdef USE_HWC2 void Layer::forceClientComposition(int32_t hwcId) { - if (mHwcLayers.count(hwcId) == 0) { + if (getBE().mHwcLayers.count(hwcId) == 0) { ALOGE("forceClientComposition: no HWC layer found (%d)", hwcId); return; } - mHwcLayers[hwcId].forceClientComposition = true; + getBE().mHwcLayers[hwcId].forceClientComposition = true; } -void Layer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) { - // Apply this display's projection's viewport to the visible region - // before giving it to the HWC HAL. - const Transform& tr = displayDevice->getTransform(); - const auto& viewport = displayDevice->getViewport(); - Region visible = tr.transform(visibleRegion.intersect(viewport)); - auto hwcId = displayDevice->getHwcDisplayId(); - auto& hwcInfo = mHwcLayers[hwcId]; - auto& hwcLayer = hwcInfo.layer; - auto error = hwcLayer->setVisibleRegion(visible); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast<int32_t>(error)); - visible.dump(LOG_TAG); - } - - error = hwcLayer->setSurfaceDamage(surfaceDamageRegion); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set surface damage: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast<int32_t>(error)); - surfaceDamageRegion.dump(LOG_TAG); - } - - // Sideband layers - if (mSidebandStream.get()) { - setCompositionType(hwcId, HWC2::Composition::Sideband); - ALOGV("[%s] Requesting Sideband composition", mName.string()); - error = hwcLayer->setSidebandStream(mSidebandStream->handle()); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", - mName.string(), mSidebandStream->handle(), - to_string(error).c_str(), static_cast<int32_t>(error)); - } - return; - } - - // Client layers - if (hwcInfo.forceClientComposition || - (mActiveBuffer != nullptr && mActiveBuffer->handle == nullptr)) { - ALOGV("[%s] Requesting Client composition", mName.string()); - setCompositionType(hwcId, HWC2::Composition::Client); - return; - } - - // SolidColor layers - if (mActiveBuffer == nullptr) { - setCompositionType(hwcId, HWC2::Composition::SolidColor); - - // For now, we only support black for DimLayer - error = hwcLayer->setColor({0, 0, 0, 255}); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set color: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast<int32_t>(error)); - } - - // Clear out the transform, because it doesn't make sense absent a - // source buffer - error = hwcLayer->setTransform(HWC2::Transform::None); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to clear transform: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast<int32_t>(error)); - } - - return; - } - - // Device or Cursor layers - if (mPotentialCursor) { - ALOGV("[%s] Requesting Cursor composition", mName.string()); - setCompositionType(hwcId, HWC2::Composition::Cursor); - } else { - ALOGV("[%s] Requesting Device composition", mName.string()); - setCompositionType(hwcId, HWC2::Composition::Device); - } - - ALOGV("setPerFrameData: dataspace = %d", mCurrentState.dataSpace); - error = hwcLayer->setDataspace(mCurrentState.dataSpace); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), - mCurrentState.dataSpace, to_string(error).c_str(), - static_cast<int32_t>(error)); +bool Layer::getForceClientComposition(int32_t hwcId) { + if (getBE().mHwcLayers.count(hwcId) == 0) { + ALOGE("getForceClientComposition: no HWC layer found (%d)", hwcId); + return false; } - uint32_t hwcSlot = 0; - sp<GraphicBuffer> hwcBuffer; - hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, - &hwcSlot, &hwcBuffer); - - auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence(); - error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), - mActiveBuffer->handle, to_string(error).c_str(), - static_cast<int32_t>(error)); - } -} - -#else -void Layer::setPerFrameData(const sp<const DisplayDevice>& hw, - HWComposer::HWCLayerInterface& layer) { - // we have to set the visible region on every frame because - // we currently free it during onLayerDisplayed(), which is called - // after HWComposer::commit() -- every frame. - // Apply this display's projection's viewport to the visible region - // before giving it to the HWC HAL. - const Transform& tr = hw->getTransform(); - Region visible = tr.transform(visibleRegion.intersect(hw->getViewport())); - layer.setVisibleRegionScreen(visible); - layer.setSurfaceDamage(surfaceDamageRegion); - mIsGlesComposition = (layer.getCompositionType() == HWC_FRAMEBUFFER); - - if (mSidebandStream.get()) { - layer.setSidebandStream(mSidebandStream); - } else { - // NOTE: buffer can be NULL if the client never drew into this - // layer yet, or if we ran out of memory - layer.setBuffer(mActiveBuffer); - } + return getBE().mHwcLayers[hwcId].forceClientComposition; } -#endif -#ifdef USE_HWC2 void Layer::updateCursorPosition(const sp<const DisplayDevice>& displayDevice) { auto hwcId = displayDevice->getHwcDisplayId(); - if (mHwcLayers.count(hwcId) == 0 || - getCompositionType(hwcId) != HWC2::Composition::Cursor) { + if (getBE().mHwcLayers.count(hwcId) == 0 || + getCompositionType(hwcId) != HWC2::Composition::Cursor) { return; } @@ -1015,285 +690,62 @@ void Layer::updateCursorPosition(const sp<const DisplayDevice>& displayDevice) { auto& displayTransform(displayDevice->getTransform()); auto position = displayTransform.transform(frame); - auto error = mHwcLayers[hwcId].layer->setCursorPosition(position.left, - position.top); - ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set cursor position " - "to (%d, %d): %s (%d)", mName.string(), position.left, - position.top, to_string(error).c_str(), - static_cast<int32_t>(error)); -} -#else -void Layer::setAcquireFence(const sp<const DisplayDevice>& /* hw */, - HWComposer::HWCLayerInterface& layer) { - int fenceFd = -1; - - // TODO: there is a possible optimization here: we only need to set the - // acquire fence the first time a new buffer is acquired on EACH display. - - if (layer.getCompositionType() == HWC_OVERLAY || layer.getCompositionType() == HWC_CURSOR_OVERLAY) { - sp<Fence> fence = mSurfaceFlingerConsumer->getCurrentFence(); - if (fence->isValid()) { - fenceFd = fence->dup(); - if (fenceFd == -1) { - ALOGW("failed to dup layer fence, skipping sync: %d", errno); - } - } - } - layer.setAcquireFenceFd(fenceFd); + auto error = getBE().mHwcLayers[hwcId].layer->setCursorPosition(position.left, + position.top); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set cursor position " + "to (%d, %d): %s (%d)", + mName.string(), position.left, position.top, to_string(error).c_str(), + static_cast<int32_t>(error)); } -Rect Layer::getPosition( - const sp<const DisplayDevice>& hw) -{ - // this gives us only the "orientation" component of the transform - const State& s(getCurrentState()); - - // apply the layer's transform, followed by the display's global transform - // here we're guaranteed that the layer's transform preserves rects - Rect win(s.active.w, s.active.h); - if (!s.crop.isEmpty()) { - win.intersect(s.crop, &win); - } - // subtract the transparent region and snap to the bounds - Rect bounds = reduce(win, s.activeTransparentRegion); - Rect frame(getTransform().transform(bounds)); - frame.intersect(hw->getViewport(), &frame); - if (!s.finalCrop.isEmpty()) { - frame.intersect(s.finalCrop, &frame); - } - const Transform& tr(hw->getTransform()); - return Rect(tr.transform(frame)); -} -#endif - // --------------------------------------------------------------------------- // drawing... // --------------------------------------------------------------------------- -void Layer::draw(const sp<const DisplayDevice>& hw, const Region& clip) const { - onDraw(hw, clip, false); +void Layer::draw(const RenderArea& renderArea, const Region& clip) const { + onDraw(renderArea, clip, false); } -void Layer::draw(const sp<const DisplayDevice>& hw, - bool useIdentityTransform) const { - onDraw(hw, Region(hw->bounds()), useIdentityTransform); +void Layer::draw(const RenderArea& renderArea, bool useIdentityTransform) const { + onDraw(renderArea, Region(renderArea.getBounds()), useIdentityTransform); } -void Layer::draw(const sp<const DisplayDevice>& hw) const { - onDraw(hw, Region(hw->bounds()), false); -} - -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); -} - -/* - * onDraw will draw the current layer onto the presentable buffer - */ -void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip, - bool useIdentityTransform) const -{ - ATRACE_CALL(); - - if (CC_UNLIKELY(mActiveBuffer == 0)) { - // the texture has not been created yet, this Layer has - // in fact never been drawn into. This happens frequently with - // SurfaceView because the WindowManager can't know when the client - // has drawn the first time. - - // If there is nothing under us, we paint the screen in black, otherwise - // we just skip this update. - - // figure out if there is something below us - Region under; - bool finished = false; - mFlinger->mDrawingState.traverseInZOrder([&](Layer* layer) { - if (finished || layer == static_cast<Layer const*>(this)) { - finished = true; - return; - } - under.orSelf( hw->getTransform().transform(layer->visibleRegion) ); - }); - // if not everything below us is covered, we plug the holes! - Region holes(clip.subtract(under)); - if (!holes.isEmpty()) { - clearWithOpenGL(hw, 0, 0, 0, 1); - } - return; - } - - // Bind the current buffer to the GL texture, and wait for it to be - // ready for us to draw into. - status_t err = mSurfaceFlingerConsumer->bindTextureImage(); - if (err != NO_ERROR) { - ALOGW("onDraw: bindTextureImage failed (err=%d)", err); - // Go ahead and draw the buffer anyway; no matter what we do the screen - // is probably going to have something visibly wrong. - } - - bool blackOutLayer = isProtected() || (isSecure() && !hw->isSecure()); - - RenderEngine& engine(mFlinger->getRenderEngine()); - - if (!blackOutLayer) { - // TODO: we could be more subtle with isFixedSize() - const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize(); - - // Query the texture matrix given our current filtering mode. - float textureMatrix[16]; - mSurfaceFlingerConsumer->setFilteringEnabled(useFiltering); - mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix); - - if (getTransformToDisplayInverse()) { - - /* - * the code below applies the primary display's inverse transform to - * the texture transform - */ - uint32_t transform = - DisplayDevice::getPrimaryDisplayOrientationTransform(); - 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)); - } - - // Set things up for texturing. - mTexture.setDimensions(mActiveBuffer->getWidth(), mActiveBuffer->getHeight()); - mTexture.setFiltering(useFiltering); - mTexture.setMatrix(textureMatrix); - - engine.setupLayerTexturing(mTexture); - } else { - engine.setupLayerBlackedOut(); - } - drawWithOpenGL(hw, useIdentityTransform); - engine.disableTexturing(); +void Layer::draw(const RenderArea& renderArea) const { + onDraw(renderArea, Region(renderArea.getBounds()), false); } - -void Layer::clearWithOpenGL(const sp<const DisplayDevice>& hw, - float red, float green, float blue, - float alpha) const -{ - RenderEngine& engine(mFlinger->getRenderEngine()); - computeGeometry(hw, mMesh, false); +void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue, + float alpha) const { + auto& engine(mFlinger->getRenderEngine()); + computeGeometry(renderArea, getBE().mMesh, false); engine.setupFillWithColor(red, green, blue, alpha); - engine.drawMesh(mMesh); + engine.drawMesh(getBE().mMesh); } -void Layer::clearWithOpenGL( - const sp<const DisplayDevice>& hw) const { - clearWithOpenGL(hw, 0,0,0,0); +void Layer::clearWithOpenGL(const RenderArea& renderArea) const { + clearWithOpenGL(renderArea, 0, 0, 0, 0); } -void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw, - bool useIdentityTransform) const { - const State& s(getDrawingState()); - - computeGeometry(hw, mMesh, useIdentityTransform); - - /* - * NOTE: the way we compute the texture coordinates here produces - * different results than when we take the HWC path -- in the later case - * the "source crop" is rounded to texel boundaries. - * This can produce significantly different results when the texture - * is scaled by a large amount. - * - * The GL code below is more logical (imho), and the difference with - * HWC is due to a limitation of the HWC API to integers -- a question - * is suspend is whether we should ignore this problem or revert to - * GL composition when a buffer scaling is applied (maybe with some - * minimal value)? Or, we could make GL behave like HWC -- but this feel - * like more of a hack. - */ - const Rect bounds{computeBounds()}; // Rounds from FloatRect - - Transform t = getTransform(); - Rect win = bounds; - if (!s.finalCrop.isEmpty()) { - win = t.transform(win); - if (!win.intersect(s.finalCrop, &win)) { - win.clear(); - } - win = t.inverse().transform(win); - if (!win.intersect(bounds, &win)) { - win.clear(); - } - } - - float left = float(win.left) / float(s.active.w); - float top = float(win.top) / float(s.active.h); - float right = float(win.right) / float(s.active.w); - float bottom = float(win.bottom) / float(s.active.h); - - // TODO: we probably want to generate the texture coords with the mesh - // here we assume that we only have 4 vertices - Mesh::VertexArray<vec2> texCoords(mMesh.getTexCoordArray<vec2>()); - texCoords[0] = vec2(left, 1.0f - top); - texCoords[1] = vec2(left, 1.0f - bottom); - texCoords[2] = vec2(right, 1.0f - bottom); - texCoords[3] = vec2(right, 1.0f - top); - - RenderEngine& engine(mFlinger->getRenderEngine()); - engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), getAlpha()); -#ifdef USE_HWC2 - engine.setSourceDataSpace(mCurrentState.dataSpace); -#endif - engine.drawMesh(mMesh); - engine.disableBlending(); -} - -#ifdef USE_HWC2 -void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, - bool callIntoHwc) { - if (mHwcLayers.count(hwcId) == 0) { +void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc) { + if (getBE().mHwcLayers.count(hwcId) == 0) { ALOGE("setCompositionType called without a valid HWC layer"); return; } - auto& hwcInfo = mHwcLayers[hwcId]; + auto& hwcInfo = getBE().mHwcLayers[hwcId]; auto& hwcLayer = hwcInfo.layer; - ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(), - to_string(type).c_str(), static_cast<int>(callIntoHwc)); + ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(), to_string(type).c_str(), + static_cast<int>(callIntoHwc)); if (hwcInfo.compositionType != type) { ALOGV(" actually setting"); hwcInfo.compositionType = type; if (callIntoHwc) { auto error = hwcLayer->setCompositionType(type); - ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set " - "composition type %s: %s (%d)", mName.string(), - to_string(type).c_str(), to_string(error).c_str(), - static_cast<int32_t>(error)); + ALOGE_IF(error != HWC2::Error::None, + "[%s] Failed to set " + "composition type %s: %s (%d)", + mName.string(), to_string(type).c_str(), to_string(error).c_str(), + static_cast<int32_t>(error)); } } } @@ -1304,86 +756,27 @@ HWC2::Composition Layer::getCompositionType(int32_t hwcId) const { // have a HWC counterpart, then it will always be Client return HWC2::Composition::Client; } - if (mHwcLayers.count(hwcId) == 0) { + if (getBE().mHwcLayers.count(hwcId) == 0) { ALOGE("getCompositionType called with an invalid HWC layer"); return HWC2::Composition::Invalid; } - return mHwcLayers.at(hwcId).compositionType; + return getBE().mHwcLayers.at(hwcId).compositionType; } void Layer::setClearClientTarget(int32_t hwcId, bool clear) { - if (mHwcLayers.count(hwcId) == 0) { + if (getBE().mHwcLayers.count(hwcId) == 0) { ALOGE("setClearClientTarget called without a valid HWC layer"); return; } - mHwcLayers[hwcId].clearClientTarget = clear; + getBE().mHwcLayers[hwcId].clearClientTarget = clear; } bool Layer::getClearClientTarget(int32_t hwcId) const { - if (mHwcLayers.count(hwcId) == 0) { + if (getBE().mHwcLayers.count(hwcId) == 0) { ALOGE("getClearClientTarget called without a valid HWC layer"); return false; } - return mHwcLayers.at(hwcId).clearClientTarget; -} -#endif - -uint32_t Layer::getProducerStickyTransform() const { - int producerStickyTransform = 0; - int ret = mProducer->query(NATIVE_WINDOW_STICKY_TRANSFORM, &producerStickyTransform); - if (ret != OK) { - ALOGW("%s: Error %s (%d) while querying window sticky transform.", __FUNCTION__, - strerror(-ret), ret); - return 0; - } - return static_cast<uint32_t>(producerStickyTransform); -} - -bool Layer::latchUnsignaledBuffers() { - static bool propertyLoaded = false; - static bool latch = false; - static std::mutex mutex; - std::lock_guard<std::mutex> lock(mutex); - if (!propertyLoaded) { - char value[PROPERTY_VALUE_MAX] = {}; - property_get("debug.sf.latch_unsignaled", value, "0"); - latch = atoi(value); - propertyLoaded = true; - } - return latch; -} - -uint64_t Layer::getHeadFrameNumber() const { - Mutex::Autolock lock(mQueueItemLock); - if (!mQueueItems.empty()) { - return mQueueItems[0].mFrameNumber; - } else { - return mCurrentFrameNumber; - } -} - -bool Layer::headFenceHasSignaled() const { -#ifdef USE_HWC2 - if (latchUnsignaledBuffers()) { - return true; - } - - Mutex::Autolock lock(mQueueItemLock); - if (mQueueItems.empty()) { - return true; - } - if (mQueueItems[0].mIsDroppable) { - // Even though this buffer's fence may not have signaled yet, it could - // be replaced by another buffer before it has a chance to, which means - // that it's possible to get into a situation where a buffer is never - // able to be latched. To avoid this, grab this buffer anyway. - return true; - } - return mQueueItems[0].mFenceTime->getSignalTime() != - Fence::SIGNAL_TIME_PENDING; -#else - return true; -#endif + return getBE().mHwcLayers.at(hwcId).clearClientTarget; } bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) { @@ -1406,28 +799,6 @@ bool Layer::getFiltering() const { return mFiltering; } -// 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 Layer::getOpacityForFormat(uint32_t format) { - if (HARDWARE_IS_DEVICE_FORMAT(format)) { - return true; - } - switch (format) { - case HAL_PIXEL_FORMAT_RGBA_8888: - case HAL_PIXEL_FORMAT_BGRA_8888: - case HAL_PIXEL_FORMAT_RGBA_FP16: - case HAL_PIXEL_FORMAT_RGBA_1010102: - return false; - } - // in all other case, we have no blending (also for unknown formats) - return true; -} - // ---------------------------------------------------------------------------- // local state // ---------------------------------------------------------------------------- @@ -1447,12 +818,11 @@ static void boundPoint(vec2* point, const Rect& crop) { } } -void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh, - bool useIdentityTransform) const -{ +void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh, + bool useIdentityTransform) const { const Layer::State& s(getDrawingState()); - const Transform hwTransform(hw->getTransform()); - const uint32_t hw_h = hw->getHeight(); + const Transform renderAreaTransform(renderArea.getTransform()); + const uint32_t height = renderArea.getHeight(); FloatRect win = computeBounds(); vec2 lt = vec2(win.left, win.top); @@ -1476,53 +846,20 @@ void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh, } Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>()); - position[0] = hwTransform.transform(lt); - position[1] = hwTransform.transform(lb); - position[2] = hwTransform.transform(rb); - position[3] = hwTransform.transform(rt); - for (size_t i=0 ; i<4 ; i++) { - position[i].y = hw_h - position[i].y; + position[0] = renderAreaTransform.transform(lt); + position[1] = renderAreaTransform.transform(lb); + position[2] = renderAreaTransform.transform(rb); + position[3] = renderAreaTransform.transform(rt); + for (size_t i = 0; i < 4; i++) { + position[i].y = height - position[i].y; } } -bool Layer::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) && (mActiveBuffer == 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) || mCurrentOpacity; -} - -bool Layer::isSecure() const -{ +bool Layer::isSecure() const { const Layer::State& s(mDrawingState); return (s.flags & layer_state_t::eLayerSecure); } -bool Layer::isProtected() const -{ - const sp<GraphicBuffer>& activeBuffer(mActiveBuffer); - return (activeBuffer != 0) && - (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED); -} - -bool Layer::isFixedSize() const { - return getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE; -} - -bool Layer::isCropped() const { - return !mCurrentCrop.isEmpty(); -} - -bool Layer::needsFiltering(const sp<const DisplayDevice>& hw) const { - return mNeedsFiltering || hw->needsFiltering(); -} - void Layer::setVisibleRegion(const Region& visibleRegion) { // always called from main thread this->visibleRegion = visibleRegion; @@ -1533,12 +870,17 @@ void Layer::setCoveredRegion(const Region& coveredRegion) { this->coveredRegion = coveredRegion; } -void Layer::setVisibleNonTransparentRegion(const Region& - setVisibleNonTransparentRegion) { +void Layer::setVisibleNonTransparentRegion(const Region& setVisibleNonTransparentRegion) { // always called from main thread this->visibleNonTransparentRegion = setVisibleNonTransparentRegion; } +void Layer::clearVisibilityRegions() { + visibleRegion.clear(); + visibleNonTransparentRegion.clear(); + coveredRegion.clear(); +} + // ---------------------------------------------------------------------------- // transaction // ---------------------------------------------------------------------------- @@ -1559,8 +901,7 @@ void Layer::pushPendingState() { // to be applied as per normal (no synchronization). mCurrentState.barrierLayer = nullptr; } else { - auto syncPoint = std::make_shared<SyncPoint>( - mCurrentState.frameNumber); + auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber); if (barrierLayer->addSyncPoint(syncPoint)) { mRemoteSyncPoints.push_back(std::move(syncPoint)); } else { @@ -1579,10 +920,7 @@ void Layer::pushPendingState() { } void Layer::popPendingState(State* stateToCommit) { - auto oldFlags = stateToCommit->flags; *stateToCommit = mPendingStates[0]; - stateToCommit->flags = (oldFlags & ~stateToCommit->mask) | - (stateToCommit->flags & stateToCommit->mask); mPendingStates.removeAt(0); ATRACE_INT(mTransactionName.string(), mPendingStates.size()); @@ -1602,10 +940,8 @@ bool Layer::applyPendingStates(State* stateToCommit) { continue; } - if (mRemoteSyncPoints.front()->getFrameNumber() != - mPendingStates[0].frameNumber) { - ALOGE("[%s] Unexpected sync point frame number found", - mName.string()); + if (mRemoteSyncPoints.front()->getFrameNumber() != mPendingStates[0].frameNumber) { + ALOGE("[%s] Unexpected sync point frame number found", mName.string()); // Signal our end of the sync point and then dispose of it mRemoteSyncPoints.front()->setTransactionApplied(); @@ -1641,17 +977,6 @@ bool Layer::applyPendingStates(State* stateToCommit) { return stateUpdateAvailable; } -void Layer::notifyAvailableFrames() { - auto headFrameNumber = getHeadFrameNumber(); - bool headFenceSignaled = headFenceHasSignaled(); - Mutex::Autolock lock(mLocalSyncPointMutex); - for (auto& point : mLocalSyncPoints) { - if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled) { - point->setFrameAvailable(); - } - } -} - uint32_t Layer::doTransaction(uint32_t flags) { ATRACE_CALL(); @@ -1663,59 +988,50 @@ uint32_t Layer::doTransaction(uint32_t flags) { const Layer::State& s(getDrawingState()); - const bool sizeChanged = (c.requested.w != s.requested.w) || - (c.requested.h != s.requested.h); + const bool sizeChanged = (c.requested.w != s.requested.w) || (c.requested.h != s.requested.h); if (sizeChanged) { // the size changed, we need to ask our client to request a new buffer ALOGD_IF(DEBUG_RESIZE, - "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n" - " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" - " requested={ wh={%4u,%4u} }}\n" - " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" - " requested={ wh={%4u,%4u} }}\n", - this, getName().string(), mCurrentTransform, - getEffectiveScalingMode(), - c.active.w, c.active.h, - c.crop.left, - c.crop.top, - c.crop.right, - c.crop.bottom, - c.crop.getWidth(), - c.crop.getHeight(), - c.requested.w, c.requested.h, - s.active.w, s.active.h, - s.crop.left, - s.crop.top, - s.crop.right, - s.crop.bottom, - s.crop.getWidth(), - s.crop.getHeight(), - s.requested.w, s.requested.h); + "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n" + " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" + " requested={ wh={%4u,%4u} }}\n" + " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" + " requested={ wh={%4u,%4u} }}\n", + this, getName().string(), mCurrentTransform, + getEffectiveScalingMode(), c.active.w, c.active.h, c.crop.left, c.crop.top, + c.crop.right, c.crop.bottom, c.crop.getWidth(), c.crop.getHeight(), c.requested.w, + c.requested.h, s.active.w, s.active.h, s.crop.left, s.crop.top, s.crop.right, + s.crop.bottom, s.crop.getWidth(), s.crop.getHeight(), s.requested.w, + s.requested.h); // record the new size, form this point on, when the client request // a buffer, it'll get the new size. - mSurfaceFlingerConsumer->setDefaultBufferSize( - c.requested.w, c.requested.h); - } - - const bool resizePending = (c.requested.w != c.active.w) || - (c.requested.h != c.active.h); + setDefaultBufferSize(c.requested.w, c.requested.h); + } + + // Don't let Layer::doTransaction update the drawing state + // if we have a pending resize, unless we are in fixed-size mode. + // the drawing state will be updated only once we receive a buffer + // with the correct size. + // + // In particular, we want to make sure the clip (which is part + // of the geometry state) is latched together with the size but is + // latched immediately when no resizing is involved. + // + // If a sideband stream is attached, however, we want to skip this + // optimization so that transactions aren't missed when a buffer + // never arrives + // + // In the case that we don't have a buffer we ignore other factors + // and avoid entering the resizePending state. At a high level the + // resizePending state is to avoid applying the state of the new buffer + // to the old buffer. However in the state where we don't have an old buffer + // there is no such concern but we may still be being used as a parent layer. + const bool resizePending = ((c.requested.w != c.active.w) || (c.requested.h != c.active.h)) && + (getBE().compositionInfo.mBuffer != nullptr); if (!isFixedSize()) { - if (resizePending && mSidebandStream == NULL) { - // don't let Layer::doTransaction update the drawing state - // if we have a pending resize, unless we are in fixed-size mode. - // the drawing state will be updated only once we receive a buffer - // with the correct size. - // - // in particular, we want to make sure the clip (which is part - // of the geometry state) is latched together with the size but is - // latched immediately when no resizing is involved. - // - // If a sideband stream is attached, however, we want to skip this - // optimization so that transactions aren't missed when a buffer - // never arrives - + if (resizePending && getBE().compositionInfo.hwc.sidebandStream == nullptr) { flags |= eDontUpdateGeometryState; } } @@ -1762,8 +1078,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { // we may use linear filtering, if the matrix scales us const uint8_t type = c.active.transform.getType(); - mNeedsFiltering = (!c.active.transform.preserveRects() || - (type >= Transform::SCALE)); + mNeedsFiltering = (!c.active.transform.preserveRects() || (type >= Transform::SCALE)); } // If the layer is hidden, signal and clear out all local sync points so @@ -1821,13 +1136,27 @@ bool Layer::setChildLayer(const sp<Layer>& childLayer, int32_t z) { if (childLayer->setLayer(z)) { mCurrentChildren.removeAt(idx); mCurrentChildren.add(childLayer); + return true; } - return true; + return false; } -bool Layer::setLayer(int32_t z) { - if (mCurrentState.z == z) +bool Layer::setChildRelativeLayer(const sp<Layer>& childLayer, + const sp<IBinder>& relativeToHandle, int32_t relativeZ) { + ssize_t idx = mCurrentChildren.indexOf(childLayer); + if (idx < 0) { return false; + } + if (childLayer->setRelativeLayer(relativeToHandle, relativeZ)) { + mCurrentChildren.removeAt(idx); + mCurrentChildren.add(childLayer); + return true; + } + return false; +} + +bool Layer::setLayer(int32_t z) { + if (mCurrentState.z == z && !usingRelativeZ(LayerVector::StateSet::Current)) return false; mCurrentState.sequence++; mCurrentState.z = z; mCurrentState.modified = true; @@ -1858,7 +1187,7 @@ void Layer::addZOrderRelative(const wp<Layer>& relative) { setTransactionFlags(eTransactionNeeded); } -bool Layer::setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t z) { +bool Layer::setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ) { sp<Handle> handle = static_cast<Handle*>(relativeToHandle.get()); if (handle == nullptr) { return false; @@ -1868,10 +1197,19 @@ bool Layer::setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t z) { return false; } + if (mCurrentState.z == relativeZ && usingRelativeZ(LayerVector::StateSet::Current) && + mCurrentState.zOrderRelativeOf == relative) { + return false; + } + mCurrentState.sequence++; mCurrentState.modified = true; - mCurrentState.z = z; + mCurrentState.z = relativeZ; + auto oldZOrderRelativeOf = mCurrentState.zOrderRelativeOf.promote(); + if (oldZOrderRelativeOf != nullptr) { + oldZOrderRelativeOf->removeZOrderRelative(this); + } mCurrentState.zOrderRelativeOf = relative; relative->addZOrderRelative(this); @@ -1881,31 +1219,39 @@ bool Layer::setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t z) { } bool Layer::setSize(uint32_t w, uint32_t h) { - if (mCurrentState.requested.w == w && mCurrentState.requested.h == h) - return false; + if (mCurrentState.requested.w == w && mCurrentState.requested.h == h) return false; mCurrentState.requested.w = w; mCurrentState.requested.h = h; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } -#ifdef USE_HWC2 bool Layer::setAlpha(float alpha) { -#else -bool Layer::setAlpha(uint8_t alpha) { -#endif - if (mCurrentState.alpha == alpha) + if (mCurrentState.color.a == alpha) return false; + mCurrentState.sequence++; + mCurrentState.color.a = alpha; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool Layer::setColor(const half3& color) { + if (color.r == mCurrentState.color.r && color.g == mCurrentState.color.g && + color.b == mCurrentState.color.b) return false; + mCurrentState.sequence++; - mCurrentState.alpha = alpha; + mCurrentState.color.r = color.r; + mCurrentState.color.g = color.g; + mCurrentState.color.b = color.b; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } + bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) { mCurrentState.sequence++; - mCurrentState.requested.transform.set( - matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); + mCurrentState.requested.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; @@ -1918,19 +1264,16 @@ bool Layer::setTransparentRegionHint(const Region& transparent) { } bool Layer::setFlags(uint8_t flags, uint8_t mask) { const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask); - if (mCurrentState.flags == newFlags) - return false; + if (mCurrentState.flags == newFlags) return false; mCurrentState.sequence++; mCurrentState.flags = newFlags; - mCurrentState.mask = mask; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setCrop(const Rect& crop, bool immediate) { - if (mCurrentState.requestedCrop == crop) - return false; + if (mCurrentState.requestedCrop == crop) return false; mCurrentState.sequence++; mCurrentState.requestedCrop = crop; if (immediate && !mFreezeGeometryUpdates) { @@ -1944,8 +1287,7 @@ bool Layer::setCrop(const Rect& crop, bool immediate) { } bool Layer::setFinalCrop(const Rect& crop, bool immediate) { - if (mCurrentState.requestedFinalCrop == crop) - return false; + if (mCurrentState.requestedFinalCrop == crop) return false; mCurrentState.sequence++; mCurrentState.requestedFinalCrop = crop; if (immediate && !mFreezeGeometryUpdates) { @@ -1959,51 +1301,28 @@ bool Layer::setFinalCrop(const Rect& crop, bool immediate) { } bool Layer::setOverrideScalingMode(int32_t scalingMode) { - if (scalingMode == mOverrideScalingMode) - return false; + if (scalingMode == mOverrideScalingMode) return false; mOverrideScalingMode = scalingMode; setTransactionFlags(eTransactionNeeded); return true; } -void Layer::setInfo(uint32_t type, uint32_t appId) { - mCurrentState.appId = appId; - mCurrentState.type = type; - mCurrentState.modified = true; - setTransactionFlags(eTransactionNeeded); -} - -uint32_t Layer::getEffectiveScalingMode() const { - if (mOverrideScalingMode >= 0) { - return mOverrideScalingMode; - } - return mCurrentScalingMode; -} - -bool Layer::setLayerStack(uint32_t layerStack) { - if (mCurrentState.layerStack == layerStack) - return false; - mCurrentState.sequence++; - mCurrentState.layerStack = layerStack; +void Layer::setInfo(int32_t type, int32_t appId) { + mCurrentState.appId = appId; + mCurrentState.type = type; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); - return true; } -bool Layer::setDataSpace(android_dataspace dataSpace) { - if (mCurrentState.dataSpace == dataSpace) - return false; +bool Layer::setLayerStack(uint32_t layerStack) { + if (mCurrentState.layerStack == layerStack) return false; mCurrentState.sequence++; - mCurrentState.dataSpace = dataSpace; + mCurrentState.layerStack = layerStack; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } -android_dataspace Layer::getDataSpace() const { - return mCurrentState.dataSpace; -} - uint32_t Layer::getLayerStack() const { auto p = mDrawingParent.promote(); if (p == nullptr) { @@ -2012,8 +1331,7 @@ uint32_t Layer::getLayerStack() const { return p->getLayerStack(); } -void Layer::deferTransactionUntil(const sp<Layer>& barrierLayer, - uint64_t frameNumber) { +void Layer::deferTransactionUntil(const sp<Layer>& barrierLayer, uint64_t frameNumber) { mCurrentState.barrierLayer = barrierLayer; mCurrentState.frameNumber = frameNumber; // We don't set eTransactionNeeded, because just receiving a deferral @@ -2025,124 +1343,16 @@ void Layer::deferTransactionUntil(const sp<Layer>& barrierLayer, mCurrentState.modified = false; } -void Layer::deferTransactionUntil(const sp<IBinder>& barrierHandle, - uint64_t frameNumber) { +void Layer::deferTransactionUntil(const sp<IBinder>& barrierHandle, uint64_t frameNumber) { sp<Handle> handle = static_cast<Handle*>(barrierHandle.get()); deferTransactionUntil(handle->owner.promote(), frameNumber); } -void Layer::useSurfaceDamage() { - if (mFlinger->mForceFullDamage) { - surfaceDamageRegion = Region::INVALID_REGION; - } else { - surfaceDamageRegion = mSurfaceFlingerConsumer->getSurfaceDamage(); - } -} - -void Layer::useEmptyDamage() { - surfaceDamageRegion.clear(); -} // ---------------------------------------------------------------------------- // pageflip handling... // ---------------------------------------------------------------------------- -bool Layer::shouldPresentNow(const DispSync& dispSync) const { - if (mSidebandStreamChanged || mAutoRefresh) { - return true; - } - - Mutex::Autolock lock(mQueueItemLock); - if (mQueueItems.empty()) { - return false; - } - auto timestamp = mQueueItems[0].mTimestamp; - nsecs_t expectedPresent = - mSurfaceFlingerConsumer->computeExpectedPresent(dispSync); - - // Ignore timestamps more than a second in the future - bool isPlausible = timestamp < (expectedPresent + s2ns(1)); - ALOGW_IF(!isPlausible, "[%s] Timestamp %" PRId64 " seems implausible " - "relative to expectedPresent %" PRId64, mName.string(), timestamp, - expectedPresent); - - bool isDue = timestamp < expectedPresent; - return isDue || !isPlausible; -} - -bool Layer::onPreComposition(nsecs_t refreshStartTime) { - if (mBufferLatched) { - Mutex::Autolock lock(mFrameEventHistoryMutex); - mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime); - } - mRefreshPending = false; - return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh; -} - -bool Layer::onPostComposition(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 (!mFrameLatencyNeeded) - return false; - - // Update mFrameEventHistory. - { - Mutex::Autolock lock(mFrameEventHistoryMutex); - mFrameEventHistory.addPostComposition(mCurrentFrameNumber, - glDoneFence, presentFence, compositorTiming); - } - - // Update mFrameTracker. - nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp(); - mFrameTracker.setDesiredPresentTime(desiredPresentTime); - - std::shared_ptr<FenceTime> frameReadyFence = - mSurfaceFlingerConsumer->getCurrentFenceTime(); - 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 (presentFence->isValid()) { - mFrameTracker.setActualPresentFence( - std::shared_ptr<FenceTime>(presentFence)); - } else { - // The HWC doesn't support present fences, so use the refresh - // timestamp instead. - mFrameTracker.setActualPresentTime( - mFlinger->getHwComposer().getRefreshTimestamp( - HWC_DISPLAY_PRIMARY)); - } - - mFrameTracker.advanceFrame(); - mFrameLatencyNeeded = false; - return true; -} - -#ifdef USE_HWC2 -void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) { - if (!mSurfaceFlingerConsumer->releasePendingBuffer()) { - return; - } - - auto releaseFenceTime = std::make_shared<FenceTime>( - mSurfaceFlingerConsumer->getPrevFinalReleaseFence()); - mReleaseTimeline.updateSignalTimes(); - mReleaseTimeline.push(releaseFenceTime); - - Mutex::Autolock lock(mFrameEventHistoryMutex); - if (mPreviousFrameNumber != 0) { - mFrameEventHistory.addRelease(mPreviousFrameNumber, - dequeueReadyTime, std::move(releaseFenceTime)); - } -} -#endif - bool Layer::isHiddenByPolicy() const { const Layer::State& s(mDrawingState); const auto& parent = mDrawingParent.promote(); @@ -2152,256 +1362,7 @@ bool Layer::isHiddenByPolicy() const { return s.flags & layer_state_t::eLayerHidden; } -bool Layer::isVisible() const { -#ifdef USE_HWC2 - return !(isHiddenByPolicy()) && getAlpha() > 0.0f - && (mActiveBuffer != NULL || mSidebandStream != NULL); -#else - return !(isHiddenByPolicy()) && getAlpha() - && (mActiveBuffer != NULL || mSidebandStream != NULL); -#endif -} - -bool Layer::allTransactionsSignaled() { - auto headFrameNumber = getHeadFrameNumber(); - bool matchingFramesFound = false; - bool allTransactionsApplied = true; - Mutex::Autolock lock(mLocalSyncPointMutex); - - for (auto& point : mLocalSyncPoints) { - if (point->getFrameNumber() > headFrameNumber) { - break; - } - matchingFramesFound = true; - - if (!point->frameIsAvailable()) { - // We haven't notified the remote layer that the frame for - // this point is available yet. Notify it now, and then - // abort this attempt to latch. - point->setFrameAvailable(); - allTransactionsApplied = false; - break; - } - - allTransactionsApplied = allTransactionsApplied && point->transactionIsApplied(); - } - return !matchingFramesFound || allTransactionsApplied; -} - -Region Layer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) -{ - ATRACE_CALL(); - - if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) { - // mSidebandStreamChanged was true - mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream(); - if (mSidebandStream != NULL) { - setTransactionFlags(eTransactionNeeded); - mFlinger->setTransactionFlags(eTraversalNeeded); - } - recomputeVisibleRegions = true; - - const State& s(getDrawingState()); - return getTransform().transform(Region(Rect(s.active.w, s.active.h))); - } - - Region outDirtyRegion; - if (mQueuedFrames <= 0 && !mAutoRefresh) { - return outDirtyRegion; - } - - // if we've already called updateTexImage() without going through - // a composition step, we have to skip this layer at this point - // because we cannot call updateTeximage() without a corresponding - // compositionComplete() call. - // we'll trigger an update in onPreComposition(). - if (mRefreshPending) { - return outDirtyRegion; - } - - // If the head buffer's acquire fence hasn't signaled yet, return and - // try again later - if (!headFenceHasSignaled()) { - mFlinger->signalLayerUpdate(); - return outDirtyRegion; - } - - // Capture the old state of the layer for comparisons later - const State& s(getDrawingState()); - const bool oldOpacity = isOpaque(s); - sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer; - - if (!allTransactionsSignaled()) { - mFlinger->signalLayerUpdate(); - return outDirtyRegion; - } - - // This boolean is used to make sure that SurfaceFlinger's shadow copy - // of the buffer queue isn't modified when the buffer queue is returning - // BufferItem's that weren't actually queued. This can happen in shared - // buffer mode. - bool queuedBuffer = false; - LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions, - getProducerStickyTransform() != 0, mName.string(), - mOverrideScalingMode, mFreezeGeometryUpdates); - status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r, - mFlinger->mPrimaryDispSync, &mAutoRefresh, &queuedBuffer, - mLastFrameNumberReceived); - if (updateResult == BufferQueue::PRESENT_LATER) { - // Producer doesn't want buffer to be displayed yet. Signal a - // layer update so we check again at the next opportunity. - mFlinger->signalLayerUpdate(); - return outDirtyRegion; - } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) { - // If the buffer has been rejected, remove it from the shadow queue - // and return early - if (queuedBuffer) { - Mutex::Autolock lock(mQueueItemLock); - mQueueItems.removeAt(0); - android_atomic_dec(&mQueuedFrames); - } - return outDirtyRegion; - } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) { - // This can occur if something goes wrong when trying to create the - // EGLImage for this buffer. If this happens, the buffer has already - // been released, so we need to clean up the queue and bug out - // early. - if (queuedBuffer) { - Mutex::Autolock lock(mQueueItemLock); - mQueueItems.clear(); - android_atomic_and(0, &mQueuedFrames); - } - - // Once we have hit this state, the shadow queue may no longer - // correctly reflect the incoming BufferQueue's contents, so even if - // updateTexImage starts working, the only safe course of action is - // to continue to ignore updates. - mUpdateTexImageFailed = true; - - return outDirtyRegion; - } - - if (queuedBuffer) { - // Autolock scope - auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber(); - - Mutex::Autolock lock(mQueueItemLock); - - // Remove any stale buffers that have been dropped during - // updateTexImage - while (mQueueItems[0].mFrameNumber != currentFrameNumber) { - mQueueItems.removeAt(0); - android_atomic_dec(&mQueuedFrames); - } - - mQueueItems.removeAt(0); - } - - - // Decrement the queued-frames count. Signal another event if we - // have more frames pending. - if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1) - || mAutoRefresh) { - mFlinger->signalLayerUpdate(); - } - - // update the active buffer - mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer( - &mActiveBufferSlot); - if (mActiveBuffer == NULL) { - // this can only happen if the very first buffer was rejected. - return outDirtyRegion; - } - - mBufferLatched = true; - mPreviousFrameNumber = mCurrentFrameNumber; - mCurrentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber(); - - { - Mutex::Autolock lock(mFrameEventHistoryMutex); - mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime); -#ifndef USE_HWC2 - auto releaseFenceTime = std::make_shared<FenceTime>( - mSurfaceFlingerConsumer->getPrevFinalReleaseFence()); - mReleaseTimeline.updateSignalTimes(); - mReleaseTimeline.push(releaseFenceTime); - if (mPreviousFrameNumber != 0) { - mFrameEventHistory.addRelease(mPreviousFrameNumber, - latchTime, std::move(releaseFenceTime)); - } -#endif - } - - mRefreshPending = true; - mFrameLatencyNeeded = true; - if (oldActiveBuffer == NULL) { - // the first time we receive a buffer, we need to trigger a - // geometry invalidation. - recomputeVisibleRegions = true; - } - - setDataSpace(mSurfaceFlingerConsumer->getCurrentDataSpace()); - - Rect crop(mSurfaceFlingerConsumer->getCurrentCrop()); - const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform()); - const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode()); - if ((crop != mCurrentCrop) || - (transform != mCurrentTransform) || - (scalingMode != mCurrentScalingMode)) - { - mCurrentCrop = crop; - mCurrentTransform = transform; - mCurrentScalingMode = scalingMode; - recomputeVisibleRegions = true; - } - - if (oldActiveBuffer != NULL) { - uint32_t bufWidth = mActiveBuffer->getWidth(); - uint32_t bufHeight = mActiveBuffer->getHeight(); - if (bufWidth != uint32_t(oldActiveBuffer->width) || - bufHeight != uint32_t(oldActiveBuffer->height)) { - recomputeVisibleRegions = true; - } - } - - mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format); - if (oldOpacity != isOpaque(s)) { - recomputeVisibleRegions = true; - } - - // Remove any sync points corresponding to the buffer which was just - // latched - { - Mutex::Autolock lock(mLocalSyncPointMutex); - auto point = mLocalSyncPoints.begin(); - while (point != mLocalSyncPoints.end()) { - if (!(*point)->frameIsAvailable() || - !(*point)->transactionIsApplied()) { - // This sync point must have been added since we started - // latching. Don't drop it yet. - ++point; - continue; - } - - if ((*point)->getFrameNumber() <= mCurrentFrameNumber) { - point = mLocalSyncPoints.erase(point); - } else { - ++point; - } - } - } - - // FIXME: postedRegion should be dirty & bounds - Region dirtyRegion(Rect(s.active.w, s.active.h)); - - // transform the dirty region to window-manager space - outDirtyRegion = (getTransform().transform(dirtyRegion)); - - return outDirtyRegion; -} - -uint32_t Layer::getEffectiveUsage(uint32_t usage) const -{ +uint32_t Layer::getEffectiveUsage(uint32_t usage) const { // TODO: should we do something special if mSecure is set? if (mProtectedByApp) { // need a hardware-protected path to external video sink @@ -2426,7 +1387,7 @@ void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const { orientation = 0; } } - mSurfaceFlingerConsumer->setTransformHint(orientation); + setTransformHint(orientation); } // ---------------------------------------------------------------------------- @@ -2451,21 +1412,21 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mHeight = ds.active.h; info.mCrop = ds.crop; info.mFinalCrop = ds.finalCrop; - info.mAlpha = ds.alpha; + info.mColor = ds.color; info.mFlags = ds.flags; info.mPixelFormat = getPixelFormat(); - info.mDataSpace = getDataSpace(); + info.mDataSpace = static_cast<android_dataspace>(mCurrentDataSpace); info.mMatrix[0][0] = ds.active.transform[0][0]; info.mMatrix[0][1] = ds.active.transform[0][1]; info.mMatrix[1][0] = ds.active.transform[1][0]; info.mMatrix[1][1] = ds.active.transform[1][1]; { - sp<const GraphicBuffer> activeBuffer = getActiveBuffer(); - if (activeBuffer != 0) { - info.mActiveBufferWidth = activeBuffer->getWidth(); - info.mActiveBufferHeight = activeBuffer->getHeight(); - info.mActiveBufferStride = activeBuffer->getStride(); - info.mActiveBufferFormat = activeBuffer->format; + sp<const GraphicBuffer> buffer = getBE().compositionInfo.mBuffer; + if (buffer != 0) { + info.mActiveBufferWidth = buffer->getWidth(); + info.mActiveBufferHeight = buffer->getHeight(); + info.mActiveBufferStride = buffer->getStride(); + info.mActiveBufferFormat = buffer->format; } else { info.mActiveBufferWidth = 0; info.mActiveBufferHeight = 0; @@ -2480,7 +1441,6 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { return info; } -#ifdef USE_HWC2 void Layer::miniDumpHeader(String8& result) { result.append("----------------------------------------"); result.append("---------------------------------------\n"); @@ -2494,7 +1454,7 @@ void Layer::miniDumpHeader(String8& result) { } void Layer::miniDump(String8& result, int32_t hwcId) const { - if (mHwcLayers.count(hwcId) == 0) { + if (getBE().mHwcLayers.count(hwcId) == 0) { return; } @@ -2512,21 +1472,21 @@ void Layer::miniDump(String8& result, int32_t hwcId) const { result.appendFormat(" %s\n", name.string()); const Layer::State& layerState(getDrawingState()); - const HWCInfo& hwcInfo = mHwcLayers.at(hwcId); - result.appendFormat(" %10u | ", layerState.z); - result.appendFormat("%10s | ", - to_string(getCompositionType(hwcId)).c_str()); + const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(hwcId); + if (layerState.zOrderRelativeOf != nullptr || mDrawingParent != nullptr) { + result.appendFormat(" rel %6d | ", layerState.z); + } else { + result.appendFormat(" %10d | ", layerState.z); + } + result.appendFormat("%10s | ", to_string(getCompositionType(hwcId)).c_str()); const Rect& frame = hwcInfo.displayFrame; - result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top, - frame.right, frame.bottom); + result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom); const FloatRect& crop = hwcInfo.sourceCrop; - result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, - crop.right, crop.bottom); + result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, crop.right, crop.bottom); result.append("- - - - - - - - - - - - - - - - - - - - "); result.append("- - - - - - - - - - - - - - - - - - - -\n"); } -#endif void Layer::dumpFrameStats(String8& result) const { mFrameTracker.dumpStats(result); @@ -2545,8 +1505,7 @@ void Layer::getFrameStats(FrameStats* outStats) const { } void Layer::dumpFrameEvents(String8& result) { - result.appendFormat("- Layer %s (%s, %p)\n", - getName().string(), getTypeId(), this); + result.appendFormat("- Layer %s (%s, %p)\n", getName().string(), getTypeId(), this); Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.checkFencesForCompletion(); mFrameEventHistory.dump(result); @@ -2555,10 +1514,16 @@ void Layer::dumpFrameEvents(String8& result) { void Layer::onDisconnect() { Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.onDisconnect(); + mTimeStats.onDisconnect(getName().c_str()); } void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, - FrameEventHistoryDelta *outDelta) { + FrameEventHistoryDelta* outDelta) { + if (newTimestamps) { + mTimeStats.setPostTime(getName().c_str(), newTimestamps->frameNumber, + newTimestamps->postedTime); + } + Mutex::Autolock lock(mFrameEventHistoryMutex); if (newTimestamps) { // If there are any unsignaled fences in the aquire timeline at this @@ -2576,23 +1541,6 @@ void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, } } -std::vector<OccupancyTracker::Segment> Layer::getOccupancyHistory( - bool forceFlush) { - std::vector<OccupancyTracker::Segment> history; - status_t result = mSurfaceFlingerConsumer->getOccupancyHistory(forceFlush, - &history); - if (result != NO_ERROR) { - ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(), - result); - return {}; - } - return history; -} - -bool Layer::getTransformToDisplayInverse() const { - return mSurfaceFlingerConsumer->getTransformToDisplayInverse(); -} - size_t Layer::getChildrenCount() const { size_t count = 0; for (const sp<Layer>& child : mCurrentChildren) { @@ -2629,7 +1577,7 @@ bool Layer::reparentChildren(const sp<IBinder>& newParentHandle) { sp<Client> client(child->mClientRef.promote()); if (client != nullptr) { - client->setParentLayer(newParent); + client->updateParent(newParent); } } mCurrentChildren.clear(); @@ -2637,21 +1585,59 @@ bool Layer::reparentChildren(const sp<IBinder>& newParentHandle) { return true; } -bool Layer::detachChildren() { - traverseInZOrder(LayerVector::StateSet::Drawing, [this](Layer* child) { - if (child == this) { - return; - } +void Layer::setChildrenDrawingParent(const sp<Layer>& newParent) { + for (const sp<Layer>& child : mDrawingChildren) { + child->mDrawingParent = newParent; + } +} + +bool Layer::reparent(const sp<IBinder>& newParentHandle) { + if (newParentHandle == nullptr) { + return false; + } + auto handle = static_cast<Handle*>(newParentHandle.get()); + sp<Layer> newParent = handle->owner.promote(); + if (newParent == nullptr) { + ALOGE("Unable to promote Layer handle"); + return false; + } + + sp<Layer> parent = getParent(); + if (parent != nullptr) { + parent->removeChild(this); + } + newParent->addChild(this); + + sp<Client> client(mClientRef.promote()); + sp<Client> newParentClient(newParent->mClientRef.promote()); + + if (client != newParentClient) { + client->updateParent(newParent); + } + + return true; +} + +bool Layer::detachChildren() { + for (const sp<Layer>& child : mCurrentChildren) { + sp<Client> parentClient = mClientRef.promote(); sp<Client> client(child->mClientRef.promote()); - if (client != nullptr) { - client->detachLayer(child); + if (client != nullptr && parentClient != client) { + client->detachLayer(child.get()); + child->detachChildren(); } - }); + } return true; } +bool Layer::isLegacyDataSpace() const { + // return true when no higher bits are set + return !(mCurrentDataSpace & (ui::Dataspace::STANDARD_MASK | + ui::Dataspace::TRANSFER_MASK | ui::Dataspace::RANGE_MASK)); +} + void Layer::setParent(const sp<Layer>& layer) { mCurrentParent = layer; } @@ -2672,8 +1658,14 @@ int32_t Layer::getZ() const { return mDrawingState.z; } -__attribute__((no_sanitize("unsigned-integer-overflow"))) -LayerVector Layer::makeTraversalList(LayerVector::StateSet stateSet) { +bool Layer::usingRelativeZ(LayerVector::StateSet stateSet) { + const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; + const State& state = useDrawing ? mDrawingState : mCurrentState; + return state.zOrderRelativeOf != nullptr; +} + +__attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::makeTraversalList( + LayerVector::StateSet stateSet, bool* outSkipRelativeZUsers) { LOG_ALWAYS_FATAL_IF(stateSet == LayerVector::StateSet::Invalid, "makeTraversalList received invalid stateSet"); const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; @@ -2681,10 +1673,11 @@ LayerVector Layer::makeTraversalList(LayerVector::StateSet stateSet) { const State& state = useDrawing ? mDrawingState : mCurrentState; if (state.zOrderRelatives.size() == 0) { + *outSkipRelativeZUsers = true; return children; } - LayerVector traverse; + LayerVector traverse(stateSet); for (const wp<Layer>& weakRelative : state.zOrderRelatives) { sp<Layer> strongRelative = weakRelative.promote(); if (strongRelative != nullptr) { @@ -2693,6 +1686,10 @@ LayerVector Layer::makeTraversalList(LayerVector::StateSet stateSet) { } for (const sp<Layer>& child : children) { + const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState; + if (childState.zOrderRelativeOf != nullptr) { + continue; + } traverse.add(child); } @@ -2703,19 +1700,35 @@ LayerVector Layer::makeTraversalList(LayerVector::StateSet stateSet) { * Negatively signed relatives are before 'this' in Z-order. */ void Layer::traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor) { - LayerVector list = makeTraversalList(stateSet); + // In the case we have other layers who are using a relative Z to us, makeTraversalList will + // produce a new list for traversing, including our relatives, and not including our children + // who are relatives of another surface. In the case that there are no relative Z, + // makeTraversalList returns our children directly to avoid significant overhead. + // However in this case we need to take the responsibility for filtering children which + // are relatives of another surface here. + bool skipRelativeZUsers = false; + const LayerVector list = makeTraversalList(stateSet, &skipRelativeZUsers); size_t i = 0; for (; i < list.size(); i++) { const auto& relative = list[i]; + if (skipRelativeZUsers && relative->usingRelativeZ(stateSet)) { + continue; + } + if (relative->getZ() >= 0) { break; } relative->traverseInZOrder(stateSet, visitor); } + visitor(this); for (; i < list.size(); i++) { const auto& relative = list[i]; + + if (skipRelativeZUsers && relative->usingRelativeZ(stateSet)) { + continue; + } relative->traverseInZOrder(stateSet, visitor); } } @@ -2725,23 +1738,110 @@ void Layer::traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector:: */ void Layer::traverseInReverseZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor) { - LayerVector list = makeTraversalList(stateSet); + // See traverseInZOrder for documentation. + bool skipRelativeZUsers = false; + LayerVector list = makeTraversalList(stateSet, &skipRelativeZUsers); int32_t i = 0; for (i = int32_t(list.size()) - 1; i >= 0; i--) { const auto& relative = list[i]; + + if (skipRelativeZUsers && relative->usingRelativeZ(stateSet)) { + continue; + } + if (relative->getZ() < 0) { break; } relative->traverseInReverseZOrder(stateSet, visitor); } visitor(this); - for (; i>=0; i--) { + for (; i >= 0; i--) { const auto& relative = list[i]; + + if (skipRelativeZUsers && relative->usingRelativeZ(stateSet)) { + continue; + } + relative->traverseInReverseZOrder(stateSet, visitor); } } +LayerVector Layer::makeChildrenTraversalList(LayerVector::StateSet stateSet, + const std::vector<Layer*>& layersInTree) { + LOG_ALWAYS_FATAL_IF(stateSet == LayerVector::StateSet::Invalid, + "makeTraversalList received invalid stateSet"); + const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; + const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; + const State& state = useDrawing ? mDrawingState : mCurrentState; + + LayerVector traverse(stateSet); + for (const wp<Layer>& weakRelative : state.zOrderRelatives) { + sp<Layer> strongRelative = weakRelative.promote(); + // Only add relative layers that are also descendents of the top most parent of the tree. + // If a relative layer is not a descendent, then it should be ignored. + if (std::binary_search(layersInTree.begin(), layersInTree.end(), strongRelative.get())) { + traverse.add(strongRelative); + } + } + + for (const sp<Layer>& child : children) { + const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState; + // If a layer has a relativeOf layer, only ignore if the layer it's relative to is a + // descendent of the top most parent of the tree. If it's not a descendent, then just add + // the child here since it won't be added later as a relative. + if (std::binary_search(layersInTree.begin(), layersInTree.end(), + childState.zOrderRelativeOf.promote().get())) { + continue; + } + traverse.add(child); + } + + return traverse; +} + +void Layer::traverseChildrenInZOrderInner(const std::vector<Layer*>& layersInTree, + LayerVector::StateSet stateSet, + const LayerVector::Visitor& visitor) { + const LayerVector list = makeChildrenTraversalList(stateSet, layersInTree); + + size_t i = 0; + for (; i < list.size(); i++) { + const auto& relative = list[i]; + if (relative->getZ() >= 0) { + break; + } + relative->traverseChildrenInZOrderInner(layersInTree, stateSet, visitor); + } + + visitor(this); + for (; i < list.size(); i++) { + const auto& relative = list[i]; + relative->traverseChildrenInZOrderInner(layersInTree, stateSet, visitor); + } +} + +std::vector<Layer*> Layer::getLayersInTree(LayerVector::StateSet stateSet) { + const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; + const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; + + std::vector<Layer*> layersInTree = {this}; + for (size_t i = 0; i < children.size(); i++) { + const auto& child = children[i]; + std::vector<Layer*> childLayers = child->getLayersInTree(stateSet); + layersInTree.insert(layersInTree.end(), childLayers.cbegin(), childLayers.cend()); + } + + return layersInTree; +} + +void Layer::traverseChildrenInZOrder(LayerVector::StateSet stateSet, + const LayerVector::Visitor& visitor) { + std::vector<Layer*> layersInTree = getLayersInTree(stateSet); + std::sort(layersInTree.begin(), layersInTree.end()); + traverseChildrenInZOrderInner(layersInTree, stateSet, visitor); +} + Transform Layer::getTransform() const { Transform t; const auto& p = mDrawingParent.promote(); @@ -2753,20 +1853,18 @@ Transform Layer::getTransform() const { // for in the transform. We need to mirror this scaling in child surfaces // or we will break the contract where WM can treat child surfaces as // pixels in the parent surface. - if (p->isFixedSize() && p->mActiveBuffer != nullptr) { + if (p->isFixedSize() && p->getBE().compositionInfo.mBuffer != nullptr) { int bufferWidth; int bufferHeight; if ((p->mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) == 0) { - bufferWidth = p->mActiveBuffer->getWidth(); - bufferHeight = p->mActiveBuffer->getHeight(); + bufferWidth = p->getBE().compositionInfo.mBuffer->getWidth(); + bufferHeight = p->getBE().compositionInfo.mBuffer->getHeight(); } else { - bufferHeight = p->mActiveBuffer->getWidth(); - bufferWidth = p->mActiveBuffer->getHeight(); + bufferHeight = p->getBE().compositionInfo.mBuffer->getWidth(); + bufferWidth = p->getBE().compositionInfo.mBuffer->getHeight(); } - float sx = p->getDrawingState().active.w / - static_cast<float>(bufferWidth); - float sy = p->getDrawingState().active.h / - static_cast<float>(bufferHeight); + float sx = p->getDrawingState().active.w / static_cast<float>(bufferWidth); + float sy = p->getDrawingState().active.h / static_cast<float>(bufferHeight); Transform extraParentScaling; extraParentScaling.set(sx, 0, 0, sy); t = t * extraParentScaling; @@ -2775,23 +1873,17 @@ Transform Layer::getTransform() const { return t * getDrawingState().active.transform; } -#ifdef USE_HWC2 -float Layer::getAlpha() const { +half Layer::getAlpha() const { const auto& p = mDrawingParent.promote(); - float parentAlpha = (p != nullptr) ? p->getAlpha() : 1.0; - return parentAlpha * getDrawingState().alpha; + half parentAlpha = (p != nullptr) ? p->getAlpha() : 1.0_hf; + return parentAlpha * getDrawingState().color.a; } -#else -uint8_t Layer::getAlpha() const { - const auto& p = mDrawingParent.promote(); - float parentAlpha = (p != nullptr) ? (p->getAlpha() / 255.0f) : 1.0; - float drawingAlpha = getDrawingState().alpha / 255.0f; - drawingAlpha = drawingAlpha * parentAlpha; - return static_cast<uint8_t>(std::round(drawingAlpha * 255)); +half4 Layer::getColor() const { + const half4 color(getDrawingState().color); + return half4(color.r, color.g, color.b, getAlpha()); } -#endif void Layer::commitChildList() { for (size_t i = 0; i < mCurrentChildren.size(); i++) { @@ -2802,6 +1894,113 @@ void Layer::commitChildList() { mDrawingParent = mCurrentParent; } +void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) { + const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; + const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; + const State& state = useDrawing ? mDrawingState : mCurrentState; + + Transform requestedTransform = state.active.transform; + Transform transform = getTransform(); + + layerInfo->set_id(sequence); + layerInfo->set_name(getName().c_str()); + layerInfo->set_type(String8(getTypeId())); + + for (const auto& child : children) { + layerInfo->add_children(child->sequence); + } + + for (const wp<Layer>& weakRelative : state.zOrderRelatives) { + sp<Layer> strongRelative = weakRelative.promote(); + if (strongRelative != nullptr) { + layerInfo->add_relatives(strongRelative->sequence); + } + } + + LayerProtoHelper::writeToProto(state.activeTransparentRegion, + layerInfo->mutable_transparent_region()); + LayerProtoHelper::writeToProto(visibleRegion, layerInfo->mutable_visible_region()); + LayerProtoHelper::writeToProto(surfaceDamageRegion, layerInfo->mutable_damage_region()); + + layerInfo->set_layer_stack(getLayerStack()); + layerInfo->set_z(state.z); + + PositionProto* position = layerInfo->mutable_position(); + position->set_x(transform.tx()); + position->set_y(transform.ty()); + + PositionProto* requestedPosition = layerInfo->mutable_requested_position(); + requestedPosition->set_x(requestedTransform.tx()); + requestedPosition->set_y(requestedTransform.ty()); + + SizeProto* size = layerInfo->mutable_size(); + size->set_w(state.active.w); + size->set_h(state.active.h); + + LayerProtoHelper::writeToProto(state.crop, layerInfo->mutable_crop()); + LayerProtoHelper::writeToProto(state.finalCrop, layerInfo->mutable_final_crop()); + + layerInfo->set_is_opaque(isOpaque(state)); + layerInfo->set_invalidate(contentDirty); + + // XXX (b/79210409) mCurrentDataSpace is not protected + layerInfo->set_dataspace(dataspaceDetails(static_cast<android_dataspace>(mCurrentDataSpace))); + + layerInfo->set_pixel_format(decodePixelFormat(getPixelFormat())); + LayerProtoHelper::writeToProto(getColor(), layerInfo->mutable_color()); + LayerProtoHelper::writeToProto(state.color, layerInfo->mutable_requested_color()); + layerInfo->set_flags(state.flags); + + LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform()); + LayerProtoHelper::writeToProto(requestedTransform, layerInfo->mutable_requested_transform()); + + auto parent = useDrawing ? mDrawingParent.promote() : mCurrentParent.promote(); + if (parent != nullptr) { + layerInfo->set_parent(parent->sequence); + } + + auto zOrderRelativeOf = state.zOrderRelativeOf.promote(); + if (zOrderRelativeOf != nullptr) { + layerInfo->set_z_order_relative_of(zOrderRelativeOf->sequence); + } + + // XXX getBE().compositionInfo.mBuffer is not protected + auto buffer = getBE().compositionInfo.mBuffer; + if (buffer != nullptr) { + LayerProtoHelper::writeToProto(buffer, layerInfo->mutable_active_buffer()); + } + + layerInfo->set_queued_frames(getQueuedFrameCount()); + layerInfo->set_refresh_pending(isBufferLatched()); + layerInfo->set_window_type(state.type); + layerInfo->set_app_id(state.appId); +} + +void Layer::writeToProto(LayerProto* layerInfo, int32_t hwcId) { + writeToProto(layerInfo, LayerVector::StateSet::Drawing); + + const auto& hwcInfo = getBE().mHwcLayers.at(hwcId); + + const Rect& frame = hwcInfo.displayFrame; + LayerProtoHelper::writeToProto(frame, layerInfo->mutable_hwc_frame()); + + const FloatRect& crop = hwcInfo.sourceCrop; + LayerProtoHelper::writeToProto(crop, layerInfo->mutable_hwc_crop()); + + const int32_t transform = static_cast<int32_t>(hwcInfo.transform); + layerInfo->set_hwc_transform(transform); + + const int32_t compositionType = static_cast<int32_t>(hwcInfo.compositionType); + layerInfo->set_hwc_composition_type(compositionType); + + if (std::strcmp(getTypeId(), "BufferLayer") == 0 && + static_cast<BufferLayer*>(this)->isProtected()) { + layerInfo->set_is_protected(true); + } else { + layerInfo->set_is_protected(false); + } +} + // --------------------------------------------------------------------------- }; // namespace android |