diff options
| author | 2017-08-21 12:12:51 -0700 | |
|---|---|---|
| committer | 2017-11-07 00:13:38 -0800 | |
| commit | 0c69cad13dda09f1df1dbf23810b1c5b7f28ba08 (patch) | |
| tree | 7e8a4444d056b2f079a2e65011685018098503b3 | |
| parent | 1b70ec25ce919767610c2e1c6df0d28bf00b4a23 (diff) | |
Refactor Layer/ColorLayer into siblings
New class hierarchy should look like:
Layer (abstract)
/ \
/ \
Buffer Color
Layer Layer
Note: LayerBuffer is what previously was referred to by class Layer
Test: Transaction_test.cpp/manual test
Change-Id: I372a27d533e08371da37be811e4372404f7787bd
| -rw-r--r-- | services/surfaceflinger/Android.mk | 1 | ||||
| -rw-r--r-- | services/surfaceflinger/BufferLayer.cpp | 911 | ||||
| -rw-r--r-- | services/surfaceflinger/BufferLayer.h | 184 | ||||
| -rw-r--r-- | services/surfaceflinger/ColorLayer.cpp | 5 | ||||
| -rw-r--r-- | services/surfaceflinger/ColorLayer.h | 16 | ||||
| -rwxr-xr-x | services/surfaceflinger/Layer.cpp | 760 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.h | 130 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 22 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 5 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 21 |
10 files changed, 1191 insertions, 864 deletions
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 3f8ab3fc3f..7115ad62ea 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -14,6 +14,7 @@ LOCAL_SRC_FILES := \ FrameTracker.cpp \ GpuService.cpp \ Layer.cpp \ + BufferLayer.cpp \ ColorLayer.cpp \ LayerRejecter.cpp \ LayerVector.cpp \ diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp new file mode 100644 index 0000000000..ccb65f6df2 --- /dev/null +++ b/services/surfaceflinger/BufferLayer.cpp @@ -0,0 +1,911 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#undef LOG_TAG +#define LOG_TAG "BufferLayer" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "BufferLayer.h" +#include "Colorizer.h" +#include "DisplayDevice.h" +#include "LayerRejecter.h" +#include "clz.h" + +#include "RenderEngine/RenderEngine.h" + +#include <gui/BufferItem.h> +#include <gui/BufferQueue.h> +#include <gui/LayerDebugInfo.h> +#include <gui/Surface.h> + +#include <ui/DebugUtils.h> + +#include <utils/Errors.h> +#include <utils/Log.h> +#include <utils/NativeHandle.h> +#include <utils/StopWatch.h> +#include <utils/Trace.h> + +#include <cutils/compiler.h> +#include <cutils/native_handle.h> +#include <cutils/properties.h> + +#include <math.h> +#include <stdlib.h> +#include <mutex> + +namespace android { + +BufferLayer::BufferLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags) + : Layer(flinger, client, name, w, h, flags), + mTextureName(-1U), + mFormat(PIXEL_FORMAT_NONE), + mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), + mBufferLatched(false), + mPreviousFrameNumber(0), + mUpdateTexImageFailed(false), + mRefreshPending(false) { +#ifdef USE_HWC2 + ALOGV("Creating Layer %s", name.string()); +#endif + + mFlinger->getRenderEngine().genTextures(1, &mTextureName); + mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName); + + if (flags & ISurfaceComposerClient::eNonPremultiplied) mPremultipliedAlpha = false; + + mCurrentState.requested = mCurrentState.active; + + // drawing state & current state are identical + mDrawingState = mCurrentState; +} + +BufferLayer::~BufferLayer() { + sp<Client> c(mClientRef.promote()); + if (c != 0) { + c->detachLayer(this); + } + + for (auto& point : mRemoteSyncPoints) { + point->setTransactionApplied(); + } + for (auto& point : mLocalSyncPoints) { + point->setFrameAvailable(); + } + mFlinger->deleteTextureAsync(mTextureName); + +#ifdef USE_HWC2 + if (!mHwcLayers.empty()) { + ALOGE("Found stale hardware composer layers when destroying " + "surface flinger layer %s", + mName.string()); + destroyAllHwcLayers(); + } +#endif +} + +bool BufferLayer::isProtected() const +{ + const sp<GraphicBuffer>& activeBuffer(mActiveBuffer); + return (activeBuffer != 0) && + (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED); +} + +bool BufferLayer::isVisible() const { + return !(isHiddenByPolicy()) && getAlpha() > 0.0f && + (mActiveBuffer != NULL || mSidebandStream != NULL); +} + +bool BufferLayer::isFixedSize() const { + return getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE; +} + +status_t BufferLayer::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; +} + +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 BufferLayer::onDraw(const RenderArea& renderArea, 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<BufferLayer const*>(this)) { + finished = true; + return; + } + under.orSelf(renderArea.getTransform().transform(layer->visibleRegion)); + }); + // if not everything below us is covered, we plug the holes! + Region holes(clip.subtract(under)); + if (!holes.isEmpty()) { + clearWithOpenGL(renderArea, 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() && !renderArea.isSecure()); + + RenderEngine& engine(mFlinger->getRenderEngine()); + + if (!blackOutLayer) { + // TODO: we could be more subtle with isFixedSize() + const bool useFiltering = getFiltering() || needsFiltering(renderArea) || 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(renderArea, useIdentityTransform); + engine.disableTexturing(); +} + +bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { + if (mBufferLatched) { + Mutex::Autolock lock(mFrameEventHistoryMutex); + mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime); + } + mRefreshPending = false; + return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh; +} + +#ifdef USE_HWC2 +void BufferLayer::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 + +Region BufferLayer::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; +} + +#ifdef USE_HWC2 +void BufferLayer::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)); + } + + 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 BufferLayer::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); + } +} +#endif + +bool BufferLayer::isOpaque(const Layer::State& s) const +{ + // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the + // layer's opaque flag. + if ((mSidebandStream == nullptr) && (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; +} + +void BufferLayer::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); +} + +// --------------------------------------------------------------------------- +// Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener +// --------------------------------------------------------------------------- + +void BufferLayer::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 BufferLayer::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 BufferLayer::onSidebandStreamChanged() { + if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) { + // mSidebandStreamChanged was false + mFlinger->signalLayerUpdate(); + } +} + +bool BufferLayer::needsFiltering(const RenderArea& renderArea) const { + return mNeedsFiltering || renderArea.needsFiltering(); +} + +// As documented in libhardware header, formats in the range +// 0x100 - 0x1FF are specific to the HAL implementation, and +// are known to have no alpha channel +// TODO: move definition for device-specific range into +// hardware.h, instead of using hard-coded values here. +#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF) + +bool BufferLayer::getOpacityForFormat(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; +} + +void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, + bool useIdentityTransform) const { + const State& s(getDrawingState()); + + computeGeometry(renderArea, 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. + */ + Rect win(computeBounds()); + + Transform t = getTransform(); + if (!s.finalCrop.isEmpty()) { + win = t.transform(win); + if (!win.intersect(s.finalCrop, &win)) { + win.clear(); + } + win = t.inverse().transform(win); + if (!win.intersect(computeBounds(), &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), false /* disableTexture */, + getColor()); +#ifdef USE_HWC2 + engine.setSourceDataSpace(mCurrentState.dataSpace); +#endif + engine.drawMesh(mMesh); + engine.disableBlending(); +} + +uint32_t BufferLayer::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 BufferLayer::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 BufferLayer::getHeadFrameNumber() const { + Mutex::Autolock lock(mQueueItemLock); + if (!mQueueItems.empty()) { + return mQueueItems[0].mFrameNumber; + } else { + return mCurrentFrameNumber; + } +} + +bool BufferLayer::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 +} + +uint32_t BufferLayer::getEffectiveScalingMode() const { + if (mOverrideScalingMode >= 0) { + return mOverrideScalingMode; + } + return mCurrentScalingMode; +} + +// ---------------------------------------------------------------------------- +// transaction +// ---------------------------------------------------------------------------- + +void BufferLayer::notifyAvailableFrames() { + auto headFrameNumber = getHeadFrameNumber(); + bool headFenceSignaled = headFenceHasSignaled(); + Mutex::Autolock lock(mLocalSyncPointMutex); + for (auto& point : mLocalSyncPoints) { + if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled) { + point->setFrameAvailable(); + } + } +} + +sp<IGraphicBufferProducer> BufferLayer::getProducer() const { + return mProducer; +} + +// --------------------------------------------------------------------------- +// h/w composer set-up +// --------------------------------------------------------------------------- + +bool BufferLayer::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; +} + +} // namespace android + +#if defined(__gl_h_) +#error "don't include gl/gl.h in this file" +#endif + +#if defined(__gl2_h_) +#error "don't include gl2/gl2.h in this file" +#endif diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h new file mode 100644 index 0000000000..b245f2976e --- /dev/null +++ b/services/surfaceflinger/BufferLayer.h @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "Layer.h" +#include "Client.h" +#include "DisplayHardware/HWComposer.h" +#include "DisplayHardware/HWComposerBufferCache.h" +#include "FrameTracker.h" +#include "LayerVector.h" +#include "MonitoredProducer.h" +#include "RenderEngine/Mesh.h" +#include "RenderEngine/Texture.h" +#include "SurfaceFlinger.h" +#include "SurfaceFlingerConsumer.h" +#include "Transform.h" + +#include <gui/ISurfaceComposerClient.h> +#include <gui/LayerState.h> + +#include <EGL/egl.h> +#include <EGL/eglext.h> + +#include <ui/FrameStats.h> +#include <ui/GraphicBuffer.h> +#include <ui/PixelFormat.h> +#include <ui/Region.h> + +#include <utils/RefBase.h> +#include <utils/String8.h> +#include <utils/Timers.h> + +#include <stdint.h> +#include <sys/types.h> +#include <list> + +namespace android { + +/* + * A new BufferQueue and a new SurfaceFlingerConsumer are created when the + * BufferLayer is first referenced. + * + * This also implements onFrameAvailable(), which notifies SurfaceFlinger + * that new data has arrived. + */ +class BufferLayer : public Layer, public SurfaceFlingerConsumer::ContentsChangedListener { +public: + BufferLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w, + uint32_t h, uint32_t flags); + + ~BufferLayer() override; + + // ----------------------------------------------------------------------- + // Overriden from Layer + // ----------------------------------------------------------------------- + + /* + * getTypeId - Provide unique string for each class type in the Layer + * hierarchy + */ + const char* getTypeId() const override { return "BufferLayer"; } + + /* + * isProtected - true if the layer may contain protected content in the + * GRALLOC_USAGE_PROTECTED sense. + */ + bool isProtected() const; + + /* + * isVisible - true if this layer is visible, false otherwise + */ + bool isVisible() const override; + + /* + * isFixedSize - true if content has a fixed size + */ + bool isFixedSize() const override; + + // the this layer's size and format + status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags); + + /* + * onDraw - draws the surface. + */ + void onDraw(const RenderArea& renderArea, const Region& clip, + bool useIdentityTransform) const override; + + bool onPreComposition(nsecs_t refreshStartTime) override; + +#ifdef USE_HWC2 + // If a buffer was replaced this frame, release the former buffer + void releasePendingBuffer(nsecs_t dequeueReadyTime); +#endif + + /* + * latchBuffer - called each time the screen is redrawn and returns whether + * the visible regions need to be recomputed (this is a fairly heavy + * operation, so this should be set only if needed). Typically this is used + * to figure out if the content or size of a surface has changed. + */ + Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) override; + bool isBufferLatched() const override { return mRefreshPending; } + +#ifdef USE_HWC2 + void setPerFrameData(const sp<const DisplayDevice>& displayDevice); +#else + void setPerFrameData(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer); +#endif + bool isOpaque(const Layer::State& s) const override; + +private: + void onFirstRef() override; + + // Interface implementation for + // SurfaceFlingerConsumer::ContentsChangedListener + void onFrameAvailable(const BufferItem& item) override; + void onFrameReplaced(const BufferItem& item) override; + void onSidebandStreamChanged() override; + + // needsLinearFiltering - true if this surface's state requires filtering + bool needsFiltering(const RenderArea& renderArea) const; + + static bool getOpacityForFormat(uint32_t format); + + // drawing + void drawWithOpenGL(const RenderArea& renderArea, + bool useIdentityTransform) const; + + // Temporary - Used only for LEGACY camera mode. + uint32_t getProducerStickyTransform() const; + + // Loads the corresponding system property once per process + static bool latchUnsignaledBuffers(); + + uint64_t getHeadFrameNumber() const; + bool headFenceHasSignaled() const; + + // Returns the current scaling mode, unless mOverrideScalingMode + // is set, in which case, it returns mOverrideScalingMode + uint32_t getEffectiveScalingMode() const override; + +public: + void notifyAvailableFrames() override; + + PixelFormat getPixelFormat() const override { return mFormat; } + sp<IGraphicBufferProducer> getProducer() const; + +private: + // Check all of the local sync points to ensure that all transactions + // which need to have been applied prior to the frame which is about to + // be latched have signaled + bool allTransactionsSignaled(); + sp<IGraphicBufferProducer> mProducer; + + // constants + uint32_t mTextureName; // from GLES + PixelFormat mFormat; + + // main thread + uint32_t mCurrentScalingMode; + bool mBufferLatched = false; // TODO: Use mActiveBuffer? + uint64_t mPreviousFrameNumber; // Only accessed on the main thread. + // The texture used to draw the layer in GLES composition mode + mutable Texture mTexture; + + bool mUpdateTexImageFailed; // This is only accessed on the main thread. + bool mRefreshPending; +}; + +} // namespace android diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 32526dd29b..72fdaaa654 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -37,7 +37,10 @@ namespace android { ColorLayer::ColorLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags) - : Layer(flinger, client, name, w, h, flags) { + : Layer(flinger, client, name, w, h, flags) { + + // drawing state & current state are identical + mDrawingState = mCurrentState; } void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */, diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index cdf3eca60a..c68ad023e1 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -26,8 +26,7 @@ namespace android { -class ColorLayer : public Layer -{ +class ColorLayer : public Layer { public: ColorLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags); @@ -36,10 +35,19 @@ public: virtual const char* getTypeId() const { return "ColorLayer"; } virtual void onDraw(const RenderArea& renderArea, const Region& clip, bool useIdentityTransform) const; + bool isVisible() const override; virtual bool isOpaque(const Layer::State&) const { return false; } - virtual bool isSecure() const { return false; } virtual bool isFixedSize() const { return true; } - virtual bool isVisible() const; + + void notifyAvailableFrames() override {} + PixelFormat getPixelFormat() const override { return PIXEL_FORMAT_NONE; } + uint32_t getEffectiveScalingMode() const override { return 0; } +#ifdef USE_HWC2 + void releasePendingBuffer(nsecs_t) override {} +#endif + Region latchBuffer(bool&, nsecs_t) override { return Region(); } + bool isBufferLatched() const override { return false; } + bool onPreComposition(nsecs_t) override { return true; } }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 0525607c35..763488c8f5 100755 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -62,19 +62,16 @@ namespace android { -// --------------------------------------------------------------------------- - 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), + : contentDirty(false), sequence(uint32_t(android_atomic_inc(&sSequence))), mFlinger(flinger), - mTextureName(UINT32_MAX), + mSurfaceFlingerConsumer(NULL), mPremultipliedAlpha(true), - mName("unnamed"), - mFormat(PIXEL_FORMAT_NONE), + mName(name), mTransactionFlags(0), mPendingStateMutex(), mPendingStates(), @@ -82,13 +79,9 @@ 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), @@ -97,24 +90,17 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, 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 mCurrentCrop.makeInvalid(); - mFlinger->getRenderEngine().genTextures(1, &mTextureName); - mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName); uint32_t layerFlags = 0; if (flags & ISurfaceComposerClient::eHidden) @@ -124,14 +110,12 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, if (flags & ISurfaceComposerClient::eSecure) layerFlags |= layer_state_t::eLayerSecure; - if (flags & ISurfaceComposerClient::eNonPremultiplied) - mPremultipliedAlpha = false; - 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(); @@ -140,7 +124,6 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, mCurrentState.z = 0; mCurrentState.color.a = 1.0f; mCurrentState.layerStack = 0; - mCurrentState.flags = layerFlags; mCurrentState.sequence = 0; mCurrentState.requested = mCurrentState.active; mCurrentState.dataSpace = HAL_DATASPACE_UNKNOWN; @@ -166,46 +149,10 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, } 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); } Layer::~Layer() { - sp<Client> c(mClientRef.promote()); - if (c != 0) { - c->detachLayer(this); - } - - for (auto& point : mRemoteSyncPoints) { - point->setTransactionApplied(); - } - 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 } // --------------------------------------------------------------------------- @@ -217,7 +164,9 @@ void Layer::onLayerDisplayed(const sp<Fence>& releaseFence) { if (mHwcLayers.empty()) { return; } - mSurfaceFlingerConsumer->setReleaseFence(releaseFence); + if (mSurfaceFlingerConsumer) { + mSurfaceFlingerConsumer->setReleaseFence(releaseFence); + } } #else void Layer::onLayerDisplayed(const sp<const DisplayDevice>& /* hw */, @@ -229,70 +178,6 @@ void Layer::onLayerDisplayed(const sp<const DisplayDevice>& /* hw */, } #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(); - } -} - void Layer::onRemovedFromCurrentState() { // the layer is removed from SF mCurrentState to mLayersPendingRemoval @@ -313,7 +198,9 @@ void Layer::onRemovedFromCurrentState() { void Layer::onRemoved() { // the layer is removed from SF mLayersPendingRemoval - mSurfaceFlingerConsumer->abandon(); + if (mSurfaceFlingerConsumer) { + mSurfaceFlingerConsumer->abandon(); + } #ifdef USE_HWC2 destroyAllHwcLayers(); #endif @@ -335,47 +222,11 @@ bool Layer::getPremultipledAlpha() const { return mPremultipliedAlpha; } -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; -} - 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 // --------------------------------------------------------------------------- @@ -1077,125 +928,6 @@ void Layer::draw(const RenderArea& renderArea) const { onDraw(renderArea, Region(renderArea.getBounds()), 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 RenderArea& renderArea, 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(renderArea.getTransform().transform(layer->visibleRegion)); - }); - // if not everything below us is covered, we plug the holes! - Region holes(clip.subtract(under)); - if (!holes.isEmpty()) { - clearWithOpenGL(renderArea, 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() && !renderArea.isSecure()); - - RenderEngine& engine(mFlinger->getRenderEngine()); - - if (!blackOutLayer) { - // TODO: we could be more subtle with isFixedSize() - const bool useFiltering = getFiltering() || needsFiltering(renderArea) || 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(renderArea, useIdentityTransform); - engine.disableTexturing(); -} - - void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue, float alpha) const @@ -1210,62 +942,6 @@ void Layer::clearWithOpenGL(const RenderArea& renderArea) const { clearWithOpenGL(renderArea, 0,0,0,0); } -void Layer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const { - const State& s(getDrawingState()); - - computeGeometry(renderArea, 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. - */ - Rect win(computeBounds()); - - Transform t = getTransform(); - if (!s.finalCrop.isEmpty()) { - win = t.transform(win); - if (!win.intersect(s.finalCrop, &win)) { - win.clear(); - } - win = t.inverse().transform(win); - if (!win.intersect(computeBounds(), &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), - false /* disableTexture */, getColor()); -#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) { @@ -1320,64 +996,6 @@ bool Layer::getClearClientTarget(int32_t hwcId) const { } #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 -} - bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) { if (point->getFrameNumber() <= mCurrentFrameNumber) { // Don't bother with a SyncPoint, since we've already latched the @@ -1398,28 +1016,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 // ---------------------------------------------------------------------------- @@ -1476,44 +1072,12 @@ void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh, } } -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 { 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 RenderArea& renderArea) const { - return mNeedsFiltering || renderArea.needsFiltering(); -} - void Layer::setVisibleRegion(const Region& visibleRegion) { // always called from main thread this->visibleRegion = visibleRegion; @@ -1632,17 +1196,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(); @@ -1657,7 +1210,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { const bool sizeChanged = (c.requested.w != s.requested.w) || (c.requested.h != s.requested.h); - if (sizeChanged) { + if (mSurfaceFlingerConsumer && 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" @@ -1984,13 +1537,6 @@ void Layer::setInfo(uint32_t type, uint32_t appId) { 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; @@ -2081,15 +1627,6 @@ bool Layer::shouldPresentNow(const DispSync& dispSync) const { 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) { @@ -2135,25 +1672,6 @@ bool Layer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence, 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(); @@ -2163,249 +1681,6 @@ bool Layer::isHiddenByPolicy() const { return s.flags & layer_state_t::eLayerHidden; } -bool Layer::isVisible() const { - return !(isHiddenByPolicy()) && getAlpha() > 0.0f - && (mActiveBuffer != NULL || mSidebandStream != NULL); -} - -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 { // TODO: should we do something special if mSecure is set? @@ -2432,7 +1707,9 @@ void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const { orientation = 0; } } - mSurfaceFlingerConsumer->setTransformHint(orientation); + if (mSurfaceFlingerConsumer) { + mSurfaceFlingerConsumer->setTransformHint(orientation); + } } // ---------------------------------------------------------------------------- @@ -2584,6 +1861,10 @@ void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, std::vector<OccupancyTracker::Segment> Layer::getOccupancyHistory( bool forceFlush) { std::vector<OccupancyTracker::Segment> history; + + if (!mSurfaceFlingerConsumer) + return {}; + status_t result = mSurfaceFlingerConsumer->getOccupancyHistory(forceFlush, &history); if (result != NO_ERROR) { @@ -2595,7 +1876,10 @@ std::vector<OccupancyTracker::Segment> Layer::getOccupancyHistory( } bool Layer::getTransformToDisplayInverse() const { - return mSurfaceFlingerConsumer->getTransformToDisplayInverse(); + if (mSurfaceFlingerConsumer) { + return mSurfaceFlingerConsumer->getTransformToDisplayInverse(); + } + return false; } size_t Layer::getChildrenCount() const { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index d75e175f5a..ee3bb7ef3f 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -69,14 +69,8 @@ class LayerDebugInfo; // --------------------------------------------------------------------------- -/* - * A new BufferQueue and a new SurfaceFlingerConsumer are created when the - * Layer is first referenced. - * - * This also implements onFrameAvailable(), which notifies SurfaceFlinger - * that new data has arrived. - */ -class Layer : public SurfaceFlingerConsumer::ContentsChangedListener { +class Layer : public virtual RefBase +{ static int32_t sSequence; public: @@ -162,18 +156,12 @@ public: half4 color; }; - // ----------------------------------------------------------------------- - Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags); - virtual ~Layer(); void setPrimaryDisplayOnly() { mPrimaryDisplayOnly = true; } - // the this layer's size and format - status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags); - // ------------------------------------------------------------------------ // Geometry setting functions. // @@ -264,8 +252,7 @@ public: // ----------------------------------------------------------------------- // Virtuals - - virtual const char* getTypeId() const { return "Layer"; } + virtual const char* getTypeId() const = 0; /* * isOpaque - true if this surface is opaque @@ -274,24 +261,18 @@ public: * pixel format includes an alpha channel) and the "opaque" flag set * on the layer. It does not examine the current plane alpha value. */ - virtual bool isOpaque(const Layer::State& s) const; + virtual bool isOpaque(const Layer::State& s) const = 0; /* * isSecure - true if this surface is secure, that is if it prevents * screenshots or VNC servers. */ - virtual bool isSecure() const; - - /* - * isProtected - true if the layer may contain protected content in the - * GRALLOC_USAGE_PROTECTED sense. - */ - virtual bool isProtected() const; + bool isSecure() const; /* * isVisible - true if this layer is visible, false otherwise */ - virtual bool isVisible() const; + virtual bool isVisible() const = 0; /* * isHiddenByPolicy - true if this layer has been forced invisible. @@ -299,12 +280,12 @@ public: * For example if this layer has no active buffer, it may not be hidden by * policy, but it still can not be visible. */ - virtual bool isHiddenByPolicy() const; + bool isHiddenByPolicy() const; /* * isFixedSize - true if content has a fixed size */ - virtual bool isFixedSize() const; + virtual bool isFixedSize() const = 0; void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing); @@ -313,11 +294,9 @@ protected: * onDraw - draws the surface. */ virtual void onDraw(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform) const; + bool useIdentityTransform) const = 0; public: - // ----------------------------------------------------------------------- - #ifdef USE_HWC2 void setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z); void forceClientComposition(int32_t hwcId); @@ -325,22 +304,17 @@ public: // callIntoHwc exists so we can update our local state and call // acceptDisplayChanges without unnecessarily updating the device's state - void setCompositionType(int32_t hwcId, HWC2::Composition type, - bool callIntoHwc = true); + void setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc = true); HWC2::Composition getCompositionType(int32_t hwcId) const; - void setClearClientTarget(int32_t hwcId, bool clear); bool getClearClientTarget(int32_t hwcId) const; - void updateCursorPosition(const sp<const DisplayDevice>& hw); #else void setGeometry(const sp<const DisplayDevice>& hw, - HWComposer::HWCLayerInterface& layer); - void setPerFrameData(const sp<const DisplayDevice>& hw, - HWComposer::HWCLayerInterface& layer); + HWComposer::HWCLayerInterface& layer); + void setPerFrameData(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer); void setAcquireFence(const sp<const DisplayDevice>& hw, - HWComposer::HWCLayerInterface& layer); - + HWComposer::HWCLayerInterface& layer); Rect getPosition(const sp<const DisplayDevice>& hw); #endif @@ -360,7 +334,7 @@ public: * called before composition. * returns true if the layer has pending updates. */ - bool onPreComposition(nsecs_t refreshStartTime); + virtual bool onPreComposition(nsecs_t refreshStartTime) = 0; /* * called after composition. @@ -372,7 +346,7 @@ public: #ifdef USE_HWC2 // If a buffer was replaced this frame, release the former buffer - void releasePendingBuffer(nsecs_t dequeueReadyTime); + virtual void releasePendingBuffer(nsecs_t dequeueReadyTime) = 0; #endif /* @@ -415,11 +389,10 @@ public: * operation, so this should be set only if needed). Typically this is used * to figure out if the content or size of a surface has changed. */ - Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime); - bool isBufferLatched() const { return mRefreshPending; } - - bool isPotentialCursor() const { return mPotentialCursor;} + virtual Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) = 0; + virtual bool isBufferLatched() const = 0; + bool isPotentialCursor() const { return mPotentialCursor; } /* * called with the state lock from a binder thread when the layer is * removed from the current list to the pending removal list @@ -526,14 +499,12 @@ public: ssize_t removeChild(const sp<Layer>& layer); sp<Layer> getParent() const { return mCurrentParent.promote(); } bool hasParent() const { return getParent() != nullptr; } - Rect computeScreenBounds(bool reduceTransparentRegion = true) const; bool setChildLayer(const sp<Layer>& childLayer, int32_t z); // Copy the current list of children to the drawing state. Called by // SurfaceFlinger to complete a transaction. void commitChildList(); - int32_t getZ() const; protected: // constant @@ -562,39 +533,21 @@ protected: -private: friend class SurfaceInterceptor; - // Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener - virtual void onFrameAvailable(const BufferItem& item) override; - virtual void onFrameReplaced(const BufferItem& item) override; - virtual void onSidebandStreamChanged() override; - void commitTransaction(const State& stateToCommit); - // needsLinearFiltering - true if this surface's state requires filtering - bool needsFiltering(const RenderArea& renderArea) const; - uint32_t getEffectiveUsage(uint32_t usage) const; FloatRect computeCrop(const sp<const DisplayDevice>& hw) const; - // Compute the initial crop as specified by parent layers and the SurfaceControl - // for this layer. Does not include buffer crop from the IGraphicBufferProducer - // client, as that should not affect child clipping. Returns in screen space. + // Compute the initial crop as specified by parent layers and the + // SurfaceControl for this layer. Does not include buffer crop from the + // IGraphicBufferProducer client, as that should not affect child clipping. + // Returns in screen space. Rect computeInitialCrop(const sp<const DisplayDevice>& hw) const; - bool isCropped() const; - static bool getOpacityForFormat(uint32_t format); // drawing void clearWithOpenGL(const RenderArea& renderArea, float r, float g, float b, float alpha) const; - void drawWithOpenGL(const RenderArea& renderArea, - bool useIdentityTransform) const; - - // Temporary - Used only for LEGACY camera mode. - uint32_t getProducerStickyTransform() const; - - // Loads the corresponding system property once per process - static bool latchUnsignaledBuffers(); void setParent(const sp<Layer>& layer); @@ -602,8 +555,7 @@ private: void addZOrderRelative(const wp<Layer>& relative); void removeZOrderRelative(const wp<Layer>& relative); - // ----------------------------------------------------------------------- - +protected: class SyncPoint { public: @@ -646,9 +598,6 @@ private: // is applied std::list<std::shared_ptr<SyncPoint>> mRemoteSyncPoints; - uint64_t getHeadFrameNumber() const; - bool headFenceHasSignaled() const; - // Returns false if the relevant frame has already been latched bool addSyncPoint(const std::shared_ptr<SyncPoint>& point); @@ -661,7 +610,7 @@ private: // Returns mCurrentScaling mode (originating from the // Client) or mOverrideScalingMode mode (originating from // the Surface Controller) if set. - uint32_t getEffectiveScalingMode() const; + virtual uint32_t getEffectiveScalingMode() const = 0; public: /* * The layer handle is just a BBinder object passed to the client @@ -680,28 +629,19 @@ public: }; sp<IBinder> getHandle(); - sp<IGraphicBufferProducer> getProducer() const; const String8& getName() const; - void notifyAvailableFrames(); - PixelFormat getPixelFormat() const { return mFormat; } + virtual void notifyAvailableFrames() = 0; + virtual PixelFormat getPixelFormat() const = 0; bool getPremultipledAlpha() const; -private: +protected: // ----------------------------------------------------------------------- - // Check all of the local sync points to ensure that all transactions - // which need to have been applied prior to the frame which is about to - // be latched have signaled - bool allTransactionsSignaled(); - // constants sp<SurfaceFlingerConsumer> mSurfaceFlingerConsumer; - sp<IGraphicBufferProducer> mProducer; - uint32_t mTextureName; // from GLES bool mPremultipliedAlpha; String8 mName; - String8 mTransactionName; // A cached version of "TX - " + mName for systraces - PixelFormat mFormat; + String8 mTransactionName; // A cached version of "TX - " + mName for systraces bool mPrimaryDisplayOnly = false; @@ -716,7 +656,7 @@ private: // thread-safe volatile int32_t mQueuedFrames; - volatile int32_t mSidebandStreamChanged; // used like an atomic boolean + volatile int32_t mSidebandStreamChanged; // used like an atomic boolean // Timestamp history for UIAutomation. Thread safe. FrameTracker mFrameTracker; @@ -734,14 +674,10 @@ private: sp<NativeHandle> mSidebandStream; Rect mCurrentCrop; uint32_t mCurrentTransform; - uint32_t mCurrentScalingMode; // We encode unset as -1. int32_t mOverrideScalingMode; bool mCurrentOpacity; - bool mBufferLatched = false; // TODO: Use mActiveBuffer? std::atomic<uint64_t> mCurrentFrameNumber; - uint64_t mPreviousFrameNumber; // Only accessed on the main thread. - bool mRefreshPending; bool mFrameLatencyNeeded; // Whether filtering is forced on or not bool mFiltering; @@ -749,8 +685,7 @@ private: bool mNeedsFiltering; // The mesh used to draw the layer in GLES composition mode mutable Mesh mMesh; - // The texture used to draw the layer in GLES composition mode - mutable Texture mTexture; + #ifdef USE_HWC2 // HWC items, accessed from the main thread @@ -786,8 +721,7 @@ private: // protected by mLock mutable Mutex mLock; - // Set to true once we've returned this surface's handle - mutable bool mHasSurface; + const wp<Client> mClientRef; // This layer can be a cursor on some displays. @@ -798,8 +732,6 @@ private: Condition mQueueItemCondition; Vector<BufferItem> mQueueItems; std::atomic<uint64_t> mLastFrameNumberReceived; - bool mUpdateTexImageFailed; // This is only accessed on the main thread. - bool mAutoRefresh; bool mFreezeGeometryUpdates; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 77b9a296dc..e40bbd561e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -72,6 +72,7 @@ #include "EventControlThread.h" #include "EventThread.h" #include "Layer.h" +#include "BufferLayer.h" #include "LayerVector.h" #include "ColorLayer.h" #include "MonitoredProducer.h" @@ -3208,14 +3209,15 @@ status_t SurfaceFlinger::createLayer( switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { case ISurfaceComposerClient::eFXSurfaceNormal: - result = createNormalLayer(client, + result = createBufferLayer(client, uniqueName, w, h, flags, format, handle, gbp, &layer); + break; case ISurfaceComposerClient::eFXSurfaceColor: result = createColorLayer(client, uniqueName, w, h, flags, - handle, gbp, &layer); + handle, &layer); break; default: result = BAD_VALUE; @@ -3269,7 +3271,7 @@ String8 SurfaceFlinger::getUniqueLayerName(const String8& name) return uniqueName; } -status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client, +status_t SurfaceFlinger::createBufferLayer(const sp<Client>& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer) { @@ -3284,24 +3286,24 @@ status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client, break; } - *outLayer = new Layer(this, client, name, w, h, flags); - status_t err = (*outLayer)->setBuffers(w, h, format, flags); + sp<BufferLayer> layer = new BufferLayer(this, client, name, w, h, flags); + status_t err = layer->setBuffers(w, h, format, flags); if (err == NO_ERROR) { - *handle = (*outLayer)->getHandle(); - *gbp = (*outLayer)->getProducer(); + *handle = layer->getHandle(); + *gbp = layer->getProducer(); + *outLayer = layer; } - ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err)); + ALOGE_IF(err, "createBufferLayer() failed (%s)", strerror(-err)); return err; } status_t SurfaceFlinger::createColorLayer(const sp<Client>& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, - sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer) + sp<IBinder>* handle, sp<Layer>* outLayer) { *outLayer = new ColorLayer(this, client, name, w, h, flags); *handle = (*outLayer)->getHandle(); - *gbp = (*outLayer)->getProducer(); return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d0f4699b82..d10b41bd34 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -244,6 +244,7 @@ private: friend class DisplayEventConnection; friend class EventThread; friend class Layer; + friend class BufferLayer; friend class MonitoredProducer; // This value is specified in number of frames. Log frame stats at most @@ -419,14 +420,14 @@ private: uint32_t windowType, uint32_t ownerUid, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent); - status_t createNormalLayer(const sp<Client>& client, const String8& name, + status_t createBufferLayer(const sp<Client>& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format, sp<IBinder>* outHandle, sp<IGraphicBufferProducer>* outGbp, sp<Layer>* outLayer); status_t createColorLayer(const sp<Client>& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* outHandle, - sp<IGraphicBufferProducer>* outGbp, sp<Layer>* outLayer); + sp<Layer>* outLayer); String8 getUniqueLayerName(const String8& name); diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index 952023ea19..714c23d9a9 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -70,6 +70,7 @@ #include "EventControlThread.h" #include "EventThread.h" #include "Layer.h" +#include "BufferLayer.h" #include "LayerVector.h" #include "ColorLayer.h" #include "MonitoredProducer.h" @@ -2733,14 +2734,14 @@ status_t SurfaceFlinger::createLayer( switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { case ISurfaceComposerClient::eFXSurfaceNormal: - result = createNormalLayer(client, + result = createBufferLayer(client, uniqueName, w, h, flags, format, handle, gbp, &layer); break; case ISurfaceComposerClient::eFXSurfaceColor: result = createColorLayer(client, uniqueName, w, h, flags, - handle, gbp, &layer); + handle, &layer); break; default: result = BAD_VALUE; @@ -2787,7 +2788,7 @@ String8 SurfaceFlinger::getUniqueLayerName(const String8& name) return uniqueName; } -status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client, +status_t SurfaceFlinger::createBufferLayer(const sp<Client>& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer) { @@ -2802,24 +2803,24 @@ status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client, break; } - *outLayer = new Layer(this, client, name, w, h, flags); - status_t err = (*outLayer)->setBuffers(w, h, format, flags); + sp<BufferLayer> layer = new BufferLayer(this, client, name, w, h, flags); + status_t err = layer->setBuffers(w, h, format, flags); if (err == NO_ERROR) { - *handle = (*outLayer)->getHandle(); - *gbp = (*outLayer)->getProducer(); + *handle = layer->getHandle(); + *gbp = layer->getProducer(); + *outLayer = layer; } - ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err)); + ALOGE_IF(err, "createBufferLayer() failed (%s)", strerror(-err)); return err; } status_t SurfaceFlinger::createColorLayer(const sp<Client>& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, - sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer) + sp<IBinder>* handle, sp<Layer>* outLayer) { *outLayer = new ColorLayer(this, client, name, w, h, flags); *handle = (*outLayer)->getHandle(); - *gbp = (*outLayer)->getProducer(); return NO_ERROR; } |